From 238c81ecde9b6b6d86f7dc5000973e3aa1c24dd8 Mon Sep 17 00:00:00 2001 From: Cameron Reikes Date: Sun, 6 Nov 2022 13:25:45 -0800 Subject: [PATCH] Add unlockable explosive block --- gamestate.c | 100 +++++++++++++++++++++++++++++++++++-------- loaded/explosion.png | Bin 0 -> 5430 bytes loaded/explosive.png | Bin 0 -> 691 bytes loaded/mystery.png | Bin 0 -> 592 bytes main.c | 91 ++++++++++++++++++++++++++++----------- server.c | 8 ++++ types.h | 19 ++++++-- 7 files changed, 170 insertions(+), 48 deletions(-) create mode 100644 loaded/explosion.png create mode 100644 loaded/explosive.png create mode 100644 loaded/mystery.png diff --git a/gamestate.c b/gamestate.c index fc582cb..a7eaa9f 100644 --- a/gamestate.c +++ b/gamestate.c @@ -471,11 +471,18 @@ static cpBool on_damage(cpArbiter* arb, cpSpace* space, cpDataPointer userData) entity_b = cp_shape_entity(b); float damage = V2length(cp_to_v2(cpArbiterTotalImpulse(arb))) * COLLISION_DAMAGE_SCALING; + + if (entity_a->is_box && entity_a->box_type == BoxExplosive) + entity_a->damage += 2.0f*EXPLOSION_DAMAGE_THRESHOLD; + if (entity_b->is_box && entity_b->box_type == BoxExplosive) + entity_b->damage += 2.0f*EXPLOSION_DAMAGE_THRESHOLD; + if (damage > 0.05f) { // Log("Collision with damage %f\n", damage); entity_a->damage += damage; entity_b->damage += damage; + } // b must be the key passed into the post step removed, the key is cast into its shape @@ -515,12 +522,6 @@ V2 grid_com(Entity* grid) return cp_to_v2(cpBodyLocalToWorld(grid->body, cpBodyGetCenterOfGravity(grid->body))); } -V2 entity_pos(Entity* e) -{ - assert(!e->is_box); - // @Robust merge entity_pos with box_pos - return cp_to_v2(cpBodyGetPosition(e->body)); -} V2 grid_vel(Entity* grid) { return cp_to_v2(cpBodyGetVelocity(grid->body)); @@ -568,15 +569,20 @@ float entity_shape_mass(Entity* box) assert(box->shape != NULL); return (float)cpShapeGetMass(box->shape); } -V2 box_pos(Entity* box) -{ - assert(box->is_box); - return V2add(entity_pos(box_grid(box)), V2rotate(entity_shape_pos(box), entity_rotation(box_grid(box)))); -} float box_rotation(Entity* box) { return (float)cpBodyGetAngle(cpShapeGetBody(box->shape)); } +V2 entity_pos(Entity* e) +{ + if (e->is_box) { + return V2add(entity_pos(box_grid(e)), V2rotate(entity_shape_pos(e), entity_rotation(box_grid(e)))); + } + else { + assert(e->body != NULL); + return cp_to_v2(cpBodyGetPosition(e->body)); + } +} struct BodyData { @@ -711,6 +717,7 @@ void ser_player(SerState* ser, Player* p) SER_VAR(&p->connected); if (p->connected) { + SER_VAR(&p->unlocked_bombs); ser_entityid(ser, &p->entity); ser_inputframe(ser, &p->input); } @@ -779,6 +786,14 @@ void ser_entity(SerState* ser, GameState* gs, Entity* e) SER_VAR(&e->goldness); } + SER_VAR(&e->is_explosion); + if (e->is_explosion) + { + ser_V2(ser, &e->explosion_pos); + ser_V2(ser, &e->explosion_vel); + SER_VAR(&e->explosion_progresss); + } + SER_VAR(&e->is_grid); if (e->is_grid) { @@ -955,6 +970,34 @@ Entity* closest_to_point_in_radius(GameState* gs, V2 point, float radius) return NULL; } +static float cur_explosion_damage = 0.0f; +static V2 explosion_origin = { 0 }; +static void explosion_callback_func(cpShape* shape, cpContactPointSet* points, void* data) +{ + GameState* gs = (GameState*)data; + cp_shape_entity(shape)->damage += cur_explosion_damage; + Entity* parent = get_entity(gs, cp_shape_entity(shape)->shape_parent_entity); + V2 from_pos = entity_pos(cp_shape_entity(shape)); + V2 impulse = V2scale(V2normalize(V2sub(from_pos, explosion_origin)), EXPLOSION_PUSH_STRENGTH); + assert(parent->body != NULL); + cpBodyApplyImpulseAtWorldPoint(parent->body, v2_to_cp(impulse), v2_to_cp(from_pos)); + +} + +static void do_explosion(GameState* gs, Entity* explosion, float dt) +{ + cur_explosion_damage = dt * EXPLOSION_DAMAGE_PER_SEC; + explosion_origin = explosion->explosion_pos; + + cpBody* tmpbody = cpBodyNew(0.0f, 0.0f); + cpShape* circle = cpCircleShapeNew(tmpbody, EXPLOSION_RADIUS, v2_to_cp(explosion_origin)); + + cpSpaceShapeQuery(gs->space, circle, explosion_callback_func, (void*)gs); + + cpShapeFree(circle); + cpBodyFree(tmpbody); +} + V2 box_facing_vector(Entity* box) { assert(box->is_box); @@ -1029,7 +1072,7 @@ void process(GameState* gs, float dt) assert(p->is_player); #ifdef INFINITE_RESOURCES - p->spice_taken_away = 0.0f; + p->damage = 0.0f; #endif // update gold win condition if (V2length(V2sub(cp_to_v2(cpBodyGetPosition(p->body)), gs->goldpos)) < GOLD_COLLECT_RADIUS) @@ -1066,7 +1109,7 @@ void process(GameState* gs, float dt) } else { - V2 pilot_seat_exit_spot = V2add(box_pos(the_seat), V2scale(box_facing_vector(the_seat), BOX_SIZE)); + V2 pilot_seat_exit_spot = V2add(entity_pos(the_seat), V2scale(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->player_who_is_inside_of_me = (EntityID){ 0 }; @@ -1095,10 +1138,10 @@ void process(GameState* gs, float dt) { assert(seat_inside_of->is_box); cpShapeSetFilter(p->shape, CP_SHAPE_FILTER_NONE); // no collisions while in a seat - cpBodySetPosition(p->body, v2_to_cp(box_pos(seat_inside_of))); + cpBodySetPosition(p->body, v2_to_cp(entity_pos(seat_inside_of))); // set thruster thrust from movement - if(seat_inside_of->box_type == BoxCockpit) { + if (seat_inside_of->box_type == BoxCockpit) { Entity* g = get_entity(gs, seat_inside_of->shape_parent_entity); V2 target_direction = { 0 }; @@ -1133,7 +1176,7 @@ void process(GameState* gs, float dt) { Entity* cur_box = cp_shape_entity(nearest); Entity* cur_grid = cp_body_entity(cpShapeGetBody(nearest)); - p->damage -= DAMAGE_TO_PLAYER_PER_BLOCK*((BATTERY_CAPACITY - cur_box->energy_used)/BATTERY_CAPACITY); + p->damage -= DAMAGE_TO_PLAYER_PER_BLOCK * ((BATTERY_CAPACITY - cur_box->energy_used) / BATTERY_CAPACITY); grid_remove_box(gs, cur_grid, cur_box); } else if (target_grid == NULL) @@ -1179,7 +1222,7 @@ void process(GameState* gs, float dt) { cpVect p = cpvsub(cpBodyGetPosition(e->body), v2_to_cp(SUN_POS)); cpFloat sqdist = cpvlengthsq(p); - if(sqdist > (INSTANT_DEATH_DISTANCE_FROM_SUN*INSTANT_DEATH_DISTANCE_FROM_SUN)) + if (sqdist > (INSTANT_DEATH_DISTANCE_FROM_SUN * INSTANT_DEATH_DISTANCE_FROM_SUN)) { entity_destroy(gs, e); continue; @@ -1194,8 +1237,27 @@ void process(GameState* gs, float dt) cpBodyUpdateVelocity(e->body, g, 1.0f, dt); } + if (e->is_explosion) + { + e->explosion_progresss += dt; + e->explosion_pos = V2add(e->explosion_pos, V2scale(e->explosion_vel, dt)); + do_explosion(gs, e, dt); + if (e->explosion_progresss >= EXPLOSION_TIME) + { + entity_destroy(gs, e); + } + } + if (e->is_box) { + if (e->box_type == BoxExplosive && e->damage >= EXPLOSION_DAMAGE_THRESHOLD) + { + Entity* explosion = new_entity(gs); + explosion->is_explosion = true; + explosion->explosion_pos = entity_pos(e); + explosion->explosion_vel = grid_vel(box_grid(e)); + grid_remove_box(gs, get_entity(gs, e->shape_parent_entity), e); + } if (e->damage >= 1.0f) { grid_remove_box(gs, get_entity(gs, e->shape_parent_entity), e); @@ -1208,7 +1270,7 @@ void process(GameState* gs, float dt) BOXES_ITER(gs, cur, e) { if (cur->box_type == BoxSolarPanel) { - cur->sun_amount = clamp01(V2dot(box_facing_vector(cur), V2normalize(V2sub(SUN_POS, box_pos(cur))))); + cur->sun_amount = clamp01(V2dot(box_facing_vector(cur), V2normalize(V2sub(SUN_POS, entity_pos(cur))))); energy_to_add += cur->sun_amount * SOLAR_ENERGY_PER_SECOND * dt; } } @@ -1237,7 +1299,7 @@ void process(GameState* gs, float dt) if (possibly_use_energy(gs, e, energy_to_consume)) { cur->thrust = cur->wanted_thrust; - cpBodyApplyForceAtWorldPoint(e->body, v2_to_cp(thruster_force(cur)), v2_to_cp(box_pos(cur))); + cpBodyApplyForceAtWorldPoint(e->body, v2_to_cp(thruster_force(cur)), v2_to_cp(entity_pos(cur))); } } if (cur->box_type == BoxMedbay) diff --git a/loaded/explosion.png b/loaded/explosion.png new file mode 100644 index 0000000000000000000000000000000000000000..528b0514454b95196a70e0b14c3730857d92b8d3 GIT binary patch literal 5430 zcmV-670K#}P)EX>4Tx04R}tkv&MmKpe$iTeYGUK|6>#WT;LS#4jABibb$c+6t{Ym|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfbaGO3krMxx6k5c1aNLh~_a1le0B^0t6r*h%P*hV- zL?c2vvnu#s(TxuDVF=SAGqhN8F$LH0bq^0;@4`IG{oJ3UN6s1y@Cd|nOw&!`4dR(i zQ{%i(9ApJiCO#(~)9Hf5k6f1=e&d|C*~>G7dMYtb93&RLejeT)G9U7%jItnXvXs-FP9XW&Y0`pY$7_LKB# zQwtpdz1zUWbyJh}fXf|V;7Jp8(UyEPy}2Clen#Jv0s3!&t~IB(#y(CTfE0DLd;=UD z0;74#UUzwSXKQc&o@w;=1Fm0kznma|)Bpeg24YJ`L;(K){{a7>y{D4^000SaNLh0L z01FcU01FcV0GgZ_00007bV*G`2j&X~6$2WQ(D%>)024AvL_t(|+U;FSuj5P+t!~>% z?p(wtV2gwhLM&MD|9=Kc#F`~65Z~N995;&_e^dA5RCRS8_i0O(olIuN$vJiE(cRS| z%kia;^wqv_5y|!+xj$4{2=K9i?<(K91l}v3jTGsVgFcY&nf$-v-dooXONjJIfnTfd zrmrdX*Uf7ouPGru3K`NT1OA%=ngQ=Afo1XDDV6u$JsHv`0shwje3Iv24@nU5|26QZ z;Cml}4Cw=d{*wY(U-3N;`~;v+Km-fy3I2Q{pPw8;yc;s44`}6Co+Ek$y9*E?IRrqE zrV8-ZX_3Sv!&?%ef5(77DnJq7PF*|rTn;KhAp{V^lD+d-dF_$m%>TSL8PYokz5|du zA>%WICfvG@peE!iOz)@Xm_ZA^6GQ7HbNbeAM25NtL&$?!~x72`!t8ZZJN3A~~ZOZ_YbVBpWECcs|3w^z@0INhTvWTFZa`o!&7QpsjwdUT+lvb|mQC zou2VPe#eoh)pRR&(BB#Sn$>UMoZou@@aJ<-*TIngK9B(rQ=N zO@sl6(18N%!G(_Mc_%h-btwt@8-OoC@YfFTGw2o}*2Ma)05D?x)?5Iu8i*vY;()dC z`)fsn?diR(dj1{))&$SKhm7qA&we!tu5kfaS+l@j1%dwtuhA`_3mBjd;DOKP2Gj@; zB>{^Cb_)D8Sibe#^Xr}1>Z;Y?CM4*uu>OeUYw!?s4g3R~%=*`0{k>uR5z9~ftA%O; zR#u=%u!87c8^YEoV0AE%mEc}K^N~FJL9Kat`Nrgqx09~9^e{09;Qvf$4v z|0bvSQ=1fu0bw*Im`Sh#BCJ97BW^1hikO=r00zb?5GvFUd2CyMPpOxlCgMNKJ+Gd98q zoQ=UXZVa4P5<+ALU4-YFHcCiA+n=qmKsyJPuKJ zwPH|z;gD|+K-QF?R@-l#yz!BUP{?=4j_=o_kKQ~)wn*gwWSIYr7y-(;lWFUPbU2>BuGGnQj!1px={pJ6Ga#laheq% zll&j!fT5xYR)y~~Mf}&0K*%5vs(^L@v&w4g-^k1L2y1z{GP(D%y+{_2<$Ubln*F;n z(mXHX|B6R4QbhK9Pb%xuF2IYkRuC9=tqQ>8-|F6BHFW4D9`Sz_>#wDVsJ@f>J&!IuSbx|RWG4k5gs-^9wmMZe zkQ>GUI%3t{Ja;yU(^{mt5TgC}@5Sz`WKF1TB0zQuL6%FXEq0Ja0bEy*DuuY-$i|p5 zoDrdj{3%3$B=TP;7-5!PoAJ8H|7E1WI4q0bPR}BSHqej)M55E4_@>A*?M43EQ~+mW zb(QR(7kiRTZXrOeVY9W!p|)6a0sJy0urh;)EB*yDOb2s=^|PsAnJ7WG$o^ep0hW!i zq8w|+d8Pt6z&vYRKyoZUNqvp}BL8g#B1;KacBUI@vsFn=3XmNJCW) zXjc^?PCEeCWvgM*AxR-5qqk* ziRHL&ikJ-*=t!29EP20Hj+S)pbppYt`er94yT}E!cGOso`w$^jibYoM0XP22%WwQ) zNl?2NOC6HPKU)Z3Eim-@>MiQNQ7{@cU{wZKuD36Mno0pQpA=|;}w zxb0Dbg(SID0VeTVlUZAwEywE9uQ zmg>}U&~$GyGO*DAesqHL<`@8_|7Z{Zn;4Fjh;&hbSh1%Ve&6dGZ1oUs8Ve|-2Eh8# z)|9}j4J=2j0O$1#w%Wy7?)V}Xz?1+xRq88iY#d1q%VPc2LXXupwx+}r#sGaI0X&P} z%X6EuwYv9O#ImVNtasj5D)CAX_?qe-92eZ|0x*iiM#Ve0?hO_mNI+7Yps;*F6<`}h z90SI;BZ_PV<8c>|ME++49?bIf!)#C2o$)}C@q({Ff{656mcNH{2d@uK91wN^67WA7 zbZj9%KaB2LaS*#9P=bZbB3KUEQ`{2VKD+;hD3b2*)&Y|A^K$ctjY$WiecGa>i zG&Fr~PbUL^6k|*vssNc(0%waJAnMnhLv_EJ+795F2%nV%B~a%-I)yd_TgO{_5(JJ; z3f`mu^Iy*LV=Iz_0)HmL4iuoJZ!jL8jRcm@ugU)2kozqJ+gk{_Sw(QV)CI75K&Jw{ zt?*v9*xjy#lobI+71*)P zl^Xa+$8h$;r4OtIQSe71`#Tj|q1CgKrQOW;mlg%64MrT4U*9VwK*_J|4$6)WRKVKX z;618A3FP{$z;-YKz1i}g)ctq$8s*=r1N>5gFCsaKOf4=T0b{cQzB@gDwMz)LlxyiC zqJO|_l#cO7PwxPDFUPlJUuRSrbPYZNza?p4ME*-u0dzKyPXAa^tj&r9TRCqbn;I;i zRm4yUBKr!zCK*aYg>Mpjbk(!^C$Rb_!}>7=#OZmZ)dk>}(Ign9-n}xiFR)bd;$B|v zsfV2~SR8OqGL(iCPn_Dm9#@$`+g=F1K3V>c>jGi~IPD{tNbsVS0J~6GE#;B{j%6k6 zeT*ZDyxeckYGie{cMCU|)Ny ze{in++ef$`loCwp|G=SREGZ|O*RLY?UY@Uk+Ci$PfoG=%e`omrQTW`8v+qzP08s&q z2ehT{CDtm|l1IGasrS;$B+g(YxMiwX8U}MpU?7cE_mBWT8{i`e4o2bU%=f3p7{L1S z6A8|Q1Zp|x^Kn&?-YxT})ZhqN#w79m2ro?=OR$z-o4$Q8BK{o|dA3MUKZ8Q-NbzSB zdxbVV!U{l0pjF`Lq-3>vxD_FzoUMQaR=pv*XTc=|s4dk(QsV@ggHhjqGUOj)fvr>g zp#>k$`deK9iwCA)kj0iQ7vYOaabCOL8GB7g&`E5ox^#gOM4DoG>gCO!*b(WsQoir- znOz|AuY%u90H;7CDkz-q_kld$lS{otI&PX=+aE7Nf>r{QK%j?p{gLGQ)~FuK`?nB0vuQ1sewlVPwsId>AXQQ+a=Q?0c)4uN&;_fKKguX-lSFO!@(U5GAs9b z13sf8{gQ4G0|bM@ngv;bACdv*xy|zn^?td7Gy2FjO-N3FXbm^B=V$6Q%F8Kp5$R_H zz<6M<-k&oDYp`b`F1DmwE5Hp%P>2eQWKd+jZcgV8h=6aT)-6#;@Iu=?7tP9kir8@d2J>D1dV*UJvFQ=YC7APPQPu(1OY z>>;4r5_LEb@V({tP2gWmfC>q`R)O9Apj<^7vjM@cA&`N;G0pDA>!)Env z2`MnL*T5fCV2SEktbv|aBLJuY&L7Y}Xcl`GtTjfC1kj+b2>7^-Y7Q2PuvE;{s+R9# z95c%KEFGM=!)Ef-R{2hsMErLrfO>#Zeni<)<6@>!Oe$QW5l8x3HPJ7Vu}2I@6W2oZfUQb$JGnZGgyj#?FqFTNbZ3QtX9qrzXZElIW-( z8_+tOK9A$`tkc>Aic*vNn*jeV2v8x%Pg0*~iX>qHUoU)Sa)!(#1q(r5*DkFHMeH6u zqr^7cDEF}X4?zGzh~FlW|2TjC7bDtl84pOtAP^&f4q&YSaWZ6mG{D9yKFdwP|4;9yXpX7WBwKo!Im5G_lu-dr04K&l8x}_{zzH*}cRbrbkc@tT^?OP_P@2qw= zt6vCk9XWnq0n+p17|BnD%eg!73juCNh~LO%`zM;4ZKhXjjEX>4Tx04R}tkv&MmKpe$iTeYGUK|6>#WT;LS#4jABibb$c+6t{Ym|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfbaGO3krMxx6k5c1aNLh~_a1le0B^0t6r*h%P*hV- zL?c2vvnu#s(TxuDVF=SAGqhN8F$LH0bq^0;@4`IG{oJ3UN6s1y@Cd|nOw&!`4dR(i zQ{%i(9ApJiCO#(~)9Hf5k6f1=e&d|C*~>G7dMYtb93&RLejeT)G9U7%jItnXvXs-FP9XW&Y0`pY$7_LKB# zQwtpdz1zUWbyJh}fXf|V;7Jp8(UyEPy}2Clen#Jv0s3!&t~IB(#y(CTfE0DLd;=UD z0;74#UUzwSXKQc&o@w;=1Fm0kznma|)Bpeg24YJ`L;(K){{a7>y{D4^000SaNLh0L z01FcU01FcV0GgZ_00007bV*G`2j&X~6bTvd^d#2+006H^L_t(I%cWDn4Z|P|yhAKe zq_RVqCEc>K&>g5m$8aBoCA8?K8(2;38NzxBEl1gq$Lr58e6q^Cke8S@D)+ zk6L53#I7TWETYD2FKUp?zuGL)oE!aR*j{}pOF={6d;m&!kSoy)W*Dg*pX?=W9@R|g z7o5LABctL~mPi+~s^=5!&IjZaky8Z8eh!=utBsm7dwcEC(N#$`8?|C}I*)#)5$b2U Zj2~`xL>TOO;&K20002ovPDHLkV1i@gB{2X1 literal 0 HcmV?d00001 diff --git a/loaded/mystery.png b/loaded/mystery.png new file mode 100644 index 0000000000000000000000000000000000000000..161413256a36c46921fd8d6782d5842918396561 GIT binary patch literal 592 zcmV-W0EX>4Tx04R}tkv&MmKpe$iTeYGUK|6>#WT;LS#4jABibb$c+6t{Ym|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfbaGO3krMxx6k5c1aNLh~_a1le0B^0t6r*h%P*hV- zL?c2vvnu#s(TxuDVF=SAGqhN8F$LH0bq^0;@4`IG{oJ3UN6s1y@Cd|nOw&!`4dR(i zQ{%i(9ApJiCO#(~)9Hf5k6f1=e&d|C*~>G7dMYtb93&RLejeT)G9U7%jItnXvXs-FP9XW&Y0`pY$7_LKB# zQwtpdz1zUWbyJh}fXf|V;7Jp8(UyEPy}2Clen#Jv0s3!&t~IB(#y(CTfE0DLd;=UD z0;74#UUzwSXKQc&o@w;=1Fm0kznma|)Bpeg24YJ`L;(K){{a7>y{D4^000SaNLh0L z01FcU01FcV0GgZ_00007bV*G`2j&X~6cQzNt&_?C002x$L_t(I%gs^C3IH$&vgrSR zxn0LtBE?`H1I-68gx!t_Bq3NSz=)NIcWm#ELj6>^3zknoC^i|qIbFZRGiG#1;|PDj elo_9PFcw(fbPOcxCvO1&0000 VISION_RADIUS) continue; - star.x += hash11(star.x * 100.0f + star.y * 67.0f)*gap; - star.y += hash11(star.y * 93.0f + star.x * 53.0f)*gap; + star.x += hash11(star.x * 100.0f + star.y * 67.0f) * gap; + star.y += hash11(star.y * 93.0f + star.x * 53.0f) * gap; sgp_draw_point(star.x, star.y); } } @@ -706,8 +739,8 @@ frame(void) { if (b->type == BoxThruster) { - dbg_rect(box_pos(b)); - dbg_line(box_pos(b), V2add(box_pos(b), V2scale(thruster_force(b), -1.0f))); + dbg_rect(entity_pos(b)); + dbg_line(entity_pos(b), V2add(entity_pos(b), V2scale(thruster_force(b), -1.0f))); } } #endif @@ -715,14 +748,14 @@ frame(void) float cur_alpha = sgp_get_color().a; Color from = WHITE; Color to = colhex(255, 0, 0); - Color result = Collerp(from, to, b->energy_used/BATTERY_CAPACITY); + Color result = Collerp(from, to, b->energy_used / BATTERY_CAPACITY); sgp_set_color(result.r, result.g, result.b, cur_alpha); } transform_scope { sgp_rotate_at(entity_rotation(g) + rotangle(b->compass_rotation), - box_pos(b).x, - box_pos(b).y); + entity_pos(b).x, + entity_pos(b).y); if (b->box_type == BoxThruster) { transform_scope @@ -735,8 +768,8 @@ frame(void) // float scaling = 1.1; // sgp_translate(-(scaling*BOX_SIZE - BOX_SIZE), 0.0); // sgp_scale(scaling, 1.0); - sgp_scale_at(scaling, 1.0f, box_pos(b).x, box_pos(b).y); - draw_texture_centered(box_pos(b), BOX_SIZE); + sgp_scale_at(scaling, 1.0f, entity_pos(b).x, entity_pos(b).y); + draw_texture_centered(entity_pos(b), BOX_SIZE); sgp_reset_image(0); } } @@ -752,19 +785,19 @@ frame(void) img = image_medbay_used; } sgp_set_image(0, img); - draw_texture_centered(box_pos(b), BOX_SIZE); + draw_texture_centered(entity_pos(b), BOX_SIZE); sgp_reset_image(0); if (b->box_type == BoxSolarPanel) { Color to_set = colhexcode(0xeb9834); - to_set.a = b->sun_amount*0.5f; + to_set.a = b->sun_amount * 0.5f; set_color(to_set); - draw_color_rect_centered(box_pos(b), BOX_SIZE); + draw_color_rect_centered(entity_pos(b), BOX_SIZE); } sgp_set_color(0.5f, 0.1f, 0.1f, b->damage); - draw_color_rect_centered(box_pos(b), BOX_SIZE); + draw_color_rect_centered(entity_pos(b), BOX_SIZE); } } @@ -784,7 +817,15 @@ frame(void) sgp_reset_image(0); } } + if (e->is_explosion) + { + sgp_set_image(0, image_explosion); + sgp_set_color(1.0f, 1.0f, 1.0f, 1.0f - (e->explosion_progresss / EXPLOSION_TIME)); + draw_texture_centered(e->explosion_pos, EXPLOSION_RADIUS*2.0f); + sgp_reset_image(0); + } } + // gold target set_color(GOLD); sgp_draw_filled_rect(gs.goldpos.x, gs.goldpos.y, 0.1f, 0.1f); @@ -807,7 +848,7 @@ frame(void) dbg_drawall(); } // world space transform end - } +} // UI drawn in screen space ui(true, dt, width, height); @@ -843,7 +884,7 @@ void event(const sapp_event* e) int key_num = e->key_code - SAPP_KEYCODE_0; int target_box = key_num - 1; if (target_box < BoxLast) { - cur_editing_boxtype = target_box; + attempt_to_build(target_box); } if (!mouse_frozen) { diff --git a/server.c b/server.c index e58b6fe..c6193ea 100644 --- a/server.c +++ b/server.c @@ -21,6 +21,11 @@ void server(void* data) initialize(&gs, entity_data, entities_size); Log("Allocated %zu bytes for entities\n", entities_size); + // unlock the explosive + if (true) + { + } + // one box policy if (false) { @@ -122,6 +127,9 @@ void server(void* data) event.peer->data = (void*)player_slot; gs.players[player_slot] = (struct Player){ 0 }; gs.players[player_slot].connected = true; +#ifdef UNLOCK_ALL + gs.players[player_slot].unlocked_bombs = true; +#endif } break; diff --git a/types.h b/types.h index f759206..3e8489e 100644 --- a/types.h +++ b/types.h @@ -6,13 +6,12 @@ #define PLAYER_SIZE ((V2){.x = BOX_SIZE, .y = BOX_SIZE}) #define PLAYER_MASS 0.5f #define PLAYER_JETPACK_FORCE 2.0f -//#define PLAYER_JETPACK_SPICE_PER_SECOND 0.3f -#define PLAYER_JETPACK_SPICE_PER_SECOND 0.0f +#define PLAYER_JETPACK_SPICE_PER_SECOND 0.3f #define MAX_HAND_REACH 1.0f #define GOLD_COLLECT_RADIUS 0.3f #define BUILD_BOX_SNAP_DIST_TO_SHIP 0.2f #define BOX_MASS 1.0f -#define COLLISION_DAMAGE_SCALING 0.1f +#define COLLISION_DAMAGE_SCALING 0.15f #define THRUSTER_FORCE 4.0f #define THRUSTER_ENERGY_USED_PER_SECOND 0.05f #define VISION_RADIUS 16.0f @@ -25,6 +24,11 @@ #define DAMAGE_TO_PLAYER_PER_BLOCK 0.1f #define BATTERY_CAPACITY DAMAGE_TO_PLAYER_PER_BLOCK #define PLAYER_ENERGY_RECHARGE_PER_SECOND 0.1f +#define EXPLOSION_TIME 0.5f +#define EXPLOSION_PUSH_STRENGTH 5.0f +#define EXPLOSION_DAMAGE_PER_SEC 10.0f +#define EXPLOSION_RADIUS 1.0f +#define EXPLOSION_DAMAGE_THRESHOLD 0.2f // how much damage until it explodes #define TIMESTEP (1.0f / 60.0f) // not required to simulate at this, but this defines what tick the game is on #define TIME_BETWEEN_INPUT_PACKETS (1.0f / 20.0f) @@ -86,6 +90,7 @@ enum BoxType BoxCockpit, BoxMedbay, BoxSolarPanel, + BoxExplosive, BoxLast, }; @@ -150,6 +155,12 @@ typedef struct Entity EntityID currently_inside_of_box; float goldness; // how much the player is a winner + // explosion + bool is_explosion; + V2 explosion_pos; + V2 explosion_vel; + float explosion_progresss; // in seconds + // grids bool is_grid; float total_energy_capacity; @@ -171,6 +182,7 @@ typedef struct Entity typedef struct Player { bool connected; + bool unlocked_bombs; EntityID entity; InputFrame input; } Player; @@ -269,7 +281,6 @@ V2 grid_world_to_local(Entity* grid, V2 world); V2 grid_snapped_box_pos(Entity* grid, V2 world); // returns the snapped pos in world coords float entity_angular_velocity(Entity* grid); V2 entity_shape_pos(Entity* box); -V2 box_pos(Entity* box); // returns in world coords float box_rotation(Entity* box); // thruster