基于 Python 制作的打地鼠小游戏
导语
各位小伙伴,好久不见,转眼都 2020 年了。感觉好久没更新公众号了,今天下午抽出了点时间写了个打地鼠小游戏,在这里分享给大家~同时祝大家新年快乐
开发工具
Python 版本: 3.6.4
相关模块:
pygame 模块;
以及一些 Python 自带的模块。
环境搭建
安装 Python 并添加到环境变量,pip 安装需要的相关模块即可。
先睹为快
在 cmd 窗口运行如下命令即可:
python Game21.py
效果如下:
原理简介
打地鼠的游戏规则相信大家都知道,这里就不多介绍了,反正就是不停地拿锤子打洞里钻出来的地鼠呗
首先,让我们确定一下游戏中有哪些元素。打地鼠打地鼠,地鼠当然得有啦,那我们就写个地鼠的游戏精灵类呗:
```
'''地鼠''' class Mole(pygame.sprite.Sprite): def init (self, image_paths, position, **kwargs): pygame.sprite.Sprite. init (self) self.images = [pygame.transform.scale(pygame.image.load(image_paths[0]), (101, 103)), pygame.transform.scale(pygame.image.load(image_paths[-1]), (101, 103))] self.image = self.images[0] self.rect = self.image.get_rect() self.mask = pygame.mask.from_surface(self.image) self.setPosition(position) self.is_hammer = False '''设置位置''' def setPosition(self, pos): self.rect.left, self.rect.top = pos '''设置被击中''' def setBeHammered(self): self.is_hammer = True '''显示在屏幕上''' def draw(self, screen): if self.is_hammer: self.image = self.images[1] screen.blit(self.image, self.rect) '''重置''' def reset(self): self.image = self.images[0] self.is_hammer = False ```
显然,地鼠有被锤子击中和未被锤子击中这两种状态,所以需要加载两张图,当地鼠被击中时从未被击中的地鼠状态图切换到被击中后的地鼠状态图(我找的图可能不太像地鼠,请各位老哥见谅)。然后我们再来定义一下锤子这个游戏精灵类,和地鼠类似,锤子也有未锤下去和已锤下去两种状态,只不过锤下去之后需要迅速恢复回未锤下去的状态,具体而言,代码实现如下:
python
class Hammer(pygame.sprite.Sprite):
def __init__(self, image_paths, position, **kwargs):
pygame.sprite.Sprite.__init__(self)
self.images = [pygame.image.load(image_paths[0]), pygame.image.load(image_paths[1])]
self.image = self.images[0]
self.rect = self.image.get_rect()
self.mask = pygame.mask.from_surface(self.images[1])
self.rect.left, self.rect.top = position
# 用于显示锤击时的特效
self.hammer_count = 0
self.hammer_last_time = 4
self.is_hammering = False
'''设置位置'''
def setPosition(self, pos):
self.rect.centerx, self.rect.centery = pos
'''设置hammering'''
def setHammering(self):
self.is_hammering = True
'''显示在屏幕上'''
def draw(self, screen):
if self.is_hammering:
self.image = self.images[1]
self.hammer_count += 1
if self.hammer_count > self.hammer_last_time:
self.is_hammering = False
self.hammer_count = 0
else:
self.image = self.images[0]
screen.blit(self.image, self.rect)
OK,定义完游戏精灵之后,我们就可以开始写主程序啦。首先自然是游戏初始化:
```python
'''游戏初始化''' def initGame(): pygame.init() pygame.mixer.init() screen = pygame.display.set_mode(cfg.SCREENSIZE) pygame.display.set_caption('Whac A Mole-微信公众号:Charles的皮卡丘') return screen ```
然后加载必要的游戏素材和定义必要的游戏变量(我都注释的比较详细了,就不在文章里赘述一遍了,自己看注释呗~)
```python
加载背景音乐和其他音效
pygame.mixer.music.load(cfg.BGM_PATH) pygame.mixer.music.play(-1) audios = { 'count_down': pygame.mixer.Sound(cfg.COUNT_DOWN_SOUND_PATH), 'hammering': pygame.mixer.Sound(cfg.HAMMERING_SOUND_PATH) } # 加载字体 font = pygame.font.Font(cfg.FONT_PATH, 40) # 加载背景图片 bg_img = pygame.image.load(cfg.GAME_BG_IMAGEPATH) # 开始界面 startInterface(screen, cfg.GAME_BEGIN_IMAGEPATHS) # 地鼠改变位置的计时 hole_pos = random.choice(cfg.HOLE_POSITIONS) change_hole_event = pygame.USEREVENT pygame.time.set_timer(change_hole_event, 800) # 地鼠 mole = Mole(cfg.MOLE_IMAGEPATHS, hole_pos) # 锤子 hammer = Hammer(cfg.HAMMER_IMAGEPATHS, (500, 250)) # 时钟 clock = pygame.time.Clock() # 分数 your_score = 0 ```
接着就是游戏主循环啦:
```python
游戏主循环
while True: # --游戏时间为60s time_remain = round((61000 - pygame.time.get_ticks()) / 1000.) # --游戏时间减少, 地鼠变位置速度变快 if time_remain == 40: pygame.time.set_timer(change_hole_event, 650) elif time_remain == 20: pygame.time.set_timer(change_hole_event, 500) # --倒计时音效 if time_remain == 10: audios['count_down'].play() # --游戏结束 if time_remain < 0: break count_down_text = font.render('Time: '+str(time_remain), True, cfg.WHITE) # --按键检测 for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() elif event.type == pygame.MOUSEMOTION: hammer.setPosition(pygame.mouse.get_pos()) elif event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: hammer.setHammering() elif event.type == change_hole_event: hole_pos = random.choice(cfg.HOLE_POSITIONS) mole.reset() mole.setPosition(hole_pos) # --碰撞检测 if hammer.is_hammering and not mole.is_hammer: is_hammer = pygame.sprite.collide_mask(hammer, mole) if is_hammer: audios['hammering'].play() mole.setBeHammered() your_score += 10 # --分数 your_score_text = font.render('Score: '+str(your_score), True, cfg.BROWN) # --绑定必要的游戏元素到屏幕(注意顺序) screen.blit(bg_img, (0, 0)) screen.blit(count_down_text, (875, 8)) screen.blit(your_score_text, (800, 430)) mole.draw(screen) hammer.draw(screen) # --更新 pygame.display.flip() clock.tick(60) ```
每一部分我也都做了注释,逻辑很简单,就不多废话了。60s 后,游戏结束,我们就可以统计分数以及和历史最高分做对比了:
```python
读取最佳分数(try块避免第一次游戏无.rec文件)
try: best_score = int(open(cfg.RECORD_PATH).read()) except: best_score = 0
若当前分数大于最佳分数则更新最佳分数
if your_score > best_score: f = open(cfg.RECORD_PATH, 'w') f.write(str(your_score)) f.close() ```
为了使游戏看起来更“正式”,再随手添个开始界面和结束界面呗:
```python '''游戏开始界面''' def startInterface(screen, begin_image_paths): begin_images = [pygame.image.load(begin_image_paths[0]), pygame.image.load(begin_image_paths[1])] begin_image = begin_images[0] while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() elif event.type == pygame.MOUSEMOTION: mouse_pos = pygame.mouse.get_pos() if mouse_pos[0] in list(range(419, 574)) and mouse_pos[1] in list(range(374, 416)): begin_image = begin_images[1] else: begin_image = begin_images[0] elif event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1 and mouse_pos[0] in list(range(419, 574)) and mouse_pos[1] in list(range(374, 416)): return True screen.blit(begin_image, (0, 0)) pygame.display.update()
'''结束界面''' def endInterface(screen, end_image_path, again_image_paths, score_info, font_path, font_colors, screensize): end_image = pygame.image.load(end_image_path) again_images = [pygame.image.load(again_image_paths[0]), pygame.image.load(again_image_paths[1])] again_image = again_images[0] font = pygame.font.Font(font_path, 50) your_score_text = font.render('Your Score: %s' % score_info['your_score'], True, font_colors[0]) your_score_rect = your_score_text.get_rect() your_score_rect.left, your_score_rect.top = (screensize[0] - your_score_rect.width) / 2, 215 best_score_text = font.render('Best Score: %s' % score_info['best_score'], True, font_colors[1]) best_score_rect = best_score_text.get_rect() best_score_rect.left, best_score_rect.top = (screensize[0] - best_score_rect.width) / 2, 275 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() elif event.type == pygame.MOUSEMOTION: mouse_pos = pygame.mouse.get_pos() if mouse_pos[0] in list(range(419, 574)) and mouse_pos[1] in list(range(374, 416)): again_image = again_images[1] else: again_image = again_images[0] elif event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1 and mouse_pos[0] in list(range(419, 574)) and mouse_pos[1] in list(range(374, 416)): return True screen.blit(end_image, (0, 0)) screen.blit(again_image, (416, 370)) screen.blit(your_score_text, your_score_rect) screen.blit(best_score_text, best_score_rect) pygame.display.update() ```
大功告成~完整源代码详见相关文件~
参考文献
- 豆玩手机游戏平台的设计与实现(吉林大学·李天明)
- 基于SSH架构的个人空间交友网站的设计与实现(北京邮电大学·隋昕航)
- 基于web的旅游服务平台的设计与实现(内蒙古大学·张凡)
- 基于PBL的初中Python教学案例开发与应用研究(佛山科学技术学院·刘星成)
- 基于页面分析的网络爬虫系统的设计与实现(华中科技大学·郝以珍)
- 南洋学院网络新闻发布系统(电子科技大学·诸国华)
- 南洋学院网络新闻发布系统(电子科技大学·诸国华)
- 促进计算思维发展的教学游戏设计与开发(山东师范大学·宗伟伟)
- 基于SSH架构的个人空间交友网站的设计与实现(北京邮电大学·隋昕航)
- 基于B/S架构的酷跑社区系统的设计与实现(内蒙古大学·张晓乐)
- 移动游戏快速开发平台设计与实现(电子科技大学·赵懋骏)
- 校园虚拟地图系统的研究与应用(中国地质大学(北京)·魏传振)
- 豆玩手机游戏平台的设计与实现(吉林大学·李天明)
- 基于J2EE的远程网络教育系统研究与实现(电子科技大学·陈南荪)
- 成语电子词典系统的设计与实现(电子科技大学·刘健)
本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:代码客栈 ,原文地址:https://bishedaima.com/yuanma/36064.html