Drawing your graphics

Now that you have initialized the application, it's time to start coding the main parts. We'll now walk through how the application handles screen events and how to start drawing graphics using OpenGL ES.

In main(), we invoke the following two functions:

  • The handleScreenEvent() function determines the type of screen event that has occurred and responds accordingly.
  • The render() function draws the square on the screen.

As long as the NAVIGATOR_EXIT event has not occurred, this frame loop continues to execute. The loop calls handleScreenEvent() to handle new events and render() to update the display.

while (!exit_application) {
     //Request and process all available BPS events
     bps_event_t *event = NULL;

    for(;;) {
        if (BPS_SUCCESS != bps_get_event(&event, 0)) {
            fprintf(stderr, "bps_get_event failed\n");
            break;
        }
 
        if (event) {
            int domain = bps_event_get_domain(event);

            if (domain == screen_get_domain()) {
                handleScreenEvent(event);
            } else if ((domain == navigator_get_domain())
                    && (NAVIGATOR_EXIT == bps_event_get_code(event))) {
                exit_application = 1;
            }
        } else {
            break;
        }
    }
    render();
 }

Handle screen events

For all screen events, we do the following in handleScreenEvent():

Extract the screen event from the generic BlackBerry Platform Services event that we received by invoking screen_event_get_event().

screen_event_t screen_event = screen_event_get_event(event);

Determine the type of screen event that occurred and the position of the event on the screen. Every screen event is associated with a set of properties. You can query these properties by using the screen_get_event_property_iv() function, which is part of screen.h. For more information on event structure and other properties that can be queried in this context, refer to the screen.h library. Here, we determine the type of screen event and store it in screen_val.

int screen_val;
screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &screen_val);

If the event is a touch screen event, determine the type of touch screen event that occurred. Touch screen events have codes associated with them, which are listed in the screen.h library.

switch (screen_val) {

    case SCREEN_EVENT_MTOUCH_TOUCH:
    case SCREEN_EVENT_MTOUCH_MOVE:
    case SCREEN_EVENT_MTOUCH_RELEASE:

break;
}

Although this project template does not perform any actions for the different types of events, you can add code here that is appropriate for your application. Now that the framework is in place, you can try experimenting with it on your device or simulator before moving on.

Render the square

It's useful to organize your per-frame OpenGL ES code into a single function. We've called ours render() and we do the following:

Invoke glClear(). This function simply clears the color and depth buffers.

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Enable GL_VERTEX_ARRAY state and provide an array of vertices that describes our simple square.

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, vertices);

Similarly, enable GL_COLOR ARRAY state and provide an array that defines a color of each of our vertices.

glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_FLOAT, 0, colors);

Add a small rotation with respect to the vertical axis and then render the square. This way, our square rotates gradually on every frame.

glRotatef(0.5f, 0.0f, 1.0f, 0.0f);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

Even though it's not necessary to disable these client states in our specific sample, it's generally a good practice to disable all client states that were used by the current rendering logic. This simple step can save you a lot of time in front of the debugger as EGL code is typically quite difficult to debug.

glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);

After the frame is complete, it must be displayed on the screen. We invoke bbutil_swap() as all our EGL interactions are handled by bbutil.h (which simply calls eglSwapBuffers with an error check).

bbutil_swap();

Clean up your application

After the user triggers the application to close (using the navigator), the NAVIGATOR_EXIT event is generated. A short time is given for your application to exit cleanly, but if it does not, the OS terminates the application's process.

To perform a clean exit, we add termination code to the end of main.c. This stops screen events, shuts down the BlackBerry Platform Services library, cleans up EGL artifacts, and destroys the screen context.

screen_stop_events(screen_cxt);
bps_shutdown();
bbutil_terminate();
screen_destroy_context(screen_cxt);
return 0;

That's it! You can now extend this template to change the graphics, modify the screen, and handle touch events to add different features to your application.