void templateAppDraw( void ) { glClearColor( 0.5f, 0.5f, 0.5f, 1.0f ); glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ); GFX_set_matrix_mode( PROJECTION_MATRIX ); GFX_load_identity(); GFX_set_perspective( 80.0f, ( float )viewport_matrix[ 2 ] / ( float )viewport_matrix[ 3 ], 1.0f, 1000.0f, -90.0f ); if( game_over == 2 ) { templateAppExit(); load_game(); game_over = 0; } GFX_set_matrix_mode( MODELVIEW_MATRIX ); GFX_load_identity(); if( view_delta.x || view_delta.y ) { if( view_delta.y ) next_rotz -= view_delta.y; if( view_delta.x ) { next_rotx -= view_delta.x; next_rotx = CLAMP( next_rotx, 0.0f, 90.0f ); } view_delta.x = view_delta.y = 0.0f; } rotx = rotx * 0.9f + next_rotx * 0.1f; rotz = rotz * 0.9f + next_rotz * 0.1f; eye.x = center.x + distance * cosf( rotx * DEG_TO_RAD ) * sinf( rotz * DEG_TO_RAD ); eye.y = center.y - distance * cosf( rotx * DEG_TO_RAD ) * cosf( rotz * DEG_TO_RAD ); eye.z = center.z + distance * sinf( rotx * DEG_TO_RAD ); rotx = rotx * 0.9f + next_rotx * 0.1f; rotz = rotz * 0.9f + next_rotz * 0.1f; center.x = maze->location.x; center.y = maze->location.y; center.z = maze->location.z; GFX_look_at( &eye, ¢er, &up ); if( double_tap ) { vec3 location; if( GFX_unproject( view_location.x, viewport_matrix[ 3 ] - view_location.y, 1.0f, GFX_get_modelview_matrix(), GFX_get_projection_matrix(), viewport_matrix, &location.x, &location.y, &location.z ) ) { btVector3 ray_from( eye.x, eye.y, eye.z ), ray_to( location.x + eye.x, location.y + eye.y, location.z + eye.z ); btCollisionWorld::ClosestRayResultCallback collision_ray( ray_from, ray_to ); dynamicsworld->rayTest( ray_from, ray_to, collision_ray ); if( collision_ray.hasHit() && collision_ray.m_collisionObject == maze->btrigidbody ) { collision_ray.m_hitNormalWorld.normalize(); if( collision_ray.m_hitNormalWorld.z() == 1.0f ) { navigationpath_player.start_location.x = player->location.x; navigationpath_player.start_location.y = player->location.y; navigationpath_player.start_location.z = player->location.z; navigationpath_player.end_location.x = collision_ray.m_hitPointWorld.x(); navigationpath_player.end_location.y = collision_ray.m_hitPointWorld.y(); navigationpath_player.end_location.z = collision_ray.m_hitPointWorld.z(); if( NAVIGATION_get_path( navigation, &navigationpath_player, &navigationpathdata_player ) ) { player_next_point = 1; unsigned int i = 0; while( i != navigationpathdata_player.path_point_count + 1 ) { console_print( "%d: %f %f %f\n", i, navigationpathdata_player.path_point_array[ i ].x, navigationpathdata_player.path_point_array[ i ].y, navigationpathdata_player.path_point_array[ i ].z ); ++i; } printf( "\n" ); } } } } double_tap = 0; } if( navigationpathdata_player.path_point_count ) { vec3 color = { 0.0f, 0.0f, 1.0f }; draw_navigation_points( &navigationpathdata_player, &color ); move_entity( player, &navigationpathdata_player, &player_next_point, 3.0f ); } static unsigned int start_time = get_milli_time(); if( get_milli_time() - start_time > 1000 ) { navigationpath_enemy.start_location.x = enemy->location.x; navigationpath_enemy.start_location.y = enemy->location.y; navigationpath_enemy.start_location.z = enemy->location.z; navigationpath_enemy.end_location.x = player->location.x; navigationpath_enemy.end_location.y = player->location.y; navigationpath_enemy.end_location.z = player->location.z; NAVIGATION_get_path( navigation, &navigationpath_enemy, &navigationpathdata_enemy ); enemy_next_point = 1; start_time = get_milli_time(); } if( navigationpathdata_enemy.path_point_count ) { vec3 color = { 1.0f, 0.0f, 0.0f }; move_entity( enemy, &navigationpathdata_enemy, &enemy_next_point, 4.0f ); draw_navigation_points( &navigationpathdata_enemy, &color ); } PROGRAM_draw( program ); glUniform1i( PROGRAM_get_uniform_location( program, ( char * )"DIFFUSE" ), 1 ); unsigned int i = 0; while( i != obj->n_objmesh ) { OBJMESH *objmesh = &obj->objmesh[ i ]; GFX_push_matrix(); mat4 mat; objmesh->btrigidbody->getWorldTransform().getOpenGLMatrix( ( float * )&mat ); memcpy( &objmesh->location, ( vec3 * )&mat.m[ 3 ], sizeof( vec3 ) ); GFX_multiply_matrix( &mat ); glUniformMatrix4fv( PROGRAM_get_uniform_location( program, ( char * )"MODELVIEWPROJECTIONMATRIX" ), 1, GL_FALSE, ( float * )GFX_get_modelview_projection_matrix() ); OBJ_draw_mesh( obj, i ); GFX_pop_matrix(); ++i; } if( !game_over ) dynamicsworld->stepSimulation( 1.0f / 60.0f ); else { GFX_set_matrix_mode( PROJECTION_MATRIX ); GFX_load_identity(); float half_width = ( float )viewport_matrix[ 2 ] * 0.5f, half_height = ( float )viewport_matrix[ 3 ] * 0.5f; GFX_set_orthographic_2d( -half_width, half_width, -half_height, half_height ); GFX_rotate( -90.0f, 0.0f, 0.0f, 1.0f ); GFX_translate( -half_height, -half_width, 0.0f ); GFX_set_matrix_mode( MODELVIEW_MATRIX ); GFX_load_identity(); vec4 color = { 0.0f, 0.0f, 0.0f, 1.0f }; char msg[ MAX_CHAR ] = {"GAME OVER!"}; if( !font ) { font = FONT_init( ( char * )"foo.ttf" ); FONT_load( font, font->name, 1, 64.0f, 512, 512, 32, 96 ); } float posx = ( viewport_matrix[ 3 ] * 0.5f ) - ( FONT_length( font, msg ) * 0.5f ), posy = viewport_matrix[ 2 ] - font->font_size; FONT_print( font, posx + 4.0f, posy - 4.0f, msg, &color ); color.y = 1.0f; FONT_print( font, posx, posy, msg, &color ); } }
void templateAppDraw( void ) { if( game_state == 2 ) { free_level(); load_level(); } glClearColor( 1.0f, 1.0f, 1.0f, 1.0f ); glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ); GFX_set_matrix_mode( PROJECTION_MATRIX ); GFX_load_identity(); GFX_set_perspective( 80.0f, ( float )viewport_matrix[ 2 ] / ( float )viewport_matrix[ 3 ], 0.1f, 50.0f, -90.0f ); GFX_set_matrix_mode( MODELVIEW_MATRIX ); GFX_load_identity(); /* Linearly interpolate the accelerometer values to get a smooth transition. */ next_accelerometer.x = accelerometer.x * 0.1f + next_accelerometer.x * 0.9f; next_accelerometer.y = accelerometer.y * 0.1f + next_accelerometer.y * 0.9f; /* Assign the current Y rotation of the accelerometer to the Z rotation of the camera, * multiplied by the accelerometer sensitivity factor. */ rotz += next_accelerometer.y * sensitivity; /* The forward vector of the ball. */ vec3 forward = { 0.0f, 1.0f, 0.0f }, /* The current direction vector of the ball. Basically, this is the forward vector rotated by the cameraÕs Z rotation. */ direction; /* If the game is running, let the user move the ball. */ if( !game_state ) { /* Pre-calculate a few variables before rotating the forward vector by the cameraÕs Z rotation. */ float r = rotz * DEG_TO_RAD, c = cosf( r ), s = sinf( r ); /* Rotate the forward vector and store the result into the direction variable. Because both vectors are already normalized, thereÕs no need to re-normalize them again. */ direction.x = c * forward.y - s * forward.x; direction.y = s * forward.y + c * forward.x; float speed = CLAMP( ( -next_accelerometer.x * sensitivity ) * ball_speed, -ball_speed, ball_speed ); /* Assign the direction vector multiplied by the current speed to the angular velocity of the ball. */ player->btrigidbody->setAngularVelocity( btVector3( direction.x * speed, direction.y * speed, 0.0f ) ); /* Activate the rigid body to make sure that the angular velocity will be applied. */ player->btrigidbody->setActivationState( ACTIVE_TAG ); } next_eye.x = player->location.x + distance * cosf( rotx * DEG_TO_RAD ) * sinf( rotz * DEG_TO_RAD ); next_eye.y = player->location.y - distance * cosf( rotx * DEG_TO_RAD ) * cosf( rotz * DEG_TO_RAD ); next_eye.z = player->location.z + distance * sinf( rotx * DEG_TO_RAD ); player->location.z += player->dimension.z; btVector3 p1( player->location.x, player->location.y, player->location.z ), p2( next_eye.x, next_eye.y, next_eye.z ); ClosestNotMeRayResultCallback back_ray( player->btrigidbody, p1, p2 ); dynamicsworld->rayTest( p1, p2, back_ray ); if( back_ray.hasHit() ) { back_ray.m_hitNormalWorld.normalize(); next_eye.x = back_ray.m_hitPointWorld.x() + ( back_ray.m_hitNormalWorld.x() * 0.1f ); next_eye.y = back_ray.m_hitPointWorld.y() + ( back_ray.m_hitNormalWorld.y() * 0.1f ); next_eye.z = back_ray.m_hitPointWorld.z() + ( back_ray.m_hitNormalWorld.z()* 0.1f ); } eye.x = next_eye.x * 0.05f + eye.x * 0.95f; eye.y = next_eye.y * 0.05f + eye.y * 0.95f; eye.z = next_eye.z * 0.05f + eye.z * 0.95f; /* Calculate the direction vector from the player to the current eye location. */ vec3_diff( &direction, &player->location, &eye ); /* Normalize the direction vector. */ vec3_normalize( &direction, &direction ); AUDIO_set_listener( &eye, &direction, &up ); GFX_look_at( &eye, &player->location, &up ); build_frustum( frustum, GFX_get_modelview_matrix(), GFX_get_projection_matrix() ); unsigned int i = 0; while( i != obj->n_objmesh ) { OBJMESH *objmesh = &obj->objmesh[ i ]; objmesh->distance = sphere_distance_in_frustum( frustum, &objmesh->location, objmesh->radius ); if( objmesh->distance && objmesh->visible ) { GFX_push_matrix(); /* Check if the current objmesh name contains Ògem.Ó * If yes, donÕt ask Bullet for the transformation matrix and handle the position and * rotation manually. */ if( strstr( objmesh->name, "gem" ) ) { GFX_translate( objmesh->location.x, objmesh->location.y, objmesh->location.z ); objmesh->rotation.z += 1.0f; GFX_rotate( objmesh->rotation.z, 0.0f, 0.0f, 1.0f ); } else if( objmesh->btrigidbody ) { mat4 mat; objmesh->btrigidbody->getWorldTransform().getOpenGLMatrix( ( float * )&mat ); memcpy( &objmesh->location, ( vec3 * )&mat.m[ 3 ], sizeof( vec3 ) ); GFX_multiply_matrix( &mat ); } else { GFX_translate( objmesh->location.x, objmesh->location.y, objmesh->location.z ); } OBJ_draw_mesh( obj, i ); GFX_pop_matrix(); } ++i; } dynamicsworld->stepSimulation( 1.0f / 60.0f ); GFX_set_matrix_mode( PROJECTION_MATRIX ); GFX_load_identity(); float half_width = ( float )viewport_matrix[ 2 ] * 0.5f, half_height = ( float )viewport_matrix[ 3 ] * 0.5f; GFX_set_orthographic_2d( -half_width, half_width, -half_height, half_height ); GFX_rotate( -90.0f, 0.0f, 0.0f, 1.0f ); GFX_translate( -half_height, -half_width, 0.0f ); GFX_set_matrix_mode( MODELVIEW_MATRIX ); GFX_load_identity(); vec4 font_color = { 0.0f, 0.0f, 0.0f, 1.0f }; char gem_str [ MAX_CHAR ] = {""}, time_str [ MAX_CHAR ] = {""}, level_str[ MAX_CHAR ] = {""}; if( game_state ) { sprintf( level_str, "Level Clear!" ); FONT_print( font_big, viewport_matrix[ 3 ] * 0.5f - FONT_length( font_big, level_str ) * 0.5f + 4.0f, viewport_matrix[ 2 ] - font_big->font_size * 1.5f - 4.0f, level_str, &font_color ); /* Yellow. */ font_color.x = 1.0f; font_color.y = 1.0f; font_color.z = 0.0f; FONT_print( font_big, viewport_matrix[ 3 ] * 0.5f - FONT_length( font_big, level_str ) * 0.5f, viewport_matrix[ 2 ] - font_big->font_size * 1.5f, level_str, &font_color ); } font_color.x = 0.0f; font_color.y = 0.0f; font_color.z = 0.0f; sprintf( gem_str, "Gem Points:%02d", gem_points ); sprintf( time_str, "Game Time:%02.2f", game_time * 0.1f ); FONT_print( font_small, viewport_matrix[ 3 ] - FONT_length( font_small, gem_str ) - 6.0f, ( font_small->font_size * 0.5f ), gem_str, &font_color ); FONT_print( font_small, 8.0f, ( font_small->font_size * 0.5f ), time_str, &font_color ); font_color.x = 1.0f; font_color.y = 1.0f; font_color.z = 0.0f; FONT_print( font_small, viewport_matrix[ 3 ] - FONT_length( font_small, gem_str ) - 8.0f, ( font_small->font_size * 0.5f ), gem_str, &font_color ); FONT_print( font_small, 6.0f, ( font_small->font_size * 0.5f ), time_str, &font_color ); if( !game_state ) game_time += SOUND_get_time( background_sound ); }
void templateAppDraw( void ) { if( game_state == 2 ) { free_level(); load_level(); } glClearColor( 1.0f, 1.0f, 1.0f, 1.0f ); glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ); GFX_set_matrix_mode( PROJECTION_MATRIX ); GFX_load_identity(); GFX_set_perspective( 80.0f, ( float )viewport_matrix[ 2 ] / ( float )viewport_matrix[ 3 ], 0.1f, 50.0f, 0.0f ); GFX_set_matrix_mode( MODELVIEW_MATRIX ); GFX_load_identity(); if(turn_left()) { next_rotz+=1.2; } if(turn_right()) { next_rotz-=1.2; } vec3 forward = { 0.0f, 1.0f, 0.0f },direction; if( !game_state ) { //Pre-calculate a few variables before rotating the forward vector by the camera's Z rotation. float r = rotz * DEG_TO_RAD, c = cosf( r ), s = sinf( r ); //Rotate the forward vector and store the result into the direction variable. Because //both vectors are already normalized, there's no need to re-normalize them one more time. direction.x = c * forward.y - s * forward.x; direction.y = s * forward.y + c * forward.x; //Calculate the current angular velocity that is relevant to the //accelerometer value that we are using as the force factor. //Then clamp the result to make sure that the speed is between the minimum and //maximum ball speed thresholds. float speed = CLAMP( -maximum_speed, -maximum_speed, maximum_speed ); player->btrigidbody->setAngularVelocity( btVector3( direction.x * speed,direction.y * speed,0.0f ) ); //Activate the rigid body to make sure that the angular velocity will be applied. player->btrigidbody->setActivationState( ACTIVE_TAG ); } /* if( view_delta.x || view_delta.y ) { if( view_delta.x ) next_rotz -= view_delta.x; if( view_delta.y ) { next_roty += view_delta.y; next_roty = CLAMP( next_roty, -180.0f, -90.0f ); } view_delta.x = view_delta.y = 0.0f; } if( move_delta.z ) { vec3 direction; float r = rotz * DEG_TO_RAD, c = cosf( r ), s = sinf( r ); direction.x = s * move_delta.y + c * move_delta.x; direction.y = c * move_delta.y - s * move_delta.x; player->btrigidbody->setAngularVelocity( 2*btVector3( -direction.y * ( move_delta.z * 6.7f ), -direction.x * ( move_delta.z * 6.7f ), 0.0f ) ); player->btrigidbody->setActivationState( ACTIVE_TAG ); }*/ //console_print("player_x: %3.f player_y: %3.f\n",player->location.x,player->location.y); next_eye.x = player->location.x + distance * cosf( roty * DEG_TO_RAD ) * sinf( rotz * DEG_TO_RAD ); next_eye.y = player->location.y - distance * cosf( roty * DEG_TO_RAD ) * cosf( rotz * DEG_TO_RAD ); next_eye.z = player->location.z + distance * sinf( roty * DEG_TO_RAD ); btVector3 p1( player->location.x, player->location.y, player->location.z ), p2( next_eye.x, next_eye.y, next_eye.z ); ClosestNotMeRayResultCallback back_ray( player->btrigidbody, p1, p2 ); dynamicsworld->rayTest( p1, p2, back_ray ); if( back_ray.hasHit() ) { back_ray.m_hitNormalWorld.normalize(); next_eye.x = back_ray.m_hitPointWorld.x() + ( back_ray.m_hitNormalWorld.x() * 0.1f ); next_eye.y = back_ray.m_hitPointWorld.y() + ( back_ray.m_hitNormalWorld.y()* 0.1f ); next_eye.z = back_ray.m_hitPointWorld.z() + ( back_ray.m_hitNormalWorld.z()* 0.1f ); } roty = roty * 0.9f + next_roty * 0.1f; rotz = rotz * 0.9f + next_rotz * 0.1f; eye.x = eye.x * 0.95f + next_eye.x * 0.05f; eye.y = eye.y * 0.95f + next_eye.y * 0.05f; eye.z = eye.z * 0.95f + next_eye.z * 0.05f; player->location.z += player->dimension.z * 0.5f; /* * needed for directional audio */ vec3 player_location={player->location.x,player->location.y,player->location.z}; AUDIO_set_listener( &eye, &player_location, &up ); GFX_look_at( &eye, &player->location, &up ); build_frustum( frustum, GFX_get_modelview_matrix(), GFX_get_projection_matrix() ); unsigned int i = 0; while( i != obj->n_objmesh ) { OBJMESH *objmesh = &obj->objmesh[ i ]; objmesh->distance = sphere_distance_in_frustum( frustum, &objmesh->location, objmesh->radius ); if( objmesh->distance && objmesh->visible ) { GFX_push_matrix(); if( strstr( objmesh->name, "gem" ) ) { GFX_translate( objmesh->location.x, objmesh->location.y, objmesh->location.z ); objmesh->rotation.z += 1.0f; GFX_rotate( objmesh->rotation.z, 0.0f, 0.0f, 1.0f ); } else if( objmesh->btrigidbody ) { mat4 mat; objmesh->btrigidbody->getWorldTransform().getOpenGLMatrix( ( float * )&mat ); memcpy( &objmesh->location, ( vec3 * )&mat.m[ 3 ], sizeof( vec3 ) ); GFX_multiply_matrix( &mat ); } else { GFX_translate( objmesh->location.x, objmesh->location.y, objmesh->location.z ); } OBJ_draw_mesh( obj, i ); GFX_pop_matrix(); } ++i; } if(!game_state ) { dynamicsworld->stepSimulation( 1.0f / 60.0f ); } GFX_set_matrix_mode( PROJECTION_MATRIX ); GFX_load_identity(); float half_width = ( float )viewport_matrix[ 2 ] * 0.5f, half_height = ( float )viewport_matrix[ 3 ] * 0.5f; GFX_set_orthographic_2d( -half_width, half_width, -half_height, half_height ); GFX_rotate( 0.0f, 0.0f, 0.0f, 1.0f ); GFX_translate( -half_width, -half_height, 0.0f ); GFX_set_matrix_mode( MODELVIEW_MATRIX ); GFX_load_identity(); vec4 font_color = { 0.0f, 0.0f, 0.0f, 1.0f }; char gem_str [ MAX_CHAR ] = {""}, time_str [ MAX_CHAR ] = {""}, level_str[ MAX_CHAR ] = {""}, pause_str [ MAX_CHAR ] = {""}; if( game_state == 3 ) { sprintf( pause_str, "Touch to Resume" ); FONT_print( font_big, viewport_matrix[ 2 ] * 0.5f - FONT_length( font_big, pause_str ) * 0.5f + 4.0f, viewport_matrix[ 3 ] * 0.7f - font_big->font_size * 1.5f - 4.0f, pause_str, &font_color ); /* Yellow. */ font_color.x = 1.0f; font_color.y = 1.0f; font_color.z = 0.0f; FONT_print( font_big, viewport_matrix[ 2 ] * 0.5f - FONT_length( font_big, pause_str ) * 0.5f, viewport_matrix[ 3 ] * 0.7f - font_big->font_size * 1.5f, pause_str, &font_color ); } if( game_state == 1 ) { sprintf( level_str, "Level Clear!" ); FONT_print( font_big, viewport_matrix[ 2 ] * 0.5f - FONT_length( font_big, level_str ) * 0.5f + 4.0f, viewport_matrix[ 3 ] - font_big->font_size * 1.5f - 4.0f, level_str, &font_color ); /* Yellow. */ font_color.x = 1.0f; font_color.y = 1.0f; font_color.z = 0.0f; FONT_print( font_big, viewport_matrix[ 2 ] * 0.5f - FONT_length( font_big, level_str ) * 0.5f, viewport_matrix[ 3 ] - font_big->font_size * 1.5f, level_str, &font_color ); } font_color.x = 0.0f; font_color.y = 0.0f; font_color.z = 0.0f; sprintf( gem_str, "Gem Points:%02d", gem_points ); sprintf( time_str, "Game Time:%02.2f", game_time * 0.1f ); FONT_print( font_small, viewport_matrix[ 2 ] - FONT_length( font_small, gem_str ) - 6.0f, ( font_small->font_size * 0.5f ), gem_str, &font_color ); FONT_print( font_small, 8.0f, ( font_small->font_size * 0.5f ), time_str, &font_color ); font_color.x = 1.0f; font_color.y = 1.0f; font_color.z = 0.0f; FONT_print( font_small, viewport_matrix[ 2 ] - FONT_length( font_small, gem_str ) - 8.0f, ( font_small->font_size * 0.5f ), gem_str, &font_color ); FONT_print( font_small, 6.0f, ( font_small->font_size * 0.5f ), time_str, &font_color ); if( !game_state ) game_time += SOUND_get_time( background_sound ); }