276 lines
9.3 KiB
Python
276 lines
9.3 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
|
|
|
|
def play_video(win, video_path):
|
|
"""Play video with audio - extracts audio and plays with pygame mixer"""
|
|
import cv2
|
|
import os
|
|
import tempfile
|
|
|
|
try:
|
|
# Extract audio from video to temporary file
|
|
audio_path = None
|
|
try:
|
|
from moviepy import VideoFileClip
|
|
print("Extracting audio from video...")
|
|
video = VideoFileClip(video_path)
|
|
if video.audio:
|
|
temp_audio = tempfile.NamedTemporaryFile(delete=False, suffix='.mp3')
|
|
audio_path = temp_audio.name
|
|
temp_audio.close()
|
|
video.audio.write_audiofile(audio_path, logger=None)
|
|
print(f"Audio extracted to: {audio_path}")
|
|
|
|
# Play audio
|
|
pygame.mixer.init()
|
|
pygame.mixer.music.load(audio_path)
|
|
pygame.mixer.music.play()
|
|
print("Audio playback started")
|
|
else:
|
|
print("No audio track found in video")
|
|
video.close()
|
|
except Exception as e:
|
|
print(f"Audio extraction warning: {e}") # Play video
|
|
cap = cv2.VideoCapture(video_path)
|
|
|
|
if not cap.isOpened():
|
|
print(f"Error: Could not open video file: {video_path}")
|
|
return
|
|
|
|
clock = pygame.time.Clock()
|
|
running = True
|
|
win_size = win.get_size()
|
|
frame_count = 0
|
|
|
|
while running and cap.isOpened():
|
|
ret, frame = cap.read()
|
|
if not ret:
|
|
break
|
|
|
|
frame_count += 1
|
|
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
|
# Transpose for pygame (width, height) format
|
|
frame = frame.swapaxes(0, 1)
|
|
frame_surface = pygame.surfarray.make_surface(frame)
|
|
frame_surface = pygame.transform.smoothscale(frame_surface, win_size)
|
|
win.blit(frame_surface, (0, 0))
|
|
pygame.display.update()
|
|
|
|
for event in pygame.event.get():
|
|
if event.type == pygame.KEYDOWN or event.type == pygame.QUIT:
|
|
running = False
|
|
if audio_path:
|
|
pygame.mixer.music.stop()
|
|
|
|
clock.tick(30)
|
|
|
|
cap.release()
|
|
if audio_path:
|
|
pygame.mixer.music.stop()
|
|
|
|
print(f"Played {frame_count} video frames")
|
|
|
|
# Clean up temp audio file
|
|
if audio_path and os.path.exists(audio_path):
|
|
try:
|
|
os.unlink(audio_path)
|
|
except:
|
|
pass
|
|
|
|
except Exception as e:
|
|
print(f"Video playback error: {e}")
|
|
print("Skipping video...")
|
|
|
|
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, kranwasser):
|
|
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 wasser in kranwasser:
|
|
pygame.draw.circle(win, (0, 180, 255), map2mini(wasser.x, wasser.y), 3)
|
|
|
|
|
|
def show_title_screen(win):
|
|
title = pygame.image.load("images/Wasser_der_Regierung.PNG")
|
|
title = pygame.transform.smoothscale(title, (WIDTH, HEIGHT))
|
|
|
|
win.blit(title,(0,0))
|
|
pygame.display.update()
|
|
pygame.time.wait(3000)
|
|
|
|
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)]
|
|
kranwasser = []
|
|
minimap_visible = True
|
|
clock = pygame.time.Clock()
|
|
|
|
play_video(WIN, "videos/test.mov")
|
|
show_title_screen(WIN)
|
|
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:
|
|
kranwasser.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 wasser in kranwasser[:]:
|
|
for enemy in enemies:
|
|
if enemy.rect.colliderect(wasser.rect):
|
|
enemy.take_damage(20)
|
|
kranwasser.remove(wasser)
|
|
break
|
|
kranwasser = [w for w in kranwasser if 0 <= w.x <= MAP_W and 0 <= w.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 wasser in kranwasser:
|
|
wasser.draw(WIN, ox, oy)
|
|
for enemy in enemies:
|
|
enemy.draw(WIN, ox, oy)
|
|
if minimap_visible:
|
|
draw_minimap(WIN, map_surface, player, enemies, kranwasser)
|
|
|
|
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()
|