Menu done, 3 gamemodes done, 3 enemies spawning done. Deathscreen sooon maybe

This commit is contained in:
kojtech 2026-10-25 21:22:56 +01:00
commit 59efcba73e
8 changed files with 257 additions and 69 deletions

BIN
background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
button.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
button_hover.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

216
main.py
View file

@ -11,6 +11,8 @@ font = pygame.font.SysFont(None, 36)
big_font = pygame.font.SysFont(None, 64)
small_font = pygame.font.SysFont(None, 26)
tiny_font = pygame.font.SysFont(None, 20)
MENU_OPTIONS = ["Play", "Quit"]
MODE_NAMES = ["easy", "medium", "hard"]
@ -33,7 +35,7 @@ class ChaserEnemy:
self.rect.y = random.randint(0, HEIGHT - 36)
if abs(self.rect.x - avoid_rect.x) > 150 or abs(self.rect.y - avoid_rect.y) > 150:
break
self.speed = 2
self.speed = 1
self.spawn_timer = 60
def update(self, target):
@ -46,6 +48,10 @@ class ChaserEnemy:
elif self.rect.centery > target.centery:
self.rect.y -= self.speed
class DasherEnemy:
WAIT_BEFORE_FIRST_DASH = 90
DASH_FRAMES = 30
WAIT_AFTER_DASH = 120
DASH_SPEED = 6
def __init__(self, avoid_rect):
self.rect = pygame.Rect(0, 0, 36, 36)
while True:
@ -58,29 +64,36 @@ class DasherEnemy:
self.vx = 0
self.vy = 0
self.state = "wait"
self.timer = 90
self.timer = self.WAIT_BEFORE_FIRST_DASH
self.spawn_timer = 60
def update(self, target):
self.timer -= 1
if self.state == "wait":
if self.timer > 0:
return
dx = target.centerx - self.rect.centerx
dy = target.centery - self.rect.centery
dist = max(1, (dx ** 2 + dy ** 2) ** 0.5)
self.vx = dx / dist * 9
self.vy = dy / dist * 9
self.vx = dx / dist * self.DASH_SPEED
self.vy = dy / dist * self.DASH_SPEED
self.state = "dash"
self.timer = 30
else:
self.timer = self.DASH_FRAMES
return
self.x += self.vx
self.y += self.vy
self.rect.x = int(self.x)
self.rect.y = int(self.y)
self.rect.clamp_ip(screen.get_rect())
self.x, self.y = float(self.rect.x), float(self.rect.y)
if self.timer <= 0:
self.state = "wait"
self.timer = 90
self.vx = 0
self.vy = 0
self.timer = self.WAIT_AFTER_DASH
class BouncerEnemy:
def __init__(self, avoid_rect):
self.rect = pygame.Rect(0, 0, 36, 36)
@ -119,6 +132,12 @@ Chaser_img = pygame.transform.scale(Chaser_img, (30, 45))
Dasher_img = pygame.image.load("Dasher.png").convert_alpha()
Dasher_img = pygame.transform.scale(Dasher_img, (30, 45))
ENEMY_IMAGES = {
"Bouncer": Bouncer_img,
"Dasher": Dasher_img,
"Chaser": Chaser_img
}
sugar_img = pygame.image.load("honey.png").convert_alpha()
sugar_img = pygame.transform.scale(sugar_img, (50, 50))
@ -127,6 +146,19 @@ sugar_img = pygame.transform.scale(sugar_img, (50, 50))
heart_img = pygame.image.load("Heart.png").convert_alpha()
heart_img = pygame.transform.scale(heart_img,(40, 40))
background_img = pygame.image.load("background.png").convert_alpha()
background_img = pygame.transform.scale(background_img, (WIDTH, HEIGHT))
title_img = pygame.image.load("titles.png").convert_alpha()
button_img = pygame.image.load("button.png").convert_alpha()
button_hover_img = pygame.image.load("button_hover.png").convert_alpha()
quit_img = pygame.image.load("quit.png").convert_alpha()
quit_hover_img = pygame.image.load("quit_hover.png").convert_alpha()
panel_img = pygame.image.load("panel.png").convert_alpha()
def new_sugar():
return pygame.Rect(random.randint(0, WIDTH - 20),
@ -152,6 +184,10 @@ def game_screen(mode):
if event.type == pygame.QUIT:
return "quit", score
if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
return "menu", score
#movement
keys = pygame.key.get_pressed()
@ -189,19 +225,19 @@ def game_screen(mode):
sugar = new_sugar()
if score % cfg["spawn_every"] == 0 and cfg["enemy_pool"]:
enemy_name = random.choice(cfg["enemy_pool"])
Enemies.append(ENEMY_CLASSES[enemy_name](player))
enemy = ENEMY_CLASSES[enemy_name](player)
enemy.image = ENEMY_IMAGES[enemy_name]
Enemies.append(enemy)
screen.fill((255, 228, 240)) # screen
screen.blit(sugar_img, sugar) #sugar
screen.blit(player_img, player) #player
if hit_timer % 10 < 5:
screen.blit(player_img, player)
text = font.render(f"score: {score}", True, (90, 30, 60))
screen.blit(text, (10, 10))
for enemy in Enemies:
if enemy.spawn_timer % 10 < 5:
screen.blit(Bouncer_img, enemy.rect)
screen.blit(enemy.image, enemy.image.get_rect(center=enemy.rect.center))
screen.blit(player_img, player)
if hit_timer > 0 and hit_timer % 10 < 5:
red = player_img.copy()
@ -212,9 +248,161 @@ def game_screen(mode):
pygame.display.flip()
clock.tick(60)
pygame.quit()
class MenuButton:
def __init__(self, center, action, image, hover_image):
self.action = action
self.image = image
self.hover_image = hover_image
self.rect = self.image.get_rect(center = center)
def hovered(self, mouse_pos):
return self.rect.collidepoint(mouse_pos)
def draw(self, surface, highlighted):
picture = self.hover_image if highlighted else self.image
surface.blit(picture, self.rect)
def menu_screen():
selected = 0
buttons = [
MenuButton((WIDTH // 2, 250), "mode", button_img, button_hover_img),
MenuButton((WIDTH // 2, 340), "quit", quit_img, quit_hover_img),
]
while True:
for
for event in pygame.event.get():
if event.type == pygame.QUIT:
return "quit"
if event.type == pygame.KEYDOWN:
if event.key in (pygame.K_UP, pygame.K_w):
selected = (selected - 1) % len(buttons)
elif event.key in (pygame.K_DOWN, pygame.K_s):
selected = (selected + 1) % len(buttons)
elif event.key == pygame.K_RETURN:
if selected == -1:
selected = 0
return buttons [selected].action
elif event.key == pygame.K_ESCAPE:
return "quit"
if event.type == pygame.MOUSEMOTION:
selected = -1
for i, button in enumerate(buttons):
if button.hovered(event.pos):
selected = i
if event.type == pygame.WINDOWLEAVE:
selected = -1
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
for button in buttons:
if button.hovered(event.pos):
return button.action
screen.blit(background_img, (0, 0))
screen.blit(title_img, title_img.get_rect(center=(WIDTH // 2, 80)))
for i, button in enumerate(buttons):
button.draw(screen, i == selected)
pygame.display.flip()
clock.tick(60)
def mode_screen():
selected = 0
hovered = -1
play_button = MenuButton((210, 405), "game", button_img, button_hover_img)
back_button = MenuButton((430, 405), "menu", quit_img, quit_hover_img)
buttons = [play_button, back_button]
panel_rect = panel_img.get_rect(center=(WIDTH // 2, 225))
slot_rects = [
pygame.Rect(panel_rect.x + 22, panel_rect.y + 22, 78, 68),
pygame.Rect(panel_rect.x + 133, panel_rect.y + 22, 77, 68),
pygame.Rect(panel_rect.x + 234, panel_rect.y + 28, 73, 66),
]
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return "quit", None
if event.type == pygame.KEYDOWN:
if event.key in (pygame.K_LEFT, pygame.K_a):
selected = (selected - 1) % len(MODE_NAMES)
elif event.key in (pygame.K_RIGHT, pygame.K_d):
selected = (selected + 1) % len(MODE_NAMES)
elif event.key == pygame.K_RETURN:
return "game", MODE_NAMES[selected]
elif event.key == pygame.K_ESCAPE:
return "menu", None
if event.type == pygame.MOUSEMOTION:
hovered = -1
for i, button in enumerate(buttons):
if button.hovered(event.pos):
hovered = i
if event.type == pygame.WINDOWLEAVE:
hovered = -1
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
for i, slot in enumerate(slot_rects):
if slot.collidepoint(event.pos):
selected = i
for button in buttons:
if button.hovered(event.pos):
if button.action == "game":
return "game", MODE_NAMES[selected]
return "menu", None
screen.blit(background_img, (0, 0))
screen.blit(title_img, title_img.get_rect(center=(WIDTH // 2, 70)))
pygame.draw.rect(screen, (255, 129, 195), panel_rect)
screen.blit(panel_img, panel_rect)
for i, slot in enumerate(slot_rects):
fill = (255, 200, 225) if i == selected else (227, 89, 161)
pygame.draw.rect(screen, fill, slot.inflate (-4, -4), border_radius=6)
for i, slot in enumerate(slot_rects):
name = small_font.render(MODE_NAMES[i].upper(), True, (255, 240, 8))
screen.blit(name, name.get_rect(center=slot.center))
cfg = MODES[MODE_NAMES[selected]]
first_sentence, second_sentence = cfg["desc"].split(". ", 1)
line1 = tiny_font.render(first_sentence + ".", True, (255, 240, 8))
line2 = tiny_font.render(second_sentence, True, (255, 240, 8))
screen.blit(line1, line1.get_rect(center=(panel_rect.centerx, panel_rect.top + 108)))
screen.blit(line2, line2.get_rect(center=(panel_rect.centerx, panel_rect.top + 132)))
for i, button in enumerate(buttons):
button.draw(screen, i == hovered)
pygame.display.flip()
clock.tick(60)
if __name__ == "__main__":
state = "menu"
mode = None
score = 0
while state != "quit":
if state == "menu":
state = menu_screen()
elif state == "mode":
state, mode = mode_screen()
elif state == "game":
state, score = game_screen(mode)
elif state == "gameover":
print(f"Game Over - score: {score}")
state = "menu"
pygame.quit()

BIN
panel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 B

BIN
quit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
quit_hover.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
titles.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB