AI智能
改变未来

用 Python 实现微信版飞机大战

文 | 野客

来源:Python 技术「ID: pythonall」

2013 年微信 5.0 版本内置了一款经典小游戏-灰黑色版飞机大战,被称为微信经典飞机大战,在这个版本中微信甚至将欢迎设置了成了这款小游戏,用户首次登陆将会直接进入飞机大战小游戏,游戏一经推出也是火爆异常,当时还出现了许多经典语录。

我们要实现飞机大战这款小游戏,主要需要用到的是第三方模块 pygame,安装使用 pip install pygame 即可。

角色 model

飞机大战这款小游戏中角色相对比较简单,主要包括三部分:玩家、敌人和子弹。

我们先来定义一个子弹类,类中主要包括子弹样式、移动速度等,代码实现如下:

# 子弹类class Bullet(pygame.sprite.Sprite):def __init__(self, img, pos):pygame.sprite.Sprite.__init__(self)self.image = img# 设置图片的区域self.rect = self.image.get_rect()self.rect.midbottom = posself.speed = 10def move(self):self.rect.top -= self.speed

接下来我们来定义敌人类,类中主要包括敌机样式、移动速度、出现位置等,代码实现如下所示:

# 敌人类class Enemy(pygame.sprite.Sprite):def __init__(self, img, explosion_img, pos):pygame.sprite.Sprite.__init__(self)self.image = imgself.rect = self.image.get_rect()self.rect.topleft = posself.explosion_img = explosion_imgself.speed = 2# 设置击毁序列self.explosion_index = 0def move(self):# 敌人的子弹只能一直向下self.rect.top += self.speed

我们再接着来定义玩家类,类中主要包括飞机初始位置、移动方法、是否被敌机击中等,代码实现如下所示:

# 玩家类class Player(pygame.sprite.Sprite):def __init__(self, img, rect, pos):pygame.sprite.Sprite.__init__(self)self.image = []# 将飞机图片部分分隔for i in range(len(rect)):self.image.append(img.subsurface(rect[i]).convert_alpha())# 获取飞机的区域self.rect = rect[0]self.rect.topleft = posself.speed = 8# 生成精灵组实例self.bullets = pygame.sprite.Group()self.img_index = 0# 判断飞机是否被打中self.is_hit = Falsedef shoot(self, img):bullet = Bullet(img, self.rect.midtop)# 添加子弹实例到玩家的子弹组self.bullets.add(bullet)def moveUp(self):# 当遇到顶部时,设置上顶部为0if self.rect.top <= 0:self.rect.top = 0else:self.rect.top -= self.speeddef moveDown(self):# 当遇到底部时,设置一直为常值if self.rect.top >= SCREEN_HEIGHT - self.rect.height:self.rect.top = SCREEN_HEIGHT - self.rect.heightelse:self.rect.top += self.speeddef moveLeft(self):# 当遇到左边时,一直停靠在左边if self.rect.left <= 0:self.rect.left = 0else:self.rect.left -= self.speeddef moveRight(self):# 当遇到右边时, 停靠右边if self.rect.left >= SCREEN_WIDTH - self.rect.width:self.rect.left = SCREEN_WIDTH - self.rect.widthelse:self.rect.left += self.speed

运行逻辑

现在我们已经定义好游戏的角色 model 了,接下来我们可以先对角色 model、图片素材及一些常量等进行一些初始化操作,代码实现如下所示:

# 设置屏幕的宽度SCREEN_WIDTH = 450# 设置屏幕的高度SCREEN_HEIGHT = 600# 初始化窗口pygame.init()# 设置窗口标题pygame.display.set_caption(\"飞机大战\")# 设置屏幕大小screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), 0, 32)# 隐藏光标pygame.mouse.set_visible(False)# 设置背景bg = pygame.image.load(\"resources/image/bg.png\")# 设置游戏结束的图片bg_game_over = pygame.image.load(\"resources/image/bg_game_over.png\")# 加载飞机资源图片img_plane = pygame.image.load(\"resources/image/shoot.png\")img_start = pygame.image.load(\"resources/image/start.png\")img_pause = pygame.image.load(\"resources/image/pause.png\")img_icon = pygame.image.load(\"resources/image/plane.png\").convert_alpha()# 顺便设置窗口pygame.display.set_icon(img_icon)# 初始化飞机区域player_rect = []player_rect.append(pygame.Rect(0, 99, 102, 126))player_rect.append(pygame.Rect(165, 360, 102, 126))# 玩家爆炸图片player_rect.append(pygame.Rect(165, 234, 102, 126))player_rect.append(pygame.Rect(330, 624, 102, 126))player_rect.append(pygame.Rect(330, 498, 102, 126))player_rect.append(pygame.Rect(432, 624, 102, 126))# 初始化位置player_pos = [200, 450]# 生成玩家类player = Player(img_plane, player_rect, player_pos)# 设置子弹框bullet_rect = pygame.Rect(1004, 987, 9, 21)# 加载子弹图片bullet_img = img_plane.subsurface(bullet_rect)# 设置敌人框enemy_rect = pygame.Rect(534, 612, 57, 43)# 设置敌人图片enemy_img = img_plane.subsurface(enemy_rect)# 设置敌人被击图片enemy_explosion_imgs = []enemy_explosion_imgs.append(img_plane.subsurface(pygame.Rect(267, 347, 57, 43)))enemy_explosion_imgs.append(img_plane.subsurface(pygame.Rect(873, 697, 57, 43)))enemy_explosion_imgs.append(img_plane.subsurface(pygame.Rect(267, 296, 57, 43)))enemy_explosion_imgs.append(img_plane.subsurface(pygame.Rect(930, 697, 57, 43)))# 设置敌机精灵组enemies = pygame.sprite.Group()# 设置敌机被击精灵组enemies_explosion = pygame.sprite.Group()# 设置射击频率shoot_frequency = 0# 设置敌机频率enemy_frequency = 0# 设置玩家被击的图片顺序player_explosion_index = 16score = 0running = Trueis_pause = Falseis_game_over = Falseclock = pygame.time.Clock()

最后,我们来看一下游戏运行中最重要的一部分-游戏的运行逻辑,主要包括:敌机的生成运行、子弹的生成运行、生成分数、游戏状态的处理(暂停、重置、结束)等,具体代码实现如下所示:

# 开始游戏循环while running:# 设置游戏帧率为 60clock.tick(60)if not is_pause and not is_game_over:if not player.is_hit:# 设置连续射击,因为每秒 60 帧,15/60=0.25 秒发一次子弹if shoot_frequency % 15 == 0:player.shoot(bullet_img)shoot_frequency += 1# 当设置的射击频率大于 15,置零if shoot_frequency >= 15:shoot_frequency = 0# 控制生成敌机的频率if enemy_frequency % 50 == 0:# 设置敌机的出现的位置enemy_pos = [random.randint(0, SCREEN_WIDTH - enemy_rect.width), 0]enemy = Enemy(enemy_img, enemy_explosion_imgs, enemy_pos)enemies.add(enemy)enemy_frequency += 1if enemy_frequency >= 100:enemy_frequency = 0# 控制子弹的显示运行for bullet in player.bullets:bullet.move()if bullet.rect.bottom < 0:player.bullets.remove(bullet)# 控制敌机的运行for enemy in enemies:enemy.move()# 判断敌机是否与玩家飞机碰撞if pygame.sprite.collide_circle(enemy, player):enemies_explosion.add(enemy)enemies.remove(enemy)player.is_hit = True# 设置玩家的飞机被毁is_game_over = True# 判断敌机是否在界面if enemy.rect.top < 0:enemies.remove(enemy)# 设置敌机与玩家的飞机子弹相碰时,返回被击的敌机实例enemy_explosion = pygame.sprite.groupcollide(enemies, player.bullets, 1, 1)for enemy in enemy_explosion:enemies_explosion.add(enemy)# 绘制屏幕screen.fill(0)# 加入背景图片screen.blit(bg, (0, 0))# 添加玩家飞机图片到屏幕if not player.is_hit:screen.blit(player.image[int(player.img_index)], player.rect)player.img_index = shoot_frequency / 8else:if player_explosion_index > 47:is_game_over = Trueelse:player.img_index = player_explosion_index / 8screen.blit(player.image[int(player.img_index)], player.rect)player_explosion_index += 1# 敌机被子弹击中的效果显示for enemy in enemies_explosion:if enemy.explosion_index == 0:passif enemy.explosion_index > 7:enemies_explosion.remove(enemy)score += 100continue# 敌机被击时显示图片screen.blit(enemy.explosion_img[int(enemy.explosion_index / 2)], enemy.rect)enemy.explosion_index += 1# 显示子弹player.bullets.draw(screen)# 显示敌机enemies.draw(screen)# 分数的显示效果score_font = pygame.font.Font(None, 36)score_text = score_font.render(str(score), True, (128, 128, 128))# 设置文字框text_rect = score_text.get_rect()# 放置文字的位置text_rect.topleft = [20, 10]# 显示出分数screen.blit(score_text, text_rect)left, middle, right = pygame.mouse.get_pressed()# 暂停游戏if right == True and not is_game_over:is_pause = Trueif left == True:# 重置游戏if is_game_over:is_game_over = Falseplayer_rect = []player_rect.append(pygame.Rect(0, 99, 102, 126))player_rect.append(pygame.Rect(165, 360, 102, 126))player_rect.append(pygame.Rect(165, 234, 102, 126))player_rect.append(pygame.Rect(330, 624, 102, 126))player_rect.append(pygame.Rect(330, 498, 102, 126))player_rect.append(pygame.Rect(432, 624, 102, 126))player = Player(img_plane, player_rect, player_pos)bullet_rect = pygame.Rect(1004, 987, 9, 21)bullet_img = img_plane.subsurface(bullet_rect)enemy_rect = pygame.Rect(534, 612, 57, 43)enemy_img = img_plane.subsurface(enemy_rect)enemy_explosion_imgs = []enemy_explosion_imgs.append(img_plane.subsurface(pygame.Rect(267, 347, 57, 43)))enemy_explosion_imgs.append(img_plane.subsurface(pygame.Rect(873, 697, 57, 43)))enemy_explosion_imgs.append(img_plane.subsurface(pygame.Rect(267, 296, 57, 43)))enemy_explosion_imgs.append(img_plane.subsurface(pygame.Rect(930, 697, 57, 43)))enemies = pygame.sprite.Group()enemies_explosion = pygame.sprite.Group()score = 0shoot_frequency = 0enemy_frequency = 0player_explosion_index = 16# 继续游戏if is_pause:is_pause = False# 游戏结束if is_game_over:font = pygame.font.SysFont(\"微软雅黑\", 48)text = font.render(\"Score: \" + str(score), True, (255, 0, 0))text_rect = text.get_rect()text_rect.centerx = screen.get_rect().centerxtext_rect.centery = screen.get_rect().centery + 70# 显示游戏结束画面screen.blit(bg_game_over, (0, 0))# 显示分数screen.blit(text, text_rect)font = pygame.font.SysFont(\"微软雅黑\", 40)text = font.render(\"Press Left Mouse to Restart\", True, (255, 0, 0))text_rect = text.get_rect()text_rect.centerx = screen.get_rect().centerxtext_rect.centery = screen.get_rect().centery + 150screen.blit(text, text_rect)# 刷新屏幕pygame.display.update()# 处理游戏退出for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()exit()if not is_pause and not is_game_over:key = pygame.key.get_pressed()if key[K_w] or key[K_UP]:player.moveUp()if key[K_s] or key[K_DOWN]:player.moveDown()if key[K_a] or key[K_LEFT]:player.moveLeft()if key[K_d] or key[K_RIGHT]:player.moveRight()

我们来看一下实现效果:

总结

本文我们使用 Python 实现了微信版飞机大战的基本功能,大家有兴趣的可以获取源码自己玩了,如果你对游戏哪个地方实现的不满意,还可以自己进行修改。

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 用 Python 实现微信版飞机大战