基于 Python 制作接金币小游戏
Python 版本:3.6.4
相关模块:
pygame 模块;
以及一些 python 自带的模块。
环境搭建
安装 Python 并添加到环境变量,pip 安装需要的相关模块即可。
原理简介
首先先声明一下,这个小游戏主要是依赖 pygame 写的,不会 pygame 的小伙伴请先阅读相关的开发文档了解一下这是啥
首先,我们来进行一下游戏的初始化操作(比如初始化游戏窗口,加载一些必要的游戏素材等等),代码实现如下:
```python
'''游戏初始化''' def initGame(): # 初始化pygame, 设置展示窗口 pygame.init() screen = pygame.display.set_mode(cfg.SCREENSIZE) pygame.display.set_caption('catch coins —— 微信公众号: Charles的皮卡丘') # 加载必要的游戏素材 game_images = {} for key, value in cfg.IMAGE_PATHS.items(): if isinstance(value, list): images = [] for item in value: images.append(pygame.image.load(item)) game_images[key] = images else: game_images[key] = pygame.image.load(value) game_sounds = {} for key, value in cfg.AUDIO_PATHS.items(): if key == 'bgm': continue game_sounds[key] = pygame.mixer.Sound(value) # 返回初始化数据 return screen, game_images, game_sounds ```
接着,为了让我们在写小游戏的过程中保持一个良好的心情,就先让自己喜欢的游戏背景音乐响起来吧
然后选一张好看的背景图片,这样才可以在它的基础上逐渐加入接金币这个小游戏涉及到的游戏元素嘛:
源代码如下:
```python
游戏主循环
clock = pygame.time.Clock() while True: # --填充背景 screen.fill(0) screen.blit(game_images['background'], (0, 0)) # --按键检测 for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() # --更新屏幕 pygame.display.flip() clock.tick(cfg.FPS) ```
小人的移动主要是通过我们自己定义的 Hero 类里的 move 函数实现的,具体而言代码实现如下:
```python
'''定义hero类''' class Hero(pygame.sprite.Sprite): def init (self, images, position=(375, 520), **kwargs): pygame.sprite.Sprite. init (self) self.images_right = images[:5] self.images_left = images[5:] self.images = self.images_right.copy() self.image = self.images[0] self.mask = pygame.mask.from_surface(self.image) self.rect = self.image.get_rect() self.rect.left, self.rect.top = position self.diretion = 'right' self.speed = 8 self.switch_frame_count = 0 self.switch_frame_freq = 1 self.frame_index = 0 '''左右移动hero''' def move(self, screensize, direction): assert direction in ['left', 'right'] if direction != self.diretion: self.images = self.images_left.copy() if direction == 'left' else self.images_right.copy() self.image = self.images[0] self.diretion = direction self.switch_frame_count = 0 self.switch_frame_count += 1 if self.switch_frame_count % self.switch_frame_freq == 0: self.switch_frame_count = 0 self.frame_index = (self.frame_index + 1) % len(self.images) self.image = self.images[self.frame_index] if direction == 'left': self.rect.left = max(self.rect.left-self.speed, 0) else: self.rect.left = min(self.rect.left+self.speed, screensize[0]) '''画到屏幕上''' def draw(self, screen): screen.blit(self.image, self.rect) ```
实现小人左右走动这个效果的核心思路其实就是根据函数输入的方向来改变小人可以使用的图片组合(images_right/images_left)。然后对于正在往某个方向行动中的小人,每隔 switch_frame_freq 帧游戏画面就切换一次小人的图片,游戏中的小人图片一共十张:
前 5 张是向右走的图片组,后 5 张是向左走的图片组。
现在,我们开始实现掉金币的效果啦,就像这样:
核心代码实现如下:
```python
定义食物组
food_sprites_group = pygame.sprite.Group() generate_food_freq = random.randint(10, 20) generate_food_count = 0 while True: ... # --随机生成食物 generate_food_count += 1 if generate_food_count > generate_food_freq: generate_food_freq = random.randint(10, 20) generate_food_count = 0 food = Food(game_images, random.choice(['gold',] * 10 + ['apple']), cfg.SCREENSIZE) food_sprites_group.add(food) # --更新食物 for food in food_sprites_group: if food.update(): food_sprites_group.remove(food) ... ```
其中食物类的定义如下:
```python
'''定义食物类''' class Food(pygame.sprite.Sprite): def init (self, images_dict, selected_key, screensize, **kwargs): pygame.sprite.Sprite. init (self) self.screensize = screensize self.image = images_dict[selected_key] self.mask = pygame.mask.from_surface(self.image) self.rect = self.image.get_rect() self.rect.left, self.rect.bottom = random.randint(20, screensize[0]-20), -10 self.speed = random.randrange(5, 10) self.score = 1 if selected_key == 'gold' else 5 '''更新食物位置''' def update(self): self.rect.bottom += self.speed if self.rect.top > self.screensize[1]: return True return False ```
整个定义其实很简单,苹果 5 分,金币 1 分,update 函数用于实时更新食物的位置以实现食物下降的效果。
问题来了,我们该怎么实现接金币的效果呢,这金币一直往下掉接不住可咋办啊。别担心,只需要调用到 pygame 库里的碰撞检测功能就可以啦,具体而言代码实现如下:
python
while True:
...
# --碰撞检测
for food in food_sprites_group:
if pygame.sprite.collide_mask(food, hero):
game_sounds['get'].play()
food_sprites_group.remove(food)
score += food.score
...
代码原理其实很简单,就是实时地检测小人有没有接触到金币,接触到的话就发出接到金币的声音,并移除对应的金币和获得一定的奖励得分。效果是这样子的:
最后,我们来完善一下我们的小游戏,让它看起来更加"规范"一些:
(1) 加入倒计时(在规定的时间内获得尽量高的得分)
python
while True:
...
# --倒计时信息
countdown_text = 'Count down: ' + str((90000 - pygame.time.get_ticks()) // 60000) + ":" + str((90000 - pygame.time.get_ticks()) // 1000 % 60).zfill(2)
countdown_text = font.render(countdown_text, True, (0, 0, 0))
countdown_rect = countdown_text.get_rect()
countdown_rect.topright = [cfg.SCREENSIZE[0]-30, 5]
screen.blit(countdown_text, countdown_rect)
...
(2) 显示得分(显示当前的得分和历史最高分)
```
while True: ... # --显示得分 score_text = f'Score: {score}, Highest: {highest_score}' score_text = font.render(score_text, True, (0, 0, 0)) score_rect = score_text.get_rect() score_rect.topleft = [5, 5] screen.blit(score_text, score_rect) ... ```
(3) 添加游戏结束界面(玩家想结束游戏还是想重新开始游戏呢?)
```python
'''游戏结束画面''' def showEndGameInterface(screen, cfg, score, highest_score): # 显示的文本信息设置 font_big = pygame.font.Font(cfg.FONT_PATH, 60) font_small = pygame.font.Font(cfg.FONT_PATH, 40) text_title = font_big.render(f"Time is up!", True, (255, 0, 0)) text_title_rect = text_title.get_rect() text_title_rect.centerx = screen.get_rect().centerx text_title_rect.centery = screen.get_rect().centery - 100 text_score = font_small.render(f"Score: {score}, Highest Score: {highest_score}", True, (255, 0, 0)) text_score_rect = text_score.get_rect() text_score_rect.centerx = screen.get_rect().centerx text_score_rect.centery = screen.get_rect().centery - 10 text_tip = font_small.render(f"Enter Q to quit game or Enter R to restart game", True, (255, 0, 0)) text_tip_rect = text_tip.get_rect() text_tip_rect.centerx = screen.get_rect().centerx text_tip_rect.centery = screen.get_rect().centery + 60 text_tip_count = 0 text_tip_freq = 10 text_tip_show_flag = True # 界面主循环 clock = pygame.time.Clock() while True: screen.fill(0) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_q: return False elif event.key == pygame.K_r: return True screen.blit(text_title, text_title_rect) screen.blit(text_score, text_score_rect) if text_tip_show_flag: screen.blit(text_tip, text_tip_rect) text_tip_count += 1 if text_tip_count % text_tip_freq == 0: text_tip_count = 0 text_tip_show_flag = not text_tip_show_flag pygame.display.flip() clock.tick(cfg.FPS) ```
大功告成啦,完整源代码详见相关文件~
在终端运行如下命令即可:
python Game9.py
效果如下:
参考文献
- 基于SSH架构的个人空间交友网站的设计与实现(北京邮电大学·隋昕航)
- 基于.NET平台的游戏门户系统设计与实现(电子科技大学·余胜鹏)
- 南洋学院网络新闻发布系统(电子科技大学·诸国华)
- 金融信息实时发布系统的设计与实现(东北大学·伦健)
- 白塔区企业现金管理系统研究与设计(吉林大学·朱健君)
- 基于.NET平台的游戏门户系统设计与实现(电子科技大学·余胜鹏)
- 银行储蓄管理系统的设计与实现(吉林大学·张卓)
- 基于asp.net的在线软件项目交易系统的设计与实现(电子科技大学·顾杰)
- 理财论坛的设计与实现(吉林大学·王雷)
- 金融信息实时发布系统的设计与实现(东北大学·伦健)
- 基于SSH架构的个人空间交友网站的设计与实现(北京邮电大学·隋昕航)
- 现金管理系统的设计与实现(电子科技大学·戴丽君)
- 基于asp.net的在线软件项目交易系统的设计与实现(电子科技大学·顾杰)
- 基于.NET平台的游戏门户系统设计与实现(电子科技大学·余胜鹏)
- 基于轻量级J2EE的网络游戏虚拟物品交易系统的设计与实现(北京邮电大学·曹鹃)
本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:毕业设计驿站 ,原文地址:https://bishedaima.com/yuanma/36048.html