149 lines
4.8 KiB
Python
149 lines
4.8 KiB
Python
# 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 = (0, 200, 0)
|
|
WATER_COLOR = (0, 180, 255)
|
|
|
|
PLAYER_SIZE = 40
|
|
PLAYER_SPEED = 5
|
|
WATER_SIZE = 10
|
|
WATER_SPEED = 10
|
|
|
|
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/lst.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):
|
|
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)
|
|
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)
|
|
|
|
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()
|