@ -1,6 +1,8 @@
# include <chipmunk.h>
# include "types.h"
# include "ipsettings.h" // debug/developer settings
# include <stdio.h> // assert logging
# include <string.h> // memset
@ -229,6 +231,12 @@ void grid_create(GameState* gs, Entity* e)
create_body ( gs , e ) ;
}
void entity_set_rotation ( Entity * e , float rot )
{
assert ( e - > body ! = NULL ) ;
cpBodySetAngle ( e - > body , rot ) ;
}
void entity_set_pos ( Entity * e , V2 pos )
{
assert ( e - > is_grid ) ;
@ -295,12 +303,8 @@ void box_create(GameState* gs, Entity* new_box, Entity* grid, V2 pos)
// removes boxes from grid, then ensures that the rule that grids must not have
// holes in them is applied.
static void grid_ remove_box ( GameState * gs , struct Entity * grid , struct Entity * box )
static void grid_ correct_for_holes ( GameState * gs , struct Entity * grid )
{
assert ( grid - > is_grid ) ;
assert ( box - > is_box ) ;
entity_destroy ( gs , box ) ;
int num_boxes = grid_num_boxes ( gs , grid ) ;
if ( num_boxes = = 0 )
{
@ -447,6 +451,14 @@ static void grid_remove_box(GameState* gs, struct Entity* grid, struct Entity* b
}
}
static void grid_remove_box ( GameState * gs , struct Entity * grid , struct Entity * box )
{
assert ( grid - > is_grid ) ;
assert ( box - > is_box ) ;
entity_destroy ( gs , box ) ;
grid_correct_for_holes ( gs , grid ) ;
}
static cpBool on_damage ( cpArbiter * arb , cpSpace * space , cpDataPointer userData )
{
cpShape * a , * b ;
@ -653,7 +665,7 @@ void ser_var(SerState* ser, char* var_pointer, size_t var_size, const char* name
}
}
# define SER_VAR_NAME(var_pointer, name) ser_var(ser, (char*)var_pointer, sizeof( var_pointer), name, __FILE__, __LINE__)
# define SER_VAR_NAME(var_pointer, name) ser_var(ser, (char*)var_pointer, sizeof( * var_pointer), name, __FILE__, __LINE__)
# define SER_VAR(var_pointer) SER_VAR_NAME(var_pointer, #var_pointer)
void ser_V2 ( SerState * ser , V2 * var )
@ -676,7 +688,7 @@ void ser_entityid(SerState* ser, EntityID* id)
SER_VAR ( & id - > index ) ;
}
void ser_inputframe ( SerState * ser , struct InputFrame * i )
void ser_inputframe ( SerState * ser , InputFrame * i )
{
SER_VAR ( & i - > tick ) ;
SER_VAR ( & i - > movement ) ;
@ -684,11 +696,11 @@ void ser_inputframe(SerState* ser, struct InputFrame* i)
SER_VAR ( & i - > seat_action ) ;
ser_entityid ( ser , & i - > seat_to_inhabit ) ;
SER_VAR ( & i - > hand_pos ) ;
ser_entityid ( ser , & i - > grid_hand_pos_local_to ) ;
SER_VAR ( & i - > dobuild ) ;
SER_VAR ( & i - > build_type ) ;
SER_VAR ( & i - > build_rotation ) ;
ser_entityid ( ser , & i - > grid_to_build_on ) ;
}
void ser_player ( SerState * ser , Player * p )
@ -941,9 +953,9 @@ Entity* closest_to_point_in_radius(GameState* gs, V2 point, float radius)
return NULL ;
}
V2 thruster_direction ( Entity * box )
V2 box_facing_vector ( Entity * box )
{
assert ( box - > is_box & & box - > box_type = = BoxThruster ) ;
assert ( box - > is_box ) ;
V2 to_return = ( V2 ) { . x = 1.0f , . y = 0.0f } ;
to_return = V2rotate ( to_return , rotangle ( box - > compass_rotation ) ) ;
@ -954,7 +966,7 @@ V2 thruster_direction(Entity* box)
V2 thruster_force ( Entity * box )
{
return V2scale ( thruster_direction ( box ) , - box - > thrust * THRUSTER_FORCE ) ;
return V2scale ( box_facing_vector ( box ) , - box - > thrust * THRUSTER_FORCE ) ;
}
uint64_t tick ( GameState * gs )
@ -962,6 +974,18 @@ uint64_t tick(GameState* gs)
return ( uint64_t ) floor ( gs - > time / ( ( double ) TIMESTEP ) ) ;
}
V2 get_world_hand_pos ( GameState * gs , InputFrame * input , Entity * player )
{
Entity * potential_grid = get_entity ( gs , input - > grid_hand_pos_local_to ) ;
if ( potential_grid ! = NULL )
{
return grid_local_to_world ( potential_grid , input - > hand_pos ) ;
}
else {
return input - > hand_pos ;
}
}
void process ( GameState * gs , float dt )
{
assert ( gs - > space ! = NULL ) ;
@ -984,6 +1008,10 @@ void process(GameState* gs, float dt)
}
assert ( p - > is_player ) ;
if ( INFINITE_RESOURCES )
{
p - > spice_taken_away = 0.0f ;
}
// update gold win condition
if ( V2length ( V2sub ( cp_to_v2 ( cpBodyGetPosition ( p - > body ) ) , gs - > goldpos ) ) < GOLD_COLLECT_RADIUS )
{
@ -993,6 +1021,7 @@ void process(GameState* gs, float dt)
}
# if 1
V2 world_hand_pos = get_world_hand_pos ( gs , & player - > input , p ) ;
if ( player - > input . seat_action )
{
player - > input . seat_action = false ; // "handle" the input
@ -1000,7 +1029,7 @@ void process(GameState* gs, float dt)
if ( the_seat = = NULL ) // not piloting any seat
{
cpPointQueryInfo query_info = { 0 } ;
cpShape * result = cpSpacePointQueryNearest ( gs - > space , v2_to_cp ( player- > input . hand_pos) , 0.1f , cpShapeFilterNew ( CP_NO_GROUP , CP_ALL_CATEGORIES , BOXES ) , & query_info ) ;
cpShape * result = cpSpacePointQueryNearest ( gs - > space , v2_to_cp ( world_ hand_pos) , 0.1f , cpShapeFilterNew ( CP_NO_GROUP , CP_ALL_CATEGORIES , BOXES ) , & query_info ) ;
if ( result ! = NULL )
{
Entity * potential_seat = cp_shape_entity ( result ) ;
@ -1013,12 +1042,13 @@ void process(GameState* gs, float dt)
}
else
{
Log ( " No ship above player at point %f %f \n " , player - > input . hand_pos . x , player - > input . hand_pos . y ) ;
Log ( " No ship above player at point %f %f \n " , world_hand_pos . x , world_hand_pos . y ) ;
}
}
else
{
V2 pilot_seat_exit_spot = V2add ( box_pos ( the_seat ) , V2 rotate( ( V2 ) { . x = BOX_SIZE } , rotangle ( the_seat - > compass_rotation ) ) ) ;
V2 pilot_seat_exit_spot = V2add ( box_pos ( the_seat ) , V2 scale( box_facing_vector ( the_seat ) , BOX_SIZE ) ) ;
cpBodySetPosition ( p - > body , v2_to_cp ( pilot_seat_exit_spot ) ) ;
cpBodySetVelocity ( p - > body , v2_to_cp ( player_vel ( gs , p ) ) ) ;
the_seat - > piloted_by = ( EntityID ) { 0 } ;
@ -1061,7 +1091,7 @@ void process(GameState* gs, float dt)
{
if ( cur - > box_type ! = BoxThruster )
continue ;
float wanted_thrust = - V2dot ( target_direction , thruster_direction ( cur ) ) ;
float wanted_thrust = - V2dot ( target_direction , box_facing_vector ( cur ) ) ;
wanted_thrust = clamp01 ( wanted_thrust ) ;
cur - > wanted_thrust = wanted_thrust ;
}
@ -1075,10 +1105,10 @@ void process(GameState* gs, float dt)
player - > input . dobuild = false ; // handle the input. if didn't do this, after destruction of hovered box, would try to build on its grid with grid_index...
cpPointQueryInfo info = { 0 } ;
V2 world_build = player- > input . hand_pos;
V2 world_build = world_ hand_pos;
// @Robust sanitize this input so player can't build on any grid in the world
Entity * target_grid = get_entity ( gs , player - > input . grid_ to_build_on ) ;
Entity * target_grid = get_entity ( gs , player - > input . grid_ hand_pos_local_to ) ;
cpShape * nearest = cpSpacePointQueryNearest ( gs - > space , v2_to_cp ( world_build ) , 0.01f , cpShapeFilterNew ( CP_NO_GROUP , CP_ALL_CATEGORIES , BOXES ) , & info ) ;
if ( nearest ! = NULL )
{
@ -1104,6 +1134,7 @@ void process(GameState* gs, float dt)
{
Entity * new_box = new_entity ( gs ) ;
box_create ( gs , new_box , target_grid , grid_world_to_local ( target_grid , world_build ) ) ;
grid_correct_for_holes ( gs , target_grid ) ; // no holey ship for you!
new_box - > box_type = player - > input . build_type ;
new_box - > compass_rotation = player - > input . build_rotation ;
p - > spice_taken_away + = 0.1f ;
@ -1134,8 +1165,6 @@ void process(GameState* gs, float dt)
}
if ( e - > is_grid )
{
float thruster_energy_consumption_per_second = 0.0f ;
BOXES_ITER ( gs , cur , e )
{
if ( cur - > box_type = = BoxThruster )
@ -1149,6 +1178,7 @@ void process(GameState* gs, float dt)
possible_battery - > energy_used + = energy_to_consume ;
cur - > thrust = cur - > wanted_thrust ;
cpBodyApplyForceAtWorldPoint ( e - > body , v2_to_cp ( thruster_force ( cur ) ) , v2_to_cp ( box_pos ( cur ) ) ) ;
break ;
}
}
}