Skip to content

Commit

Permalink
u
Browse files Browse the repository at this point in the history
  • Loading branch information
JackAshwell11 committed Feb 12, 2024
1 parent c9a3e0b commit 0c16d8b
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 198 deletions.
2 changes: 1 addition & 1 deletion build.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def build_extension(self: CMakeBuild, ext: Extension) -> None:
"-DDO_TESTS=OFF",
"--fresh",
"--preset",
"Release",
"WinRelease",
],
check=True,
)
Expand Down
38 changes: 5 additions & 33 deletions hades_extensions/game_objects/__init__.pyi
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Builtin
from abc import abstractmethod
from enum import Enum
from typing import Callable, Final, Self, TypeAlias, TypeVar
from typing import Callable, Final, TypeAlias, TypeVar

# Define some type vars for the registry
_C = TypeVar("_C")
Expand Down Expand Up @@ -50,39 +50,15 @@ class SystemBase:
@abstractmethod
def update(self: SystemBase, delta_time: float) -> None: ...

class Vec2d:
class cpVect: # noqa: N801 # TODO: Should we give it another name?
x: float
y: float

def __init__(self: Vec2d, x: float, y: float) -> None: ...
def magnitude(self: Vec2d) -> float: ...
def normalised(self: Vec2d) -> Vec2d: ...
def rotated(self: Vec2d, angle: float) -> Vec2d: ...
def angle_between(self: Vec2d, other: Vec2d) -> float: ...
def distance_to(self: Vec2d, other: Vec2d) -> float: ...
def __iter__(self: Vec2d) -> tuple[float, float]: ...
def __add__(self: Vec2d, other: Vec2d) -> Vec2d: ...
def __iadd__(self: Self, other: Vec2d) -> Self: ...
def __sub__(self: Vec2d, other: Vec2d) -> Vec2d: ...
def __mul__(self: Vec2d, other: Vec2d) -> Vec2d: ...
def __truediv__(self: Vec2d, other: Vec2d) -> Vec2d: ...
def __eq__(self: Vec2d, other: object) -> bool: ...
def __ne__(self: Vec2d, other: object) -> bool: ...
def __hash__(self: Vec2d) -> int: ...

class KinematicObject:
position: Vec2d
velocity: Vec2d
rotation: float
def __init__(self: cpVect, x: float, y: float) -> None: ...

class Registry:
def __init__(self: Registry) -> None: ...
def create_game_object(
self: Registry,
components: list[ComponentBase],
*,
kinematic: bool = False,
) -> int: ...
def create_game_object(self: Registry, components: list[ComponentBase]) -> int: ...
def delete_game_object(self: Registry, game_object_id: int) -> None: ...
def has_component(
self: Registry,
Expand All @@ -95,10 +71,6 @@ class Registry:
component: type[_C],
) -> _C: ...
def update(self: Registry, delta_time: float) -> None: ...
def get_kinematic_object(
self: Registry,
game_object_id: int,
) -> KinematicObject: ...
def add_wall(self: Registry, wall: Vec2d) -> None: ...
def add_wall(self: Registry, wall: cpVect) -> None: ...
def add_systems(self: Registry) -> None: ...
def get_system(self: Registry, system: type[_S]) -> _S: ...
7 changes: 5 additions & 2 deletions hades_extensions/game_objects/components/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ from hades_extensions.game_objects import (
StatusEffectType,
SteeringBehaviours,
SteeringMovementState,
Vec2d,
cpVect,
)

class StatusEffectData:
Expand Down Expand Up @@ -71,6 +71,9 @@ class Money(ComponentBase):

class MovementForce(Stat): ...

class KinematicComponent(ComponentBase):
def __init__(self: KinematicComponent, vertices: list[cpVect]) -> None: ...

class StatusEffect:
value: float
duration: float
Expand All @@ -84,7 +87,7 @@ class SteeringMovement(ComponentBase):
behaviours: dict[SteeringMovementState, list[SteeringBehaviours]]
movement_state: SteeringMovementState
target_id: int
path_list: list[Vec2d]
path_list: list[cpVect]
def __init__(
self: SteeringMovement,
behaviours: dict[SteeringMovementState, list[SteeringBehaviours]],
Expand Down
2 changes: 2 additions & 0 deletions hades_extensions/game_objects/systems/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class KeyboardMovementSystem(SystemBase):
@abstractmethod
def update(self: SystemBase, delta_time: float) -> None: ...

class PhysicsSystem(SystemBase): ...

class SteeringMovementSystem(SystemBase):
def calculate_force(self: SteeringMovementSystem, game_object_id: int) -> Vec2d: ...
def update_path_list(
Expand Down
8 changes: 4 additions & 4 deletions src/hades/constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
AttackAlgorithm,
SteeringBehaviours,
SteeringMovementState,
cpVect,
)
from hades_extensions.game_objects.components import (
Armour,
Expand All @@ -20,6 +21,7 @@
Health,
Inventory,
KeyboardMovement,
KinematicComponent,
MovementForce,
SteeringMovement,
)
Expand All @@ -41,15 +43,13 @@ class GameObjectConstructor(NamedTuple):
textures: The game object's texture paths.
components: The game object's components.
blocking: Whether the game object blocks sprite movement or not.
kinematic: Whether the game object should have a kinematic object or not.
"""

game_object_type: GameObjectType
name: str
textures: list[str]
components: ClassVar[list[ComponentBase]] = []
blocking: bool = False
kinematic: bool = False


# Static tiles
Expand All @@ -73,6 +73,7 @@ class GameObjectConstructor(NamedTuple):
[
Health(200, 5),
Armour(100, 5),
KinematicComponent([cpVect(5, 6)]),
Inventory(6, 5),
Attacks([
AttackAlgorithm.Ranged,
Expand All @@ -83,7 +84,6 @@ class GameObjectConstructor(NamedTuple):
KeyboardMovement(),
Footprints(),
],
kinematic=True,
)
ENEMY: Final[GameObjectConstructor] = GameObjectConstructor(
GameObjectType.ENEMY,
Expand All @@ -92,6 +92,7 @@ class GameObjectConstructor(NamedTuple):
[
Health(100, 5),
Armour(50, 5),
KinematicComponent([]),
MovementForce(1000, 5),
SteeringMovement(
{
Expand All @@ -104,7 +105,6 @@ class GameObjectConstructor(NamedTuple):
},
),
],
kinematic=True,
)

# Items
Expand Down
93 changes: 34 additions & 59 deletions src/hades/views/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from arcade import (
MOUSE_BUTTON_LEFT,
Camera,
PymunkPhysicsEngine,
SpriteList,
SpriteSolidColor,
Text,
Expand All @@ -25,26 +24,26 @@
# Custom
from hades.constants import (
COLLECTIBLE_TYPES,
DAMPING,
ENEMY_GENERATE_INTERVAL,
ENEMY_GENERATION_DISTANCE,
ENEMY_RETRY_COUNT,
MAX_VELOCITY,
TOTAL_ENEMY_COUNT,
USABLE_TYPES,
GameObjectType,
)
from hades.constructors import ENEMY, FLOOR, PLAYER, POTION, WALL, GameObjectConstructor
from hades.indicator_bar import IndicatorBar
from hades.sprite import AnimatedSprite, Bullet, HadesSprite, grid_pos_to_pixel
from hades_extensions.game_objects import SPRITE_SIZE, Registry, Vec2d
from hades_extensions.game_objects.components import KeyboardMovement, SteeringMovement
from hades_extensions.game_objects import SPRITE_SIZE, Registry, cpVect
from hades_extensions.game_objects.components import (
KeyboardMovement,
KinematicComponent,
SteeringMovement,
)
from hades_extensions.game_objects.systems import (
AttackSystem,
EffectSystem,
InventorySystem,
KeyboardMovementSystem,
SteeringMovementSystem,
)
from hades_extensions.generation import TileType, create_map

Expand All @@ -64,7 +63,6 @@ class Game(View):
Attributes:
game_camera: The camera used for moving the viewport around the screen.
gui_camera: The camera used for visualising the GUI elements.
physics_engine: The physics engine which processes wall collision.
tile_sprites: The sprite list for the tile game objects.
entity_sprites: The sprite list for the entity game objects.
item_sprites: The sprite list for the item game objects.
Expand Down Expand Up @@ -92,40 +90,37 @@ def _create_sprite(
Returns:
The created sprite object.
"""
# Get the constructor and create a game object
# Create a game object if possible and add a wall if the game object is blocking
game_object_id = -1
if constructor.components:
game_object_id = self.registry.create_game_object(
constructor.components,
kinematic=constructor.kinematic,
)
game_object_id = self.registry.create_game_object(constructor.components)
if constructor.blocking:
self.registry.add_wall(Vec2d(*position))
self.registry.add_wall(cpVect(*position))

# Create a sprite and add its ID to the dictionary
sprite_class = AnimatedSprite if constructor.kinematic else HadesSprite
sprite_class = AnimatedSprite if len(constructor.textures) > 1 else HadesSprite
sprite = sprite_class(
(game_object_id, constructor.game_object_type),
position,
constructor.textures,
)
self.ids.setdefault(constructor.game_object_type, []).append(sprite)

# Add the game object to the physics engine if it is blocking or kinematic
if constructor.blocking or constructor.kinematic:
self.physics_engine.add_sprite(
sprite,
moment_of_inertia=(
None if constructor.blocking else self.physics_engine.MOMENT_INF
),
body_type=(
self.physics_engine.STATIC # type: ignore[misc]
if constructor.blocking
else self.physics_engine.DYNAMIC # type: ignore[misc]
),
max_velocity=MAX_VELOCITY,
collision_type=constructor.game_object_type.name,
)
# # Add the game object to the physics engine if it is blocking or kinematic
# if constructor.blocking or constructor.kinematic:
# self.physics_engine.add_sprite(
# sprite,
# moment_of_inertia=(
# None if constructor.blocking else self.physics_engine.MOMENT_INF
# ),
# body_type=(
# self.physics_engine.STATIC # type: ignore[misc]
# if constructor.blocking
# else self.physics_engine.DYNAMIC # type: ignore[misc]
# ),
# max_velocity=MAX_VELOCITY,
# collision_type=constructor.game_object_type.name,
# )

# Add all the indicator bars to the game
indicator_bar_offset = 0
Expand All @@ -152,7 +147,6 @@ def __init__(self: Game, level: int) -> None:
# Arcade types
self.game_camera: Camera = Camera()
self.gui_camera: Camera = Camera()
self.physics_engine: PymunkPhysicsEngine = PymunkPhysicsEngine(damping=DAMPING)
self.tile_sprites: SpriteList[HadesSprite] = SpriteList[HadesSprite]()
self.entity_sprites: SpriteList[HadesSprite] = SpriteList[HadesSprite]()
self.item_sprites: SpriteList[HadesSprite] = SpriteList[HadesSprite]()
Expand Down Expand Up @@ -248,42 +242,23 @@ def on_update(self: Game, delta_time: float) -> None:
# Update the systems
self.registry.update(delta_time)

# Process the results from the system updates
for entity in self.ids.get(GameObjectType.PLAYER, []) + self.ids.get(
GameObjectType.ENEMY,
[],
):
new_force = Vec2d(0, 0)
if self.registry.has_component(entity.game_object_id, KeyboardMovement):
new_force = self.registry.get_system(
KeyboardMovementSystem,
).calculate_force(entity.game_object_id)
elif self.registry.has_component(entity.game_object_id, SteeringMovement):
new_force = self.registry.get_system(
SteeringMovementSystem,
).calculate_force(entity.game_object_id)
self.physics_engine.apply_force(
entity,
tuple(new_force), # type: ignore[arg-type]
)

# Update the physics engine and find the nearest item to the player
self.physics_engine.step()
# Find the nearest item to the player
self.nearest_item = self.ids[GameObjectType.PLAYER][0].collides_with_list(
self.item_sprites,
)

# Process the results from the physics engine
# Update all entity's positions from the physics engine
for entity in self.ids.get(GameObjectType.PLAYER, []) + self.ids.get(
GameObjectType.ENEMY,
[],
):
kinematic_object, body = (
self.registry.get_kinematic_object(entity.game_object_id),
self.physics_engine.get_physics_object(entity).body,
)
kinematic_object.position = Vec2d(*body.position)
kinematic_object.velocity = Vec2d(*body.velocity)
entity.position = self.registry.get_component(
entity.game_object_id,
KinematicComponent,
).body.p
# TODO: Need to get position

# Update the indicator bars
for indicator_bar in self.indicator_bars:
indicator_bar.on_update(delta_time)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ struct KinematicComponent final : ComponentBase {
};

// ----- SYSTEMS ------------------------------
/// Provides facilities to manipulate
/// Provides facilities to manipulate a game object's physics.
struct PhysicsSystem final : SystemBase {
/// Initialise the object.
///
Expand Down
Loading

0 comments on commit 0c16d8b

Please sign in to comment.