def handle_key_pressed(key_map, elapsed_time, entities):
        mov_speed_player_vert = 2.0
        mov_speed_player_horz = 2.0
        if key_map[pygame.K_UP]:
            for e in entities:
                e.send_msg(
                    UpdateTransform2DMessage(
                        translate_vec=Vec2(0.0, -mov_speed_player_horz)
                    )
                )

        if key_map[pygame.K_DOWN]:
            for e in entities:
                e.send_msg(
                    UpdateTransform2DMessage(
                        translate_vec=Vec2(0.0, mov_speed_player_horz)
                    )
                )

        if key_map[pygame.K_LEFT]:
            for e in entities:
                e.send_msg(
                    UpdateTransform2DMessage(
                        translate_vec=Vec2(-mov_speed_player_vert, 0.0)
                    )
                )

        if key_map[pygame.K_RIGHT]:
            for e in entities:
                e.send_msg(
                    UpdateTransform2DMessage(
                        translate_vec=Vec2(mov_speed_player_vert, 0.0)
                    )
                )
Exemplo n.º 2
0
def init_ecs(screen_width, screen_height, verbose: bool = True):
    if verbose:
        print("Initializing ECS objects")
    # we put the player at 0,0 at let her view at positive x=+1
    entities, components, systems = [], [], []

    ctrans = CTransform2(pos=Point2(100, 100), v_dir=Vec2(1, 0))
    cvel = CVelocity(velocity=5)
    cfov = CFieldOfView(fov_angle_rad=pi / 4.0, fov_distance=100.0)
    crnd = CRenderable(render_color=(64, 64, 228))
    components.append(ctrans)
    components.append(cvel)
    components.append(cfov)
    components.append(crnd)

    e_player = EPlayer().add(ctrans).add(cvel).add(crnd).add(cfov)
    entities.append(e_player)

    box_pos_x = (50, 100, 200, 400, 450, 500, 550, 600, 620)
    box_pos_y = (100, 200, 50, 100, 300, 400, 250, 100, 225)
    box_width = (20, 50, 10, 40, 20, 30, 50, 10, 10)

    for i, p in enumerate(zip(box_pos_x, box_pos_y)):
        ctrans = CTransform2(p, Vec2(0, 0))
        crnd = CRenderable(
            render_color=(200, 200, 200), shape=Shape.Square, width=box_width[i]
        )
        components.append(ctrans)
        components.append(crnd)

        n1 = Vec2(0, 1)
        o1 = Vec2(p[0] + box_width[i] // 2, p[1])
        p1 = Plane2(n1, o1)

        n2 = Vec2(1, 0)
        o2 = Vec2(p[0] + box_width[i], p[1] + box_width[i] // 2)
        p2 = Plane2(n2, o2)

        n3 = Vec2(0, -1)
        o3 = Vec2(p[0] + box_width[i] // 2, p[1] + box_width[i])
        p3 = Plane2(n3, o3)

        n4 = Vec2(-1, 0)
        o4 = Vec2(p[0], p[1] + box_width[i] // 2)
        p4 = Plane2(n4, o4)

        planes = [p1, p2, p3, p4]
        ccol = CCollidable(planes=planes)
        components.append(ccol)
        e_box = EBox().add(ctrans).add(crnd).add(ccol)
        entities.append(e_box)

    systems.append(SInput())
    systems.append(SRender(screen_width, screen_height))

    return components, entities, systems
 def __init__(self, w, h):
     super(BoxEntity, self).__init__()
     w2 = w // 2
     h2 = h // 2
     self._center = Point2(0, 0)
     self._width = w
     self._height = h
     self._w2 = w2
     self._h2 = h2
     self._p0 = self._center + Vec2(-w2, h2)
     self._p1 = self._center + Vec2(-w2, -h2)
     self._p2 = self._center + Vec2(w2, -h2)
     self._p3 = self._center + Vec2(w2, h2)
def setup_ecs() -> tuple:
    trans = Transform2DComponent(Point2(a=0, b=0))
    player = PlayerEntity(r=20).add(trans)
    kb_sys = KeyboardInputSystem()
    t_sys = RenderSystem(screen_width=640, screen_height=480)

    entities = [player]
    components = [trans]
    # we add some very large boxes that are out of view initially, but gradually become visible if we move to the left or right
    # end of the world
    box_pos_x = (-300, -200, -50, 0, 100, 300, 250, 500, 1000, -1000)
    box_pos_y = (-300, 100, -200, 300, -300, 40, 40, 100, 200, 300)
    box_width = (10, 20, 50, 10, 30, 10, 40, 10, 20, 100, 100)

    debug = False
    if debug:
        box_pos_x = ()
        box_pos_y = ()
        box_width = ()

    for (x, y, w) in zip(box_pos_x, box_pos_y, box_width):
        t = Transform2DComponent(pos=Vec2(x, y))
        b = BoxEntity(w=w, h=w).add(t)
        entities.append(b)
        components.append(t)

    kb_sys.on_key_pressed = handle_key_pressed_event(kb_sys)
    systems = {"KEYBOARD": kb_sys, "TRANSFORM": t_sys}
    return entities, components, systems
    def update(self, time_delta: float, entities: list):
        if not entities or len(entities) < 1:
            return None

        req_update = [e for e in entities if e.has_component_type("Transform2D")]

        self.clear_buffer(self._back_buffer, RenderSystem.C_WHITE)

        # before we update the entities in the world, we need to align the camera with the player.
        # here, we do a simple look for the player and position the camera at some offset from the player
        cam_offset = Vec2(-50, -50)
        player = [e for e in entities if isinstance(e, PlayerEntity)][0]
        # get the current transform - since this will determine our cam position
        p_trans: Transform2DComponent = player.get_of_type("Transform2D")
        p_pos = p_trans.position
        # since we want to align the camera with the players position, we transform him to the origin and apply the
        # camera local-world transformation. we do this by getting the inverse transformation of the player
        # and multiply this with the camera world transformation.
        # since the player is a translation only, we construct the inverse by hand, by taking the negative translation
        inverse_p = translate2D(-p_pos.x, -p_pos.y)
        cam_p = translate2D(cam_offset.x, cam_offset.y)
        final_p = cam_p * inverse_p
        # now here we set the camera world transformation, so that our overall transformation is ...
        # take the primitive, apply the normalized (0,0) to object-local transform
        # take the output and apply the object-local to world transform (final p)
        # we could achieve the same by multiplying final p with the transformation matrix stored in the entity's
        # transform component and applying that
        self._cam2d.mat_ws = final_p

        for e in req_update:
            # the transform component needs to be applied to the entity
            e_trans = e.get_of_type("Transform2D")
            # e_mat   = final_p * e_trans.transform
            e_mat = e_trans.transform
            e_points = e.points

            eg_points = [e_mat * Vec3(p.x, p.y, 1.0) for p in e_points]
            ws_points = [self._cam2d.project_ws(p) for p in eg_points]
            nc_points = [self._cam2d.project_nc(p) for p in ws_points]

            fully_visible = all([self._cam2d.is_visible(p) for p in nc_points])
            if not fully_visible:
                # print("{} is not fully visible".format(e))
                next

            vp_points = [self._cam2d.project_vp(p) for p in nc_points]

            if isinstance(e, PlayerEntity):
                draw_player(self._back_buffer, e.radius, *vp_points)
            else:
                draw_box(self._back_buffer, *vp_points)

        self._screen_buffer.blit(self._back_buffer, (0, 0))
        pygame.display.flip()
Exemplo n.º 6
0
 def handle_orientation_update(self, delta_angle: float):
     orientation = self.transform.viewing_direction
     rorientation = orientation.to_angle() % (pi * 2.0)
     aorientation = elisa.linalg.rad_to_angle(rorientation)
     s_angle = 1.0 if delta_angle >= 0 else -1.0
     aorientation = aorientation + s_angle * elisa.linalg.rad_to_angle(
         abs(delta_angle)
     )
     aorientation = aorientation % 360.0
     orientation = elisa.linalg.angle_to_rad(aorientation)
     self.transform.viewing_direction = Vec2.from_angle(orientation)
 def __init__(self, pos: Point2):
     super(Transform2DComponent, self).__init__("Transform2D")
     self._position = pos
     self._rotation = 0.0
     self._scale = Vec2(1.0, 1.0)
Exemplo n.º 8
0
    def update(self, time_delta, entities):
        if len(entities) < 1:
            return None

        pvis = [e for e in entities if e.has_component_type("Collidable")]

        # for now we just render everyone having a position component
        # and do not care about the projection from world space coordinates to camera space
        renderables = [
            e
            for e in entities
            if e.has_component_type("Renderable") and e.has_component_type("Transform2")
        ]

        # clear the backbuffer
        self.clear_back_buffer()

        for e in renderables:
            # get the position of the renderable and draw it - for now we assume that there is only one
            pos = e.get_of_type("Transform2").position
            rx = e.get_of_type("Renderable")
            col = rx.color

            if rx.shape == Shape.Point:
                pygame.draw.circle(
                    self.back_buffer, col, (int(pos.x), int(pos.y)), 5, 0
                )
            elif rx.shape == Shape.Square:
                pygame.draw.rect(
                    self.back_buffer,
                    SRender.C_DARK_GRAY,
                    (pos.x, pos.y, rx.width, rx.width),
                    1,
                )
            else:
                pass

        fov_entity = [
            e
            for e in entities
            if e.has_component_type("FieldOfView")
            and e.has_component_type("Transform2")
        ]

        if fov_entity:
            for e in fov_entity:
                transform = e.get_of_type("Transform2")
                fov = e.get_of_type("FieldOfView")

                pos, dvec = transform.position, transform.viewing_direction
                view_dist = fov.distance
                dvec_alpha = dvec.to_angle()
                fov_angle = fov.angle
                falpha1, falpha2 = (dvec_alpha - fov_angle / 2.0) % (
                    2.0 * pi
                ), dvec_alpha + fov_angle / 2.0 % (2.0 * pi)
                N_sample = int(elisa.linalg.rad_to_angle(fov_angle))
                v1 = Vec2.from_angle(falpha1) * view_dist
                v2 = Vec2.from_angle(falpha2) * view_dist
                dv = (v2 - v1) / N_sample
                pdvi = v1

                pv1, pv2 = pos + v1, pos + v2
                pygame.draw.polygon(
                    self.back_buffer,
                    SRender.C_VDARK_GRAY,
                    [(pos.x, pos.y), (pv1.x, pv1.y), (pv2.x, pv2.y)],
                    0,
                )

                for i in range(N_sample):
                    # perform the collision test
                    ppvi = pos + pdvi
                    pdvi = pdvi + dv
                    rayi = Ray2(origin=pos, direction=pdvi)
                    for vis in pvis:
                        visplanes = vis.get_of_type("Collidable").planes
                        vpos = vis.get_of_type("Transform2").position
                        vrx = vis.get_of_type("Renderable")

                        intersects = False
                        for planei in visplanes:
                            r, t, _ip = elisa.linalg.intersection2(rayi, planei)
                            if (
                                r
                                and 0 <= t <= pdvi.length
                                and elisa.linalg.inside_square2(
                                    vpos.x, vpos.y, vrx.width, _ip
                                )
                            ):
                                intersects = True
                                break

                        if intersects:
                            pygame.draw.line(
                                self.back_buffer,
                                SRender.C_GRAY,
                                (pos.x, pos.y),
                                (ppvi.x, ppvi.y),
                                1,
                            )
                            pygame.draw.rect(
                                self.back_buffer,
                                SRender.C_WHITE,
                                (vpos.x, vpos.y, vrx.width, vrx.width),
                                1,
                            )

                pygame.draw.circle(
                    self.back_buffer,
                    SRender.C_DARK_GRAY,
                    (int(pos.x), int(pos.y)),
                    int(view_dist),
                    1,
                )

        self.screen_buffer.blit(self.back_buffer, (0, 0))
        pygame.display.flip()

        return None