2025年Pygame学习笔记11:三角函数及Tank Battle游戏

Pygame学习笔记11:三角函数及Tank Battle游戏这一次将运用三角函数的相关知识以及前面学过的相关知识 如声音 精灵图像等来设计 Tank Battle 游戏 即坦克大战 Tank Battle 游戏 为了实现该游戏 需要再向 MyLibrary py 文件中添加一些东西 计算两个点之间的角度 def target angle x1 y1 x2 y2

大家好,我是讯享网,很高兴认识大家。

这一次将运用三角函数的相关知识以及前面学过的相关知识,如声音、精灵图像等来设计Tank Battle游戏,即坦克大战。

Tank Battle游戏

为了实现该游戏,需要再向MyLibrary.py文件中添加一些东西:

# 计算两个点之间的角度 def target_angle(x1, y1, x2, y2): delta_x = x2 - x1 delta_y = y2 - y1 angle_radians = math.atan2(delta_y, delta_x) angle_degrees = math.degrees(angle_radians) return angle_degrees def angular_velocity(angle): vel = Point(0, 0) vel.x = math.cos(math.radians(angle)) vel.y = math.sin(math.radians(angle)) return vel 

讯享网

即用于实现旋转角度的一些函数

精灵类

涉及的精灵类有玩家坦克、敌方坦克和子弹类:


讯享网

讯享网class Tank(MySprite): def __init__(self, tank_file="tank.png", turret_file="turret.png"): MySprite.__init__(self) self.load(tank_file, 50, 60, 4) self.speed = 0.0 self.scratch = None self.float_pos = Point(0, 0) self.velocity = Point(0, 0) self.turret = MySprite() self.turret.load(turret_file, 32, 64, 4) self.fire_timer = 0 def update(self, ticks): MySprite.update(self, ticks, 100) self.rotation = wrap_angle(self.rotation) self.scratch = pygame.transform.rotate(self.image, -self.rotation) angle = wrap_angle(self.rotation - 90) self.velocity = angular_velocity(angle) self.float_pos.x += self.velocity.x self.float_pos.y += self.velocity.y # 保证坦克会一直留在界面上 if self.float_pos.x < -50: self.float_pos.x = 800 elif self.float_pos.x > 800: self.float_pos.x = -50 if self.float_pos.y < -60: self.float_pos.y = 600 elif self.float_pos.y > 600: self.float_pos.y = -60 self.X = int(self.float_pos.x) self.Y = int(self.float_pos.y) self.turret.position = (self.X, self.Y) self.turret.last_frame = 0 self.turret.update(ticks, 100) self.turret.rotation = wrap_angle(self.turret.rotation) angle = self.turret.rotation + 90 self.turret.scratch = pygame.transform.rotate(self.turret.image, -angle) def draw(self, surface): width, height = self.scratch.get_size() center = Point(width / 2, height / 2) surface.blit(self.scratch, (self.X - center.x, self.Y - center.y)) # 绘制炮塔 width, height = self.turret.scratch.get_size() center = Point(width / 2, height / 2) surface.blit(self.turret.scratch, (self.turret.X - center.x, self.turret.Y - center.y)) def __str__(self): return MySprite.__str__(self) + ", " + str(self.velocity) class EnemyTank(Tank): def __init__(self, tank_file="enemy_tank.png", turret_file="enemy_turret.png"): Tank.__init__(self, tank_file, turret_file) def update(self, ticks): self.turret.rotation = wrap_angle(self.rotation - 90) Tank.update(self, ticks) def draw(self, surface): Tank.draw(self, surface) class Bullet(object): def __init__(self, position): self.alive = True self.color = (250, 20, 20) self.position = Point(position.x, position.y) self.velocity = Point(0, 0) self.rect = Rect(0, 0, 4, 4) self.owner = "" def update(self, ticks): self.position.x += self.velocity.x * 10.0 self.position.y += self.velocity.y * 10.0 if self.position.x < 0 or self.position.x > 800 or self.position.y < 0 or self.position.y > 600: self.alive = False self.rect = Rect(self.position.x, self.position.y, 4, 4) def draw(self, surface): pos = (int(self.position.x), int(self.position.y)) pygame.draw.circle(surface, self.color, pos, 4, 0) 

为了实现子弹类,还需要三个辅助函数用以实现双方坦克发射炮弹:

# 坦克发射炮弹 def fire_cannon(tank): position = Point(tank.turret.X, tank.turret.Y) bullet = Bullet(position) angle = tank.turret.rotation bullet.velocity = angular_velocity(angle) bullets.append(bullet) play_sound(shoot_sound) return bullet # 玩家发射炮弹 def player_fire_cannon(): bullet = fire_cannon(player) bullet.owner = "player" bullet.color = (30, 250, 30) # 敌方发射炮弹 def enemy_fire_cannon(): bullet = fire_cannon(enemy_tank) bullet.owner = "enemy" bullet.color = (250, 30, 30) 

游戏初始化操作

讯享网# 游戏的一些初始化操作 def game_init(): global screen, backbuffer, font, timer, player_group, player, enemy_tank, bullets, crosshair, crosshair_group pygame.init() screen = pygame.display.set_mode((800, 600)) backbuffer = pygame.Surface((800, 600)) pygame.display.set_caption("Tank Battle Game") font = pygame.font.Font(None, 30) timer = pygame.time.Clock() pygame.mouse.set_visible(False) # 加载鼠标光标 crosshair = MySprite() crosshair.load("crosshair.png") crosshair_group = pygame.sprite.GroupSingle() crosshair_group.add(crosshair) # 创建玩家的坦克 player = Tank() player.float_pos = Point(400, 300) # 创建敌方坦克 enemy_tank = EnemyTank() enemy_tank.float_pos = Point(random.randint(50, 760), 50) enemy_tank.rotation = 135 # 创建子弹精灵组 bullets = list() 

还有声音的相关函数:

# 用于初始化加载声音 def audio_init(): global shoot_sound, boom_sound pygame.mixer.init() shoot_sound = pygame.mixer.Sound("shoot.wav") boom_sound = pygame.mixer.Sound("boom.wav") # 播放声音 def play_sound(sound): channel = pygame.mixer.find_channel(True) channel.set_volume(0.5) channel.play(sound) 

完整源代码

源代码如下:

讯享网import random import sys import pygame from pygame.locals import * from MyLibrary import * class Tank(MySprite): def __init__(self, tank_file="tank.png", turret_file="turret.png"): MySprite.__init__(self) self.load(tank_file, 50, 60, 4) self.speed = 0.0 self.scratch = None self.float_pos = Point(0, 0) self.velocity = Point(0, 0) self.turret = MySprite() self.turret.load(turret_file, 32, 64, 4) self.fire_timer = 0 def update(self, ticks): MySprite.update(self, ticks, 100) self.rotation = wrap_angle(self.rotation) self.scratch = pygame.transform.rotate(self.image, -self.rotation) angle = wrap_angle(self.rotation - 90) self.velocity = angular_velocity(angle) self.float_pos.x += self.velocity.x self.float_pos.y += self.velocity.y # 保证坦克会一直留在界面上 if self.float_pos.x < -50: self.float_pos.x = 800 elif self.float_pos.x > 800: self.float_pos.x = -50 if self.float_pos.y < -60: self.float_pos.y = 600 elif self.float_pos.y > 600: self.float_pos.y = -60 self.X = int(self.float_pos.x) self.Y = int(self.float_pos.y) self.turret.position = (self.X, self.Y) self.turret.last_frame = 0 self.turret.update(ticks, 100) self.turret.rotation = wrap_angle(self.turret.rotation) angle = self.turret.rotation + 90 self.turret.scratch = pygame.transform.rotate(self.turret.image, -angle) def draw(self, surface): width, height = self.scratch.get_size() center = Point(width / 2, height / 2) surface.blit(self.scratch, (self.X - center.x, self.Y - center.y)) # 绘制炮塔 width, height = self.turret.scratch.get_size() center = Point(width / 2, height / 2) surface.blit(self.turret.scratch, (self.turret.X - center.x, self.turret.Y - center.y)) def __str__(self): return MySprite.__str__(self) + ", " + str(self.velocity) class EnemyTank(Tank): def __init__(self, tank_file="enemy_tank.png", turret_file="enemy_turret.png"): Tank.__init__(self, tank_file, turret_file) def update(self, ticks): self.turret.rotation = wrap_angle(self.rotation - 90) Tank.update(self, ticks) def draw(self, surface): Tank.draw(self, surface) class Bullet(object): def __init__(self, position): self.alive = True self.color = (250, 20, 20) self.position = Point(position.x, position.y) self.velocity = Point(0, 0) self.rect = Rect(0, 0, 4, 4) self.owner = "" def update(self, ticks): self.position.x += self.velocity.x * 10.0 self.position.y += self.velocity.y * 10.0 if self.position.x < 0 or self.position.x > 800 or self.position.y < 0 or self.position.y > 600: self.alive = False self.rect = Rect(self.position.x, self.position.y, 4, 4) def draw(self, surface): pos = (int(self.position.x), int(self.position.y)) pygame.draw.circle(surface, self.color, pos, 4, 0) # 坦克发射炮弹 def fire_cannon(tank): position = Point(tank.turret.X, tank.turret.Y) bullet = Bullet(position) angle = tank.turret.rotation bullet.velocity = angular_velocity(angle) bullets.append(bullet) play_sound(shoot_sound) return bullet # 玩家发射炮弹 def player_fire_cannon(): bullet = fire_cannon(player) bullet.owner = "player" bullet.color = (30, 250, 30) # 敌方发射炮弹 def enemy_fire_cannon(): bullet = fire_cannon(enemy_tank) bullet.owner = "enemy" bullet.color = (250, 30, 30) # 游戏的一些初始化操作 def game_init(): global screen, backbuffer, font, timer, player_group, player, enemy_tank, bullets, crosshair, crosshair_group pygame.init() screen = pygame.display.set_mode((800, 600)) backbuffer = pygame.Surface((800, 600)) pygame.display.set_caption("Tank Battle Game") font = pygame.font.Font(None, 30) timer = pygame.time.Clock() pygame.mouse.set_visible(False) # 加载鼠标光标 crosshair = MySprite() crosshair.load("crosshair.png") crosshair_group = pygame.sprite.GroupSingle() crosshair_group.add(crosshair) # 创建玩家的坦克 player = Tank() player.float_pos = Point(400, 300) # 创建敌方坦克 enemy_tank = EnemyTank() enemy_tank.float_pos = Point(random.randint(50, 760), 50) enemy_tank.rotation = 135 # 创建子弹精灵组 bullets = list() # 用于初始化加载声音 def audio_init(): global shoot_sound, boom_sound pygame.mixer.init() shoot_sound = pygame.mixer.Sound("shoot.wav") boom_sound = pygame.mixer.Sound("boom.wav") # 播放声音 def play_sound(sound): channel = pygame.mixer.find_channel(True) channel.set_volume(0.5) channel.play(sound) if __name__ == "__main__": game_init() audio_init() game_over = False player_score = 0 enemy_score = 0 last_time = 0 mouse_x = mouse_y = 0 while True: timer.tick(30) ticks = pygame.time.get_ticks() mouse_up = mouse_down = 0 mouse_up_x = mouse_up_y = 0 mouse_down_x = mouse_down_y = 0 for event in pygame.event.get(): if event.type == QUIT: sys.exit() elif event.type == MOUSEMOTION: mouse_x, mouse_y = event.pos mov_x, mov_y = event.rel elif event.type == MOUSEBUTTONDOWN: mouse_down = event.button mouse_down_x, mouse_down_y = event.pos elif event.type == MOUSEBUTTONUP: mouse_up = event.button mouse_up_x, mouse_up_y = event.pos keys = pygame.key.get_pressed() if keys[K_ESCAPE]: sys.exit() # 左右键用于控制旋转 elif keys[K_a] or keys[K_LEFT]: player.rotation -= 2.0 elif keys[K_d] or keys[K_RIGHT]: player.rotation += 2.0 # 按空格键或者按鼠标则发射炮弹 if keys[K_SPACE] or mouse_up > 0: if ticks > player.fire_timer + 1000: player.fire_timer = ticks player_fire_cannon() if not game_over: crosshair.position = (mouse_x, mouse_y) crosshair_group.update(ticks) angle = target_angle(player.turret.X, player.turret.Y, crosshair.X + crosshair.frame_width / 2, crosshair.Y + crosshair.frame_height / 2) player.turret.rotation = angle player.update(ticks) enemy_tank.update(ticks) # 设置敌方坦克每隔1秒发射一枚炮弹 if ticks > enemy_tank.fire_timer + 1000: enemy_tank.fire_timer = ticks enemy_fire_cannon() # 对每一枚炮弹做相应的处理 for bullet in bullets: bullet.update(ticks) if bullet.owner == "player": if pygame.sprite.collide_rect(bullet, enemy_tank): player_score += 1 bullet.alive = False play_sound(boom_sound) elif bullet.owner == "enemy": if pygame.sprite.collide_rect(bullet, player): enemy_score += 1 bullet.alive = False play_sound(boom_sound) backbuffer.fill((100, 100, 20)) for bullet in bullets: bullet.draw(backbuffer) enemy_tank.draw(backbuffer) player.draw(backbuffer) crosshair_group.draw(backbuffer) screen.blit(backbuffer, (0, 0)) if not game_over: print_text(font, 0, 0, "PLAYER:" + str(player_score)) print_text(font, 700, 0, "ENEMY:" + str(enemy_score)) else: print_text(font, 0, 0, "G A M E O V E R") # 命中的子弹消失 for bullet in bullets: if bullet.alive == False: bullets.remove(bullet) pygame.display.update() 

运行结果如下:
在这里插入图片描述

小讯
上一篇 2025-03-02 09:56
下一篇 2025-03-09 14:13

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/21321.html