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);
}

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);

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);

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);
}

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;
}

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.

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;

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;
}

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).

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);
}

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