From b2fcd2d60691f14b0a2dbee71274c45d60c3bd33 Mon Sep 17 00:00:00 2001 From: Cameron Reikes Date: Sun, 11 Dec 2022 16:00:48 -0800 Subject: [PATCH] Add tutorial helpers and gyroscope spin feedback --- buildsettings.h | 6 +- flight.rdbg | Bin 1926 -> 1450 bytes gamestate.c | 29 ++++---- loaded/cockpit.png | Bin 277 -> 428 bytes loaded/cockpit_used.png | Bin 417 -> 651 bytes loaded/gyroscope.png | Bin 542 -> 514 bytes loaded/gyroscope_spinner.png | Bin 0 -> 154 bytes loaded/right_click.png | Bin 0 -> 304 bytes loaded/rothelp.png | Bin 0 -> 798 bytes main.c | 132 ++++++++++++++++++++++++++++++++--- tooling.ahk | 2 +- types.h | 44 ++++++++++-- 12 files changed, 181 insertions(+), 32 deletions(-) create mode 100644 loaded/gyroscope_spinner.png create mode 100644 loaded/right_click.png create mode 100644 loaded/rothelp.png diff --git a/buildsettings.h b/buildsettings.h index 3d3b2a2..feb161f 100644 --- a/buildsettings.h +++ b/buildsettings.h @@ -19,10 +19,10 @@ // #define DEBUG_WORLD // #define UNLOCK_ALL #define TIME_BETWEEN_WORLD_SAVE 1.0f -#define INFINITE_RESOURCES -// #define DEBUG_TOOLS +// #define INFINITE_RESOURCES +#define DEBUG_TOOLS // #define FAT_THRUSTERS -#define NO_GRAVITY +// #define NO_GRAVITY // #define NO_SUNS #else diff --git a/flight.rdbg b/flight.rdbg index e51b7d19a86ff251746291bd1b4e1ea80d8976bb..1ed3c22354d4d6b0d84ed479dbe08a0c429da2d2 100644 GIT binary patch delta 56 zcmZqUU&Xy)5{ob+0|Ns$5a;A4C+5T#TSe6>20GIOV5QYH5PRb?uUXYzd(7>>K@8N?waaA(X@hVDKuiT)1!Omh1I1vPU{du^_k(N% zxeg`{73M?I0x_5$O{5~V7-TN8J<&#%X0dun`9LWSpj2ia(Cw-5m5e}k1uu|DDM~Dl mPb`ivE-X!COqsltWhtZJnext_box = separate_grids[cur_separate_grid_index]; separate_grids[cur_separate_grid_index] = get_id(gs, N); - cur_separate_grid_size++; processed_boxes++; if (get_id(gs, N).index > biggest_box_index) @@ -741,14 +736,8 @@ static void grid_correct_for_holes(GameState *gs, struct Entity *grid) } } - if (biggest_box_index > biggest_separate_grid_length) - { - biggest_separate_grid_length = biggest_box_index; - biggest_separate_grid_index = cur_separate_grid_index; - } cur_separate_grid_index++; flight_assert(cur_separate_grid_index < MAX_SEPARATE_GRIDS); - cur_separate_grid_size = 0; } // create new grids for all lists of boxes except for the biggest one. @@ -1106,14 +1095,13 @@ SerMaybeFailure ser_data(SerState *ser, char *data, size_t data_len, const char // now compare! SER_ASSERT(strcmp(read_name, name) == 0); - // deserialize and check the size too! SER_ASSERT(data_len < 65535); // uh oh stinky! uint16_t expected_size = (uint16_t)data_len; uint16_t got_size = 0; for (int b = 0; b < sizeof(got_size); b++) { - ((char*)&got_size)[b] = ser->bytes[ser->cursor]; + ((char *)&got_size)[b] = ser->bytes[ser->cursor]; ser->cursor += 1; SER_ASSERT(ser->cursor <= ser->max_size); } @@ -1382,6 +1370,8 @@ SerMaybeFailure ser_entity(SerState *ser, GameState *gs, Entity *e) case BoxGyroscope: SER_MAYBE_RETURN(ser_f(ser, &e->thrust)); SER_MAYBE_RETURN(ser_f(ser, &e->wanted_thrust)); + SER_MAYBE_RETURN(ser_f(ser, &e->gyrospin_angle)); + SER_MAYBE_RETURN(ser_f(ser, &e->gyrospin_velocity)); break; case BoxBattery: SER_MAYBE_RETURN(ser_f(ser, &e->energy_used)); @@ -2408,10 +2398,12 @@ void process(struct GameState *gs, double dt) if (potential_seat->box_type == BoxScanner) // learn everything from the scanner { + flight_assert(box_interactible(potential_seat->box_type)); player->box_unlocks |= potential_seat->blueprints_learned; } if (potential_seat->box_type == BoxMerge) // disconnect! { + flight_assert(box_interactible(potential_seat->box_type)); potential_seat->wants_disconnect = true; grid_correct_for_holes(gs, box_grid(potential_seat)); flight_assert(potential_seat->exists); @@ -2420,6 +2412,7 @@ void process(struct GameState *gs, double dt) } if (potential_seat->box_type == BoxCockpit || potential_seat->box_type == BoxMedbay) { + flight_assert(box_interactible(potential_seat->box_type)); // don't let players get inside of cockpits that somebody else is already inside of if (get_entity(gs, potential_seat->player_who_is_inside_of_me) == NULL) { @@ -2833,6 +2826,10 @@ void process(struct GameState *gs, double dt) { double energy_to_consume = cur_box->wanted_thrust * THRUSTER_ENERGY_USED_PER_SECOND * dt; + if (cur_box->wanted_thrust == 0.0) + { + cur_box->thrust = 0.0; + } if (energy_to_consume > 0.0) { cur_box->thrust = 0.0; @@ -2844,6 +2841,12 @@ void process(struct GameState *gs, double dt) } if (cur_box->box_type == BoxGyroscope) { + cur_box->gyrospin_velocity = lerp(cur_box->gyrospin_velocity, cur_box->thrust * 20.0, dt * 5.0); + cur_box->gyrospin_angle += cur_box->gyrospin_velocity * dt; + if (cur_box->wanted_thrust == 0.0) + { + cur_box->thrust = 0.0; + } double energy_to_consume = fabs(cur_box->wanted_thrust * GYROSCOPE_ENERGY_USED_PER_SECOND * dt); if (energy_to_consume > 0.0) { diff --git a/loaded/cockpit.png b/loaded/cockpit.png index c1e25490535e98dae147711a3b46d21686f21e9c..c464a85b80767366037242944a19db954845b838 100644 GIT binary patch literal 428 zcmV;d0aN~oP)Px$W=TXrR7i={RxxYBKp1@|`4I}WW1*u+kC3If6%;yj>Qc-f(B0rvaL+G@xHxqv zWN-^EA)H9vgpO^Y8T|*>#V?*VNpqSO`j-1bF7JKcdvF(qEiSKY2~C*Rby9n7m!<7t zy5#GHmr7*!$1+W*Qj}OFw|H|vE7hLcWuDt*c7H5`C{7w?MZ3@HoCE+M6w49SK@`iD zS!IPL$Ra-^RmECnl?72O4GQYv{^r}qlj)2EavKQ6azwT`z4o54RtCqwD2vGHwH;vJ zvdMG?BMRpL09tiHVbU|@P?|+5c^XQyh@e^&h4bGJ`F{&+;?*vLi}SP0jqAnnBBh0_ zhO6T5GI)LaIEhF-x&fe8Z^+O07iMhYRkBGaHRqj^1PPfL2;mnNvUqcll>w{O8$Vt+ zoOkg2^q6}js33a)ph86+gz#~DH`M+q0JfKYktu+kU0Kr*kJ>ale5oU(LI@veZhQeK WB9*OgQeG_p00009^Ye literal 277 zcmV+w0qXvVP)Px#&q+iLld%fIFcd{^NPx%MM*?KR7i=PR843TK^T2g76lJIr^TwLLN7uQmk_~_N+8gHV4=_+N>U-E&>s&9 zB|(e`p@#?!7Q|jsN-4x@68OsUyNK$Qv^gf66JBZlpObwuvk2zUdgg2i_4`H zDVI_ty}U^c%i)5Fta?A?i~s;k`>?=b!*XaW93oO3_!Vz2Dw4&*A!1k#RhUsTQ;CkB zw<bht#gJ%$l6Z74sJ-(X!LBngINV$zz!!nwcU6fQ8i^ zzW#pyan37WdYdk+?%>UV?pj-4ne6({iF5R?gW(J3eG>G*?8R+mx9d1f1a0*Y7=(ry~7WUztR+(W1>p%XQGis~Z3YhDPb}w|7K2agKPB zEySvt>`B;cwCI_$O4kGD>w#@+oG9NaxeV35>{2Txv^YD3BfzsPlBx&!4flWgc lP1--oz-t58wg#_h`~ko(^kI$csR;l8002ovPDHLkV1oU2Fd6^= literal 417 zcmV;S0bc%zP)Px$TS-JgR5*=|ld($zaTLctCs(b}q>{Br;Fg0&TZBtOQ&2+NEk;Aw(9o7H%|U_K zl9SM1P)mvga-2|YLAY2^H%6Nx{2KCi-S5t`zT3O^-uHdp@Ao?mAeAu%K7Bfm0DQbY zX#Sj6T3EAej3v@yl2K%m`_0*b=yf~vx*cMPw2)?s%wkP6Ek`shN0`N$TXcJE2a88U zP0Mj}p#)cUSBVGxp}Wf3N>r03y47xBwOdMYpc8}<#2*{r3%3N-mXG&ezXn1^o;Hr{z)Jy@StI3^Rs00000 LNkvXXu0mjfX+F9; diff --git a/loaded/gyroscope.png b/loaded/gyroscope.png index 46fd47be30c0e38b80a5634b8aaf88307451e49a..b97b0397e5f398f4f6b8b710d4a4c1e26bc32020 100644 GIT binary patch delta 475 zcmV<10VMvO1cC&RF@L;CL_t(YiLF&JOT$1IeJ5Roj7exl2L~k?4AQ!YV}>vpK0iF8`97F{j#K|J(%l5V8qJglHP4|15RyrFZiKE;eQG^Sq z3)RSU0z4Xx&`IZ(0*gB^xn2gA?Mq1_qE?1nb*_p4plT$!2u#ky2I0qK5Ro87P!whv zI9@=LI3k}P!+*TMD&B%+`$*ylEQ@N4^e6qU?4FAVZ$_I%I)n{^evhKxqsDtsk;|f0 z;qvOHoPg-ul&&hcKsp~22Ybey%Mvf@6qN*k?8#Tnq;!_0CoAXDCF=@TS*RSjJE#%` za}NN|PY(bzX_~|l5f_#r7u{bUe#ru2nJ5w|szoaK%Tz_kx%d&WCoYO4ab&Enx;`M1 zyKX(-GK;#@GA&aizyCc201zN+`dW(`$ADZEbw|nOM}scmF3NVX|HN5;{{xsu)ivxI R8l(UK002ovPDHLkV1kBY)v*8o delta 503 zcmVjszcLqU}G}*;QlL?bZ)*;uj1O@3B%3dD;^SeL$QCHes~$UcKi{SA)f#Q@@L<;;6S_5us!PS$1dPgjdhj@BxziCG z+X}2DZ z6JZecE)t!v;&;bJ@SurVIkrW{!)~mb+R=c7iECOe*fPVqRFam-ieLZi0{{pxZ~BpG tGH`%*D|1Na$HOl1vq;;;;^4Hu{{rGQbP0l+XkKPr@Px#>PbXFR9J=WmP-=EAP7VuHTS==v(h37@|n?+MZaYP>>wgU0000$CD>YQt+ipu zY})R|70S%q1wY01_2;({-1#}_Fa2%;BMFkuTA=8+*;>Z`6BT><=r7N}JDMy_knwYc z68$b#6U2f{tdP*YLEk*Px%*hxe|RCt{2nNO0VAQZ+QQ6Lwzt7REgq9wGG+y1V2zmEn} z*R`>|swxlD=MWjAB*z-yRpVR%6-B`&2g_9y1+xWvHvc3>DJ4k@LJ0Zw^+iI6%{UBv3V%)01m&s6V4QJfS$b_K%d%9Ts624RaL8ZVwn2I7 zZPr(H?;B_S|Lt~Dn>VkD$905ge{?AZ|K+*m&tW45i@ z=IAE$6*Zyx3+i_$Pn)Cpqp>Io8plyqRkeJDkK;&0-%o7{NZ+EE?iZg*BJ%I8|K!uh zDfc$?ev7}5JXZ$yf)qj!=bZY!mz;Cf_x;9@LAd2_!;>}&oJcsUk-Z1yljq8wPoV0S z#bnGToF1I^3OoC{a0%zKv)6AgPn9IcvA)8E_Vw|%H{(>hv8BO8j-A6MffS2CfNzy- z=k(dOTn3yqC=vO84VuUy9HU7jDW&?VEbSS5emg(mmo%b$Gj1iGsXdclYgtGwXma6{ zVm*tr=|cI$vlY|izOu|XO*~^4N-y4N^^GWlZ~-f5%1@zW{d_rm9!In~+lo4=2t6A+ z+n4#ezZRmNrZbopY(VdataLength; unsigned char *decompressed = malloc( sizeof *decompressed * MAX_SERVER_TO_CLIENT); // @Robust no malloc size_t decompressed_max_len = MAX_SERVER_TO_CLIENT; @@ -1603,6 +1637,26 @@ static void frame(void) local_hand_pos = cpvsub(global_hand_pos, entity_pos(myentity())); } + // for tutorial text + piloting_rotation_capable_ship = false; + + if (myentity() != NULL) + { + Entity *inside_of = get_entity(&gs, myentity()->currently_inside_of_box); + if (inside_of != NULL && inside_of->box_type == BoxCockpit) + { + BOXES_ITER(&gs, cur, box_grid(inside_of)) + { + flight_assert(cur->is_box); + if (cur->box_type == BoxGyroscope) + { + piloting_rotation_capable_ship = true; + break; + } + } + } + } + // process player interaction (squad invites) if (interact_pressed && myplayer() != NULL && myplayer()->squad != SquadNone) ENTITIES_ITER(cur) @@ -1632,7 +1686,15 @@ static void frame(void) if (cpvlength(input) > 0.0) input = cpvnormalize(input); cur_input_frame.movement = input; - cur_input_frame.rotation = (float)keydown[SAPP_KEYCODE_E] - (float)keydown[SAPP_KEYCODE_Q]; + cur_input_frame.rotation = -((float)keydown[SAPP_KEYCODE_E] - (float)keydown[SAPP_KEYCODE_Q]); + + if (fabs(cur_input_frame.rotation) > 0.01f) + { + if (piloting_rotation_capable_ship) + rotation_in_cockpit_learned += dt * 0.35; + else + rotation_learned += dt * 0.35; + } if (interact_pressed) cur_input_frame.seat_action = interact_pressed; @@ -1745,6 +1807,10 @@ static void frame(void) Log("Failed to send packet error %d\n", err); enet_packet_destroy(packet); } + else + { + total_bytes_sent += packet->dataLength; + } last_sent_input_time = stm_now(); } else @@ -1761,8 +1827,9 @@ static void frame(void) global_hand_pos = get_global_hand_pos(world_mouse_pos, &hand_at_arms_length); - Entity *placing_grid = box_grid(closest_box_to_point_in_radius( - &gs, global_hand_pos, BUILD_BOX_SNAP_DIST_TO_SHIP, NULL)); + Entity *nearest_box = closest_box_to_point_in_radius(&gs, global_hand_pos, BUILD_BOX_SNAP_DIST_TO_SHIP, NULL); + Entity *placing_grid = box_grid(nearest_box); + if (placing_grid == NULL) { build_preview = (struct BuildPreviewInfo){ @@ -1887,15 +1954,14 @@ static void frame(void) // building preview if (currently_building() != BoxInvalid && can_build(currently_building())) { - set_color_values(0.5, 0.5, 0.5, - (sin((float)exec_time * 9.0) + 1.0) / 3.0 + 0.2); transform_scope { - sgp_set_image(0, boxinfo(currently_building()).image); rotate_at(build_preview.grid_rotation + rotangle(cur_editing_rotation), global_hand_pos.x, global_hand_pos.y); + sgp_set_image(0, boxinfo(currently_building()).image); + set_color_values(0.5, 0.5, 0.5, (sin((float)exec_time * 9.0) + 1.0) / 3.0 + 0.2); pipeline_scope(goodpixel_pipeline) draw_texture_centered(global_hand_pos, BOX_SIZE); // drawbox(hand_pos, build_preview.grid_rotation, 0.0, @@ -1972,6 +2038,33 @@ static void frame(void) */ } + if (box_interactible(b->box_type)) + { + if (box_has_point((BoxCentered){ + .pos = entity_pos(b), + .rotation = entity_rotation(b), + .size = (cpVect){BOX_SIZE, BOX_SIZE}, + }, + world_mouse_pos)) + { + // set_color_values(1.0, 1.0, 1.0, 0.2); + // draw_color_rect_centered(entity_pos(b), BOX_SIZE); + set_color(WHITE); + draw_circle(entity_pos(b), BOX_SIZE / 1.75 + sin(exec_time * 5.0) * BOX_SIZE * 0.1); + transform_scope + { + pipeline_scope(goodpixel_pipeline) + { + sgp_set_image(0, image_rightclick); + cpVect draw_at = cpvadd(entity_pos(b), cpv(BOX_SIZE, 0)); + rotate_at(-entity_rotation(b) - rotangle(b->compass_rotation), draw_at.x, draw_at.y); + draw_texture_centered(draw_at, BOX_SIZE + sin(exec_time * 5.0) * BOX_SIZE * 0.1); + sgp_reset_image(0); + } + } + } + } + sgp_set_image(0, img); if (b->indestructible) { @@ -2007,11 +2100,27 @@ static void frame(void) pipeline_scope(goodpixel_pipeline) { rotate_at(b->scanner_head_rotate, entity_pos(b).x, entity_pos(b).y); + set_color(WHITE); + draw_texture_centered(entity_pos(b), BOX_SIZE); + } + } + sgp_reset_image(0); + } + + if (b->box_type == BoxGyroscope) + { + sgp_set_image(0, image_gyrospin); + + transform_scope + { + pipeline_scope(goodpixel_pipeline) + { + set_color(WHITE); + rotate_at(b->gyrospin_angle, entity_pos(b).x, entity_pos(b).y); draw_texture_centered(entity_pos(b), BOX_SIZE); } } sgp_reset_image(0); - set_color(WHITE); } // scanner range, visualizes what scanner can scan @@ -2221,6 +2330,13 @@ void event(const sapp_event *e) mouse_frozen = !mouse_frozen; } #endif + if (e->key_code == SAPP_KEYCODE_F3) + { + // print statistics + double received_per_sec = (double)total_bytes_received / exec_time; + double sent_per_sec = (double)total_bytes_sent / exec_time; + Log("Byte/s received %d byte/s sent %d\n", (int)received_per_sec, (int)sent_per_sec); + } if (e->key_code == SAPP_KEYCODE_TAB) { if (zoom_target < DEFAULT_ZOOM) diff --git a/tooling.ahk b/tooling.ahk index 8763350..5daa540 100644 --- a/tooling.ahk +++ b/tooling.ahk @@ -14,7 +14,7 @@ WinActivate, flightbuild If WinActive("flightbuild") { Send, {Enter} - Send, remedybg continue-execution && timeout 1 && remedybg.exe stop-debugging && msbuild && remedybg.exe start-debugging {Enter} + Send, remedybg continue-execution && timeout 1 && remedybg.exe stop-debugging && shadergen.bat && msbuild && remedybg.exe start-debugging {Enter} } Send, {Blind} ; So it doesn't hold down ctrl after running! WTF return diff --git a/types.h b/types.h index 9f19f1c..f0f950b 100644 --- a/types.h +++ b/types.h @@ -3,7 +3,7 @@ #include "buildsettings.h" #define MAX_BOX_TYPES 64 -#define ZOOM_MIN 0.10 // smaller means you can zoom out more +#define ZOOM_MIN 0.10 // smaller means you can zoom out more #define ZOOM_MAX 1500.0 // bigger means you can zoom in more #define MAX_PLAYERS 16 #define MAX_SUNS 8 @@ -29,7 +29,6 @@ // centered on the sprite #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}) -// distance at which things become geostationary and no more solar power! #define PLAYER_JETPACK_ROTATION_ENERGY_PER_SECOND 0.2f #define PLAYER_JETPACK_SPICE_PER_SECOND 0.08f #define SCANNER_ENERGY_USE 0.05f @@ -60,7 +59,7 @@ #define EXPLOSION_DAMAGE_PER_SEC 10.0f #define EXPLOSION_DAMAGE_THRESHOLD 0.2f // how much damage until it explodes #define GOLD_UNLOCK_RADIUS 1.0f -#ifndef TIME_BETWEEN_WORLD_SAVE +#ifndef TIME_BETWEEN_WORLD_SAVE #define TIME_BETWEEN_WORLD_SAVE 30.0f #endif @@ -104,7 +103,7 @@ #include "cpVect.h" // offers vector functions and types for the structs #include "miniaudio.h" // @Robust BAD. using miniaudio mutex construct for server thread synchronization. AWFUL! -#include // sqrt and cos vector functions +#include // sqrt and cos vector functions #include // tick is unsigned integer #include // logging on errors for functions @@ -170,6 +169,20 @@ enum BoxType BoxLast, }; +static inline bool box_interactible(enum BoxType type) +{ + enum BoxType types[] = { + BoxCockpit, + BoxMedbay, + BoxMerge, + BoxScanner, + }; + for (int i = 0; i < ARRLEN(types); i++) + if (types[i] == type) + return true; + return false; +} + enum CompassRotation { Right, @@ -198,7 +211,7 @@ typedef struct EntityID 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); } // when updated, must update serialization, comparison in main.c, and the server @@ -299,6 +312,10 @@ typedef struct Entity // can mean rotation thrust! double wanted_thrust; // the thrust command applied to the thruster double thrust; // the actual thrust it can provide based on energy sources in the grid + + // only gyroscope, velocity not serialized. Cosmetic + double gyrospin_angle; + double gyrospin_velocity; // only serialized when box_type is battery double energy_used; // battery, between 0 battery capacity. You have to look through code to figure out what that is! haha sucker! @@ -311,9 +328,9 @@ typedef struct Entity // scanner only stuff! EntityID currently_scanning; - double currently_scanning_progress; // when 1.0, scans it! + double currently_scanning_progress; // when 1.0, scans it! 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; cpVect platonic_nearest_direction; // normalized double platonic_detection_strength; // from zero to one @@ -537,6 +554,19 @@ static inline double cpvangle(cpVect vec) return atan2(vec.y, vec.x); } +typedef struct BoxCentered +{ + cpVect pos; + double rotation; + cpVect size; +} BoxCentered; + +static inline bool box_has_point(BoxCentered box, cpVect point) +{ + 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); +} + static double sign(double f) { if (f >= 0.0f)