python 游戏(滑动拼图Slide_Puzzle)

1. 游戏功能和流程图

实现16宫格滑动拼图,实现3个按钮(重置用户操作,重新开始游戏,解密游戏),后续难度,额外添加重置一次的按钮,解密算法的植入,数字改变为图片植入

游戏流程图

2. 游戏配置

配置游戏目录

配置游戏(game_conf.py)

#游戏参数配置BOARD_WIDTH=4 #游戏板列数BOARD_HEIGHT=4 #游戏板行数TILE_SIZE=80 #游戏板块大小WINDOW_WIDTH=1024 #窗口大小WINDOW_HEIGHT=768FPS=30 #游戏帧数BASICFONT_SIZE=20 #字体大小X_MARGIN=int((WINDOW_WIDTH-(TILE_SIZE*BOARD_WIDTH+(BOARD_WIDTH-1)))/2) #x边距Y_MARGIN=int((WINDOW_HEIGHT-(TILE_SIZE*BOARD_HEIGHT+(BOARD_HEIGHT-1)))/2) #y边距

配置颜色(color.py)

#游戏色彩配置BLACK=(0,0,0) #黑色WHITE=(255,255,255) #白色BRIGHT_BLUE=(0,50,250) #宝石蓝色DARKTURQUOIS=(3,54,73)     #深珠宝绿GREEN=(0,204,0)  #绿色

配置动作(handle.py)

#动作配置UP = ‘up‘DOWN = ‘down‘LEFT = ‘left‘RIGHT = ‘right‘

3. 游戏使用工具和函数(views.py)

3.1 工具和绘画类使用模块和常量

from conf.color import *from conf.game_conf import *from conf.handle import *from pygame import *import random,pygame,sysTILE_COLOR=GREENTEXT_COLOR=WHITEBG_COLOR=DARKTURQUOISMESSAGE_COLOR=WHITEBORDER_COLOR=BRIGHT_BLUE

3.2 生成游戏数据

def get_starting_board():    ‘‘‘生成游戏板数据结构    :return 返回数据坐标‘‘‘    board=[]    for x in range(BOARD_WIDTH):        counter = 1+x        column=[]        for y in range(BOARD_HEIGHT):            column.append(counter)#添加y轴数据            counter+=BOARD_WIDTH        board.append(column) #添加x轴数据    board[BOARD_WIDTH-1][BOARD_HEIGHT-1]=None #最后一个方块是空方块    return board

3.3 查找空白块坐标

def get_blank_position(board):    ‘‘‘找到游戏空白块坐标    :param board 游戏板块坐标列表    :return 返回空板块坐标‘‘‘    for x in range(BOARD_WIDTH):        for y in range(BOARD_HEIGHT):            if board[x][y]==None:                return (x,y)

3.4 移动方块坐标

def make_move(board,move):    ‘‘‘数据移动方块    :param 移动板块列表    :param move 移动方向‘‘‘    blank_x,blank_y=get_blank_position(board)    if move==UP:#上升空白块        #blank_y+1 下个格子的y坐标,下降空白格,向上移动格子        board[blank_x][blank_y],board[blank_x][blank_y+1]=board[blank_x][blank_y+1],board[blank_x][blank_y]    elif move==DOWN:        # blank_y-1 上个格子的y坐标,上降空白格,向下移动格子        board[blank_x][blank_y], board[blank_x][blank_y - 1] = board[blank_x][blank_y - 1], board[blank_x][blank_y]    elif move==LEFT:        #blank_x + 1 右边格子的x坐标,右移空白格,向左移动格子        board[blank_x][blank_y], board[blank_x+1][blank_y] = board[blank_x+1][blank_y], board[blank_x][blank_y]    elif move==RIGHT:        # blank_x - 1 左边格子的x坐标,左移空白格,向右移动格子        board[blank_x][blank_y], board[blank_x - 1][blank_y] = board[blank_x - 1][blank_y], board[blank_x][blank_y]

3.5  移动限制

def is_valid_move(board,move):    ‘‘‘移动判断,移动断言    :param board 移动板块列表    :param move 移动方向    :return 返回True可移动,返回False不可移动‘‘‘    blank_x,blank_y=get_blank_position(board) #获取空白位置的坐标    #如果是上升的话,空白格的坐标不能等于y边界的坐标,如果返回Flase    #下降,空白坐标不能等于y零界点左边,如果等于返回False    return (move==UP and blank_y !=BOARD_HEIGHT-1)\           or (move==DOWN and blank_y !=0) \           or (move==LEFT and blank_x !=BOARD_WIDTH-1) \           or (move==RIGHT and blank_x !=0)

3.6 随机移动方向

def get_random_move(board,last_move=None):    ‘‘‘随机移动方向    :param board 游戏数据    :param last_move 上次移动记录    :return 返回随机移动方位‘‘‘    vaild_moves=[UP,DOWN,LEFT,RIGHT]    if last_move ==UP or not is_valid_move(board,DOWN):#排除上下重复移动和向下不能移动选项        vaild_moves.remove(DOWN) #删除向下移动    if last_move ==DOWN or not is_valid_move(board,UP):        vaild_moves.remove(UP)    if last_move ==LEFT or not is_valid_move(board,RIGHT):#排除左右重复移动和向右不能移动选项        vaild_moves.remove(RIGHT)    if last_move ==RIGHT or not is_valid_move(board,LEFT):        vaild_moves.remove(LEFT)    return random.choice(vaild_moves)

3.7  数据坐标转化像素坐标

def get_left_top_of_tile(tile_x,tile_y):    ‘‘‘根据坐标返回像素坐标    :param tile_x 数据x坐标    :param tile_y 数据y坐标    :return 返回像素left,top坐标‘‘‘    left=X_MARGIN+(tile_x*TILE_SIZE)+(tile_x-1) #获取左边的像素坐标(tile_x-1)格子间的间距    top=Y_MARGIN+(tile_y*TILE_SIZE)+(tile_y-1)#获取头部坐标    return (left,top)

3.8 矩形碰撞(根据像素坐标找到数据坐标)

def get_spot_clicked(board,x,y):    ‘‘‘矩形碰撞    :param board 游戏数据列表    :param x 像素x坐标    :param y 像素y坐标    :return 返回数据坐标‘‘‘    for tile_x in range(len(board)):        for tile_y in range(len(board[0])):            left,top=get_left_top_of_tile(tile_x,tile_y)            tile_rect=pygame.Rect(left,top,TILE_SIZE,TILE_SIZE) #创建坐标矩形            if tile_rect.collidepoint(x,y): #判断像素坐标点是否在矩形内部                return (tile_x,tile_y) #返回数据坐标    return (None,None)

3.9 退出游戏函数

def terminate():    ‘‘‘退出游戏‘‘‘    pygame.quit()    sys.exit()

3.10 退出事件监控

def check_for_quit():    ‘‘‘循环事件监控‘‘‘    for event in pygame.event.get(QUIT):        terminate()    for event in pygame.event.get(KEYUP):        if event.key==K_ESCAPE: #获取Esc按键            terminate()        pygame.event.post(event) #将其他事件放回event

4  创建游戏绘画类(views.py)

4.1  创建类的初始化

def __init__(self,DISPLAY_SURF,FPS_CLOCK,BASIC_FONT):    self.DISPLAY_SURF=DISPLAY_SURF#surf对象    self.FPS_CLOCK=FPS_CLOCK#fps对象    self.BASIC_FONT=BASIC_FONT#文字对象

4.2  绘制单个方块

def draw_tile(self,tile_x,tile_y,number,adjx=0,adjy=0):    ‘‘‘绘制游戏方块    :param tile_x 数据x坐标    :param tile_y 数据y坐标    :param number 方块显示信息    :param adjx 滑动动画x位移像素    :param adjy 滑动动画y位移像素‘‘‘    left,top=get_left_top_of_tile(tile_x,tile_y)    pygame.draw.rect(self.DISPLAY_SURF,TILE_COLOR,(left+adjx,top+adjy,TILE_SIZE,TILE_SIZE))    text_surf=self.BASIC_FONT.render(str(number),True,TEXT_COLOR)#创建文字图层    text_rect=text_surf.get_rect()#创建文字矩形块    text_rect.center=(left+int(TILE_SIZE/2)+adjx,top+int(TILE_SIZE/2)+adjy) #文字居中    self.DISPLAY_SURF.blit(text_surf,text_rect) #生成字体

4.3 创建字体通用对象

def make_text(self,text,color,bg_color,left,top):    ‘‘‘创建字体对象    :param text 显示文本    :param color 文本颜色    :param bg_color 文本背景颜色    :param left 像素x坐标    :param top 像素y坐标    :return text_surf 文本对象 text_rect 位置对象‘‘‘    text_surf=self.BASIC_FONT.render(text,True,color,bg_color) #创建文本    #定位文字矩形块    text_rect=text_surf.get_rect()    text_rect.topleft=(left,top)    return (text_surf,text_rect)

4.4 生成游戏按钮文本对象

def make_button_obj(self):    ‘‘‘生成按钮文本对象    :param 返回按钮文本对象‘‘‘    button_left = WINDOW_WIDTH-120    button_top = WINDOW_HEIGHT-90    reset_surf,reset_rect=self.make_text(‘Reset‘,TEXT_COLOR,TILE_COLOR,button_left,button_top)    new_surf, new_rect = self.make_text(‘New Game‘, TEXT_COLOR, TILE_COLOR, button_left, button_top+30)    solve_surf, solve_rect = self.make_text(‘Solve‘, TEXT_COLOR, TILE_COLOR, button_left, button_top + 60)    return (reset_surf, reset_rect,new_surf, new_rect,solve_surf, solve_rect)

4.5 绘制游戏面板

def draw_board(self,board,message):    ‘‘‘绘制画板    :param board 游戏坐标数据    :param message 游戏左上角提示信息‘‘‘    self.DISPLAY_SURF.fill(BG_COLOR)#添加背景    if message: #如果有提示信息显示提示信息        text_surf,text_rect=self.make_text(message,MESSAGE_COLOR,BG_COLOR,5,5) #获取文本对象和定位对象        self.DISPLAY_SURF.blit(text_surf,text_rect) #显示消息    for tile_x in range(len(board)): #绘制方块        for tile_y in range(len(board[0])):            if board[tile_x][tile_y]:                self.draw_tile(tile_x,tile_y,board[tile_x][tile_y])    #绘制边框    left,top=get_left_top_of_tile(0,0)    width=BOARD_WIDTH*TILE_SIZE    height=BOARD_HEIGHT*TILE_SIZE    pygame.draw.rect(self.DISPLAY_SURF,BORDER_COLOR,(left-5,top-5,width+11,height+11),4)    #绘制按钮    reset_surf, reset_rect,new_surf, new_rect,solve_surf, solve_rect=self.make_button_obj()    self.DISPLAY_SURF.blit(reset_surf,reset_rect)    self.DISPLAY_SURF.blit(new_surf, new_rect)    self.DISPLAY_SURF.blit(solve_surf, solve_rect)

4.6 绘制滑动动画

def slide_animation(self,board,direction,message,animation_speed):    ‘‘‘绘制滑动动画    :param board 游戏坐标数据    :param direction 移动方位    :param message 游戏左上角提示信息    :param animation_speed 移动动画速度‘‘‘    blank_x,blank_y=get_blank_position(board)    #根据空白坐标和移动方位获取要移动方块的坐标    move_x,move_y=0,0    if direction == UP:        move_x,move_y =blank_x,blank_y+1    if direction == DOWN:        move_x,move_y=blank_x,blank_y-1    if direction == LEFT:        move_x,move_y=blank_x+1,blank_y    if direction == RIGHT:        move_x,move_y=blank_x-1,blank_y    self.draw_board(board,message) #绘制画板    base_surf=self.DISPLAY_SURF.copy()#复制一个新的窗口对象    move_left,move_top=get_left_top_of_tile(move_x,move_y)    #绘制空白区(这时候有2块空白区域)    pygame.draw.rect(base_surf,BG_COLOR,(move_left,move_top,TILE_SIZE,TILE_SIZE))    #绘制滑动效果    for i in range(0,TILE_SIZE,animation_speed): #animation_speed步长偏移速度,每次循环后方块的位置向指定方向移动        check_for_quit()        self.DISPLAY_SURF.blit(base_surf,(0,0))        if direction==UP:            self.draw_tile(move_x,move_y,board[move_x][move_y],0,-i) #x不动,y轴向上偏移        if direction==DOWN:            self.draw_tile(move_x, move_y, board[move_x][move_y], 0, i)  # x不动,y轴向下偏移        if direction==LEFT:            self.draw_tile(move_x, move_y, board[move_x][move_y], -i, 0)  # x不动,y轴向左偏移        if direction==RIGHT:            self.draw_tile(move_x, move_y, board[move_x][move_y], i, 0)  # x不动,y轴向右偏移        pygame.display.update()        self.FPS_CLOCK.tick(FPS)

4.7 绘制重新开始游戏动画并重置游戏数据

def generate_new_puzzle(self,num_slides):    ‘‘‘重新开始游戏    :param num_slides 移动次数    :return board 游戏坐标数据sequence 移动数据‘‘‘    sequence=[] #移动数据    board=get_starting_board() #重新生成游戏数据    self.draw_board(board,‘‘) #显示开始画板    pygame.display.update()    pygame.time.wait(500) #等待500毫秒    last_move=None    for i in range(num_slides): #执行移动打乱游戏数据        move=get_random_move(board,last_move) #获取随机移动方向        self.slide_animation(board,move,‘Generating new puzzle...‘,animation_speed=int(TILE_SIZE/3)) #执行移动动画        make_move(board,move) #数据坐标移动        sequence.append(move) #记录移动信息        last_move=move    return (board,sequence)

4.8 绘制重置玩家步骤动画

def reset_animation(self,board,all_moves):    ‘‘‘重置步骤    :param board 游戏坐标数据    :param all_moves 游戏移动信息列表‘‘‘    rev_all_moves=all_moves[:]    if rev_all_moves:        rev_all_moves.reverse() #翻转操作列表        opposite_move=DOWN        for move in rev_all_moves: #反转移动方向,反向移动重置            if move==UP:                opposite_move=DOWN            if move==DOWN:                opposite_move=UP            if move == LEFT:                opposite_move = RIGHT            if move == RIGHT:                opposite_move = LEFT            self.slide_animation(board,opposite_move,‘‘,animation_speed=int(TILE_SIZE/2)) #执行移动动画            make_move(board,opposite_move)#数据移动方块

5. 游戏逻辑判断(游戏核心Slide_Puzzle.py)

5.1 游戏使用模块和常量

import pygame,sys,randomfrom pygame.locals import *import os,sysBASE_PATH=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))sys.path.insert(0,BASE_PATH)from conf.color import *from conf.game_conf import *from conf.handle import *from core.views import *BLANK=NoneBUTTON_COLOR = WHITE #按钮颜色BUTTONTEXT_COLOR = BLACK #按钮文本颜色MESSAGE_COLOR = WHITE 

5.2 游戏逻辑判断

def main():    pygame.init()    FPS_CLOCK = pygame.time.Clock()    DISPLAY_SURF=pygame.display.set_mode((WINDOW_WIDTH,WINDOW_HEIGHT))    pygame.display.set_caption(‘Slide Puzzle‘)    BASIC_FONT = pygame.font.Font(BASE_PATH+‘\conf\FreeSansBold.ttf‘, BASICFONT_SIZE)    Puzzle=Game_Draw(DISPLAY_SURF,FPS_CLOCK,BASIC_FONT)    reset_surf, reset_rect, new_surf, new_rect, solve_surf, solve_rect = Puzzle.make_button_obj()    main_board,solution_seq=Puzzle.generate_new_puzzle(80)    solved_board=get_starting_board() #游戏胜利对比数据    all_move=[] #游戏移动方向数据    while True:        slide_to=None #        msg=‘Click tile or press arrow keys to slide.‘ #游戏开始提示        if main_board==solved_board: #游戏获胜判断            msg=‘Solved!‘            solution_seq = []            all_move = []        Puzzle.draw_board(main_board,msg)        check_for_quit()        for event in pygame.event.get():            if event.type==MOUSEBUTTONUP: #鼠标点击按钮                spot_x,spot_y=get_spot_clicked(main_board,event.pos[0],event.pos[1]) #鼠标点击碰撞                if (spot_x,spot_y)==(None,None): #如果没有在游戏方块上                    if reset_rect.collidepoint(event.pos):                        Puzzle.reset_animation(main_board,all_move) #重置用户移动数据                        all_move = []                    elif new_rect.collidepoint(event.pos):                        main_board,solution_seq=Puzzle.generate_new_puzzle(80) #重置游戏数据和初始系统移动数据                        all_move = []                    elif solve_rect.collidepoint(event.pos):                        Puzzle.reset_animation(main_board,solution_seq+all_move) #重置用户移动列表,在重置系统移动列表                        solution_seq=[]                        all_move = []                else:                    blank_x,blank_y=get_blank_position(main_board)                    if spot_x-1==blank_x and spot_y == blank_y:                        slide_to = LEFT                    if spot_x+1==blank_x and spot_y == blank_y:#如果方块的右边是空白                        slide_to = RIGHT                    if spot_x==blank_x and spot_y-1 == blank_y:                        slide_to = UP                    if spot_x==blank_x and spot_y+1 == blank_y:                        slide_to = DOWN            elif event.type == KEYUP:                # 监控按键移动方式                if event.key in (K_LEFT, K_a) and is_valid_move(main_board, LEFT):                    slide_to = LEFT                # 如果按键触发在右按键和d按键并且可以右移动方块                elif event.key in (K_RIGHT, K_d) and is_valid_move(main_board, RIGHT):                    slide_to = RIGHT                elif event.key in (K_UP, K_w) and is_valid_move(main_board, UP):                    slide_to = UP                elif event.key in (K_DOWN, K_s) and is_valid_move(main_board, DOWN):                    slide_to = DOWN        if slide_to:            Puzzle.slide_animation(main_board,slide_to, ‘Click tile or press arrow keys to slide.‘, 8) #执行滑动动画            make_move(main_board,slide_to) #修改游戏坐标数据            all_move.append(slide_to) #添加移动记录        pygame.display.update()        FPS_CLOCK.tick(FPS)

5.3 运行游戏

if __name__ == ‘__main__‘:    main()

python学习途径

本游戏参考书本 <<Python和Pygame游戏开发>>

游戏源码下载 https://inventwithpython.com/slidepuzzle.py

友情推荐:  猿人学Python【https://www.yuanrenxue.com/】 由一群工作十余年的老程序员结合实际工作经验所写的Python教程。

原文地址:https://www.cnblogs.com/gm332211/p/10886428.html

时间: 2024-10-13 07:20:29

python 游戏(滑动拼图Slide_Puzzle)的相关文章

Python游戏引擎开发(四):TextField文本类

上一章我们主要介绍了显示对象和如何显示图片.本章来讲述显示文本. 以下是本系列教程前几章地址,在阅读本篇正文之前,请务必阅读前几章内容. Python游戏引擎开发(一):序 Python游戏引擎开发(二):创建窗口以及重绘界面 Python游戏引擎开发(三):显示图片 文本类TextField 使用过flash的朋友都知道,这个类其实不光是显示文本用的,还可以用于显示输入框.我这里就只实现一些基础实用的功能,以后有时间了慢慢拓展.和上一章一样,TextField是一个显示对象,继承自Displa

Python游戏引擎开发(一):序

邂逅Python 写了这么久的html5,感觉html5学得差不多了,是时候去接触更多的语言来扩充自己的能力了.我先后看了Swift,Java等语言.首先开发Swift需要一台mac,对于我这个寒士而言,过于奢华了一些:Java吧,又感觉太胖了,不够苗条,身材不好,也看不上.最后遇到了Miss Python,先前也和她打过交道,不过感觉语法怪怪的,总是出现>>>这类符号(当时没有深入接触,不晓得是命令输入提示),实在是太高冷了.幸好遇见了廖雪峰大侠,在他的引荐下,我开始初步了解Pytho

Python游戏引擎开发(六):动画的小小研究

今天我们来研究动画,其实这个动画就是一个Sprite+Bitmap的结合体.不造什么是Sprite和Bitmap?=__=#看来你是半路杀进来的,快去看看前几章吧: Python游戏引擎开发(一):序 Python游戏引擎开发(二):创建窗口以及重绘界面 Python游戏引擎开发(三):显示图片 Python游戏引擎开发(四):TextField文本类 Python游戏引擎开发(五):Sprite精灵类和鼠标事件 动画的原理 一般而言,我们的动画是用的这样一种图片: 播放动画的时候,像播放电影一

【python游戏编程之旅】第一篇---初识pygame

本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 参考书籍:<python游戏编程入门> 一.pygame简介 Pygame 是一组用来开发游戏软件的 Python 程序模块,基于 SDL 库的基础上开发.允许你在 Python 程序中创建功能丰富的游戏和多媒体程序,Pygame 是一个高可移植性的模块可以支持多个操作系统.用它来开发小游戏非常适合. 可以去http://www.pygame.org/hifi.html 下载并安装使用pygame. 二

Python游戏引擎开发(三):显示图片

在上一章中我们讲了如何创建窗口以及对界面进行重绘.可能有朋友不理解为什么要进行全窗口的重绘呢?我在这里可以大致讲一下原因: 由于我们的游戏是动态的,所以我们每次更改数据后(例如播放动画时切换图片),要让界面显示更改后的结果,一般的想法是:首先进行擦除原先要改的地方,然后再把变更的内容画出来.不过这个看似简单,如果遇到了重叠放置的对象就麻烦了,比如说A在B的下面,我们要更改A,那么把A擦掉后,B也会被擦掉,原因在于我们的画布是2D的,无法控制Z方向的擦除.这样一来,我们除了重画A还要再把B画上去.

Python游戏引擎开发(二):创建窗口以及重绘界面

开发本地应用之前,我们得先有个窗口,用于显示界面.其次我们还得实现重绘机制,使游戏不停地刷新,达到动态化的目的.所以我们的引擎开发的第一个阶段就是创建窗口和重绘界面. 以下是之前的文章: Python游戏引擎开发(一):序 Qt的渲染机制 在上一章<序>中我们讲到本次开发用到了PyQt,也就是Qt的Python版.在开始实现引擎功能之前我们要先了解一下Qt,这里先了解渲染机制. 在Qt中,绘画用到的类叫做QPainter,顾名思义,就是个画家类吧.在这个类中,提供了非常多的方法用于操控这个&q

Python游戏引擎开发(五):Sprite精灵类和鼠标事件

本次来实现Sprite类和鼠标事件. 说起这个Sprite啊,涉及过2D游戏研究领域的看官应该都听说过它.它中文原意是"精灵",不过在不同人的眼中,它所表示的意义不同.比如说在cocos2d中,它可以是一张图片.不过在flash中,Sprite是一个类似于"层"的家伙.当然你把它定义为层并不是很准确,实际上它是一个含显示列表的显示对象.什么意思呢?各位看官如果阅读了前面的章节,那对显示列表并不陌生.它说白了就是一个包含其他显示对象的容器. 那也许你会想,为什么要有这

一个python游戏源码

#finalPyPong.py import pygame,sys class MyBallClass(pygame.sprite.Sprite): def __init__(self,image_file,speed,location=[0,0]): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load(image_file) self.rect = self.image.get_rect() self.rect.

js实现滑动拼图验证码

js实现滑动拼图验证码,我这个样式是仿那些大网站做了, 学习用的,只用到前端. 小的个人网站感觉还可以用,大一点的别人用机器一下就破解了. 下面看图示: 样子大概是这样的. 源码在这 百度网盘:   链接: https://pan.baidu.com/s/1htjxYBE 密码: m5aw 3.9MB 是因为里面绝大部分是图片 使用示例 代码里面都有 js源码 (function (window, document) { var SliderBar = function (targetDom,