# Simple top-down game skeleton with WASD movement and water bottle shooting import pygame import sys import numpy as np import rasterio pygame.init() WIDTH, HEIGHT = 800, 600 WIN = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Water Bottle Shooter") WHITE = (255, 255, 255) BLUE = (0, 150, 255) PLAYER_COLOR = (200, 200, 0) WATER_COLOR = (0, 180, 255) PLAYER_SIZE = 40 PLAYER_SPEED = 5 WATER_SIZE = 10 WATER_SPEED = 10 PLAYER_IMAGE_PATH = "images/player.png" # Path to your player image try: PLAYER_IMAGE = pygame.image.load(PLAYER_IMAGE_PATH).convert_alpha() PLAYER_IMAGE = pygame.transform.scale(PLAYER_IMAGE, (PLAYER_SIZE, PLAYER_SIZE)) except Exception as e: print(f"Could not load player image: {e}") PLAYER_IMAGE = None ENEMY_IMAGE_PATH = "images/enemy.png" # Path to your player image try: ENEMY_IMAGE = pygame.image.load(ENEMY_IMAGE_PATH).convert_alpha() ENEMY_IMAGE = pygame.transform.scale(ENEMY_IMAGE, (PLAYER_SIZE, PLAYER_SIZE)) except Exception as e: print(f"Could not load player image: {e}") ENEMY_IMAGE = None clock = pygame.time.Clock() # Load raster map as background # Load full raster as a surface def load_full_map_surface(path): try: src = rasterio.open(path) arr = src.read(1) arr = arr - 272.15 # Convert Kelvin to Celsius if needed arr = np.nan_to_num(arr, nan=0) arr = np.clip(arr, np.percentile(arr, 5), np.percentile(arr, 95)) arr = (arr - arr.min()) / (arr.max() - arr.min()) * 255 arr = arr.astype(np.uint8) arr = np.stack([arr, arr, arr], axis=-1) # grayscale to RGB arr = np.flipud(arr) # flip vertically for correct orientation # Always scale map to at least fill the screen, preserving aspect ratio h, w = arr.shape[:2] scale_factor = max(WIDTH / w, HEIGHT / h) new_w = int(w * scale_factor) new_h = int(h * scale_factor) surf = pygame.surfarray.make_surface(arr) surf = pygame.transform.smoothscale(surf, (new_w, new_h)) return surf, new_w, new_h except Exception as e: print(f"Could not load map background: {e}") return None, WIDTH, HEIGHT MAP_PATH = "results/s2_2025.tif" map_surface, MAP_W, MAP_H = load_full_map_surface(MAP_PATH) class Player: def __init__(self, x, y): self.x = x self.y = y self.rect = pygame.Rect(self.x, self.y, PLAYER_SIZE, PLAYER_SIZE) self.direction = "up" # Default direction def move(self, keys): if keys[pygame.K_w]: self.y -= PLAYER_SPEED self.direction = "up" if keys[pygame.K_s]: self.y += PLAYER_SPEED self.direction = "down" if keys[pygame.K_a]: self.x -= PLAYER_SPEED self.direction = "left" if keys[pygame.K_d]: self.x += PLAYER_SPEED self.direction = "right" # Clamp to map boundaries self.x = max(0, min(MAP_W - PLAYER_SIZE, self.x)) self.y = max(0, min(MAP_H - PLAYER_SIZE, self.y)) self.rect.topleft = (self.x, self.y) def draw(self, win, offset_x, offset_y): if PLAYER_IMAGE: win.blit(PLAYER_IMAGE, (self.x - offset_x, self.y - offset_y)) else: pygame.draw.rect(win, PLAYER_COLOR, (self.x - offset_x, self.y - offset_y, PLAYER_SIZE, PLAYER_SIZE)) class Enemy: def __init__(self, x, y): self.x = x self.y = y self.rect = pygame.Rect(self.x, self.y, PLAYER_SIZE /2, PLAYER_SIZE /2) self.direction = "up" # Default direction def move(self, keys): if keys[pygame.K_UP]: self.y -= PLAYER_SPEED self.direction = "up" if keys[pygame.K_DOWN]: self.y += PLAYER_SPEED self.direction = "down" if keys[pygame.K_LEFT]: self.x -= PLAYER_SPEED self.direction = "left" if keys[pygame.K_RIGHT]: self.x += PLAYER_SPEED self.direction = "right" # Clamp to map boundaries self.x = max(0, min(MAP_W - PLAYER_SIZE, self.x)) self.y = max(0, min(MAP_H - PLAYER_SIZE, self.y)) self.rect.topleft = (self.x, self.y) def draw(self, win, offset_x, offset_y): if ENEMY_IMAGE: win.blit(ENEMY_IMAGE, (self.x - offset_x, self.y - offset_y)) else: pygame.draw.rect(win, PLAYER_COLOR, (self.x - offset_x, self.y - offset_y, PLAYER_SIZE, PLAYER_SIZE)) class WaterBottle: def __init__(self, x, y, direction): self.x = x + PLAYER_SIZE // 2 - WATER_SIZE // 2 self.y = y + PLAYER_SIZE // 2 - WATER_SIZE // 2 self.direction = direction self.rect = pygame.Rect(self.x, self.y, WATER_SIZE, WATER_SIZE) def move(self): if self.direction == "up": self.y -= WATER_SPEED elif self.direction == "down": self.y += WATER_SPEED elif self.direction == "left": self.x -= WATER_SPEED elif self.direction == "right": self.x += WATER_SPEED self.rect.topleft = (self.x, self.y) def draw(self, win, offset_x, offset_y): pygame.draw.rect(win, WATER_COLOR, (self.x - offset_x, self.y - offset_y, WATER_SIZE, WATER_SIZE)) def main(): # Start player in center of map player = Player(MAP_W // 2, MAP_H // 2) enemy = Enemy(MAP_W // 3, MAP_H // 3) water_bottles = [] 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: # Shoot water bottle water_bottles.append(WaterBottle(player.x, player.y, player.direction)) keys = pygame.key.get_pressed() player.move(keys) enemy.move(keys) for bottle in water_bottles: bottle.move() # Remove bottles that go off map water_bottles = [b for b in water_bottles if 0 <= b.x <= MAP_W and 0 <= b.y <= MAP_H] # Camera offset: keep player centered unless near edge offset_x = max(0, min(player.x + PLAYER_SIZE // 2 - WIDTH // 2, MAP_W - WIDTH)) offset_y = max(0, min(player.y + PLAYER_SIZE // 2 - HEIGHT // 2, MAP_H - HEIGHT)) # Draw map portion if map_surface: WIN.blit(map_surface, (0, 0), area=pygame.Rect(offset_x, offset_y, WIDTH, HEIGHT)) else: WIN.fill(WHITE) player.draw(WIN, offset_x, offset_y) for bottle in water_bottles: bottle.draw(WIN, offset_x, offset_y) pygame.display.update() pygame.quit() sys.exit() if __name__ == "__main__": main()