Ejemplo n.º 1
0
 def afterPhysics(self):
     for i, obj in enumerate(self.generated):
         obj.position = local_space_to_world_space(
             self.relative_location
             + local_space_to_world_space(self.relative_positions[i], self.relative_rotation, np.array([0, 0])),
             self.physical_object.rotation,
             self.physical_object.position,
         )
         obj.rotation = self.physical_object.rotation + self.relative_rotation
Ejemplo n.º 2
0
 def afterPhysics(self):
     for i, obj in enumerate(self.generated):
         obj.position = local_space_to_world_space(
             self.relative_location
             + local_space_to_world_space(self.relative_positions[i], self.relative_rotation, np.array([0, 0])),
             self.physical_object.rotation,
             self.physical_object.position,
         )
         if obj.key == (self.getPrefix() + "relative_north"):
             obj.rotation = self.device_class.global_rotation - self.do_rotation
         else:
             obj.rotation = self.physical_object.rotation + self.relative_rotation
Ejemplo n.º 3
0
    def afterPhysics(self):
        from ev3sim.objects.base import PhysicsObject

        for i, obj in enumerate(self.generated):
            obj.position = local_space_to_world_space(
                self.relative_location + local_space_to_world_space(
                    self.relative_positions[i], self.relative_rotation,
                    np.array([0, 0])),
                self.physical_object.rotation,
                self.physical_object.position,
            )
            obj.rotation = self.physical_object.rotation + self.relative_rotation
            if isinstance(obj, PhysicsObject):
                obj.body.position = obj.position
                obj.body.angle = obj.rotation
Ejemplo n.º 4
0
 def calculatePoints(self):
     try:
         tmp = self.rotation, self.position
     except:
         return
     for i, v in enumerate(self.verts):
         self.points[i] = utils.worldspace_to_screenspace(local_space_to_world_space(v, self.rotation, self.position))
Ejemplo n.º 5
0
 def spawnAt(self, tileIndex):
     self.can_scored_this_spawn = False
     self.resetFollows()
     spawn_point = (
         self.tiles[tileIndex]["follows"][0][0][0]
         if isinstance(self.tiles[tileIndex]["follows"][0], (list, tuple))
         else self.tiles[tileIndex]["follows"][0]
     )
     for i in range(len(self.robots)):
         self.robots[i].body.angle = self.tiles[tileIndex]["rotation"]
         if self.tiles[tileIndex]["flip"]:
             self.robots[i].body.angle = self.robots[i].body.angle + np.pi
         self.bot_follows[i].body.position = [
             float(v)
             for v in local_space_to_world_space(
                 ScriptLoader.instance.robots[f"Robot-{i}"]._follow_collider_offset,
                 self.robots[i].body.angle,
                 (self.robots[i].body.position.x, self.robots[i].body.position.y),
             )
         ]
         self.robots[i].body.position = [
             a + b - c
             for a, b, c in zip(self.robots[i].body.position, spawn_point, self.bot_follows[i].body.position)
         ]
         self.robots[i].body.velocity = (0, 0)
         self.robots[i].body.angular_velocity = 0
     self.touchBot()
Ejemplo n.º 6
0
    def startUp(self):
        super().startUp()
        self.START_TIME = datetime.timedelta(minutes=self.GAME_LENGTH_MINUTES)
        self.spawnTiles()
        self.spawnFollowPointPhysics()
        self.spawnTileUI()
        self.spawnRobotFollows()
        assert len(self.robots) <= len(self.BOT_SPAWN_POSITION), "Not enough spawning locations specified."
        self.spawnCan()

        self.reset()
        for i in range(len(self.robots)):
            # This is bad, I should get the robot key somehow else (Generally speaking the robot class, interactor and object should be more tightly coupled.)
            self.bot_follows[i].body.position = [
                float(v)
                for v in local_space_to_world_space(
                    ScriptLoader.instance.robots[f"Robot-{i}"]._follow_collider_offset,
                    self.robots[i].body.angle,
                    (self.robots[i].body.position.x, self.robots[i].body.position.y),
                )
            ]
        self.addCollisionHandler()

        for robot in self.robots:
            robot.robot_class.onSpawn()
Ejemplo n.º 7
0
 def onReset(self):
     super().onReset()
     self.tunnelTop.body.position = [
         float(v) for v in local_space_to_world_space(
             [0, 9],
             self.rescue.tiles[self.index]["rotation"],
             self.rescue.tiles[self.index]["all_elems"][0].position,
         )
     ]
     self.tunnelBot.body.position = [
         float(v) for v in local_space_to_world_space(
             [0, -9],
             self.rescue.tiles[self.index]["rotation"],
             self.rescue.tiles[self.index]["all_elems"][0].position,
         )
     ]
Ejemplo n.º 8
0
 def changeForce(self, force):
     # Reduce the force by a factor
     # args[0]: slow factor
     if self.force_type == "slow":
         return force * self.force_args[0]
     # Reduce the force by a factor in a certain direction.
     # args[0]: normalised vector to slow by
     # args[1]: slow factor
     if self.force_type == "slow_dir":
         parallel = np.dot(
             force,
             local_space_to_world_space(
                 self.force_args[0], self.rotation,
                 [0, 0])) * local_space_to_world_space(
                     self.force_args[0], self.rotation, [0, 0])
         perpendicular = force - parallel
         parallel *= self.force_args[1]
         return perpendicular + parallel
     raise ValueError(f"Unknown Force Effect Type {self.force_type}")
Ejemplo n.º 9
0
 def _applyMotors(self, object, position, rotation):
     # Look at motor global position for any force modification fields.
     pos = local_space_to_world_space(object.body.position, rotation,
                                      position)
     new_force = self.applied_force * np.array(
         [np.cos(rotation), np.sin(rotation)])
     shapes = World.instance.space.point_query(
         [float(v) for v in pos], 0.0,
         pymunk.ShapeFilter(mask=STATIC_CATEGORY))
     if shapes:
         max_z = max(pq.shape.obj.clickZ for pq in shapes)
         shapes = [pq for pq in shapes if pq.shape.obj.clickZ == max_z]
         for pq in shapes:
             if pq.shape.obj.affectsForce:
                 new_force = pq.shape.obj.changeForce(new_force)
     object.apply_force(new_force, pos=position)
Ejemplo n.º 10
0
    def spawnTiles(self):
        self.tiles = []
        for i, tile in enumerate(self.TILE_DEFINITIONS):
            self.tiles.append({})
            import yaml

            path = find_abs(tile["path"], allowed_areas=preset_locations())
            with open(path, "r") as f:
                t = yaml.safe_load(f)
            self.maxZpos = 0
            base_pos = np.array(tile.get("position", [0, 0]))
            # Transfer to rescue space.
            base_pos = [base_pos[0] * self.TILE_LENGTH, base_pos[1] * self.TILE_LENGTH]
            base_rotation = tile.get("rotation", 0) * np.pi / 180
            flip = tile.get("flip", False)
            for obj in t["elements"]:
                rel_pos = np.array(obj.get("position", [0, 0]))
                if flip:
                    rel_pos[0] = -rel_pos[0]
                    if obj.get("name", "") == "Image":
                        obj["flip"] = [True, False]
                    if obj.get("name", "") == "Arc":
                        obj["rotation"] = 180 - obj.get("rotation", 0)
                        obj["angle"] = -obj["angle"]
                obj["rotation"] = (obj.get("rotation", 0)) * np.pi / 180 + base_rotation
                obj["position"] = local_space_to_world_space(rel_pos, base_rotation, base_pos)
                obj["sensorVisible"] = True
                k = obj["key"]
                obj["key"] = f"Tile-{i}-{k}"
                self.maxZpos = max(self.maxZpos, obj.get("zPos", 0))
            t["elements"].append(
                {
                    "position": local_space_to_world_space(np.array([0, 0]), base_rotation, base_pos),
                    "rotation": base_rotation,
                    "type": "visual",
                    "name": "Rectangle",
                    "width": self.TILE_LENGTH,
                    "height": self.TILE_LENGTH,
                    "fill": None,
                    "stroke_width": 0.1,
                    "stroke": "rescue_outline_color",
                    "zPos": self.maxZpos + 0.1,
                    "key": f"Tile-{i}-outline",
                    "sensorVisible": False,
                }
            )
            self.tiles[-1]["type"] = t.get("type", "follow")
            self.tiles[-1]["follows"] = []
            self.tiles[-1]["roam_status"] = []
            self.tiles[-1]["world_pos"] = base_pos
            self.tiles[-1]["rotation"] = base_rotation
            self.tiles[-1]["flip"] = flip
            if self.tiles[-1]["type"] == "follow":
                self.tiles[-1]["entries"] = t["entries"]
                self.tiles[-1]["exits"] = t["exits"]
                mname, cname = t.get("checker").rsplit(".", 1)
                import importlib

                klass = getattr(importlib.import_module(mname), cname)
                with open(find_abs(t["ui"], allowed_areas=preset_locations()), "r") as f:
                    self.tiles[-1]["ui_elem"] = yaml.safe_load(f)
                for j, point in enumerate(t["follow_points"]):
                    if isinstance(point[0], (list, tuple)):
                        self.tiles[-1]["follows"].append([])
                        self.tiles[-1]["roam_status"].append([])
                        for path in point:
                            self.tiles[-1]["follows"][-1].append([])
                            self.tiles[-1]["roam_status"][-1].append([])
                            for point2 in path:
                                if isinstance(point2, str):
                                    self.tiles[-1]["roam_status"][-1][-1][-1] = point2
                                else:
                                    if flip:
                                        point2[0] = -point2[0]
                                    self.tiles[-1]["follows"][-1][-1].append(
                                        local_space_to_world_space(
                                            np.array(point2), tile.get("rotation", 0) * np.pi / 180, base_pos
                                        )
                                    )
                                    self.tiles[-1]["roam_status"][-1][-1].append(None)
                    else:
                        if isinstance(point, str):
                            self.tiles[-1]["roam_status"][-1] = point
                        else:
                            if flip:
                                point[0] = -point[0]
                            self.tiles[-1]["follows"].append(
                                local_space_to_world_space(
                                    np.array(point), tile.get("rotation", 0) * np.pi / 180, base_pos
                                )
                            )
                            self.tiles[-1]["roam_status"].append(None)
                self.tiles[-1]["checker"] = klass(self.tiles[-1]["follows"], i, self, **t.get("checker_kwargs", {}))
            else:
                self.tiles[-1]["green_conns"] = t.get("green_conns", [])
            self.tiles[-1]["all_elems"] = ScriptLoader.instance.loadElements(t["elements"])
        connecting_objs = []
        for tile in self.tiles:
            # We need to add connections between green tiles if they exist.
            if tile["type"] == "follow":
                continue
            under, right, under_right = self._checkConnectingRescueTiles(tile["world_pos"])
            if under_right and under and right:
                # Draw a big square connecting all 4 tiles.
                key = "c1-" + str(tile["world_pos"][0]) + "-" + str(tile["world_pos"][1])
                connecting_objs.append(
                    {
                        "type": "visual",
                        "name": "Rectangle",
                        "width": 50,
                        "height": 50,
                        "fill": "grass_color",
                        "zPos": 0.3,
                        "key": key,
                        "position": [
                            tile["world_pos"][0] + self.TILE_LENGTH / 2,
                            tile["world_pos"][1] + self.TILE_LENGTH / 2,
                        ],
                        "sensorVisible": True,
                    }
                )
            else:
                if under:
                    key = "c2-" + str(tile["world_pos"][0]) + "-" + str(tile["world_pos"][1])
                    connecting_objs.append(
                        {
                            "type": "visual",
                            "name": "Rectangle",
                            "width": 20,
                            "height": 50,
                            "fill": "grass_color",
                            "zPos": 0.3,
                            "key": key,
                            "position": [tile["world_pos"][0], tile["world_pos"][1] + self.TILE_LENGTH / 2],
                            "sensorVisible": True,
                        }
                    )
                if right:
                    key = "c3-" + str(tile["world_pos"][0]) + "-" + str(tile["world_pos"][1])
                    connecting_objs.append(
                        {
                            "type": "visual",
                            "name": "Rectangle",
                            "width": 50,
                            "height": 20,
                            "fill": "grass_color",
                            "zPos": 0.3,
                            "key": key,
                            "position": [tile["world_pos"][0] + self.TILE_LENGTH / 2, tile["world_pos"][1]],
                            "sensorVisible": True,
                        }
                    )
        self.connecting_objs = ScriptLoader.instance.loadElements(connecting_objs)
Ejemplo n.º 11
0
    def tick(self, tick):
        super().tick(tick)
        self.cur_tick = tick
        for i in range(len(self.robots)):
            self.bot_follows[i].body.position = [
                float(v)
                for v in local_space_to_world_space(
                    ScriptLoader.instance.robots[f"Robot-{i}"]._follow_collider_offset,
                    self.robots[i].body.angle,
                    (self.robots[i].body.position.x, self.robots[i].body.position.y),
                )
            ]
            # Ensure visual is not 1 frame behind.
            self.bot_follows[i].position = np.array(self.bot_follows[i].body.position)
            if self.current_follow is not None and not World.instance.paused:
                distance = magnitude_sq(
                    self.bot_follows[i].position
                    - self._recurseObj(self.tiles[self.current_follow[0]]["follows"], self.current_follow[1:])
                )
                if distance > self.MAX_FOLLOW_DIST * self.MAX_FOLLOW_DIST and not self.roaming[i]:
                    self.lackOfProgress(i)
            if self.roaming[i] and not World.instance.paused:
                # Check we are still in the tile. Kinda bad.
                if (
                    abs(self.bot_follows[i].position[0] - self.tiles[self.roam_tile[i]]["world_pos"][0])
                    > self.TILE_LENGTH / 2
                    or abs(self.bot_follows[i].position[1] - self.tiles[self.roam_tile[i]]["world_pos"][1])
                    > self.TILE_LENGTH / 2
                ) and magnitude_sq(
                    self.bot_follows[i].position
                    - self._recurseObj(self.tiles[self.roam_tile[i]]["follows"], self.roaming[i][1])
                ) > (
                    self.ROBOT_CENTRE_RADIUS + self.FOLLOW_POINT_RADIUS + 0.05
                ) * (
                    self.ROBOT_CENTRE_RADIUS + self.FOLLOW_POINT_RADIUS + 0.05
                ):
                    self.lackOfProgress(i)
            if not World.instance.paused:
                x = (self.bot_follows[i].position[0] + self.TILE_LENGTH / 2) // self.TILE_LENGTH
                y = (self.bot_follows[i].position[1] + self.TILE_LENGTH / 2) // self.TILE_LENGTH
                for tile in self.tiles:
                    tx = (tile["world_pos"][0] + self.TILE_LENGTH / 2) // self.TILE_LENGTH
                    ty = (tile["world_pos"][1] + self.TILE_LENGTH / 2) // self.TILE_LENGTH
                    if tx == x and ty == y:
                        if tile["type"] == "rescue" and self.modes[i] == self.MODE_FOLLOW:
                            self.modes[i] = self.MODE_RESCUE
                            # For reentry.
                            self.resetFollows()
                            self.current_follow = None
                        elif tile["type"] == "follow" and self.modes[i] == self.MODE_RESCUE:
                            self.modes[i] = self.MODE_FOLLOW
                            if self.can_scored_this_spawn:
                                self.scoreReEntry()
                        break
                else:
                    self.lackOfProgress(i)
                if not self.can_scored_this_spawn:
                    cx = (self.can_obj.position[0] + self.TILE_LENGTH / 2) // self.TILE_LENGTH
                    cy = (self.can_obj.position[1] + self.TILE_LENGTH / 2) // self.TILE_LENGTH
                    for tile in self.tiles:
                        tx = (tile["world_pos"][0] + self.TILE_LENGTH / 2) // self.TILE_LENGTH
                        ty = (tile["world_pos"][1] + self.TILE_LENGTH / 2) // self.TILE_LENGTH
                        if tx == cx and ty == cy:
                            if tile["type"] != "rescue":
                                self.scoreCan()
                            rel_pos_x = self.can_obj.position[0] - tile["world_pos"][0]
                            rel_pos_y = self.can_obj.position[1] - tile["world_pos"][1]
                            sx = 1
                            sy = 1
                            if rel_pos_x < 0:
                                rel_pos_x = -rel_pos_x
                                sx = -1
                            if rel_pos_y < 0:
                                rel_pos_y = -rel_pos_y
                                sy = -1
                            if rel_pos_y < self.TILE_LENGTH / 3 and rel_pos_x < self.TILE_LENGTH / 3:
                                break
                            under, right, under_right = self._checkConnectingRescueTiles(tile["world_pos"], sx, sy)
                            if under_right and under and right:
                                # We can't be outside of the area.
                                break
                            if under:
                                if rel_pos_x < self.TILE_LENGTH / 3:
                                    break
                            if right:
                                if rel_pos_y < self.TILE_LENGTH / 3:
                                    break
                            self.scoreCan()
                            break
                    else:
                        self.scoreCan()

        for i in range(len(self.tiles)):
            if self.tiles[i]["type"] == "follow":
                self.tiles[i]["checker"].tick(tick)
        # UI Tick
        if self._pressed:
            ScriptLoader.instance.object_map["controlsReset"].visual.image_path = "ui/controls_reset_pressed.png"
        else:
            ScriptLoader.instance.object_map["controlsReset"].visual.image_path = "ui/controls_reset_released.png"
        self.update_time()