开心消消乐在屏幕中向下移动的完整代码

#--coding:utf8--
import random
import pygame as pg
 
WIDTH = 400
HEIGHT = 400
NUMGRID = 8
GRIDSIZE = 36
XMARGIN = (WIDTH - GRIDSIZE * NUMGRID) // 2
YMARGIN = (HEIGHT - GRIDSIZE * NUMGRID) // 2
 
# 加载图片
gem_imgs = [pg.image.load('resources/images/gem{}.png'.format(i)) for i in range(1, 8)]
gem_imgsx = [pg.image.load('resources/images_x/gem{}.png'.format(i)) for i in range(1, 8)]
gem_imgsy = [pg.image.load('resources/images_y/gem{}.png'.format(i)) for i in range(1, 8)]
gem_imgsbomb = [pg.image.load('resources/images_bomb/gem{}.png'.format(i)) for i in range(1, 8)]
 
 
class Puzzle(pg.sprite.Sprite):
    speed_x = 10
    speed_y = 10
 
    def __init__(self,(x,y), img= None, size=(GRIDSIZE, GRIDSIZE)):
        self.img =img if img else random.randint(0, len(gem_imgs) - 1)
        self.fixed,self.direction = False,"down"
        self.pos=[x,y]
        self.types = "gem" + str(self.img)
 
        super(Puzzle, self).__init__()
        self.image = gem_imgs[self.img]
        self.image = pg.transform.smoothscale(self.image, size)
        self.rect = self.image.get_rect(x=XMARGIN + x * GRIDSIZE,y=YMARGIN + y * GRIDSIZE - GRIDSIZE) # 向上移动一格
        
 
    def update(self):
        if not self.fixed:
            self.move(*self.pos)
 
      # 拼图块移动
    def move(self,x,y):
        target_x, target_y=[XMARGIN + x * GRIDSIZE, YMARGIN + y * GRIDSIZE]
        if self.direction == 'down':
            self.rect.top = min(target_y, self.rect.top + self.speed_y)
            if target_y == self.rect.top:
                self.fixed = True
        elif self.direction == 'up':
            self.rect.top = max(target_y, self.rect.top - self.speed_y)
            if target_y == self.rect.top:
                self.fixed = True
        elif self.direction == 'left':
            self.rect.left = max(target_x, self.rect.left - self.speed_x)
            if target_x == self.rect.left:
                self.fixed = True
        elif self.direction == 'right':
            self.rect.left = min(target_x, self.rect.left + self.speed_x)
            if target_x == self.rect.left:
                self.fixed = True
 
 
class Puzzle_x(Puzzle):
    def __init__(self, position, img, size=(GRIDSIZE, GRIDSIZE)):
        super(Puzzle_x, self).__init__(position, img)
        self.image = pg.transform.smoothscale(gem_imgsx[self.img], size)
        self.rect.top = self.rect.bottom
 
 
class Puzzle_y(Puzzle):
    def __init__(self, position, img, size=(GRIDSIZE, GRIDSIZE)):
        super(Puzzle_y, self).__init__(position, img) 
        self.image = pg.transform.smoothscale(gem_imgsy[self.img], size)
        self.rect.top = self.rect.bottom
 
 
class Puzzle_bomb(Puzzle):
    def __init__(self, position, img, size=(GRIDSIZE, GRIDSIZE)):
        super(Puzzle_bomb, self).__init__(position, img) 
        self.image = pg.transform.smoothscale(gem_imgsbomb[self.img], size)
        self.rect.top = self.rect.bottom
 
 
class Puzzle_bird(Puzzle):
    def __init__(self, position, img, size=(GRIDSIZE, GRIDSIZE)):
        super(Puzzle_bird, self).__init__(position, img)
        self.types = "bird"
        self.image=pg.transform.smoothscale(pg.image.load('resources/bird.png'),size)
        self.rect.top = self.rect.bottom

 特效.py 中建立一个比方格长2格,宽2格的二维列表, 防止 遍历特效区域时报错

并将该二维列表全部置为None ,存入在该区域拼图的类型名称

from tool import *

 
bird_x = {(-2, 0), (-1, 0), (1, 0), (2, 0)}  # x轴五连集合
bird1_x = {(-2, 0), (-1, 0), (-3, 0), (-4, 0)}
bird1_y = {(0, -2), (0, -1), (0, 1), (0, 2)}  # y轴五连集合
bird_y = {(0, -2), (0, -1), (0, -3), (0, -4)} 

birds = [bird_x,bird1_x, bird_y,bird1_y] # 五连列表

# 四联集合
line_y1 = {(0, -1), (0, 1), (0, 2)}
line_y2 = {(0, -1), (0, 1), (0, -2)}
line_x1 = {(-1, 0), (1, 0), (2, 0)}
line_x2 = {(-1, 0), (1, 0), (-2, 0)}
 
# 四连列表
lines_x = [line_x1, line_x2]
lines_y = [line_y1, line_y2]
# 左L
bomb1 = {(2, 0), (1, 0), (0, 1), (0, 2)}
bomb2 = {(2, 0), (1, 0), (0, -1), (0, -2)}
bomb3 = {(2, 0), (1, 0), (0, 1), (0, -2)}
bomb4 = {(2, 0), (1, 0), (0, -1), (0, 2)}
# 右L
bomb5 = {(-2, 0), (-1, 0), (0, 1), (0, 2)}
bomb6 = {(-2, 0), (-1, 0), (0, -1), (0, -2)}
bomb7 = {(-2, 0), (-1, 0), (0, 1), (0, -2)}
bomb8 = {(-2, 0), (-1, 0), (0, -1), (0, 2)}
 
bomb9 = {(-1, 0), (1, 0), (0, 1), (0, 2)}       # T
bomb10 = {(-1, 0), (1, 0), (0, -1), (0, -2)}   # T
 
bombs = [bomb1, bomb2, bomb3, bomb4, bomb5, bomb6, bomb7, bomb8, bomb9, bomb10]
# 三联
triple_y1 = {(0, -1), (0, 1)}
triple_y2 = {(0, -1), (0, -2)}
triple_y3 = {(0, 2), (0, 1)}
triple_x1 = {(-1, 0), (1, 0)}
triple_x2 = {(2, 0), (1, 0)}
triple_x3 = {(-1, 0), (-2, 0)}
 
triples = [triple_x1, triple_x2, triple_x3, triple_y1, triple_y2, triple_y3]
double_for=[(gem_i,gem_j) for gem_i in range(NUMGRID) for gem_j in range(NUMGRID)] 
# 初始化置None
def reset():
    all_gem.clear()
    for gem_i in range(NUMGRID + 2):
        all_gem.append([])
        for gem_j in range(NUMGRID + 2):
            all_gem[gem_i].append(None)
    return all_gem
 
 
# 将特效集合的区域置None
def assignment(grop, gem_i=0,pos_x=0, pos_y=0):
    for g_x, g_y in grop[gem_i]:
        all_gem[g_x+pos_x][g_y+pos_y] = None
    return len(grop)
 

def matchgroup(pos_x, pos_y, grp, grp_i=0):
    types = all_gem[pos_x][pos_y]
    def match():    # 开始匹配  
        for gem_x, gem_y in grp[grp_i]: # 特效集合
            ty = all_gem[gem_x+pos_x][gem_y+pos_y]
            # 判断匹配项是否相同并且不为None
            if ty != types or ty == types is None: 
                return True
    if grp_i >= len(grp): # 遍历到最后一个特效列表,返回Flase
        return False, -1
    else:
        # 不满足 遍历下一个特效列表
        if match(): 
            return matchgroup(pos_x, pos_y, grp, grp_i + 1)
        else:
            # 满足 直接返回Ture
            return True, grp_i
  
# 是否构成特效,构成那种特效
def isMatch(pos_x, pos_y):
    def get_types():
        return all_gem[pos_x][pos_y],pos_x,pos_y
    """
    :param pos_x: 判断坐标的x轴
    :param pos_y: 判断坐标的y轴
    :return: 
    """
    types=get_types()
    bird, bird_i = matchgroup(pos_x, pos_y, birds)       # 五连
    bomb, bomb_i = matchgroup(pos_x, pos_y, bombs)       # T形 或L形
    line_x, line_i_x = matchgroup(pos_x, pos_y, lines_x) # 四连
    line_y, line_i_y = matchgroup(pos_x, pos_y, lines_y) # 四连
    triple, triple_i = matchgroup(pos_x, pos_y, triples) # 三连
    # 其他特效成立,三联一定成立
    # 三连成立 其他特效不一定成立
    # 三联不成立,其他特效一定不成立
    if bird:
        all_gem[pos_x][pos_y] = "bird"
        return 'bird', assignment(birds, bird_i,pos_x, pos_y),types
    if bomb:
        return 'bomb', assignment(bombs, bomb_i,pos_x, pos_y),types
    if line_x:
        return 'line_x', assignment(lines_x, line_i_x,pos_x, pos_y),types
    if line_y:
        return 'line_y', assignment(lines_y, line_i_y,pos_x, pos_y),types
    if triple:
        all_gem[pos_x][pos_y] = None
        return 'triple', assignment(triples, triple_i,pos_x, pos_y),types
    return None, 0,types
 
 
 
def clear_y(gem_y):
    """
    :param gem_y: 将纵坐标为gem_y的列表置None
    :return:
    """
    for gem_x in range(NUMGRID):
        all_gem[gem_x][gem_y] = None
    return NUMGRID
 
 
def clear_x(gem_x):
    """
    :param gem_x: 将横坐标为gem_x的列表置None
    :return:
    """
    for gem_y in range(NUMGRID):
        all_gem[gem_x][gem_y] = None
    return NUMGRID
  
# 爆炸所爆区域
def clear_bomb(gem_x, gem_y):
    """
      :param gem_x: 爆炸中心横坐标x点
      :param gem_y: 爆炸中心纵坐标y点
      :return:
      """
     for gem_i in range(NUMGRID):
        for gem_j in range(NUMGRID):
            if abs(gem_x - gem_i) + abs(gem_y - gem_j) <= 2:
                all_gem[gem_x][gem_y] = None
                clear.add((gem_i,gem_j))
    return len(clear)
 
# 魔法鸟特效作用坐标的集合
def clear_bird(types):
    b = set()
    for gem_x in range(NUMGRID):
        for gem_y in range(NUMGRID):
            if all_gem[gem_x][gem_y] == types:
                all_gem[gem_x][gem_y]=None
                b.add((gem_x, gem_y))
    return b
 
 
all_gem = []
reset()
 
def drop():
    for gem_x in range(NUMGRID):
        for gem_y in range(NUMGRID):
            if not all_gem[gem_x][gem_y]:
                return True
 
def move_gem_xy(gem_x=NUMGRID - 1, gem_y=NUMGRID - 1):
    """
    :param gem_x:
    :param gem_y:
    :return:从右下方开始遍历,从右到左,从下到上
    """
    res_match, score,types = isMatch(gem_x, gem_y)
    if res_match:
        return res_match, score, types
    else:
        if gem_x >= 0:
            return move_gem_xy(gem_x - 1, gem_y)
        else:
            if gem_y >= 0:
                return move_gem_xy(NUMGRID - 1, gem_y - 1)
            else:
                return res_match, score, types

isMatch:匹配特效区域,如果符合上述特效,引用 assignment 将特效区域集合全部置None

拼图停止下降后,引用 move_gem_xy判断是否能形成新的特效

在消除.py中, 交换的二个拼图都为特效拼图引用 exchange 

被波及的特效拼图引用clear_sigle

from 特效 import *
death_gem=pg.sprite.Group()

def get_pos(pos_x,pos_y):
    return  (XMARGIN + pos_x * GRIDSIZE, YMARGIN + pos_y * GRIDSIZE)
   
# gem1 特效拼图波及的魔法鸟拼图 或 交换拼图的第一个拼图
# gem2 魔法鸟拼图作用的普通拼图 或 交换拼图的第二个拼图
def exchange(gem1, gem2):
    match1,match2 = isMatch(*gem1.pos),isMatch(*gem2.pos)
    gem1_x,gem1_y,gem2_x,gem2_y=gem1.pos+gem2.pos # 获取坐标
    # 初始化返回值
    kind,score,grp,bird=match1[0] or match2[0],-1,[match1,match2],-1
    def return_kind():
        if kind:
            gem1.kill() 
            gem2.kill()
            death_gem.add(gem1,gem2)
        return kind abs(assignment([bird])*score),grp
    def Jigsaw_puzzle(pos1, pos2):     # 四行 或 四纵 的集合
        return set([pos1 - 1, pos1, pos1 + 1,pos2 - 1, pos2, pos2 + 1])
    # 交换拼图中有一个为魔法鸟 跳出
    if isinstance(gem1, Puzzle_bird):
        # 魔法鸟作用的特效拼图信息列表,
        bird,kind= clear_bird(gem2.types),"bird1"
        if isinstance(gem2, Puzzle_bomb):
            score+=clear_bomb(gem2_x, gem2_y)
            for gem_x, gem_y in bird:
                # 添加魔法鸟作用坐标的数据信息 下同
                grp.append(['bomb', score,(gem2.types, gem_x, gem_y)])
        elif isinstance(gem2, Puzzle_x) or isinstance(gem2, Puzzle_y):
            score += NUMGRID
            for gem_x, gem_y in bird:
                choice = random.choice(["line_x", "line_y"])
                grp.append([choice, NUMGRID, (gem2.types, gem_x, gem_y)])
        elif isinstance(gem2, Puzzle_bird):
            reset() # 重新初始化二维列表
            return "clear", int(NUMGRID * NUMGRID * 1.2), grp
    elif isinstance(gem2, Puzzle_bird):
       	# 魔法鸟作用的特效拼图信息列表
        bird,kind  = clear_bird(gem1.types),"bird2"
        if isinstance(gem1, Puzzle_bomb):
            score+=clear_bomb(gem1_x, gem1_y)
            for gem_x, gem_y in bird:
                grp.append(["bomb", score, (gem1.types, gem_x, gem_y)])
        elif isinstance(gem1, Puzzle_x) or isinstance(gem1, Puzzle_y):
            score += NUMGRID
            for gem_x, gem_y in bird:
                choice = random.choice(["line_x", "line_y"])
                grp.append([choice, NUMGRID, (gem1.types, gem_x, gem_y)])
        return ,abs(assignment([bird]) * score), grp
    elif isinstance(gem2, Puzzle_y):
        kind='y'
        if isinstance(gem1, Puzzle_y) or isinstance(gem1, Puzzle_x):
             score=clear_x(gem2_x)+clear_y(gem2_y)
        elif isinstance(gem1, Puzzle_bomb):
            for gem_y in Jigsaw_puzzle(gem1_y, gem2_y):
                score +=clear_y(gem_y)
    elif isinstance(gem2, Puzzle_x):
        kind="x"
        if isinstance(gem1, Puzzle_y) or isinstance(gem1, Puzzle_x):
           score=clear_x(gem2_x)+clear_y(gem2_y)
        elif isinstance(gem1, Puzzle_bomb):
            for gem_x in Jigsaw_puzzle(gem1_x, gem2_x):
                score +=clear_x(gem_x)
    elif isinstance(gem2, Puzzle_bomb):
        kind="bomb"
        if isinstance(gem1, Puzzle_y):
            for gem_y in Jigsaw_puzzle(gem1_y, gem2_y):
                score +=clear_y(gem_y)
        elif isinstance(gem1, Puzzle_x):
            for gem_x in Jigsaw_puzzle(gem1_x, gem2_xy):
                score +=clear_x(gem_x)
        elif isinstance(gem1, Puzzle_bomb):
            score += int(clear_bomb(gem1_x, gem1_y) * 1.2 * clear_bomb(gem2_x, gem2_y))
    return return_kind()
 
def clear_sigle(gem, (gem_x,gem_y)):   # 列表 获取的分数
    gem.kill()
    death_gem.add(gem)
    if isinstance(gem, Puzzle_bomb):
        return clear_bomb(gem_x, gem_y)
    elif isinstance(gem, Puzzle_x):
        return clear_x(gem_x)
    elif isinstance(gem, Puzzle_y):
        return clear_y(gem_y)
    elif isinstance(gem, Puzzle_bird):
        # 随机获取普通拼图
        g = exchange(gem, gem_puzzle())
        return g[1]
    else: #普通拼图
        return 1 

tool.py

from puzz import *

pg.init()
pg.display.set_caption("开心消消乐")
screen = pg.display.set_mode((WIDTH, HEIGHT))
font = pg.font.Font(r'C:\Windows\Fonts\simsun.ttc', 25)
FPS = 30

# 三联不生成拼图,
def get_None((x,y)=(-1,-1),img=None):
    return None
 
puzzples={
"line_x":Puzzle_x,"line_y":Puzzle_y,
'bomb':Puzzle_bomb,'bird':Puzzle_bird,
None:Puzzle,"triple":get_None
}

# 获取拼图的相关信息(图像,坐标,到达位置,类型名称 等等)
def gem_puzzle(x=-1, y=-1, types='none', ty=None):
    try:
        img=int(types[3])
    except (ValueError,KeyError,TypeError):
        img = None
    finally:
        return puzzples[ty]((x,y),img)
   
 
# 方格
def drawwBlock(rect, color, size):
    pg.draw.rect(screen, color, rect, size)
 
# 信息
def showstep(step, score,gem):
    remaining_time_render = font.render('步数' + str(step), True, (85, 65, 0))
    score_render = font.render('分数:' + str(score), True, (85, 65, 0))
    screen.blit(remaining_time_render, (WIDTH - 190, 15))
    screen.blit(score_render, (55, 15))
    if gem:
        drawwBlock(gem.rect,(255, 0, 0), 2)
 
 
# 画出背景
def drawGrids(step, score,gem):
    screen.fill((255, 255, 220))
    showstep(step, score,gem)
    for rect_x in range(NUMGRID):
        for rect_y in range(NUMGRID):
            rect = pg.Rect((XMARGIN + rect_x * GRIDSIZE, YMARGIN + rect_y * GRIDSIZE, GRIDSIZE, GRIDSIZE))
            drawwBlock(rect, color=(255, 165, 0), size=1)

game.py

from 消除 import *
 
 
class GAME:
    def swapGem(self, gem1, gem2):
        gem1_pos,gem2_pos=gem1.pos,gem2.pos
        if gem1_pos[0] - gem2_pos[0] == 1:
            gem1.direction = 'left'
            gem2.direction = 'right'
        elif gem1_pos[0] - gem2_pos[0] == -1:
            gem2.direction = 'left'
            gem1.direction = 'right'
        elif gem1_pos[1] - gem2_pos[1] == 1:
            gem1.direction = 'up'
            gem2.direction = 'down'
        elif gem1_pos[1] - gem2_pos[1] == -1:
            gem2.direction = 'up'
            gem1.direction = 'down'
 
        margin = abs(gem1_pos[0] - gem2_pos[0]) + abs(gem1_pos[1] - gem2_pos[1])
        if abs(margin) != 1: # 拼图不相连
            return False
        gem1.pos,gem2.pos=gem2_pos,gem1_pos
        gem1.fixed = gem2.fixed =False
 
        self.all_gem[gem2_pos[0]][gem2_pos[1]] = gem1.types
        self.all_gem[gem1_pos[0]][gem1_pos[1]] = gem2.types
        return True
 
    # 初始化
    def reset(self):
        self.step = 20
        self.score = 0
        self.all_gem = reset()
        self.gems_group = pg.sprite.Group()
 
    def effects_puzzle(self, ty, score, (types, pos_x, pos_y)):
        # 在该处可形成相应特效拼图
        gem = gem_puzzle(pos_x, pos_y, types, ty)
        # 可合成特效拼图,更换拼图图像,位置不变
        if gem and ty:  
            self.gems_group.add(gem)
            self.all_gem[pos_x][pos_y]=gem.types
        return score
 
    # 将列表为空的位置处的拼图消除
    def eliminate(self):
        score = self.effects_puzzle(*move_gem_xy())
        for gem_x in range(NUMGRID):
            for gem_y in range(NUMGRID):
                gem1= self.get_gem(get_pos(gem_x,gem_y))
                gem2= self.get_gem(get_pos(gem_x,gem_y-1))
                if not gem1:
                    self.all_gem[gem_x][gem_y]=None
                # 列表的值为None并有拼图就消除
                elif not self.all_gem[gem_x][gem_y] and gem1:
                    clear_sigle(gem1, (gem_x, gem_y)) # 消除特殊拼图
                # 列表第一行为空 新增加一个拼图
                if not gem_y and not self.all_gem[gem_x][gem_y]:
                    gems = gem_puzzle(gem_x, gem_y)  # 添加Puzzle普通拼图
                    self.gems_group.add(gems)
                    self.all_gem[gem_x][gem_y] = gems.types
                # 列表的值为None并且上方有拼图
                # 将列表上下互换,并且将上方拼图的到达位置下降一格
                # 将该位置上方数值赋值给自己,上方数值赋为None
                elif not self.all_gem[gem_x][gem_y] and gem2:
                    self.all_gem[gem_x][gem_y] = self.all_gem[gem_x][gem_y - 1]
                    self.all_gem[gem_x][gem_y - 1] = None
                    gem2.pos[1] += 1
                    gem2.fixed = False
                    gem2.direction = 'down'
        return score
 
 
    # 检查拼图是否全部下落
    def isFull(self):
        for gems in self.gems_group:
            if not gems.fixed:
                return True
 
    # 检查有无拼图块被选中
    def get_gem(self, poss):
        for gems in self.gems_group:
            if gems.rect.collidepoint(poss):
                return gems
       
       # 游戏开始 
    def start(self):
        clock = pg.time.Clock()
        # gem1 与 gem2 是否相连
        individual_moving = False
        # gem_group 中的拼图是否全部下落
        overall_moving = False
        gem1=gem2 = None
        while True:
            overall_moving = not self.isFull()
            for event in pg.event.get():
                pos = pg.mouse.get_pos()
                if event.type == pg.QUIT:
                    sys.exit()
                elif event.type == pg.MOUSEBUTTONDOWN and overall_moving and not drop():
                    if not gem1:
                        gem1 = self.get_gem(pos)
                    else:
                        gem2 = self.get_gem(pos)
                        if gem2:
                            if self.swapGem(gem1, gem2):
                                individual_moving = True #交换拼图相连
                            else:
                                gem1 = gem2 
            if individual_moving and overall_moving:
	            cl,score,grp = exchange(gem1, gem2)
	            if not cl:
	                self.swapGem(gem1, gem2)
	            else:
                    for ma in grp:
                        self.score += self.effects_puzzle(*ma)
	                self.score += score
	                self.step -= 1
	                if cl == 'clear': 
	                    # 列表初始化后,精灵组全部清空,以防出错
	                    self.gems_group.empty()
	            individual_moving = False
	            gem1 =gem2= None
            elif overall_moving:
                self.score += self.eliminate()
 
            self.gems_group.update()
            drawGrids(self.step, self.score)
            self.gems_group.draw(screen)
            if self.step <= 0 and not self.isFull():
                return self.score
            pg.display.flip()
            clock.tick(FPS)

主函数 

g = GAME()

g.reset()

score = g.start()

你可能感兴趣的:(娱乐,游戏,pygame,python)