EPhysics - Logo

The purpose of this example is to demonstrate the EPhysics_Logo.

For this example we'll have an EPhysics_World.

The basic concepts like - initializing an EPhysics_World, render geometry, physics limiting boundaries, were already covered in EPhysics - Bouncing Ball

Logo 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 letter_desc {
const char *letter;
int padding;
} falling_letters[] = {
{"P", PADDING_X_1},
{"H", PADDING_X_1},
{"Y", PADDING_X_3},
{"S1", PADDING_X_2},
{"I", PADDING_X_2},
{"C", PADDING_X_3},
{"S2", 0}
};

Adding the letters

To add the letters we'll use this function that creates the shadow, light and letter images.

_letter_add(Evas *evas, const char *letter, Evas_Object **image, Evas_Object **light, Evas_Object **shadow)
{
int w, h, sh_w, sh_h;
char buf[1024];
snprintf(buf, sizeof(buf), PACKAGE_DATA_DIR "/logo_shadow-%s.png", letter);
evas_object_image_file_set(*shadow, buf, NULL);
evas_object_image_size_get(*shadow, &sh_w, &sh_h);
evas_object_resize(*shadow, sh_w, sh_h);
evas_object_color_set(*shadow, 0, 0, 0, 0);
evas_object_layer_set(*shadow, LAYER_SHADOW);
evas_object_show(*shadow);
snprintf(buf, sizeof(buf), PACKAGE_DATA_DIR "/logo_letter-%s.png", letter);
evas_object_image_file_set(*image, buf, NULL);
evas_object_image_size_get(*image, &w, &h);
evas_object_resize(*image, w, h);
evas_object_layer_set(*image, LAYER_LETTER);
snprintf(buf, sizeof(buf), PACKAGE_DATA_DIR "/logo_light-%s.png", letter);
evas_object_image_file_set(*light, buf, NULL);
evas_object_resize(*light, w, h);
evas_object_layer_set(*light, LAYER_LETTER);
/* allow easy access to shadow and light from the letter image */
evas_object_data_set(*image, "shadow", *shadow);
evas_object_data_set(*image, "light", *light);
}
Eo Evas
An opaque handle to an Evas canvas.
Definition: Evas_Common.h:163
EVAS_API void evas_object_show(Evas_Object *eo_obj)
Makes the given Evas object visible.
Definition: evas_object_main.c:1814
EVAS_API void evas_object_color_set(Evas_Object *obj, int r, int g, int b, int a)
Sets the general/main color of the given Evas object to the given one.
Definition: evas_object_main.c:2024
EVAS_API void evas_object_data_set(Evas_Object *eo_obj, const char *key, const void *data)
Set an attached data pointer to an object with a given string key.
Definition: evas_data.c:5
EVAS_API void evas_object_layer_set(Evas_Object *obj, short l)
Sets the layer of its canvas that the given object will be part of.
Definition: evas_layer.c:212
Efl_Canvas_Object Evas_Object
An Evas Object handle.
Definition: Evas_Common.h:185
EVAS_API void evas_object_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
Changes the size of the given Evas object.
Definition: evas_object_main.c:1236
EVAS_API void evas_object_image_size_get(const Evas_Object *obj, int *w, int *h)
Retrieves the size of the given image object.
Definition: evas_image_legacy.c:159
EVAS_API void evas_object_image_file_set(Evas_Object *obj, const char *file, const char *key)
Set the source file from where an image object must fetch the real image data (it may be an Eet file,...
Definition: evas_image_legacy.c:194
EVAS_API Evas_Object * evas_object_image_filled_add(Evas *eo_e)
Creates a new image object that automatically scales its bound image to the object's area,...
Definition: evas_image_legacy.c:35

In this loop we'll use the function letter_add using the falling_letters declared in logo data struct.

for (i = 0; i < EINA_C_ARRAY_LENGTH(falling_letters); i++)
{
_letter_add(evas, falling_letters[i].letter, &image, &light, &shadow);
evas_object_image_size_get(shadow, &sh_w, NULL);
#define EINA_C_ARRAY_LENGTH(arr)
Macro to return the array length of a standard c array.
Definition: eina_types.h:621

Place image and light on top, above what the viewport can show, to fall later on.

evas_object_move(image, x, -h * (i + 1) - 50);
evas_object_move(light, x, -h * (i + 1) - 50);
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

Place shadow below the hit-line: FLOOR_Y, centered at image.

evas_object_move(shadow, x + CENTER(w, sh_w), FLOOR_Y);

Here we set the letters padding and add letter body using the function below and setting its friction.

x += falling_letters[i].padding + w;
letter_body = _letter_body_box_add(world, image);
ephysics_body_friction_set(letter_body, 0.4);
}
EAPI void ephysics_body_friction_set(EPhysics_Body *body, double friction)
Set body's friction.

Here we call another function that will be common to the circle body as well, note that we add a callback that will be explained later.

_letter_body_box_add(EPhysics_World *world, Evas_Object *image)
{
_letter_body_setup_common(body, image);
(body, EPHYSICS_CALLBACK_BODY_UPDATE, _update_box_cb, NULL);
return body;
}
EAPI EPhysics_Body * ephysics_body_box_add(EPhysics_World *world)
Create a new box physics body.
EAPI void ephysics_body_event_callback_add(EPhysics_Body *body, EPhysics_Callback_Body_Type type, EPhysics_Body_Event_Cb func, const void *data)
Register a callback to a type of physics body event.
struct _EPhysics_Body EPhysics_Body
Body handle, represents an object on EPhysics world.
Definition: EPhysics.h:655
@ EPHYSICS_CALLBACK_BODY_UPDATE
Body being updated.
Definition: EPhysics.h:2263
struct _EPhysics_World EPhysics_World
World handle, most basic type of EPhysics.
Definition: EPhysics.h:901

This function is used to create the body setting its properties. Note that we disable its angular movement (rotation) on Z axis to this letters don't tilt or recline.

_letter_body_setup_common(EPhysics_Body *body, Evas_Object *view)
{
}
EAPI void ephysics_body_angular_movement_enable_set(EPhysics_Body *body, Eina_Bool enable_x, Eina_Bool enable_y, Eina_Bool enable_z)
Enable or disable body's rotation on z axis.
EAPI void ephysics_body_evas_object_set(EPhysics_Body *body, Evas_Object *evas_obj, Eina_Bool use_obj_pos)
Set an evas object to a physics body.
EAPI void ephysics_body_restitution_set(EPhysics_Body *body, double restitution)
Set body's coefficient of restitution.
EAPI void ephysics_body_mass_set(EPhysics_Body *body, double mass)
Set body's mass.
#define EINA_TRUE
boolean value TRUE (numerical value 1)
Definition: eina_types.h:539
#define EINA_FALSE
boolean value FALSE (numerical value 0)
Definition: eina_types.h:533

In this callback function that we added to our letter body we'll update its light and shadow.

First we'll update the body, get its image geometry and set the floor distance based on images height.

_update_box_cb(void *data __UNUSED__, EPhysics_Body *body, void *event_info)
{
Evas_Object *image = event_info;
Evas_Object *shadow = evas_object_data_get(image, "shadow");
Evas_Object *light = evas_object_data_get(image, "light");
int x, y, w, h, floor_distance, alpha = 0;
/* modify the evas object according to the body */
evas_object_geometry_get(image, &x, &y, &w, &h);
floor_distance = FLOOR_Y - h;
EAPI void ephysics_body_evas_object_update(EPhysics_Body *body)
Update the evas object associated to the body.
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
EVAS_API void * evas_object_data_get(const Evas_Object *obj, const char *key)
Return an attached data pointer on an Evas object by its given string key.
Definition: evas_data.c:12

As long as the letter approaches the floor, its shadow is darker, with bigger y.

if (y > SH_THRESHOLD)
{
int sh_w, sh_h;
double pos_x;
evas_object_image_size_get(shadow, &sh_w, &sh_h);
alpha = 255 * (y - SH_THRESHOLD) / (floor_distance - SH_THRESHOLD);

And with bigger x – its proportional to x / WIDTH, but varies from 100 to 255

pos_x = (double) x / (WIDTH - w);
alpha = alpha * PROP_GET(pos_x, 100, 255);

Note that the box shadow is not resized, just moved. And here set also the colors.

evas_object_move(shadow, x + CENTER(w, sh_w) + SH_OFFSET_X,
FLOOR_Y - sh_h + 2);
}
evas_object_color_set(shadow, alpha, alpha, alpha, alpha);

As long as the letter approaches the floor, its lighter, with bigger x and y.

evas_object_move(light, x, y);
alpha = (y <= 0) ? 0 : y * 255 / floor_distance;
alpha = alpha * (x - OFFSET_X + 80) / (WIDTH - OFFSET_X);
evas_object_color_set(light, alpha, alpha, alpha, alpha);
}

Adding the letter E

Here we'll add the last letter, "E" is a circle that comes rolling on the floor.

First we use the letter_add function, set its shadow color and get its sizes.

_letter_add(evas, "E", &image, &light, &shadow);
evas_object_color_set(shadow, 255, 255, 255, 255);
evas_object_image_size_get(shadow, &sh_w, NULL);

Place image and light above the floor and to the left of viewport, to comes rolling later on.

evas_object_move(image, -w - 1, FLOOR_Y - h + 1);
evas_object_move(light, -w - 1, FLOOR_Y - h + 1);

Place the shadow below the hit-line: FLOOR_Y centered at image.

evas_object_move(shadow, -w - 1 + CENTER(w, sh_w), FLOOR_Y);

Here we create the body using body_circle function and enable its rotation on Z axis.

Make the "E" logo get into the viewport by applying a horizontal force.

Here we use the letter_body_setup_common to create the body and set its properties, note that we add a callback that will be explained below.

_letter_body_circle_add(EPhysics_World *world, Evas_Object *image)
{
_letter_body_setup_common(body, image);
(body, EPHYSICS_CALLBACK_BODY_UPDATE, _update_circle_cb, NULL);
return body;
}
EAPI EPhysics_Body * ephysics_body_cylinder_add(EPhysics_World *world)
Create a new cylinder physics body.

In this callback function that we added to our "E" letter body we'll update its light and shadow.

First we'll update the body and get its image geometry.

_update_circle_cb(void *data __UNUSED__, EPhysics_Body *body, void *event_info)
{
Evas_Object *image = event_info;
Evas_Object *shadow = evas_object_data_get(image, "shadow");
Evas_Object *light = evas_object_data_get(image, "light");
int x, y, w, h, sh_w, sh_h, alpha = 0;
const Evas_Map *map;
/* modify the evas object according to the body */
evas_object_geometry_get(image, &x, &y, &w, &h);

As long as the letter approaches the floor, its lighter, with bigger x.

evas_object_move(light, x, y);
alpha = x * 255 / (WIDTH - w);
evas_object_color_set(light, alpha, alpha, alpha, alpha);

Use the same map from image to the light (rotate it).

map = evas_object_map_get(image);
evas_object_map_set(light, map);
EVAS_API const Evas_Map * evas_object_map_get(const Evas_Object *eo_obj)
Get current object transformation map.
Definition: evas_map.c:649
EVAS_API void evas_object_map_set(Evas_Object *eo_obj, const Evas_Map *map)
Set current object transformation map.
Definition: evas_map.c:532
EVAS_API void evas_object_map_enable_set(Eo *eo_obj, Eina_Bool enabled)
Enable or disable the map that is set.
Definition: evas_map.c:516

As long as the letter approaches the floor, its shadow is darker, with bigger y.

evas_object_image_size_get(shadow, &sh_w, &sh_h);
evas_object_move(shadow, x + CENTER(w, sh_w) + SH_OFFSET_X,
FLOOR_Y - sh_h + 2);
alpha = 127 + alpha / 2;
evas_object_color_set(shadow, alpha, alpha, alpha, alpha);

When the letter "E" passes the viewport, we send it to the begin again to collide with the other letters.

if (x > E_THRESHOLD)
ephysics_body_move(body, -w - 1, y, -15);
}
EAPI void ephysics_body_move(EPhysics_Body *body, Evas_Coord x, Evas_Coord y, Evas_Coord z)
Set physics body position.

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