From 7a708c28f9980d8fe0aea156f0f29579605b43e4 Mon Sep 17 00:00:00 2001 From: KikooDX Date: Sat, 18 Dec 2021 17:20:00 +0100 Subject: [PATCH] gravity is out of their mind Implements: https://todo.sr.ht/~kikoodx/jtmm2/6 --- CMakeLists.txt | 1 + inc/conf.h | 1 + inc/player.h | 2 +- inc/tile.h | 4 +++ res/shake.kble | Bin 0 -> 356 bytes res/tileset.png | Bin 7169 -> 8578 bytes src/level.c | 10 +++---- src/player.c | 68 ++++++++++++++++++++++++++++++++++++++++-------- 8 files changed, 68 insertions(+), 18 deletions(-) create mode 100644 res/shake.kble diff --git a/CMakeLists.txt b/CMakeLists.txt index d268d6e..d4caf97 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ set(ASSETS res/burn.kble res/bounce.kble res/worm.kble + res/shake.kble res/fonts/dina.png ) diff --git a/inc/conf.h b/inc/conf.h index efec6c8..f11e2b7 100644 --- a/inc/conf.h +++ b/inc/conf.h @@ -18,3 +18,4 @@ #define BURN_DEATH 3 #define BOUNCE_SPEED -2.0f #define DRAW_OFF_X -2 +#define GRAVS_MARGIN 0 diff --git a/inc/player.h b/inc/player.h index d14a4b7..1cd8de2 100644 --- a/inc/player.h +++ b/inc/player.h @@ -4,7 +4,7 @@ enum AirState { AS_NEUTRAL, AS_RISING, AS_BREAKING }; struct Player { - struct Vec pos; + struct Vec pos, gravity; struct VecF spd, rem; enum AirState air_state; int jump_buffer, jump_grace, burn, bouncing; diff --git a/inc/tile.h b/inc/tile.h index 30d23fc..74862a6 100644 --- a/inc/tile.h +++ b/inc/tile.h @@ -9,5 +9,9 @@ enum Tile { TILE_EXIT, TILE_BURN, TILE_BOUNCER, + TILE_GRAV_D, + TILE_GRAV_U, + TILE_GRAV_R, + TILE_GRAV_L, TILE_OOB, }; diff --git a/res/shake.kble b/res/shake.kble new file mode 100644 index 0000000000000000000000000000000000000000..2c4c2ebb9a1ade9842960177e79b88d213d5176b GIT binary patch literal 356 zcmZ{g+YZ1W2t$i(BucXP{r`^+yc=gmCD4P0ZLp zbj~6M?#YT6og5Qx-EUaUF9^YaPKjVP_Hs+8YOfMEvKVmH#AT!8>QbNC@eAn#3@HJO literal 0 HcmV?d00001 diff --git a/res/tileset.png b/res/tileset.png index c7337ebdd353adfdebf3f7464cc4b1e4399d1db0..4e32e11a39acd5a4ba4f23f7b7d2935845bcc68b 100644 GIT binary patch delta 5109 zcmV$^<(dQPVIev zfA;4QfB$g*Dc>FxZdE?(*Po+*#(%q?zfbV>VO+_dCK{h5^7`??Y@hkZPZNC>su58{ zaXu5x&qTF+J;}y-8&!KN>-UMbs_)$2C;9pBreyC3H)|@648xN+b;+GfXer)pU^6w6g)qp z)yii`{VB=)`{yt3KUsc_%A5K>t=z`vs{DAL@%9zbPuY*(d(XJ;uiro|e^4tgQZZ1! zqsCp;Z&T!;6A8=!tUN7)xCR6ibP3GT$gPz?E-*{8&=pb$QUbG+12GV6o{QZ44ZEj* zd?6ah{a?5}+J3;T{IAG80o`vR_gCD0h1#)KPV0+MbYUblRl4t%%$hRp29YM6<UUQ+64R-TA#Kl~M8u$x9-SARzim8spo!AiNKSrhyNfZsfdTZ|y|t>NoV!8CvzUTu zrC=x%-*qLsEU~hP$SPmB1~nOhD=?HapaRO6Gmw_?~6WXZ4(^uS|kgb}9gT?mDN@k$aKOvn`zA zrcUnhJiM6q3H_eyi(Om5KOx~Y$XR3m&>eA7H_|7Q2%U{<@!iPt?uF(z`U>teYKwNf6sXA`4{(GcV@#lO3)hZLo;Gno1ZG?@2jVXoyax`L1Vr zVl}4HrRM>TGyRY?dbql1P`z4jV-L#GTGTrg4$YCvxMIE=_Bb0GP@K>u9r$d}qgVar zL4VM+qwEx}$cNNo)Y7Q6kPe5za)T7F!e`**ND2E6gW`qCJ_f;mGX@T4x&m_p{LZm` z@2ox=B)A%tjkkwxmS_E=Y0jLgcey;wmzxrkD*VYmm>JHEAy5X5jb4R8Q)Ne%jDnO7 zRs8WNMOP8gjYH7;T)pQ>)GHPfXu5lO8Gzt~^k8CiZ#pCe%F&n|9=>g{z4ipsjz_6s z`jZRVM9XNN~Ex}o|}Xou(Rz!VOh%oBtK zOWv^yGJ#26NK@^GNL?6nhQ^CxQ4#;?Kg?+OHQ+G6fKt10h?zNqDU;~=dB@aXX zn^*3n2R*s?Z)|?2N8u0{wA!H>^O#iEgp_D`RIishGdLI>e)tL$BB2$|)U`eIqfEN0 zMAo22gBZ|{v|7ScWtcap4V{M(j6kHdqm(L6bRs1P>gI&d^*M`Xw|R4cusmvN2zf^J zf|&43RL@y|+RH|YHdPJlP^ERi_>^p@+a?E-WKW2nuhF&)!6DEo8kC>Tneba^5Y=9$ z6v8_i-!#X9!JC~%CU2cb&lc#E!)Av8TBhxY#}>vpFE+Uq6>EVN8HZqmBBqS=*c7Zu z*oFlMo1pz|Q;igNCQKDP^o5%Z-4WOI$j^`OR4eK?qlL793pDL`iz5?kBS)nAPjT)a?31lji6tD1wPfd3Ceo ziLk9TNQSnkQp)q}P!Wz-R18DOkD&W(5dyL2-~l1?g(IYN8m4QF#dh!%868czz7 z?uogem`LNwv}f6EQ-%UQsAfo3pom4ju=H@1g(r{a>|fYF?-y(={Xto zxL>RUQM~+2L^(c5q&T`s2FJj8VRYBVFbSG}h=W#44>GWiEl@*gpsmC%JzSk7l7j7o zG8WC{8)wUnivX8J5Rh3X-q}!pLsL;ecI>A=;ZdUnGft0vAixn|7+Xk@(nUXoC$tx& zM}0z|2Fq6211|(3WOfhR52YWRgB3+LLeUsbAxasIt}#fop#TfJ2Y;amB8V(Ms9&olstVk~>3g{X3BpB>HHlp5Q%28{hYqccu4 zg&5)hoW?vH=$f2la$$vgDj7~%;X5d~ zTC`eC7pm?0p0J!g$KI6quT!hhb_g*iAv^|siXDbMBPFk~DmEle>Cgo(ho-IPtmhiX zcPbw0igh^$?9W~cA{B?9k^au-^PdL5qMQqX_TPRnHhU7>An*Mwq zct4|W$^w12K=+#4TXP?$4?vo_O5OkmhrmdIve!M{-PPXPzh|2L{Q#vaa=St-mv8_8 z4gG0USaeuTOggh^3W5S8F=J#hHDqRGEnzh=W-T;iGBqt?W-w$eIW##nGC472WMW}8 zlMfB43N$k{GB+|dGBh)@!VO&klROSwBxN)>VPrHjF)d~{H)Sm}Vl!baIbk?BEjKtd zHe_ZvGch(eWRtuOP6szSFf}?dH?t8BZU`2W&!j>C000JJOGiWi{{a60|De66larMf zA%74B8(xXbT>twxZM;do*7bt$i%Wl8arwT-hp?w4{zV@ zLWCVnRd<`v?d~-Eo3F+@jsNLK!hM>ye}CI){I~h{JB`11@&oqStj7cqZ3CTchCQrp z;`{NhdG7(V~SY3H!@KvTGC91jMA zqA0Q~8;wSDJMFUztdN#Z!3&1Q7~T06>pkq#kFZLYtDX;w+=G3+1Q|`-ZuX1>@3g^fH;n`EIT_p`_O6pK7Xp_d(~18 zwf#KLN28G^Apk{Dj7FmxI_Y-1fqnw7bhoJ7s_JYu3nA>bVb7jDyEBB*t|IyoR-#wq z&W$2^Q$cSJoex}zPSf=1)2D;M0KoI-&tJTFQ3IgKWO96bytd!huV0^>oZL8mI-PnI z{69ss*X)NQqSx}NRfzkKcYkK`k7t{Co{z`l>2&HPQN4FPk!)X{m`X>PnX5q&Vt z)Z4li4OZ?KKnK%IZQ$}S0J>NAe0Oy8XIU!nWxHJfzt87$5%G;rK!28O5z?h!fBqV( z0Iao9)B$l>UPV!-ET>gfLABLR47U`zSiFtnPwyR$^Ursi@T39Id$m92^N1P1FGV3D ztHnAGqt#T1yp#c2QM=XpWIlgWRto}Ehf$7EeOVOw5bL?A@&Z zHmr(Plti}ExbV;c8VHzK&c(%p67Ss#*{+2+p}yEAAYfG%h^w z5Qb&LO93V_M3#tv!Z})sWhMeq#Qek<0*T0cJ`JIYh`gMxss#WM$83x-G9 zL}Zvtk%@EHmBW>kN`ZxQKL27O!;EFeOhlQ;Q;`=?))-%(7LmxdMVdn5p=+SelB8{n z|C!hr%Y4l)M3y-=#)q)j+K8EexN|Hb&IweRStXT<&s&)1Iq#31=<^GH$okdopZ;z{Zx_~)l#WEXI404@0r6i9GPsfM zqcV|6To>to9G|K23COSF^!{`_GIurqa?%%6-dEqydPRb*eM2j!*A)2{-1=)e9=@Yh9D?iajQfu$beHBU(K7dBuf`Ih~My8W$-o5cENnmU>#^_+|e_OAQRS zC@3yq7e>?Dmv}GRuNCgql$Cd6YKjS{|@Ut^~&8~xaIx2?PHapHkWC!cca zX-7{#!=Rc;ux!PuHB;+0-l)A`{ptG$sKpm*=|;*Ywl`{ww)SBnx||fp48T&z5yYEA z0HKp(c4^ExIdYEK)e~7!5>6J!Y)3~71oMfhSp2{)qz6$)?tj89wEP9P^tZ?bhwcx5 zk^339U!k_W46PfnCks8OmymtHyoKq;wdT=mMsvY}%w`(;w&S2`KArgzqFr?eES zY}K)dn@QVsvQ(PmdhB8PlfCd5WR1t-+n%%OA1&%7*gPu5jWYMd5GxNV4i?*p@PQ~c z)l%hDFxv=>B+XHmGQ}cOswIr&3L3Qxx+G&!Xteyl8@GSU(VCA?S9?E z1b zG(x&&*RUlW6CGmIJ%Vo_ksj~9_dUxnkKct80oAndcIbx2SMBHQ1DGIo|tf zXsQkmU$wnP$~uiPk~`KFy@agMAoQrdu1sAwX0SzD=)>8QF$9S1VQrOlqtP*hBPSUi zI`#Q8A7AB8mZp36vrG56A<~0?#dG^=Ry4EWen*|&Oh%nYduq@bWKzWkNb9$jWid z3Y#NNP0|WPTRQA(&xzD^utHijWeVb)-um4^zhjOEKcfB-^WTej4p%&l3?Oc0+oB@p z>O_EWg(xuQa){V5qEapdQsA2Y5IvQ%pbOsb65%8js^)!kt)^ZdcMbag zGUW1UqYJY1C?0}I#p<_CHMiR2lTN{>)X*t}hG2F&b=0AzG(tbw^ZpU4@%Od@#@@CF z+;nqy41dIuBIlQ|P^{(;8Du}MaK$_`lo*v;@DMJDu}AIOxvf!uMk{O2I^fYE8yftn z6WHlueAzl?U#YD_FVHTLuv!;m%`34Zf72U+6tSM#}_KTUDVHY`}oqev*hsHl1++0-A;32h(BkUw?2{?;u%gZ z)kgaPeqFVYiL6#v&TaCx*U7s>O7n(ST8K6jFlm8Lyf%57dV`mHSHnPpU&PoPdLhX= zZ{m@1%!|g_rzS7Gv{D3vTBHw?0o^MaN|#X=GQW ze0Xp2Dub};YHhHSO=cUl|W{!)S44T0FLdl8R;45-NxM)Oi%g?86CC79R|84 zXOdp9nLJXZV=~Jd`32vtjcW30Dr9J-BRcGH8TA*D-D^_)));{e2p!vCS2QcxLqk)0 z>ZHXSd*r=;8p4IX?0t&+M>lm&Nuz1KyyW$`=u<3s5|qn}C&hruzIa=B70>i^8bY0M zk*8NPVjo+fxNQ&vwuBYoJ+H+;C8S);n~VEATvYQK3KvP``_b*-NpddsN!pNC%exP6 zm7!K`I|j1sYOy2SLl)jQ^mSu@XG;9KM?>-dVmxiiyIooI0d;EK z3%SNkB1a=EbgNyw<>lBHoe2fpDK>qDPjeM;I_euTW3!0<6|?waSp#b@rjPJC&Sw!la`>8 z{i9S}@?>3s(wX21y?!T!`T+XOrpm1i&5fLkcw=3VR9 z^S}xl)K(glehxvqHp z#yRJ*z%xT;GBHmaA{KK^tTZvpn;P*Xaah%K$`?`|tDLtuYsE6F-;=*En9*03xlVHs zF)U&U5=1B{qktl8L}=AXv5=tsXbb;<>zBx-kgEVjjs=vUL3aJ%fAG6oD}OsN?j;4I zK>Lg1d<+4BU7%KRobO}Dsht4+XW&Y2_)Aq_`jhlZLkk}PJ=?&=bwgA3fXf}A|H+U| z*_He>g=`jhKcjC-1AVtZ*P7Q`eIKU}K$5zO-v9@Pz;KST*IT^1qq(<#&(!<-0ny!Z z&0%e1nE(I{8fjEmbXZMHI2{nI5snr+7GD;GBGtaI5jpgI5o445M2SY%@SY;7C-KtR{#J224YJ`L;wH)0002_ zL%V;ILmMG~2|FB;-`act00b;aL_t(&-tAdSvKvJZ%&hJiNzaDBuy=3)I0PJnEemeL z8Q2iqg<#Kug~KZrc7zH1EX{ORC5x5@@t&%#E~ZHxF0-! ze$?{szIl1n`k#LyPHCF`e$@K!U;TL0`rLd<@(|a5AF}LW?LI!ve9!stEnbTE@9guv z7thD+5N+CuGXns+LmrN(3Y$A%KjCmOTJcN@gh(WgMnzL5XBPyB6WS{qrO- zx5hQa-GN2UqkBj-qKykAP0(&hU}iKM$JM`o1z0i(eYfcH%{2h~2N*30Cfdn=q)U*N zwKj*guhS1`Bxq)kq^QNWTU;}X2m+-pBg&-*z)t;udCmelv&Jft8tO^fM&wN1H#0MX z5DJe_G{)lO{=S<5GBV{Hp;F5=1NPY9Zsh1bjc6LQn=bP0Hz8}v63AJ%7{?{e6wz** zSx#N8Bh7?x_r9O!?pgy5u-M3dd?OQ?NdilEZi=muAUm^9QX&`;!|-mR8j`IX*E#}- zaI=(BD&wk@)inV7Yd{0|P0mluZX>2fOdBG~W&{TJSMI)<7YQ)qIw=GwT7#BSlH|3J zG_z{}4(P?mWL6?xyRSR1ElDF_bZ`2{$Yh4i#3({Wwp3^ZB&XE+5MmL$w<|#D_n&;e^5t!dRiwO6CWM%?F(X?snheI9_?M2tKFTT3; a0Q>{cHP+af$21cF0000pos.x = pos.x * TILE_SIZE + (TILE_SIZE - PLAYER_WIDTH) / 2; p->pos.y = pos.y * TILE_SIZE + TILE_SIZE - PLAYER_HEIGHT; + p->gravity.x = 0; + p->gravity.y = 1; reset_speed(p, 1, 1); p->air_state = AS_NEUTRAL; p->jump_buffer = 0; @@ -29,7 +31,8 @@ player_spawn(struct Player *p) void player_update(struct Player *p) { - const int on_ground = collide_solid(p->pos.x, p->pos.y + 1); + const int on_ground = + collide_solid(p->pos.x + p->gravity.x, p->pos.y + p->gravity.y); const int k_left = input_down(K_LEFT); const int k_right = input_down(K_RIGHT); // const int k_up = input_down(K_UP); @@ -38,18 +41,27 @@ player_update(struct Player *p) const int kp_jump = input_pressed(K_JUMP); const int kp_polarity = input_pressed(K_POLARITY); const int dir_x = k_right - k_left; + const struct Vec rem_gravity = p->gravity; + float spd_x, spd_y; + + /* speed transformation */ + spd_x = p->spd.x; + spd_y = p->spd.y * p->gravity.y; + if (p->gravity.x) { + spd_x = p->spd.y; + spd_y = p->spd.x * p->gravity.x; + } /* polarity swap */ if (kp_polarity) polarity_invert(); /* horizontal friction & acceleration */ - p->spd.x *= on_ground ? (1 - GROUND_FRICTION) : (1 - AIR_FRICTION); - p->spd.x += - dir_x * (on_ground ? GROUND_ACCELERATION : AIR_ACCELERATION); + spd_x *= on_ground ? (1 - GROUND_FRICTION) : (1 - AIR_FRICTION); + spd_x += dir_x * (on_ground ? GROUND_ACCELERATION : AIR_ACCELERATION); /* air resistance & gravity */ - p->spd.y *= (1 - AIR_RESISTANCE); - p->spd.y += + spd_y *= (1 - AIR_RESISTANCE); + spd_y += (p->air_state == AS_BREAKING) ? (GRAVITY * JUMP_BREAK) : (GRAVITY); /* air state machine */ @@ -59,7 +71,7 @@ player_update(struct Player *p) if (!k_jump) p->air_state = AS_BREAKING; /* fallthrough */ case AS_BREAKING: - if (p->spd.y > 0) p->air_state = AS_NEUTRAL; + if (spd_y > 0) p->air_state = AS_NEUTRAL; break; case AS_NEUTRAL: default: @@ -78,7 +90,7 @@ player_update(struct Player *p) p->jump_grace--; /* jump */ if (p->jump_grace && p->jump_buffer && k_jump) { - p->spd.y = JUMP_SPEED; + spd_y = JUMP_SPEED; p->air_state = AS_RISING; p->jump_buffer = 0; p->jump_grace = 0; @@ -87,7 +99,7 @@ player_update(struct Player *p) /* bounce */ if (collide(p->pos.x, p->pos.y, TILE_BOUNCER)) { if (!p->bouncing) { - p->spd.y = -absf(p->spd.y) + BOUNCE_SPEED; + spd_y = -absf(spd_y) + BOUNCE_SPEED; p->bouncing = 1; } } else { @@ -96,15 +108,49 @@ player_update(struct Player *p) /* burn and death */ if (collide(p->pos.x, p->pos.y, TILE_BURN)) { - if (++p->burn >= BURN_DEATH) level_reload(); + if (++p->burn >= BURN_DEATH) { + level_reload(); + return; + } } else if (p->burn) { p->burn--; } /* next level */ - if (collide(p->pos.x, p->pos.y, TILE_EXIT)) level_next(); + if (collide(p->pos.x, p->pos.y, TILE_EXIT)) { + level_next(); + return; + } + + /* speed transformation */ + if (rem_gravity.y) { + p->spd.x = spd_x; + p->spd.y = spd_y * p->gravity.y; + } + if (rem_gravity.x) { + p->spd.y = spd_x; + p->spd.x = spd_y * p->gravity.x; + } player_move(p, update_rem(p)); + + /* gravity modifiers */ + if (collide_margin(p->pos.x, p->pos.y, TILE_GRAV_D, GRAVS_MARGIN)) { + p->gravity.x = 0; + p->gravity.y = 1; + } + if (collide_margin(p->pos.x, p->pos.y, TILE_GRAV_U, GRAVS_MARGIN)) { + p->gravity.x = 0; + p->gravity.y = -1; + } + if (collide_margin(p->pos.x, p->pos.y, TILE_GRAV_R, GRAVS_MARGIN)) { + p->gravity.x = 1; + p->gravity.y = 0; + } + if (collide_margin(p->pos.x, p->pos.y, TILE_GRAV_L, GRAVS_MARGIN)) { + p->gravity.x = -1; + p->gravity.y = 0; + } } void