added docstrings to every file and function. (with claude, checked it)
tower and game_play dont meet pylint check yet.
This commit is contained in:
+94
-18
@@ -1,19 +1,34 @@
|
||||
"""Gameplay screen - map rendering, camera control, tower placement, and enemy waves."""
|
||||
|
||||
import pygame_gui as pgi
|
||||
import pygame as pg
|
||||
from game.screens.base_screen import BaseScreen
|
||||
from game.enemy import Enemy, EnemyGroup
|
||||
from game.camera import Camera
|
||||
from game.tower import Tower, TowerGroup
|
||||
from game.util import *
|
||||
import pygame as pg
|
||||
import pygame_gui as pgi
|
||||
from game.util import pixel_to_tile
|
||||
|
||||
class GamePlay(BaseScreen):
|
||||
# pylint: disable=too-many-instance-attributes
|
||||
"""The main gameplay screen handling the game loop, input, and rendering.
|
||||
|
||||
Attributes:
|
||||
game_surface (pg.Surface): The subsurface used for the game viewport.
|
||||
camera (Camera): Controls zoom and pan over the tilemap.
|
||||
movment (list[bool]): Movement flags for [left, right, up, down] (WASD).
|
||||
selected (Tower | None): The currently selected tower, or ``None``.
|
||||
bought (bool): Whether the player is currently placing a tower.
|
||||
tile_pos (tuple[int, int] | None): Tile under the mouse cursor, or ``None``.
|
||||
enemy_group (EnemyGroup): All active enemies.
|
||||
tower_group (TowerGroup): All placed towers.
|
||||
"""
|
||||
|
||||
def __init__(self, game):
|
||||
super().__init__(game)
|
||||
|
||||
# self.tile_multiplicator = 2.0
|
||||
self.width, self.height = pg.display.get_surface().get_size()
|
||||
self.game_surface = pg.surface.Surface((int(self.width/4*3),int(self.height/6*5)))
|
||||
# self.map_surface = pg.surface.Surface((self.game_surface.get_width()/self.tile_multiplicator,self.game_surface.get_height()/self.tile_multiplicator))
|
||||
|
||||
self.camera = Camera()
|
||||
self.center = (self.game_surface.get_width() /2, self.game_surface.get_height() /2)
|
||||
@@ -65,7 +80,19 @@ class GamePlay(BaseScreen):
|
||||
self.cancel_button
|
||||
]
|
||||
|
||||
self.mpos = (0, 0)
|
||||
self.tile_pos = None
|
||||
self.tile_pos_decimal = (0, 0)
|
||||
|
||||
def process_event(self, event):
|
||||
"""Handle mouse clicks, keyboard input, and UI button presses.
|
||||
|
||||
Translates mouse position to tile coordinates, manages tower
|
||||
placement and selection, camera movement keys, and zoom controls.
|
||||
|
||||
Args:
|
||||
event (pg.event.Event): The pygame event to process.
|
||||
"""
|
||||
#calculate tile position from mouse position
|
||||
self.mpos = pg.mouse.get_pos()
|
||||
game_rect = self.game_surface.get_rect(topleft=(0, self.height / 6))
|
||||
@@ -88,7 +115,7 @@ class GamePlay(BaseScreen):
|
||||
# self.tower = Tower(self.game, self.mpos, self.tile_pos, 'cannon')
|
||||
if event.ui_element == self.cancel_button:
|
||||
self.bought = False
|
||||
|
||||
|
||||
self.tile_pos = (int(self.tile_pos_decimal[0]), int(self.tile_pos_decimal[1]))
|
||||
if event.type == pg.MOUSEBUTTONDOWN:
|
||||
if self.tile_pos is not None:
|
||||
@@ -101,7 +128,7 @@ class GamePlay(BaseScreen):
|
||||
print(f'{self.selected}')
|
||||
if self.bought:
|
||||
if self.game.tilemap.placeable(self.tile_pos):
|
||||
if not any(tower.tile_pos == self.tile_pos for tower in self.tower_group):
|
||||
if not any(tw.tile_pos == self.tile_pos for tw in self.tower_group):
|
||||
tower = Tower(self.game, self.mpos, self.tile_pos, 'cannon', 40)
|
||||
self.tower_group.add(tower)
|
||||
self.bought = False
|
||||
@@ -109,7 +136,7 @@ class GamePlay(BaseScreen):
|
||||
for tower in self.tower_group:
|
||||
if tower.tile_pos == self.tile_pos:
|
||||
tower.kill()
|
||||
|
||||
|
||||
if event.type == pg.KEYDOWN:
|
||||
if event.key == pg.K_a:
|
||||
self.movment[0] = True
|
||||
@@ -119,7 +146,7 @@ class GamePlay(BaseScreen):
|
||||
self.movment[2] = True
|
||||
if event.key == pg.K_s:
|
||||
self.movment[3] = True
|
||||
|
||||
|
||||
if event.key == pg.K_q:
|
||||
self.camera.zoom_offset(self.center, -0.25)
|
||||
if event.key == pg.K_e:
|
||||
@@ -133,14 +160,26 @@ class GamePlay(BaseScreen):
|
||||
self.movment[2] = False
|
||||
if event.key == pg.K_s:
|
||||
self.movment[3] = False
|
||||
|
||||
|
||||
def update(self, dt):
|
||||
"""Update enemies, towers, and camera position.
|
||||
|
||||
Args:
|
||||
dt (float): Time elapsed since the last frame in seconds.
|
||||
"""
|
||||
self.enemy_group.update()
|
||||
self.tower_group.update(self.enemy_group)
|
||||
|
||||
self.camera.move((self.movment[1] - self.movment[0]) * 2, (self.movment[3] - self.movment[2]) * 2)
|
||||
self.camera.move(
|
||||
(self.movment[1] - self.movment[0]) * 2, (self.movment[3] - self.movment[2]) * 2
|
||||
)
|
||||
|
||||
def draw(self, surface):
|
||||
"""Render the tilemap, enemies, towers, and tower placement preview.
|
||||
|
||||
Args:
|
||||
surface (pg.Surface): The main window surface to draw onto.
|
||||
"""
|
||||
self.game_surface.fill((40, 40, 40))
|
||||
# self.map_surface.fill((40, 40, 40))
|
||||
|
||||
@@ -151,22 +190,59 @@ class GamePlay(BaseScreen):
|
||||
|
||||
if self.bought:
|
||||
if self.game.tilemap.placeable(self.tile_pos):
|
||||
self.game_surface.blit(pg.transform.scale2x(self.game.assets["cannon"]), (self.mpos[0] - (self.game.tilemap.tile_size //2), self.mpos[1] - (self.game.tilemap.tile_size //2 + self.height/6)))
|
||||
self.game_surface.blit(
|
||||
pg.transform.scale2x(self.game.assets["cannon"]),
|
||||
(
|
||||
self.mpos[0] - (self.game.tilemap.tile_size //2),
|
||||
self.mpos[1] - (self.game.tilemap.tile_size //2 + self.height/6)
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.game_surface.blit(pg.transform.scale2x(self.game.assets["red_cannon"]), (self.mpos[0] - (self.game.tilemap.tile_size //2), self.mpos[1] - (self.game.tilemap.tile_size //2 + self.height/6)))
|
||||
|
||||
# self.game_surface.blit(pg.transform.scale(self.map_surface, self.game_surface.get_size()))
|
||||
self.game_surface.blit(
|
||||
pg.transform.scale2x(self.game.assets["red_cannon"]),
|
||||
(self.mpos[0] - (self.game.tilemap.tile_size //2),
|
||||
self.mpos[1] - (self.game.tilemap.tile_size //2 + self.height/6))
|
||||
)
|
||||
|
||||
surface.blit(self.game_surface, (0, self.height/6))
|
||||
|
||||
# if self.bought:
|
||||
# self.game_surface.blit(pg.transform.scale2x(self.game.assets["cannon"]), (self.mpos[0] - (self.game.tilemap.tile_size //2), self.mpos[1] - (self.game.tilemap.tile_size //2)))
|
||||
|
||||
def select_turret(self, tile_pos):
|
||||
"""Return the tower at tile_pos, or ``None`` if the tile is empty.
|
||||
|
||||
Args:
|
||||
tile_pos (tuple[int, int]): Grid position to check.
|
||||
|
||||
Returns:
|
||||
Tower | None: The tower occupying that tile, or ``None``.
|
||||
"""
|
||||
for tower in self.tower_group:
|
||||
if (tile_pos[0], tile_pos[1]) == (tower.tile_pos[0], tower.tile_pos[1]):
|
||||
return tower
|
||||
return None
|
||||
|
||||
def clear_selection(self):
|
||||
"""Deselect all towers."""
|
||||
for tower in self.tower_group:
|
||||
tower.selected = False
|
||||
tower.selected = False
|
||||
|
||||
#private helpers jsut within class (planned not sure yet)
|
||||
def _remove_tower_at(self, tile_pos):
|
||||
"""Remove the tower at tile_pos on right click, if one exists.
|
||||
|
||||
Args:
|
||||
tile_pos (tuple[int, int]): Grid position to remove from.
|
||||
"""
|
||||
|
||||
def _handle_keydown(self, key):
|
||||
"""Set movement flags and trigger zoom on key press.
|
||||
|
||||
Args:
|
||||
key (int): pygame key constant.
|
||||
"""
|
||||
|
||||
def _handle_keyup(self, key):
|
||||
"""Clear movement flags on key release.
|
||||
|
||||
Args:
|
||||
key (int): pygame key constant.
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user