發(fā)布時間:2023-11-27 06:50:13 瀏覽量:124次
作者 | 李秋鍵
責編 | Carol
封圖 | CSDN 下載自視覺中國
近幾年來Python語言得到了快速發(fā)展,而Pygame作為Python開發(fā)應(yīng)用和游戲必備的庫更是展現(xiàn)了Python的優(yōu)越性。
而今天我們就將借助Pygame建立吃豆人游戲。
吃豆人是電子游戲歷史上的經(jīng)典街機游戲,由Namco公司的巖谷徹設(shè)計并由Midway Games在1980年發(fā)行
。Pac-Man被認為是80年代最經(jīng)典的街機游戲之一,游戲的主角小精靈的形象甚至被作為一種大眾文化符號,或是此產(chǎn)業(yè)的代表形象。
而Pygame模塊是跨平臺Python模塊,專為電子游戲設(shè)計,包含圖像、聲音。建立在SDL基礎(chǔ)上,允許實時電子游戲研發(fā)而無需被低級語言(如機器語言和匯編語言)束縛。
最終游戲效果如下可見:
實驗前的準備
首先我們使用的python版本是3.6.5所用到的模塊是pygame模塊,用來創(chuàng)建游戲框架。Random模塊用來隨機生成方向。
如下圖可見:
整體的類變量定義包括墻類,通過pygame的圖片填充作為墻類的加載;同理還包括食物類和角色。而怪物的隨機運動使用random產(chǎn)生隨機運動方向。
其對應(yīng)的代碼如下:
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、游戲關(guān)卡定義:
在這里設(shè)置好了關(guān)卡一。關(guān)卡的定義必須包括墻的位置,不同關(guān)卡墻的位置和怪物的位置不同。更多關(guān)卡可以參照設(shè)置
對應(yīng)代碼如下:
import pygame
from Sprites import *
NUMLEVELS = 1
'''關(guān)卡一'''
class Level1:
def __init__(self):
self.info = 'level1'
'''創(chuàng)建墻'''
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
'''創(chuàng)建門'''
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
'''創(chuàng)建角色'''
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
'''創(chuàng)建食物'''
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_sprites
在通過關(guān)卡定義墻等位置后以及精靈自身屬性怪物運動、食物定義等后,通過調(diào)用已經(jīng)創(chuàng)建好的類達到搭建游戲的目的。
具體如下可見:
import os
import sys
import pygame
import Levels
'''定義一些必要的參數(shù)'''
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')
'''開始某一關(guān)游戲'''
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
'''主函數(shù)'''
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)
最終運行程序結(jié)果如下:
源碼地址:
https://pan.baidu.com/s/128id8L-PDPgGOPuH-5uHDg
提取碼:rj9f
熱門資訊
探討游戲引擎的文章,介紹了10款游戲引擎及其代表作品,涵蓋了RAGE Engine、Naughty Dog Game Engine、The Dead Engine、Cry Engine、Avalanche Engine、Anvil Engine、IW Engine、Frostbite Engine、Creation引擎、Unreal Engine等引擎。借此分析引出了游戲設(shè)計領(lǐng)域和數(shù)字藝術(shù)教育的重要性,歡迎點擊咨詢報名。
2. 手機游戲如何開發(fā)(如何制作傳奇手游,都需要準備些什么?)
?如何制作傳奇手游,都需要準備些什么?提到傳奇手游相信大家都不陌生,他是許多80、90后的回憶;從起初的端游到現(xiàn)在的手游,說明時代在進步游戲在更新,更趨于方便化移動化。而如果我們想要制作一款傳奇手游的
3. B站視頻剪輯軟件「必剪」:免費、炫酷特效,小白必備工具
B站視頻剪輯軟件「必剪」,完全免費、一鍵制作炫酷特效,適合新手小白??靵碓囋?!
游戲中玩家將面臨武俠人生的掙扎抉擇,戰(zhàn)或降?殺或放?每個抉定都將觸發(fā)更多愛恨糾葛的精彩奇遇?!短烀嬗肪哂卸嗑€劇情多結(jié)局,不限主線發(fā)展,高自由...
5. Bigtime加密游戲經(jīng)濟體系揭秘,不同玩家角色的經(jīng)濟活動
Bigtime加密游戲經(jīng)濟模型分析,探討游戲經(jīng)濟特點,幫助玩家更全面了解這款GameFi產(chǎn)品。
6. 3D動漫建模全過程,不是一般人能學(xué)的會的,會的多不是人?
步驟01:面部,頸部,身體在一起這次我不準備設(shè)計圖片,我從雕刻進入。這一次,它將是一種純粹關(guān)注建模而非整體繪畫的形式。像往常一樣,我從Sphere創(chuàng)建它...
7. 3D動畫軟件你知道幾個?3ds Max、Blender、Maya、Houdini大比拼
當提到3D動畫軟件或動畫工具時,指的是數(shù)字內(nèi)容創(chuàng)建工具。它是用于造型、建模以及繪制3D美術(shù)動畫的軟件程序。但是,在3D動畫軟件中還包含了其他類型的...
8. 3D打印技巧揭秘!Cura設(shè)置讓你的模型更堅固
想讓你的3D打印模型更堅固?不妨嘗試一下Cura參數(shù)設(shè)置和設(shè)計技巧,讓你輕松掌握!
?三昧動漫對于著名ARPG游戲《巫師》系列,最近CD Projekt 的高層回應(yīng)并不會推出《巫師4》。因為《巫師》系列在策劃的時候一直定位在“三部曲”的故事框架,所以在游戲的出品上不可能出現(xiàn)《巫師4》
10. 虛幻引擎5節(jié)省存儲空間用這招!緩存的清理與設(shè)置
眾所周知,虛幻引擎5(下面簡稱UE5)特別占用存儲空間,僅一個版本安裝好的文件就有60G,這還不包括我們在使用時保存的工程文件和隨之產(chǎn)生的緩存文件。而...
最新文章
同學(xué)您好!