python最简单代码做游戏(Python玩出花儿了一文教你用)
python最简单代码做游戏(Python玩出花儿了一文教你用)如下图可见:最终游戏效果如下可见:吃豆人是电子游戏历史上的经典街机游戏,由Namco公司的岩谷彻设计并由Midway Games在1980年发行。Pac-Man被认为是80年代最经典的街机游戏之一,游戏的主角小精灵的形象甚至被作为一种大众文化符号,或是此产业的代表形象。而Pygame模块是跨平台Python模块,专为电子游戏设计,包含图像、声音。建立在SDL基础上,允许实时电子游戏研发而无需被低级语言(如机器语言和汇编语言)束缚。
作者 | 李秋键
责编 | Carol
封图 | CSDN 下载自视觉中国
近几年来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 [0 0 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 = [30 30]
self.speed = [0 0]
self.is_move = False
self.tracks =
self.tracks_loc = [0 0]
'''改变速度方向'''
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.5 0] [0.5 0] [0 0.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 = [[0 0 6 600]
[0 0 600 6]
[0 600 606 6]
[600 0 6 606]
[300 0 6 66]
[60 60 186 6]
[360 60 186 6]
[60 120 66 6]
[60 120 6 126]
[180 120 246 6]
[300 120 6 66]
[480 120 66 6]
[540 120 6 126]
[120 180 126 6]
[120 180 6 126]
[360 180 126 6]
[480 180 6 126]
[180 240 6 126]
[180 360 246 6]
[420 240 6 126]
[240 240 42 6]
[324 240 42 6]
[240 240 6 66]
[240 300 126 6]
[360 240 6 66]
[0 300 66 6]
[540 300 66 6]
[60 360 66 6]
[60 360 6 186]
[480 360 66 6]
[540 360 6 186]
[120 420 366 6]
[120 420 6 66]
[480 420 6 66]
[180 480 246 6]
[300 480 6 66]
[120 540 126 6]
[360 540 126 6]]
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(282 242 42 2 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(287 439 hero_image_path))
for each in ghost_images_path:
role_name = each.split('/')[-1].split('.')[0]
if role_name == 'Blinky':
player = Player(287 199 each)
player.is_move = True
player.tracks = [[0 -0.5 4] [0.5 0 9] [0 0.5 11] [0.5 0 3] [0 0.5 7] [-0.5 0 11] [0 0.5 3]
[0.5 0 15] [0 -0.5 15] [0.5 0 3] [0 -0.5 11] [-0.5 0 3] [0 -0.5 11] [-0.5 0 3]
[0 -0.5 3] [-0.5 0 7] [0 -0.5 3] [0.5 0 15] [0 0.5 15] [-0.5 0 3] [0 0.5 3]
[-0.5 0 3] [0 -0.5 7] [-0.5 0 3] [0 0.5 7] [-0.5 0 11] [0 -0.5 7] [0.5 0 5]]
self.ghost_sprites.add(player)
elif role_name == 'Clyde':
player = Player(319 259 each)
player.is_move = True
player.tracks = [[-1 0 2] [0 -0.5 4] [0.5 0 5] [0 0.5 7] [-0.5 0 11] [0 -0.5 7]
[-0.5 0 3] [0 0.5 7] [-0.5 0 7] [0 0.5 15] [0.5 0 15] [0 -0.5 3]
[-0.5 0 11] [0 -0.5 7] [0.5 0 3] [0 -0.5 11] [0.5 0 9]]
self.ghost_sprites.add(player)
elif role_name == 'Inky':
player = Player(255 259 each)
player.is_move = True
player.tracks = [[1 0 2] [0 -0.5 4] [0.5 0 10] [0 0.5 7] [0.5 0 3] [0 -0.5 3]
[0.5 0 3] [0 -0.5 15] [-0.5 0 15] [0 0.5 3] [0.5 0 15] [0 0.5 11]
[-0.5 0 3] [0 -0.5 7] [-0.5 0 11] [0 0.5 3] [-0.5 0 11] [0 0.5 7]
[-0.5 0 3] [0 -0.5 3] [-0.5 0 3] [0 -0.5 15] [0.5 0 15] [0 0.5 3]
[-0.5 0 15] [0 0.5 11] [0.5 0 3] [0 -0.5 11] [0.5 0 11] [0 0.5 3] [0.5 0 1]]
self.ghost_sprites.add(player)
elif role_name == 'Pinky':
player = Player(287 259 each)
player.is_move = True
player.tracks = [[0 -1 4] [0.5 0 9] [0 0.5 11] [-0.5 0 23] [0 0.5 7] [0.5 0 3]
[0 -0.5 3] [0.5 0 19] [0 0.5 3] [0.5 0 3] [0 0.5 3] [0.5 0 3]
[0 -0.5 15] [-0.5 0 7] [0 0.5 3] [-0.5 0 19] [0 -0.5 11] [0.5 0 9]]
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 == 8) and (col == 8 or col == 9 or col == 10):
continue
else:
food = Food(30*col 32 30*row 32 4 4 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_sprites3、游戏创建:
在通过关卡定义墙等位置后以及精灵自身属性怪物运动、食物定义等后,通过调用已经创建好的类达到搭建游戏的目的。具体如下可见:
import os
import sys
import pygame
import Levels
'''定义一些必要的参数'''
BLACK = (0 0 0)
WHITE = (255 255 255)
BLUE = (0 0 255)
GREEN = (0 255 0)
RED = (255 0 0)
YELLOW = (255 255 0)
PURPLE = (255 0 255)
SKYBLUE = (0 191 255)
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([-1 0])
hero.is_move = True
elif event.key == pygame.K_RIGHT:
for hero in hero_sprites:
hero.changeSpeed([1 0])
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([0 1])
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] < ghost.tracks[ghost.tracks_loc[0]][2]:
ghost.changeSpeed(ghost.tracks[ghost.tracks_loc[0]][0: 2])
ghost.tracks_loc[1] = 1
else:
if ghost.tracks_loc[0] < len(ghost.tracks) - 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]][0: 2])
ghost.tracks_loc[1] = 0
if ghost.tracks_loc[1] < ghost.tracks[ghost.tracks_loc[0]][2]:
ghost.changeSpeed(ghost.tracks[ghost.tracks_loc[0]][0: 2])
else:
if ghost.tracks_loc[0] < len(ghost.tracks) - 1:
loc0 = ghost.tracks_loc[0] 1
elif ghost.role_name == 'Clyde':
loc0 = 2
else:
loc0 = 0
ghost.changeSpeed(ghost.tracks[loc0][0: 2])
ghost.update(wall_sprites None)
ghost_sprites.draw(screen)
score_text = font.render("Score: %s" % SCORE True RED)
screen.blit(score_text [10 10])
if len(food_sprites) == 0:
is_clearance = True
break
if pygame.sprite.groupcollide(hero_sprites ghost_sprites False False):
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 = [[235 233] [65 303] [170 333]] if not is_clearance else [[145 233] [65 303] [170 333]]
surface = pygame.Surface((400 200))
surface.set_alpha(10)
surface.fill((128 128 128))
screen.blit(surface (100 200))
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([606 606])
pygame.display.set_caption('吃豆人')
return screen
'''主函数'''
def main(screen):
pygame.mixer.init
pygame.mixer.music.load(BGMPATH)
pygame.mixer.music.play(-1 0.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
作者简介:
李秋键,CSDN博客专家,CSDN达人课作者。硕士在读于中国矿业大学,开发有taptap竞赛获奖等等。