当前位置: 首页 > article >正文

【Python游戏】双人简单对战游戏

以下是一个使用 Python 的 pygame 库实现的简单对战游戏示例,游戏中玩家可以控制两个角色进行对战,并且支持自定义图片(最好使用无底色的png图片)。

在这里插入图片描述
完整源码以及实现思路:

import pygame
import os

# 初始化 Pygame
pygame.init()

# 设置游戏窗口
WIDTH, HEIGHT = 800, 600
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("对战游戏")

# 加载角色图片(假设图片存在于当前目录下)
try:
    PLAYER1_IMAGE = pygame.image.load(os.path.join('player1.png')).convert_alpha()
    PLAYER2_IMAGE = pygame.image.load(os.path.join('player2.png')).convert_alpha()
    PLAYER1_IMAGE = pygame.transform.scale(PLAYER1_IMAGE, (100, 100))
    PLAYER2_IMAGE = pygame.transform.scale(PLAYER2_IMAGE, (100, 100))
    BULLET_IMAGE = pygame.image.load(os.path.join('bullet.png')).convert_alpha()
    BULLET_IMAGE = pygame.transform.scale(BULLET_IMAGE, (50, 50))
except FileNotFoundError:
    print("未找到角色或子弹图片,请确保 player1.png、player2.png 和 bullet.png 在当前目录。")
    pygame.quit()
    exit()

# 定义颜色
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)

# 定义字体
FONT = pygame.font.SysFont('comicsans', 30)

# 定义子弹类
class Bullet(pygame.sprite.Sprite):
    def __init__(self, x, y, direction):
        super().__init__()
        self.image = BULLET_IMAGE
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.speed = 10
        self.direction = direction

    def update(self):
        if self.direction == 1:  # 向右
            self.rect.x += self.speed
        else:  # 向左
            self.rect.x -= self.speed
        # 如果子弹超出屏幕范围,将其从精灵组中移除
        if self.rect.x < 0 or self.rect.x > WIDTH:
            self.kill()

# 定义角色类
class Player(pygame.sprite.Sprite):
    def __init__(self, x, y, image):
        super().__init__()
        self.image = image
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.speed = 5
        self.health = 100
        self.attacking = False
        self.attack_cooldown = 0
        self.bullets = pygame.sprite.Group()

    def move_left(self):
        if self.rect.x > 0:
            self.rect.x -= self.speed

    def move_right(self):
        if self.rect.x < WIDTH - self.rect.width:
            self.rect.x += self.speed

    def move_up(self):
        if self.rect.y > 0:
            self.rect.y -= self.speed

    def move_down(self):
        if self.rect.y < HEIGHT - self.rect.height:
            self.rect.y += self.speed

    def attack(self):
        if self.attack_cooldown == 0:
            self.attacking = True
            self.attack_cooldown = 20
            # 创建子弹并添加到精灵组
            if self.image == PLAYER1_IMAGE:
                bullet = Bullet(self.rect.right, self.rect.centery, 1)
            else:
                bullet = Bullet(self.rect.left - self.rect.width, self.rect.centery, -1)
            self.bullets.add(bullet)

    def take_damage(self, damage):
        self.health -= damage
        if self.health < 0:
            self.health = 0

    def update(self):
        if self.attack_cooldown > 0:
            self.attack_cooldown -= 1
        if self.attack_cooldown == 0:
            self.attacking = False
        self.bullets.update()

# 创建角色实例
player1 = Player(100, 250, PLAYER1_IMAGE)
player2 = Player(600, 250, PLAYER2_IMAGE)

# 创建精灵组
all_sprites = pygame.sprite.Group()
all_sprites.add(player1, player2)

# 主游戏循环
clock = pygame.time.Clock()
running = True
while running:
    clock.tick(60)

    # 处理事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_a:
                player1.move_left()
            elif event.key == pygame.K_d:
                player1.move_right()
            elif event.key == pygame.K_w:
                player1.move_up()
            elif event.key == pygame.K_s:
                player1.move_down()
            elif event.key == pygame.K_SPACE:
                player1.attack()
            elif event.key == pygame.K_LEFT:
                player2.move_left()
            elif event.key == pygame.K_RIGHT:
                player2.move_right()
            elif event.key == pygame.K_UP:
                player2.move_up()
            elif event.key == pygame.K_DOWN:
                player2.move_down()
            elif event.key == pygame.K_RETURN:
                player2.attack()

    # 更新角色状态
    player1.update()
    player2.update()

    # 检测子弹与角色的碰撞
    for bullet in player1.bullets:
        if pygame.sprite.collide_rect(bullet, player2):
            player2.take_damage(10)
            bullet.kill()
    for bullet in player2.bullets:
        if pygame.sprite.collide_rect(bullet, player1):
            player1.take_damage(10)
            bullet.kill()

    # 绘制背景
    WIN.fill(WHITE)

    # 绘制血量条
    pygame.draw.rect(WIN, RED, (10, 10, 200, 20))
    pygame.draw.rect(WIN, GREEN, (10, 10, 2 * player1.health, 20))
    pygame.draw.rect(WIN, RED, (WIDTH - 210, 10, 200, 20))
    pygame.draw.rect(WIN, GREEN, (WIDTH - 210, 10, 2 * player2.health, 20))

    # 绘制血量数值
    player1_health_text = FONT.render(f"Player 1 Health: {player1.health}", 1, RED)
    player2_health_text = FONT.render(f"Player 2 Health: {player2.health}", 1, RED)
    WIN.blit(player1_health_text, (10, 40))
    WIN.blit(player2_health_text, (WIDTH - 210, 40))

    # 绘制角色和子弹
    all_sprites.draw(WIN)
    player1.bullets.draw(WIN)
    player2.bullets.draw(WIN)

    # 检查游戏结束
    if player1.health <= 0:
        winner_text = FONT.render("Player 2 Wins!", 1, RED)
        WIN.blit(winner_text, (WIDTH // 2 - winner_text.get_width() // 2, HEIGHT // 2 - winner_text.get_height() // 2))
        pygame.display.flip()
        pygame.time.delay(3000)
        running = False
    elif player2.health <= 0:
        winner_text = FONT.render("Player 1 Wins!", 1, RED)
        WIN.blit(winner_text, (WIDTH // 2 - winner_text.get_width() // 2, HEIGHT // 2 - winner_text.get_height() // 2))
        pygame.display.flip()
        pygame.time.delay(3000)
        running = False

    # 更新显示
    pygame.display.flip()

# 退出 Pygame
pygame.quit()

代码说明:
1、子弹类 Bullet:
继承自 pygame.sprite.Sprite,包含子弹的位置、速度和方向等属性。
update 方法用于更新子弹的位置,当子弹超出屏幕范围时,将其从精灵组中移除。
2、角色类 Player:
添加了 bullets 属性,用于管理该角色发射的子弹精灵组。
在 attack 方法中,当角色攻击时,创建子弹对象并添加到 bullets 精灵组中。
update 方法中调用 self.bullets.update() 来更新子弹的状态。
3、主循环部分:
增加了检测子弹与角色碰撞的逻辑,当子弹击中对方角色时,对方角色扣血,子弹消失。
在绘制部分,除了绘制角色,还绘制了角色发射的子弹。

使用方法:
1、将代码保存为一个 Python 文件(例如 battle_game_with_bullets.py)。
准备三张图片,分别命名为 player1.png、player2.png 和 bullet.png,并将它们放在与代码文件相同的目录下。
2、运行代码,即可开始游戏。玩家 1 使用 A、D、W、S 键移动(记得开启大写),Space 键攻击;玩家 2 使用方向键移动,Enter 键攻击。攻击时会发射子弹,子弹击中对方角色可造成伤害。

可以自由补充扩展


http://www.kler.cn/a/553650.html

相关文章:

  • 数组和指针常见笔试题(深度剖析)
  • Centos7 使用 yum 报错 Could not retrieve mirrorlist
  • 【Rust中级教程】1.10. 引用及内部可变性(简单回顾):引用、内部可变性、`Cell`类型及相关操作
  • less 和 sass 的异同(css 预处理语言)
  • 非docker安装open-webui连接ollama实现deepseek本地使用,集成其他openai模型,常见启动报错问题解决。
  • 人工智能丨卷积神经网络的概念, 它与普通的神经网络有何不同
  • HarmonyOS的核心特性:分布式技术引领创新
  • DeepSeek与ChatGPT:会取代搜索引擎和人工客服的人工智能革命
  • Zookeeper(54)如何使用Zookeeper的命令行工具?
  • Redis-03高级篇下-最佳实践:
  • Nginx下proxy_redirect的三种配置方式
  • scroll、offset、client三大家族和getBoundingClientRect方法
  • android 定制mtp连接外设的设备名称
  • 基于JavaSpringboot+Vue实现前后端分离房屋租赁系统
  • lua的local 变量和self 变量的理解理解后解决自己写的bug.
  • 【论文阅读】DeepSeek-R1: Incentivizing Reasoning Capability in LLMs via Reinforcement Learning
  • git-提交时间和作者时间的区别
  • 当使用vcpkg安装的qt5时,在VS调用出现libcrypto-*-x64.dll不是有效路径时
  • Docker如何切换文件目录安装——详细攻略!
  • IOS UITextField 无法隐藏键盘问题