예제 #1
0
void cBackground::Update(void)
{
    if (!Is_Float_Equal(m_const_vel_x, 0.0f)) {
        m_pos_x += (m_const_vel_x * 2) * pFramerate->m_speed_factor;
    }

    if (!Is_Float_Equal(m_const_vel_y, 0.0f)) {
        m_pos_y += (m_const_vel_y * 2) * pFramerate->m_speed_factor;
    }
}
예제 #2
0
void cMovingSprite :: Handle_Move_Object_Collision( const cObjectCollision *collision )
{
	// if not massive
	if( m_massive_type != MASS_MASSIVE )
	{
		return;
	}

	// get object
	cMovingSprite *obj = NULL;

	if( collision->m_array == ARRAY_ENEMY )
	{
		obj = static_cast<cMovingSprite *>(pActive_Sprite_Manager->Get_Pointer( collision->number ));

		// ignore these enemies
		if( obj->m_type == TYPE_THROMP || obj->m_type == TYPE_EATO || obj->m_type == TYPE_FLYON || obj->m_type == TYPE_STATIC_ENEMY )
		{
			return;
		}
	}
	else if( collision->m_array == ARRAY_PLAYER )
	{
		obj = static_cast<cMovingSprite *>(pPlayer);
	}
	// not a valid type
	else
	{
		return;
	}

	// top collision is handled in cMovingSprite::Collide_Move()
	if( collision->direction == DIR_BOTTOM )
	{
		if( obj->m_ground_object && obj->m_ground_object->m_massive_type == MASS_MASSIVE )
		{
			// got crunched
			obj->DownGrade( 1 );
		}
		else
		{
			// move
			obj->Col_Move( 0.0f, m_vely, 0, 0, 0 );
		}
	}
	else if( ( collision->direction == DIR_LEFT && m_velx < 0.0f ) || ( collision->direction == DIR_RIGHT && m_velx > 0.0f ) )
	{
		// save posx for possible can not move test
		float posx_orig = obj->m_pos_x;
		// move with check on ground
		obj->Col_Move( m_velx, 0.0f, 0, 0 );

		// test if we could not move it upwards because something did block it
		if( Is_Float_Equal( obj->m_pos_x, posx_orig ) )
		{
			// got crunched
			obj->DownGrade( 1 );
		}
	}
}
예제 #3
0
void cEato::Update_Dying(void)
{
    m_counter += pFramerate->m_speed_factor;

    if (!Is_Float_Equal(m_rot_z, 180.0f))
    {
        Set_Active(0);
    }
    else
    {
        if (m_counter < 5.0f)
        {
            Move(0.0f, -5.0f);
        }
        else if (m_pos_y < game_res_h + m_col_rect.m_h)
        {
            Move(0.0f, 20.0f);
        }
        else
        {
            m_rot_z = 0.0f;
            Set_Active(0);
        }
    }
}
예제 #4
0
파일: spikeball.cpp 프로젝트: sKabYY/SMC
void cSpikeball :: Update_Dying( void )
{
	// stomp death
	if( !Is_Float_Equal( m_rot_z, 180.0f ) )
	{
		// scale out
		float speed = pFramerate->m_speed_factor * 0.05f;

		Add_Scale_X( -speed * 0.5f );
		Add_Scale_Y( -speed );

		if( m_scale_y < 0.01f )
		{
			Set_Scale( 1.0f );
			Set_Active( 0 );
		}
	}
	// falling death
	else
	{
		m_counter += pFramerate->m_speed_factor * 0.1f;

		// a little bit upwards first
		if( m_counter < 0.3f )
		{
			Move( 0.0f, -5.0f );
		}
		// if not below the ground : fall
		else if( m_col_rect.m_y < pActive_Camera->m_limit_rect.m_y )
		{
			Move( 0.0f, 20.0f );
			Add_Scale( -pFramerate->m_speed_factor * 0.01f );
		}
		// if below disable
		else
		{
			m_rot_z = 0.0f;
			Set_Scale( 1.0f );
			Set_Active( 0 );
		}
	}
}
예제 #5
0
void cPreferences :: Apply_Video( Uint16 screen_w, Uint16 screen_h, Uint8 screen_bpp, bool fullscreen, bool vsync, float geometry_detail, float texture_detail )
{
	/* if resolution, bpp, vsync or texture detail changed
	 * a texture reload is necessary
	*/
	if( m_video_screen_w != screen_w || m_video_screen_h != screen_h || m_video_screen_bpp != screen_bpp || m_video_vsync != vsync || !Is_Float_Equal( pVideo->m_texture_quality, texture_detail ) )
	{
		// new settings
		m_video_screen_w = screen_w;
		m_video_screen_h = screen_h;
		m_video_screen_bpp = screen_bpp;
		m_video_vsync = vsync;
		m_video_fullscreen = fullscreen;
		pVideo->m_texture_quality = texture_detail;
		pVideo->m_geometry_quality = geometry_detail;

		// reinitialize video and reload textures from file
		pVideo->Init_Video( 1 );
	}
	// no texture reload necessary
	else
	{
		// geometry detail changed
		if( !Is_Float_Equal( pVideo->m_geometry_quality, geometry_detail ) )
		{
			pVideo->m_geometry_quality = geometry_detail;
			pVideo->Init_Geometry();
		}

		// fullscreen changed
		if( m_video_fullscreen != fullscreen )
		{
			// toggle fullscreen and switches video_fullscreen itself
			pVideo->Toggle_Fullscreen();
		}
	}
}
예제 #6
0
파일: spikeball.cpp 프로젝트: sKabYY/SMC
void cSpikeball :: Update( void )
{
	cEnemy::Update();

	if( !m_valid_update || !Is_In_Range() )
	{
		return;
	}

	Update_Animation();

	if( m_state == STA_STAY )
	{
		m_counter_stay += pFramerate->m_speed_factor;

		// slow down
		if( !Is_Float_Equal( m_velx, 0.0f ) )
		{
			Add_Velocity_X( -m_velx * 0.25f );

			if( m_velx < 0.3f && m_velx > -0.3f )
			{
				m_velx = 0.0f;
			}
		}

		// set turn around image
		if( m_counter_stay > 40.0f && m_curr_img != 8 )
		{
			Set_Image_Num( 8 );

			// random direction
			if( ( rand() % 2 ) == 1 )
			{
				// turn around
				m_direction = Get_Opposite_Direction( m_direction );
				Update_Rotation_Hor();
			}
		}

		// finished stay animation
		if( m_counter_stay > 60.0f )
		{
			// run
			Set_Moving_State( STA_RUN );
			//pAudio->Play_Sound( "enemy/spikeball/run.wav" );
		}
	}
	else if( m_state == STA_WALK )
	{
		m_counter_walk += pFramerate->m_speed_factor;

		// finished walking
		if( m_counter_walk > 240.0f )
		{
			// stay
			Set_Moving_State( STA_STAY );
		}
	}
	else if( m_state == STA_RUN )
	{
		m_counter_running += pFramerate->m_speed_factor;

		// finished running
		if( m_counter_running > 120.0f )
		{
			// walk
			Set_Moving_State( STA_WALK );
		}

		// running particles
		m_running_particle_counter += pFramerate->m_speed_factor * 0.5f;

		// create particles
		if( m_running_particle_counter > 1.0f )
		{
			cParticle_Emitter *anim = new cParticle_Emitter( m_sprite_manager );
			anim->Set_Emitter_Rect( m_col_rect.m_x, m_col_rect.m_y + m_col_rect.m_h - 2.0f, m_col_rect.m_w );
			anim->Set_Quota( static_cast<int>(m_running_particle_counter) );
			anim->Set_Pos_Z( m_pos_z - 0.000001f );
			anim->Set_Image( pVideo->Get_Surface( "animation/particles/smoke_black.png" ) );
			anim->Set_Time_to_Live( 0.6f );
			anim->Set_Scale( 0.2f );

			float vel;

			if( m_velx > 0.0f )
			{
				vel = m_velx;
			}
			else
			{
				vel = -m_velx;
			}

			anim->Set_Speed( vel * 0.08f, 0.1f + vel * 0.1f );

			if( m_direction == DIR_RIGHT )
			{
				anim->Set_Direction_Range( 180.0f, 90.0f );
			}
			else
			{
				anim->Set_Direction_Range( 270.0f, 90.0f );
			}

			anim->Emit();
			pActive_Animation_Manager->Add( anim );

			m_running_particle_counter -= static_cast<int>(m_running_particle_counter);
		}
	}

	if( m_state != STA_STAY )
	{
		// if turn around image
		if( m_curr_img == 8 )
		{
			m_anim_counter += pFramerate->m_elapsed_ticks;

			// back to normal animation
			if( m_anim_counter >= 200 )
			{
				Reset_Animation();
				Set_Image_Num( m_anim_img_start );
				Set_Animation( 1 );
				Update_Rotation_Hor();
			}
			// rotate the turn image
			else if( m_anim_counter >= 100 )
			{
				Update_Rotation_Hor();
			}
		}
		else
		{
			Update_Velocity();
		}
	}

	Update_Gravity();
}
예제 #7
0
void cFramerate :: Update( void )
{
	const Uint32 current_ticks = SDL_GetTicks();

	// if speed factor is forced
	if( !Is_Float_Equal( m_force_speed_factor, 0.0f ) )
	{
		m_speed_factor = m_force_speed_factor;
		m_elapsed_ticks = static_cast<Uint32>(( m_force_speed_factor * 1000 ) / m_fps_target);

		// change to minimum
		if( m_elapsed_ticks == 0 )
		{
			m_elapsed_ticks = 1;
		}
	}
	// measure speed factor
	else
	{
		// set elapsed ticks
		m_elapsed_ticks = current_ticks - m_last_ticks;

		// minimum
		if( m_elapsed_ticks == 0 )
		{
			m_elapsed_ticks = 1;
		}
		// maximum
		else if( m_elapsed_ticks > m_max_elapsed_ticks )
		{
			m_elapsed_ticks = m_max_elapsed_ticks;
		}

		// speed factor calculation for this frame
		m_speed_factor = static_cast<float>(m_elapsed_ticks / ( 1000 / m_fps_target ));
	}

	// speed factor based fps
	m_fps = m_fps_target / m_speed_factor;
	
	// calculate average fps every second
	if( current_ticks - m_fps_average_framedelay > 1000 )
	{
		m_fps_average = m_frames_counted;

		m_fps_average_framedelay += 1000;
		m_frames_counted = 0;
	}
	// count a fps
	else
	{
		m_frames_counted++;
	}

	// best fps
	if( m_fps > m_fps_best )
	{
		m_fps_best = m_fps;
	}
	// worst fps
	else if( m_fps < m_fps_worst )
	{
		m_fps_worst = m_fps;
	}

	m_last_ticks = current_ticks;
}
예제 #8
0
파일: keyboard.cpp 프로젝트: sKabYY/SMC
bool cKeyboard :: Key_Down( SDLKey key )
{
	// input was processed by the gui system
	if( CEGUI_Handle_Key_Down( key ) )
	{
		return 1;
	}

	// set key to 1
	m_keys[key] = 1;

	// ## first the internal keys

	// game exit
	if( key == SDLK_F4 && pKeyboard->Is_Alt_Down() )
	{
		game_exit = 1;
		return 1;
	}
	// fullscreen toggle
	else if( key == SDLK_RETURN && pKeyboard->Is_Alt_Down() )
	{
		pVideo->Toggle_Fullscreen();
		return 1;
	}
	// GUI copy
	else if( key == SDLK_c && pKeyboard->Is_Ctrl_Down() )
	{
		if( GUI_Copy_To_Clipboard() )
		{
			return 1;
		}
	}
	// GUI cut
	else if( key == SDLK_x && pKeyboard->Is_Ctrl_Down() )
	{
		if( GUI_Copy_To_Clipboard( 1 ) )
		{
			return 1;
		}
	}
	// GUI paste
	else if( key == SDLK_v && pKeyboard->Is_Ctrl_Down() )
	{
		if( GUI_Paste_From_Clipboard() )
		{
			return 1;
		}
	}

	// handle key in the current mode
	if( Game_Mode == MODE_LEVEL )
	{
		// processed by the level
		if( pActive_Level->Key_Down( key ) )
		{
			return 1;
		}
	}
	else if( Game_Mode == MODE_OVERWORLD )
	{
		// processed by the overworld
		if( pActive_Overworld->Key_Down( key ) )
		{
			return 1;
		}
	}
	else if( Game_Mode == MODE_MENU )
	{
		// processed by the menu
		if( pMenuCore->Key_Down( key ) )
		{
			return 1;
		}
	}
	else if( Game_Mode == MODE_LEVEL_SETTINGS )
	{
		// processed by the level settings
		if( pLevel_Editor->m_settings_screen->Key_Down( key ) )
		{
			return 1;
		}
	}

	// set fixed speed factor mode
	if( key == SDLK_F6 )
	{
		float fixed_speedfactor = string_to_float( Box_Text_Input( float_to_string( pFramerate->m_force_speed_factor, 2 ), "Set Fixed Speedfactor", 1 ) );

		// disable
		if( Is_Float_Equal( fixed_speedfactor, 0.0f ) )
		{
			pFramerate->Set_Fixed_Speedfacor( 0.0f );
			pHud_Debug->Set_Text( "Fixed speed factor disabled" );
		}
		// below minimum
		else if( fixed_speedfactor <= 0.04f )
		{
			pHud_Debug->Set_Text( "Fixed speed factor must be greater than 0.04" );
		}
		// enable
		else
		{
			pFramerate->Set_Fixed_Speedfacor( fixed_speedfactor );
			pHud_Debug->Set_Text( "Fixed speed factor enabled" );
		}
	}
	// take a screenshot
	else if( key == pPreferences->m_key_screenshot )
	{
		pVideo->Save_Screenshot();
	}
	// pause the game
	else if( key == SDLK_PAUSE )
	{
		Draw_Static_Text( "Pause", &yellow, &lightgreyalpha64 );
	}
	// load a level
	else if( key == SDLK_l && pKeyboard->Is_Ctrl_Down() && !( Game_Mode == MODE_OVERWORLD && pOverworld_Manager->m_debug_mode ) && Game_Mode != MODE_LEVEL_SETTINGS )
	{
		pLevel_Editor->Function_Load();
	}
	// load an overworld
	else if( key == SDLK_w && pKeyboard->Is_Ctrl_Down() && !( Game_Mode == MODE_OVERWORLD && pOverworld_Manager->m_debug_mode ) && Game_Mode != MODE_LEVEL_SETTINGS )
	{
		pWorld_Editor->Function_Load();
	}
	// sound toggle
	else if( key == SDLK_F10 )
	{
		pAudio->Toggle_Sounds();

		if( !pAudio->m_sound_enabled )
		{
			pHud_Debug->Set_Text( "Sound disabled" );
		}
		else
		{
			pHud_Debug->Set_Text( "Sound enabled" );
		}
	}
	// music toggle
	else if( key == SDLK_F11 )
	{
		pAudio->Toggle_Music();

		if( !pAudio->m_music_enabled )
		{
			pHud_Debug->Set_Text( "Music disabled" );
		}
		else
		{
			pHud_Debug->Set_Text( "Music enabled" );
		}
	}
	// debug mode
	else if( key == SDLK_d && pKeyboard->Is_Ctrl_Down() )
	{
		if( game_debug )
		{
			pHud_Debug->Set_Text( "Debug mode disabled" );
		}
		else
		{
			pFramerate->m_fps_worst = 100000;
			pFramerate->m_fps_best = 0;
			pHud_Debug->Set_Text( "Debug mode enabled" );
		}

		game_debug = !game_debug;
	}
	// performance mode
	else if( key == SDLK_p && pKeyboard->Is_Ctrl_Down() )
	{
		if( game_debug_performance )
		{
			pHud_Debug->Set_Text( "Performance debug mode disabled" );
		}
		else
		{
			pFramerate->m_fps_worst = 100000;
			pFramerate->m_fps_best = 0;
			pHud_Debug->Set_Text( "Performance debug mode enabled" );
		}

		game_debug_performance = !game_debug_performance;
	}

	return 0;
}
예제 #9
0
파일: point.hpp 프로젝트: Clever-Boy/TSC
 // != operator
 inline bool operator != (const GL_point& p) const
 {
     return !Is_Float_Equal(m_x, p.m_x) || !Is_Float_Equal(m_y, p.m_y);
 }
예제 #10
0
파일: point.hpp 프로젝트: Clever-Boy/TSC
 // == operator
 inline bool operator == (const GL_point& p) const
 {
     return Is_Float_Equal(m_x, p.m_x) && Is_Float_Equal(m_y, p.m_y);
 }
예제 #11
0
cObjectCollisionType *cMovingSprite :: Collision_Check( const GL_rect &new_rect, const ColCheckType check_type /* = COLLIDE_COMPLETE */, cSprite_List *objects /* = NULL */ )
{
	// blocking collisions list
	cObjectCollisionType *col_list = new cObjectCollisionType();

	// no width or height is invalid
	if( Is_Float_Equal( new_rect.m_w, 0.0f ) || Is_Float_Equal( new_rect.m_h, 0.0f ) )
	{
		return col_list;
	}

	// if no object list is given get all objects available
	if( !objects )
	{
		objects = &pActive_Sprite_Manager->objects;

		// Player
		if( m_type != TYPE_PLAYER && new_rect.Intersects( pActive_Player->m_col_rect ) )
		{
			// validate
			Col_Valid_Type col_valid = Validate_Collision( pActive_Player );

			// ignore internal collisions
			if( check_type == COLLIDE_ONLY_BLOCKING )
			{
				if( col_valid == COL_VTYPE_INTERNAL )
				{
					col_valid = COL_VTYPE_NOT_VALID;
				}
			}
			// ignore blocking collisions
			else if( check_type == COLLIDE_ONLY_INTERNAL )
			{
				if( col_valid == COL_VTYPE_BLOCKING )
				{
					col_valid = COL_VTYPE_NOT_VALID;
				}
			}

			// valid collision
			if( col_valid != COL_VTYPE_NOT_VALID )
			{
				// add to list
				col_list->Add( Create_Collision_Object( this, pActive_Player, col_valid ) );
			}
		}
	}

	// Check objects
	for( cSprite_List::iterator itr = objects->begin(), itr_end = objects->end(); itr != itr_end; ++itr )
	{
		// get object pointer
		cSprite *level_object = (*itr);

		// if the same object or destroyed object
		if( this == level_object || level_object->m_auto_destroy )
		{
			continue;
		}

		// if rects don't touch
		if( !new_rect.Intersects( level_object->m_col_rect ) )
		{
			continue;
		}

		// if undefined, hud or animation
		if( level_object->m_sprite_array == ARRAY_UNDEFINED || level_object->m_sprite_array == ARRAY_HUD || level_object->m_sprite_array == ARRAY_ANIM )
		{
			continue;
		}

		// if enemy is dead
		if( level_object->m_sprite_array == ARRAY_ENEMY && static_cast<cEnemy *>(level_object)->m_dead )
		{
			continue;
		}

		// validate
		Col_Valid_Type col_valid = Validate_Collision( level_object );

		// not a valid collision
		if( col_valid == COL_VTYPE_NOT_VALID )
		{
			continue;
		}

		// ignore internal collisions
		if( check_type == COLLIDE_ONLY_BLOCKING )
		{
			if( col_valid == COL_VTYPE_INTERNAL )
			{
				continue;
			}
		}
		// ignore blocking collisions
		else if( check_type == COLLIDE_ONLY_INTERNAL )
		{
			if( col_valid == COL_VTYPE_BLOCKING )
			{
				continue;
			}
		}

		// add to list
		col_list->Add( Create_Collision_Object( this, level_object, col_valid ) );
	}

	return col_list;
}
예제 #12
0
cObjectCollisionType *cMovingSprite :: Collision_Check_Absolute( const float x, const float y, const float w /* = 0 */, const float h /* = 0 */, const ColCheckType check_type /* = COLLIDE_COMPLETE */, cSprite_List *objects /* = NULL */ )
{
	// save original rect
	GL_rect new_rect;

	// if given use x position
	if( !Is_Float_Equal( x, 0.0f ) )
	{
		new_rect.m_x = x;
	}
	else
	{
		new_rect.m_x = m_col_rect.m_x;
	}

	// if given use y position
	if( !Is_Float_Equal( y, 0.0f ) )
	{
		new_rect.m_y = y;
	}
	else
	{
		new_rect.m_y = m_col_rect.m_y;
	}

	// if given use width
	if( w > 0.0f )
	{
		new_rect.m_w = w;
	}
	else
	{
		new_rect.m_w = m_col_rect.m_w;
	}

	// if given use height
	if( h > 0.0f )
	{
		new_rect.m_h = h;
	}
	else
	{
		new_rect.m_h = m_col_rect.m_h;
	}

	// visual debugging
	if( game_debug )
	{
		// create request
		cRect_Request *request = new cRect_Request();

		pVideo->Draw_Rect( &new_rect, m_pos_z + 0.00001f, &green, request );
		request->no_camera = 0;

		request->blend_sfactor = GL_SRC_COLOR;
		request->blend_dfactor = GL_DST_ALPHA;


		// add request
		pRenderer->Add( request );
	}

	// return collisions list
	return Collision_Check( &new_rect, check_type, objects );
}
예제 #13
0
void cMovingSprite :: Col_Move( float move_x, float move_y, bool real /* = 0 */, bool force /* = 0 */, bool check_on_ground /* = 1 */ )
{
	// no need to move
	if( Is_Float_Equal( move_x, 0.0f ) && Is_Float_Equal( move_y, 0.0f ) )
	{
		return;
	}

	// invalid collision rect
	if( Is_Float_Equal( m_col_rect.m_w, 0.0f ) || Is_Float_Equal( m_col_rect.m_h, 0.0f ) )
	{
		return;
	}

	// use speedfactor
	if( !real )
	{
		move_x *= pFramerate->m_speed_factor;
		move_y *= pFramerate->m_speed_factor;
	}
 
	// check for collisions
	if( !force )
	{
		// get all possible colliding items
		GL_rect complete_rect = m_col_rect;

		if( move_x > 0.0f )
		{
			complete_rect.m_w += move_x;
		}
		else
		{
			complete_rect.m_x += move_x;
			complete_rect.m_w -= move_x;
		}

		if( move_y > 0.0f )
		{
			complete_rect.m_h += move_y;
		}
		else
		{
			complete_rect.m_y += move_y;
			complete_rect.m_h -= move_y;
		}

		cSprite_List sprite_list;
		pActive_Sprite_Manager->Get_Colliding_Objects( sprite_list, complete_rect, 1, this );

		// step size
		float step_size_x = move_x;
		float step_size_y = move_y;

		// check if object collision rect is smaller as the position check size
		if( step_size_x > m_col_rect.m_w )
		{
			step_size_x = m_col_rect.m_w;
		}
		else if( step_size_x < -m_col_rect.m_w )
		{
			step_size_x = -m_col_rect.m_w;
		}

		if( step_size_y > m_col_rect.m_h )
		{
			step_size_y = m_col_rect.m_h;
		}
		else if( step_size_y < -m_col_rect.m_h )
		{
			step_size_y = -m_col_rect.m_h;
		}

		float final_pos_x = m_pos_x + move_x;
		float final_pos_y = m_pos_y + move_y;

		// move in big steps
		cObjectCollisionType *col_list = Col_Move_in_Steps( move_x, move_y, step_size_x, step_size_y, final_pos_x, final_pos_y, sprite_list, 1 );

		// if a collision is found enter pixel checking
		if( col_list && col_list->size() )
		{
			// change to pixel checking
			if( step_size_x < -1.0f )
			{
				step_size_x = -1.0f;
			}
			else if( step_size_x > 1.0f )
			{
				step_size_x = 1.0f;
			}

			if( step_size_y < -1.0f )
			{
				step_size_y = -1.0f;
			}
			else if( step_size_y > 1.0f )
			{
				step_size_y = 1.0f;
			}

			delete col_list;
			col_list = Col_Move_in_Steps( move_x, move_y, step_size_x, step_size_y, final_pos_x, final_pos_y, sprite_list );

			Add_Collisions( col_list, 1 );
		}

		if( col_list )
		{
			delete col_list;
		}
	}
	// don't check for collisions
	else
	{
		m_pos_x += move_x;
		m_pos_y += move_y;
		Update_Position_Rect();
	}

	// if check on ground
	if( check_on_ground )
	{
		Check_on_Ground();
	}

	// check/handle if moved out of level rect
	Check_Out_Of_Level_Hor( move_x, 1 );
	Check_Out_Of_Level_Ver( move_y, 1 );
}
예제 #14
0
cObjectCollisionType *cMovingSprite :: Col_Move_in_Steps( float move_x, float move_y, float step_size_x, float step_size_y, float final_pos_x, float final_pos_y, cSprite_List sprite_list, bool stop_on_internal /* = 0 */ )
{
	if( sprite_list.empty() )
	{
		cSprite::Move( final_pos_x - m_pos_x, final_pos_y - m_pos_y, 1 );
		return NULL;
	}

	// collision list
	cObjectCollisionType *col_list = new cObjectCollisionType();

	bool move_x_valid = 1;
	bool move_y_valid = 1;

	/* Checks in both directions simultaneously
	 * if a collision occurs it saves the direction
	*/
	while( move_x_valid || move_y_valid )
	{
		if( move_x_valid )
		{
			// nothing to do
			if( Is_Float_Equal( step_size_x, 0.0f ) )
			{
				move_x_valid = 0;
				continue;
			}

			// collision check
			cObjectCollisionType *col_list_temp = Collision_Check_Relative( step_size_x, 0.0f, 0.0f, 0.0f, COLLIDE_COMPLETE, &sprite_list );
			
			bool collision_found = 0;

			// stop on everything
			if( stop_on_internal )
			{
				if( col_list_temp->size() )
				{
					collision_found = 1;
				}
			}
			// stop only on blocking
			else
			{
				if( col_list_temp->Is_Included( COL_VTYPE_BLOCKING ) )
				{
					collision_found = 1;
				}
				// remove internal collision from further checks
				else if( col_list_temp->objects.size() )
				{
					for( cObjectCollision_List::iterator itr = col_list_temp->objects.begin(), itr_end = col_list_temp->objects.end(); itr != itr_end; ++itr )
					{
						cObjectCollision *col = (*itr);

						if( col->valid_type != COL_VTYPE_INTERNAL )
						{
							continue;
						}

						// find in sprite list
						cSprite_List::iterator sprite_itr = std::find( sprite_list.begin(), sprite_list.end(), col->obj );

						// not found
						if( sprite_itr == sprite_list.end() )
						{
							continue;
						}

						sprite_list.erase( sprite_itr );
					}

					// if no objects left
					if( sprite_list.empty() )
					{
						// move to final position
						m_pos_x = final_pos_x;
					}
				}
			}
			
			if( col_list_temp->size() )
			{
				col_list->objects.insert( col_list->objects.end(), col_list_temp->objects.begin(), col_list_temp->objects.end() );
				col_list_temp->objects.clear();
			}

			delete col_list_temp;

			if( !collision_found )
			{
				m_pos_x += step_size_x;

				if( ( step_size_x > 0.0f && final_pos_x <= m_pos_x ) || ( step_size_x < 0.0f && final_pos_x >= m_pos_x ) )
				{
					m_pos_x = final_pos_x;
					move_x_valid = 0;
					step_size_x = 0.0f;
				}

				// update collision rects
				Update_Position_Rect();
			}
			// collision found
			else
			{
				step_size_x = 0.0f;
				move_x_valid = 0;
			}
		}

		if( move_y_valid )
		{
			// nothing to do
			if( Is_Float_Equal( step_size_y, 0.0f ) )
			{
				move_y_valid = 0;
				continue;
			}

			// collision check
			cObjectCollisionType *col_list_temp = Collision_Check_Relative( 0.0f, step_size_y, 0.0f, 0.0f, COLLIDE_COMPLETE, &sprite_list );

			bool collision_found = 0;

			// stop on everything
			if( stop_on_internal )
			{
				if( col_list_temp->size() )
				{
					collision_found = 1;
				}
			}
			// stop only on blocking
			else
			{
				if( col_list_temp->Is_Included( COL_VTYPE_BLOCKING ) )
				{
					collision_found = 1;
				}
				// remove internal collision from further checks
				else if( col_list_temp->objects.size() )
				{
					for( cObjectCollision_List::iterator itr = col_list_temp->objects.begin(), itr_end = col_list_temp->objects.end(); itr != itr_end; ++itr )
					{
						cObjectCollision *col = (*itr);

						if( col->valid_type != COL_VTYPE_INTERNAL )
						{
							continue;
						}

						// find in sprite list
						cSprite_List::iterator sprite_itr = std::find( sprite_list.begin(), sprite_list.end(), col->obj );

						// not found
						if( sprite_itr == sprite_list.end() )
						{
							continue;
						}

						sprite_list.erase( sprite_itr );

						// if no objects left
						if( sprite_list.empty() )
						{
							// move to final position
							m_pos_y = final_pos_y;
						}
					}
				}
			}
			
			if( col_list_temp->size() )
			{
				col_list->objects.insert( col_list->objects.end(), col_list_temp->objects.begin(), col_list_temp->objects.end() );
				col_list_temp->objects.clear();
			}

			delete col_list_temp;

			if( !collision_found )
			{
				m_pos_y += step_size_y;

				if( ( step_size_y > 0.0f && final_pos_y <= m_pos_y ) || ( step_size_y < 0.0f && final_pos_y >= m_pos_y ) )
				{
					m_pos_y = final_pos_y;
					move_y_valid = 0;
					step_size_y = 0.0f;
				}

				// update collision rects
				Update_Position_Rect();
			}
			// collision found
			else
			{
				step_size_y = 0.0f;
				move_y_valid = 0;
			}
		}
	}

	return col_list;
}
예제 #15
0
void cMovingSprite :: Move_With_Ground( void )
{
	if( !m_ground_object || ( m_ground_object->m_sprite_array != ARRAY_ACTIVE && m_ground_object->m_sprite_array != ARRAY_ENEMY ) ) // || m_ground_object->sprite_array == ARRAY_MASSIVE
	{
		return;
	}

	cMovingSprite *moving_ground_object = dynamic_cast<cMovingSprite *>(m_ground_object);

	// invalid moving sprite
	if( !moving_ground_object )
	{
		return;
	}

	// does not move
	if( Is_Float_Equal( moving_ground_object->m_velx, 0.0f ) && Is_Float_Equal( moving_ground_object->m_vely, 0.0f ) )
	{
		return;
	}

	// check ground first because of the moving object velocity
	Check_on_Ground();
	// save posx for possible can not move test
	float posy_orig = m_pos_y;
	/* stop object from getting stopped of the moving object which did not yet move itself
	 * for example the player always moves as last
	*/
	bool is_massive = 0;
	if( moving_ground_object->m_massive_type == MASS_MASSIVE )
	{
		moving_ground_object->m_massive_type = MASS_PASSIVE;
		is_massive = 1;
	}
	// move
	Col_Move( moving_ground_object->m_velx, moving_ground_object->m_vely, 0, 0, 0 );

	if( is_massive )
	{
		moving_ground_object->m_massive_type = MASS_MASSIVE;
	}
	// if ground object is moving up
	if( moving_ground_object->m_vely < -0.01f )
	{
		// test if we could not move upwards because something did block us in Col_Move()
		if( Is_Float_Equal( m_pos_y, posy_orig ) )
		{
			// massive
			if( moving_ground_object->m_massive_type == MASS_MASSIVE )
			{
				// got crunched
				DownGrade( 1 );
			}
			// halfmassive
			else if( moving_ground_object->m_massive_type == MASS_HALFMASSIVE )
			{
				// lost ground
				Move( 0.0f, 1.9f, 1 );
				Reset_On_Ground();
			}
		}
	}
}