cdec/water-game.py
2025-10-12 11:56:02 +02:00

186 lines
6.4 KiB
Python

import sys
import random
import pygame
import numpy as np
import rasterio
from player import Player
from enemy import Enemy
from tapwater import TapWater
from settings import PLAYER_SIZE, MAP_PATH, WIDTH, HEIGHT, MINIMAP_MARGIN
DEBUG = False
MAX_AMMO = 5
trinkbrunnen_positions = np.load('trinkbrunnen_pixel_positions.npy')
# Nach dem Laden der Positionen:
used_brunnen = [False] * len(trinkbrunnen_positions)
pygame.init()
# logo_img = pygame.image.load("images/logo.png")
# pygame.display.set_icon(logo_img)
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Wasser der Regierung")
logo_img = pygame.image.load("images/Wasser_der_Regierung.PNG")
pygame.display.set_icon(logo_img)
def load_map(path):
try:
arr = rasterio.open(path).read(1)
arr = np.nan_to_num(arr - 272.15, nan=0)
arr = np.clip(arr, np.percentile(arr, 5), np.percentile(arr, 95))
arr = ((arr - arr.min()) / (arr.max() - arr.min()) * 255).astype(np.uint8)
arr = np.stack([arr, arr, arr], -1)
surf = pygame.surfarray.make_surface(arr)
return surf, arr.shape[1], arr.shape[0]
except Exception as e:
print(f"Map load error: {e}")
return None, WIDTH, HEIGHT
map_surface, MAP_W, MAP_H = load_map(MAP_PATH)
DIST_FACTOR = 2.0 # 2.0 = doppelte Entfernung, 1.0 = Standard
# Karte vergrößern
scaled_map = pygame.transform.smoothscale(map_surface, (int(MAP_W * DIST_FACTOR), int(MAP_H * DIST_FACTOR)))
WIN.blit(scaled_map, (0, 0))
MINIMAP_WIDTH = 200
MINIMAP_HEIGHT = int(MAP_H / MAP_W * MINIMAP_WIDTH)
def draw_minimap(win, map_surface, player, enemies, bottles):
mini = pygame.transform.smoothscale(map_surface, (MINIMAP_WIDTH, MINIMAP_HEIGHT))
win.blit(mini, (WIDTH - MINIMAP_WIDTH - MINIMAP_MARGIN, MINIMAP_MARGIN))
def map2mini(x, y):
mx = int(x / MAP_W * MINIMAP_WIDTH)
my = int(y / MAP_H * MINIMAP_HEIGHT)
return WIDTH - MINIMAP_WIDTH - MINIMAP_MARGIN + mx, MINIMAP_MARGIN + my
pygame.draw.circle(win, (0, 255, 0), map2mini(player.x + PLAYER_SIZE // 2, player.y + PLAYER_SIZE // 2), 5)
for enemy in enemies:
color = (0, 128, 255) if enemy.is_human else (255, 0, 0) if enemy.controlled else (200, 200, 0)
ex, ey = map2mini(enemy.x + PLAYER_SIZE // 4, enemy.y + PLAYER_SIZE // 4)
pygame.draw.circle(win, color, (ex, ey), 5)
for bottle in bottles:
pygame.draw.circle(win, (0, 180, 255), map2mini(bottle.x, bottle.y), 3)
def show_win_screen(win):
win.fill((40, 180, 80))
font = pygame.font.SysFont(None, 72)
text = font.render("Gewonnen!", True, (255, 255, 255))
win.blit(text, (win.get_width() // 2 - text.get_width() // 2, win.get_height() // 2 - text.get_height() // 2))
pygame.display.update()
pygame.time.wait(5000)
def show_lose_screen(win):
win.fill((180, 40, 40))
font = pygame.font.SysFont(None, 72)
text = font.render("Verloren!", True, (255, 255, 255))
win.blit(text, (win.get_width() // 2 - text.get_width() // 2, win.get_height() // 2 - text.get_height() // 2))
pygame.display.update()
pygame.time.wait(5000)
def main():
from settings import PLAYER_IMG_PATH, ENEMY_IMG_PATH, HUMAN_IMG_PATH, PLAYER_SIZE, load_img
player_img = load_img(PLAYER_IMG_PATH, (PLAYER_SIZE, PLAYER_SIZE))
enemy_img = load_img(ENEMY_IMG_PATH, (PLAYER_SIZE, PLAYER_SIZE))
human_img = load_img(HUMAN_IMG_PATH, (PLAYER_SIZE, PLAYER_SIZE))
player = Player(MAP_W // 2, MAP_H // 2, player_img)
enemies = [
Enemy(random.randint(0, MAP_W - PLAYER_SIZE), random.randint(0, MAP_H - PLAYER_SIZE), enemy_img, human_img,
i == 0) for i in range(20)]
bottles = []
minimap_visible = True
clock = pygame.time.Clock()
running = True
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if player.ammo > 0:
bottles.append(TapWater(player.x, player.y, player.dir))
player.ammo -= 1
else:
print("Keine Munition!")
if event.key == pygame.K_m:
minimap_visible = not minimap_visible
keys = pygame.key.get_pressed()
player.move(keys, MAP_W, MAP_H)
for enemy in enemies:
enemy.move(keys, player, MAP_W, MAP_H)
enemy.check_kill_player(player)
for bottle in bottles[:]:
for enemy in enemies:
if enemy.rect.colliderect(bottle.rect):
enemy.take_damage(20)
bottles.remove(bottle)
break
bottles = [b for b in bottles if 0 <= b.x <= MAP_W and 0 <= b.y <= MAP_H]
ox = max(0, min(player.x + PLAYER_SIZE // 2 - WIDTH // 2, MAP_W - WIDTH))
oy = max(0, min(player.y + PLAYER_SIZE // 2 - HEIGHT // 2, MAP_H - HEIGHT))
if scaled_map:
WIN.blit(scaled_map, (0, 0), area=pygame.Rect(ox, oy, WIDTH, HEIGHT))
else:
WIN.fill((255, 255, 255))
for px, py in trinkbrunnen_positions:
pygame.draw.circle(WIN, (0, 0, 0), (px - ox, py - oy), 4)
player.draw(WIN, ox, oy)
for bottle in bottles:
bottle.draw(WIN, ox, oy)
for enemy in enemies:
enemy.draw(WIN, ox, oy)
if minimap_visible:
draw_minimap(WIN, map_surface, player, enemies, bottles)
player_rect = pygame.Rect(player.x, player.y, PLAYER_SIZE, PLAYER_SIZE)
# Beim Auffüllen:
for i, (px, py) in enumerate(trinkbrunnen_positions):
brunnen_rect = pygame.Rect(px, py, 20, 20)
if player_rect.colliderect(brunnen_rect) and not used_brunnen[i] and player.ammo < MAX_AMMO:
player.ammo += 3
used_brunnen[i] = True # Brunnen blockieren
font = pygame.font.SysFont(None, 32)
ammo_text = font.render(f"Wasser: {player.ammo}", True, (0, 0, 255))
WIN.blit(ammo_text, (20, 20))
pygame.display.update()
if not player.alive:
show_lose_screen(WIN)
running = False
elif all(not e.alive or e.health <= 0 for e in enemies):
show_win_screen(WIN)
running = False
pygame.quit()
sys.exit()
if __name__ == "__main__":
main()