吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 221|回复: 5
上一主题 下一主题
收起左侧

[原创工具] Python开发的“松鼠大战”游戏

[复制链接]
跳转到指定楼层
楼主
xhlbudd 发表于 2026-5-6 23:49 回帖奖励
最近在教舅舅家上初二的儿子Python编程,每次教完基本语法,都会用一个小游戏来帮助他提高兴趣。今天为大家带来Python开发的“松鼠大战”游戏,使用pygame 2.5.2 (SDL 2.28.3, Python 3.12.6)开发,一共580行代码,欢迎大家下载试玩。下载链接如下(exe格式的游戏26MB,附源代码和音乐素材):

通过网盘分享的文件:202605 松鼠大战
链接: https://pan.baidu.com/s/1vUVXW87iwoHCeh0o3klY1w?pwd=52pj 提取码: 52pj
同时把源代码分享如下,请大家多多指点:
[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()

游戏截图1.png (205.02 KB, 下载次数: 0)

游戏截图1

游戏截图1

游戏截图2.png (147.93 KB, 下载次数: 0)

游戏截图2

游戏截图2

免费评分

参与人数 3吾爱币 +3 热心值 +3 收起 理由
didi科学家 + 1 + 1 热心回复!
cuul953 + 1 + 1 热心回复!
CGR + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
cuul953 发表于 2026-5-7 00:03
有其他网盘就更好了
3#
 楼主| xhlbudd 发表于 2026-5-7 00:05 |楼主
cuul953 发表于 2026-5-7 00:03
有其他网盘就更好了

百度网盘如果没有会员下载会慢一些,不过一共27MB,不算很大
4#
leishoulin 发表于 2026-5-7 00:43
5#
kmoui 发表于 2026-5-7 01:39
  有一种小时候学 Flash 的既视感
6#
sunhuan 发表于 2026-5-7 07:04
厉害厉害
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-5-7 07:04

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表