pygame从入门到放弃(上)--构建沙雕迷宫游戏

先上资源,图片资源,源代码及打包成的exe文件:

链接:https://pan.baidu.com/s/1jc8Yrr8XeknHLxicdRUzyw 
提取码:j1ax

上效果gif,可解压上述百度云链接中的压缩包打开此沙雕游戏:

做一下说明:

一直想做一个游戏,现正好借熟悉python来写一个游戏,写着写着(边查资料)发现,这简直太难了,首先得学习下pygame,因为本来适用面较窄没有其他游戏引擎比如unity3D运用广泛,所以资料较少(相对而言),除此之外没有美工,图片得找,甚至还要自行PS(所以有时会显示出奇怪的字,动画也不连贯,水平有限啦),过于艰难,还要写底层逻辑,比如这个游戏需要判断是否与墙壁碰撞这些都是纯手工。基本入门之后,决定-->放弃。

源代码基本每一行都有注释,提供给初学者,这些都是什么意义。最开始通过教程学动画滚动啊等等,但是后来发现还是无法满足要求,建议:先构思游戏,再一步一步写,边写边查

上述沙雕游戏步骤大致为:pygame游戏框架-->机器人动态,不同移动方向不同姿态-->引入背景及障碍物方块-->碰撞判断-->输赢判断及结束动画图-->构造迷宫二维List(之后改变该list则改变迷宫样式,接下来准备写点算法生成自动迷宫,给这个沙雕游戏一个ending)

机器人动态是相当于多个图片,图片如下(网上找的):

打包成exe时可参考上一篇文章https://blog.csdn.net/qq_36187544/article/details/86550376

算法自动生成迷宫pygame从入门到放弃(下)--迷宫游戏随机迷宫生成算法链接:https://blog.csdn.net/qq_36187544/article/details/87613346

这里由于涉及到图片,打包完成后会输出图片读取不到的问题,所以手动在exe同级目录下增加image文件夹,内含图片资源

源代码如下(这么简单的游戏200多行,放弃吧):

# -*- coding: cp936 -*-

import os, sys, pygame

from pygame.locals import *

size = (700, 700)  # 对话框大小

white = (255, 255, 255)  # 定义白色

block_group = []  # 障碍物组

isOver = False  # 判断游戏是否结束

# 定义迷宫的二维list,0为可走为空,1为填充砖块处
background_group = [
    [0, 1, 1, 1, 0, 0, 0, 0, 0, 0],
    [0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
    [0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
    [0, 1, 1, 1, 0, 1, 1, 0, 1, 0],
    [0, 1, 0, 0, 0, 1, 1, 1, 1, 0],
    [0, 1, 0, 1, 1, 0, 0, 0, 0, 0],
    [0, 1, 0, 1, 1, 0, 1, 1, 1, 1],
    [0, 1, 0, 1, 1, 0, 0, 0, 0, 1],
    [0, 1, 0, 1, 1, 0, 1, 1, 1, 1],
    [0, 0, 0, 0, 1, 0, 0, 0, 0, 0]]

# 游戏主角是机器人android
class Android:
    # 初始化类
    def __init__(self, img, rect, speed):

        # full_img 是整张图,imgs 是full_img的surface
        # rect 是机器人的位置,speed则是移动速度
        self.ful_img = img
        self.imgs = [self.ful_img.subsurface(Rect((i * 64.5, 0), (70, 70)))
                     for i in range(11)]

        self.rect = rect
        self.speed = speed
        self.num = 0

    # 当按下键盘时,移动机器人
    def update(self, screen, press_keys):
        global isOver   # 声明这是全局变量
        # num是surface的编号,根据编号来轮流显示surface
        self.num += 1
        if self.num % 11 == 0:
            self.num = 0

        # 退出
        if press_keys[K_ESCAPE]:
            exit()

        # 根据按下的方向键来移动机器人
        if press_keys[K_LEFT]:

            self.rect.left -= self.speed
            # 如果碰壁则无法再移动
            if self.rect.left <= 0:
                self.rect.left = 0
            # 判断是否碰撞,70是一个基数是障碍物方块边长
            for n in range(len(block_group)-1):     # block_group列表记录所有的方块,最后一位记录终点方块,判断胜利调用最后一位,除此之外不涉及最后一位
                # 此后两个if判断与某一方块是否碰撞
                if self.rect.top > block_group[n].rect.top - 70 and self.rect.bottom < block_group[n].rect.bottom + 70:
                    if self.rect.right > block_group[n].rect.right > self.rect.left:
                        self.rect.left += self.speed
                        break   # 发生了碰撞则复原并跳出此For循环
            # 接下来的if...else用于使机器人产生向左移动时的动画
            if self.num % 3 == 1 or self.num % 3 == 0:
                screen.blit(self.imgs[2], self.rect)
                return 0
            else:
                screen.blit(self.imgs[0], self.rect)
                return 0

        if press_keys[K_RIGHT]:

            self.rect.left += self.speed
            # 如果碰壁则无法再移动
            if self.rect.right >= 700:
                self.rect.right = 700
            # 判断是否碰撞,70是一个基数是障碍物方块边长
            for n in range(len(block_group)-1):
                if self.rect.top > block_group[n].rect.top - 70 and self.rect.bottom < block_group[n].rect.bottom + 70:
                    if self.rect.left < block_group[n].rect.left < self.rect.right:
                        self.rect.left -= self.speed
                        break
            # 判断是否胜利
            if self.rect.top > block_group[len(block_group) - 1].rect.top - 70 and self.rect.bottom < block_group[len(block_group) - 1].rect.bottom + 70:
                if self.rect.left < block_group[len(block_group) - 1].rect.left < self.rect.right:
                    isOver = True
            # 接下来的if...else用于使机器人产生向右移动时的动画
            if self.num % 3 == 1 or self.num % 3 == 0:
                screen.blit(self.imgs[1], self.rect)
                return 0
            else:
                screen.blit(self.imgs[0], self.rect)
                return 0

        if press_keys[K_UP]:

            self.rect.top -= self.speed
            # 如果碰壁则无法再移动
            if self.rect.top <= 0:
                self.rect.top = 0
            # 判断是否碰撞,70是一个基数是障碍物方块边长
            for n in range(len(block_group)-1):
                if self.rect.left > block_group[n].rect.left - 70 and self.rect.right < block_group[n].rect.right + 70:
                    if self.rect.bottom > block_group[n].rect.bottom > self.rect.top:
                        self.rect.top += self.speed
                        break
            # 接下来的if...else用于使机器人产生向上移动时的动画
            if self.num % 3 == 1 or self.num % 3 == 0:
                screen.blit(self.imgs[9], self.rect)
                return 0
            else:
                screen.blit(self.imgs[0], self.rect)
                return 0

        if press_keys[K_DOWN]:

            self.rect.top += self.speed
            # 如果碰壁则无法再移动
            if self.rect.bottom >= 700:
                self.rect.bottom = 700
            # 判断是否碰撞,70是一个基数是障碍物方块边长
            for n in range(len(block_group)-1):
                if self.rect.left > block_group[n].rect.left - 70 and self.rect.right < block_group[n].rect.right + 70:
                    if self.rect.top < block_group[n].rect.top < self.rect.bottom:
                        self.rect.top -= self.speed
                        break
            # 判断是否胜利
            if self.rect.left > block_group[len(block_group)-1].rect.left - 70 and self.rect.right < block_group[len(block_group)-1].rect.right + 70:
                if self.rect.top < block_group[len(block_group)-1].rect.top < self.rect.bottom:
                    isOver = True
            # 接下来的if...else用于使机器人产生向下移动时的动画
            if self.num % 3 == 1 or self.num % 3 == 0:
                screen.blit(self.imgs[3], self.rect)
                return 0
            else:
                screen.blit(self.imgs[0], self.rect)
                return 0

        # 用于产生静止时的动画
        if 3 >= self.num >= 0 or self.num > 7:
            screen.blit(self.imgs[0], self.rect)
        elif self.num == 5 or self.num == 4:
            screen.blit(self.imgs[5], self.rect)
        elif self.num == 6 or self.num == 7:
            screen.blit(self.imgs[6], self.rect)

        return 0


# 由于需要判断碰撞,所以无法简单绘制障碍物,需设置障碍物类
class Block:
    def __init__(self, img, rect):
        self.img = img
        self.rect = rect

    # 绘制障碍物方块
    def draw(self, screen):
        screen.blit(self.img, self.rect)

# 绘制背景方块
def drawBackground(screen):
    # 清空列表,初始化
    block_group.clear()

    # 定义障碍物
    block1_img = pygame.image.load('image/block1.png').convert()

    # 通过background_group这个二维List进行迷宫的绘制
    for i in range(10):
        for j in range(10):
            if background_group[i][j] == 1:
                block = Block(block1_img, Rect(70*j, 70*i, 70, 70))  # 初始化障碍物方块
                block.draw(screen)  # 绘制障碍物方块
                block_group.append(block)  # 向列表中加入该方块

    # 定义终点方块
    block_final = Block(pygame.image.load('image/block2.png').convert(), Rect(630, 630, 70, 70))
    block_final.draw(screen)
    block_group.append(block_final)


def game():
    # 使窗口居中
    os.environ['SDL_VIDEO_CENTERED'] = '1'
    # 定义机器人移动速度
    speed_android = 5
    # 定义间隔时间,没过一个间隔时间进行一次循环判断
    dwTime = 6
    # 定义机器人所占的空间,为一个矩形,Rect(左上角位置横坐标,左上角位置纵坐标,长,宽)
    r_android = Rect(0, 0, 70, 70)
    # 初始化pygame
    pygame.init()
    # 定义时钟
    clock = pygame.time.Clock()
    # 定义屏幕
    screen = pygame.display.set_mode(size, 0, 32)
    # 定义机器人图画
    android = pygame.image.load('image/robot.png').convert_alpha()
    # 定义背景
    background1 = pygame.image.load('image/background1.jpg').convert()
    # 定义一个Android
    Andr = Android(android, r_android, speed_android)
    # 设置窗口标题
    pygame.display.set_caption("真是一个小游戏")
    # 开始循环
    while True:
        # 判断游戏是否结束,结束则换另一套逻辑
        if isOver:
            screen.blit(pygame.image.load('image/over.jpg').convert(), (0, 0))  # 绘制胜利背景
            pygame.display.update()
            # 按任意键退出
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
                if event.type == KEYDOWN:
                    exit()
            clock.tick(1000)
            continue
        # 屏幕填充为白色
        screen.fill(white)
        # 屏幕填充为背景图
        screen.blit(background1, (0, 0))
        # 调用方法绘制背景障碍物方块
        drawBackground(screen)
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
        # 当有按键按下时调用机器人类进行更新
        press_keys = pygame.key.get_pressed()
        Andr.update(screen, press_keys)
        # 更新展示
        pygame.display.update()
        # 定时装置
        clock.tick(dwTime)


if __name__ == "__main__":
    game()

猜你喜欢

转载自blog.csdn.net/qq_36187544/article/details/87442425