python
复制代码
import pygame
import random
import os
# 初始化pygame和混音器
pygame.init()
pygame.mixer.init()
# 屏幕设置
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("坦克大战增强版")
# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
# 游戏常量
TANK_SIZE = 40
BULLET_SIZE = 10
WALL_SIZE = 40
# 加载图片和音效
def load_image(name):
return pygame.image.load(os.path.join('images', name)).convert_alpha()
def load_sound(name):
return pygame.mixer.Sound(os.path.join('sounds', name))
# 游戏状态
class GameState:
def __init__(self):
self.score = 0
self.lives = 3
self.level = 1
self.game_over = False
self.paused = False
# 坦克基类
class BaseTank(pygame.sprite.Sprite):
def __init__(self, color, x, y):
super().__init__()
self.original_image = pygame.Surface((TANK_SIZE, TANK_SIZE))
self.original_image.fill(color)
self.image = self.original_image
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.speed = 5
self.direction = "up"
self.shoot_delay = 500 # 射击延迟(毫秒)
self.last_shot = pygame.time.get_ticks()
def rotate(self, angle):
self.image = pygame.transform.rotate(self.original_image, angle)
self.rect = self.image.get_rect(center=self.rect.center)
# 玩家坦克
class PlayerTank(BaseTank):
def __init__(self, x, y):
super().__init__(GREEN, x, y)
self.lives = 3
self.invincible = False
self.invincible_timer = 0
def update(self, keys, current_time):
if self.invincible:
if current_time - self.invincible_timer > 3000: # 3秒无敌时间
self.invincible = False
if keys[pygame.K_LEFT]:
self.rect.x = max(0, self.rect.x - self.speed)
self.direction = "left"
self.rotate(90)
if keys[pygame.K_RIGHT]:
self.rect.x = min(SCREEN_WIDTH - self.rect.width, self.rect.x + self.speed)
self.direction = "right"
self.rotate(-90)
if keys[pygame.K_UP]:
self.rect.y = max(0, self.rect.y - self.speed)
self.direction = "up"
self.rotate(0)
if keys[pygame.K_DOWN]:
self.rect.y = min(SCREEN_HEIGHT - self.rect.height, self.rect.y + self.speed)
self.direction = "down"
self.rotate(180)
# 敌人坦克
class EnemyTank(BaseTank):
def __init__(self, x, y):
super().__init__(RED, x, y)
self.speed = 3
self.direction_timer = pygame.time.get_ticks()
self.direction_change_delay = 1000
def update(self, current_time):
# 随机改变方向
if current_time - self.direction_timer > self.direction_change_delay:
self.direction = random.choice(["up", "down", "left", "right"])
self.direction_timer = current_time
# 根据方向移动
if self.direction == "left":
self.rect.x = max(0, self.rect.x - self.speed)
self.rotate(90)
elif self.direction == "right":
self.rect.x = min(SCREEN_WIDTH - self.rect.width, self.rect.x + self.speed)
self.rotate(-90)
elif self.direction == "up":
self.rect.y = max(0, self.rect.y - self.speed)
self.rotate(0)
elif self.direction == "down":
self.rect.y = min(SCREEN_HEIGHT - self.rect.height, self.rect.y + self.speed)
self.rotate(180)
# 随机射击
if random.random() < 0.02: # 2%的概率射击
return True
return False
# 子弹类
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, direction, owner):
super().__init__()
self.image = pygame.Surface((BULLET_SIZE, BULLET_SIZE))
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.direction = direction
self.speed = 10
self.owner = owner # 'player' 或 'enemy'
def update(self):
if self.direction == "up":
self.rect.y -= self.speed
elif self.direction == "down":
self.rect.y += self.speed
elif self.direction == "left":
self.rect.x -= self.speed
elif self.direction == "right":
self.rect.x += self.speed
# 移除屏幕外的子弹
if (self.rect.bottom < 0 or self.rect.top > SCREEN_HEIGHT or
self.rect.right < 0 or self.rect.left > SCREEN_WIDTH):
self.kill()
# 墙壁类
class Wall(pygame.sprite.Sprite):
def __init__(self, x, y, destructible=True):
super().__init__()
self.image = pygame.Surface((WALL_SIZE, WALL_SIZE))
self.image.fill(BLUE if destructible else WHITE)
self.rect = self.image.get_rect()
self.rect.topleft = (x, y)
self.destructible = destructible
# 基地类
class Base(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface((WALL_SIZE, WALL_SIZE))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.topleft = (x, y)
# 游戏管理器
class Game:
def __init__(self):
self.state = GameState()
self.all_sprites = pygame.sprite.Group()
self.players = pygame.sprite.Group()
self.enemies = pygame.sprite.Group()
self.bullets = pygame.sprite.Group()
self.walls = pygame.sprite.Group()
self.bases = pygame.sprite.Group()
# 创建玩家
self.player = PlayerTank(SCREEN_WIDTH // 2, SCREEN_HEIGHT - 60)
self.all_sprites.add(self.player)
self.players.add(self.player)
# 创建基地
self.base = Base(SCREEN_WIDTH // 2 - WALL_SIZE // 2, SCREEN_HEIGHT - WALL_SIZE)
self.all_sprites.add(self.base)
self.bases.add(self.base)
# 创建初始敌人
self.spawn_enemies()
# 创建墙壁
self.create_walls()
# 加载音效
# self.shoot_sound = load_sound('shoot.wav')
# self.explosion_sound = load_sound('explosion.wav')
def spawn_enemies(self):
for _ in range(5):
x = random.randint(0, SCREEN_WIDTH - TANK_SIZE)
enemy = EnemyTank(x, 50)
self.all_sprites.add(enemy)
self.enemies.add(enemy)
def create_walls(self):
# 创建一些随机的墙壁
for _ in range(20):
x = random.randint(0, SCREEN_WIDTH - WALL_SIZE)
y = random.randint(100, SCREEN_HEIGHT - 100)
wall = Wall(x, y)
self.all_sprites.add(wall)
self.walls.add(wall)
def handle_collisions(self):
# 子弹与墙壁碰撞
for bullet in self.bullets:
wall_hits = pygame.sprite.spritecollide(bullet, self.walls, False)
for wall in wall_hits:
if wall.destructible:
wall.kill()
bullet.kill()
# self.explosion_sound.play()
# 子弹与坦克碰撞
for bullet in self.bullets:
if bullet.owner == 'player':
enemy_hits = pygame.sprite.spritecollide(bullet, self.enemies, True)
if enemy_hits:
bullet.kill()
self.state.score += 100
# self.explosion_sound.play()
elif bullet.owner == 'enemy':
player_hits = pygame.sprite.spritecollide(bullet, self.players, False)
if player_hits and not self.player.invincible:
bullet.kill()
self.player.lives -= 1
if self.player.lives <= 0:
self.state.game_over = True
else:
self.player.invincible = True
self.player.invincible_timer = pygame.time.get_ticks()
# self.explosion_sound.play()
# 子弹与基地碰撞
base_hits = pygame.sprite.spritecollide(self.base, self.bullets, True)
if base_hits:
self.state.game_over = True
def update(self):
current_time = pygame.time.get_ticks()
# 更新玩家
keys = pygame.key.get_pressed()
self.player.update(keys, current_time)
# 更新敌人
for enemy in self.enemies:
if enemy.update(current_time):
bullet = Bullet(enemy.rect.centerx, enemy.rect.centery,
enemy.direction, 'enemy')
self.all_sprites.add(bullet)
self.bullets.add(bullet)
# self.shoot_sound.play()
# 更新子弹
self.bullets.update()
# 处理碰撞
self.handle_collisions()
# 检查是否需要生成新的敌人
if len(self.enemies) < 5:
self.spawn_enemies()
def draw(self):
screen.fill(BLACK)
self.all_sprites.draw(screen)
# 绘制得分和生命值
font = pygame.font.Font(None, 36)
score_text = font.render(f'Score: {self.state.score}', True, WHITE)
lives_text = font.render(f'Lives: {self.player.lives}', True, WHITE)
screen.blit(score_text, (10, 10))
screen.blit(lives_text, (10, 40))
if self.state.game_over:
game_over_text = font.render('GAME OVER', True, RED)
screen.blit(game_over_text,
(SCREEN_WIDTH//2 - game_over_text.get_width()//2,
SCREEN_HEIGHT//2 - game_over_text.get_height()//2))
pygame.display.flip()
def main():
clock = pygame.time.Clock()
game = Game()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and not game.state.game_over:
bullet = Bullet(game.player.rect.centerx,
game.player.rect.centery,
game.player.direction, 'player')
game.all_sprites.add(bullet)
game.bullets.add(bullet)
# game.shoot_sound.play()
elif event.key == pygame.K_r and game.state.game_over:
game = Game() # 重新开始游戏
if not game.state.game_over:
game.update()
game.draw()
clock.tick(60)
pygame.quit()
if __name__ == "__main__":
main()