import pygame
import sys
import math
import random
from pygame.locals import *
# 初始化pygame
pygame.init()
# 屏幕设置
SCREEN_WIDTH = 1200
SCREEN_HEIGHT = 700
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("3v3fc 足球世界")
# 颜色定义
GREEN = (30, 180, 30)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (220, 20, 20)
BLUE = (30, 80, 200)
YELLOW = (255, 255, 0)
ORANGE = (255, 165, 0)
LIGHT_GREEN = (100, 230, 100)
LIGHT_BLUE = (100, 180, 255)
# 足球场尺寸
FIELD_RECT = pygame.Rect(50, 50, SCREEN_WIDTH - 100, SCREEN_HEIGHT - 100)
CENTER_X = SCREEN_WIDTH // 2
CENTER_Y = SCREEN_HEIGHT // 2
# 加载字体
font_large = pygame.font.SysFont('simhei', 48)
font_medium = pygame.font.SysFont('simhei', 32)
font_small = pygame.font.SysFont('simhei', 24)
class Player:
def __init__(self, x, y, team, number, is_user=False, position="forward"):
self.original_x = x
self.original_y = y
self.x = x
self.y = y
self.team = team
self.number = number
self.position = position
self.radius = 13
self.normal_speed = 4.0
self.speed = self.normal_speed
self.is_user = is_user
self.color = RED if team == "red" else BLUE
self.has_ball = False
self.sprint_cooldown = 0
self.sprint_duration = 0
self.is_sprinting = False
self.steal_cooldown = 0
self.pass_cooldown = 0
self.selected = is_user
self.role_radius = 120
self.home_x = x
self.home_y = y
self.target_x = x
self.target_y = y
self.last_target_update = 0
self.smooth_factor = 0.3
self.direction = (1, 0) if team == "red" else (-1, 0)
self.stamina = 100
self.aggression = random.uniform(0.6, 0.9)
self.defense = random.uniform(0.6, 0.9)
self.pass_accuracy = random.uniform(0.7, 0.95)
self.last_action_time = 0
self.move_lock = 0
def reset_position(self):
self.x = self.original_x
self.y = self.original_y
self.has_ball = False
self.is_sprinting = False
self.steal_cooldown = 0
self.pass_cooldown = 0
self.stamina = 100
self.direction = (1, 0) if self.team == "red" else (-1, 0)
self.move_lock = 0
def draw(self):
color = self.color
if self.is_sprinting:
color = YELLOW
elif self.has_ball:
color = WHITE
pygame.draw.circle(screen, color, (int(self.x), int(self.y)), self.radius)
pygame.draw.circle(screen, BLACK if not self.has_ball else RED if self.team=="red" else BLUE,
(int(self.x), int(self.y)), self.radius, 2)
# 绘制球员号码
number_text = font_small.render(str(self.number), True, WHITE if not self.has_ball else BLACK)
text_rect = number_text.get_rect(center=(self.x, self.y))
screen.blit(number_text, text_rect)
# 如果球员被选中,绘制选择圈
if self.selected:
pygame.draw.circle(screen, YELLOW, (int(self.x), int(self.y)), self.radius + 5, 2)
# 如果球员持球,绘制球在正前方
if self.has_ball:
# 根据移动方向计算球的位置
dx, dy = self.direction
if dx == 0 and dy == 0:
dx, dy = (1, 0) if self.team == "red" else (-1, 0)
# 归一化
length = math.sqrt(dx*dx + dy*dy)
if length > 0:
dx = dx / length
dy = dy / length
ball_x = self.x + dx * (self.radius + 10)
ball_y = self.y + dy * (self.radius + 10)
pygame.draw.circle(screen, WHITE, (int(ball_x), int(ball_y)), 10)
def sprint(self):
if self.has_ball and self.sprint_cooldown == 0 and self.stamina > 30:
self.speed = self.normal_speed * 1.8
self.sprint_duration = 30
self.sprint_cooldown = 90
self.is_sprinting = True
self.stamina -= 15
return True
return False
def steal(self):
if not self.has_ball and self.steal_cooldown == 0:
self.steal_cooldown = 30
return True
return False
def pass_ball(self, teammates, ball):
if self.has_ball and self.pass_cooldown == 0:
best_teammate = None
best_score = -9999
for player in teammates:
if player.team == self.team and player != self and not player.has_ball:
dist = math.sqrt((self.x - player.x)**2 + (self.y - player.y)**2)
if self.team == "red":
position_score = (player.x - CENTER_X) * 1.5
else:
position_score = (CENTER_X - player.x) * 1.5
angle_score = 0
if dist > 0:
dx = player.x - self.x
dy = player.y - self.y
obstructed = False
for opp in teammates:
if opp.team != self.team:
dist_to_line = abs((dy)*opp.x - (dx)*opp.y + self.x*player.y - player.x*self.y) / dist
if dist_to_line < 25 and math.sqrt((opp.x - self.x)**2 + (opp.y - self.y)**2) < dist:
obstructed = True
break
if not obstructed:
angle_score = 60
player_score = player.pass_accuracy * 30
score = position_score + angle_score + player_score + random.uniform(0, 20) - dist / 4
if score > best_score:
best_score = score
best_teammate = player
if best_teammate and random.random() < self.pass_accuracy:
predict_x = best_teammate.x + (best_teammate.x - self.x) * 0.3
predict_y = best_teammate.y + (best_teammate.y - self.y) * 0.3
ball.target_x = predict_x
ball.target_y = predict_y
ball.speed = 8
ball.is_moving = True
self.has_ball = False
self.pass_cooldown = 30
return best_teammate
return None
def update_status(self):
if not self.is_sprinting and self.stamina < 100:
self.stamina += 0.1
if self.sprint_duration > 0:
self.sprint_duration -= 1
if self.sprint_duration == 0:
self.speed = self.normal_speed
self.is_sprinting = False
if self.sprint_cooldown > 0:
self.sprint_cooldown -= 1
if self.steal_cooldown > 0:
self.steal_cooldown -= 1
if self.pass_cooldown > 0:
self.pass_cooldown -= 1
if self.last_target_update > 0:
self.last_target_update -= 1
if self.move_lock > 0:
self.move_lock -= 1
self.last_action_time += 1
def calculate_position(self, ball, teammates, opponents):
if self.last_target_update == 0:
if self.team == "red":
attack_direction = 1
defend_direction = -1
else:
attack_direction = -1
defend_direction = 1
ball_side = ball.x > CENTER_X if self.team == "red" else ball.x < CENTER_X
our_ball = any(p.has_ball and p.team == self.team for p in teammates)
if self.position == "forward":
if our_ball or ball_side:
self.target_x = self.home_x + attack_direction * 200
self.target_y = CENTER_Y + random.uniform(-30, 30)
else:
self.target_x = CENTER_X - attack_direction * 100
self.target_y = CENTER_Y
elif self.position == "midfielder":
if our_ball:
self.target_x = self.home_x + attack_direction * 100
self.target_y = ball.y
elif ball_side:
self.target_x = self.home_x + attack_direction * 50
self.target_y = CENTER_Y
else:
self.target_x = CENTER_X - attack_direction * 50
self.target_y = CENTER_Y
else:
if ball_side or not our_ball:
self.target_x = self.home_x
self.target_y = self.home_y
else:
self.target_x = self.home_x + attack_direction * 50
self.target_y = CENTER_Y
self.last_target_update = 30
self.target_x = max(FIELD_RECT.left + self.radius,
min(self.target_x, FIELD_RECT.right - self.radius))
self.target_y = max(FIELD_RECT.top + self.radius,
min(self.target_y, FIELD_RECT.bottom - self.radius))
def move_ai(self, ball, teammates, opponents, game):
# 如果是玩家控制且选中的球员,跳过AI移动
if self.selected and self.team == "red":
return 0, 0
self.calculate_position(ball, teammates, opponents)
# 如果持球,决定传球或带球
if self.has_ball:
if self.last_action_time > 30:
best_teammate = None
best_score = -9999
for player in teammates:
if player.team == self.team and player != self and not player.has_ball:
dist = math.sqrt((self.x - player.x)**2 + (self.y - player.y)**2)
if self.team == "red":
position_score = (player.x - CENTER_X) * 2.0
else:
position_score = (CENTER_X - player.x) * 2.0
if position_score > best_score and dist < 300:
best_score = position_score
best_teammate = player
if best_teammate and best_score > 50 and random.random() < 0.03:
return "pass"
if (self.team == "red" and self.x > FIELD_RECT.right - 250) or \
(self.team == "blue" and self.x < FIELD_RECT.left + 250):
if random.random() < 0.02:
return "shoot"
if random.random() < 0.01 and self.sprint_cooldown == 0 and self.stamina > 40:
self.sprint()
# 检查是否应该切换到该球员
if self.team == "red" and not self.selected:
if self.is_closest_to_ball(ball, teammates + opponents):
game.switch_to_player(self)
closest_to_ball = self.is_closest_to_ball(ball, teammates + opponents)
if closest_to_ball and not self.has_ball and self.move_lock == 0:
dx = ball.x - self.x
dy = ball.y - self.y
dist = math.sqrt(dx*dx + dy*dy)
if dist > 0:
self.direction = (dx/dist, dy/dist)
if dist < 80 and self.steal_cooldown == 0 and random.random() < 0.05:
self.steal()
else:
dx = self.target_x - self.x
dy = self.target_y - self.y
dist = math.sqrt(dx*dx + dy*dy)
if dist > 0:
self.direction = (dx/dist, dy/dist)
if dist > 0:
dx = dx * self.smooth_factor
dy = dy * self.smooth_factor
move_dist = math.sqrt(dx*dx + dy*dy)
if move_dist > self.speed:
dx = dx / move_dist * self.speed
dy = dy / move_dist * self.speed
return dx, dy
def is_closest_to_ball(self, ball, players):
min_dist = float('inf')
closest_player = None
for player in players:
if isinstance(player, Goalie):
continue
dist = math.sqrt((player.x - ball.x)**2 + (player.y - ball.y)**2)
if dist < min_dist:
min_dist = dist
closest_player = player
return closest_player == self if closest_player else False
def move(self, keys, ball, teammates, opponents, game):
dx, dy = 0, 0
# 玩家控制逻辑
if self.selected and self.team == "red":
if keys[K_LEFT]:
dx = -self.speed
if keys[K_RIGHT]:
dx = self.speed
if keys[K_UP]:
dy = -self.speed
if keys[K_DOWN]:
dy = self.speed
if dx != 0 or dy != 0:
self.direction = (dx, dy)
length = math.sqrt(dx*dx+dy*dy)
if length > 0:
self.direction = (dx/length, dy/length)
if keys[K_LSHIFT]:
self.sprint()
if keys[K_LCTRL]:
self.steal()
else:
ai_action = self.move_ai(ball, teammates, opponents, game)
if ai_action == "shoot" and self.has_ball:
return "shoot"
elif ai_action == "pass" and self.has_ball:
return "pass"
elif isinstance(ai_action, tuple):
dx, dy = ai_action
new_x = self.x + dx
new_y = self.y + dy
new_x = max(FIELD_RECT.left + self.radius,
min(new_x, FIELD_RECT.right - self.radius))
new_y = max(FIELD_RECT.top + self.radius,
min(new_y, FIELD_RECT.bottom - self.radius))
self.x = new_x
self.y = new_y
self.update_status()
for opponent in opponents:
if opponent != self:
dist = math.sqrt((self.x - opponent.x)**2 + (self.y - opponent.y)**2)
if dist < (self.radius + opponent.radius + 5):
self.handle_collision(opponent, ball)
def handle_collision(self, opponent, ball):
if opponent.has_ball:
steal_chance = 0.6 + (self.defense - opponent.aggression) * 0.2
if self.steal_cooldown == 0 and random.random() < steal_chance:
opponent.has_ball = False
self.has_ball = True
self.move_lock = 10
dx = self.x - opponent.x
dy = self.y - opponent.y
if dx == 0 and dy == 0:
dx = 1
length = math.sqrt(dx*dx+dy*dy)
self.direction = (dx/length, dy/length)
elif self.has_ball and opponent.steal_cooldown == 0:
steal_chance = 0.5 + (opponent.defense - self.aggression) * 0.2
if random.random() < steal_chance:
self.has_ball = False
opponent.has_ball = True
self.move_lock = 10
dx = opponent.x - self.x
dy = opponent.y - self.y
if dx == 0 and dy == 0:
dx = -1 if self.team=="red" else 1
length = math.sqrt(dx*dx+dy*dy)
opponent.direction = (dx/length, dy/length)
class Ball:
def __init__(self, x, y):
self.original_x = x
self.original_y = y
self.x = x
self.y = y
self.radius = 10
self.speed = 0
self.is_moving = False
self.target_x = x
self.target_y = y
self.trail = []
def reset_position(self):
self.x = self.original_x
self.y = self.original_y
self.is_moving = False
self.trail = []
def draw(self):
# 只在球移动时绘制轨迹
if self.is_moving:
for i, (trail_x, trail_y) in enumerate(self.trail):
pygame.draw.circle(screen, (200, 200, 200), (int(trail_x), int(trail_y)), 3)
# 只在球未被球员持有时绘制球
if not any(p.has_ball for p in game.players + game.goalies):
pygame.draw.circle(screen, WHITE, (int(self.x), int(self.y)), self.radius)
pygame.draw.circle(screen, BLACK, (int(self.x), int(self.y)), self.radius, 1)
def move(self):
if self.is_moving:
if len(self.trail) > 10:
self.trail.pop(0)
self.trail.append((self.x, self.y))
dx = self.target_x - self.x
dy = self.target_y - self.y
dist = math.sqrt(dx*dx + dy*dy)
if dist < self.speed:
self.x = self.target_x
self.y = self.target_y
self.is_moving = False
else:
dx = dx / dist * self.speed
dy = dy / dist * self.speed
self.x += dx
self.y += dy
def check_collision(self, players):
for player in players:
dx, dy = player.direction
if dx == 0 and dy == 0:
dx, dy = (1, 0) if player.team == "red" else (-1, 0)
length = math.sqrt(dx*dx + dy*dy)
if length > 0:
dx = dx / length
dy = dy / length
ball_x = player.x + dx * (player.radius + 10)
ball_y = player.y + dy * (player.radius + 10)
dist = math.sqrt((self.x - ball_x)**2 + (self.y - ball_y)**2)
if dist < (self.radius + 10) and self.is_moving:
if random.random() < 0.8:
self.is_moving = False
player.has_ball = True
return player
return None
class Goalie:
def __init__(self, x, y, team):
self.x = x
self.y = y
self.team = team
self.radius = 20
self.speed = 4
self.home_x = x
self.home_y = y
self.has_ball = False
self.pass_cooldown = 0
self.direction = (0, 0)
self.skill = random.uniform(0.7, 0.95)
self.number = 1 # 为守门员添加号码属性
def reset_position(self):
self.x = self.home_x
self.y = self.home_y
self.has_ball = False
self.pass_cooldown = 0
def draw(self):
color = RED if self.team == "red" else BLUE
if self.has_ball:
color = WHITE
pygame.draw.circle(screen, color, (int(self.x), int(self.y)), self.radius)
pygame.draw.circle(screen, WHITE if not self.has_ball else BLACK,
(int(self.x), int(self.y)), self.radius, 2)
# 绘制守门员号码
number_text = font_small.render(str(self.number), True, WHITE if not self.has_ball else BLACK)
text_rect = number_text.get_rect(center=(self.x, self.y))
screen.blit(number_text, text_rect)
if self.has_ball:
pygame.draw.circle(screen, WHITE, (int(self.x), int(self.y + 20)), 10)
def move(self, ball, teammates):
if self.pass_cooldown > 0:
self.pass_cooldown -= 1
if self.has_ball:
if self.pass_cooldown == 0:
closest_teammate = None
min_dist = float('inf')
for player in teammates:
if player.team == self.team and not isinstance(player, Goalie): # 只找普通球员
dist = math.sqrt((self.x - player.x)**2 + (self.y - player.y)**2)
if dist < min_dist:
min_dist = dist
closest_teammate = player
if closest_teammate:
ball.target_x = closest_teammate.x
ball.target_y = closest_teammate.y
ball.speed = 10
ball.is_moving = True
self.has_ball = False
self.pass_cooldown = 60
return
# 守门员移动逻辑 - 只在球进入危险区域时移动
if (self.team == "red" and ball.x > FIELD_RECT.left + 200) or \
(self.team == "blue" and ball.x < FIELD_RECT.right - 200):
if ball.is_moving:
if self.team == "red":
goal_x = FIELD_RECT.right
else:
goal_x = FIELD_RECT.left
dx = ball.x - self.x
dy = ball.y - self.y
if dx != 0:
slope = dy / dx
intercept_y = ball.y - slope * ball.x
predict_y = slope * goal_x + intercept_y
predict_y = max(self.home_y - 80, min(predict_y, self.home_y + 80))
skill_factor = 0.3 + self.skill * 0.7
self.y = predict_y * skill_factor + self.y * (1 - skill_factor)
else:
# 球静止时,向球移动
dy = ball.y - self.y
if abs(dy) > 5:
self.y += dy / abs(dy) * self.speed
else:
# 返回初始位置
if abs(self.y - self.home_y) > 5:
self.y += (self.home_y - self.y) / abs(self.home_y - self.y) * self.speed
class FootballGame:
def __init__(self):
self.reset_game()
def reset_positions(self):
for player in self.players:
player.reset_position()
for goalie in self.goalies:
goalie.reset_position()
self.ball.reset_position()
if self.score_red > self.score_blue:
player = random.choice([p for p in self.players if p.team == "red"])
player.has_ball = True
self.switch_to_player(player)
elif self.score_blue > self.score_red:
player = random.choice([p for p in self.players if p.team == "blue"])
player.has_ball = True
else:
if random.random() < 0.5:
player = random.choice([p for p in self.players if p.team == "red"])
player.has_ball = True
self.switch_to_player(player)
else:
player = random.choice([p for p in self.players if p.team == "blue"])
player.has_ball = True
def switch_to_player(self, player):
for i, p in enumerate(self.players):
if p == player:
self.selected_player = i
p.selected = True
p.is_user = (p.team == "red")
else:
p.selected = False
def switch_to_closest_to_ball(self, team="red"):
"""切换到离球最近的队友(忽略守门员)"""
min_dist = float('inf')
closest_player = None
for player in self.players:
if player.team == team and not isinstance(player, Goalie): # 忽略守门员
dist = math.sqrt((player.x - self.ball.x)**2 + (player.y - self.ball.y)**2)
if dist < min_dist:
min_dist = dist
closest_player = player
if closest_player:
self.switch_to_player(closest_player)
def reset_game(self):
# 创建球员
self.players = [
Player(CENTER_X - 150, CENTER_Y - 100, "red", 10, True, "forward"),
Player(CENTER_X - 250, CENTER_Y, "red", 8, False, "midfielder"),
Player(CENTER_X - 350, CENTER_Y, "red", 5, False, "defender"),
Player(CENTER_X + 150, CENTER_Y - 100, "blue", 9, False, "forward"),
Player(CENTER_X + 250, CENTER_Y, "blue", 7, False, "midfielder"),
Player(CENTER_X + 350, CENTER_Y, "blue", 3, False, "defender"),
]
# 创建守门员
self.goalies = [
Goalie(FIELD_RECT.left + 30, CENTER_Y, "red"),
Goalie(FIELD_RECT.right - 30, CENTER_Y, "blue")
]
# 创建球
self.ball = Ball(CENTER_X, CENTER_Y)
self.players[0].has_ball = True
# 创建球门
self.goals = [
pygame.Rect(FIELD_RECT.left, CENTER_Y - 100, 10, 200),
pygame.Rect(FIELD_RECT.right - 10, CENTER_Y - 100, 10, 200) # 修正球门位置
]
# 游戏状态
self.score_red = 0
self.score_blue = 0
self.game_time = 0
self.message = ""
self.message_timer = 0
self.waiting_reset = 0
self.selected_player = 0
self.player_switch_cooldown = 0
self.possession = {"red": 0, "blue": 0}
self.last_ball_holder_team = "red"
def switch_player(self):
if self.player_switch_cooldown > 0:
return
red_players = [i for i, p in enumerate(self.players) if p.team == "red" and not isinstance(p, Goalie)]
if not red_players:
return
current_index = red_players.index(self.selected_player)
next_index = (current_index + 1) % len(red_players)
self.selected_player = red_players[next_index]
for i, player in enumerate(self.players):
player.selected = (i == self.selected_player)
self.message = f"切换至{self.players[self.selected_player].number}号"
self.message_timer = 30
self.player_switch_cooldown = 20
def handle_events(self):
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_s and self.waiting_reset == 0:
player = self.players[self.selected_player]
if player.has_ball:
if player.team == "red":
target_x = FIELD_RECT.right
else:
target_x = FIELD_RECT.left
accuracy = player.aggression * 0.8 + 0.2
offset = random.uniform(-100, 100) * (1 - accuracy)
self.ball.is_moving = True
self.ball.target_x = target_x
self.ball.target_y = CENTER_Y + offset
self.ball.speed = 15
player.has_ball = False
self.message = "射门!"
self.message_timer = 60
if event.key == K_SPACE and self.waiting_reset == 0:
player = self.players[self.selected_player]
if player.has_ball:
teammates = [p for p in self.players if p.team == player.team and p != player]
receiver = player.pass_ball(teammates, self.ball)
if receiver:
self.message = f"传球给{receiver.number}号!"
self.message_timer = 30
if receiver.team == "red":
self.switch_to_player(receiver)
if event.key == K_TAB:
self.switch_player()
if event.key == K_r:
self.reset_game()
def update(self):
# 更新控球统计
for player in self.players:
if player.has_ball:
self.possession[player.team] += 1
if self.player_switch_cooldown > 0:
self.player_switch_cooldown -= 1
if self.waiting_reset > 0:
self.waiting_reset -= 1
if self.waiting_reset == 0:
self.reset_positions()
return
self.game_time += 1
keys = pygame.key.get_pressed()
# 更新球员
for player in self.players:
action = player.move(keys, self.ball,
[p for p in self.players if p.team == player.team and p != player],
[p for p in self.players if p.team != player.team], self)
# 处理AI动作
if not (player.selected and player.team == "red"):
if action == "shoot" and player.has_ball:
if player.team == "red":
target_x = FIELD_RECT.right
else:
target_x = FIELD_RECT.left
accuracy = player.aggression * 0.7 + 0.3
offset = random.uniform(-80, 80) * (1 - accuracy)
self.ball.is_moving = True
self.ball.target_x = target_x
self.ball.target_y = CENTER_Y + offset
self.ball.speed = 15
player.has_ball = False
self.message = "电脑射门!"
self.message_timer = 60
elif action == "pass" and player.has_ball:
teammates = [p for p in self.players if p.team == player.team and p != player]
receiver = player.pass_ball(teammates, self.ball)
if receiver:
self.message = f"电脑传球!"
self.message_timer = 30
# 更新守门员
for goalie in self.goalies:
goalie.move(self.ball, self.players)
# 更新足球
self.ball.move()
# 检查足球与球员的碰撞
ball_holder = self.ball.check_collision(self.players + self.goalies)
if ball_holder:
# 修复:守门员没有number属性会导致错误
if isinstance(ball_holder, Goalie):
self.message = "守门员接球!"
else:
self.message = f"{ball_holder.number}号接球!"
self.message_timer = 30
# 记录最后持球队伍
self.last_ball_holder_team = ball_holder.team
# 如果是普通球员且是玩家队伍,切换到该球员
if not isinstance(ball_holder, Goalie):
if ball_holder.team == "red" and not ball_holder.selected:
self.switch_to_player(ball_holder)
elif ball_holder.team == "blue":
# 如果球被对方球员接到,自动切换到离球最近的队友
self.switch_to_closest_to_ball("red")
# 检查与守门员的碰撞
for goalie in self.goalies:
if self.ball.is_moving:
dist = math.sqrt((self.ball.x - goalie.x)**2 + (self.ball.y - goalie.y)**2)
if dist < (self.ball.radius + goalie.radius):
if random.random() < goalie.skill:
# 扑救成功
self.ball.is_moving = False
goalie.has_ball = True
self.message = "守门员扑救成功!"
self.message_timer = 60
# 记录最后持球队伍
self.last_ball_holder_team = goalie.team
if goalie.team == "blue":
self.switch_to_closest_to_ball("red")
else:
# 扑救失误
self.message = "守门员扑救失误!"
self.message_timer = 60
# 检查是否进球 - 只在球移动时检查
if self.ball.is_moving:
for i, goal in enumerate(self.goals):
if goal.collidepoint(self.ball.x, self.ball.y):
self.ball.is_moving = False
if i == 0: # 蓝队得分
self.score_blue += 1
self.message = "蓝队得分!"
else: # 红队得分
self.score_red += 1
self.message = "红队得分!"
self.message_timer = 60
self.waiting_reset = 90
break
# 如果球没人控制且静止
if not self.ball.is_moving and not any(p.has_ball for p in self.players + self.goalies):
closest_player = None
min_dist = float('inf')
for player in self.players + self.goalies:
dist = math.sqrt((player.x - self.ball.x)**2 + (player.y - self.ball.y)**2)
if dist < min_dist:
min_dist = dist
closest_player = player
if closest_player:
closest_player.has_ball = True
# 修复:添加对守门员的判断
if isinstance(closest_player, Goalie):
self.message = "守门员拿到球!"
else:
self.message = f"{closest_player.number}号拿到球!"
self.message_timer = 30
if not isinstance(closest_player, Goalie): # 普通球员
if closest_player.team == "red" and not closest_player.selected:
self.switch_to_player(closest_player)
elif closest_player.team == "blue":
# 如果球被对方控制,自动切换到离球最近的队友
self.switch_to_closest_to_ball("red")
if self.message_timer > 0:
self.message_timer -= 1
def draw(self):
screen.fill(LIGHT_GREEN)
# 绘制球场
pygame.draw.rect(screen, GREEN, FIELD_RECT)
pygame.draw.rect(screen, WHITE, FIELD_RECT, 3)
pygame.draw.line(screen, WHITE, (CENTER_X, FIELD_RECT.top), (CENTER_X, FIELD_RECT.bottom), 2)
pygame.draw.circle(screen, WHITE, (CENTER_X, CENTER_Y), 80, 2)
pygame.draw.circle(screen, WHITE, (CENTER_X, CENTER_Y), 5)
# 绘制禁区
pygame.draw.rect(screen, WHITE, (FIELD_RECT.left, CENTER_Y - 120, 120, 240), 2)
pygame.draw.rect(screen, WHITE, (FIELD_RECT.right - 120, CENTER_Y - 120, 120, 240), 2)
# 绘制球门
pygame.draw.rect(screen, WHITE, (FIELD_RECT.left, CENTER_Y - 100, 10, 200), 2)
pygame.draw.rect(screen, WHITE, (FIELD_RECT.right - 10, CENTER_Y - 100, 10, 200), 2)
# 绘制球门区
pygame.draw.rect(screen, WHITE, (FIELD_RECT.left, CENTER_Y - 50, 40, 100), 2)
pygame.draw.rect(screen, WHITE, (FIELD_RECT.right - 40, CENTER_Y - 50, 40, 100), 2)
# 绘制球员
for player in self.players:
player.draw()
# 绘制守门员
for goalie in self.goalies:
goalie.draw()
# 绘制足球
self.ball.draw()
# 绘制比分
score_text = font_large.render(f"{self.score_red} - {self.score_blue}", True, WHITE)
screen.blit(score_text, (CENTER_X - score_text.get_width() // 2, 10))
# 绘制时间
minutes = self.game_time // 3600
seconds = (self.game_time // 60) % 60
time_text = font_medium.render(f"{minutes:02d}:{seconds:02d}", True, WHITE)
screen.blit(time_text, (CENTER_X - time_text.get_width() // 2, 70))
# 绘制队伍名称
red_text = font_medium.render("玩家", True, RED)
blue_text = font_medium.render("电脑", True, BLUE)
screen.blit(red_text, (FIELD_RECT.left + 20, 10))
screen.blit(blue_text, (FIELD_RECT.right - blue_text.get_width() - 20, 10))
# 绘制控球率
total_possession = self.possession["red"] + self.possession["blue"]
if total_possession > 0:
red_percent = int(self.possession["red"] / total_possession * 100)
blue_percent = 100 - red_percent
possession_text = font_small.render(f"控球率: {red_percent}% - {blue_percent}%", True, WHITE)
screen.blit(possession_text, (CENTER_X - possession_text.get_width() // 2, 110))
# 绘制消息
if self.message_timer > 0:
msg_surface = font_medium.render(self.message, True, YELLOW)
screen.blit(msg_surface, (CENTER_X - msg_surface.get_width() // 2, CENTER_Y - 100))
# 绘制控制说明
controls = [
"方向键: 移动球员",
"空格键: 传球",
"S键: 射门",
"Shift键: 暴趟(加速)",
"Ctrl键: 抢断",
"Tab键: 切换球员",
"R键: 重置游戏"
]
for i, text in enumerate(controls):
ctrl_text = font_small.render(text, True, LIGHT_BLUE)
screen.blit(ctrl_text, (SCREEN_WIDTH - ctrl_text.get_width() - 20, 20 + i * 30))
# 创建游戏实例
game = FootballGame()
clock = pygame.time.Clock()
# 游戏主循环
while True:
game.handle_events()
game.update()
game.draw()
pygame.display.flip()
clock.tick(60)