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) { glClearColor(0.5f, 0.5f, 0.5f, 1.0f); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); gfx->set_matrix_mode(MODELVIEW_MATRIX); gfx->load_identity(); /* First check if the direction vector on the X or Y axis was triggered * from the user touch on the right side of the screen. */ if (view_delta->x || view_delta->y) { /* If the Y is active (!=0), then add the value to the next Z * rotation. Since you are going to interpolate the rotation, you have to * assign the value to the next camera Z rotation. */ if (view_delta->y) next_rotz -= view_delta->y; /* Same as above, but this time for the X rotation axis. In addition, * clamp the value in the range of -180 to -90 degrees to allow the camera * to only look from straight up to straight down. */ if (view_delta->x) { next_rotx -= view_delta->x; next_rotx = CLAMP(next_rotx, -180.0f, -90.0f); } /* Reset the view deltas to avoid triggering another pass inside this * block on the next rendering pass. */ view_delta->x = view_delta->y = 0.0f; } /* If you got a force comming from the left side of the screen. */ if (move_delta->z) { /* Temp. variable to calculate the direction (aka forward) vector. */ vec3 direction; /* Rotate the coordinate system to fit the current Z rotation * of the camera. */ float r = rotz * DEG_TO_RAD, c = cosf(r), s = sinf(r); direction->x = c * move_delta->y - s * move_delta->x; direction->y = s * move_delta->y + c * move_delta->x; /* Assign the direction vector to the angular velocity of the ball. */ player->btrigidbody->setAngularVelocity(btVector3(direction->y * (move_delta->z * 6.7f), -direction->x * (move_delta->z * 6.7f), 0.0f)); /* Make sure the state of the rigid body is active in order to * trigger the rotation. */ 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); /* Declare the starting point and end point of the collision ray. * Basically, what you are trying to achieve is that the ray starts * from the ball and aims straight at the next_eye position. If anthing * collides with the ray (with the exception of the ball), you need to * re-adjust the next_eye position to be located where this is a hit. * This will prevent the camera from seeing through walls and insure * that the ball is focused at all times. */ btVector3 p1(player->location->x, player->location->y, player->location->z), p2(next_eye->x, next_eye->y, next_eye->z); /* Initialize the collision ray, passing in as parameters the ball rigid * body pointer and the start and end points of the ray. */ ClosestNotMeRayResultCallback back_ray(player->btrigidbody, p1, p2); /* Launch the ray in 3D space. */ dynamicsworld->rayTest(p1, p2, back_ray); /* If the collision ray got hit. */ if (back_ray.hasHit()) { /* Normalize the hit point normal. */ back_ray.m_hitNormalWorld.normalize(); /* Adjust the next_eye position to be located where the collision ray * hits inside the world. In addition, to make sure that the camera * stays inside the scene and does not simple "stick" on the wall, add * a slight offset based on the bit point normal. This will ensure that * the camera next_position will always be located in front of where * the collision ray hits. */ 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); } /* Linearly interpolate the rotation between the current and the next. */ rotx = rotx * 0.9f + next_rotx * 0.1f; rotz = rotz * 0.9f + next_rotz * 0.1f; /* Same as for the rotation, but this time for the current eye position. */ eye = eye * 0.95f + next_eye * 0.05f; /* Give an offset to the player Z location to make sure that the camera * is always looking at the top of the ball and not at it's center. This * way, even in tight corners, the user will always be able to see in front * of the ball. */ player->location->z += player->dimension->z * 0.5f; /* Feed the current eye position and player location to the GFX::look_at * function to be able to generate the view matrix. */ gfx->look_at(eye, player->location, up); for (auto objmesh=obj->objmesh.begin(); objmesh!=obj->objmesh.end(); ++objmesh) { gfx->push_matrix(); mat4 mat; objmesh->btrigidbody->getWorldTransform().getOpenGLMatrix(mat.m()); objmesh->location = vec3(mat[3], true); gfx->multiply_matrix(mat); glUniformMatrix4fv(program->uniform_map["MODELVIEWPROJECTIONMATRIX"].location, 1, GL_FALSE, gfx->get_modelview_projection_matrix().m()); objmesh->draw(); gfx->pop_matrix(); } dynamicsworld->stepSimulation(1.0f / 60.0f); }
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 ); }