Add radar

main
Cameron Murphy Reikes 2 years ago
parent 89a7cab44c
commit 2feb571c1d

@ -26,8 +26,8 @@
#define DEBUG_TOOLS #define DEBUG_TOOLS
#define CHIPMUNK_INTEGRITY_CHECK #define CHIPMUNK_INTEGRITY_CHECK
// #define FAT_THRUSTERS // #define FAT_THRUSTERS
// #define NO_GRAVITY #define NO_GRAVITY
// #define NO_SUNS #define NO_SUNS
#else #else

Binary file not shown.

@ -348,6 +348,14 @@ static void raycast_query_callback(cpShape *shape, cpVect point, cpVect normal,
} }
} }
static THREADLOCAL cpVect from_point = {0};
static int sort_bodies_callback(const void *a, const void *b)
{
double a_dist = cpvdist(cpBodyGetPosition((cpBody *)a), from_point);
double b_dist = cpvdist(cpBodyGetPosition((cpBody *)b), from_point);
return (int)(a_dist - b_dist);
}
LauncherTarget missile_launcher_target(GameState *gs, Entity *launcher) LauncherTarget missile_launcher_target(GameState *gs, Entity *launcher)
{ {
double to_face = 0.0; double to_face = 0.0;
@ -1517,8 +1525,10 @@ SerMaybeFailure ser_entity(SerState *ser, GameState *gs, Entity *e)
SER_MAYBE_RETURN(ser_f(ser, &e->currently_scanning_progress)); SER_MAYBE_RETURN(ser_f(ser, &e->currently_scanning_progress));
SER_VAR(&e->blueprints_learned); SER_VAR(&e->blueprints_learned);
SER_MAYBE_RETURN(ser_f(ser, &e->scanner_head_rotate)); SER_MAYBE_RETURN(ser_f(ser, &e->scanner_head_rotate));
SER_MAYBE_RETURN(ser_fV2(ser, &e->platonic_nearest_direction)); for (int i = 0; i < SCANNER_MAX_POINTS; i++)
SER_MAYBE_RETURN(ser_f(ser, &e->platonic_detection_strength)); {
SER_VAR(&e->scanner_points[i]);
}
break; break;
case BoxCloaking: case BoxCloaking:
SER_MAYBE_RETURN(ser_f(ser, &e->cloaking_power)); SER_MAYBE_RETURN(ser_f(ser, &e->cloaking_power));
@ -3123,13 +3133,11 @@ void process(struct GameState *gs, double dt)
// only the server knows all the positions of all the solids // only the server knows all the positions of all the solids
if (gs->server_side_computing) if (gs->server_side_computing)
{ {
if (cur_box->energy_effectiveness < 1.0) for (int i = 0; i < SCANNER_MAX_POINTS; i++)
{ cur_box->scanner_points[i] = (struct ScannerPoint){0};
cur_box->platonic_detection_strength = 0.0; if (cur_box->energy_effectiveness >= 1.0)
cur_box->platonic_nearest_direction = (cpVect){0};
}
else
{ {
/*
cpVect from_pos = entity_pos(cur_box); cpVect from_pos = entity_pos(cur_box);
cpVect nearest = {0}; cpVect nearest = {0};
double nearest_dist = INFINITY; double nearest_dist = INFINITY;
@ -3146,15 +3154,67 @@ void process(struct GameState *gs, double dt)
} }
} }
} }
if (nearest_dist < INFINITY) */
circle_query(gs->space, entity_pos(cur_box), SCANNER_MAX_RANGE);
cpBody *body_results[128] = {0};
size_t cur_results_len = 0;
QUEUE_ITER(&query_result, QueryResult, res)
{
cpBody *cur_body = cpShapeGetBody(res->shape);
bool unique_body = true;
for (int i = 0; i < cur_results_len; i++)
{
if (body_results[i] == cur_body)
{
unique_body = false;
break;
}
}
if (unique_body && cur_results_len < ARRLEN(body_results))
{
body_results[cur_results_len] = cur_body;
cur_results_len++;
}
}
from_point = entity_pos(cur_box);
qsort(body_results, cur_results_len, sizeof(cpBody *), sort_bodies_callback);
size_t bodies_detected = cur_results_len < SCANNER_MAX_POINTS ? cur_results_len : SCANNER_MAX_POINTS;
for (int i = 0; i < bodies_detected; i++)
{
cpVect rel_vect = cpvsub(cpBodyGetPosition(body_results[i]), from_point);
double vect_length = cpvlength(rel_vect);
if (vect_length > SCANNER_MIN_RANGE)
{ {
cur_box->platonic_nearest_direction = cpvnormalize(cpvsub(nearest, from_pos)); if (vect_length > SCANNER_MAX_RANGE)
cur_box->platonic_detection_strength = fmax(0.1, 1.0 - fmin(1.0, nearest_dist / 100.0)); {
rel_vect = cpvmult(cpvnormalize(rel_vect), SCANNER_MAX_RANGE);
} }
else
enum ScannerPointKind kind = Platonic;
Entity *body_entity =cp_body_entity(body_results[i]) ;
if(body_entity->is_grid) {
kind = Neutral;
BOXES_ITER(gs, cur_potential_platonic, body_entity)
{
if(cur_potential_platonic->is_platonic)
{ {
cur_box->platonic_nearest_direction = (cpVect){0}; kind = Platonic;
cur_box->platonic_detection_strength = 0.0; break;
}
}
} else if(body_entity->is_player) {
kind = Neutral;
} else {
kind = Enemy;
}
cur_box->scanner_points[i] = (struct ScannerPoint){
.kind = (char)kind,
.x = (char)((rel_vect.x / SCANNER_MAX_RANGE) * 128.0),
.y = (char)((rel_vect.y / SCANNER_MAX_RANGE) * 128.0),
};
}
} }
} }
} }
@ -3173,7 +3233,8 @@ void process(struct GameState *gs, double dt)
cur_box->currently_scanning = new_id; cur_box->currently_scanning = new_id;
} }
double target_head_rotate_speed = cur_box->platonic_detection_strength > 0.0 ? 3.0 : 0.0; // double target_head_rotate_speed = cur_box->platonic_detection_strength > 0.0 ? 3.0 : 0.0;
double target_head_rotate_speed = 3.0 * cur_box->energy_effectiveness;
if (to_learn != NULL) if (to_learn != NULL)
{ {
cur_box->currently_scanning_progress += dt * SCANNER_SCAN_RATE; cur_box->currently_scanning_progress += dt * SCANNER_SCAN_RATE;

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

@ -127,6 +127,7 @@ static sg_image image_gyrospin;
static sg_image image_noenergy; static sg_image image_noenergy;
static sg_image image_orb; static sg_image image_orb;
static sg_image image_orb_frozen; static sg_image image_orb_frozen;
static sg_image image_radardot;
static enum BoxType toolbar[TOOLBAR_SLOTS] = { static enum BoxType toolbar[TOOLBAR_SLOTS] = {
BoxHullpiece, BoxHullpiece,
@ -657,6 +658,7 @@ static void init(void)
image_noenergy = load_image("loaded/no_energy.png"); image_noenergy = load_image("loaded/no_energy.png");
image_orb = load_image("loaded/orb.png"); image_orb = load_image("loaded/orb.png");
image_orb_frozen = load_image("loaded/orb_frozen.png"); image_orb_frozen = load_image("loaded/orb_frozen.png");
image_radardot = load_image("loaded/radardot.png");
} }
// socket initialization // socket initialization
@ -2171,13 +2173,6 @@ static void frame(void)
sgp_reset_image(0); sgp_reset_image(0);
} }
// scanner range, visualizes what scanner can scan
if (b->box_type == BoxScanner)
{
set_color(BLUE);
draw_circle(entity_pos(b), SCANNER_RADIUS);
set_color(WHITE);
}
set_color_values(0.5, 0.1, 0.1, b->damage); set_color_values(0.5, 0.1, 0.1, b->damage);
draw_color_rect_centered(entity_pos(b), BOX_SIZE); draw_color_rect_centered(entity_pos(b), BOX_SIZE);
@ -2215,13 +2210,52 @@ static void frame(void)
if (b->box_type == BoxScanner) if (b->box_type == BoxScanner)
{ {
if (b->platonic_detection_strength > 0.0) if (b->energy_effectiveness >= 1.0)
{ {
// maximum scanner range
set_color(BLUE);
draw_circle(entity_pos(b), SCANNER_RADIUS);
set_color_values(0.0, 0.0, 1.0, 0.3);
draw_circle(entity_pos(b), SCANNER_RADIUS * 0.25);
draw_circle(entity_pos(b), SCANNER_RADIUS * 0.5);
draw_circle(entity_pos(b), SCANNER_RADIUS * 0.75);
set_color(WHITE);
set_color(colhexcode(0xf2d75c)); set_color(colhexcode(0xf2d75c));
cpVect to = cpvadd(entity_pos(b), cpvmult(b->platonic_nearest_direction, b->platonic_detection_strength)); sgp_set_image(0, image_radardot);
for (int i = 0; i < SCANNER_MAX_POINTS; i++)
{
if(b->scanner_points[i].x != 0 && b->scanner_points[i].y != 0)
{
struct ScannerPoint point = b->scanner_points[i];
switch(point.kind)
{
case Platonic:
set_color(GOLD);
break;
case Neutral:
set_color(WHITE);
break;
case Enemy:
set_color(RED);
break;
default:
set_color(WHITE); // @Robust assert false in serialization if unexpected kind
break;
}
cpVect rel = cpv(
((double)point.x / 128.0) * SCANNER_RADIUS,
((double)point.y / 128.0) * SCANNER_RADIUS
);
cpVect to = cpvadd(entity_pos(b), rel);
dbg_rect(to); dbg_rect(to);
dbg_rect(entity_pos(b)); dbg_rect(entity_pos(b));
draw_line(entity_pos(b).x, entity_pos(b).y, to.x, to.y); pipeline_scope(goodpixel_pipeline)
draw_texture_centered(to, BOX_SIZE / 2.0);
}
}
sgp_reset_image(0);
// draw_line(entity_pos(b).x, entity_pos(b).y, to.x, to.y);
} }
} }
if (b->box_type == BoxMissileLauncher) if (b->box_type == BoxMissileLauncher)

@ -10,14 +10,7 @@
#define MAX_ENTITIES 1024 * 25 #define MAX_ENTITIES 1024 * 25
#define BOX_SIZE 0.25f #define BOX_SIZE 0.25f
#define MERGE_MAX_DIST (BOX_SIZE / 2.0f + 0.01f) #define MERGE_MAX_DIST (BOX_SIZE / 2.0f + 0.01f)
#define PLAYER_SIZE ((cpVect){.x = BOX_SIZE, .y = BOX_SIZE})
#define PLAYER_MASS 0.5f
#ifdef FAT_THRUSTERS
#define PLAYER_JETPACK_FORCE 200.0f
#else
#define PLAYER_JETPACK_FORCE 3.5f
#endif
#define PLAYER_JETPACK_TORQUE 0.05f
#define MISSILE_RANGE 4.0f #define MISSILE_RANGE 4.0f
#define MISSILE_BURN_TIME 1.5f #define MISSILE_BURN_TIME 1.5f
#define MISSILE_ARM_TIME 0.5f #define MISSILE_ARM_TIME 0.5f
@ -30,6 +23,17 @@
#define MISSILE_SPRITE_SIZE ((cpVect){.x = BOX_SIZE, .y = BOX_SIZE}) #define MISSILE_SPRITE_SIZE ((cpVect){.x = BOX_SIZE, .y = BOX_SIZE})
#define MISSILE_COLLIDER_SIZE ((cpVect){.x = BOX_SIZE * 0.5f, .y = BOX_SIZE * 0.5f}) #define MISSILE_COLLIDER_SIZE ((cpVect){.x = BOX_SIZE * 0.5f, .y = BOX_SIZE * 0.5f})
#define MISSILE_SPAWN_DIST (sqrt((BOX_SIZE / 2.0) * (BOX_SIZE / 2.0) * 2.0) + MISSILE_COLLIDER_SIZE.x / 2.0 + 0.1) #define MISSILE_SPAWN_DIST (sqrt((BOX_SIZE / 2.0) * (BOX_SIZE / 2.0) * 2.0) + MISSILE_COLLIDER_SIZE.x / 2.0 + 0.1)
#define MISSILE_EXPLOSION_PUSH 2.5f
#define MISSILE_EXPLOSION_RADIUS 0.4f
#define PLAYER_SIZE ((cpVect){.x = BOX_SIZE, .y = BOX_SIZE})
#define PLAYER_MASS 0.5f
#ifdef FAT_THRUSTERS
#define PLAYER_JETPACK_FORCE 200.0f
#else
#define PLAYER_JETPACK_FORCE 3.5f
#endif
#define PLAYER_JETPACK_TORQUE 0.05f
#define PLAYER_JETPACK_ROTATION_ENERGY_PER_SECOND 0.2f #define PLAYER_JETPACK_ROTATION_ENERGY_PER_SECOND 0.2f
#define PLAYER_JETPACK_SPICE_PER_SECOND 0.08f #define PLAYER_JETPACK_SPICE_PER_SECOND 0.08f
#define PLAYER_BIG_SCALING 300.0 #define PLAYER_BIG_SCALING 300.0
@ -43,22 +47,30 @@
#define ORB_HEAL_RATE 0.2 #define ORB_HEAL_RATE 0.2
#define ORB_MAX_FORCE 200.0 #define ORB_MAX_FORCE 200.0
#define SCANNER_ENERGY_USE 0.05f #define VISION_RADIUS 12.0f
#define MAX_HAND_REACH 1.0f #define MAX_HAND_REACH 1.0f
#define SCANNER_SCAN_RATE 0.5f
#define SCANNER_RADIUS 1.0f
#define GOLD_COLLECT_RADIUS 0.3f #define GOLD_COLLECT_RADIUS 0.3f
#define BUILD_BOX_SNAP_DIST_TO_SHIP 0.2f #define BUILD_BOX_SNAP_DIST_TO_SHIP 0.2f
#define BOX_MASS 1.0f #define BOX_MASS 1.0f
#define COLLISION_DAMAGE_SCALING 0.15f #define COLLISION_DAMAGE_SCALING 0.15f
#define THRUSTER_FORCE 24.0f #define THRUSTER_FORCE 24.0f
#define THRUSTER_ENERGY_USED_PER_SECOND 0.005f #define THRUSTER_ENERGY_USED_PER_SECOND 0.005f
#define GYROSCOPE_ENERGY_USED_PER_SECOND 0.005f #define GYROSCOPE_ENERGY_USED_PER_SECOND 0.005f
#define GYROSCOPE_TORQUE 1.5f #define GYROSCOPE_TORQUE 1.5f
#define GYROSCOPE_PROPORTIONAL_INERTIAL_RESPONSE 0.7 // between 0-1. How strongly responds to rotation, to stop the rotation #define GYROSCOPE_PROPORTIONAL_INERTIAL_RESPONSE 0.7 // between 0-1. How strongly responds to rotation, to stop the rotation
#define CLOAKING_ENERGY_USE 0.1f #define CLOAKING_ENERGY_USE 0.1f
#define CLOAKING_PANEL_SIZE BOX_SIZE * 3.0f #define CLOAKING_PANEL_SIZE BOX_SIZE * 3.0f
#define VISION_RADIUS 12.0f
#define SCANNER_ENERGY_USE 0.05f
#define SCANNER_SCAN_RATE 0.5f
#define SCANNER_RADIUS 1.0f
#define SCANNER_MAX_RANGE 1500.0
#define SCANNER_MIN_RANGE 1.0
#define SCANNER_MAX_POINTS 10
#define MAX_SERVER_TO_CLIENT 1024 * 512 // maximum size of serialized gamestate buffer #define MAX_SERVER_TO_CLIENT 1024 * 512 // maximum size of serialized gamestate buffer
#define MAX_CLIENT_TO_SERVER 1024 * 10 // maximum size of serialized inputs and mic data #define MAX_CLIENT_TO_SERVER 1024 * 10 // maximum size of serialized inputs and mic data
#define GRAVITY_CONSTANT 0.05f #define GRAVITY_CONSTANT 0.05f
@ -77,8 +89,6 @@
#define TIME_BETWEEN_WORLD_SAVE 30.0f #define TIME_BETWEEN_WORLD_SAVE 30.0f
#endif #endif
#define MISSILE_EXPLOSION_PUSH 2.5f
#define MISSILE_EXPLOSION_RADIUS 0.4f
#define BOMB_EXPLOSION_PUSH 5.0f #define BOMB_EXPLOSION_PUSH 5.0f
#define BOMB_EXPLOSION_RADIUS 1.0f #define BOMB_EXPLOSION_RADIUS 1.0f
@ -224,6 +234,13 @@ static inline bool entityids_same(EntityID a, EntityID b)
return (a.generation == b.generation) && (a.index == b.index); return (a.generation == b.generation) && (a.index == b.index);
} }
enum ScannerPointKind
{
Platonic,
Neutral,
Enemy,
};
// when updated, must update serialization, comparison in main.c, and the server // when updated, must update serialization, comparison in main.c, and the server
// on input received processing function // on input received processing function
typedef struct InputFrame typedef struct InputFrame
@ -328,7 +345,6 @@ typedef struct Entity
// used by medbay and cockpit // used by medbay and cockpit
EntityID player_who_is_inside_of_me; EntityID player_who_is_inside_of_me;
// only serialized when box_type is thruster or gyroscope, used for both. Thrust // only serialized when box_type is thruster or gyroscope, used for both. Thrust
// can mean rotation thrust! // can mean rotation thrust!
double wanted_thrust; // the thrust command applied to the thruster double wanted_thrust; // the thrust command applied to the thruster
@ -353,8 +369,13 @@ typedef struct Entity
BOX_UNLOCKS_TYPE blueprints_learned; BOX_UNLOCKS_TYPE blueprints_learned;
double scanner_head_rotate_speed; // not serialized, cosmetic double scanner_head_rotate_speed; // not serialized, cosmetic
double scanner_head_rotate; double scanner_head_rotate;
cpVect platonic_nearest_direction; // normalized
double platonic_detection_strength; // from zero to one struct ScannerPoint
{
char kind; // is of ScannerPointKind
char x;
char y;
} scanner_points[SCANNER_MAX_POINTS];
} Entity; } Entity;
typedef struct Player typedef struct Player
@ -583,7 +604,7 @@ typedef struct BoxCentered
static inline bool box_has_point(BoxCentered box, cpVect point) static inline bool box_has_point(BoxCentered box, cpVect point)
{ {
cpVect local_point = cpvspin(cpvsub(point, box.pos), -box.rotation); cpVect local_point = cpvspin(cpvsub(point, box.pos), -box.rotation);
return has_point((AABB){.x = -box.size.x/2.0, .y = -box.size.y/2.0, .width = box.size.x, .height = box.size.y}, local_point); return has_point((AABB){.x = -box.size.x / 2.0, .y = -box.size.y / 2.0, .width = box.size.x, .height = box.size.y}, local_point);
} }
static double sign(double f) static double sign(double f)

Loading…
Cancel
Save