doublejointed.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  1. /*******************************************************************************************
  2. *
  3. * Double Jointed - Double Dragon parody. - beat 'em up game
  4. *
  5. * *Added zorder drawing function (needs more testing..) other sprite drawing functions can be removed
  6. * // debugging phase sill in progress above...
  7. * Added oneshot and loop anims to entities.. fixed damage anims.
  8. *
  9. *
  10. *
  11. ********************************************************************************************/
  12. #include "raylib.h"
  13. #include "math.h"
  14. #define MAX_FRAME_SPEED 15
  15. #define MIN_FRAME_SPEED 1
  16. #define stateFlee 1
  17. #define stateAttack 2
  18. #define stateChase 3
  19. #define stateIdle 4
  20. #define stateSawplayer 5
  21. #define stateDead 6
  22. #define statemoveto 7 // for scattering if they are clumped up together.
  23. #define animIdle 0
  24. #define animKick 1
  25. #define animHit1 2
  26. #define animUcut 3
  27. #define animHit2 4
  28. #define animWalk 5
  29. #define animDamage 6
  30. #define animFlying 7
  31. #define animNothing 8
  32. #define MAX_SPRITES 1000
  33. #define MAX_PLAYERS 1
  34. #define MAX_ENTITIES 3
  35. #define MAX_ITEMS 3
  36. typedef struct item{
  37. bool active;
  38. float facing;
  39. bool blinking;
  40. int blinkingtime;
  41. int blinkingcnt;
  42. bool visible; // sprite is drawn or not drawn.
  43. Vector2 position;
  44. int currentFrame;
  45. Rectangle frameRec;
  46. float angle;
  47. float incx;
  48. float incy;
  49. float shadey;
  50. }item;
  51. static struct item it[MAX_ITEMS];
  52. typedef struct entity{
  53. bool active;
  54. float facing; //-1 left, 1 right
  55. Vector2 position;
  56. int w;
  57. int h;
  58. float health;
  59. bool blinking;
  60. int blinkingtime;
  61. int blinkingcnt;
  62. bool visible; // sprite is drawn or not drawn.
  63. bool flying; // for when nocked flying
  64. float flyingincx;
  65. float flyingincy;
  66. Vector2 target;
  67. int state;
  68. float shadey;//shadow coordinate for when physics. bottom of sprites last/start position
  69. int frameSpeed;
  70. int damagedelay;
  71. int currentFrame;
  72. int currentAnim; // which animation is currenty active
  73. bool animLoop;
  74. bool animOneshot;
  75. int lastAnim;
  76. int framesCounter;
  77. int frame_start;
  78. int frame_end;
  79. int lastFiretime;
  80. int lastFireAnim;
  81. Rectangle frameRec;
  82. int mod; //collumn of sprites (+5 = enemy1 +9 = enemy headless)
  83. }entity;
  84. static struct entity e[MAX_ENTITIES];
  85. typedef struct player{
  86. bool active;
  87. float facing; //-1 left, 1 right
  88. Vector2 position;
  89. int w;
  90. int h;
  91. int enemyweareatattacking;
  92. int enemyattheright; // only 1 enemy at every side (integer of entity number)
  93. int enemyattheleft;
  94. int hitcombo;
  95. int score;
  96. int health;
  97. int currentFrame;
  98. int currentAnim; // which animation is currenty active
  99. int lastAnim;
  100. int framesCounter;
  101. int frame_start;
  102. int frame_end;
  103. int keynothingtime; // when key is down this is zero (used to disable animations..)
  104. int lastFiretime;
  105. int lastFireAnim;
  106. }player;
  107. static struct player p[MAX_PLAYERS];
  108. // controls for player (true/false) ,,add function to read keyboard/joypad/touchscreen
  109. bool LEFT;
  110. bool RIGHT;
  111. bool UP;
  112. bool DOWN;
  113. bool FIRE1;
  114. bool FIRE2;
  115. // currentframe hold the current position of the cells (typewriter style)
  116. int currentFrame;
  117. int framesSpeed = 8; // Number of spritesheet frames shown by second
  118. Rectangle frameRec = { 0.0f, 0.0f, (float)96, (float)96 };
  119. int frame_start = 0;
  120. int frame_end = 0;
  121. int frame_kickstart = 1;
  122. int frame_kickend = 3;
  123. int frame_hit1start = 16;
  124. int frame_hit1end = 18;
  125. int frame_ucutstart = 31;
  126. int frame_ucutend = 33;
  127. int frame_hit2start = 46;
  128. int frame_hit2end = 48;
  129. int frame_walkstart = 61;
  130. int frame_walkend = 62;
  131. int frame_damagestart = 76;
  132. int frame_damageend = 77;
  133. int frame_flyingstart = 91;
  134. int frame_flyingend = 93;
  135. int frame_idlestart = 1;
  136. int frame_idleend = 1;
  137. // this sets the frame to start and sets start and end position(loop)
  138. void updateplayer(int player);
  139. void setplayeranimation(int player, int anim);
  140. void playercontrols(int player);
  141. void setentityanimation(int entity, int anim);
  142. void updateentity(int entity);
  143. void entityattack(int entity);
  144. void updateitems();
  145. void drawZordered(); //Draw every sprite z sorted infront/back from the feet
  146. // Our rectsoverlap function. Returns true/false.
  147. static bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2);
  148. float distance(float x1,float y1,float x2,float y2);
  149. Texture2D scarfy;
  150. Texture2D backg;
  151. int debug;
  152. int main(void)
  153. {
  154. // Initialization
  155. //--------------------------------------------------------------------------------------
  156. const int screenWidth = 940;
  157. const int screenHeight = 720;
  158. InitWindow(screenWidth, screenHeight, "raylib [texture] example - texture rectangle");
  159. // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required)
  160. //Texture2D scarfy = LoadTexture("resources/mrskelly.png"); // Texture loading
  161. //Texture2D backg = LoadTexture("resources/onedragon.png");
  162. scarfy = LoadTexture("resources/mrskelly.png"); // Texture loading
  163. backg = LoadTexture("resources/onedragon.png");
  164. Vector2 position = { 350.0f, 480.0f };
  165. //Rectangle frameRec = { 0.0f, 0.0f, (float)96, (float)96 };
  166. //int currentFrame = frame_kickstart;
  167. int framesCounter = 0;
  168. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  169. //--------------------------------------------------------------------------------------
  170. //setanimation(animKick);
  171. //setanimation(animFlying);
  172. it[0].active=false;
  173. it[0].frameRec = (Rectangle){ 0.0f, 0.0f, (float)96, (float)96 };
  174. it[1].active=false;
  175. it[1].frameRec = (Rectangle){ 0.0f, 0.0f, (float)96, (float)96 };
  176. it[2].active=false;
  177. it[2].frameRec = (Rectangle){ 0.0f, 0.0f, (float)96, (float)96 };
  178. e[0].active=true;
  179. e[0].state = stateIdle;
  180. e[0].visible=true;
  181. e[0].frameSpeed = 8;
  182. e[0].health = 10;
  183. e[0].frameRec = (Rectangle){ 0.0f, 0.0f, (float)96, (float)96 };
  184. e[0].facing=1;
  185. e[0].position.y = 470;
  186. e[0].position.x = 320;
  187. e[0].mod = 5;
  188. setentityanimation(0,animIdle);
  189. e[1].active=true;
  190. e[1].state = stateIdle;
  191. e[1].visible=true;
  192. e[1].frameSpeed = 8;
  193. e[1].health = 10;
  194. e[1].frameRec = (Rectangle){ 0.0f, 0.0f, (float)96, (float)96 };
  195. e[1].facing=1;
  196. e[1].position.y = 270;
  197. e[1].position.x = 320;
  198. e[1].mod = 5;
  199. setentityanimation(1,animIdle);
  200. e[2].active=true;
  201. e[2].state = stateIdle;
  202. e[2].visible=true;
  203. e[2].frameSpeed = 8;
  204. e[2].health = 10;
  205. e[2].frameRec = (Rectangle){ 0.0f, 0.0f, (float)96, (float)96 };
  206. e[2].facing=1;
  207. e[2].position.y = 370;
  208. e[2].position.x = 220;
  209. e[2].mod = 5;
  210. setentityanimation(2,animIdle);
  211. p[0].active=true;
  212. p[0].enemyweareatattacking=-1;
  213. p[0].facing=1;
  214. p[0].position.y = 370;
  215. p[0].position.x = 320;
  216. p[0].enemyattheleft=-1;
  217. p[0].enemyattheright=-1;
  218. setplayeranimation(0,animIdle);
  219. //other sprites -
  220. int mod=0;
  221. // Main game loop
  222. while (!WindowShouldClose()) // Detect window close button or ESC key
  223. {
  224. /*
  225. // Update
  226. //----------------------------------------------------------------------------------
  227. */
  228. playercontrols(0);
  229. updateplayer(0);
  230. updateentity(0);
  231. updateentity(1);
  232. updateentity(2);
  233. entityattack(0);
  234. entityattack(1);
  235. entityattack(2);
  236. updateitems();
  237. //----------------------------------------------------------------------------------
  238. // Draw
  239. //----------------------------------------------------------------------------------
  240. BeginDrawing();
  241. ClearBackground(RAYWHITE);
  242. DrawTexture(backg, 0, 0, WHITE);
  243. //DrawTexture(scarfy, 15, 40, WHITE);
  244. drawZordered();
  245. //drawplayers(true);
  246. //drawentities(true);
  247. //drawitems();
  248. // spceial case if player is near enemy check if he is below than draw infront.
  249. //for(int i=0;i<MAX_ENTITIES;i++){
  250. //if(rectsoverlap(p[0].position.x,p[0].position.y,96,96,e[i].position.x,e[i].position.y,96,96)){
  251. // if(p[0].position.y>e[i].position.y){
  252. // drawplayers(false);
  253. // }
  254. //}
  255. //}
  256. DrawRectangle(0,2,screenWidth,23,WHITE);
  257. DrawText("Cursor LEFT/RIGHT/UP/DOWN Z(FIRE1)/X(FIRE2)", 0, 0, 30, BLACK);
  258. //DrawText(FormatText("hitcombo %i",p[0].hitcombo), 0, 20, 30, BLACK);
  259. //DrawText(FormatText("ca : %i",e[0].currentFrame), 0, 20, 30, BLACK);
  260. //DrawText(FormatText("ca : %i",e[1].currentFrame), 0, 50, 30, BLACK);
  261. //DrawText(FormatText("debug: %i",debug),210,20,30,BLACK);
  262. EndDrawing();
  263. //----------------------------------------------------------------------------------
  264. }
  265. // De-Initialization
  266. //--------------------------------------------------------------------------------------
  267. UnloadTexture(scarfy); // Texture unloading
  268. UnloadTexture(backg);
  269. CloseWindow(); // Close window and OpenGL context
  270. //--------------------------------------------------------------------------------------
  271. return 0;
  272. }
  273. void setentityanimation(int entity, int anim){
  274. //e[entity].lastAnim = anim;
  275. switch(anim){
  276. case animNothing:
  277. //e[entity].frame_start = frame_idlestart+e[entity].mod;
  278. //e[entity].frame_end = frame_idleend+e[entity].mod;
  279. //e[entity].currentFrame = frame_flyingend;
  280. break;
  281. case animIdle:
  282. e[entity].frame_start = frame_idlestart+e[entity].mod;
  283. e[entity].frame_end = frame_idleend+e[entity].mod;
  284. e[entity].currentFrame = e[entity].frame_start;
  285. e[entity].animLoop=true;
  286. e[entity].animOneshot=false;
  287. break;
  288. case animKick:
  289. e[entity].frame_start = frame_kickstart+e[entity].mod;
  290. e[entity].frame_end = frame_kickend+e[entity].mod;
  291. e[entity].currentFrame = e[entity].frame_start;
  292. e[entity].animLoop=false;
  293. e[entity].animOneshot=true;
  294. break;
  295. case animHit1:
  296. e[entity].frame_start = frame_hit1start+e[entity].mod;
  297. e[entity].frame_end = frame_hit1end+e[entity].mod;
  298. e[entity].currentFrame = e[entity].frame_start;
  299. e[entity].animLoop=false;
  300. e[entity].animOneshot=true;
  301. break;
  302. case animHit2:
  303. e[entity].frame_start = frame_hit2start+e[entity].mod;
  304. e[entity].frame_end = frame_hit2end+e[entity].mod;
  305. e[entity].currentFrame = e[entity].frame_start;
  306. e[entity].animLoop=false;
  307. e[entity].animOneshot=true;
  308. break;
  309. case animUcut:
  310. e[entity].frame_start = frame_ucutstart+e[entity].mod;
  311. e[entity].frame_end = frame_ucutend+e[entity].mod;
  312. e[entity].currentFrame = e[entity].frame_start;
  313. e[entity].animLoop=false;
  314. e[entity].animOneshot=true;
  315. break;
  316. case animWalk:
  317. e[entity].framesCounter = 8;
  318. e[entity].frame_start = frame_walkstart+e[entity].mod;
  319. e[entity].frame_end = frame_walkend+e[entity].mod;
  320. e[entity].currentFrame = e[entity].frame_start;
  321. e[entity].animLoop=true;
  322. e[entity].animOneshot=false;
  323. break;
  324. case animDamage:
  325. e[entity].frame_start = frame_damagestart+e[entity].mod;
  326. e[entity].frame_end = frame_damageend+e[entity].mod;
  327. e[entity].currentFrame = e[entity].frame_start;
  328. e[entity].animLoop=false;
  329. e[entity].animOneshot=true;
  330. break;
  331. case animFlying:
  332. e[entity].framesCounter = 100;
  333. e[entity].frame_start = frame_flyingstart+e[entity].mod;
  334. e[entity].frame_end = frame_flyingend+e[entity].mod;
  335. e[entity].currentFrame = e[entity].frame_start;
  336. e[entity].animLoop=false;
  337. e[entity].animOneshot=true;
  338. break;
  339. }
  340. e[entity].currentAnim = anim;
  341. }
  342. void setplayeranimation(int player, int anim){
  343. p[player].lastAnim = anim;
  344. switch(anim){
  345. case animIdle:
  346. p[player].frame_start = frame_idlestart;
  347. p[player].frame_end = frame_idleend;
  348. p[player].currentFrame = p[player].frame_start;
  349. break;
  350. case animKick:
  351. p[player].frame_start = frame_kickstart;
  352. p[player].frame_end = frame_kickend;
  353. p[player].currentFrame = p[player].frame_start;
  354. break;
  355. case animHit1:
  356. p[player].frame_start = frame_hit1start;
  357. p[player].frame_end = frame_hit1end;
  358. p[player].currentFrame = p[player].frame_start;
  359. break;
  360. case animUcut:
  361. p[player].frame_start = frame_ucutstart;
  362. p[player].frame_end = frame_ucutend;
  363. p[player].currentFrame = p[player].frame_start;
  364. break;
  365. case animHit2:
  366. p[player].frame_start = frame_hit2start;
  367. p[player].frame_end = frame_hit2end;
  368. p[player].currentFrame = p[player].frame_start;
  369. break;
  370. case animWalk:
  371. if(p[0].currentAnim!=animWalk){
  372. p[player].frame_start = frame_walkstart;
  373. p[player].frame_end = frame_walkend;
  374. p[player].currentFrame = p[player].frame_start;
  375. }
  376. break;
  377. case animDamage:
  378. p[player].frame_start = frame_damagestart;
  379. p[player].frame_end = frame_damageend;
  380. p[player].currentFrame = p[player].frame_start;
  381. break;
  382. case animFlying:
  383. p[player].frame_start = frame_flyingstart;
  384. p[player].frame_end = frame_flyingend;
  385. p[player].currentFrame = p[player].frame_start;
  386. break;
  387. }
  388. p[player].currentAnim = anim;
  389. }
  390. void updateitems(){
  391. for(int i=0;i<MAX_ITEMS;i++){
  392. if(it[i].active==false)continue;
  393. if(it[i].incx!=0){
  394. if(it[i].incx>0){
  395. it[i].incx-=.05;
  396. it[i].angle+=10;
  397. }
  398. if(it[i].incx<0){
  399. it[i].incx+=.05;
  400. it[i].angle-=10;
  401. }
  402. if(it[i].incx>-0.1 && it[i].incx<0.1){
  403. it[i].incx=0;
  404. }
  405. it[i].incy+=.42;
  406. it[i].position.x+=it[i].incx;
  407. if(it[i].incy<8)it[i].position.y+=it[i].incy;
  408. }else{
  409. if(it[i].blinking==false){
  410. it[i].blinking=true;
  411. it[i].blinkingtime=0;
  412. it[i].blinkingcnt=0;
  413. }
  414. }
  415. // For the blinking of the entity
  416. if(it[i].blinking==true)it[i].blinkingtime++;
  417. if(it[i].blinkingtime<150 && it[i].blinking==true){
  418. it[i].blinkingcnt++;
  419. if(it[i].blinkingcnt>10){
  420. it[i].blinkingcnt=0;
  421. if(it[i].visible==true){
  422. it[i].visible=false;
  423. }else{
  424. it[i].visible=true;
  425. }
  426. }
  427. }
  428. if(it[i].blinking && it[i].blinkingtime>150)it[i].active=false;
  429. }
  430. }
  431. void updateentity(int entity){
  432. // animation
  433. if(e[entity].active!=true)return;
  434. if(e[entity].currentAnim==animNothing)return;
  435. e[entity].lastFiretime++;
  436. e[entity].framesCounter++;
  437. ;
  438. if(e[entity].flying){
  439. if(e[entity].flyingincx!=0){
  440. if(e[entity].flyingincx>0){
  441. e[entity].flyingincx-=.05;
  442. }
  443. if(e[entity].flyingincx<0){
  444. e[entity].flyingincx+=.05;
  445. }
  446. if(e[entity].flyingincx>-0.1 && e[entity].flyingincx<0.1){
  447. e[entity].flyingincx=0;
  448. }
  449. e[entity].flyingincy+=.42;
  450. e[entity].position.x+=e[entity].flyingincx;
  451. if(e[entity].flyingincy<8)e[entity].position.y+=e[entity].flyingincy;
  452. }else{
  453. if(e[entity].blinking==false){
  454. e[entity].blinking=true;
  455. e[entity].blinkingtime=0;
  456. e[entity].blinkingcnt=0;
  457. }
  458. }
  459. }
  460. // For the blinking of the entity
  461. if(e[entity].blinking==true)e[entity].blinkingtime++;
  462. if(e[entity].blinkingtime<150 && e[entity].blinking==true){
  463. e[entity].blinkingcnt++;
  464. if(e[entity].blinkingcnt>10){
  465. e[entity].blinkingcnt=0;
  466. if(e[entity].visible==true){
  467. e[entity].visible=false;
  468. }else{
  469. e[entity].visible=true;
  470. }
  471. }
  472. }
  473. if(e[entity].blinking && e[entity].blinkingtime>150)e[entity].active=false;
  474. // actual animation system for the entities
  475. if (e[entity].framesCounter >= (60/e[entity].frameSpeed))
  476. {
  477. e[entity].framesCounter = 0;
  478. e[entity].currentFrame++;
  479. if (e[entity].currentFrame > e[entity].frame_end){
  480. if(e[entity].animLoop==true){
  481. e[entity].currentFrame = e[entity].frame_start;
  482. }
  483. if(e[entity].animOneshot==true){
  484. if(e[entity].currentAnim==animFlying){
  485. e[entity].currentFrame = e[entity].frame_end;
  486. //e[entity].currentAnim = animNothing;
  487. }else{
  488. setentityanimation(entity,animIdle);
  489. }
  490. }
  491. }
  492. int ypos = e[entity].currentFrame/15;
  493. e[entity].frameRec.y = (float)(e[entity].currentFrame/15)*(float)96;
  494. e[entity].frameRec.x = (float)((e[entity].currentFrame)-ypos*15)*(float)96;
  495. }
  496. // states
  497. if(e[entity].state==stateDead)return;
  498. if(e[entity].currentAnim==animHit1)return;
  499. if(e[entity].currentAnim==animHit2)return;
  500. if(e[entity].currentAnim==animKick)return;
  501. if(e[entity].currentAnim==animUcut)return;
  502. if(e[entity].state==stateIdle && GetRandomValue(0,60)==1){
  503. e[entity].state=stateChase;
  504. }
  505. Vector2 oldpos=e[entity].position;
  506. if(p[0].enemyattheleft==entity && e[entity].currentAnim==animFlying)p[0].enemyattheleft=-1;
  507. if(p[0].enemyattheleft==entity && e[entity].mod==9)p[0].enemyattheleft=-1;
  508. if(p[0].enemyattheright==entity && e[entity].currentAnim==animFlying)p[0].enemyattheright=-1;
  509. if(p[0].enemyattheright==entity && e[entity].mod==9)p[0].enemyattheright=-1;
  510. if(e[entity].state==stateChase && e[entity].mod==5 && e[entity].currentAnim!=animFlying){
  511. //
  512. //
  513. if(e[entity].position.x<p[0].position.x && p[0].enemyattheleft==-1 && p[0].enemyattheright!=entity){
  514. if(e[entity].target.x<e[entity].position.x)e[entity].facing=-1;
  515. if(e[entity].target.x>e[entity].position.x)e[entity].facing=1;
  516. e[entity].target.x=p[0].position.x-48;
  517. e[entity].target.y=p[0].position.y;
  518. p[0].enemyattheleft = entity;
  519. //if(e[entity].currentAnim!=animWalk)setentityanimation(entity,animWalk);
  520. //e[entity].state = stateChase;
  521. }
  522. if(e[entity].position.x>p[0].position.x && p[0].enemyattheright==-1 && p[0].enemyattheleft!=entity){
  523. if(e[entity].target.x<e[entity].position.x)e[entity].facing=-1;
  524. if(e[entity].target.x>e[entity].position.x)e[entity].facing=1;
  525. e[entity].target.x=p[0].position.x+48;
  526. e[entity].target.y=p[0].position.y;
  527. p[0].enemyattheright = entity;
  528. //e[entity].state = stateChase;
  529. }
  530. if(p[0].enemyattheleft==entity || p[0].enemyattheright==entity){
  531. if(e[entity].position.x>e[entity].target.x)e[entity].position.x--;
  532. if(e[entity].position.x<e[entity].target.x)e[entity].position.x++;
  533. if(e[entity].position.y>e[entity].target.y)e[entity].position.y--;
  534. if(e[entity].position.y<e[entity].target.y)e[entity].position.y++;
  535. if(distance(e[entity].position.x,e[entity].position.y,p[0].position.x,p[0].position.y)<20){
  536. if(p[0].position.x<e[entity].position.x)e[entity].facing=-1;
  537. if(p[0].position.x>e[entity].position.x)e[entity].facing=1;
  538. }
  539. //
  540. for(int i=0;i<MAX_ENTITIES;i++){
  541. if(i==entity)continue;
  542. if(e[i].state!=stateChase)continue;
  543. if(e[i].mod==9)continue;
  544. if(distance(e[i].position.x,e[i].position.y,e[entity].position.x,e[entity].position.y)<48){
  545. if(e[i].position.x>e[entity].position.x)e[i].position.x+=2;
  546. if(e[i].position.x<e[entity].position.x)e[i].position.x-=2;
  547. if(e[i].position.y>e[entity].position.y)e[i].position.y+=2;
  548. if(e[i].position.y<e[entity].position.y)e[i].position.y-=2;
  549. if(p[0].enemyattheleft==entity)p[0].enemyattheleft=-1;
  550. if(p[0].enemyattheright==entity)p[0].enemyattheright=-1;
  551. e[entity].state = stateIdle;
  552. }
  553. }
  554. //
  555. if(e[entity].currentAnim!=animWalk && e[entity].currentAnim!=animDamage)setentityanimation(entity,animWalk);
  556. }
  557. if(rectsoverlap(p[0].position.x,p[0].position.y,96,96,e[entity].position.x,e[entity].position.y,48,48)==false){
  558. if(p[0].enemyattheleft==entity)p[0].enemyattheleft=-1;
  559. if(p[0].enemyattheright==entity)p[0].enemyattheright=-1;
  560. //e[entity].state=stateIdle;
  561. }
  562. }
  563. // Scatter if clumped up together.
  564. for(int i=0;i<MAX_ENTITIES;i++){
  565. if(e[entity].state!=stateIdle)continue;
  566. if(i==entity)continue;
  567. if(distance(e[entity].position.x,e[entity].position.y,e[i].position.x,e[i].position.y)<80){
  568. e[entity].state=statemoveto;
  569. e[entity].target.x = e[entity].position.x+GetRandomValue(-50,50);
  570. e[entity].target.y = e[entity].position.y+GetRandomValue(-50,50);
  571. if(e[entity].target.x<48)e[entity].target.x+=48;
  572. if(e[entity].target.x>1000-48)e[entity].target.x-=48;
  573. if(e[entity].target.y<148)e[entity].target.y+=48;
  574. if(e[entity].target.y>600-48)e[entity].target.y-=48;
  575. setentityanimation(entity,animWalk);
  576. }
  577. }
  578. // Move to state
  579. if(e[entity].state==statemoveto){
  580. if(e[entity].position.x>e[entity].target.x)e[entity].position.x--;
  581. if(e[entity].position.x<e[entity].target.x)e[entity].position.x++;
  582. if(e[entity].position.y>e[entity].target.y)e[entity].position.y--;
  583. if(e[entity].position.y<e[entity].target.y)e[entity].position.y++;
  584. if(distance(e[entity].position.x,e[entity].position.y,e[entity].target.x,e[entity].target.y)<4){
  585. e[entity].state = stateIdle;
  586. }
  587. }
  588. // If we have not moved then revert back to the idle state.
  589. if(e[entity].position.x==oldpos.x && e[entity].position.y==oldpos.y){
  590. if(e[entity].currentAnim!=animDamage)setentityanimation(entity,animIdle);
  591. }
  592. }
  593. void updateplayer(int player){
  594. // animation
  595. p[player].lastFiretime++;
  596. p[player].keynothingtime++;
  597. p[player].framesCounter++;
  598. p[player].enemyweareatattacking=-1;
  599. if (p[0].framesCounter >= (60/framesSpeed))
  600. {
  601. p[0].framesCounter = 0;
  602. p[0].currentFrame++;
  603. if (p[0].currentFrame > p[0].frame_end) p[0].currentFrame = p[0].frame_start;
  604. int ypos = p[0].currentFrame/15;
  605. frameRec.y = (float)(p[0].currentFrame/15)*(float)96;
  606. frameRec.x = (float)((p[0].currentFrame)-ypos*15)*(float)96;
  607. }
  608. //
  609. // Player hits a enemy!
  610. //
  611. // Is he nearby
  612. for(int entity=0;entity<MAX_ENTITIES;entity++){
  613. if(e[entity].damagedelay>0)e[entity].damagedelay-=1;
  614. if(p[player].enemyweareatattacking!=entity && p[player].enemyweareatattacking!=-1)continue;
  615. if(rectsoverlap(p[player].position.x,p[player].position.y,70,60,e[entity].position.x,e[entity].position.y+10,60,40)){
  616. // Are we on the final damaging frame.
  617. if(p[0].currentFrame == frame_hit1end || p[0].currentFrame == frame_hit2end || p[0].currentFrame == frame_kickend || p[0].currentFrame == frame_ucutend){
  618. // Are we faced into the right direction
  619. bool goahead=false;
  620. if(p[player].facing==-1 && e[entity].position.x<p[player].position.x){
  621. goahead=true;
  622. }
  623. if(p[player].facing==1 && e[entity].position.x>p[player].position.x){
  624. goahead=true;
  625. }
  626. // We have hit 'em
  627. if(goahead && e[entity].damagedelay==0){
  628. p[player].enemyweareatattacking=entity;
  629. //
  630. e[entity].damagedelay=10;
  631. //if(e[0].health>0)e[0].health-=2;
  632. //if(e[0].health<4 && e[0].health>0 && p[player].hitcombo==4){
  633. if(p[player].hitcombo==4){
  634. if(GetRandomValue(0,10)>5 || e[entity].mod==9){
  635. p[player].hitcombo=0;
  636. e[entity].frameSpeed = 2;
  637. e[entity].flying = true;
  638. e[entity].flyingincx = 5;
  639. e[entity].flyingincy = -5;
  640. setentityanimation(entity,animFlying);
  641. e[entity].state = stateDead;
  642. e[entity].shadey = e[entity].position.y;
  643. if(p[0].position.x>e[entity].position.x)e[entity].flyingincx=-e[entity].flyingincx;
  644. }else{
  645. p[player].hitcombo=0;
  646. e[entity].health=0;
  647. setentityanimation(entity,animDamage);
  648. //
  649. if(e[entity].mod==5){
  650. e[entity].mod = 9;
  651. it[entity].active=true;
  652. it[entity].visible=true;
  653. it[entity].shadey=e[entity].position.y;
  654. it[entity].incx=5;
  655. it[entity].incy=-5;
  656. it[entity].position = e[entity].position;
  657. if(p[0].position.x>e[entity].position.x)it[entity].incx=-it[entity].incx;
  658. }
  659. }
  660. }else{
  661. if(p[player].hitcombo==4)p[player].hitcombo=0;
  662. setentityanimation(entity,animDamage);
  663. p[player].hitcombo++;
  664. }
  665. }
  666. }
  667. }
  668. }
  669. // player movement
  670. if(p[player].currentAnim == animWalk && p[player].keynothingtime>1){
  671. setplayeranimation(player,animIdle);
  672. }
  673. if(p[player].currentAnim == animHit1 && p[player].keynothingtime>15){
  674. setplayeranimation(player,animIdle);
  675. }
  676. if(p[player].currentAnim == animHit2 && p[player].keynothingtime>15){
  677. setplayeranimation(player,animIdle);
  678. }
  679. if(p[player].currentAnim == animUcut && p[player].keynothingtime>15){
  680. setplayeranimation(player,animIdle);
  681. }
  682. if(p[player].currentAnim == animKick && p[player].keynothingtime>15){
  683. setplayeranimation(player,animIdle);
  684. }
  685. if(LEFT==false && RIGHT==false && UP==false && DOWN==false && FIRE1){
  686. bool cont=true;
  687. if(p[player].lastFireAnim == animHit1 || p[player].lastFireAnim == animHit2){
  688. if(p[player].hitcombo==4){
  689. //p[player].hitcombo=0;
  690. setplayeranimation(player,animUcut);
  691. p[player].lastFireAnim=animUcut;
  692. cont=false;
  693. }
  694. }
  695. if(cont){
  696. if(p[player].lastFireAnim==animHit2){
  697. setplayeranimation(player,animHit1);
  698. p[player].lastFireAnim=animHit1;
  699. }else{
  700. setplayeranimation(player,animHit2);
  701. p[player].lastFireAnim=animHit2;
  702. }
  703. }
  704. FIRE1=false;
  705. }
  706. if(LEFT==false && RIGHT==false && UP==false && DOWN==false && FIRE2){
  707. p[player].hitcombo=0;
  708. setplayeranimation(player,animKick);
  709. FIRE2=false;
  710. }
  711. if (RIGHT){
  712. p[player].hitcombo=0;
  713. p[player].lastFiretime=50;
  714. p[0].facing = 1;
  715. p[0].position.x+=2;
  716. RIGHT=false;
  717. setplayeranimation(player,animWalk);
  718. }
  719. else if (LEFT){
  720. p[player].hitcombo=0;
  721. p[player].lastFiretime=50;
  722. p[0].facing=-1;
  723. p[0].position.x-=2;
  724. LEFT=false;
  725. setplayeranimation(player,animWalk);
  726. }
  727. if (DOWN){
  728. p[player].hitcombo=0;
  729. p[player].lastFiretime=50;
  730. p[0].position.y+=2;
  731. DOWN=false;
  732. setplayeranimation(player,animWalk);
  733. }
  734. else if (UP){
  735. p[player].hitcombo=0;
  736. p[player].lastFiretime=50;
  737. p[0].position.y-=2;
  738. UP=false;
  739. setplayeranimation(player,animWalk);
  740. }
  741. }
  742. void playercontrols(int player){
  743. if (p[player].lastFiretime>30 && IsKeyDown(KEY_Z) && FIRE1==false && FIRE2==false){
  744. FIRE1 = true;
  745. p[player].lastFiretime=0;
  746. p[player].keynothingtime = 0;
  747. }
  748. if (p[player].lastFiretime>30 && IsKeyDown(KEY_X) && FIRE1==false && FIRE2==false){
  749. FIRE2 = true;
  750. p[player].lastFiretime=0;
  751. p[player].keynothingtime = 0;
  752. }
  753. if(p[player].lastFiretime<20)return; //WATCH this return!!
  754. if (IsKeyDown(KEY_RIGHT)){
  755. RIGHT = true;
  756. LEFT = false;
  757. p[player].keynothingtime = 0;
  758. }
  759. else if (IsKeyDown(KEY_LEFT)){
  760. LEFT = true;
  761. RIGHT = false;
  762. p[player].keynothingtime = 0;
  763. }
  764. if (IsKeyDown(KEY_DOWN)){
  765. DOWN = true;
  766. UP = false;
  767. p[player].keynothingtime = 0;
  768. }
  769. else if (IsKeyDown(KEY_UP)){
  770. UP = true;
  771. DOWN = false;
  772. p[player].keynothingtime = 0;
  773. }
  774. }
  775. //
  776. // What this function does is create a list of every y position of each sprite on the screen. This list gets
  777. // sorted(bubble sort) so that the first sprite to be drawn is the upper most sprite. The last sprite on the list
  778. // is the sprite that is on the lowest position on the screen.
  779. // This is done because if a sprite is drawn ontop of another we need to know if he is infront or behind it. Knowing
  780. // the feet position is a good way of this. If two sprites are close by, the one which is lower(at the feet) needs
  781. // to be drawn infront(I think anyways, testing still for bugs)
  782. // There might be problems later on so any weirdness with drawing wil be needed to be fixed here(different sprite sizes(standing/laying/items))
  783. //
  784. void drawZordered(){
  785. int totalsprites; // how many sprites
  786. int sortedlist[MAX_SPRITES][3]; // max of 1000 sprites ( 1 = player, 2 = entity, 3 = items)(playerid, entityid, itemid)
  787. int position=0;
  788. for(int i=0;i<MAX_PLAYERS;i++){
  789. sortedlist[position][0]=1;
  790. sortedlist[position][1]=i;
  791. sortedlist[position][2]=p[i].position.y+96;
  792. position++;
  793. }
  794. for(int i=0;i<MAX_ENTITIES;i++){
  795. if(e[i].active==false)continue;
  796. sortedlist[position][0]=2;
  797. sortedlist[position][1]=i;
  798. sortedlist[position][2]=e[i].position.y+96;
  799. //102/98 - special case - sprites are lying down so they have different bottom potision
  800. if(e[i].currentFrame==102 || e[i].currentFrame==98)sortedlist[position][2]-=32;
  801. position++;
  802. }
  803. for(int i=0;i<MAX_ITEMS;i++){
  804. if(it[i].active==false)continue;
  805. sortedlist[position][0]=3;
  806. sortedlist[position][1]=i;
  807. sortedlist[position][2]=it[i].position.y+48;
  808. position++;
  809. }
  810. totalsprites=position;
  811. //bubble sort - infinitly loop through the list and move lower value one position up and the one there one down.
  812. //exit when one loop is done without a modification.
  813. bool exit=false;
  814. while(exit==false){
  815. exit=true;
  816. for(int i=1;i<totalsprites;i++){
  817. if(sortedlist[i][2]<sortedlist[i-1][2]){
  818. int temp[3];
  819. temp[0]=sortedlist[i-1][0];
  820. temp[1]=sortedlist[i-1][1];
  821. temp[2]=sortedlist[i-1][2];
  822. sortedlist[i-1][0]=sortedlist[i][0];
  823. sortedlist[i-1][1]=sortedlist[i][1];
  824. sortedlist[i-1][2]=sortedlist[i][2];
  825. sortedlist[i][0]=temp[0];
  826. sortedlist[i][1]=temp[1];
  827. sortedlist[i][2]=temp[2];
  828. exit=false;
  829. }
  830. }
  831. }
  832. //
  833. // Here we draw everything z ordered
  834. //
  835. for(int i=0;i<totalsprites;i++){
  836. if(sortedlist[i][0]==1){//draw player
  837. int pn = sortedlist[i][1];
  838. if(p[pn].facing==1){
  839. DrawEllipse(p[pn].position.x+40,p[pn].position.y+96,20,10,(Color){0,0,0,96});
  840. DrawTextureRec(scarfy, frameRec, (Vector2){p[pn].position.x,p[pn].position.y}, WHITE); // Draw part of the texture
  841. }else{
  842. DrawEllipse(p[pn].position.x+48,p[pn].position.y+96,20,10,(Color){0,0,0,96});
  843. DrawTexturePro(scarfy, (Rectangle){frameRec.x,frameRec.y,-96,96},// the -96 (-)means mirror on x axis
  844. (Rectangle){p[pn].position.x,p[pn].position.y,96,96},
  845. (Vector2){0,0},0,WHITE);
  846. }
  847. }
  848. if(sortedlist[i][0]==2){//draw entities
  849. int en = sortedlist[i][1];
  850. if(e[en].active==false)continue;
  851. if(e[en].visible==false)continue;
  852. bool shade=true;
  853. if(e[en].facing==1){
  854. if(shade){
  855. if(e[en].currentAnim!=animFlying){
  856. DrawEllipse(e[en].position.x+40,e[en].position.y+96,20,10,(Color){0,0,0,96});
  857. }else{
  858. DrawEllipse(e[en].position.x+40,e[en].shadey+96,20,10,(Color){0,0,0,96});
  859. }
  860. }
  861. DrawTextureRec(scarfy, e[en].frameRec, (Vector2){e[en].position.x,e[en].position.y}, WHITE); // Draw part of the texture
  862. }else{
  863. if(shade){
  864. if(e[en].currentAnim!=animFlying){
  865. DrawEllipse(e[en].position.x+48,e[en].position.y+96,20,10,(Color){0,0,0,96});
  866. }else{
  867. DrawEllipse(e[en].position.x+48,e[en].shadey+96,20,10,(Color){0,0,0,96});
  868. }
  869. }
  870. DrawTexturePro(scarfy, (Rectangle){e[en].frameRec.x,e[en].frameRec.y,-96,96},// the -96 (-)means mirror on x axis
  871. (Rectangle){e[en].position.x,e[en].position.y,96,96},
  872. (Vector2){0,0},0,WHITE);
  873. }
  874. }
  875. if(sortedlist[i][0]==3){//Draw items
  876. int in = sortedlist[i][1];
  877. if(it[in].active==false)continue;
  878. if(it[in].visible==false)continue;
  879. DrawEllipse(it[in].position.x+47,it[in].shadey+106,16,8,(Color){0,0,0,96});
  880. // get the head cell
  881. it[in].frameRec.y = 0;
  882. it[in].frameRec.x = 96*4;
  883. //DrawTextureRec(scarfy, it[0].frameRec, (Vector2){it[0].position.x,it[0].position.y}, WHITE); // Draw part of the texture
  884. DrawTexturePro(scarfy, (Rectangle){it[in].frameRec.x,it[in].frameRec.y,-96,96},// the -96 (-)means mirror on x axis
  885. (Rectangle){it[in].position.x+48,it[in].position.y+48,96,96},
  886. (Vector2){96/2,96/2},it[in].angle,WHITE);
  887. }
  888. }
  889. }
  890. // Not build for 2 players yet p[x]
  891. void entityattack(int entity){
  892. if(e[entity].currentAnim!=animIdle)return;
  893. if(GetRandomValue(0,100)>1)return;
  894. // if close to player or headless then attack
  895. if(rectsoverlap(e[entity].position.x,e[entity].position.y+24,64,20,p[0].position.x,p[0].position.y+24,64,32)==true || e[entity].mod==9){
  896. // If the entity is not headless then he turns into the direction of the player.
  897. if(e[entity].mod==5){
  898. if(p[0].position.x<e[entity].position.x)e[entity].facing=-1;
  899. if(p[0].position.x>e[entity].position.x)e[entity].facing=1;
  900. }
  901. switch(GetRandomValue(0,3)){
  902. case 0:
  903. setentityanimation(entity,animHit1);
  904. //debug = GetRandomValue(0,100);
  905. break;
  906. case 1:
  907. setentityanimation(entity,animHit2);
  908. break;
  909. case 2:
  910. setentityanimation(entity,animKick);
  911. break;
  912. case 3:
  913. setentityanimation(entity,animUcut);
  914. break;
  915. }
  916. }
  917. }
  918. // Rectangles overlap
  919. bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2){
  920. if(x1 >= (x2 + w2) || (x1 + w1) <= x2) return false;
  921. if(y1 >= (y2 + h2) || (y1 + h1) <= y2) return false;
  922. return true;
  923. }
  924. // Manhattan Distance (less precise)
  925. float distance(float x1,float y1,float x2,float y2){
  926. return (float)abs(x2-x1)+abs(y2-y1);
  927. }