pygame联网飞机大战游戏实现

客户端

python 复制代码
import pygame
import socket
import json
import threading


class GameClient:
    def __init__(self):
        pygame.init()
        self.screen_width = 600  # 宽度减小
        self.screen_height = 800  # 高度增加
        self.screen = pygame.display.set_mode((self.screen_width, self.screen_height))
        pygame.display.set_caption("竖版飞机大战")

        self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.server_address = ('localhost', 5555)

        self.player_id = None
        self.game_state = {
            'players': {},
            'bullets': [],
            'enemies': []
        }

        self.input_state = {
            'up': False,
            'down': False,
            'left': False,
            'right': False,
            'shoot': False
        }

        # 连接服务器
        self.connect_to_server()
        self.running = True
        # 启动接收线程
        threading.Thread(target=self.receive_data).start()

        # 游戏主循环
        self.clock = pygame.time.Clock()

        self.game_loop()

    def connect_to_server(self):
        join_message = {'type': 'join'}
        self.client_socket.sendto(json.dumps(join_message).encode(), self.server_address)

    def receive_data(self):
        while self.running:
            try:
                data, _ = self.client_socket.recvfrom(4096)
                message = json.loads(data.decode())

                if message['type'] == 'welcome':
                    self.player_id = message['id']
                elif message['type'] == 'update':
                    self.game_state = message
            except:
                pass

    def game_loop(self):
        while self.running:
            # 处理输入事件
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.running = False
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_UP:
                        self.input_state['up'] = True
                    elif event.key == pygame.K_DOWN:
                        self.input_state['down'] = True
                    elif event.key == pygame.K_LEFT:
                        self.input_state['left'] = True
                    elif event.key == pygame.K_RIGHT:
                        self.input_state['right'] = True
                    elif event.key == pygame.K_SPACE:
                        self.input_state['shoot'] = True
                elif event.type == pygame.KEYUP:
                    if event.key == pygame.K_UP:
                        self.input_state['up'] = False
                    elif event.key == pygame.K_DOWN:
                        self.input_state['down'] = False
                    elif event.key == pygame.K_LEFT:
                        self.input_state['left'] = False
                    elif event.key == pygame.K_RIGHT:
                        self.input_state['right'] = False
                    elif event.key == pygame.K_SPACE:
                        self.input_state['shoot'] = False

            # 发送输入状态到服务器
            if self.player_id is not None:
                input_message = {
                    'type': 'input',
                    'id': self.player_id,
                    **self.input_state
                }
                self.client_socket.sendto(json.dumps(input_message).encode(), self.server_address)

            # 渲染游戏
            self.render()

            self.clock.tick(60)

        pygame.quit()

    def render(self):
        self.screen.fill((0, 0, 0))

        # 绘制玩家
        for player_id, player in self.game_state['players'].items():
            color = (0, 255, 0) if int(player_id) == self.player_id else (0, 0, 255)
            pygame.draw.rect(self.screen, color, (player['x'], player['y'], player['width'], player['height']))

            # 显示生命值
            if 'health' in player:
                font = pygame.font.SysFont(None, 24)
                health_text = font.render(f"HP: {player['health']}", True, (255, 255, 255))
                self.screen.blit(health_text, (player['x'], player['y'] - 20))

            # 显示分数
            if 'score' in player:
                font = pygame.font.SysFont(None, 24)
                score_text = font.render(f"Score: {player['score']}", True, (255, 255, 255))
                self.screen.blit(score_text, (player['x'], player['y'] - 40))

        # 绘制子弹
        for bullet in self.game_state['bullets']:
            pygame.draw.rect(self.screen, (255, 255, 0), (bullet['x'], bullet['y'], bullet['width'], bullet['height']))

        # 绘制敌机
        for enemy in self.game_state['enemies']:
            pygame.draw.circle(self.screen, (255, 0, 0), (enemy['x'], enemy['y']), enemy['radius'])

        pygame.display.flip()


if __name__ == "__main__":
    client = GameClient()

服务器

python 复制代码
import socket
import threading
import json
import random
import time


class GameServer:
    def __init__(self):
        self.players = {}
        self.bullets = []
        self.enemies = []
        self.last_enemy_spawn = 0
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.server_socket.bind(('0.0.0.0', 5555))
        self.running = True

        # 游戏参数
        self.screen_width = 600  # 宽度可以小一些
        self.screen_height = 800  # 高度增加
        self.player_speed = 5
        self.bullet_speed = 7
        self.enemy_speed = 3

        # 启动接收线程
        threading.Thread(target=self.receive_data).start()
        threading.Thread(target=self.game_loop).start()

    def receive_data(self):
        while self.running:
            try:
                data, addr = self.server_socket.recvfrom(1024)
                message = json.loads(data.decode())

                if message['type'] == 'join':
                    player_id = len(self.players)
                    # 玩家初始位置改为底部
                    self.players[player_id] = {
                        'x': 200 if player_id == 0 else 400,
                        'y': self.screen_height - 100,
                        'width': 40,
                        'height': 40,
                        'addr': addr,
                        'last_shot': 0
                    }
                    response = {'type': 'welcome', 'id': player_id}
                    self.server_socket.sendto(json.dumps(response).encode(), addr)

                elif message['type'] == 'input':
                    player_id = message['id']
                    if player_id in self.players:
                        player = self.players[player_id]
                        if 'up' in message and message['up']:
                            player['y'] = max(0, player['y'] - self.player_speed)
                        if 'down' in message and message['down']:
                            player['y'] = min(self.screen_height - player['height'], player['y'] + self.player_speed)
                        if 'left' in message and message['left']:
                            player['x'] = max(0, player['x'] - self.player_speed)
                        if 'right' in message and message['right']:
                            player['x'] = min(self.screen_width - player['width'], player['x'] + self.player_speed)
                        if 'shoot' in message and message['shoot']:
                            current_time = time.time()
                            if current_time - player['last_shot'] > 0.2:  # 射击冷却
                                # 子弹改为向上发射
                                self.bullets.append({
                                    'x': player['x'] + player['width'] // 2 - 5,
                                    'y': player['y'],
                                    'width': 5,
                                    'height': 10,
                                    'speed': -self.bullet_speed,  # 负值表示向上
                                    'owner': player_id
                                })
                                player['last_shot'] = current_time
            except:
                pass

    def game_loop(self):
        while self.running:
            # 生成敌机(从顶部)
            current_time = time.time()
            if current_time - self.last_enemy_spawn > 2.0:  # 每2秒生成一个敌机
                self.enemies.append({
                    'x': random.randint(0, self.screen_width - 20),
                    'y': -20,  # 从屏幕外顶部生成
                    'radius': 10,
                    'speed': self.enemy_speed
                })
                self.last_enemy_spawn = current_time

            # 更新子弹位置
            for bullet in self.bullets[:]:
                bullet['y'] += bullet['speed']  # 速度可以是正或负
                if bullet['y'] < -10 or bullet['y'] > self.screen_height + 10:
                    self.bullets.remove(bullet)

            # 更新敌机位置(向下移动)
            for enemy in self.enemies[:]:
                enemy['y'] += enemy['speed']
                if enemy['y'] > self.screen_height + 20:
                    self.enemies.remove(enemy)

            # 碰撞检测
            self.check_collisions()

            # 广播游戏状态
            self.broadcast_state()

            time.sleep(0.016)  # 约60FPS

    def check_collisions(self):
        # 子弹与敌机碰撞
        for bullet in self.bullets[:]:
            for enemy in self.enemies[:]:
                if (bullet['x'] < enemy['x'] + enemy['radius'] and
                        bullet['x'] + bullet['width'] > enemy['x'] and
                        bullet['y'] < enemy['y'] + enemy['radius'] and
                        bullet['y'] + bullet['height'] > enemy['y']):

                    # 增加玩家分数
                    if bullet['owner'] in self.players:
                        if 'score' not in self.players[bullet['owner']]:
                            self.players[bullet['owner']]['score'] = 0
                        self.players[bullet['owner']]['score'] += 1

                    if bullet in self.bullets:
                        self.bullets.remove(bullet)
                    if enemy in self.enemies:
                        self.enemies.remove(enemy)
                    break

        # 玩家与敌机碰撞
        for player_id, player in self.players.items():
            for enemy in self.enemies[:]:
                if (player['x'] < enemy['x'] + enemy['radius'] and
                        player['x'] + player['width'] > enemy['x'] and
                        player['y'] < enemy['y'] + enemy['radius'] and
                        player['y'] + player['height'] > enemy['y']):

                    # 减少玩家生命值
                    if 'health' not in player:
                        player['health'] = 3
                    player['health'] -= 1

                    if enemy in self.enemies:
                        self.enemies.remove(enemy)

                    if player['health'] <= 0:
                        # 玩家死亡,重置位置
                        player['x'] = 200 if player_id == 0 else 400
                        player['y'] = self.screen_height - 100
                        player['health'] = 3

    def broadcast_state(self):
        game_state = {
            'type': 'update',
            'players': self.players,
            'bullets': self.bullets,
            'enemies': self.enemies
        }

        for player_id, player in self.players.items():
            try:
                self.server_socket.sendto(json.dumps(game_state).encode(), player['addr'])
            except:
                pass


if __name__ == "__main__":
    server = GameServer()
    input("Press Enter to stop the server...\n")
    server.running = False
相关推荐
www_pp_28 分钟前
# 创建一个功能完备的计算器应用:使用PyQt5和Python
开发语言·python·qt
攻城狮7号29 分钟前
大模型微调Fine-tuning:从概念到实践的全面解析
人工智能·python·前沿技术·fine-tuning·大模型微调
basketball6161 小时前
使用pytorch保存和加载预训练的模型方法
人工智能·pytorch·python
蓑笠翁0011 小时前
Python异步编程入门:从同步到异步的思维转变
linux·前端·python
程序员Bears1 小时前
Django进阶:用户认证、REST API与Celery异步任务全解析
后端·python·django
仰望星空的凡人2 小时前
【JS逆向基础】前端基础-HTML与CSS
css·python·html·js逆向
灏瀚星空2 小时前
PyTorch 入门与核心概念详解:从基础到实战问题解决
人工智能·pytorch·python·深度学习·算法·机器学习
Q_Q19632884752 小时前
python小说网站管理系统-小说阅读系统
开发语言·spring boot·python·django·flask·node.js·php
hie988942 小时前
如何配置 Java 安全管理器来避免访问控制异常
java·python·安全
wgc2k3 小时前
Java游戏服务器开发流水账(2)开发中Maven的管理
java·服务器·游戏