pkulev / xoinvader

Python space game in terminal
http://mmap.me
MIT License
12 stars 1 forks source link

Brand new object system #38

Open pkulev opened 7 years ago

pkulev commented 7 years ago

THIS IS DRAFT

Abstract

This time not came yet, but some changes we need to do in order to unblock further development. We need to design and implement as simple as possible object system that will fit to our needs for this time. We have ships and backgrounds that have Surface to render. We have projectiles that looks like not good designed lists of coordinates...

Design

GameObject and State

Appllication and States

Event-based messaging

Game-specific implementation examples

Ship


class PlayerShip(Renderable):
    def __init__(self, ...):
         self.add(WeaponSlot(transform, ...))  # transform is offset
         self.add(WeaponSlot(transform. ...))  # that applied to PlayerShip's transform
         self.add(LeftEngine(transform, ...))  # maybe some form of declarative definition

class InGameState(State):
    def __init__(self, owner):
        self._actor = PlayerShip(transform, ... )
        self.add(self._actor)  # will be rendered and updated

class InGameEventHandler(Handler):
     def handle(self):
          # after input
          for event in self.owner.get_events():
              if event.recepient:
                  self.dispatch(event)
              # some other things

Weapon

class Weapon(Renderable):
    def update(self):
        if self._fire:
            self.add(Projectile(self))
        ...

Collision detection

class RocketProjectile(...):
    def on_trigger_enter(collider):
        if self.side != collider.game_object.side and collider.game_object.side != "obstacles":
            collider.game_object.apply_damage(self)
            ...
alex-eg commented 7 years ago

Are you sure it absolutely must be implemented in scope of current milestone?

pkulev commented 7 years ago
class Transform(object):
    """t"""

    required = True

    def __init__(self, pos=None, rot=None, scale=None):
        self._pos = pos or Point()
        self._rot = rot or Point()
        self._scale = scale or Point(1, 1, 1)

class GameObject(object):
    """t"""

    default_components = [Transform]
    components = default_components[:]

    def __init__(self, transform=None):
        self.add_component(transform or Transform())

    def add_component(self, component):
        """t"""
        self.components.append(component)
pkulev commented 7 years ago
@dispatch(Ship, Projectile)
def on_collision(ship, projectile):
    ship.apply_damage(projectile.damage)

@dispatch(EnemyShip, EnemyShip)
def on_collision(ship1, ship2):
    pass
alex-eg commented 7 years ago

It's shame that we cannot construct function in runtime. It would be very nice to just have something like defcollision for collision detection.

pkulev commented 4 years ago
diff --git a/xoinvader/menu.py b/xoinvader/menu.py
index 16e0710..eb8d801 100644
--- a/xoinvader/menu.py
+++ b/xoinvader/menu.py
@@ -41,6 +41,62 @@ class PauseMenuState(State):
             KEY.N: lambda: self.notify("This is test notification"),
         })

+    def key_event_map(self):
+        # Under the hood
+        # self._events = EventHandler(self, self.key_event_map)
+        # dispatch(event)
+        # if action == call-app then getattr(application.get_current(), target)(*args, **kwargs)
+        # if action == call-self then getattr(self, target)(*args, **kwargs)
+        # if action == call then parse()
+        {
+            "type": "State",
+            "name": "PauseMenuState",
+            "init": {
+                "objects": [
+                    {"class": "TextWidget", "args": ([4, 4], "Pause")},
+                    {"class": "MenuItemWidget", "args": ([10, 10], "Continue")},
+                    {"class": "MenuItemWidget", "args": ([10, 11], "Quit")},
+                ],
+            },
+            "key-event-map": {
+                "KEY.ESCAPE": {
+                    "action": "call-app",
+                    "target": "stop",
+                },
+                "KEY.R": {
+                    "action": "call-self",
+                    "target": "notify",
+                    "args": "This is test notification",
+                },
+                "KEY.N": {
+                    "action": "trigger-state",
+                    "target": "InGameState",
+                },
+            },
+            "scripts": [
+                {
+                    "name": "notify.py",
+                    "id": "{fdfdfdf}",
+                },
+            ],
+        }

     def notify(self, text, pos=Point(15, 15)):
         self.add(
             PopUpNotificationWidget(
alex-eg commented 4 years ago

👍