[Python] 纯文本查看 复制代码
import pygame
import random
import math
import sys
from enum import Enum
import os
game_path = os.path.dirname(__file__)
bg_music = os.path.join(game_path, "蒂沃丽花园.ogg")
pygame.mixer.init()
pygame.mixer.music.load(bg_music)
pygame.mixer.music.play(-1)
# 初始化pygame
pygame.init()
# 屏幕设置
SCREEN_WIDTH = 1000
SCREEN_HEIGHT = 700
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("松鼠大战 by xhlbudd@52pojie")
clock = pygame.time.Clock()
# 颜色定义
class Colors:
BROWN = (139, 69, 19)
DARK_BROWN = (101, 67, 33)
LIGHT_BROWN = (205, 133, 63)
GREEN = (34, 139, 34)
DARK_GREEN = (0, 100, 0)
RED = (220, 20, 60)
YELLOW = (255, 215, 0)
ORANGE = (255, 165, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
SKY_BLUE = (135, 206, 235)
CLOUD_WHITE = (248, 248, 255)
TREE_TRUNK = (101, 67, 33)
LEAF_GREEN = (34, 139, 34)
ACORN_BROWN = (139, 90, 43)
# 游戏状态枚举
class GameState(Enum):
START = 1
PLAYING = 2
GAME_OVER = 3
WIN = 4
class Squirrel:
def __init__(self, x, y, size, speed, is_player=False):
self.x = x
self.y = y
self.size = size
self.original_size = size
self.speed = speed
self.is_player = is_player
self.color = Colors.ORANGE if is_player else Colors.BROWN
self.direction = random.uniform(0, 2 * math.pi)
self.energy = 100
self.last_eat_time = 0
self.flash_timer = 0
self.wobble = 0
self.wobble_speed = random.uniform(0.05, 0.1)
self.animation_timer = 0
self.tail_angle = 0
def move(self, player_x=None, player_y=None):
"""移动松鼠"""
self.animation_timer += 1
if self.is_player:
# 玩家松鼠跟随鼠标
mouse_x, mouse_y = pygame.mouse.get_pos()
dx = mouse_x - self.x
dy = mouse_y - self.y
dist = math.sqrt(dx*dx + dy*dy)
if dist > 5: # 防止抖动
self.direction = math.atan2(dy, dx)
move_speed = min(self.speed, dist/10)
self.x += math.cos(self.direction) * move_speed
self.y += math.sin(self.direction) * move_speed
else:
# AI松鼠移动
if random.random() < 0.02:
self.direction += random.uniform(-1, 1)
# 如果有玩家,尝试靠近(如果玩家比自己小)或远离(如果玩家比自己大)
if player_x is not None and player_y is not None:
dx = player_x - self.x
dy = player_y - self.y
dist = math.sqrt(dx*dx + dy*dy)
if dist > 0:
if self.size > 30: # 大松鼠会追逐玩家
self.direction = math.atan2(dy, dx)
elif self.size < 20: # 小松鼠会逃离玩家
self.direction = math.atan2(dy, dx) + math.pi
self.x += math.cos(self.direction) * self.speed
self.y += math.sin(self.direction) * self.speed
# 边界检查
if self.x < self.size:
self.x = self.size
self.direction = random.uniform(-math.pi/2, math.pi/2)
elif self.x > SCREEN_WIDTH - self.size:
self.x = SCREEN_WIDTH - self.size
self.direction = random.uniform(math.pi/2, 3*math.pi/2)
if self.y < self.size:
self.y = self.size
self.direction = random.uniform(0, math.pi)
elif self.y > SCREEN_HEIGHT - self.size:
self.y = SCREEN_HEIGHT - self.size
self.direction = random.uniform(math.pi, 2*math.pi)
# 更新动画效果
self.wobble = math.sin(self.animation_timer * self.wobble_speed) * 3
self.tail_angle = math.sin(self.animation_timer * 0.1) * 0.5
# 更新闪光效果
if self.flash_timer > 0:
self.flash_timer -= 1
def draw(self, screen):
"""绘制松鼠"""
# 计算绘制位置(带波动效果)
draw_x = self.x + self.wobble
draw_y = self.y
# 如果正在闪光,改变颜色
current_color = self.color
if self.flash_timer > 0 and self.flash_timer % 4 < 2:
current_color = Colors.WHITE
# 绘制身体(椭圆)
pygame.draw.ellipse(screen, current_color,
(draw_x - self.size, draw_y - self.size/1.5,
self.size*2, self.size*1.5))
# 绘制尾巴(弧形)
tail_points = []
for i in range(5):
angle = self.tail_angle + i * 0.3
px = draw_x - self.size + math.cos(angle) * self.size * 1.5
py = draw_y - self.size/2 + math.sin(angle) * self.size
tail_points.append((px, py))
if len(tail_points) >= 3:
pygame.draw.polygon(screen, Colors.DARK_BROWN, tail_points)
# 绘制头部
head_radius = self.size * 0.6
pygame.draw.circle(screen, Colors.LIGHT_BROWN,
(int(draw_x + self.size * 0.8), int(draw_y)),
int(head_radius))
# 绘制耳朵
ear_radius = self.size * 0.3
for i in [-1, 1]:
ear_x = draw_x + self.size * 0.8 + i * head_radius * 0.7
ear_y = draw_y - head_radius * 0.7
pygame.draw.circle(screen, Colors.LIGHT_BROWN, (int(ear_x), int(ear_y)), int(ear_radius))
pygame.draw.circle(screen, Colors.DARK_BROWN, (int(ear_x), int(ear_y)), int(ear_radius * 0.6))
# 绘制眼睛
eye_radius = self.size * 0.15
for i in [-1, 1]:
eye_x = draw_x + self.size * 0.8 + i * head_radius * 0.4
eye_y = draw_y
pygame.draw.circle(screen, Colors.BLACK, (int(eye_x), int(eye_y)), int(eye_radius))
pygame.draw.circle(screen, Colors.WHITE, (int(eye_x - eye_radius*0.3), int(eye_y - eye_radius*0.3)), int(eye_radius*0.4))
# 绘制胡须
whisker_length = self.size * 0.4
for i in [-1, 0, 1]:
start_x = draw_x + self.size * 0.8 + head_radius
start_y = draw_y + i * self.size * 0.2
end_x = start_x + whisker_length
end_y = start_y + i * self.size * 0.1
pygame.draw.line(screen, Colors.BLACK, (start_x, start_y), (end_x, end_y), 1)
# 如果松鼠特别大,添加特殊效果
if self.size > 50:
# 绘制光环
pygame.draw.circle(screen, Colors.YELLOW,
(int(draw_x), int(draw_y)),
int(self.size + 10), 3)
# 如果是玩家松鼠,显示大小
if self.is_player:
font = pygame.font.Font(None, 24)
size_text = font.render(f"Size: {int(self.size)}", True, Colors.WHITE)
screen.blit(size_text, (int(draw_x - 30), int(draw_y - self.size - 20)))
def check_collision(self, other):
"""检查与另一只松鼠的碰撞"""
dx = self.x - other.x
dy = self.y - other.y
distance = math.sqrt(dx*dx + dy*dy)
return distance < (self.size + other.size) * 0.8
def grow(self, amount):
"""松鼠长大"""
self.size += amount
self.speed = max(2, 5 - self.size * 0.05) # 越大越慢
def flash(self):
"""闪光(被攻击时)"""
self.flash_timer = 20
class Game:
def __init__(self):
self.state = GameState.START
self.player = Squirrel(SCREEN_WIDTH//2, SCREEN_HEIGHT//2, 20, 5, True) # 玩家松鼠的初始大小为20,可以自行调整
self.ai_squirrels = []
self.acorns = []
self.score = 0
self.lives = 3
self.game_time = 0
self.spawn_timer = 0
self.omega_size = 300 # 成为Omega Squirrel的大小
self.particles = []
self.init_ai_squirrels()
self.init_acorns()
# 加载音效
self.sounds = {}
try:
# 创建简单的音效
self.create_sounds()
except:
pass
# 加载字体
self.font_large = pygame.font.SysFont('simhei', 48)
self.font_medium = pygame.font.SysFont('simhei', 36)
self.font_small = pygame.font.SysFont('simhei', 24)
def create_sounds(self):
"""创建简单的音效"""
pass # 可以在这里添加音效生成代码
def init_ai_squirrels(self):
"""初始化AI松鼠"""
for _ in range(10):
size = random.uniform(10, 40)
speed = 5 - size * 0.1
x = random.randint(50, SCREEN_WIDTH-50)
y = random.randint(50, SCREEN_HEIGHT-50)
self.ai_squirrels.append(Squirrel(x, y, size, speed))
def init_acorns(self):
"""初始化橡子"""
for _ in range(20):
x = random.randint(20, SCREEN_WIDTH-20)
y = random.randint(20, SCREEN_HEIGHT-20)
self.acorns.append((x, y))
def draw_acorn(self, screen, x, y):
"""绘制橡子"""
# 橡子身体
pygame.draw.ellipse(screen, Colors.ACORN_BROWN,
(x-8, y-5, 16, 10))
# 橡子帽子
pygame.draw.arc(screen, Colors.DARK_BROWN,
(x-6, y-10, 12, 8), 0, math.pi, 3)
# 橡子柄
pygame.draw.line(screen, Colors.DARK_BROWN,
(x, y-10), (x, y-15), 2)
def draw_background(self, screen):
"""绘制游戏背景"""
# 天空
screen.fill(Colors.SKY_BLUE)
# 云朵
for i in range(3):
x = (self.game_time * 0.5 + i * 300) % (SCREEN_WIDTH + 400) - 200
y = 100 + i * 100
pygame.draw.ellipse(screen, Colors.CLOUD_WHITE, (x, y, 120, 50))
pygame.draw.ellipse(screen, Colors.CLOUD_WHITE, (x+30, y-20, 100, 60))
pygame.draw.ellipse(screen, Colors.CLOUD_WHITE, (x+80, y, 80, 50))
# 树木
for i in range(5):
x = i * 200
# 树干
pygame.draw.rect(screen, Colors.TREE_TRUNK,
(x + 20, SCREEN_HEIGHT-150, 30, 150))
# 树冠
for j in range(3):
pygame.draw.circle(screen, Colors.LEAF_GREEN,
(x + 35, SCREEN_HEIGHT-200 + j*40), 50)
# 草地
for i in range(SCREEN_WIDTH // 20):
x = i * 20
height = random.randint(10, 30)
pygame.draw.line(screen, Colors.GREEN,
(x, SCREEN_HEIGHT),
(x, SCREEN_HEIGHT - height), 3)
def draw_ui(self, screen):
"""绘制用户界面"""
# 分数
score_text = self.font_small.render(f"得分: {self.score}", True, Colors.WHITE)
screen.blit(score_text, (10, 10))
# 玩家大小
size_text = self.font_small.render(f"大小: {int(self.player.size)}/{self.omega_size}", True, Colors.YELLOW)
screen.blit(size_text, (10, 40))
# 进度条
progress = min(1.0, self.player.size / self.omega_size)
pygame.draw.rect(screen, Colors.DARK_GREEN, (10, 100, 200, 20))
pygame.draw.rect(screen, Colors.GREEN, (10, 100, int(200 * progress), 20))
pygame.draw.rect(screen, Colors.WHITE, (10, 100, 200, 20), 2)
# 进度文本
progress_text = self.font_small.render(f"进度: {int(progress*100)}%", True, Colors.WHITE)
screen.blit(progress_text, (10, 70))
def draw_start_screen(self, screen):
"""绘制开始屏幕"""
screen.fill(Colors.DARK_GREEN)
# 标题
title_text = self.font_large.render("松鼠大战", True, Colors.YELLOW)
screen.blit(title_text, (SCREEN_WIDTH//2 - title_text.get_width()//2, 100))
# 绘制示例松鼠
for i, size in enumerate([15, 30, 60, 100]):
x = 200 + i * 200
y = 300
squirrel = Squirrel(x, y, size, 0)
squirrel.draw(screen)
size_text = self.font_small.render(f"大小: {size}", True, Colors.WHITE)
screen.blit(size_text, (x - 30, y + 50))
# 游戏说明
instructions = [
"玩法介绍:",
"移动鼠标控制松鼠",
"吃掉比自己小的松鼠就可以长大",
"碰到比自己大的松鼠游戏结束",
"长到300变成松鼠之王,获得胜利"
]
for i, line in enumerate(instructions):
text = self.font_small.render(line, True, Colors.WHITE)
screen.blit(text, (SCREEN_WIDTH//2 - text.get_width()//2, 400 + i * 30))
# 开始按钮
start_button = pygame.Rect(SCREEN_WIDTH//2 - 100, 600, 200, 60)
pygame.draw.rect(screen, Colors.ORANGE, start_button, border_radius=15)
pygame.draw.rect(screen, Colors.YELLOW, start_button, 3, border_radius=15)
start_text = self.font_medium.render("开始游戏", True, Colors.WHITE)
screen.blit(start_text, (SCREEN_WIDTH//2 - start_text.get_width()//2, 610))
return start_button
def draw_game_over_screen(self, screen, win=False):
"""绘制游戏结束屏幕"""
overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
overlay.fill((0, 0, 0, 200))
screen.blit(overlay, (0, 0))
if win:
title = "你是松鼠之王,获得胜利啦!"
color = Colors.YELLOW
else:
title = "游戏结束"
color = Colors.RED
title_text = self.font_large.render(title, True, color)
screen.blit(title_text, (SCREEN_WIDTH//2 - title_text.get_width()//2, 200))
stats = [
f"最终得分: {self.score}",
f"最终大小: {int(self.player.size)}",
]
for i, line in enumerate(stats):
text = self.font_medium.render(line, True, Colors.WHITE)
screen.blit(text, (SCREEN_WIDTH//2 - text.get_width()//2, 300 + i * 50))
# 重新开始按钮
restart_button = pygame.Rect(SCREEN_WIDTH//2 - 150, 550, 300, 60)
pygame.draw.rect(screen, Colors.ORANGE, restart_button, border_radius=15)
pygame.draw.rect(screen, Colors.YELLOW, restart_button, 3, border_radius=15)
restart_text = self.font_medium.render("点击重玩", True, Colors.WHITE)
screen.blit(restart_text, (SCREEN_WIDTH//2 - restart_text.get_width()//2, 560))
return restart_button
def spawn_particles(self, x, y, color, count=20):
"""生成粒子效果"""
for _ in range(count):
angle = random.uniform(0, 2 * math.pi)
speed = random.uniform(1, 5)
size = random.uniform(2, 6)
lifetime = random.uniform(20, 40)
self.particles.append({
'x': x,
'y': y,
'vx': math.cos(angle) * speed,
'vy': math.sin(angle) * speed,
'size': size,
'color': color,
'lifetime': lifetime
})
def update_particles(self):
"""更新粒子效果"""
for particle in self.particles[:]:
particle['x'] += particle['vx']
particle['y'] += particle['vy']
particle['vy'] += 0.1 # 重力
particle['lifetime'] -= 1
if particle['lifetime'] <= 0:
self.particles.remove(particle)
def draw_particles(self, screen):
"""绘制粒子效果"""
for particle in self.particles:
alpha = int(255 * (particle['lifetime'] / 40))
color = list(particle['color'])
if len(color) == 3:
color.append(alpha)
pygame.draw.circle(screen, color,
(int(particle['x']), int(particle['y'])),
int(particle['size']))
def update(self):
"""更新游戏状态"""
if self.state != GameState.PLAYING:
return
self.game_time += 1
self.spawn_timer += 1
# 更新玩家
self.player.move()
# 边界检查
self.player.x = max(self.player.size, min(SCREEN_WIDTH - self.player.size, self.player.x))
self.player.y = max(self.player.size, min(SCREEN_HEIGHT - self.player.size, self.player.y))
# 更新AI松鼠
for squirrel in self.ai_squirrels[:]:
squirrel.move(self.player.x, self.player.y)
# 检查碰撞
if self.player.check_collision(squirrel):
if self.player.size > squirrel.size * 1.01: #1.1: # 玩家更大,吃掉AI
# 玩家长大
growth = squirrel.size * 0.3
self.player.grow(growth)
self.score += int(squirrel.size * 10)
# 粒子效果
self.spawn_particles(squirrel.x, squirrel.y, Colors.ORANGE)
# 移除被吃掉的松鼠
self.ai_squirrels.remove(squirrel)
# 检查是否获胜
if self.player.size >= self.omega_size:
self.state = GameState.WIN
return
elif squirrel.size > self.player.size * 1.1: # AI更大,玩家受伤
self.lives -= 1
self.player.flash()
# 粒子效果
self.spawn_particles(self.player.x, self.player.y, Colors.RED)
if self.lives <= 0:
self.state = GameState.GAME_OVER
return
# 定期生成新松鼠
if self.spawn_timer > 60 and len(self.ai_squirrels) < 20: # 每秒最多生成一个,最多20个
size = random.uniform(10, min(50, self.player.size * 1.5))
speed = 5 - size * 0.1
x = random.randint(50, SCREEN_WIDTH-50)
y = random.randint(50, SCREEN_HEIGHT-50)
self.ai_squirrels.append(Squirrel(x, y, size, speed))
self.spawn_timer = 0
# 更新粒子
self.update_particles()
def draw(self, screen):
"""绘制游戏"""
self.draw_background(screen)
# 绘制橡子
for acorn in self.acorns:
self.draw_acorn(screen, acorn[0], acorn[1])
# 绘制AI松鼠
for squirrel in self.ai_squirrels:
squirrel.draw(screen)
# 绘制玩家
self.player.draw(screen)
# 绘制粒子
self.draw_particles(screen)
# 绘制UI
self.draw_ui(screen)
def handle_events(self):
"""处理事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = pygame.mouse.get_pos()
if self.state == GameState.START:
start_button = self.draw_start_screen(screen)
if start_button.collidepoint(mouse_pos):
self.state = GameState.PLAYING
elif self.state in [GameState.GAME_OVER, GameState.WIN]:
restart_button = self.draw_game_over_screen(screen, self.state == GameState.WIN)
if restart_button.collidepoint(mouse_pos):
self.__init__() # 重新开始游戏
self.state = GameState.PLAYING
return True
def run(self):
"""运行游戏主循环"""
running = True
while running:
# 处理事件
running = self.handle_events()
# 更新游戏状态
self.update()
# 绘制
screen.fill(Colors.BLACK)
if self.state == GameState.START:
self.draw_start_screen(screen)
elif self.state == GameState.PLAYING:
self.draw(screen)
elif self.state in [GameState.GAME_OVER, GameState.WIN]:
self.draw(screen) # 先绘制游戏画面
self.draw_game_over_screen(screen, self.state == GameState.WIN)
pygame.display.flip()
clock.tick(60) # 60 FPS
pygame.quit()
sys.exit()
# 运行游戏
if __name__ == "__main__":
try:
game = Game()
game.run()
except Exception as e:
print(f"游戏运行出错: {e}")
import traceback
traceback.print_exc()
pygame.quit()