ya2 · news · projects · code · about

domino+box: end condition
authorFlavio Calva <f.calva@gmail.com>
Fri, 18 Feb 2022 18:41:05 +0000 (19:41 +0100)
committerFlavio Calva <f.calva@gmail.com>
Fri, 18 Feb 2022 18:41:05 +0000 (19:41 +0100)
pmachines/items/box.py
pmachines/items/domino.py
pmachines/items/item.py
pmachines/scene.py
pmachines/scenes/scene_box.py
pmachines/scenes/scene_domino.py
pmachines/scenes/scene_domino_box.py
prj.org

index ad25341242ca8f8020c41ce81848742150e3c781..56d6285f32d60fed7a4d3554e7cedd88440d5aa9 100644 (file)
@@ -11,14 +11,15 @@ class Box(Item):
         self.node.add_shape(BulletBoxShape((.5, .5, .5)))
 
 
-class TargetBox(Box):
+class HitStrategy:
 
-    def __init__(self, world, plane_node, cb_inst, curr_bottom, repos, mass=1, pos=(0, 0, 0), r=0, count=0, hit_by=None):
+    def __init__(self, hit_by, node, world):
         self._hit_by = hit_by
-        super().__init__(world, plane_node, cb_inst, curr_bottom, repos, mass=mass, pos=pos, r=r, count=count)
+        self._node = node
+        self._world = world
 
     def end_condition(self):
-        for contact in self._world.contact_test(self.node).get_contacts():
-            other = contact.get_node1() if contact.get_node0() == self.node else contact.get_node0()
+        for contact in self._world.contact_test(self._node).get_contacts():
+            other = contact.get_node1() if contact.get_node0() == self._node else contact.get_node0()
             if other == self._hit_by.node:
                 return True
index fe07278144c47a04fc77b62e1f1a3ebfa9f92a57..c50cb5d645c0f71eb033fe40ee306b25a5b57286 100644 (file)
@@ -1,5 +1,5 @@
 from panda3d.bullet import BulletBoxShape, BulletRigidBodyNode, BulletGhostNode
-from pmachines.items.item import Item
+from pmachines.items.item import Item, StillStrategy
 
 
 class Domino(Item):
@@ -11,11 +11,23 @@ class Domino(Item):
         self.node.add_shape(BulletBoxShape((.1, .25, .5)))
 
 
-class TargetDomino(Domino):
+class UpStrategy(StillStrategy):
 
-    def __init__(self, world, plane_node, cb_inst, curr_bottom, repos, mass=1, pos=(0, 0, 0), r=0, count=0, tgt_degrees=0):
+    def __init__(self, np, tgt_degrees):
+        super().__init__(np)
         self._tgt_degrees = tgt_degrees
-        super().__init__(world, plane_node, cb_inst, curr_bottom, repos, mass=mass, pos=pos, r=r, count=count)
+        self._np = np
 
     def end_condition(self):
-        return abs(self._np.get_r()) >= self._tgt_degrees
+        return super().end_condition() and abs(self._np.get_r()) <= self._tgt_degrees
+
+
+class DownStrategy(StillStrategy):
+
+    def __init__(self, np, tgt_degrees):
+        super().__init__(np)
+        self._tgt_degrees = tgt_degrees
+        self._np = np
+
+    def end_condition(self):
+        return super().end_condition() and abs(self._np.get_r()) >= self._tgt_degrees
index 4e31a43ee1fe8b65c164d63638a82b291b69266f..6562af21a45070603b56472ad3cef39512604297 100644 (file)
@@ -12,6 +12,40 @@ class Command:
         self.rot = rot
 
 
+class FixedStrategy:
+
+    def end_condition(self):
+        return True
+
+
+class StillStrategy:
+
+    def __init__(self, np):
+        self._np = np
+        self._positions = []
+        self._rotations = []
+
+    def end_condition(self):
+        self._positions += [self._np.get_pos()]
+        self._rotations += [self._np.get_hpr()]
+        if len(self._positions) > 10:
+            self._positions.pop(0)
+        if len(self._rotations) > 10:
+            self._rotations.pop(0)
+        if len(self._positions) < 8:
+            return
+        avg_x = sum(pos.x for pos in self._positions) / len(self._positions)
+        avg_y = sum(pos.y for pos in self._positions) / len(self._positions)
+        avg_z = sum(pos.z for pos in self._positions) / len(self._positions)
+        avg_h = sum(rot.x for rot in self._rotations) / len(self._rotations)
+        avg_p = sum(rot.y for rot in self._rotations) / len(self._rotations)
+        avg_r = sum(rot.z for rot in self._rotations) / len(self._rotations)
+        avg_pos = Point3(avg_x, avg_y, avg_z)
+        avg_rot = Point3(avg_h, avg_p, avg_r)
+        return all((pos - avg_pos).length() < .1 for pos in self._positions) and \
+            all((rot - avg_rot).length() < 1 for rot in self._rotations)
+
+
 class Item:
 
     def __init__(self, world, plane_node, cb_inst, curr_bottom, scene_repos, model_path, model_scale=1, exp_num_contacts=1, mass=1, pos=(0, 0, 0), r=0, count=0):
@@ -26,6 +60,7 @@ class Item:
         self._mass = mass
         self._pos = pos
         self._r = r
+        self.strategy = FixedStrategy()
         self._exp_num_contacts = exp_num_contacts
         self._curr_bottom = curr_bottom
         self._scene_repos = scene_repos
@@ -69,6 +104,9 @@ class Item:
     def _set_shape(self):
         pass
 
+    def set_strategy(self, strategy):
+        self.strategy = strategy
+
     def _repos(self):
         p_from, p_to = P3dGfxMgr.world_from_to((-1, 1))
         for hit in self._world.ray_test_all(p_from, p_to).get_hits():
@@ -261,9 +299,6 @@ class Item:
         if hasattr(self, '_txt') and not self._txt.is_empty():
             self._txt.set_alpha_scale(1)
 
-    def end_condition(self):
-        return True
-
     def destroy(self):
         self._np.remove_node()
         taskMgr.remove(self._box_tsk)
index 8adf4f747c53a6f9293085a9a5db1f0d66443e5e..f27e7b43c927698052aeee943a7e1a2c6996dcac 100644 (file)
@@ -295,6 +295,9 @@ class Scene(DirectObject):
     def on_aspect_ratio_changed(self):
         self.repos()
 
+    def _end_condition(self):
+        pass
+
     def on_frame(self, task):
         hits = self._get_hits()
         pos = None
@@ -313,7 +316,7 @@ class Scene(DirectObject):
             self._item_active.on_mouse_move(pos)
         if self._dbg_items:
             self._update_info(items_hit[0] if items_hit else None)
-        if all(itm.end_condition() for itm in self.items) and not self._paused:
+        if self._end_condition():
             self._set_end()
         if any(itm._overlapping for itm in self.items):
             self._cursor.cursor_img.img.set_color(.9, .1, .1, 1)
index 9982c7769a11d4b528f908ddfd44c7b8f9f56c32..c7abbc1e4fff1ddfe1a663885a3bac91e2794082 100644 (file)
@@ -1,7 +1,7 @@
 from pmachines.scene import Scene
-from pmachines.items.box import Box, TargetBox
+from pmachines.items.box import Box, HitStrategy
 from pmachines.items.shelf import Shelf
-from pmachines.items.domino import Domino, TargetDomino
+from pmachines.items.domino import Domino
 from pmachines.items.basketball import Basketball
 from pmachines.items.teetertooter import TeeterTooter
 
@@ -23,7 +23,8 @@ class SceneBox(Scene):
         self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-1.29, 0, .26), r=28.45)]
         self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(2.15, 0, -1.49), r=28.45)]
         self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-1.55, 0, 1.23))]
-        self.items += [TargetBox(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(4.38, 0, -3.35), hit_by=self.items[-1])]
+        self.items += [Box(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(4.38, 0, -3.35))]
+        self.items[-1].set_strategy(HitStrategy(self.items[-2], self.items[-1].node, self.items[-1]._world))
         #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=2)]
         #self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-1.14, 0, -.04), tgt_degrees=60)]
         #self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.49, 0, -.04), tgt_degrees=60)]
@@ -39,3 +40,6 @@ class SceneBox(Scene):
         txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
                 'keep \5mouse_r\5 pressed to rotate an item')
         return txt
+
+    def _end_condition(self):
+        return all(itm.strategy.end_condition() for itm in self.items) and not self._paused
index f682626a7840ec7db416e1551b81e168d7ecee4c..3911464fd7bae22cedd6c3d33e161a3afb0cc2ea 100644 (file)
@@ -1,7 +1,7 @@
 from pmachines.scene import Scene
 from pmachines.items.box import Box
 from pmachines.items.shelf import Shelf
-from pmachines.items.domino import Domino, TargetDomino
+from pmachines.items.domino import Domino, DownStrategy
 from pmachines.items.basketball import Basketball
 from pmachines.items.teetertooter import TeeterTooter
 
@@ -21,11 +21,16 @@ class SceneDomino(Scene):
         self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(-1.2, 0, -.6))]
         self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.2, 0, -.6))]
         self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=2)]
-        self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-1.14, 0, -.04), tgt_degrees=60)]
-        self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.49, 0, -.04), tgt_degrees=60)]
-        self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.94, 0, -.04), tgt_degrees=60)]
-        self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.55, 0, -.04), tgt_degrees=60)]
-        self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.09, 0, -.04), tgt_degrees=88)]
+        self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-1.14, 0, -.04))]
+        self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 60))
+        self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.49, 0, -.04))]
+        self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 60))
+        self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.94, 0, -.04))]
+        self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 60))
+        self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.55, 0, -.04))]
+        self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 60))
+        self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.09, 0, -.04))]
+        self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 88))
         #self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
         #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
 
@@ -35,3 +40,6 @@ class SceneDomino(Scene):
         txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
                 'keep \5mouse_r\5 pressed to rotate an item')
         return txt
+
+    def _end_condition(self):
+        return all(itm.strategy.end_condition() for itm in self.items) and not self._paused
index 91921c24540db7e4301695b0c8b5409d93bc5e88..663842b61dc23b8a1b19dcd9337276fa362faba9 100644 (file)
@@ -1,7 +1,7 @@
 from pmachines.scene import Scene
 from pmachines.items.box import Box
 from pmachines.items.shelf import Shelf
-from pmachines.items.domino import Domino, TargetDomino
+from pmachines.items.domino import Domino, UpStrategy, DownStrategy
 from pmachines.items.basketball import Basketball
 from pmachines.items.teetertooter import TeeterTooter
 
@@ -24,22 +24,35 @@ class SceneDominoBox(Scene):
         self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(1.67, 0, -1.45))]
         self.items += [Shelf(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, mass=0, pos=(3.78, 0, -1.45))]
         #self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=9)]
-        self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.61, 0, -.94), r=37, tgt_degrees=60)]
-        self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.06, 0, -.89), tgt_degrees=60)]
-        self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.91, 0, -.89), tgt_degrees=60)]
-        self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.73, 0, -.89), tgt_degrees=60)]
-        self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.57, 0, -.89), tgt_degrees=88)]
-        self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.61, 0, .73), r=37, tgt_degrees=60)]
-        self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.06, 0, .78), tgt_degrees=60)]
-        self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.91, 0, .78), tgt_degrees=60)]
-        self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.73, 0, .78), tgt_degrees=60)]
-        self.items += [TargetDomino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.57, 0, .78), tgt_degrees=88)]
+        self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.61, 0, -.94), r=37)]
+        self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+        self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.06, 0, -.89))]
+        self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+        self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.91, 0, -.89))]
+        self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+        self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.73, 0, -.89))]
+        self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+        self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.57, 0, -.89))]
+        self.items[-1].set_strategy(UpStrategy(self.items[-1]._np, 30))
+        self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.61, 0, .73), r=37)]
+        self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+        self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(-.06, 0, .78))]
+        self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+        self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(0.91, 0, .78))]
+        self.items[-1].set_strategy(DownStrategy(self.items[-1]._np, 35))
+        self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(1.73, 0, .78))]
+        self.items[-1].set_strategy(UpStrategy(self.items[-1]._np, 30))
+        self.items += [Domino(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, pos=(2.57, 0, .78))]
+        self.items[-1].set_strategy(UpStrategy(self.items[-1]._np, 30))
         #self.items += [Basketball(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
         #self.items += [TeeterTooter(self._world, self._mouse_plane_node, self.cb_inst, self.current_bottom, self.repos, count=3)]
 
     def _instr_txt(self):
         txt = _('Scene: ') + self.name() + '\n\n'
-        txt += _('Goal: at least one domino piece per row must be up\n\n')
+        txt += _('Goal: only the last piece of each row must be up\n\n')
         txt += _('keep \5mouse_l\5 pressed to drag an item\n\n'
                 'keep \5mouse_r\5 pressed to rotate an item')
         return txt
+
+    def _end_condition(self):
+        return all(itm.strategy.end_condition() for itm in self.items) and not self._paused
diff --git a/prj.org b/prj.org
index 0397aaaaacb5afd73bad3f3c85f9846271a71b72..b00180ab2985d0a2185c2ef8fe2044222f61ba7c 100644 (file)
--- a/prj.org
+++ b/prj.org
@@ -1,6 +1,6 @@
 * issues
 * todo
-** level domino + box: end condition
+** first levels: fail condition - you fail! (every item in the screen is still)
 ** level basketball
 ** level domino + box + basketball
 ** level teetertooter