EPhysics - Camera Track

The purpose of this example is to demonstrate the EPhysics_Camera Track usage.

The EPhysics_Camera facilitates the usage of scenarios bigger than the viewport, that's because the EPhysics handles the position of objects which has control.

For this example we'll have an EPhysics_World, one main EPhysics_Body that will be tracked by an EPhysics_Camera on three ways, horizontal, vertical and full tracking. Also nine EPhysics_Bodys with mass 0, that will be used as scenario in order to our main body change its position on x and y axes when passes through this scenario.

The basic concepts like - initializing an EPhysics_World, render geometry, physics limiting boundaries, add an Ephysics_Body, associate it to evas objects, change restitution, friction and impulse properties, were already covered in EPhysics - Bouncing Ball

# Track Data Struct

While in this example we'll be working with a struct to hold some objects in our code. For clarity sake we present you the struct declaration in the following block.

struct _Track_Data {
Test_Data base;
EPhysics_Body *body;
Evas_Object *sp;
int old_cx;
};
EPhysics_Body
struct _EPhysics_Body EPhysics_Body
Body handle, represents an object on EPhysics world.
Definition EPhysics.h:655
Evas_Object
Efl_Canvas_Object Evas_Object
An Evas Object handle.
Definition Evas_Common.h:185

# Adding a Camera

In this example we'll use 3 kinds of tracking, to change this values we'll have an Elementary spinner widget and handle it on this function.

Every world has a camera, so here we get this camera used by our EPhysics_World.

_track_apply(Track_Data *track_data)
{
Eina_Bool hor = EINA_FALSE;
Eina_Bool ver = EINA_FALSE;
EPhysics_Camera *camera;
EPhysics_Body *body;
int mode;
body = track_data->body;
camera = ephysics_world_camera_get(track_data->base.world);
EPhysics_Camera
struct _EPhysics_Camera EPhysics_Camera
Camera handle, used to change the position of the frame to be rendered.
Definition EPhysics.h:673
ephysics_world_camera_get
EAPI EPhysics_Camera * ephysics_world_camera_get(const EPhysics_World *world)
Get the camera used by an ephysics world.
EINA_FALSE
#define EINA_FALSE
boolean value FALSE (numerical value 0)
Definition eina_types.h:533
Eina_Bool
unsigned char Eina_Bool
Type to mimic a boolean.
Definition eina_types.h:527

Here we'll get the elm_spinner value to the tracking base on this value

mode = (int) elm_spinner_value_get(track_data->sp);
switch (mode)
{
case 1:
hor = EINA_TRUE;
break;
case 3:
hor = EINA_TRUE;
case 2:
ver = EINA_TRUE;
}
EINA_TRUE
#define EINA_TRUE
boolean value TRUE (numerical value 1)
Definition eina_types.h:539
elm_spinner_value_get
double elm_spinner_value_get(const Evas_Object *obj)
Control the value the spinner displays.
Definition elm_spinner.c:1387

Here we'll set the camera to track the body, when a body is tracked, the camera will move automatically, following this body. It will keeps the body centralized on rendered area. If it will be centralized horizontally and / or vertically depends if parameters horizontal and vertical are set to EINA_TRUE, in this case we based these values on elm_spinner.

ephysics_camera_body_track(camera, body, hor, ver);
}
ephysics_camera_body_track
EAPI void ephysics_camera_body_track(EPhysics_Camera *camera, EPhysics_Body *body, Eina_Bool horizontal, Eina_Bool vertical)
Set camera to track a body.

# Updating the floor

Here we'll use 2 floor images to give the impression of an infinite ground.

Calling ephysics_world_event_callback_add() will register a callback to a type of physics world event.

EPHYSICS_CALLBACK_WORLD_CAMERA_MOVED : called if the camera position changed on physics simulation tick.

ephysics_world_event_callback_add(world,
EPHYSICS_CALLBACK_WORLD_CAMERA_MOVED,
_camera_moved_cb, track_data);
ephysics_world_event_callback_add
EAPI void ephysics_world_event_callback_add(EPhysics_World *world, EPhysics_Callback_World_Type type, EPhysics_World_Event_Cb func, const void *data)
Register a callback to a type of physics world event.
EPHYSICS_CALLBACK_WORLD_CAMERA_MOVED
@ EPHYSICS_CALLBACK_WORLD_CAMERA_MOVED
camera position changed
Definition EPhysics.h:919

In the function, we'll get the cameras position to know how much the camera moved and move the same value to the floor passing it as delta_x to the function, note that we use an old_x variable to do this calculation.

We'll get also if the body is being tracked on x and y axes. If the body isn't being tracked on x axis the floors x position won't change, delta_x will be zero.

_camera_moved_cb(void *data, EPhysics_World *world __UNUSED__, void *event_info)
{
EPhysics_Camera *camera = event_info;
Track_Data *track_data = data;
int cx, cy, delta_x = 0;
Eina_Bool hor, ver;
DBG("Camera moved");
ephysics_camera_tracked_body_get(camera, NULL, &hor, &ver);
ephysics_camera_position_get(camera, &cx, &cy);
if (hor)
delta_x = track_data->old_cx - cx;
_update_floor(track_data->base.layout, "floor", delta_x, cy, ver);
_update_floor(track_data->base.layout, "floor2", delta_x, cy, ver);
track_data->old_cx = cx;
}
ephysics_camera_tracked_body_get
EAPI void ephysics_camera_tracked_body_get(EPhysics_Camera *camera, EPhysics_Body **body, Eina_Bool *horizontal, Eina_Bool *vertical)
Get body tracked by camera.
ephysics_camera_position_get
EAPI void ephysics_camera_position_get(const EPhysics_Camera *camera, Evas_Coord *x, Evas_Coord *y)
Get camera's position.
EPhysics_World
struct _EPhysics_World EPhysics_World
World handle, most basic type of EPhysics.
Definition EPhysics.h:901
DBG
#define DBG(...)
Macro for logging Eina debug messages.
Definition eina_file_common.h:179

Here we get the floors position and plus the delta_x value to move the floor in the same "velocity".

_update_floor(Evas_Object *layout, const char *name, int delta_x, int cy, Eina_Bool ver)
{
Evas_Object *floor_obj;
int x, y, fx, fy;
floor_obj = evas_object_data_get(layout, name);
evas_object_geometry_get(floor_obj, &x, &y, NULL, NULL);
fx = x + delta_x;
evas_object_geometry_get
EVAS_API void evas_object_geometry_get(const Evas_Object *eo_obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
Retrieves the position and (rectangular) size of the given Evas object.
Definition evas_object_main.c:1335

We use 2 floor images because whenever one exits the screen by the left side, another is being shown, when it happens the one which exit the screen is sent to the right side, entering into an infinite loop, giving the impression of an infinite ground image. Its important to note that we need to use the fx to don't gap the images.

Note that the fy is being defined considering its offsets, -20 is to the floor image be above the floor, thus having an border above the collision point, +40 is the render area height, to offset the cameras y, basically to draw in the correct position in the canvas.

if (fx < -FLOOR_WIDTH)
fx += 2 * FLOOR_WIDTH;
fy = (ver) ? FLOOR_Y - 20 - cy + 40 : y;
evas_object_move(floor_obj, fx, fy);
}
evas_object_move
EVAS_API void evas_object_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
Move the given Evas object to the given location inside its canvas' viewport.
Definition evas_object_main.c:1171

Here we finish the example. The full source code can be found at test_camera_track.c.