|
|
发表于 2026-8-2 11:43:07
|
显示全部楼层
import pygame
import socket
import pickle
import sys
# ===================== 这里一定要改!!=====================
SERVER_IP = "192.168.2.33"
# 本地同一台电脑测试填 "127.0.0.1"
PORT = 5555
# =========================================================
WIDTH, HEIGHT = 900, 600
FPS = 60
PLAYER_SIZE = 50
ATTACK_RANGE = 70
WHITE = (255, 255, 255)
RED = (220, 30, 30)
BLUE = (30, 80, 220)
GREEN = (40, 180, 40)
BLACK = (0, 0, 0)
# ========= 固定收发函数(解决粘包核心!不要删除)=========
def send_data(sock, obj):
data = pickle.dumps(obj)
sock.sendall(len(data).to_bytes(4, byteorder='big'))
sock.sendall(data)
def recv_data(sock):
length_raw = sock.recv(4)
if not length_raw:
return None
data_len = int.from_bytes(length_raw, byteorder='big')
buffer = b''
while len(buffer) < data_len:
packet = sock.recv(data_len - len(buffer))
if not packet:
return None
buffer += packet
return pickle.loads(buffer)
# ======================================================
class Network:
def __init__(self):
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.addr = (SERVER_IP, PORT)
self.player_id = None
def connect(self):
try:
self.client.connect(self.addr)
self.player_id = recv_data(self.client)
print(f"✅ 连接成功!你是玩家{self.player_id}")
return self.player_id
except Exception as e:
print("❌ 无法连接服务器!检查IP、防火墙、是否同局域网", e)
return None
def send(self, obj):
try:
send_data(self.client, obj)
return recv_data(self.client)
except Exception as e:
print("通信异常:", e)
return None
def close(self):
self.client.close()
def main():
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("联网双人近战对战【客户端】")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 48)
net = Network()
pid = net.connect()
if pid is None:
pygame.quit()
return
game_over = False
winner = -1
while True:
current_time = pygame.time.get_ticks()
keys = {"left":False, "right":False, "up":False, "down":False}
attack = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
net.close()
pygame.quit()
sys.exit()
pressed = pygame.key.get_pressed()
if pid == 0:
# 玩家0 蓝色:WASD + 空格攻击
keys["left"] = pressed[pygame.K_a]
keys["right"] = pressed[pygame.K_d]
keys["up"] = pressed[pygame.K_w]
keys["down"] = pressed[pygame.K_s]
attack = pressed[pygame.K_SPACE]
else:
# 玩家1 红色:方向键 + 小键盘0攻击
keys["left"] = pressed[pygame.K_LEFT]
keys["right"] = pressed[pygame.K_RIGHT]
keys["up"] = pressed[pygame.K_UP]
keys["down"] = pressed[pygame.K_DOWN]
attack = pressed[pygame.K_KP0]
receive_data = net.send((keys, attack, current_time))
if receive_data is None:
print("服务器断开连接")
break
p1, p2 = receive_data
# 胜负判定
if p1.hp <= 0 and not game_over:
game_over = True
winner = 1
elif p2.hp <= 0 and not game_over:
game_over = True
winner = 0
# 渲染
screen.fill((26,26,26))
pygame.draw.rect(screen, p1.color, pygame.Rect(p1.x, p1.y, PLAYER_SIZE, PLAYER_SIZE))
pygame.draw.rect(screen, p2.color, pygame.Rect(p2.x, p2.y, PLAYER_SIZE, PLAYER_SIZE))
# 攻击范围特效
if p1.is_attacking:
ar = pygame.Rect(p1.x - ATTACK_RANGE//2, p1.y, ATTACK_RANGE+PLAYER_SIZE, PLAYER_SIZE)
pygame.draw.rect(screen, (100,100,255), ar, 2)
if p2.is_attacking:
ar = pygame.Rect(p2.x - ATTACK_RANGE//2, p2.y, ATTACK_RANGE+PLAYER_SIZE, PLAYER_SIZE)
pygame.draw.rect(screen, (255,100,100), ar, 2)
# 血条
pygame.draw.rect(screen, BLACK, (p1.x, p1.y-12, PLAYER_SIZE, 8))
pygame.draw.rect(screen, GREEN, (p1.x, p1.y-12, PLAYER_SIZE*(p1.hp/100), 8))
pygame.draw.rect(screen, BLACK, (p2.x, p2.y-12, PLAYER_SIZE, 8))
pygame.draw.rect(screen, GREEN, (p2.x, p2.y-12, PLAYER_SIZE*(p2.hp/100), 8))
if game_over:
if winner == 0:
text = font.render("蓝色玩家胜利!", True, BLUE)
else:
text = font.render("红色玩家胜利!", True, RED)
screen.blit(text, (WIDTH//2 - 130, HEIGHT//2))
pygame.display.flip()
clock.tick(FPS)
if __name__ == "__main__":
main() |
|