Untitled
unknown
plain_text
9 months ago
81 kB
24
Indexable
# New Star Football - Complete Career Mode Game
import pygame
import sys
import random
import json
import os
import math
from pygame import Vector2
pygame.init()
WIDTH, HEIGHT = 1200, 700
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
CLOCK = pygame.time.Clock()
pygame.display.set_caption("New Star Football")
# Fonts
FONT = pygame.font.SysFont("Arial", 22)
SMALL_FONT = pygame.font.SysFont("Arial", 18)
TINY_FONT = pygame.font.SysFont("Arial", 14)
BIG = pygame.font.SysFont("Arial", 48)
TITLE_FONT = pygame.font.SysFont("Arial", 72, bold=True)
MEDIUM_FONT = pygame.font.SysFont("Arial", 32, bold=True)
# Colors
WHITE = (245, 245, 245)
GREEN = (34, 139, 34)
DARK_GREEN = (20, 90, 20)
BLUE = (66, 135, 245)
RED = (220, 60, 60)
YELLOW = (240, 220, 60)
BLACK = (10, 10, 10)
GRAY = (128, 128, 128)
STAMINA_BG = (60, 60, 60)
STAMINA_FILL = (80, 220, 120)
MENU_BG = (25, 35, 50)
MENU_ACCENT = (45, 65, 90)
BUTTON_COLOR = (60, 90, 130)
BUTTON_HOVER = (80, 110, 150)
WIN_GREEN = (50, 180, 50)
LOSS_RED = (200, 50, 50)
GOLD = (255, 215, 0)
# Game settings
PLAYER_RADIUS = 18
BALL_RADIUS = 10
SPRINT_MULTIPLIER = 1.9
BALL_FRICTION = 0.995
PLAYER_FRICTION = 0.85
GOAL_WIDTH = 140
KICK_RADIUS = 80.0
MAX_CHARGE_TIME = 1.6
MIN_KICK_MULT = 0.35
MAX_KICK_MULT = 1.6
FOUL_COOLDOWN = 3.5
MATCH_TIME_DEFAULT = 90
CAREER_DATA_FILE = "career_data.json"
CLUBS = [
"Manchester Rovers", "Liverpool City", "Chelsea United", "Arsenal FC",
"Tottenham Athletic", "Newcastle Stars", "Everton Rangers", "Leicester Foxes",
"West Ham Warriors", "Brighton Seagulls", "Crystal Palace Eagles", "Southampton Saints"
]
FIRST_NAMES = ["James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph",
"Thomas", "Christopher", "Daniel", "Matthew", "Anthony", "Mark", "Donald",
"Steven", "Andrew", "Paul", "Joshua", "Kenneth", "Carlos", "Luis", "Diego",
"Fernando", "Pablo", "Marco", "Andrea", "Alessandro", "Francesco", "Giovanni"]
LAST_NAMES = ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis",
"Rodriguez", "Martinez", "Hernandez", "Lopez", "Gonzalez", "Wilson", "Anderson",
"Thomas", "Taylor", "Moore", "Jackson", "Martin", "Silva", "Santos", "Fernandez",
"Costa", "Rossi", "Russo", "Romano", "Colombo", "Ricci", "Marino"]
def generate_player_name():
return f"{random.choice(FIRST_NAMES)} {random.choice(LAST_NAMES)}"
def clamp(v, a, b):
return max(a, min(b, v))
class Particle:
def __init__(self, pos, vel, color, radius, lifetime):
self.pos = Vector2(pos)
self.vel = Vector2(vel)
self.color = color
self.radius = float(radius)
self.lifetime = float(lifetime)
self.age = 0.0
def update(self, dt):
self.pos += self.vel * dt * 60.0
self.age += dt
self.radius *= 0.985
def draw(self, surf):
if self.age < self.lifetime and self.radius > 0.5:
alpha = max(0, int(255 * (1 - self.age/self.lifetime)))
size = int(max(2, self.radius*2))
s = pygame.Surface((size, size), pygame.SRCALPHA)
pygame.draw.circle(s, (*self.color, alpha), (size//2, size//2), max(1, int(self.radius)))
surf.blit(s, (self.pos.x - size//2, self.pos.y - size//2))
particles = []
class Player:
def __init__(self, pos, color, controls=None, is_cpu=False, name="Player", stats=None):
self.pos = Vector2(pos)
self.vel = Vector2(0, 0)
self.color = color
self.controls = controls or {}
self.is_cpu = is_cpu
self.name = name
if stats:
self.base_speed = 3.0 + (stats["speed"] / 100.0) * 2.5
self.kick_force = 4.0 + (stats["shot_power"] / 100.0) * 5.0
self.max_stamina = 60.0 + (stats["stamina"] / 100.0) * 70.0
self.foul_strength = 6.0 + (stats["foul_strength"] / 100.0) * 6.0
else:
self.base_speed = 4.2
self.kick_force = 6.8
self.max_stamina = 100.0
self.foul_strength = 8.5
self.speed = self.base_speed
self.stamina = self.max_stamina
self.score = 0
self.last_touch = False
self._stun_timer = 0.0
self.STUN_DURATION = 0.5
self.sprint_depletion = 28.0
self.stamina_regen = 18.0
self.regen_delay = 0.6
self._sprint_cooldown_timer = 0.0
self.is_sprinting = False
self.is_charging = False
self.charge_time = 0.0
self.max_charge = MAX_CHARGE_TIME
self._foul_cooldown_timer = 0.0
def update(self, ball, keys, dt):
if self._stun_timer > 0:
self._stun_timer = max(0.0, self._stun_timer - dt)
if self._foul_cooldown_timer > 0:
self._foul_cooldown_timer = max(0.0, self._foul_cooldown_timer - dt)
want_sprint = False
if not self.is_cpu and self.controls:
if self.controls.get('sprint') and keys[self.controls['sprint']]:
want_sprint = True
if self.is_cpu:
dist_to_ball = (ball.pos - self.pos).length()
if dist_to_ball > 120 and self.stamina > 25:
want_sprint = True
if want_sprint and self.stamina > 6.0:
self.is_sprinting = True
self.speed = self.base_speed * SPRINT_MULTIPLIER
self.stamina -= self.sprint_depletion * dt
if self.stamina < 0.0: self.stamina = 0.0
self._sprint_cooldown_timer = 0.0
for _ in range(2):
offset = Vector2(random.uniform(-PLAYER_RADIUS/2, PLAYER_RADIUS/2),
random.uniform(-PLAYER_RADIUS/2, PLAYER_RADIUS/2))
vel = Vector2(random.uniform(-0.6, 0.6), random.uniform(-0.6, 0.6)) - self.vel*0.05
particles.append(Particle(self.pos + offset, vel, YELLOW, random.uniform(3.0, 5.5), 0.28))
else:
if self.is_sprinting:
self._sprint_cooldown_timer = 0.0
self.is_sprinting = False
self.speed = self.base_speed
self._sprint_cooldown_timer += dt
if self._sprint_cooldown_timer >= self.regen_delay:
self.stamina += self.stamina_regen * dt
if self.stamina > self.max_stamina:
self.stamina = self.max_stamina
if self.is_cpu:
self._ai_move(ball)
else:
self._player_move(keys)
if self.is_charging:
self.charge_time += dt
if self.charge_time > self.max_charge:
self.charge_time = self.max_charge
self.pos += self.vel
self.vel *= PLAYER_FRICTION
self._contain()
def _player_move(self, keys):
if self._stun_timer > 0.0:
return
acc = Vector2(0, 0)
c = self.controls
if c:
if keys[c.get('up')]: acc.y = -1
if keys[c.get('down')]: acc.y = 1
if keys[c.get('left')]: acc.x = -1
if keys[c.get('right')]: acc.x = 1
if acc.length_squared() > 0:
acc = acc.normalize() * self.speed
self.vel += acc * 0.25
if self.vel.length() > self.speed:
self.vel.scale_to_length(self.speed)
def _ai_move(self, ball):
if self._stun_timer > 0.0:
return
# Improved AI with ball prediction
ball_future = ball.pos + ball.vel * 0.5
target = ball_future
direction = (target - self.pos)
if direction.length() > 1:
desired = direction.normalize() * self.speed
steer_force = (desired - self.vel) * 0.22
self.vel += steer_force
self.vel += Vector2(random.uniform(-0.08, 0.08), random.uniform(-0.08, 0.08))
if self.vel.length() > self.speed:
self.vel.scale_to_length(self.speed)
def _contain(self):
margin = PLAYER_RADIUS + 2
self.pos.x = clamp(self.pos.x, margin, WIDTH - margin)
self.pos.y = clamp(self.pos.y, margin, HEIGHT - margin)
def draw(self, surf, ball):
rr_surf = pygame.Surface((int(KICK_RADIUS*2)+4, int(KICK_RADIUS*2)+4), pygame.SRCALPHA)
pygame.draw.circle(rr_surf, (255,255,255,36), (int(KICK_RADIUS)+2, int(KICK_RADIUS)+2), int(KICK_RADIUS))
surf.blit(rr_surf, (self.pos.x - KICK_RADIUS - 2, self.pos.y - KICK_RADIUS - 2))
pygame.draw.circle(surf, self.color, (int(self.pos.x), int(self.pos.y)), PLAYER_RADIUS)
pygame.draw.circle(surf, BLACK, (int(self.pos.x), int(self.pos.y)), PLAYER_RADIUS, 2)
bar_w = 46
bar_h = 6
bar_x = int(self.pos.x - bar_w/2)
bar_y = int(self.pos.y + PLAYER_RADIUS + 8)
pygame.draw.rect(surf, STAMINA_BG, (bar_x, bar_y, bar_w, bar_h), border_radius=3)
fill_w = int((self.stamina / self.max_stamina) * (bar_w - 4))
if fill_w < 0: fill_w = 0
pygame.draw.rect(surf, STAMINA_FILL, (bar_x + 2, bar_y + 2, fill_w, bar_h - 4), border_radius=2)
if self.is_sprinting:
pygame.draw.rect(surf, YELLOW, (bar_x - 1, bar_y - 1, bar_w + 2, bar_h + 2), 1, border_radius=4)
if self._stun_timer > 0:
overlay = pygame.Surface((PLAYER_RADIUS*2, PLAYER_RADIUS*2), pygame.SRCALPHA)
overlay.fill((150,150,150,120))
surf.blit(overlay, (self.pos.x - PLAYER_RADIUS, self.pos.y - PLAYER_RADIUS))
if self.name:
name_font = pygame.font.SysFont("Arial", 16, bold=True)
txt = name_font.render(self.name, True, WHITE)
surf.blit(txt, (self.pos.x - txt.get_width()/2, self.pos.y - PLAYER_RADIUS - 34))
if self.is_charging:
offset = ball.pos - self.pos
if offset.length() > 0:
dir = offset.normalize()
arrow_length = 20 + 80 * (self.charge_time / self.max_charge)
end_pos = self.pos + dir * arrow_length
pygame.draw.line(surf, YELLOW, (int(self.pos.x), int(self.pos.y)),
(int(end_pos.x), int(end_pos.y)), 4)
perp = Vector2(-dir.y, dir.x) * 6
pygame.draw.polygon(surf, YELLOW, [(end_pos.x, end_pos.y),
(end_pos.x - perp.x - dir.x*10, end_pos.y - perp.y - dir.y*10),
(end_pos.x + perp.x - dir.x*10, end_pos.y + perp.y - dir.y*10)])
if self._foul_cooldown_timer > 0:
cooldown_frac = clamp(self._foul_cooldown_timer / FOUL_COOLDOWN, 0.0, 1.0)
fx = int(self.pos.x + PLAYER_RADIUS + 8)
fy = int(self.pos.y - PLAYER_RADIUS)
pygame.draw.circle(surf, (150,150,150), (fx, fy), 8)
inner_h = int((1.0 - cooldown_frac) * 12)
pygame.draw.rect(surf, (220,220,220), (fx-6, fy+6-inner_h, 12, inner_h))
class Ball:
def __init__(self, pos):
self.pos = Vector2(pos)
self.vel = Vector2(0, 0)
def update(self):
self.pos += self.vel
self.vel *= BALL_FRICTION
if self.pos.x - BALL_RADIUS < 0:
self.pos.x = BALL_RADIUS
self.vel.x *= -0.6
if self.pos.x + BALL_RADIUS > WIDTH:
self.pos.x = WIDTH - BALL_RADIUS
self.vel.x *= -0.6
if self.pos.y - BALL_RADIUS < 0:
self.pos.y = BALL_RADIUS
self.vel.y *= -0.6
if self.pos.y + BALL_RADIUS > HEIGHT:
self.pos.y = HEIGHT - BALL_RADIUS
self.vel.y *= -0.6
def draw(self, surf):
pygame.draw.circle(surf, YELLOW, (int(self.pos.x), int(self.pos.y)), BALL_RADIUS)
pygame.draw.circle(surf, BLACK, (int(self.pos.x), int(self.pos.y)), BALL_RADIUS, 2)
def handle_collisions(players, ball):
for p in players:
offset = ball.pos - p.pos
dist = offset.length()
min_dist = BALL_RADIUS + PLAYER_RADIUS
if dist < min_dist and dist > 0:
n = offset.normalize()
overlap = min_dist - dist
ball.pos += n * overlap
relative = ball.vel - p.vel
impulse = (1.8) * (relative.dot(n))
ball.vel -= n * impulse
p.last_touch = True
for o in players:
if o is not p:
o.last_touch = False
for i in range(len(players)):
for j in range(i+1, len(players)):
a = players[i]; b = players[j]
offset = b.pos - a.pos
d = offset.length()
min_d = PLAYER_RADIUS*2
if d < min_d and d > 0:
n = offset.normalize()
overlap = (min_d - d) / 2
a.pos += -n * overlap
b.pos += n * overlap
va = a.vel.dot(n); vb = b.vel.dot(n)
a.vel += (vb - va) * n * 0.6
b.vel += (va - vb) * n * 0.6
def draw_field(surf):
surf.fill(GREEN)
pygame.draw.rect(surf, DARK_GREEN, (40, 20, WIDTH-80, HEIGHT-40), 12)
pygame.draw.line(surf, WHITE, (WIDTH//2, 26), (WIDTH//2, HEIGHT-14), 4)
pygame.draw.circle(surf, WHITE, (WIDTH//2, HEIGHT//2), 65, 3)
gx = 40; gy1 = (HEIGHT - GOAL_WIDTH)//2; gy2 = gy1 + GOAL_WIDTH
pygame.draw.rect(surf, WHITE, (gx-8, gy1, 8, GOAL_WIDTH))
pygame.draw.rect(surf, WHITE, (gx, gy1, 120, GOAL_WIDTH), 3)
gx2 = WIDTH-40
pygame.draw.rect(surf, WHITE, (gx2, gy1, 8, GOAL_WIDTH))
pygame.draw.rect(surf, WHITE, (gx2-120, gy1, 120, GOAL_WIDTH), 3)
def check_goal(ball, left_player, right_player):
gy1 = (HEIGHT - GOAL_WIDTH)//2; gy2 = gy1 + GOAL_WIDTH
goal = None
if ball.pos.x - BALL_RADIUS <= 40 and gy1 < ball.pos.y < gy2:
right_player.score += 1
goal = "RIGHT"
for _ in range(40):
vel = Vector2(random.uniform(-3,3), random.uniform(-3,3))
particles.append(Particle(Vector2(WIDTH/2 + random.uniform(-8,8), HEIGHT/2 + random.uniform(-8,8)),
vel, right_player.color, random.uniform(4.0, 7.0), 0.9))
kickoff(ball, left_player, right_player)
if ball.pos.x + BALL_RADIUS >= WIDTH-40 and gy1 < ball.pos.y < gy2:
left_player.score += 1
goal = "LEFT"
for _ in range(40):
vel = Vector2(random.uniform(-3,3), random.uniform(-3,3))
particles.append(Particle(Vector2(WIDTH/2 + random.uniform(-8,8), HEIGHT/2 + random.uniform(-8,8)),
vel, left_player.color, random.uniform(4.0, 7.0), 0.9))
kickoff(ball, left_player, right_player)
return goal
def kickoff(ball, left_player, right_player):
ball.pos = Vector2(WIDTH/2, HEIGHT/2)
ball.vel = Vector2(0, 0)
left_player.pos = Vector2(160, HEIGHT/2)
right_player.pos = Vector2(WIDTH-160, HEIGHT/2)
left_player.vel = Vector2(0, 0)
right_player.vel = Vector2(0, 0)
left_player.is_sprinting = False
right_player.is_sprinting = False
left_player.stamina = left_player.max_stamina
right_player.stamina = right_player.max_stamina
left_player._sprint_cooldown_timer = 0.0
right_player._sprint_cooldown_timer = 0.0
left_player.is_charging = False; left_player.charge_time = 0.0
right_player.is_charging = False; right_player.charge_time = 0.0
def draw_game_ui(surf, left, right, time_left):
top_bar_height = 70
bar_surf = pygame.Surface((WIDTH, top_bar_height), pygame.SRCALPHA)
bar_surf.fill((20, 30, 45, 220))
surf.blit(bar_surf, (0, 0))
score_font = pygame.font.SysFont("Arial", 42, bold=True)
score_text = score_font.render(f"{left.score} — {right.score}", True, WHITE)
surf.blit(score_text, (WIDTH//2 - score_text.get_width()//2, 15))
time_font = pygame.font.SysFont("Arial", 28, bold=True)
time_mins = int(time_left) // 60
time_secs = int(time_left) % 60
time_text = time_font.render(f"{time_mins:02d}:{time_secs:02d}", True, YELLOW)
pygame.draw.circle(surf, (40, 50, 70), (50, 35), 28)
surf.blit(time_text, (50 - time_text.get_width()//2, 35 - time_text.get_height()//2))
name_font = pygame.font.SysFont("Arial", 20, bold=True)
left_name = name_font.render(left.name, True, left.color)
right_name = name_font.render(right.name, True, right.color)
surf.blit(left_name, (120, 25))
surf.blit(right_name, (WIDTH - 120 - right_name.get_width(), 25))
control_font = pygame.font.SysFont("Arial", 16)
controls_text = "WASD + SPACE (kick) + LSHIFT (sprint) + C (foul) | R: Reset | ESC: Menu"
ctrl_surf = control_font.render(controls_text, True, WHITE)
ctrl_bg = pygame.Surface((ctrl_surf.get_width() + 20, 30), pygame.SRCALPHA)
ctrl_bg.fill((20, 30, 45, 180))
surf.blit(ctrl_bg, (WIDTH//2 - ctrl_surf.get_width()//2 - 10, HEIGHT - 35))
surf.blit(ctrl_surf, (WIDTH//2 - ctrl_surf.get_width()//2, HEIGHT - 30))
def perform_kick(shooter, ball, charge_time):
frac = clamp(charge_time / MAX_CHARGE_TIME, 0.0, 1.0)
mult = MIN_KICK_MULT + frac * (MAX_KICK_MULT - MIN_KICK_MULT)
offset = ball.pos - shooter.pos
dist = offset.length()
if dist > KICK_RADIUS:
return False
if dist > 0:
closest = shooter.pos + offset.normalize() * PLAYER_RADIUS
else:
closest = shooter.pos.copy()
kick_dir = (ball.pos - closest)
if kick_dir.length() > 0:
kick_dir = kick_dir.normalize()
else:
kick_dir = Vector2(random.uniform(-1,1), random.uniform(-1,1)).normalize()
ball.vel += kick_dir * (shooter.kick_force * mult)
for _ in range(12):
vel = kick_dir * random.uniform(0.8, 3.0) + Vector2(random.uniform(-2,2), random.uniform(-2,2))
particles.append(Particle(ball.pos.copy(), vel, YELLOW, random.uniform(2.2,4.0), 0.35))
shooter.last_touch = True
return True
def perform_foul(actor, other, ball):
if actor._foul_cooldown_timer > 0.0:
return False
if (other.pos - actor.pos).length() > KICK_RADIUS:
return False
dir = other.pos - ball.pos
if dir.length() == 0:
dir = Vector2(random.uniform(-1,1), random.uniform(-1,1))
dir = dir.normalize()
other.vel += dir * actor.foul_strength
other._stun_timer = other.STUN_DURATION
for _ in range(8):
particles.append(Particle(other.pos.copy(), dir.rotate(random.uniform(-40,40)) * random.uniform(1.2,3.0),
(200,200,200), random.uniform(2.5,4.5), 0.35))
actor._foul_cooldown_timer = FOUL_COOLDOWN
return True
def draw_button(surf, rect, text, font, hovered=False):
color = BUTTON_HOVER if hovered else BUTTON_COLOR
pygame.draw.rect(surf, color, rect, border_radius=12)
pygame.draw.rect(surf, WHITE, rect, 3, border_radius=12)
txt_surf = font.render(text, True, WHITE)
surf.blit(txt_surf, (rect.centerx - txt_surf.get_width()//2, rect.centery - txt_surf.get_height()//2))
def load_career_data():
if os.path.exists(CAREER_DATA_FILE):
try:
with open(CAREER_DATA_FILE, 'r') as f:
data = json.load(f)
if "stats" not in data:
data["stats"] = {"speed": 25, "shot_power": 25, "stamina": 25, "foul_strength": 25}
if "training_points" not in data:
data["training_points"] = 3
if "money" not in data:
data["money"] = 100
if "season" not in data:
data["season"] = 1
if "club" not in data:
data["club"] = random.choice(CLUBS)
if "league_position" not in data:
data["league_position"] = 6
if "matches" not in data:
data["matches"] = []
return data
except:
pass
return None
def save_career_data(data):
with open(CAREER_DATA_FILE, 'w') as f:
json.dump(data, f, indent=2)
def character_creation():
title_font = pygame.font.SysFont("Arial", 48, bold=True)
button_font = pygame.font.SysFont("Arial", 24, bold=True)
player_name = ""
stats = {"speed": 25, "shot_power": 25, "stamina": 25, "foul_strength": 25}
points_remaining = 1
blink = 0.0
name_input_active = True
start_button = pygame.Rect(WIDTH//2 - 150, HEIGHT - 100, 300, 60)
stat_buttons = {}
y_start = 280
for i, stat in enumerate(["speed", "shot_power", "stamina", "foul_strength"]):
y = y_start + i * 80
stat_buttons[stat] = {
"minus": pygame.Rect(WIDTH//2 - 80, y, 40, 40),
"plus": pygame.Rect(WIDTH//2 + 40, y, 40, 40),
"label_y": y
}
while True:
dt = CLOCK.tick(60) / 1000.0
blink += dt
mx, my = pygame.mouse.get_pos()
start_hover = start_button.collidepoint(mx, my)
SCREEN.fill(MENU_BG)
title = title_font.render("CREATE YOUR PLAYER", True, GOLD)
SCREEN.blit(title, (WIDTH//2 - title.get_width()//2, 40))
name_label = FONT.render("Player Name:", True, WHITE)
SCREEN.blit(name_label, (WIDTH//2 - 200, 130))
name_rect = pygame.Rect(WIDTH//2 - 200, 160, 400, 50)
pygame.draw.rect(SCREEN, MENU_ACCENT, name_rect, border_radius=8)
pygame.draw.rect(SCREEN, WHITE, name_rect, 2, border_radius=8)
name_surf = FONT.render(player_name if player_name else "Enter name...", True, WHITE if player_name else GRAY)
SCREEN.blit(name_surf, (name_rect.x + 10, name_rect.y + 12))
if name_input_active and (blink % 1.0) < 0.5:
cursor_x = name_rect.x + 10 + name_surf.get_width() + 2
pygame.draw.rect(SCREEN, WHITE, (cursor_x, name_rect.y + 14, 3, 22))
points_text = MEDIUM_FONT.render(f"Points: {points_remaining}", True, GOLD)
SCREEN.blit(points_text, (WIDTH//2 - points_text.get_width()//2, 230))
for stat_name, btns in stat_buttons.items():
y = btns["label_y"]
stat_display = stat_name.replace("_", " ").title()
label = FONT.render(f"{stat_display}:", True, WHITE)
SCREEN.blit(label, (WIDTH//2 - 300, y + 8))
value_text = button_font.render(str(stats[stat_name]), True, WHITE)
SCREEN.blit(value_text, (WIDTH//2 - 20, y + 5))
minus_hover = btns["minus"].collidepoint(mx, my)
plus_hover = btns["plus"].collidepoint(mx, my)
draw_button(SCREEN, btns["minus"], "-", button_font, minus_hover)
draw_button(SCREEN, btns["plus"], "+", button_font, plus_hover)
if player_name and points_remaining == 0:
draw_button(SCREEN, start_button, "START CAREER", button_font, start_hover)
else:
pygame.draw.rect(SCREEN, GRAY, start_button, border_radius=12)
txt = button_font.render("START CAREER", True, WHITE)
SCREEN.blit(txt, (start_button.centerx - txt.get_width()//2, start_button.centery - txt.get_height()//2))
hint_text = SMALL_FONT.render("Allocate all 100 points to start your career!", True, YELLOW)
SCREEN.blit(hint_text, (WIDTH//2 - hint_text.get_width()//2, HEIGHT - 150))
pygame.display.flip()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.KEYDOWN:
if name_input_active:
if ev.key == pygame.K_BACKSPACE:
player_name = player_name[:-1]
elif ev.key == pygame.K_RETURN:
name_input_active = False
elif ev.unicode and ord(ev.unicode) >= 32 and len(player_name) < 20:
player_name += ev.unicode
if ev.type == pygame.MOUSEBUTTONDOWN:
if name_rect.collidepoint(mx, my):
name_input_active = True
else:
name_input_active = False
for stat_name, btns in stat_buttons.items():
if btns["minus"].collidepoint(mx, my) and stats[stat_name] > 0:
stats[stat_name] -= 1
points_remaining += 1
if btns["plus"].collidepoint(mx, my) and points_remaining > 0:
stats[stat_name] += 1
points_remaining -= 1
if start_hover and player_name and points_remaining == 0:
career_data = {
"player_name": player_name,
"stats": stats,
"training_points": 3,
"money": 100,
"season": 1,
"club": random.choice(CLUBS),
"league_position": 8,
"matches": []
}
save_career_data(career_data)
return career_data
def penalty_shootout(left, right):
def draw_scene(ball_pos, goalie_pos, left_marks, right_marks, prompt=None, big_msg=None, shooter_side=None):
SCREEN.fill(GREEN)
goal_w = 420
goal_h = 140
goal_x = WIDTH//2 - goal_w//2
goal_y = 90
post_thick = 8
pygame.draw.rect(SCREEN, WHITE, (goal_x, goal_y, post_thick, goal_h))
pygame.draw.rect(SCREEN, WHITE, (goal_x + goal_w - post_thick, goal_y, post_thick, goal_h))
pygame.draw.rect(SCREEN, WHITE, (goal_x, goal_y, goal_w, post_thick))
net_cols = 12
net_rows = 6
for i in range(1, net_cols):
nx = goal_x + int(i * goal_w / net_cols)
pygame.draw.line(SCREEN, (230,230,230), (nx, goal_y+post_thick), (nx, goal_y+goal_h), 1)
for r in range(1, net_rows):
ry = goal_y + post_thick + int(r * (goal_h - post_thick) / net_rows)
pygame.draw.line(SCREEN, (230,230,230), (goal_x, ry), (goal_x + goal_w, ry), 1)
spot_x = WIDTH//2
spot_y = HEIGHT - 120
pygame.draw.circle(SCREEN, WHITE, (spot_x, spot_y), 6)
pygame.draw.circle(SCREEN, WHITE, (spot_x, spot_y), 90, 1)
shooter_y = spot_y + 30
pygame.draw.circle(SCREEN, left.color if shooter_side == "left" else right.color, (spot_x, shooter_y), PLAYER_RADIUS)
if ball_pos:
pygame.draw.circle(SCREEN, YELLOW, (int(ball_pos[0]), int(ball_pos[1])), BALL_RADIUS)
pygame.draw.circle(SCREEN, BLACK, (int(ball_pos[0]), int(ball_pos[1])), BALL_RADIUS, 2)
if goalie_pos:
gx, gy = int(goalie_pos[0]), int(goalie_pos[1])
gw, gh = 36, 40
goalie_rect = pygame.Rect(gx - gw//2, gy - gh//2, gw, gh)
pygame.draw.rect(SCREEN, right.color if shooter_side == "left" else left.color, goalie_rect)
pygame.draw.rect(SCREEN, BLACK, goalie_rect, 2)
title = TITLE_FONT.render("PENALTY SHOOTOUT", True, YELLOW)
SCREEN.blit(title, (WIDTH//2 - title.get_width()//2, 10))
left_label = FONT.render(left.name, True, left.color)
right_label = FONT.render(right.name, True, right.color)
SCREEN.blit(left_label, (WIDTH//2 - 320, 60))
SCREEN.blit(right_label, (WIDTH//2 + 140, 60))
for i in range(5):
lx = WIDTH//2 - 270 + i*40
rx = WIDTH//2 + 200 + i*40
ly = 100
if i < len(left_marks):
col = WIN_GREEN if left_marks[i] else LOSS_RED
else:
col = (120,120,120)
if i < len(right_marks):
rcol = WIN_GREEN if right_marks[i] else LOSS_RED
else:
rcol = (120,120,120)
pygame.draw.circle(SCREEN, col, (lx, ly), 12)
pygame.draw.circle(SCREEN, BLACK, (lx, ly), 12, 2)
pygame.draw.circle(SCREEN, rcol, (rx, ly), 12)
pygame.draw.circle(SCREEN, BLACK, (rx, ly), 12, 2)
if prompt:
p_surf = SMALL_FONT.render(prompt, True, WHITE)
SCREEN.blit(p_surf, (WIDTH//2 - p_surf.get_width()//2, HEIGHT - 70))
if big_msg:
bm = BIG.render(big_msg, True, YELLOW)
SCREEN.blit(bm, (WIDTH//2 - bm.get_width()//2, HEIGHT//2 - 20))
pygame.display.flip()
def goal_target_coords(direction):
goal_w = 420
goal_x = WIDTH//2 - goal_w//2
goal_y = 90
goal_h = 140
if direction == "left":
tx = goal_x + int(goal_w * 0.22)
elif direction == "right":
tx = goal_x + int(goal_w * 0.78)
else:
tx = WIDTH//2
ty = goal_y + goal_h - 18
return (tx, ty)
def animate_shot_and_dive(shooter_side, shooter_direction, goalie_direction):
start_x = WIDTH//2
start_y = HEIGHT - 120
target_x, target_y = goal_target_coords(shooter_direction)
goalie_start_x = WIDTH//2
goalie_start_y = 135
g_tx, g_ty = goal_target_coords(goalie_direction)
g_target_x = g_tx
steps = 36
arc_h = 70
for step in range(steps):
t = (step + 1) / steps
bx = start_x + (target_x - start_x) * t
by = start_y + (target_y - start_y) * t - arc_h * math.sin(math.pi * t)
gx = goalie_start_x + (g_target_x - goalie_start_x) * min(1.0, t * 1.5)
gy = goalie_start_y + (30 * min(1.0, t * 1.3))
draw_scene((bx, by), (gx, gy), left_marks, right_marks, shooter_side=shooter_side)
CLOCK.tick(60)
if shooter_direction == goalie_direction:
saved = random.random() < 0.92
else:
saved = random.random() < 0.06
return not saved
left_marks = []
right_marks = []
while True:
shooter_is_left = (len(left_marks) == len(right_marks))
shooter = left if shooter_is_left else right
goalie = right if shooter_is_left else left
shooter_side = "left" if shooter_is_left else "right"
prompt = f"{shooter.name} to shoot — choose direction (LEFT/UP/RIGHT keys), then press KICK."
shooter_choice = None
confirmed = False
elapsed = 0.0
while not confirmed:
dt = CLOCK.tick(60) / 1000.0
elapsed += dt
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.KEYDOWN:
if shooter.controls:
if ev.key == shooter.controls.get('left'):
shooter_choice = "left"
elif ev.key == shooter.controls.get('right'):
shooter_choice = "right"
elif ev.key == shooter.controls.get('up'):
shooter_choice = "center"
elif ev.key == shooter.controls.get('kick'):
if shooter_choice is None:
shooter_choice = "center"
confirmed = True
if ev.key == pygame.K_ESCAPE:
return left.name
if shooter.is_cpu:
if shooter_choice is None and elapsed > 0.35:
shooter_choice = random.choice(["left", "center", "right"])
if elapsed > random.uniform(0.6, 1.0):
if shooter_choice is None:
shooter_choice = random.choice(["left", "center", "right"])
confirmed = True
if (not shooter.is_cpu) and elapsed > 4.0:
if shooter_choice is None:
shooter_choice = "center"
confirmed = True
draw_scene((WIDTH//2, HEIGHT - 120), (WIDTH//2, 135), left_marks, right_marks, prompt, shooter_side=shooter_side)
pygame.time.wait(180)
goalie_choice = None
g_elapsed = 0.0
while goalie_choice is None:
dt = CLOCK.tick(60) / 1000.0
g_elapsed += dt
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.KEYDOWN:
if goalie.controls:
if ev.key == goalie.controls.get('left'):
goalie_choice = "left"
elif ev.key == goalie.controls.get('right'):
goalie_choice = "right"
elif ev.key == goalie.controls.get('up'):
goalie_choice = "center"
if ev.key == pygame.K_ESCAPE:
return left.name
if goalie.is_cpu and g_elapsed > random.uniform(0.3, 0.9):
goalie_choice = random.choice(["left", "center", "right"])
if (not goalie.is_cpu) and g_elapsed > 3.5:
if goalie_choice is None:
goalie_choice = "center"
break
draw_scene((WIDTH//2, HEIGHT - 120), (WIDTH//2, 135), left_marks, right_marks,
f"{goalie.name} (goalie) — pick a dive!", shooter_side=shooter_side)
scored = animate_shot_and_dive(shooter_side, shooter_choice, goalie_choice)
if shooter_is_left:
left_marks.append(bool(scored))
else:
right_marks.append(bool(scored))
draw_scene(None, None, left_marks, right_marks, None,
big_msg="GOAL!" if scored else "SAVED!", shooter_side=shooter_side)
pygame.time.wait(900)
left_score = sum(1 for v in left_marks if v)
right_score = sum(1 for v in right_marks if v)
left_taken = len(left_marks)
right_taken = len(right_marks)
remaining_left = max(0, 5 - left_taken)
remaining_right = max(0, 5 - right_taken)
if left_score > right_score + remaining_right:
return left.name
if right_score > left_score + remaining_left:
return right.name
if left_taken >= 5 and right_taken >= 5 and left_taken == right_taken:
if left_score != right_score:
return left.name if left_score > right_score else right.name
if left_taken > 5 and right_taken > 5 and left_taken == right_taken:
if left_score != right_score:
return left.name if left_score > right_score else right.name
def training_speed(career_data):
"""Sprint through cones mini-game"""
if career_data["training_points"] < 1:
return
career_data["training_points"] -= 1
save_career_data(career_data)
player_pos = Vector2(100, HEIGHT//2)
player_vel = Vector2(0, 0)
speed = 6.0
cones = []
for i in range(8):
x = 200 + i * 130
y = HEIGHT//2 + random.randint(-80, 80)
cones.append({"pos": Vector2(x, y), "collected": False})
finish_line_x = 1150
timer = 0.0
completed = False
while not completed:
dt = CLOCK.tick(60) / 1000.0
timer += dt
keys = pygame.key.get_pressed()
acc = Vector2(0, 0)
if keys[pygame.K_w]: acc.y = -1
if keys[pygame.K_s]: acc.y = 1
if keys[pygame.K_a]: acc.x = -1
if keys[pygame.K_d]: acc.x = 1
if acc.length_squared() > 0:
acc = acc.normalize() * speed
player_vel += acc * 0.3
if player_vel.length() > speed:
player_vel.scale_to_length(speed)
player_vel *= 0.88
player_pos += player_vel
player_pos.y = clamp(player_pos.y, 30, HEIGHT - 30)
for cone in cones:
if not cone["collected"] and (cone["pos"] - player_pos).length() < 30:
cone["collected"] = True
if player_pos.x >= finish_line_x:
completed = True
SCREEN.fill(GREEN)
pygame.draw.line(SCREEN, WHITE, (finish_line_x, 0), (finish_line_x, HEIGHT), 4)
for cone in cones:
color = GRAY if cone["collected"] else YELLOW
pygame.draw.circle(SCREEN, color, (int(cone["pos"].x), int(cone["pos"].y)), 15)
pygame.draw.circle(SCREEN, BLUE, (int(player_pos.x), int(player_pos.y)), PLAYER_RADIUS)
title_surf = MEDIUM_FONT.render("SPEED TRAINING - Sprint through cones!", True, WHITE)
SCREEN.blit(title_surf, (WIDTH//2 - title_surf.get_width()//2, 20))
timer_surf = FONT.render(f"Time: {timer:.1f}s", True, WHITE)
SCREEN.blit(timer_surf, (20, 20))
cones_collected = sum(1 for c in cones if c["collected"])
cones_surf = FONT.render(f"Cones: {cones_collected}/8", True, WHITE)
SCREEN.blit(cones_surf, (20, 50))
pygame.display.flip()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.KEYDOWN:
if ev.key == pygame.K_ESCAPE:
return
cones_collected = sum(1 for c in cones if c["collected"])
bonus = max(0, 20 - int(timer))
points_gained = cones_collected + bonus
career_data["stats"]["speed"] = min(100, career_data["stats"]["speed"] + points_gained // 3)
save_career_data(career_data)
SCREEN.fill(MENU_BG)
result_surf = BIG.render(f"Speed +{points_gained // 3}!", True, GOLD)
SCREEN.blit(result_surf, (WIDTH//2 - result_surf.get_width()//2, HEIGHT//2 - 50))
detail_surf = FONT.render(f"Time: {timer:.1f}s | Cones: {cones_collected}/8", True, WHITE)
SCREEN.blit(detail_surf, (WIDTH//2 - detail_surf.get_width()//2, HEIGHT//2 + 20))
cont_surf = FONT.render("Press any key to continue...", True, WHITE)
SCREEN.blit(cont_surf, (WIDTH//2 - cont_surf.get_width()//2, HEIGHT//2 + 60))
pygame.display.flip()
waiting = True
while waiting:
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.KEYDOWN:
waiting = False
def training_shot(career_data):
"""Target shooting mini-game"""
if career_data["training_points"] < 1:
return
career_data["training_points"] -= 1
save_career_data(career_data)
ball_pos = Vector2(WIDTH//2, HEIGHT - 150)
ball_vel = Vector2(0, 0)
targets = []
for i in range(5):
x = random.randint(200, WIDTH - 200)
y = random.randint(100, 300)
targets.append({"pos": Vector2(x, y), "radius": random.randint(30, 50), "hit": False})
charging = False
charge_time = 0.0
max_charge = 1.5
shots_taken = 0
max_shots = 10
while shots_taken < max_shots:
dt = CLOCK.tick(60) / 1000.0
ball_vel *= 0.97
ball_pos += ball_vel
if ball_pos.y < 0 or ball_pos.y > HEIGHT or ball_pos.x < 0 or ball_pos.x > WIDTH:
ball_pos = Vector2(WIDTH//2, HEIGHT - 150)
ball_vel = Vector2(0, 0)
for target in targets:
if not target["hit"] and (target["pos"] - ball_pos).length() < target["radius"]:
target["hit"] = True
keys = pygame.key.get_pressed()
mx, my = pygame.mouse.get_pos()
if charging:
charge_time += dt
if charge_time > max_charge:
charge_time = max_charge
SCREEN.fill(DARK_GREEN)
for target in targets:
color = GRAY if target["hit"] else RED
pygame.draw.circle(SCREEN, color, (int(target["pos"].x), int(target["pos"].y)), target["radius"], 3)
pygame.draw.circle(SCREEN, color, (int(target["pos"].x), int(target["pos"].y)), 5)
pygame.draw.circle(SCREEN, YELLOW, (int(ball_pos.x), int(ball_pos.y)), BALL_RADIUS)
if charging:
dir_vec = Vector2(mx - ball_pos.x, my - ball_pos.y)
if dir_vec.length() > 0:
dir_vec = dir_vec.normalize()
arrow_len = 30 + 100 * (charge_time / max_charge)
end_pos = ball_pos + dir_vec * arrow_len
pygame.draw.line(SCREEN, WHITE, (ball_pos.x, ball_pos.y), (end_pos.x, end_pos.y), 4)
title_surf = MEDIUM_FONT.render("SHOT TRAINING - Hit the targets!", True, WHITE)
SCREEN.blit(title_surf, (WIDTH//2 - title_surf.get_width()//2, 20))
shots_surf = FONT.render(f"Shots: {shots_taken}/{max_shots}", True, WHITE)
SCREEN.blit(shots_surf, (20, 20))
hits = sum(1 for t in targets if t["hit"])
hits_surf = FONT.render(f"Targets: {hits}/5", True, WHITE)
SCREEN.blit(hits_surf, (20, 50))
inst_surf = SMALL_FONT.render("Hold SPACE and aim with mouse, release to shoot", True, WHITE)
SCREEN.blit(inst_surf, (WIDTH//2 - inst_surf.get_width()//2, HEIGHT - 30))
pygame.display.flip()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.KEYDOWN:
if ev.key == pygame.K_SPACE and ball_vel.length() < 1:
charging = True
charge_time = 0.0
if ev.key == pygame.K_ESCAPE:
return
if ev.type == pygame.KEYUP:
if ev.key == pygame.K_SPACE and charging:
dir_vec = Vector2(mx - ball_pos.x, my - ball_pos.y)
if dir_vec.length() > 0:
dir_vec = dir_vec.normalize()
power = 8 + 12 * (charge_time / max_charge)
ball_vel = dir_vec * power
shots_taken += 1
charging = False
charge_time = 0.0
hits = sum(1 for t in targets if t["hit"])
points_gained = hits * 4
career_data["stats"]["shot_power"] = min(100, career_data["stats"]["shot_power"] + points_gained)
save_career_data(career_data)
SCREEN.fill(MENU_BG)
result_surf = BIG.render(f"Shot Power +{points_gained}!", True, GOLD)
SCREEN.blit(result_surf, (WIDTH//2 - result_surf.get_width()//2, HEIGHT//2 - 50))
detail_surf = FONT.render(f"Targets Hit: {hits}/5", True, WHITE)
SCREEN.blit(detail_surf, (WIDTH//2 - detail_surf.get_width()//2, HEIGHT//2 + 20))
cont_surf = FONT.render("Press any key to continue...", True, WHITE)
SCREEN.blit(cont_surf, (WIDTH//2 - cont_surf.get_width()//2, HEIGHT//2 + 60))
pygame.display.flip()
waiting = True
while waiting:
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.KEYDOWN:
waiting = False
def training_stamina(career_data):
"""Endurance run mini-game"""
if career_data["training_points"] < 1:
return
career_data["training_points"] -= 1
save_career_data(career_data)
player_pos = Vector2(100, HEIGHT//2)
obstacles = []
distance = 0.0
stamina = 100.0
game_speed = 5.0
timer = 0.0
max_time = 20.0
while timer < max_time and stamina > 0:
dt = CLOCK.tick(60) / 1000.0
timer += dt
if random.random() < 0.02:
y = random.randint(50, HEIGHT - 50)
obstacles.append(Vector2(WIDTH + 20, y))
for obs in obstacles:
obs.x -= game_speed
obstacles = [o for o in obstacles if o.x > -30]
keys = pygame.key.get_pressed()
if keys[pygame.K_w] and player_pos.y > 30:
player_pos.y -= 5
if keys[pygame.K_s] and player_pos.y < HEIGHT - 30:
player_pos.y += 5
distance += game_speed * dt
stamina -= 2.5 * dt
for obs in obstacles:
if abs(obs.x - player_pos.x) < 25 and abs(obs.y - player_pos.y) < 25:
stamina -= 10
obstacles.remove(obs)
break
SCREEN.fill((40, 100, 40))
for obs in obstacles:
pygame.draw.rect(SCREEN, RED, (obs.x - 15, obs.y - 15, 30, 30))
pygame.draw.circle(SCREEN, BLUE, (int(player_pos.x), int(player_pos.y)), PLAYER_RADIUS)
title_surf = MEDIUM_FONT.render("STAMINA TRAINING - Dodge obstacles!", True, WHITE)
SCREEN.blit(title_surf, (WIDTH//2 - title_surf.get_width()//2, 20))
stam_surf = FONT.render(f"Stamina: {int(stamina)}", True, WHITE)
SCREEN.blit(stam_surf, (20, 20))
dist_surf = FONT.render(f"Distance: {int(distance)}", True, WHITE)
SCREEN.blit(dist_surf, (20, 50))
time_surf = FONT.render(f"Time: {max_time - timer:.1f}s", True, WHITE)
SCREEN.blit(time_surf, (20, 80))
pygame.display.flip()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.KEYDOWN:
if ev.key == pygame.K_ESCAPE:
return
points_gained = int(distance // 20)
career_data["stats"]["stamina"] = min(100, career_data["stats"]["stamina"] + points_gained)
save_career_data(career_data)
SCREEN.fill(MENU_BG)
result_surf = BIG.render(f"Stamina +{points_gained}!", True, GOLD)
SCREEN.blit(result_surf, (WIDTH//2 - result_surf.get_width()//2, HEIGHT//2 - 50))
detail_surf = FONT.render(f"Distance: {int(distance)}", True, WHITE)
SCREEN.blit(detail_surf, (WIDTH//2 - detail_surf.get_width()//2, HEIGHT//2 + 20))
cont_surf = FONT.render("Press any key to continue...", True, WHITE)
SCREEN.blit(cont_surf, (WIDTH//2 - cont_surf.get_width()//2, HEIGHT//2 + 60))
pygame.display.flip()
waiting = True
while waiting:
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.KEYDOWN:
waiting = False
def training_foul(career_data):
"""Tackle timing mini-game"""
if career_data["training_points"] < 1:
return
career_data["training_points"] -= 1
save_career_data(career_data)
opponents = []
for i in range(5):
opponents.append({
"pos": Vector2(random.randint(200, WIDTH - 200), random.randint(100, HEIGHT - 100)),
"vel": Vector2(random.uniform(-3, 3), random.uniform(-3, 3)),
"tackled": False
})
player_pos = Vector2(WIDTH//2, HEIGHT//2)
player_vel = Vector2(0, 0)
speed = 6.0
tackle_cooldown = 0.0
tackles_made = 0
timer = 0.0
max_time = 15.0
while timer < max_time:
dt = CLOCK.tick(60) / 1000.0
timer += dt
tackle_cooldown = max(0, tackle_cooldown - dt)
keys = pygame.key.get_pressed()
acc = Vector2(0, 0)
if keys[pygame.K_w]: acc.y = -1
if keys[pygame.K_s]: acc.y = 1
if keys[pygame.K_a]: acc.x = -1
if keys[pygame.K_d]: acc.x = 1
if acc.length_squared() > 0:
acc = acc.normalize() * speed
player_vel += acc * 0.3
if player_vel.length() > speed:
player_vel.scale_to_length(speed)
player_vel *= 0.88
player_pos += player_vel
player_pos.x = clamp(player_pos.x, 30, WIDTH - 30)
player_pos.y = clamp(player_pos.y, 30, HEIGHT - 30)
for opp in opponents:
if not opp["tackled"]:
opp["pos"] += opp["vel"]
if opp["pos"].x < 30 or opp["pos"].x > WIDTH - 30:
opp["vel"].x *= -1
if opp["pos"].y < 30 or opp["pos"].y > HEIGHT - 30:
opp["vel"].y *= -1
SCREEN.fill(GREEN)
for opp in opponents:
if not opp["tackled"]:
pygame.draw.circle(SCREEN, RED, (int(opp["pos"].x), int(opp["pos"].y)), PLAYER_RADIUS)
else:
pygame.draw.circle(SCREEN, GRAY, (int(opp["pos"].x), int(opp["pos"].y)), PLAYER_RADIUS)
pygame.draw.circle(SCREEN, BLUE, (int(player_pos.x), int(player_pos.y)), PLAYER_RADIUS)
if tackle_cooldown > 0:
pygame.draw.circle(SCREEN, YELLOW, (int(player_pos.x), int(player_pos.y)), PLAYER_RADIUS + 5, 3)
title_surf = MEDIUM_FONT.render("FOUL TRAINING - Tackle opponents!", True, WHITE)
SCREEN.blit(title_surf, (WIDTH//2 - title_surf.get_width()//2, 20))
tackles_surf = FONT.render(f"Tackles: {tackles_made}/5", True, WHITE)
SCREEN.blit(tackles_surf, (20, 20))
time_surf = FONT.render(f"Time: {max_time - timer:.1f}s", True, WHITE)
SCREEN.blit(time_surf, (20, 50))
inst_surf = SMALL_FONT.render("Get close and press C to tackle", True, WHITE)
SCREEN.blit(inst_surf, (WIDTH//2 - inst_surf.get_width()//2, HEIGHT - 30))
pygame.display.flip()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.KEYDOWN:
if ev.key == pygame.K_c and tackle_cooldown == 0:
tackle_cooldown = 1.5
for opp in opponents:
if not opp["tackled"] and (opp["pos"] - player_pos).length() < 50:
opp["tackled"] = True
tackles_made += 1
if ev.key == pygame.K_ESCAPE:
return
points_gained = tackles_made * 4
career_data["stats"]["foul_strength"] = min(100, career_data["stats"]["foul_strength"] + points_gained)
save_career_data(career_data)
SCREEN.fill(MENU_BG)
result_surf = BIG.render(f"Foul Strength +{points_gained}!", True, GOLD)
SCREEN.blit(result_surf, (WIDTH//2 - result_surf.get_width()//2, HEIGHT//2 - 50))
detail_surf = FONT.render(f"Tackles: {tackles_made}/5", True, WHITE)
SCREEN.blit(detail_surf, (WIDTH//2 - detail_surf.get_width()//2, HEIGHT//2 + 20))
cont_surf = FONT.render("Press any key to continue...", True, WHITE)
SCREEN.blit(cont_surf, (WIDTH//2 - cont_surf.get_width()//2, HEIGHT//2 + 60))
pygame.display.flip()
waiting = True
while waiting:
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.KEYDOWN:
waiting = False
def training_menu(career_data):
"""Training menu with all mini-games"""
button_font = pygame.font.SysFont("Arial", 26, bold=True)
buttons = [
{"name": "Speed Training", "rect": pygame.Rect(WIDTH//2 - 200, 200, 400, 60), "action": "speed"},
{"name": "Shot Power Training", "rect": pygame.Rect(WIDTH//2 - 200, 280, 400, 60), "action": "shot"},
{"name": "Stamina Training", "rect": pygame.Rect(WIDTH//2 - 200, 360, 400, 60), "action": "stamina"},
{"name": "Foul Strength Training", "rect": pygame.Rect(WIDTH//2 - 200, 440, 400, 60), "action": "foul"},
{"name": "Back", "rect": pygame.Rect(WIDTH//2 - 150, HEIGHT - 100, 300, 60), "action": "back"}
]
while True:
mx, my = pygame.mouse.get_pos()
SCREEN.fill(MENU_BG)
title = TITLE_FONT.render("TRAINING", True, GOLD)
SCREEN.blit(title, (WIDTH//2 - title.get_width()//2, 40))
stats_text = f"Training Points: {career_data['training_points']} | Speed: {career_data['stats']['speed']} | Shot: {career_data['stats']['shot_power']} | Stamina: {career_data['stats']['stamina']} | Foul: {career_data['stats']['foul_strength']}"
stats_surf = SMALL_FONT.render(stats_text, True, WHITE)
SCREEN.blit(stats_surf, (WIDTH//2 - stats_surf.get_width()//2, 130))
for btn in buttons:
hover = btn["rect"].collidepoint(mx, my)
if btn["action"] != "back" and career_data["training_points"] < 1:
pygame.draw.rect(SCREEN, GRAY, btn["rect"], border_radius=12)
txt = button_font.render(btn["name"] + " (No points)", True, WHITE)
SCREEN.blit(txt, (btn["rect"].centerx - txt.get_width()//2, btn["rect"].centery - txt.get_height()//2))
else:
draw_button(SCREEN, btn["rect"], btn["name"], button_font, hover)
pygame.display.flip()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.MOUSEBUTTONDOWN and ev.button == 1:
for btn in buttons:
if btn["rect"].collidepoint(mx, my):
if btn["action"] == "back":
return
elif career_data["training_points"] >= 1:
if btn["action"] == "speed":
training_speed(career_data)
elif btn["action"] == "shot":
training_shot(career_data)
elif btn["action"] == "stamina":
training_stamina(career_data)
elif btn["action"] == "foul":
training_foul(career_data)
CLOCK.tick(60)
def shop_menu(career_data):
"""Shop for buying energy and stat boosts"""
button_font = pygame.font.SysFont("Arial", 24, bold=True)
items = [
{"name": "Training Point (+1)", "cost": 50, "type": "training"},
{"name": "Speed Boost (+5)", "cost": 100, "type": "speed"},
{"name": "Shot Boost (+5)", "cost": 100, "type": "shot"},
{"name": "Stamina Boost (+5)", "cost": 100, "type": "stamina"},
{"name": "Foul Boost (+5)", "cost": 100, "type": "foul"},
]
y_start = 180
item_buttons = []
for i, item in enumerate(items):
rect = pygame.Rect(WIDTH//2 - 250, y_start + i * 80, 500, 60)
item_buttons.append({"item": item, "rect": rect})
back_button = pygame.Rect(WIDTH//2 - 150, HEIGHT - 100, 300, 60)
while True:
mx, my = pygame.mouse.get_pos()
back_hover = back_button.collidepoint(mx, my)
SCREEN.fill(MENU_BG)
title = TITLE_FONT.render("SHOP", True, GOLD)
SCREEN.blit(title, (WIDTH//2 - title.get_width()//2, 40))
money_surf = MEDIUM_FONT.render(f"Money: ${career_data['money']}", True, GOLD)
SCREEN.blit(money_surf, (WIDTH//2 - money_surf.get_width()//2, 120))
for btn_data in item_buttons:
item = btn_data["item"]
rect = btn_data["rect"]
hover = rect.collidepoint(mx, my)
can_afford = career_data["money"] >= item["cost"]
if can_afford:
draw_button(SCREEN, rect, f"{item['name']} - ${item['cost']}", button_font, hover)
else:
pygame.draw.rect(SCREEN, GRAY, rect, border_radius=12)
txt = button_font.render(f"{item['name']} - ${item['cost']}", True, WHITE)
SCREEN.blit(txt, (rect.centerx - txt.get_width()//2, rect.centery - txt.get_height()//2))
draw_button(SCREEN, back_button, "Back", button_font, back_hover)
pygame.display.flip()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.MOUSEBUTTONDOWN and ev.button == 1:
if back_hover:
return
for btn_data in item_buttons:
item = btn_data["item"]
rect = btn_data["rect"]
if rect.collidepoint(mx, my) and career_data["money"] >= item["cost"]:
career_data["money"] -= item["cost"]
if item["type"] == "training":
career_data["training_points"] += 1
elif item["type"] == "speed":
career_data["stats"]["speed"] = min(100, career_data["stats"]["speed"] + 5)
elif item["type"] == "shot":
career_data["stats"]["shot_power"] = min(100, career_data["stats"]["shot_power"] + 5)
elif item["type"] == "stamina":
career_data["stats"]["stamina"] = min(100, career_data["stats"]["stamina"] + 5)
elif item["type"] == "foul":
career_data["stats"]["foul_strength"] = min(100, career_data["stats"]["foul_strength"] + 5)
save_career_data(career_data)
CLOCK.tick(60)
def career_home_screen(career_data):
"""Career mode home screen"""
button_font = pygame.font.SysFont("Arial", 26, bold=True)
play_button = pygame.Rect(WIDTH - 270, HEIGHT - 120, 220, 70)
train_button = pygame.Rect(WIDTH//2 - 110, HEIGHT - 120, 220, 70)
shop_button = pygame.Rect(50, HEIGHT - 120, 220, 70)
back_button = pygame.Rect(WIDTH//2 - 110, HEIGHT - 200, 220, 60)
scroll_offset = 0
max_scroll = max(0, len(career_data["matches"]) * 60 - 280)
while True:
mx, my = pygame.mouse.get_pos()
play_hover = play_button.collidepoint(mx, my)
train_hover = train_button.collidepoint(mx, my)
shop_hover = shop_button.collidepoint(mx, my)
back_hover = back_button.collidepoint(mx, my)
SCREEN.fill(MENU_BG)
title_font = pygame.font.SysFont("Arial", 52, bold=True)
title = title_font.render("CAREER MODE", True, GOLD)
SCREEN.blit(title, (WIDTH//2 - title.get_width()//2, 30))
info_y = 100
player_text = FONT.render(f"Player: {career_data['player_name']} | Club: {career_data['club']}", True, WHITE)
SCREEN.blit(player_text, (50, info_y))
season_text = FONT.render(f"Season: {career_data['season']} | Position: {career_data['league_position']}/12", True, WHITE)
SCREEN.blit(season_text, (50, info_y + 30))
money_text = FONT.render(f"Money: ${career_data['money']} | Training Points: {career_data['training_points']}", True, GOLD)
SCREEN.blit(money_text, (50, info_y + 60))
total_matches = len(career_data["matches"])
wins = sum(1 for m in career_data["matches"] if m["player_score"] > m["opponent_score"])
losses = sum(1 for m in career_data["matches"] if m["player_score"] < m["opponent_score"])
draws = total_matches - wins - losses
stats_text = SMALL_FONT.render(f"Matches: {total_matches} | W: {wins} | D: {draws} | L: {losses} | Speed: {career_data['stats']['speed']} | Shot: {career_data['stats']['shot_power']} | Stamina: {career_data['stats']['stamina']} | Foul: {career_data['stats']['foul_strength']}", True, WHITE)
SCREEN.blit(stats_text, (50, info_y + 90))
history_rect = pygame.Rect(50, 230, WIDTH - 100, 280)
pygame.draw.rect(SCREEN, MENU_ACCENT, history_rect, border_radius=10)
pygame.draw.rect(SCREEN, WHITE, history_rect, 2, border_radius=10)
history_title = FONT.render("Match History", True, WHITE)
SCREEN.blit(history_title, (70, 245))
if career_data["matches"]:
y_offset = 280 - scroll_offset
for i, match in enumerate(reversed(career_data["matches"])):
if y_offset > 220 and y_offset < 510:
player_won = match["player_score"] > match["opponent_score"]
match_color = WIN_GREEN if player_won else (LOSS_RED if match["player_score"] < match["opponent_score"] else GRAY)
match_rect = pygame.Rect(70, y_offset, WIDTH - 140, 50)
pygame.draw.rect(SCREEN, match_color, match_rect, border_radius=8)
match_text = SMALL_FONT.render(f"Match {len(career_data['matches']) - i}: {career_data['player_name']} {match['player_score']} - {match['opponent_score']} {match['opponent_name']}", True, BLACK)
SCREEN.blit(match_text, (85, y_offset + 15))
y_offset += 60
else:
no_matches = SMALL_FONT.render("No matches played yet!", True, WHITE)
SCREEN.blit(no_matches, (WIDTH//2 - no_matches.get_width()//2, 370))
draw_button(SCREEN, play_button, "PLAY MATCH", button_font, play_hover)
draw_button(SCREEN, train_button, "TRAINING", button_font, train_hover)
draw_button(SCREEN, shop_button, "SHOP", button_font, shop_hover)
draw_button(SCREEN, back_button, "MAIN MENU", button_font, back_hover)
if max_scroll > 0:
scroll_bar_height = int(280 * (280 / (len(career_data["matches"]) * 60)))
scroll_bar_y = 230 + int((scroll_offset / max_scroll) * (280 - scroll_bar_height))
pygame.draw.rect(SCREEN, WHITE, (WIDTH - 110, scroll_bar_y, 8, scroll_bar_height), border_radius=4)
pygame.display.flip()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.MOUSEBUTTONDOWN:
if ev.button == 1:
if play_hover:
return "play"
if train_hover:
return "train"
if shop_hover:
return "shop"
if back_hover:
return "back"
elif ev.button == 4:
scroll_offset = max(0, scroll_offset - 30)
elif ev.button == 5:
scroll_offset = min(max_scroll, scroll_offset + 30)
CLOCK.tick(60)
def run_match(left_name, right_name, is_career=False, career_data=None):
"""Run a match"""
left_controls = {
'up': pygame.K_w, 'down': pygame.K_s, 'left': pygame.K_a, 'right': pygame.K_d,
'kick': pygame.K_SPACE, 'sprint': pygame.K_LSHIFT, 'foul': pygame.K_c
}
if is_career and career_data:
left = Player((160, HEIGHT/2), BLUE, controls=left_controls, is_cpu=False, name=left_name, stats=career_data["stats"])
right = Player((WIDTH-160, HEIGHT/2), RED, controls=None, is_cpu=True, name=right_name)
else:
right_controls = {
'up': pygame.K_UP, 'down': pygame.K_DOWN, 'left': pygame.K_LEFT, 'right': pygame.K_RIGHT,
'kick': pygame.K_KP0, 'sprint': pygame.K_RSHIFT, 'foul': pygame.K_KP_PERIOD
}
left = Player((160, HEIGHT/2), BLUE, controls=left_controls, is_cpu=False, name=left_name)
right = Player((WIDTH-160, HEIGHT/2), RED, controls=right_controls, is_cpu=False, name=right_name)
ball = Ball((WIDTH/2, HEIGHT/2))
kickoff(ball, left, right)
start_ticks = pygame.time.get_ticks()
paused = False
MATCH_TIME = MATCH_TIME_DEFAULT
while True:
dt = CLOCK.tick(60) / 1000.0
keys = pygame.key.get_pressed()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.KEYDOWN:
if ev.key == pygame.K_ESCAPE:
return None
if ev.key == pygame.K_r:
left.score = 0
right.score = 0
kickoff(ball, left, right)
start_ticks = pygame.time.get_ticks()
paused = False
if ev.key == left.controls['kick']:
left.is_charging = True
left.charge_time = 0.0
if not is_career and ev.key == right.controls['kick']:
right.is_charging = True
right.charge_time = 0.0
if ev.key == left.controls['foul']:
perform_foul(left, right, ball)
if not is_career and ev.key == right.controls['foul']:
perform_foul(right, left, ball)
if ev.type == pygame.KEYUP:
if ev.key == left.controls['kick']:
if left.is_charging:
perform_kick(left, ball, left.charge_time)
left.is_charging = False
left.charge_time = 0.0
if not is_career and ev.key == right.controls['kick']:
if right.is_charging:
perform_kick(right, ball, right.charge_time)
right.is_charging = False
right.charge_time = 0.0
if not paused:
if right.is_cpu:
dist = (ball.pos - right.pos).length()
if dist <= KICK_RADIUS:
if not right.is_charging and random.random() < 0.025:
right.is_charging = True
right.charge_time = random.uniform(0.1, 0.85 * MAX_CHARGE_TIME)
if right.is_charging:
if random.random() < 0.08 or right.charge_time >= right.max_charge:
perform_kick(right, ball, right.charge_time)
right.is_charging = False
right.charge_time = 0.0
left.update(ball, keys, dt)
right.update(ball, keys, dt)
ball.update()
handle_collisions([left, right], ball)
check_goal(ball, left, right)
elapsed = (pygame.time.get_ticks() - start_ticks)/1000.0
time_left = max(0.0, MATCH_TIME - elapsed)
if time_left <= 0.0 and not paused:
paused = True
for p in particles[:]:
p.update(dt)
if p.age >= p.lifetime or p.radius <= 0.6:
particles.remove(p)
draw_field(SCREEN)
for p in particles:
p.draw(SCREEN)
ball.draw(SCREEN)
left.draw(SCREEN, ball)
right.draw(SCREEN, ball)
draw_game_ui(SCREEN, left, right, time_left)
if paused:
overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
overlay.fill((0, 0, 0, 180))
SCREEN.blit(overlay, (0, 0))
result_font = pygame.font.SysFont("Arial", 56, bold=True)
txt = result_font.render("MATCH OVER", True, YELLOW)
SCREEN.blit(txt, (WIDTH//2 - txt.get_width()//2, HEIGHT//2 - 100))
score_font = pygame.font.SysFont("Arial", 42, bold=True)
score_txt = score_font.render(f"{left.name} {left.score} - {right.score} {right.name}", True, WHITE)
SCREEN.blit(score_txt, (WIDTH//2 - score_txt.get_width()//2, HEIGHT//2 - 30))
if is_career:
if left.score == right.score:
pen_font = pygame.font.SysFont("Arial", 32, bold=True)
pen_txt = pen_font.render("Draw! Going to Penalties...", True, YELLOW)
SCREEN.blit(pen_txt, (WIDTH//2 - pen_txt.get_width()//2, HEIGHT//2 + 10))
pygame.display.flip()
pygame.time.wait(800)
winner_name = penalty_shootout(left, right)
if winner_name == left.name:
return {"player_score": left.score + 1, "opponent_score": right.score, "opponent_name": right.name}
else:
return {"player_score": left.score, "opponent_score": right.score + 1, "opponent_name": right.name}
continue_font = pygame.font.SysFont("Arial", 28)
cont_txt = continue_font.render("Press SPACE to continue | R: Restart | ESC: Menu", True, WHITE)
SCREEN.blit(cont_txt, (WIDTH//2 - cont_txt.get_width()//2, HEIGHT//2 + 40))
if keys[pygame.K_SPACE]:
return {"player_score": left.score, "opponent_score": right.score, "opponent_name": right.name}
else:
sub = FONT.render("Press R to restart | ESC for menu", True, WHITE)
SCREEN.blit(sub, (WIDTH//2 - sub.get_width()//2, HEIGHT//2 + 40))
pygame.display.flip()
def main_menu():
"""Main menu"""
button_font = pygame.font.SysFont("Arial", 32, bold=True)
career_button = pygame.Rect(WIDTH//2 - 200, 280, 400, 70)
kickoff_button = pygame.Rect(WIDTH//2 - 200, 380, 400, 70)
quit_button = pygame.Rect(WIDTH//2 - 200, 480, 400, 70)
while True:
mx, my = pygame.mouse.get_pos()
career_hover = career_button.collidepoint(mx, my)
kickoff_hover = kickoff_button.collidepoint(mx, my)
quit_hover = quit_button.collidepoint(mx, my)
SCREEN.fill(MENU_BG)
title = TITLE_FONT.render("NEW STAR FOOTBALL", True, GOLD)
SCREEN.blit(title, (WIDTH//2 - title.get_width()//2, 100))
subtitle = FONT.render("Complete Career Mode", True, WHITE)
SCREEN.blit(subtitle, (WIDTH//2 - subtitle.get_width()//2, 200))
draw_button(SCREEN, career_button, "CAREER MODE", button_font, career_hover)
draw_button(SCREEN, kickoff_button, "KICK OFF", button_font, kickoff_hover)
draw_button(SCREEN, quit_button, "QUIT", button_font, quit_hover)
pygame.display.flip()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.MOUSEBUTTONDOWN:
if career_hover:
return "career"
if kickoff_hover:
return "kickoff"
if quit_hover:
pygame.quit()
sys.exit()
CLOCK.tick(60)
def kickoff_menu():
"""Kick off mode menu"""
input_font = pygame.font.SysFont("Arial", 26)
title_font = pygame.font.SysFont("Arial", 42, bold=True)
fields = ["Player 1 Name", "Player 2 Name"]
vals = ["Blue", "Red"]
active = 0
blink = 0.0
button_font = pygame.font.SysFont("Arial", 28, bold=True)
start_button = pygame.Rect(WIDTH//2 - 150, 450, 300, 60)
while True:
dt = CLOCK.tick(60) / 1000.0
blink += dt
mx, my = pygame.mouse.get_pos()
start_hover = start_button.collidepoint(mx, my)
SCREEN.fill(MENU_BG)
title = title_font.render("KICK OFF MODE", True, YELLOW)
SCREEN.blit(title, (WIDTH//2 - title.get_width()//2, 100))
subtitle = FONT.render("Enter player names (Tab to switch)", True, WHITE)
SCREEN.blit(subtitle, (WIDTH//2 - subtitle.get_width()//2, 160))
for i, f in enumerate(fields):
y = 240 + i*90
label = input_font.render(f + ":", True, WHITE)
SCREEN.blit(label, (WIDTH//2 - 250, y))
rect_w = 280
rect_h = 45
rect_x = WIDTH//2 - 30
rect_y = y - 5
color_bg = BUTTON_HOVER if active == i else BUTTON_COLOR
pygame.draw.rect(SCREEN, color_bg, (rect_x, rect_y, rect_w, rect_h), border_radius=8)
pygame.draw.rect(SCREEN, WHITE, (rect_x, rect_y, rect_w, rect_h), 2, border_radius=8)
val_surf = input_font.render(vals[i], True, WHITE)
SCREEN.blit(val_surf, (rect_x + 10, y))
if active == i and (blink % 1.0) < 0.5:
cursor_x = rect_x + 10 + val_surf.get_width() + 2
pygame.draw.rect(SCREEN, WHITE, (cursor_x, y + 5, 3, 22))
draw_button(SCREEN, start_button, "START MATCH", button_font, start_hover)
pygame.display.flip()
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.KEYDOWN:
if ev.key == pygame.K_TAB:
active = (active + 1) % len(fields)
elif ev.key == pygame.K_RETURN:
p1 = vals[0].strip() or "Blue"
p2 = vals[1].strip() or "Red"
return p1, p2
elif ev.key == pygame.K_BACKSPACE:
vals[active] = vals[active][:-1]
else:
if ev.unicode and ord(ev.unicode) >= 32 and len(vals[active]) < 15:
vals[active] += ev.unicode
if ev.type == pygame.MOUSEBUTTONDOWN:
if start_hover:
p1 = vals[0].strip() or "Blue"
p2 = vals[1].strip() or "Red"
return p1, p2
def career_mode():
"""Main career mode loop"""
career_data = load_career_data()
if not career_data:
career_data = character_creation()
while True:
action = career_home_screen(career_data)
if action == "play":
opponent_name = generate_player_name()
result = run_match(career_data["player_name"], opponent_name, is_career=True, career_data=career_data)
if result:
career_data["matches"].append(result)
# Calculate earnings
if result["player_score"] > result["opponent_score"]:
earnings = 150
career_data["training_points"] += 2
elif result["player_score"] == result["opponent_score"]:
earnings = 75
career_data["training_points"] += 1
else:
earnings = 50
career_data["money"] += earnings
# Update league position (simple simulation)
if result["player_score"] > result["opponent_score"]:
career_data["league_position"] = max(1, career_data["league_position"] - random.randint(0, 2))
elif result["player_score"] < result["opponent_score"]:
career_data["league_position"] = min(12, career_data["league_position"] + random.randint(0, 1))
save_career_data(career_data)
# Show match result screen
SCREEN.fill(MENU_BG)
if result["player_score"] > result["opponent_score"]:
result_text = "VICTORY!"
result_color = WIN_GREEN
elif result["player_score"] < result["opponent_score"]:
result_text = "DEFEAT"
result_color = LOSS_RED
else:
result_text = "DRAW"
result_color = YELLOW
result_surf = BIG.render(result_text, True, result_color)
SCREEN.blit(result_surf, (WIDTH//2 - result_surf.get_width()//2, HEIGHT//2 - 120))
score_surf = MEDIUM_FONT.render(f"{career_data['player_name']} {result['player_score']} - {result['opponent_score']} {result['opponent_name']}", True, WHITE)
SCREEN.blit(score_surf, (WIDTH//2 - score_surf.get_width()//2, HEIGHT//2 - 40))
earnings_surf = FONT.render(f"Earned: ${earnings}", True, GOLD)
SCREEN.blit(earnings_surf, (WIDTH//2 - earnings_surf.get_width()//2, HEIGHT//2 + 20))
tp_surf = FONT.render(f"Training Points: +{2 if result['player_score'] > result['opponent_score'] else (1 if result['player_score'] == result['opponent_score'] else 0)}", True, GOLD)
SCREEN.blit(tp_surf, (WIDTH//2 - tp_surf.get_width()//2, HEIGHT//2 + 50))
pos_surf = FONT.render(f"League Position: {career_data['league_position']}/12", True, WHITE)
SCREEN.blit(pos_surf, (WIDTH//2 - pos_surf.get_width()//2, HEIGHT//2 + 90))
cont_surf = SMALL_FONT.render("Press any key to continue...", True, WHITE)
SCREEN.blit(cont_surf, (WIDTH//2 - cont_surf.get_width()//2, HEIGHT - 100))
pygame.display.flip()
waiting = True
while waiting:
for ev in pygame.event.get():
if ev.type == pygame.QUIT:
pygame.quit()
sys.exit()
if ev.type == pygame.KEYDOWN:
waiting = False
CLOCK.tick(60)
elif action == "train":
training_menu(career_data)
elif action == "shop":
shop_menu(career_data)
elif action == "back":
return
def main():
while True:
mode = main_menu()
if mode == "career":
career_mode()
elif mode == "kickoff":
p1_name, p2_name = kickoff_menu()
run_match(p1_name, p2_name, is_career=False)
if __name__ == "__main__":
main()Editor is loading...
Leave a Comment