社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python 玩出花儿了!一文教你用 Python 制作吃豆人游戏! | 附代码

机器学习算法与Python学习 • 4 年前 • 570 次点击  





点击 机器学习算法与Python学习 , 选择加星标

精彩内容不迷路


近几年来Python语言得到了快速发展,而Pygame作为Python开发应用和游戏必备的库更是展现了Python的优越性。

而今天我们就将借助Pygame建立吃豆人游戏。

吃豆人是电子游戏历史上的经典街机游戏,由Namco公司的岩谷彻设计并由Midway Games在1980年发行。Pac-Man被认为是80年代最经典的街机游戏之一,游戏的主角小精灵的形象甚至被作为一种大众文化符号,或是此产业的代表形象。

而Pygame模块是跨平台Python模块,专为电子游戏设计,包含图像、声音。建立在SDL基础上,允许实时电子游戏研发而无需被低级语言(如机器语言和汇编语言)束缚。

最终游戏效果如下可见:

 


一、实验前的准备

首先我们使用的python版本是3.6.5所用到的模块是pygame模块,用来创建游戏框架。Random模块用来随机生成方向。


素材准备

首先我们将图片放到images目录下,背景音乐放到sounds目录下。

如下图可见:

游戏搭建

1、定义一些精灵:

整体的类变量定义包括墙类,通过pygame的图片填充作为墙类的加载;同理还包括食物类和角色。而怪物的随机运动使用random产生随机运动方向。

其对应的代码如下:

import random
import pygame
墙类
class Wall(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height, color, **kwargs):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface([width, height])
        self.image.fill(color)
        self.rect = self.image.get_rect()
        self.rect.left = x
        self.rect.top = y
食物类
class Food(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height, color, bg_color, **kwargs):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface([width, height])
        self.image.fill(bg_color)
        self.image.set_colorkey(bg_color)
        pygame.draw.ellipse(self.image, color, [00, width, height])
        self.rect = self.image.get_rect()
        self.rect.left = x
        self.rect.top = y
角色类
class Player(pygame.sprite.Sprite):
    def __init__(self, x, y, role_image_path):
        pygame.sprite.Sprite.__init__(self)
        self.role_name = role_image_path.split( / )[-1].split( . )[0]
        self.base_image = pygame.image.load(role_image_path).convert()
        self.image = self.base_image.copy()
        self.rect = self.image.get_rect()
        self.rect.left = x
        self.rect.top = y
        self.prev_x = x
        self.prev_y = y
        self.base_speed = [3030]
        self.speed = [00]
        self.is_move = False
        self.tracks = []
        self.tracks_loc = [00]
     改变速度方向
    def changeSpeed(self, direction):
        if direction[0] 0:
            self.image = pygame.transform.flip(self.base_image, True, False)
        elif direction[0] > 0:
            self.image = self.base_image.copy()
        elif direction[1] 0:
            self.image = pygame.transform.rotate(self.base_image, 90)
        elif direction[1] > 0:
            self.image = pygame.transform.rotate(self.base_image, -90)
        self.speed = [direction[0] * self.base_speed[0], direction[1] * self.base_speed[1]]
        return self.speed
     更新角色位置
    def update(self, wall_sprites, gate_sprites):
        if not self.is_move:
            return False
        x_prev = self.rect.left
        y_prev = self.rect.top
        self.rect.left += self.speed[0]
        self.rect.top += self.speed[1]
        is_collide = pygame.sprite.spritecollide(self, wall_sprites, False)
        if gate_sprites is not None:
            if not is_collide:
                is_collide = pygame.sprite.spritecollide(self, gate_sprites, False)
        if is_collide:
            self.rect.left = x_prev
            self.rect.top = y_prev
            return False
        return True
     生成随机的方向
    def randomDirection(self):
        return random.choice([[-0.50], [0.50], [00.5], [0, -0.5]])

2、游戏关卡定义:

在这里设置好了关卡一。关卡的定义必须包括墙的位置,不同关卡墙的位置和怪物的位置不同。更多关卡可以参照设置

对应代码如下:

import pygame
from Sprites import *
NUMLEVELS = 1
关卡一
class Level1():
    def __init__(self):
        self.info =  level1
     创建墙
    def setupWalls(self, wall_color):
        self.wall_sprites = pygame.sprite.Group()
        wall_positions = [[006600],
                          [006006],
                          [06006066],
                          [6000 6606],
                          [3000666],
                          [60601866],
                          [360601866],
                          [60120666],
                          [601206126],
                          [1801202466],
                          [300120666],
                          [480120666],
                          [5401206126],
                          [1201801266],
                          [1201806126],
                          [3601801266],
                          [4801806126],
                          [1802406126],
                          [1803602466],
                          [4202406126],
                          [240240426],
                          [324240426],
                          [240240666],
                          [2403001266],
                          [360240666],
                          [0300666],
                          [540300666],
                          [60360666],
                          [603606186],
                          [480360666],
                          [5403606186],
                          [1204203666],
                          [120420666],
                          [480420666],
                          [180480 2466],
                          [300480666],
                          [1205401266],
                          [3605401266]]
        for wall_position in wall_positions:
            wall = Wall(*wall_position, wall_color)
            self.wall_sprites.add(wall)
        return self.wall_sprites
     创建门
    def setupGate(self, gate_color):
        self.gate_sprites = pygame.sprite.Group()
        self.gate_sprites.add(Wall(282242422, gate_color))
        return self.gate_sprites
     创建角色
    def setupPlayers(self, hero_image_path, ghost_images_path):
        self.hero_sprites = pygame.sprite.Group()
        self.ghost_sprites = pygame.sprite.Group()
        self.hero_sprites.add(Player(287439, hero_image_path))
        for each in ghost_images_path:
            role_name = each.split( / )[-1].split( . )[0]
            if role_name ==  Blinky :
                player = Player(287199, each)
                player.is_move = True
                player.tracks = [[0-0.54], [0.509], [00.511], [0.503], [00.57], [-0.5 011], [00.53],
                                 [0.5015], [0-0.515], [0.503], [0-0.511], [-0.503], [0-0.511], [-0.503],
                                 [0-0.53], [-0.507], [0-0.53], [0.5015], [00.515], [-0.503], [00.53],
                                 [-0.503], [0-0.57], [-0.503], [00.57], [-0.5011], [0-0.5 7], [0.505]]
                self.ghost_sprites.add(player)
            elif role_name ==  Clyde :
                player = Player(319259, each)
                player.is_move = True
                player.tracks = [[-102], [0-0.54], [0.505], [00.57], [-0.5011], [0-0.57],
                                 [-0.503], [00.57], [-0.507], [00.515], [0.5015], [0-0.53],
                                 [-0.5011], [0-0.57], [0.503], [0-0.511], [0.509]]
                self.ghost_sprites.add(player)
            elif role_name ==  Inky :
                player = Player(255 259, each)
                player.is_move = True
                player.tracks = [[102], [0-0.54], [0.5010], [00.57], [0.503], [0-0.53],
                                 [0.503], [0-0.515], [-0.5015], [00.53], [0.5015], [00.511],
                                 [-0.503], [0-0.57], [-0.5011], [00.53], [-0.5011], [00.57],
                                 [-0.503], [0-0.53], [-0.50 3], [0-0.515], [0.5015], [00.53],
                                 [-0.5015], [00.511], [0.503], [0-0.511], [0.5011], [00.53], [0.501]]
                self.ghost_sprites.add(player)
            elif role_name ==  Pinky :
                player = Player(287259, each)
                player.is_move = True
                player.tracks = [[0-14], [0.509], [00.511], [-0.5023], [00.57], [0.503],
                                 [0-0.53], [0.5019], [00.53 ], [0.503], [00.53], [0.503],
                                 [0-0.515], [-0.507], [00.53], [-0.5019], [0-0.511], [0.509]]
                self.ghost_sprites.add(player)
        return self.hero_sprites, self.ghost_sprites
     创建食物
    def setupFood(self, food_color, bg_color):
        self.food_sprites = pygame.sprite.Group()
        for row in range(19):
            for col in range(19):
                if (row == 7 or row == 8and (col == 8 or col == 9 or col == 10):
                    continue
                else:
                    food = Food(30*col+3230*row+3244, food_color, bg_color)
                    is_collide = pygame.sprite.spritecollide(food, self.wall_sprites, False)
                    if is_collide:
                        continue
                    is_collide = pygame.sprite.spritecollide(food, self.hero_sprites, False)
                    if is_collide:
                        continue
                    self.food_sprites.add(food)
        return self.food_sprites

3、游戏创建:

在通过关卡定义墙等位置后以及精灵自身属性怪物运动、食物定义等后,通过调用已经创建好的类达到搭建游戏的目的。

具体如下可见:

import os
import sys
import pygame
import Levels
定义一些必要的参数
BLACK = (000)
WHITE = (255255255)
BLUE = (00255)
GREEN = (02550)
RED = (25500)
YELLOW = (2552550)
PURPLE = (2550255)
SKYBLUE = (0191255)
BGMPATH = os.path.join(os.getcwd(),  resources/sounds/bg.mp3 )
ICONPATH = os.path.join(os.getcwd(),  resources/images/icon.png )
FONTPATH = os.path.join(os.getcwd(),  resources/font/ALGER.TTF )
HEROPATH = os.path.join(os.getcwd(),  resources/images/pacman.png )
BlinkyPATH = os.path.join(os.getcwd(),  resources/images/Blinky.png )
ClydePATH = os.path.join(os.getcwd(),  resources/images/Clyde.png )
InkyPATH = os.path.join(os.getcwd(),  resources/images/Inky.png )
PinkyPATH = os.path.join(os.getcwd(),  resources/images/Pinky.png )
开始某一关游戏
def startLevelGame(level, screen, font):
    clock = pygame.time.Clock()
    SCORE = 0
    wall_sprites = level.setupWalls(SKYBLUE)
    gate_sprites = level.setupGate(WHITE)
    hero_sprites, ghost_sprites = level.setupPlayers(HEROPATH, [BlinkyPATH, ClydePATH, InkyPATH, PinkyPATH])
    food_sprites = level.setupFood(YELLOW, WHITE)
    is_clearance = False
    while True:
        for  event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit(-1)
                pygame.quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    for hero in hero_sprites:
                        hero.changeSpeed([-10])
                        hero.is_move = True
                elif event.key == pygame.K_RIGHT:
                    for hero in hero_sprites:
                        hero.changeSpeed([10])
                        hero.is_move = True
                elif event.key == pygame.K_UP:
                    for hero in hero_sprites:
                        hero.changeSpeed([0-1])
                        hero.is_move = True
                elif event.key == pygame.K_DOWN:
                    for hero in hero_sprites:
                        hero.changeSpeed([01])
                        hero.is_move = True
            if event.type == pygame.KEYUP:
                if (event.key == pygame.K_LEFT) or (event.key == pygame.K_RIGHT) or (event.key == pygame.K_UP) or (event.key == pygame.K_DOWN):
                    hero.is_move = False
        screen.fill(BLACK)
        for hero in hero_sprites:
            hero.update(wall_sprites, gate_sprites)
        hero_sprites.draw(screen)
        for hero in hero_sprites:
            food_eaten = pygame.sprite.spritecollide(hero, food_sprites, True)
        SCORE += len(food_eaten)
        wall_sprites.draw(screen)
        gate_sprites.draw(screen)
        food_sprites.draw(screen)
        for ghost in ghost_sprites:
            # 幽灵随机运动(效果不好且有BUG)
            
            res = ghost.update(wall_sprites, None)
            while not res:
                ghost.changeSpeed(ghost.randomDirection())
                res = ghost.update(wall_sprites, None)
            

            # 指定幽灵运动路径
            if ghost.tracks_loc[1] 0]][2]:
                ghost.changeSpeed(ghost.tracks[ghost.tracks_loc[0]][02])
                ghost.tracks_loc[1] += 1
             else:
                if ghost.tracks_loc[0] 1:
                    ghost.tracks_loc[0] += 1
                elif ghost.role_name ==  Clyde :
                    ghost.tracks_loc[0] = 2
                else:
                    ghost.tracks_loc[0] = 0
                ghost.changeSpeed(ghost.tracks[ghost.tracks_loc[0]][02])
                ghost.tracks_loc[1] = 0
            if ghost.tracks_loc[1] 0]][2]:
                ghost.changeSpeed(ghost.tracks[ghost.tracks_loc[0]][02])
            else:
                if ghost.tracks_loc[0] 1:
                    loc0 = ghost.tracks_loc[0] + 1
                elif ghost.role_name ==  Clyde :
                    loc0 = 2
                else:
                    loc0 = 0
                ghost.changeSpeed(ghost.tracks[loc0][02])
            ghost.update(wall_sprites, None)
        ghost_sprites.draw(screen)
        score_text = font.render("Score: %s" % SCORE, True, RED)
        screen.blit(score_text, [1010])
        if len(food_sprites) == 0:
            is_clearance = True
            break
        if pygame.sprite.groupcollide(hero_sprites, ghost_sprites, FalseFalse):
            is_clearance = False
            break
        pygame.display.flip()
        clock.tick(10)
    return is_clearance
显示文字
def showText(screen, font, is_clearance, flag=False):
    clock = pygame.time.Clock()
    msg =  Game Over!  if  not is_clearance else  Congratulations, you won!
    positions = [[235233], [65303], [170333]] if not is_clearance else [[145233], [65303], [170333]]
    surface = pygame.Surface((400200))
    surface.set_alpha(10)
    surface.fill((128128128))
    screen.blit(surface, (100200))
    texts = [font.render(msg, True, WHITE),
             font.render( Press ENTER to continue or play again. True, WHITE),
             font.render( Press ESCAPE to quit. True, WHITE)]
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
                pygame.quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RETURN:
                    if is_clearance:
                        if not flag:
                            return
                        else:
                            main(initialize())
                    else:
                        main(initialize())
                elif event.key == pygame.K_ESCAPE:
                    sys.exit()
                    pygame.quit()
        for idx, (text, position) in enumerate(zip(texts, positions)):
            screen.blit(text, position)
        pygame.display.flip()
        clock.tick(10)
初始化
def initialize():
    pygame.init()
    icon_image = pygame.image.load(ICONPATH)
    pygame.display.set_icon(icon_image)
    screen = pygame.display.set_mode([606606])
    pygame.display.set_caption( 吃豆人 )
    return screen
主函数
def main(screen):
    pygame.mixer.init()
    pygame.mixer.music.load(BGMPATH)
    pygame.mixer.music.play(-10.0)
    pygame.font.init()
    font_small = pygame.font.Font(FONTPATH, 18)
    font_big = pygame.font.Font(FONTPATH, 24)
    for num_level in range(1, Levels.NUMLEVELS+1):
        if num_level == 1:
            level = Levels.Level1()
            is_clearance = startLevelGame(level, screen, font_small)
            if num_level == Levels.NUMLEVELS:
                showText(screen, font_big, is_clearance, True)
            else:
                showText(screen, font_big, is_clearance)

最终运行程序结果如下:

 

源码地址:

https://pan.baidu.com/s/128id8L-PDPgGOPuH-5uHDg

提取码:rj9f

喜欢就点击“在看”吧!

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/99077
 
570 次点击