ourgame/game.py

973 lines
39 KiB
Python

import pygame
import random
import sys
import os
import math
# Inicializējam pygame
pygame.init()
# --- AUDIO SISTĒMAS LABOJUMS ---
# Mēģinam ieslēgt skaņu, ja neizdodas - turpinām bez tās.
mixer_initialized = False
try:
pygame.mixer.init()
mixer_initialized = True
except pygame.error:
print("Brīdinājums: Neizdevās inicializēt audio sistēmu. Spēle tiks palaista bez skaņas.")
# ------------------------------
WIDTH, HEIGHT = 1024, 576
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Pixel Kombat: Ultimate")
# --- CUSTOM CURSOR IESTATĪJUMI (SĀKUMS) ---
# Paslēpjam noklusējuma sistēmas kursoru
pygame.mouse.set_visible(False)
# --- CUSTOM CURSOR IESTATĪJUMI (BEIGAS) ---
CLOCK = pygame.time.Clock()
# --- KRĀSAS ---
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GRAY = (50, 50, 50)
DARK_GRAY = (20, 20, 20)
YELLOW = (255, 215, 0)
GREEN = (50, 200, 50)
CYAN = (0, 255, 255)
PURPLE = (160, 32, 240)
ORANGE = (255, 165, 0)
LIGHT_BLUE = (100, 149, 237)
# --- Fonti ---
def get_font(name, size):
if os.path.exists(name):
try:
return pygame.font.Font(name, size)
except:
return pygame.font.SysFont('arial', size)
else:
return pygame.font.SysFont('arial', size)
FONT_BIG = get_font("Act_Of_Rejection.ttf", 80)
FONT_MED = get_font("PressStart2P-Regular.ttf", 36)
FONT_SMALL = get_font("PressStart2P-Regular.ttf", 20)
FONT_TINY = get_font("PressStart2P-Regular.ttf", 14)
# --- Globālie mainīgie ---
STATE = "MENU"
SELECTED_BG = "BEACH"
GAME_MODE = "PVP"
# --- Mūzika ---
MUSIC_FILE = "lofiewme-pixel-fantasia-355123.mp3"
sound_on = True
# Mūzikas ielāde (tikai ja audio sistēma darbojas)
if mixer_initialized:
if os.path.exists(MUSIC_FILE):
try:
pygame.mixer.music.load(MUSIC_FILE)
pygame.mixer.music.set_volume(0.5)
pygame.mixer.music.play(-1)
except Exception as e:
print(f"Kļūda ielādējot mūziku: {e}")
else:
print(f"Mūzikas fails '{MUSIC_FILE}' nav atrasts.")
else:
print("Mūzika netiks atskaņota (audio nav pieejams).")
# --- Sitiena skaņa ---
HIT_SOUND_FILE = "freesound_community-pixel-sound-effect-3-82880.mp3"
hit_sound = None
# Skaņas ielāde (tikai ja audio sistēma darbojas)
if mixer_initialized:
if os.path.exists(HIT_SOUND_FILE):
try:
hit_sound = pygame.mixer.Sound(HIT_SOUND_FILE)
hit_sound.set_volume(0.7)
except Exception as e:
print(f"Kļūda ielādējot sitiena skaņu: {e}")
else:
print(f"Skaņas fails '{HIT_SOUND_FILE}' nav atrasts.")
# --- High score ---
HIGHSCORE_FILE = "highscores.txt"
def save_highscore(winner_name):
try:
with open(HIGHSCORE_FILE, "a") as f:
f.write(f"{winner_name}\n")
except Exception as e:
print(f"Neizdevās saglabāt rezultātu: {e}")
def load_highscores():
scores = []
if os.path.exists(HIGHSCORE_FILE):
try:
with open(HIGHSCORE_FILE, "r") as f:
lines = f.readlines()
scores = [line.strip() for line in lines[-5:]]
except:
pass
return scores
# --- Tēlu un fona datu bāzes ---
FALLBACK_COLORS = [
(235, 64, 52), (52, 119, 235), (52, 235, 86), (255, 215, 0), (160, 32, 240), (255, 105, 180)
]
CHARACTER_FILES = [
"characters/first1_char.png", "characters/second2_char.png", "characters/third3_char.png",
"characters/forth4_char.png", "characters/fifth5_char.png", "characters/sixth6_char.png"
]
BOSS_FILES = ["boss/boss1.png", "boss/boss2.png", "boss/boss3.png"]
P1_CHAR_INDEX = 0
P2_CHAR_INDEX = 1
BG_FILES = {
"BEACH": "backgrounds/beach.jpg", "EVENINGSTREET": "backgrounds/evening_street.jpg",
"MARKET": "backgrounds/market.jpg", "RESTAURANT": "backgrounds/restaurant.jpg",
"SAKURASTREET": "backgrounds/sakura_street.jpg", "SHIP": "backgrounds/ship.jpg",
"STREETMARKETS": "backgrounds/street_markets.jpg"
}
# --- Safe character(nav svarīgi) ---
def create_placeholder_image(color, size=(80, 160), text="", is_boss=False):
surf = pygame.Surface(size)
surf.fill(color)
if text:
font = pygame.font.SysFont('arial', 20)
txt = font.render(text, True, WHITE)
surf.blit(txt, (size[0]//2 - txt.get_width()//2, size[1]//2 - txt.get_height()//2))
return surf
# --- Tēlu ielade ---
def load_character_images():
chars_data = []
SPRITE_SIZE = (80, 150)
ICON_SIZE = (100, 100)
for i, filename in enumerate(CHARACTER_FILES):
color = FALLBACK_COLORS[i % len(FALLBACK_COLORS)]
try:
if os.path.exists(filename):
img = pygame.image.load(filename).convert_alpha()
game_img = pygame.transform.scale(img, SPRITE_SIZE)
icon_img = pygame.transform.scale(img, ICON_SIZE)
else:
raise FileNotFoundError
# --- Ja ne atrod attēlu ---
except:
game_img = create_placeholder_image(color, SPRITE_SIZE, f"T{i+1}")
icon_surf = pygame.Surface(ICON_SIZE)
icon_surf.fill(color)
pygame.draw.rect(icon_surf, WHITE, (0,0,ICON_SIZE[0], ICON_SIZE[1]), 2)
font = pygame.font.SysFont('arial', 24)
txt = font.render(f"Char {i+1}", True, WHITE)
icon_surf.blit(txt, (ICON_SIZE[0]//2 - txt.get_width()//2, ICON_SIZE[1]//2 - txt.get_height()//2))
icon_img = icon_surf
chars_data.append({'game_img': game_img, 'icon': icon_img, 'color': color})
return chars_data
# --- Bossu ielade ---
def load_boss_images():
bosses = []
BOSS_SIZE = (160, 300)
boss_colors = [(100, 0, 0), (0, 100, 0), (0, 0, 100)]
for i, filename in enumerate(BOSS_FILES):
try:
if os.path.exists(filename):
img = pygame.image.load(filename).convert_alpha()
img = pygame.transform.scale(img, BOSS_SIZE)
bosses.append(img)
else:
raise FileNotFoundError
except:
img = create_placeholder_image(boss_colors[i % len(boss_colors)], BOSS_SIZE, f"BOSS", is_boss=True)
bosses.append(img)
return bosses
# --- Ja fons un logu bildes nav atrastas ---
def load_image_safe(filename, fallback_color, size=None):
try:
if os.path.exists(filename):
img = pygame.image.load(filename)
if size:
img = pygame.transform.scale(img, size)
else:
img = pygame.transform.scale(img, (WIDTH, HEIGHT))
return img
else:
raise FileNotFoundError
except:
surf = pygame.Surface(size if size else (WIDTH, HEIGHT))
surf.fill(fallback_color)
return surf
# --- Attēlu ielade ---
CHARACTERS = load_character_images()
BOSS_IMAGES = load_boss_images()
# --- Menu bildes ---
MENU_PIC_WIDTH = 250
menupic1 = load_image_safe("menupic1.png", FALLBACK_COLORS[1], (MENU_PIC_WIDTH, HEIGHT))
menupic2 = load_image_safe("menupic2.png", FALLBACK_COLORS[0], (MENU_PIC_WIDTH, HEIGHT))
# --- Fonu attēli ---
bg_images = {}
cols = {"BEACH": (194, 178, 128), "EVENINGSTREET": (30, 30, 50), "MARKET": (100, 80, 60),
"RESTAURANT": (150, 100, 50), "SAKURASTREET": (255, 183, 197), "SHIP": (0, 105, 148),
"STREETMARKETS": (90, 90, 90)}
for key, path in BG_FILES.items():
bg_images[key] = load_image_safe(path, cols.get(key, GRAY))
# --- Boom attēla ielade ---
try:
if os.path.exists("boom.png"):
BOOM_IMG_ORIGINAL = pygame.image.load("boom.png").convert_alpha()
BOOM_IMG = pygame.transform.scale(BOOM_IMG_ORIGINAL, (80, 80))
BOOM_IMG_LARGE = pygame.transform.scale(BOOM_IMG_ORIGINAL, (160, 160))
else:
BOOM_IMG = pygame.Surface((80, 80)); BOOM_IMG.fill(YELLOW)
BOOM_IMG_LARGE = pygame.Surface((160, 160)); BOOM_IMG_LARGE.fill(ORANGE)
except:
BOOM_IMG = pygame.Surface((80, 80)); BOOM_IMG.fill(YELLOW)
BOOM_IMG_LARGE = pygame.Surface((160, 160)); BOOM_IMG_LARGE.fill(ORANGE)
# --- Custom cursor ielade ---
CURSOR_IMG = None
CURSOR_FILE = "custom_cursor.png"
if os.path.exists(CURSOR_FILE):
try:
CURSOR_IMG = pygame.image.load(CURSOR_FILE).convert_alpha()
CURSOR_IMG = pygame.transform.scale(CURSOR_IMG, (32, 32))
print("Kursors veiksmīgi ielādēts.")
except Exception as e:
print(f"Kļūda ielādējot kursoru: {e}")
else:
print(f"Kursora fails '{CURSOR_FILE}' nav atrasts.")
CURSOR_IMG = pygame.Surface((20, 20), pygame.SRCALPHA)
pygame.draw.circle(CURSOR_IMG, WHITE, (10, 10), 10)
pygame.draw.circle(CURSOR_IMG, BLACK, (10, 10), 10, 2)
# ---- UI Klases ----
# --- Visas pogas(to visparīgums un pārbaude)
class Button:
def __init__(self, x, y, w, h, text, color, hover_color, action_code):
self.rect = pygame.Rect(x, y, w, h)
self.text = text
self.color = color
self.hover_color = hover_color
self.action_code = action_code
def draw(self, surface):
mouse_pos = pygame.mouse.get_pos()
is_hovered = self.rect.collidepoint(mouse_pos)
current_color = self.hover_color if is_hovered else self.color
text_surf = FONT_SMALL.render(self.text, True, current_color)
surface.blit(text_surf, (self.rect.centerx - text_surf.get_width()//2, self.rect.centery - text_surf.get_height()//2))
def is_clicked(self, event):
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1 and self.rect.collidepoint(event.pos):
return True
return False
# ---Consolēs zīmejums ---
def draw_key_visual(surface, x, y, w, h, key_text, action_text, color):
pygame.draw.rect(surface, color, (x, y, w, h), 2)
pygame.draw.rect(surface, DARK_GRAY, (x+4, y+4, w-8, h-8))
txt_surf = FONT_SMALL.render(key_text, True, WHITE)
surface.blit(txt_surf, (x + w//2 - txt_surf.get_width()//2, y + 10))
desc_surf = FONT_TINY.render(action_text, True, GRAY)
surface.blit(desc_surf, (x + w//2 - desc_surf.get_width()//2, y + h + 5))
# ---Cīnītājs ---
class Fighter(pygame.sprite.Sprite):
def __init__(self, x, y, char_data, facing_right, controls):
super().__init__()
# - Ka izskatas -
self.char_data = char_data
self.image = char_data['game_img']
self.color_accent = char_data['color']
self.start_x = x
self.start_y = y
self.facing_right_start = facing_right
# - Fizika -
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.rect.bottom = HEIGHT - 50
# - Fizikas un Kustības -
self.vel_y = 0
self.speed = 7
self.jump_power = -20
self.gravity = 0.8
self.on_ground = False
# - Stāvokļa un cīnas -
self.facing_right = facing_right
self.controls = controls
self.attacking = False
self.attack_cooldown = 0
self.attack_box = pygame.Rect(0, 0, 0, 0)
self.health = 100
self.hit_timer = 0
# - Sagatavot nākamajai kārtai -
def reset_round(self):
self.health = 100
self.vel_y = 0
self.rect.center = (self.start_x, self.start_y)
self.rect.bottom = HEIGHT - 50
self.facing_right = self.facing_right_start
self.attacking = False
self.attack_cooldown = 0
self.hit_timer = 0
# - tēla pārvietošana -
def move(self, keys):
# - Horizontāla kustība -
dx = 0
if keys[self.controls['left']]:
dx = -self.speed
self.facing_right = False
if keys[self.controls['right']]:
dx = self.speed
self.facing_right = True
# - robežas -
self.rect.x += dx
if self.rect.left < 0: self.rect.left = 0
if self.rect.right > WIDTH: self.rect.right = WIDTH
# - Lekšana -
if keys[self.controls['jump']] and self.on_ground:
self.vel_y = self.jump_power
self.on_ground = False
# - Gravitācija -
self.vel_y += self.gravity
self.rect.y += self.vel_y
if self.rect.bottom >= HEIGHT - 50:
self.rect.bottom = HEIGHT - 50
self.vel_y = 0
self.on_ground = True
# - Uzbrukuma uzsākšana -
def attack(self):
if self.attack_cooldown == 0:
self.attacking = True
self.attack_cooldown = 20
if self.facing_right:
self.attack_box = pygame.Rect(self.rect.right, self.rect.y + 40, 80, 80)
else:
self.attack_box = pygame.Rect(self.rect.left - 80, self.rect.y + 40, 80, 80)
# - Taimeris -
def update(self):
if self.attack_cooldown > 0: self.attack_cooldown -= 1
else: self.attacking = False
if self.hit_timer > 0: self.hit_timer -= 1
# - Tēla darbība uz ekranā -
def draw(self, surface):
img_to_draw = pygame.transform.flip(self.image, not self.facing_right, False)
surface.blit(img_to_draw, self.rect)
if self.attacking:
surface.blit(BOOM_IMG, self.attack_box)
def take_damage(self, amount):
self.health -= amount
self.hit_timer = 10
self.vel_y = -5
if self.rect.centerx < WIDTH // 2: self.rect.x -= 20
else: self.rect.x += 20
# --- Boss ---
class Boss(pygame.sprite.Sprite):
def __init__(self, image):
super().__init__()
self.image = image
self.rect = self.image.get_rect()
self.rect.center = (WIDTH // 2, HEIGHT // 2)
self.rect.bottom = HEIGHT - 50
self.health = 150
self.max_health = 150
self.speed = 3
self.damage = 3
self.vel_y = 0
self.gravity = 0.8
self.on_ground = False
self.facing_right = True
self.attacking = False
self.attack_cooldown = 0
self.attack_box = pygame.Rect(0, 0, 0, 0)
self.hit_timer = 0
self.target = None
def ai_move(self, targets):
closest_dist = 99999
target = None
# - Attālums līdz target -
for t in targets:
if t.health > 0:
dist = abs(self.rect.centerx - t.rect.centerx)
if dist < closest_dist:
closest_dist = dist
target = t
if target:
self.target = target
if target.rect.centerx < self.rect.centerx:
self.rect.x -= self.speed
self.facing_right = False
else:
self.rect.x += self.speed
self.facing_right = True
if closest_dist < 180:
self.attack()
self.vel_y += self.gravity
self.rect.y += self.vel_y
if self.rect.bottom >= HEIGHT - 50:
self.rect.bottom = HEIGHT - 50
self.vel_y = 0
self.on_ground = True
def attack(self):
if self.attack_cooldown == 0:
self.attacking = True
self.attack_cooldown = 45
if self.facing_right:
self.attack_box = pygame.Rect(self.rect.right, self.rect.y + 80, 160, 160)
else:
self.attack_box = pygame.Rect(self.rect.left - 160, self.rect.y + 80, 160, 160)
def update(self):
if self.attack_cooldown > 0: self.attack_cooldown -= 1
else: self.attacking = False
if self.hit_timer > 0: self.hit_timer -= 1
def draw(self, surface):
img_to_draw = pygame.transform.flip(self.image, not self.facing_right, False)
surface.blit(img_to_draw, self.rect)
if self.attacking:
surface.blit(BOOM_IMG_LARGE, self.attack_box)
def take_damage(self, amount):
self.health -= amount
self.hit_timer = 10
if self.rect.centerx < WIDTH // 2: self.rect.x -= 5
else: self.rect.x += 5
def draw_background(surface, bg_name):
img = bg_images.get(bg_name, list(bg_images.values())[0])
surface.blit(img, (0, 0))
# --- Dialogi ---
class DialogueManager:
def __init__(self):
self.lines = ["SAGATAVOJIES CĪŅAI!", "Kurš šodien uzvarēs?", "Cīnies ar godu!", "Parādi savas kustības!"]
self.current_text = random.choice(self.lines)
self.active = False
self.timer = 0
def start(self, is_boss=False):
self.active = True
self.timer = pygame.time.get_ticks()
if is_boss:
self.current_text = "BOSS APPROACHING!"
else:
self.current_text = random.choice(self.lines)
def draw(self, surface):
if not self.active: return
text_surf = FONT_SMALL.render(self.current_text, True, YELLOW)
text_width = text_surf.get_width()
text_height = text_surf.get_height()
padding_x = 40
padding_y = 25
box_w = text_width + padding_x * 2
box_h = text_height + padding_y * 2
box_rect = pygame.Rect(WIDTH//2 - box_w//2, HEIGHT//2 - box_h//2, box_w, box_h)
pygame.draw.rect(surface, BLACK, box_rect)
pygame.draw.rect(surface, WHITE, box_rect, 4)
surface.blit(text_surf, (box_rect.centerx - text_width//2, box_rect.centery - text_height//2))
sub_surf = FONT_TINY.render("Nospiediet [SPACE] lai saktu", True, WHITE)
surface.blit(sub_surf, (WIDTH//2 - sub_surf.get_width()//2, box_rect.bottom + 15))
# --- Galvenā Spēle ---
def main():
global STATE, P1_CHAR_INDEX, P2_CHAR_INDEX, SELECTED_BG, GAME_MODE, sound_on
controls_p1 = {'left': pygame.K_a, 'right': pygame.K_d, 'jump': pygame.K_w, 'attack': pygame.K_SPACE}
controls_p2 = {'left': pygame.K_LEFT, 'right': pygame.K_RIGHT, 'jump': pygame.K_UP, 'attack': pygame.K_RETURN}
dialogue_mgr = DialogueManager()
# Pogas (novietotas centrā)
btn_x = WIDTH//2 - 100
menu_buttons = [
Button(btn_x, 180, 200, 50, "PvP", YELLOW, RED, "START_PVP"),
Button(btn_x, 240, 200, 50, "Cīna ar Bossu", YELLOW, RED, "START_BOSS"),
Button(btn_x, 300, 200, 50, "Tēlu Izvēle", YELLOW, RED, "CHARS"),
Button(btn_x, 360, 200, 50, "Fona Izvēle", YELLOW, RED, "BG"),
Button(btn_x, 420, 200, 50, "Kontroles", YELLOW, RED, "INSTRUCTIONS"),
]
bg_buttons = [
Button(150, 200, 200, 50, "Pludmale", WHITE, YELLOW, "BEACH"),
Button(412, 200, 200, 50, "Nakts iela", WHITE, YELLOW, "EVENINGSTREET"),
Button(674, 200, 200, 50, "Tirgus", WHITE, YELLOW, "MARKET"),
Button(150, 280, 200, 50, "Restorāns", WHITE, YELLOW, "RESTAURANT"),
Button(412, 280, 200, 50, "Sakuras iela", WHITE, YELLOW, "SAKURASTREET"),
Button(674, 280, 200, 50, "Ports", WHITE, YELLOW, "SHIP"),
Button(WIDTH//2 - 100, 360, 200, 50, "Ielu tirgus", WHITE, YELLOW, "STREETMARKETS"),
Button(WIDTH//2 - 100, 450, 200, 50, "Atpakaļ", GRAY, WHITE, "BACK")
]
back_btn_chars = Button(WIDTH//2 - 100, HEIGHT - 80, 200, 50, "Atpakal", GRAY, WHITE, "BACK")
back_btn_inst = Button(WIDTH//2 - 100, HEIGHT - 80, 200, 50, "Atpakal", GRAY, WHITE, "BACK")
fighter1 = None
fighter2 = None
boss = None
p1_score = 0
p2_score = 0
current_round = 1
round_winner_name = ""
match_winner_name = ""
state_timer = 0
# --- SKAŅAS POGA ---
mute_btn_rect = pygame.Rect(20, HEIGHT - 35, 140, 25)
run = True
while run:
CLOCK.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# --- Skaņas pogas loģika (LABOTS) ---
if event.type == pygame.MOUSEBUTTONDOWN:
if mute_btn_rect.collidepoint(event.pos):
sound_on = not sound_on
# Mainām skaļumu tikai tad, ja audio sistēma ir inicializēta
if mixer_initialized:
if sound_on:
pygame.mixer.music.set_volume(0.5)
else:
pygame.mixer.music.set_volume(0)
if STATE == "MENU":
for btn in menu_buttons:
if btn.is_clicked(event):
if btn.action_code == "START_PVP":
GAME_MODE = "PVP"
p1_score = 0
p2_score = 0
current_round = 1
fighter1 = Fighter(200, 300, CHARACTERS[P1_CHAR_INDEX], True, controls_p1)
fighter2 = Fighter(800, 300, CHARACTERS[P2_CHAR_INDEX], False, controls_p2)
dialogue_mgr.start(is_boss=False)
STATE = "DIALOGUE"
elif btn.action_code == "START_BOSS":
GAME_MODE = "BOSS"
fighter1 = Fighter(150, 300, CHARACTERS[P1_CHAR_INDEX], True, controls_p1)
fighter2 = Fighter(300, 300, CHARACTERS[P2_CHAR_INDEX], True, controls_p2)
boss_img = random.choice(BOSS_IMAGES)
boss = Boss(boss_img)
dialogue_mgr.start(is_boss=True)
STATE = "DIALOGUE"
elif btn.action_code == "CHARS":
STATE = "CHAR_SELECT"
elif btn.action_code == "BG":
STATE = "BG_SELECT"
elif btn.action_code == "INSTRUCTIONS":
STATE = "INSTRUCTIONS"
elif STATE == "CHAR_SELECT":
icon_w = 100
gap = 10
total_w = len(CHARACTERS) * icon_w + (len(CHARACTERS)-1) * gap
start_x = (WIDTH - total_w) // 2
y_p1 = 150
for i, char in enumerate(CHARACTERS):
icon_rect = pygame.Rect(start_x + i * (icon_w + gap), y_p1, icon_w, icon_w)
if event.type == pygame.MOUSEBUTTONDOWN and icon_rect.collidepoint(event.pos):
P1_CHAR_INDEX = i
y_p2 = 350
for i, char in enumerate(CHARACTERS):
icon_rect = pygame.Rect(start_x + i * (icon_w + gap), y_p2, icon_w, icon_w)
if event.type == pygame.MOUSEBUTTONDOWN and icon_rect.collidepoint(event.pos):
P2_CHAR_INDEX = i
if back_btn_chars.is_clicked(event):
STATE = "MENU"
elif STATE == "BG_SELECT":
for btn in bg_buttons:
if btn.is_clicked(event):
if btn.action_code == "BACK":
STATE = "MENU"
else:
SELECTED_BG = btn.action_code
elif STATE == "INSTRUCTIONS":
if back_btn_inst.is_clicked(event):
STATE = "MENU"
elif STATE == "DIALOGUE":
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
dialogue_mgr.active = False
state_timer = pygame.time.get_ticks()
STATE = "ROUND_START"
elif STATE == "GAME":
if event.type == pygame.KEYDOWN:
if event.key == fighter1.controls['attack']: fighter1.attack()
if event.key == fighter2.controls['attack']: fighter2.attack()
elif STATE == "GAMEOVER":
if event.type == pygame.KEYDOWN and event.key == pygame.K_r:
STATE = "MENU"
# --- Zīmēšana un Loģika ---
if STATE == "MENU":
SCREEN.fill(BLACK)
SCREEN.blit(menupic1, (0, 0))
SCREEN.blit(menupic2, (WIDTH - MENU_PIC_WIDTH, 0))
title_text = "PIXEL KOMBAT"
shadow_text = FONT_BIG.render(title_text, True, (180, 0, 0))
SCREEN.blit(shadow_text, (WIDTH//2 - shadow_text.get_width()//2 + 3, 53))
main_text = FONT_BIG.render(title_text, True, YELLOW)
SCREEN.blit(main_text, (WIDTH//2 - main_text.get_width()//2, 50))
for btn in menu_buttons: btn.draw(SCREEN)
cp_text = "© PIXEL KOMBAT 2026"
cp_surf = FONT_TINY.render(cp_text, True, WHITE)
SCREEN.blit(cp_surf, (WIDTH//2 - cp_surf.get_width()//2, HEIGHT - 30))
elif STATE == "INSTRUCTIONS":
SCREEN.fill(BLACK)
title = FONT_BIG.render("KONTROLES", True, YELLOW)
SCREEN.blit(title, (WIDTH//2 - title.get_width()//2, 30))
p1_center_x = WIDTH // 2 - 200
p2_center_x = WIDTH // 2 + 200
title_y = 170
key_row1_y = 240
key_row2_y = 320
key_row3_y = 420
p1_title = FONT_MED.render("PLAYER 1", True, BLUE)
SCREEN.blit(p1_title, (p1_center_x - p1_title.get_width()//2, title_y))
draw_key_visual(SCREEN, p1_center_x - 35, key_row1_y, 70, 50, "W", "LEKT", BLUE)
draw_key_visual(SCREEN, p1_center_x - 35 - 80, key_row2_y, 70, 50, "A", "KREISI", BLUE)
draw_key_visual(SCREEN, p1_center_x - 35 + 80, key_row2_y, 70, 50, "D", "LABI", BLUE)
space_w = 200
draw_key_visual(SCREEN, p1_center_x - space_w//2, key_row3_y, space_w, 50, "SPACE", "SIT", RED)
p2_title = FONT_MED.render("PLAYER 2", True, RED)
SCREEN.blit(p2_title, (p2_center_x - p2_title.get_width()//2, title_y))
draw_key_visual(SCREEN, p2_center_x - 35, key_row1_y, 70, 50, "UP", "LEKT", RED)
draw_key_visual(SCREEN, p2_center_x - 35 - 80, key_row2_y, 70, 50, "LEFT", "KREISI", RED)
draw_key_visual(SCREEN, p2_center_x - 35 + 80, key_row2_y, 70, 50, "RIGHT", "LABI", RED)
enter_w = 150
draw_key_visual(SCREEN, p2_center_x - enter_w//2, key_row3_y, enter_w, 50, "ENTER", "SIT", BLUE)
back_btn_inst.draw(SCREEN)
elif STATE == "CHAR_SELECT":
SCREEN.fill(DARK_GRAY)
title1 = FONT_SMALL.render("IZVELIES TELU", True, WHITE)
SCREEN.blit(title1, (WIDTH//2 - title1.get_width()//2, 30))
icon_w = 100
gap = 10
total_w = len(CHARACTERS) * icon_w + (len(CHARACTERS)-1) * gap
start_x = (WIDTH - total_w) // 2
p1_text = FONT_SMALL.render("PLAYER 1", True, CHARACTERS[P1_CHAR_INDEX]['color'])
SCREEN.blit(p1_text, (WIDTH//2 - p1_text.get_width()//2, 110))
y_p1 = 150
for i, char in enumerate(CHARACTERS):
icon_rect = pygame.Rect(start_x + i * (icon_w + gap), y_p1, icon_w, icon_w)
SCREEN.blit(char['icon'], icon_rect.topleft)
border_color = WHITE if i != P1_CHAR_INDEX else YELLOW
border_width = 2 if i != P1_CHAR_INDEX else 4
pygame.draw.rect(SCREEN, border_color, icon_rect, border_width)
p2_text = FONT_SMALL.render("PLAYER 2", True, CHARACTERS[P2_CHAR_INDEX]['color'])
SCREEN.blit(p2_text, (WIDTH//2 - p2_text.get_width()//2, 300))
y_p2 = 340
for i, char in enumerate(CHARACTERS):
icon_rect = pygame.Rect(start_x + i * (icon_w + gap), y_p2, icon_w, icon_w)
SCREEN.blit(char['icon'], icon_rect.topleft)
border_color = WHITE if i != P2_CHAR_INDEX else YELLOW
border_width = 2 if i != P2_CHAR_INDEX else 4
pygame.draw.rect(SCREEN, border_color, icon_rect, border_width)
back_btn_chars.draw(SCREEN)
elif STATE == "BG_SELECT":
SCREEN.fill(BLACK)
title = FONT_MED.render("IZVELIES VIDI", True, WHITE)
SCREEN.blit(title, (WIDTH//2 - title.get_width()//2, 100))
for btn in bg_buttons:
btn.draw(SCREEN)
elif STATE == "DIALOGUE":
draw_background(SCREEN, SELECTED_BG)
dialogue_mgr.draw(SCREEN)
elif STATE == "ROUND_START":
draw_background(SCREEN, SELECTED_BG)
fighter1.draw(SCREEN)
fighter2.draw(SCREEN)
if GAME_MODE == "BOSS" and boss:
boss.draw(SCREEN)
if GAME_MODE == "BOSS" and boss:
pygame.draw.rect(SCREEN, BLACK, (WIDTH//2 - 302, 18, 604, 34))
pygame.draw.rect(SCREEN, RED, (WIDTH//2 - 300, 20, 600, 30))
w = (boss.health / boss.max_health) * 600
pygame.draw.rect(SCREEN, PURPLE, (WIDTH//2 - 300, 20, w, 30))
pygame.draw.rect(SCREEN, WHITE, (WIDTH//2 - 300, 20, 600, 30), 2)
else:
pygame.draw.rect(SCREEN, BLACK, (20, 20, 400, 40))
pygame.draw.rect(SCREEN, fighter1.color_accent, (20, 20, 400, 40))
pygame.draw.rect(SCREEN, WHITE, (20, 20, 400, 40), 2)
pygame.draw.rect(SCREEN, BLACK, (WIDTH-420, 20, 400, 40))
pygame.draw.rect(SCREEN, fighter2.color_accent, (WIDTH-420, 20, 400, 40))
pygame.draw.rect(SCREEN, WHITE, (WIDTH-420, 20, 400, 40), 2)
elapsed = pygame.time.get_ticks() - state_timer
if elapsed < 1500:
txt = FONT_MED.render(f"ROUND {current_round}" if GAME_MODE == "PVP" else "BOSS FIGHT", True, YELLOW)
SCREEN.blit(txt, (WIDTH//2 - txt.get_width()//2, HEIGHT//2 - 50))
elif elapsed < 3000:
txt = FONT_BIG.render("FIGHT!", True, WHITE)
offset_x = random.randint(-2, 2)
offset_y = random.randint(-2, 2)
SCREEN.blit(txt, (WIDTH//2 - txt.get_width()//2 + offset_x, HEIGHT//2 - 50 + offset_y))
else:
STATE = "GAME"
elif STATE == "GAME":
keys = pygame.key.get_pressed()
fighter1.move(keys)
fighter2.move(keys)
fighter1.update()
fighter2.update()
if GAME_MODE == "PVP":
# P1 sit P2
if fighter1.attacking and fighter1.attack_box.colliderect(fighter2.rect):
if fighter2.hit_timer == 0:
fighter2.take_damage(5)
# SKAŅA: P1 sitiena skaņa (pārbaude vai ir)
if sound_on and hit_sound:
hit_sound.play()
# P2 sit P1
if fighter2.attacking and fighter2.attack_box.colliderect(fighter1.rect):
if fighter1.hit_timer == 0:
fighter1.take_damage(5)
# SKAŅA: P2 sitiena skaņa (pārbaude vai ir)
if sound_on and hit_sound:
hit_sound.play()
if fighter1.health <= 0 or fighter2.health <= 0:
if fighter2.health <= 0:
p1_score += 1
round_winner_name = "PLAYER 1"
else:
p2_score += 1
round_winner_name = "PLAYER 2"
state_timer = pygame.time.get_ticks()
STATE = "ROUND_OVER"
elif GAME_MODE == "BOSS" and boss:
targets = [fighter1, fighter2]
boss.ai_move(targets)
boss.update()
# Spēlētāji sit Bosu
if fighter1.attacking and fighter1.attack_box.colliderect(boss.rect):
if boss.hit_timer == 0:
boss.take_damage(5)
if sound_on and hit_sound: hit_sound.play()
if fighter2.attacking and fighter2.attack_box.colliderect(boss.rect):
if boss.hit_timer == 0:
boss.take_damage(5)
if sound_on and hit_sound: hit_sound.play()
# Boss sit spēlētājus
if boss.attacking:
if boss.attack_box.colliderect(fighter1.rect):
if fighter1.hit_timer == 0: fighter1.take_damage(boss.damage)
if boss.attack_box.colliderect(fighter2.rect):
if fighter2.hit_timer == 0: fighter2.take_damage(boss.damage)
if boss.health <= 0:
match_winner_name = "PLAYERS"
save_highscore("Players (Team)")
STATE = "GAMEOVER"
if fighter1.health <= 0 and fighter2.health <= 0:
match_winner_name = "BOSS"
STATE = "GAMEOVER"
draw_background(SCREEN, SELECTED_BG)
fighter1.draw(SCREEN)
fighter2.draw(SCREEN)
if GAME_MODE == "BOSS" and boss:
boss.draw(SCREEN)
if GAME_MODE == "BOSS" and boss:
pygame.draw.rect(SCREEN, BLACK, (WIDTH//2 - 302, 18, 604, 34))
pygame.draw.rect(SCREEN, RED, (WIDTH//2 - 300, 20, 600, 30))
w = (boss.health / boss.max_health) * 600
pygame.draw.rect(SCREEN, PURPLE, (WIDTH//2 - 300, 20, w, 30))
pygame.draw.rect(SCREEN, WHITE, (WIDTH//2 - 300, 20, 600, 30), 2)
pygame.draw.rect(SCREEN, BLACK, (20, HEIGHT - 60, 200, 20))
pygame.draw.rect(SCREEN, fighter1.color_accent, (20, HEIGHT - 60, (fighter1.health/100)*200, 20))
pygame.draw.rect(SCREEN, WHITE, (20, HEIGHT - 60, 200, 20), 2)
pygame.draw.rect(SCREEN, BLACK, (WIDTH-220, HEIGHT - 60, 200, 20))
pygame.draw.rect(SCREEN, fighter2.color_accent, (WIDTH-220, HEIGHT - 60, (fighter2.health/100)*200, 20))
pygame.draw.rect(SCREEN, WHITE, (WIDTH-220, HEIGHT - 60, 200, 20), 2)
else:
pygame.draw.rect(SCREEN, BLACK, (20, 20, 400, 40))
pygame.draw.rect(SCREEN, RED, (20, 20, 400, 40))
pygame.draw.rect(SCREEN, fighter1.color_accent, (20, 20, (fighter1.health/100)*400, 40))
pygame.draw.rect(SCREEN, WHITE, (20, 20, 400, 40), 2)
pygame.draw.rect(SCREEN, BLACK, (WIDTH-420, 20, 400, 40))
pygame.draw.rect(SCREEN, RED, (WIDTH-420, 20, 400, 40))
pygame.draw.rect(SCREEN, fighter2.color_accent, (WIDTH-420, 20, (fighter2.health/100)*400, 40))
pygame.draw.rect(SCREEN, WHITE, (WIDTH-420, 20, 400, 40), 2)
score_text = FONT_MED.render(f"{p1_score} - {p2_score}", True, WHITE)
SCREEN.blit(score_text, (WIDTH//2 - score_text.get_width()//2, 25))
elif STATE == "ROUND_OVER":
draw_background(SCREEN, SELECTED_BG)
fighter1.draw(SCREEN)
fighter2.draw(SCREEN)
pygame.draw.rect(SCREEN, BLACK, (20, 20, 400, 40))
pygame.draw.rect(SCREEN, fighter1.color_accent, (20, 20, 400, 40))
pygame.draw.rect(SCREEN, WHITE, (20, 20, 400, 40), 2)
pygame.draw.rect(SCREEN, BLACK, (WIDTH-420, 20, 400, 40))
pygame.draw.rect(SCREEN, fighter2.color_accent, (WIDTH-420, 20, 400, 40))
pygame.draw.rect(SCREEN, WHITE, (WIDTH-420, 20, 400, 40), 2)
score_text = FONT_MED.render(f"{p1_score} - {p2_score}", True, WHITE)
SCREEN.blit(score_text, (WIDTH//2 - score_text.get_width()//2, 25))
txt1 = FONT_MED.render(f"{round_winner_name} WINS!", True, YELLOW)
SCREEN.blit(txt1, (WIDTH//2 - txt1.get_width()//2, HEIGHT//2 - 50))
elapsed = pygame.time.get_ticks() - state_timer
if elapsed > 2000:
if p1_score == 3 or p2_score == 3:
match_winner_name = "PLAYER 1" if p1_score == 3 else "PLAYER 2"
save_highscore(match_winner_name)
STATE = "GAMEOVER"
else:
current_round += 1
fighter1.reset_round()
fighter2.reset_round()
state_timer = pygame.time.get_ticks()
STATE = "ROUND_START"
elif STATE == "GAMEOVER":
SCREEN.fill(BLACK)
if GAME_MODE == "BOSS":
if match_winner_name == "PLAYERS":
txt = FONT_BIG.render("PLAYERS WIN!", True, GREEN)
else:
txt = FONT_BIG.render("PLAYERS LOSE!", True, RED)
SCREEN.blit(txt, (WIDTH//2 - txt.get_width()//2, 150))
else:
txt = FONT_BIG.render(f"{match_winner_name} WINS!", True, YELLOW)
SCREEN.blit(txt, (WIDTH//2 - txt.get_width()//2, 100))
hs_title = FONT_MED.render("HIGH SCORES", True, WHITE)
SCREEN.blit(hs_title, (WIDTH//2 - hs_title.get_width()//2, 200))
scores = load_highscores()
scores.reverse()
y_offset = 260
for i, score in enumerate(scores[:5]):
if score == match_winner_name:
color = YELLOW
else:
color = WHITE
s_text = FONT_SMALL.render(f"{i+1}. {score}", True, color)
SCREEN.blit(s_text, (WIDTH//2 - s_text.get_width()//2, y_offset))
y_offset += 35
restart = FONT_SMALL.render("Nospied [R] atgriezties uz izvelni", True, GRAY)
SCREEN.blit(restart, (WIDTH//2 - restart.get_width()//2, HEIGHT - 80))
# --- Zīmēt skaņas pogu ---
btn_color = GREEN if sound_on else RED
pygame.draw.rect(SCREEN, DARK_GRAY, mute_btn_rect)
pygame.draw.rect(SCREEN, btn_color, mute_btn_rect, 2)
btn_label = "Skaņa: ON" if sound_on else "Skaņa: OFF"
text_surf = FONT_TINY.render(btn_label, True, btn_color)
text_x = mute_btn_rect.centerx - text_surf.get_width() // 2
text_y = mute_btn_rect.centery - text_surf.get_height() // 2
SCREEN.blit(text_surf, (text_x, text_y))
# --- Zīmēt kursoru ---
if CURSOR_IMG:
mouse_pos = pygame.mouse.get_pos()
SCREEN.blit(CURSOR_IMG, mouse_pos)
pygame.display.update()
pygame.quit()
sys.exit()
if __name__ == "__main__":
main()