pgfe 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pgfe-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,5 @@
1
+ Metadata-Version: 2.3
2
+ Name: pgfe
3
+ Version: 0.1.0
4
+ Requires-Dist: pygame-ce
5
+ Requires-Python: >=3.14
@@ -0,0 +1,9 @@
1
+ [project]
2
+ name = "pgfe"
3
+ version = "0.1.0"
4
+ requires-python = ">=3.14"
5
+ dependencies = ["pygame-ce"]
6
+
7
+ [build-system]
8
+ requires = ["uv_build>=0.12.9,<0.13"]
9
+ build-backend = "uv_build"
@@ -0,0 +1,11 @@
1
+ [project]
2
+ name = "pgfe"
3
+ version = "0.1.0"
4
+ requires-python = ">=3.14"
5
+ dependencies = [
6
+ "pygame-ce",
7
+ ]
8
+
9
+ [build-system]
10
+ requires = ["uv_build>=0.12.9,<0.13"]
11
+ build-backend = "uv_build"
@@ -0,0 +1,6 @@
1
+
2
+ import enum
3
+
4
+ class Axis(enum.Enum):
5
+ X = enum.auto()
6
+ Y = enum.auto()
@@ -0,0 +1,6 @@
1
+
2
+ import pgfe.entity
3
+ import pgfe.game
4
+ import pgfe.scene
5
+ import pgfe.Enum
6
+ import pgfe.events_manager
@@ -0,0 +1,29 @@
1
+
2
+ import abc
3
+ import pygame as pg
4
+
5
+ from pgfe.entity.entity_controllers.AbstractController import AbstractController
6
+
7
+
8
+ class AbstractEntity(pg.sprite.Sprite, abc.ABC):
9
+
10
+ def __init__(self, *groups, x: int, y: int, image: pg.Surface) -> None:
11
+ pg.sprite.Sprite.__init__(self, *groups)
12
+ self.controller: AbstractController|None = None
13
+
14
+ self.image = image
15
+ self.rect = self.image.get_rect()
16
+ self.rect.x = x
17
+ self.rect.y = y
18
+
19
+ self.velocity: pg.Vector2 = pg.Vector2()
20
+
21
+ def update_velocity(self, x: float = 0.0, y: float = 0.0) -> None:
22
+ self.velocity.x += x
23
+ self.velocity.y += y
24
+
25
+ def move_x(self):
26
+ self.rect.x += self.velocity.x
27
+
28
+ def move_y(self):
29
+ self.rect.y += self.velocity.y
File without changes
@@ -0,0 +1,9 @@
1
+
2
+ import abc
3
+ import pygame as pg
4
+
5
+
6
+ class AbstractComponent(abc.ABC):
7
+ def __init__(self):
8
+ self.rect: pg.FRect|Pg.Rect = None
9
+ self.velocity: pg.Vector2|None = None
@@ -0,0 +1,37 @@
1
+
2
+
3
+
4
+ import dataclasses, typing
5
+
6
+ from pgfe.entity.entity_components.AbstractComponent import AbstractComponent
7
+
8
+ if typing.TYPE_CHECKING:
9
+ from rampant.world.tiles.Tile import Tile
10
+
11
+
12
+ @dataclasses.dataclass
13
+ class CollisionExceptions(AbstractComponent):
14
+ def __init__(self):
15
+ super().__init__()
16
+ self.unconditional: CollisionRules.Unconditional = self.Unconditional()
17
+ self.conditional: CollisionRules.Conditional = self.Conditional()
18
+
19
+ class Unconditional(list):
20
+ def add(self, tile: "type[Tile]"):
21
+ self.append(tile)
22
+
23
+ def remove(self, tile: "type[Tile]"):
24
+ super().remove(tile)
25
+
26
+ def get_rules(self):
27
+ return [i for i in self]
28
+
29
+ class Conditional(dict):
30
+ def add(self, tile: "type[Tile]", condition: "typing.Callable[[Tile], Tile|None]"):
31
+ self[tile] = condition
32
+
33
+ def remove(self, tile: "type[Tile]"):
34
+ super().pop(self, tile)
35
+
36
+ def get_rules(self):
37
+ return {(t, c) for t, c in self.items()}
@@ -0,0 +1,37 @@
1
+
2
+ import abc
3
+
4
+ from pgfe import Enum
5
+ from pgfe.entity.entity_components.colliders.AbstractCollider import AbstractCollider
6
+
7
+
8
+ class AABBCollider(AbstractCollider, abc.ABC):
9
+ def __init__(self):
10
+ super().__init__()
11
+
12
+ def collide(self, sprite, axis) -> tuple[bool, bool]:
13
+ if axis == Enum.Axis.X:
14
+ to_return = [False, False]
15
+ if self.velocity.x > 0:
16
+ self.rect.right = sprite.rect.left
17
+ self.velocity.x = 0
18
+ to_return[0] = True
19
+ if self.velocity.x < 0:
20
+ self.rect.left = sprite.rect.right
21
+ self.velocity.x = 0
22
+ to_return[1] = True
23
+ return tuple(to_return)
24
+
25
+ if axis == Enum.Axis.Y:
26
+ to_return = [False, False]
27
+ if self.velocity.y > 0:
28
+ self.rect.bottom = sprite.rect.top
29
+ self.velocity.y = 0
30
+ to_return[1] = True
31
+ if self.velocity.y < 0:
32
+ self.rect.top = sprite.rect.bottom
33
+ self.velocity.y = 0
34
+ to_return[0] = True
35
+ return tuple(to_return)
36
+
37
+ return False, False
@@ -0,0 +1,57 @@
1
+
2
+ import abc
3
+ import pygame as pg
4
+
5
+ from pgfe import Enum
6
+ from pgfe.entity.entity_components.AbstractComponent import AbstractComponent
7
+ from pgfe.entity.entity_components.CollisionExceptions import CollisionExceptions
8
+
9
+
10
+ class AbstractCollider(AbstractComponent, abc.ABC):
11
+ def __init__(self):
12
+ super().__init__()
13
+
14
+ self.collision_exceptions = CollisionExceptions()
15
+
16
+ def get_collides(self, sprite_group):
17
+ for sprite in sprite_group.sprites():
18
+ if sprite != self and self.rect.colliderect(sprite.rect):
19
+ yield sprite
20
+
21
+ @abc.abstractmethod
22
+ def collide(self, sprite: pg.sprite.Sprite, axis: Enum.Axis) -> tuple[bool, bool]:
23
+ pass
24
+
25
+ def collides(self, sprite_group):
26
+ directions = {"top": False, "left": False, "bottom": False, "right": False}
27
+
28
+ # Remove unwanted sprites
29
+ for sprite in sprite_group.sprites():
30
+ if sprite != self and type(sprite) in self.collision_exceptions.unconditional:
31
+ sprite_group.remove(sprite)
32
+
33
+ self.move_x()
34
+ for sprite in self.get_collides(sprite_group):
35
+ right, left = self.collide(sprite, Enum.Axis.X)
36
+ directions.update({
37
+ "left": left,
38
+ "right": right
39
+ })
40
+
41
+ self.move_y()
42
+ for sprite in self.get_collides(sprite_group):
43
+ top, bottom = self.collide(sprite, Enum.Axis.Y)
44
+ directions.update({
45
+ "top": top,
46
+ "bottom": bottom
47
+ })
48
+
49
+ return directions
50
+
51
+ @abc.abstractmethod
52
+ def move_x(self):
53
+ pass
54
+
55
+ @abc.abstractmethod
56
+ def move_y(self):
57
+ pass
@@ -0,0 +1,11 @@
1
+
2
+ import abc
3
+
4
+
5
+ class AbstractController(abc.ABC):
6
+ def __init__(self):
7
+ pass
8
+
9
+ @abc.abstractmethod
10
+ def return_movement(self):
11
+ pass
@@ -0,0 +1,38 @@
1
+
2
+ import pygame as pg
3
+
4
+ from pgfe.entity.entity_controllers.AbstractController import AbstractController
5
+
6
+
7
+ class WASDController(AbstractController):
8
+ def __init__(self):
9
+ super().__init__()
10
+
11
+ def return_wasd(self) -> dict[str, float]:
12
+ pressed = pg.key.get_pressed()
13
+
14
+ return {
15
+ "w": pressed[pg.K_w],
16
+ "a": pressed[pg.K_a],
17
+ "s": pressed[pg.K_s],
18
+ "d": pressed[pg.K_d]
19
+ }
20
+
21
+ def return_movement(self) -> pg.Vector2:
22
+ vector = pg.math.Vector2()
23
+ wasd = self.return_wasd()
24
+
25
+ if wasd["w"]:
26
+ vector.x = 0
27
+ vector.y -= 1
28
+ if wasd["a"]:
29
+ vector.y = 0
30
+ vector.x -= 1
31
+ if wasd["s"]:
32
+ vector.x = 0
33
+ vector.y += 1
34
+ if wasd["d"]:
35
+ vector.y = 0
36
+ vector.x += 1
37
+
38
+ return vector
@@ -0,0 +1,33 @@
1
+
2
+ import pygame as pg
3
+ import typing
4
+
5
+
6
+ events: dict[int, list[typing.Callable]] = {}
7
+
8
+
9
+ def add(hook: int, event: typing.Callable[[int], None]):
10
+ global events
11
+
12
+ event_list = events.get(hook)
13
+ if event_list:
14
+ events[hook].append(event)
15
+ else:
16
+ events[hook] = [event]
17
+
18
+ def remove(hook: int, event: typing.Callable):
19
+ global events
20
+ events[hook].remove(event)
21
+
22
+ def clear(hook: int):
23
+ global events
24
+ events[hook] = []
25
+
26
+ def update_events():
27
+ global events
28
+
29
+ for event in pg.event.get():
30
+ if event.type in events:
31
+ for called in events[event.type]:
32
+ called(event)
33
+
@@ -0,0 +1,53 @@
1
+
2
+ import abc
3
+ import pygame as pg
4
+
5
+ from pgfe.scene.AbstractScene import AbstractScene
6
+ from pgfe import events_manager
7
+
8
+
9
+ def quit(event: int):
10
+ pg.quit()
11
+ raise SystemExit
12
+
13
+
14
+ class AbstractGame(abc.ABC):
15
+
16
+ def __init__(self, framerate: int = 60, tickrate: int = 60, **window_args):
17
+ self.window: pg.Window = pg.Window(**window_args)
18
+ self.window.get_surface()
19
+
20
+ self.clock: pg.time.Clock = pg.time.Clock()
21
+
22
+ self.framerate: int = framerate
23
+ self.tickrate: int = tickrate
24
+
25
+ self.dt: float = 0
26
+ self.frame_dt: float = 0
27
+
28
+ self.scene: AbstractScene|None = None
29
+
30
+ events_manager.add(pg.QUIT, quit)
31
+
32
+ def set_scene(self, scene: AbstractScene):
33
+ self.scene = scene
34
+ self.scene.load()
35
+
36
+ def tick(self):
37
+ self.dt = self.clock.tick(self.tickrate) / 1000
38
+ self.frame_dt = self.dt * self.framerate
39
+
40
+ def update_idle_tasks(self):
41
+ self.scene.render(self.window.get_surface())
42
+ events_manager.update_events()
43
+ self.window.flip()
44
+
45
+ def play(self):
46
+ while True:
47
+ self.tick()
48
+
49
+ self.window.get_surface().fill(self.scene.colors.BG)
50
+
51
+ self.scene.update()
52
+
53
+ self.update_idle_tasks()
File without changes
@@ -0,0 +1,54 @@
1
+
2
+ from __future__ import annotations
3
+
4
+ import abc
5
+ import typing
6
+ import dataclasses
7
+ import pygame as pg
8
+
9
+ if typing.TYPE_CHECKING:
10
+ from pgfe.game.AbstractGame import AbstractGame
11
+
12
+
13
+ @dataclasses.dataclass
14
+ class SceneColors:
15
+
16
+ BG: pg.Color = dataclasses.field(
17
+ default_factory=lambda: pg.Color("black")
18
+ )
19
+
20
+ FG: pg.Color = dataclasses.field(
21
+ default_factory=lambda: pg.Color("grey")
22
+ )
23
+
24
+ extra: dict[str, pg.Color] = dataclasses.field(default_factory=dict)
25
+
26
+ def add_color(self, name: str, color: pg.Color):
27
+ self.extra[name] = color
28
+
29
+
30
+ class AbstractScene(abc.ABC):
31
+
32
+ def __init__(self, game: AbstractGame, colors: SceneColors = SceneColors(), **groups: pg.sprite.Group):
33
+
34
+ self.game: AbstractGame = game
35
+
36
+ self.colors: SceneColors = colors
37
+
38
+ self.groups: dict[str, pg.sprite.Group] = groups
39
+
40
+ @abc.abstractmethod
41
+ def load(self):
42
+ pass
43
+
44
+ def reset(self):
45
+ for group in self.groups.values():
46
+ group.empty()
47
+
48
+ def update(self, *args, **kwargs):
49
+ for group in self.groups.values():
50
+ group.update(*args, **kwargs)
51
+
52
+ def render(self, surface: pg.Surface):
53
+ for group in self.groups.values():
54
+ group.draw(surface)
File without changes