python/pygame坦克游戏边学边写笔记——完结(七)

python/pygame坦克游戏边学边写笔记——完结(七)预想的坦克游戏的基本功能到这里基本都实现了 这里贴出全部源文件完整代码 一共 8 个文件 把使用到的游戏元素路径 命名对应就可以实际运行

大家好,欢迎来到IT知识分享网。

预想的坦克游戏的基本功能到这里基本都实现了,这里贴出全部源文件完整代码,一共8个文件,把使用到的游戏元素路径、命名对应就可以实际运行。

一、完整主循环文件代码:main.py

# 导入使用到的库 import os.path import pygame import sys import player_tank import wall_map import enemy_tank import sound from player_tank import PlayerTank from collision_detection import collision_detection # 初始化pygame pygame.init() # 定义常量 WIDTH = 1000 HEIGHT = 600 BLACK = (0, 0, 0) FPS = 60 # 定义变量,running用来控制主循环 running = True option_number = 0 level = 0 # 确定游戏窗口,设定游戏时钟 game_window = pygame.display.set_mode((WIDTH, HEIGHT)) clock = pygame.time.Clock() # 建立精灵组,all_sprites用来存放全部的精灵组,通过调用draw函数和update函数实现图片绘制及更新移动 all_sprites = pygame.sprite.Group() # 事件响应函数,接受键盘控制响应 def control(player): global running, option_number, level for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.KEYDOWN: # 按Tab键移动mini坦克位置,执行不同选项 if event.key == pygame.K_TAB: if option_number < 4: option_number += 1 else: option_number = 0 # 如果在1 Player位置时按Enter键进入第一关游戏 if event.key == pygame.K_RETURN and option_number == 0: level = 1 # 游戏中按Esc终结游戏 if event.key == pygame.K_ESCAPE: player.life = 0 def draw_text(surface, text, x, y, size): font = pygame.font.Font(os.path.join('font', 'HarmonyOS_Sans_SC_Regular.ttf'), size) font_text = font.render(text, False, (255, 255, 255)) font_rect = font_text.get_rect() font_rect.x = x font_rect.y = y surface.blit(font_text, (x, y)) def game_info(surface, player): surface.fill((100, 100, 100), (900, 0, 1000, 600)) draw_text(surface, '玩家坦克: ' + str(player.life), 905, 20, 12) draw_text(surface, '游戏说明: ', 905, 60, 12) draw_text(surface, '← 向左移动', 905, 80, 12) draw_text(surface, '↑ 向上移动', 905, 100, 12) draw_text(surface, '↓ 向下移动', 905, 120, 12) draw_text(surface, '→ 向右移动', 905, 140, 12) draw_text(surface, '空格键发射子弹', 905, 160, 12) draw_text(surface, '击毁敌方坦克数:', 905, 220, 12) draw_text(surface, str(player.score), 905, 240, 20) # 开始界面函数 def start_interface(surface): start_image = pygame.image.load(os.path.join('image', 'game', 'GameStart.png')) surface.blit(start_image, (0, 0)) mini_image = pygame.image.load((os.path.join('image', 'game', 'mini_tank.png'))) surface.blit(mini_image, (340, 310 + option_number * 45)) draw_text(surface, '按Tab键选择菜单,按Enter键进入', 340, 270, 20) sound.Music(sound.intro_sound).play() # 结束界面函数 def end_interface(surface): end_image = pygame.image.load(os.path.join('image', 'game', 'GameOver.png')) surface.blit(end_image, (0, 0)) sound.Music(sound.game_over_sound).play() # 游戏主循环 def main(): # 实例化玩家坦克,初始位置为家的左侧 player = PlayerTank(325, 550) # 主循环 while running: # 接受键盘控制并响应 control(player) # 游戏窗口背景,暂时填充为黑色 game_window.fill(BLACK) # 如果玩家生命数量大于0,游戏开始,小于0则游戏结束 if player.life > 0: # 设定level为0是为开始界面,游戏选择及玩法说明 if level == 0: start_interface(game_window) # 第一关游戏,更换地图等 elif level == 1: game_info(game_window, player) # 地图墙 wall_map.wall_map(game_window) # 敌方坦克 enemy_tank.new_enemy_tank() # 所有精灵添加到组,显示并更新 all_sprites.add(player, player_tank.player_bullets, wall_map.wall_sprites, enemy_tank.enemy_sprites, enemy_tank.enemy_bullets) all_sprites.draw(game_window) all_sprites.update() # 碰撞检测 collision_detection(player, game_window) # 第二关游戏,更换地图等 elif level == 2: pass # 玩家生命数量为0时,结束游戏,显示得分及重新开始 else: end_interface(game_window) # 设定游戏帧率 clock.tick(FPS) # 设定游戏窗口名称,并显示实时帧率 pygame.display.set_caption('Tank ' + '{0:0.2f}'.format(clock.get_fps())) # 刷新游戏窗口 pygame.display.update() # 退出pygame/python pygame.quit() sys.exit() if __name__ == '__main__': main() 

二、完整玩家坦克代码:player_tank.py

import os import pygame import sound from bullet import Bullet player_bullets = pygame.sprite.Group() # 玩家坦克类,继承精灵属性,图片存放于字典中,并按照方向归类 class PlayerTank(pygame.sprite.Sprite): player_tank_dict = { 'up': [], 'down': [], 'left': [], 'right': [] } # 通过for循环,将图片分别加入字典中个方向值的列表 for i in range(6): player_tank_dict['up'].append( pygame.image.load(os.path.join('image', 'player_tank', 'up' + str(i + 1) + '.png'))) player_tank_dict['down'].append( pygame.image.load(os.path.join('image', 'player_tank', 'down' + str(i + 1) + '.png'))) player_tank_dict['left'].append( pygame.image.load(os.path.join('image', 'player_tank', 'left' + str(i + 1) + '.png'))) player_tank_dict['right'].append( pygame.image.load(os.path.join('image', 'player_tank', 'right' + str(i + 1) + '.png'))) # 初始化函数,定义方向、装甲、移动开关、速度 def __init__(self, x, y): pygame.sprite.Sprite.__init__(self) self.direction = 'up' self.amour = 5 self.life = 3 self.image = self.player_tank_dict[self.direction][self.amour] self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y self.radius = (self.rect.width - 4) / 2 self.direction_x = None self.direction_y = None self.extra_speed = 2 self.speed = 2 + self.extra_speed self.prx, self.pry = self.rect.x, self.rect.y self.last_shoot = 0 self.shoot_reload = 500 self.score = 0 # 重写update函数,重新加载图片,实现图片跟随direction值改变方向,实现玩家坦克移动 def update(self): self.image = self.player_tank_dict[self.direction][self.amour] self.prx, self.pry = self.rect.x, self.rect.y self.speed = 2 + self.extra_speed key_pressed = pygame.key.get_pressed() if key_pressed[pygame.K_UP] and self.rect.top >= 0: sound.Music(sound.move_sound).play() self.direction = 'up' if self.direction_y: self.rect.y -= self.speed if key_pressed[pygame.K_DOWN] and self.rect.bottom <= 600: sound.Music(sound.move_sound).play() self.direction = 'down' if self.direction_y: self.rect.y += self.speed if key_pressed[pygame.K_LEFT] and self.rect.x >= 0: sound.Music(sound.move_sound).play() self.direction = 'left' if self.direction_x: self.rect.x -= self.speed if key_pressed[pygame.K_RIGHT] and self.rect.right <= 900: sound.Music(sound.move_sound).play() self.direction = 'right' if self.direction_x: self.rect.x += self.speed if key_pressed[pygame.K_SPACE]: self.shoot() # 设定移动方向开关,控制坦克只能在横向或纵向移动 if self.direction == 'up' or self.direction == 'down': self.direction_x = False self.direction_y = True if self.direction == 'left' or self.direction == 'right': self.direction_x = True self.direction_y = False def shoot(self): now_shoot = pygame.time.get_ticks() if now_shoot - self.last_shoot >= self.shoot_reload: player_bullet = Bullet(self.direction, self.rect.centerx, self.rect.centery) player_bullets.add(player_bullet) sound.Music(sound.shoot_sound).play() self.last_shoot = now_shoot

三、敌方坦克完整代码:enemy_tank.py

# 导入库 import random import os.path import pygame from bullet import Bullet enemy_sprites = pygame.sprite.Group() enemy_bullets = pygame.sprite.Group() enemy_tank_number = 0 # 敌方坦克类 class EnemyTank(pygame.sprite.Sprite): # 根据坦克种类及各种类的状态数量,建立一个列表来遍历。如第1种坦克有3种状态。。。。第4种坦克有10种状态。 type_list = [(1, 3, 3, 0), (2, 1, 5, 3), (3, 2, 7, 2), (4, 10, 6, 1)] # 初始化函数,定义方向、速度等 def __init__(self): pygame.sprite.Sprite.__init__(self) # 随机选择一种坦克 self.order = self.type_list[random.randint(0, len(self.type_list) - 1)] self.enemy_tank_dict = { 'up': [], 'down': [], 'left': [], 'right': [] } for i in range(self.order[1]): self.enemy_tank_dict['up'].append( pygame.image.load( os.path.join('image', 'enemy', 'enemy_tank' + str(self.order[0]), 'up' + str(i + 1) + '.png'))) self.enemy_tank_dict['down'].append( pygame.image.load( os.path.join('image', 'enemy', 'enemy_tank' + str(self.order[0]), 'down' + str(i + 1) + '.png'))) self.enemy_tank_dict['left'].append( pygame.image.load( os.path.join('image', 'enemy', 'enemy_tank' + str(self.order[0]), 'left' + str(i + 1) + '.png'))) self.enemy_tank_dict['right'].append( pygame.image.load( os.path.join('image', 'enemy', 'enemy_tank' + str(self.order[0]), 'right' + str(i + 1) + '.png'))) print(self.order, self.enemy_tank_dict) self.direction = 'up' self.amour = self.order[1] self.image = self.enemy_tank_dict[self.direction][self.amour - 1] self.rect = self.image.get_rect() self.rect.x = random.randrange(0, 900 - self.rect.width) self.rect.y = 0 self.radius = (self.rect.width - 4) / 2 self.move = True self.extra_speed = 5 self.speed = self.order[2] + self.extra_speed self.damage = self.order[3] self.step = 30 self.accumulationMax = 0 self.accumulation = 0.1 self.prx, self.pry = self.rect.x, self.rect.y # 移动、重绘坦克 def update(self): self.shoot() if self.move: self.speed = self.order[2] + self.extra_speed self.prx, self.pry = self.rect.x, self.rect.y if self.accumulationMax >= 1: self.accumulationMax = 0 if self.direction == 'up' and self.step > 0: self.rect.y -= self.speed self.step -= 1 elif self.direction == 'down' and self.step > 0: self.rect.y += self.speed self.step -= 1 elif self.direction == 'left' and self.step > 0: self.rect.x -= self.speed self.step -= 1 elif self.direction == 'right' and self.step > 0: self.rect.x += self.speed self.step -= 1 else: self.accumulationMax += self.accumulation else: self.direction = random.choice(['up', 'down', 'left', 'right']) self.image = self.enemy_tank_dict[self.direction][self.amour - 1] self.rect.x, self.rect.y = self.prx, self.pry self.step = 30 self.move = True if self.direction == 'up' and self.rect.top <= 0: self.move = False elif self.direction == 'down' and self.rect.bottom >= 600: self.move = False elif self.direction == 'left' and self.rect.left <= 0: self.move = False elif self.direction == 'right' and self.rect.right >= 900: self.move = False if self.step <= 0: self.move = False def shoot(self): i = random.randrange(0, 100) if i == 5: enemy_bullet = Bullet(self.direction, self.rect.centerx, self.rect.centery) enemy_bullets.add(enemy_bullet) def new_enemy_tank(): if len(enemy_sprites) < 4: enemy = EnemyTank() enemy_sprites.add(enemy)

 四、地图、墙wall_map.py

# 导入库 import os.path import pygame import pandas # 导入各种墙图片 black_stone_wall = pygame.image.load(os.path.join('image', 'wall', 'black_stone_wall.png')) white_stone_wall = pygame.image.load(os.path.join('image', 'wall', 'white_stone_wall.png')) brick_wall = pygame.image.load(os.path.join('image', 'wall', 'brick_wall.png')) grass = pygame.image.load(os.path.join('image', 'wall', 'grass.png')) river = pygame.image.load(os.path.join('image', 'wall', 'river.png')) home = pygame.image.load(os.path.join('image', 'wall', 'home.png')) # 墙加载开关 wall_switch = True # 所有墙的组 wall_sprites = pygame.sprite.Group() # 砖墙类 class Wall(pygame.sprite.Sprite): # 砖墙属性字典 wall_dict = { 'black_stone_wall': [black_stone_wall, 50], 'white_stone_wall': [white_stone_wall, 10], 'brick_wall': [brick_wall, 1], 'grass': [grass, 100], 'river': [river, 100], 'home': [home, 1] } # 初始化属性 def __init__(self, surface, filename, wall_type, x, y): pygame.sprite.Sprite.__init__(self) self.surface = surface self.filename = filename self.wall_type = wall_type self.image = self.wall_dict[self.wall_type][0] self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y self.radius = (self.rect.width - 2) / 2 self.hp = self.wall_dict[self.wall_type][1] # 更新图片 def update(self): self.image = self.wall_dict[self.wall_type][0] self.surface.blit(self.image, (self.rect.x, self.rect.y)) def wall_map(surface): global wall_switch filename = os.path.join('image', 'map', 'map1.xlsx') data = pandas.read_excel(filename, header=None) if wall_switch: for row in range(24): for colum in range(36): if data.iloc[row, colum] == '石': wall_type = 'white_stone_wall' wall = Wall(surface, filename, wall_type, colum * 25, row * 25) wall_sprites.add(wall) if data.iloc[row, colum] == '砖': wall_type = 'brick_wall' wall = Wall(surface, filename, wall_type, colum * 25, row * 25) wall_sprites.add(wall) if data.iloc[row, colum] == '黑': wall_type = 'black_stone_wall' wall = Wall(surface, filename, wall_type, colum * 25, row * 25) wall_sprites.add(wall) if data.iloc[row, colum] == '草': wall_type = 'grass' wall = Wall(surface, filename, wall_type, colum * 25, row * 25) wall_sprites.add(wall) if data.iloc[row, colum] == '河': wall_type = 'river' wall = Wall(surface, filename, wall_type, colum * 25, row * 25) wall_sprites.add(wall) if data.iloc[row, colum] == '家': wall_type = 'home' wall = Wall(surface, filename, wall_type, colum * 25, row * 25) wall_sprites.add(wall) wall_switch = False 

五、子弹类完整代码bullet.py 

import pygame import os bullet_up = pygame.image.load(os.path.join('image', 'bullet', 'bullet_up.png')) bullet_down = pygame.image.load(os.path.join('image', 'bullet', 'bullet_down.png')) bullet_left = pygame.image.load(os.path.join('image', 'bullet', 'bullet_left.png')) bullet_right = pygame.image.load(os.path.join('image', 'bullet', 'bullet_right.png')) class Bullet(pygame.sprite.Sprite): bullet_dict = { 'up': bullet_up, 'down': bullet_down, 'left': bullet_left, 'right': bullet_right } def __init__(self, bullet_type, x, y): pygame.sprite.Sprite.__init__(self) self.bullet_type = bullet_type self.image = self.bullet_dict[self.bullet_type] self.rect = self.image.get_rect() self.rect.centerx = x self.rect.centery = y self.extra_speed = 5 self.speed = 5 + self.extra_speed self.damage = 1 def update(self): self.speed = 5 + self.extra_speed if self.bullet_type == 'up' and self.rect.top > 0: self.rect.y -= self.speed elif self.bullet_type == 'down' and self.rect.bottom < 600: self.rect.y += self.speed elif self.bullet_type == 'left' and self.rect.left > 0: self.rect.x -= self.speed elif self.bullet_type == 'right' and self.rect.right < 900: self.rect.x += self.speed else: self.kill() 

六、碰撞检测collision_detection.py:

import pygame import sound from enemy_tank import enemy_sprites, enemy_bullets from player_tank import player_bullets from wall_map import wall_sprites from explode import Explode # 碰撞检测 def collision_detection(player, surface): # 敌方坦克与墙的碰撞,遇到墙则停止移动,重新调整方向,遇到草地则减速,失去额外速度加成。 enemy_wall = pygame.sprite.groupcollide(enemy_sprites, wall_sprites, False, False, pygame.sprite.collide_circle) for enemy_w, e_wall in enemy_wall.items(): if e_wall[0].wall_type == 'grass': enemy_w.extra_speed = 0 else: enemy_w.extra_speed = 5 enemy_w.move = False # 玩家坦克与墙的碰撞,遇到墙则停止移动,遇到草地则减速,失去额外速度加成。 player_wall = pygame.sprite.spritecollide(player, wall_sprites, False, pygame.sprite.collide_circle) if player_wall: for p_wall in player_wall: if p_wall.wall_type == 'grass': player.extra_speed = 0 else: player.extra_speed = 2 player.rect.x, player.rect.y = player.prx, player.pry # 敌方子弹与墙的碰撞,子弹消失,红砖墙可以被击毁,白砖、黑砖需要多次才能击毁,子弹可以通过草地,子弹不能通过河水。 bullet_wall = pygame.sprite.groupcollide(wall_sprites, enemy_bullets, False, False) for b_wall, bullet_w in bullet_wall.items(): if b_wall.wall_type == 'grass': bullet_w[0].extra_speed = max(bullet_w[0].extra_speed - 1, 0) elif b_wall.wall_type == 'river': bullet_w[0].kill() elif b_wall.wall_type == 'home': player.life = 0 else: b_wall.hp -= bullet_w[0].damage bullet_w[0].kill() if b_wall.hp <= 0: b_wall.kill() # 玩家子弹与墙的碰撞,子弹消失,红砖墙可以被击毁,白砖、黑砖需要多次才能击毁,子弹可以通过草地,子弹不能通过河水。 bullet_wall = pygame.sprite.groupcollide(wall_sprites, player_bullets, False, False) for b_wall, bullet_w in bullet_wall.items(): if b_wall.wall_type == 'grass': bullet_w[0].extra_speed = max(bullet_w[0].extra_speed - 1, 0) elif b_wall.wall_type == 'river': bullet_w[0].kill() else: b_wall.hp -= bullet_w[0].damage bullet_w[0].kill() if b_wall.hp <= 0: b_wall.kill() # 玩家子弹击中敌方坦克,子弹消失,敌方坦克生命值减少 player_hit_enemy = pygame.sprite.groupcollide(enemy_sprites, player_bullets, False, True) for hit_enemy, hit_bullet in player_hit_enemy.items(): hit_enemy.amour -= hit_bullet[0].damage if hit_enemy.amour <= 0: explode = Explode(surface, hit_enemy.rect.x, hit_enemy.rect.y) explode.update() hit_enemy.kill() sound.Music(sound.kill_sound).play() player.score += 1 # 玩家坦克被击中,敌方子弹消失,玩家坦克生命、装甲值减少 enemy_hit_player = pygame.sprite.spritecollide(player, enemy_bullets, False) for e_bullet in enemy_hit_player: e_bullet.kill() # 防止玩家坦克同时被多颗子弹击中出现amour为负值。 player.amour = max(player.amour - e_bullet.damage, 0) if player.amour <= 0: player.kill() explode = Explode(surface, player.rect.x, player.rect.y) explode.update() player.life -= 1 # 如果玩家还有生命数量,玩家坦克在初始位置重生,重置各项属性 if player.life > 0: player.rect.x, player.rect.y = 325, 550 player.amour = 5 player.extra_speed = 2 player.direction = 'up' 

 七、爆炸效果explode.py

import os.path import pygame class Explode: def __init__(self, surface, x, y): self.surface = surface self.image = pygame.image.load(os.path.join('image', 'explode', 'explode.png')) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y def update(self): for i in range(6): self.image = pygame.image.load(os.path.join('image', 'explode', 'explode.png')) self.surface.blit(self.image, (self.rect.x, self.rect.y)) 

 八、声音效果sound.py

import pygame import os move_sound = os.path.join('sound', 'move.wav') shoot_sound = os.path.join('sound', 'shoot.wav') intro_sound = os.path.join('sound', 'intro.wav') game_over_sound = os.path.join('sound', 'game_over.wav') kill_sound = os.path.join('sound', 'kill.wav') class Music: def __init__(self, sound_name): pygame.mixer.init() self.sound_name = sound_name self.sound = pygame.mixer.Sound(self.sound_name) def play(self, loops=0): self.sound.set_volume(0.2) self.sound.play(loops) 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/117441.html

(0)
上一篇 2025-11-21 07:45
下一篇 2025-11-21 08:10

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信