[Python] 纯文本查看 复制代码
import pygame
import socket
import threading
import json
# ========= 请修改为运行服务端电脑的局域网IPv4地址 =========
SERVER_HOST = "192.168.1.100"
SERVER_PORT = 8899
# ==========================================================
# 窗口基础配置
WIDTH, HEIGHT = 800, 600
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("局域网多人联机植物大战僵尸")
clock = pygame.time.Clock()
# 本地缓存游戏数据
game_state = {
"sun": 150,
"plants": {},
"zombies": {},
"bullets": {}
}
selected_plant = None
# 植物卡片UI
plant_buttons = [
{"name": "sunflower", "rect": pygame.Rect(10, 10, 70, 70), "color": (255, 220, 0)},
{"name": "peashooter", "rect": pygame.Rect(90, 10, 70, 70), "color": (0, 180, 0)},
{"name": "wallnut", "rect": pygame.Rect(170, 10, 70, 70), "color": (120, 80, 40)}
]
cost_map = {"sunflower": 50, "peashooter": 100, "wallnut": 50}
# 连接服务器
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((SERVER_HOST, SERVER_PORT))
def recv_server_data():
"""持续接收服务器同步数据"""
global game_state
buf = b""
while True:
try:
data = sock.recv(4096)
if not data:
break
buf += data
while b"\n" in buf:
line, buf = buf.split(b"\n", 1)
msg = json.loads(line.decode())
if msg["type"] == "sync":
game_state = msg
except Exception:
break
print("❌ 与服务器断开连接")
pygame.quit()
# 启动接收后台线程
threading.Thread(target=recv_server_data, daemon=True).start()
# 绘图函数
def draw_grass():
"""绘制5行草坪区域"""
for row in range(5):
y = row * 120 + 80
pygame.draw.rect(screen, (35, 120, 30), (0, y, 800, 115))
pygame.draw.line(screen, (20, 80, 20), (0, y), (800, y), 2)
def draw_ui():
"""绘制顶部UI栏、阳光数值、植物卡片"""
pygame.draw.rect(screen, (20, 20, 20), (0, 0, 800, 90))
font = pygame.font.SysFont(None, 36)
sun_text = font.render(f"阳光: {game_state['sun']}", True, (255, 255, 0))
screen.blit(sun_text, (280, 25))
# 绘制植物按钮
for btn in plant_buttons:
pygame.draw.rect(screen, btn["color"], btn["rect"])
pygame.draw.rect(screen, (255, 255, 255), btn["rect"], 2)
cost_txt = font.render(str(cost_map[btn["name"]]), True, (0, 0, 0))
screen.blit(cost_txt, (btn["rect"].x + 20, btn["rect"].y + 25))
def draw_plants():
"""绘制所有场上植物"""
for p in game_state["plants"].values():
x, y = p["x"], p["y"]
if p["type"] == "sunflower":
pygame.draw.circle(screen, (255, 210, 0), (x, y), 22)
elif p["type"] == "peashooter":
pygame.draw.circle(screen, (0, 160, 0), (x, y), 22)
elif p["type"] == "wallnut":
pygame.draw.circle(screen, (110, 70, 30), (x, y), 26)
def draw_zombies():
"""绘制所有僵尸"""
for z in game_state["zombies"].values():
pygame.draw.rect(screen, (80, 80, 80), (z["x"] - 20, z["y"] - 25, 40, 50))
def draw_bullets():
"""绘制子弹"""
for b in game_state["bullets"].values():
pygame.draw.circle(screen, (220, 220, 0), (b["x"], b["y"]), 6)
# 游戏主渲染循环
running = True
while running:
dt = clock.tick(60) / 1000
mx, my = pygame.mouse.get_pos()
# 事件监听
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 鼠标点击操作
if event.type == pygame.MOUSEBUTTONDOWN:
# 选择植物卡片
for btn in plant_buttons:
if btn["rect"].collidepoint(mx, my):
selected_plant = btn["name"]
# 在草坪种下选中植物
if my > 90 and selected_plant is not None:
send_msg = json.dumps({
"type": "plant",
"plant_type": selected_plant,
"x": mx,
"y": my
}) + "\n"
sock.send(send_msg.encode("utf-8"))
# 渲染画面
screen.fill((0, 0, 0))
draw_grass()
draw_plants()
draw_zombies()
draw_bullets()
draw_ui()
pygame.display.flip()
# 退出释放资源
sock.close()
pygame.quit()