bubblebobble.c 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722
  1. //
  2. // ONE LEVEL.. Controls : Cursors Left,Right,Up,Down and Left Alt = shoot bubble.
  3. //
  4. //
  5. enum flag2{PLAYER1,PLAYER2,LEFT,RIGHT};
  6. enum bubblestates{SHOT,FLOATUP,FLOAT};
  7. enum aistates{ROAMING,TRAPPED,DAMAGED,TRAJECTORY};
  8. enum flag{SCROLLLEVELDOWN,INGAME};
  9. #define CHEATMODE false
  10. #define MAX_JUMP 4.0f
  11. #define MAX_PLAYERS 2 // second player not fully implemented yet.
  12. #define MAX_FALL_SPEED 2.0f
  13. #define MAX_BUBBLES 256
  14. #define BUBBLE_SHOOTFORCE 10.0f //how fast does the bubble shoot away from the player
  15. #define BUBBLE_LIFE 60*20 //how long does a empty bubble stay alive
  16. #define CAPTURED_TIMEOUT 60*7 //how long does a ai stay inside the bubble
  17. #define RESTOREFROMDAMAGED 200 //time a ai stays damaged
  18. #define BUBBLE_PUSHTIME 4 //how long do we push the ai holding bubble before it pops
  19. #define MAX_AI 32
  20. #define AI_SPEED 3
  21. #define AI_LAUNCHFORCE 4.5
  22. #define AI_TRAJTIME 60*2
  23. #define MAX_PICKUP 128
  24. #define PICKUP_TIMEDISAPPEAR 60*6
  25. #define MAX_PICKUPEFFECT 128
  26. #define PICKUPEFFECT_MY 2
  27. #define PICKUPEFFECT_DISAPPEAR 60*1.5
  28. #define POINT1 200
  29. #define POINT2 500
  30. #define POINT3 1000
  31. #define POINT4 10000
  32. #define POINT5 20000
  33. #include "raylib.h"
  34. #include "math.h"
  35. static const int screenWidth=800;
  36. static const int screenHeight=450;
  37. static int mapWidth;
  38. static int mapHeight;
  39. static float tileWidth;
  40. static float tileHeight;
  41. static int map[512][512];
  42. static Color c64color[16]; //' our colors
  43. typedef struct player{
  44. bool active;
  45. float facing;
  46. float x;
  47. float y;
  48. int shotfiredtime;
  49. int w;
  50. int h;
  51. int score;
  52. bool canjump;
  53. float jumpforce;
  54. }player;
  55. static struct player p[MAX_PLAYERS];
  56. typedef struct bubble{
  57. bool active;
  58. bool contains;
  59. int timeout;
  60. int timeoutcaptured;
  61. float x;
  62. float y;
  63. int state;
  64. int r;
  65. float mx;
  66. float my;
  67. int shakex;
  68. int shakey;
  69. int pushtime;
  70. }bubble;
  71. static struct bubble arr_bubble[MAX_BUBBLES];
  72. typedef struct ai{
  73. bool active;
  74. float rotation;
  75. int state;
  76. int animframetime;
  77. int facing;
  78. int timedamaged;
  79. float x;
  80. float y;
  81. int trajtime;
  82. float mx;
  83. float my;
  84. int w;
  85. int h;
  86. int lastjump;
  87. bool canjump;
  88. float jumpforce;
  89. }ai;
  90. static struct ai arr_ai[MAX_AI];
  91. typedef struct pickup{
  92. bool active;
  93. int x;
  94. int y;
  95. int w;
  96. int h;
  97. int type;
  98. Color col;
  99. int timedisappear;
  100. }pickup;
  101. static struct pickup arr_pickup[MAX_PICKUP];
  102. typedef struct pickupeffect{
  103. bool active;
  104. float x;
  105. float y;
  106. float my;
  107. int type;
  108. float alpha;
  109. float timedisappear;
  110. int points;
  111. }pickupeffect;
  112. static struct pickupeffect arr_pueffect[MAX_PICKUPEFFECT];
  113. static void inilevel(void);
  114. static void drawmap(int offsetx,int offsety);
  115. static void drawplayers(void);
  116. static void updateplayers(void);
  117. static bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2);
  118. static bool playertilecollide(int num,int tile, int offsetx,int offsety);
  119. static void updateplayergravity();
  120. static void shootbubble(int player, int direction);
  121. static void drawbubbles(void);
  122. static void updatebubbles(void);
  123. static bool circlerectcollide(int cx,int cy,int cr, int rx, int ry,int rw,int rh);
  124. static bool bubbletilecollide(int num,int offsetx,int offsety);
  125. static float Clamp(float value, float min, float max);
  126. static void drawai(void);
  127. static void addai(int x,int y);
  128. static void updateai(void);
  129. static bool aitilecollide(int num,int tile,int offsetx,int offsety);
  130. static void bubbleaicollision(void);
  131. static void playeraicollision(void);
  132. static void playerbubblecollision(void);
  133. static void inigfx(void);
  134. static void createaitrajectory(int x,int y,int facing);
  135. static float getangle(float x1,float y1,float x2,float y2);
  136. static void drawpickups(void);
  137. static void updatepickups(void);
  138. static void addpickup(int x,int y);
  139. static void playerpickupcollision();
  140. static void updatepickupeffects();
  141. static void drawpickupeffects();
  142. static void addpickupeffect(int type,int x, int y);
  143. static int getscore(int type);
  144. static void drawplayerbar(void);
  145. static void inigame(void);
  146. static void inic64colors(void);
  147. static void drawplayerscolling(void);
  148. // Here the gfx are defined.
  149. static RenderTexture2D tilepurple;
  150. static RenderTexture2D spritebobble1;
  151. static RenderTexture2D spritebobble2;
  152. static RenderTexture2D spriteai1;
  153. static RenderTexture2D spriteai2;
  154. static RenderTexture2D spritefruit1;
  155. static RenderTexture2D spritefruit2;
  156. static RenderTexture2D spritefruit3;
  157. static RenderTexture2D spritefruit4;
  158. static RenderTexture2D spritefruit5;
  159. static bool gameover = false;
  160. static int fx=0; // for moving the playr in a bubble to the level.
  161. static int fy=0;
  162. int main(void)
  163. {
  164. // Initialization
  165. //--------------------------------------------------------------------------------------
  166. InitWindow(screenWidth, screenHeight, "raylib example.");
  167. // Create a Image in memory
  168. tilepurple = LoadRenderTexture(32, 32);
  169. spritebobble1 = LoadRenderTexture(32, 32);
  170. spritebobble2 = LoadRenderTexture(32, 32);
  171. spriteai1 = LoadRenderTexture(32, 32);
  172. spriteai2 = LoadRenderTexture(32, 32);
  173. spritefruit1 = LoadRenderTexture(32, 32);
  174. spritefruit2 = LoadRenderTexture(32, 32);
  175. spritefruit3 = LoadRenderTexture(32, 32);
  176. spritefruit4 = LoadRenderTexture(32, 32);
  177. spritefruit5 = LoadRenderTexture(32, 32);
  178. inic64colors();
  179. inigfx();
  180. SetTargetFPS(60); // Set our game to run at 60 frames-per-second
  181. inilevel();
  182. inigame();
  183. //--------------------------------------------------------------------------------------
  184. static int offsety;
  185. offsety = -(mapHeight*tileHeight);
  186. static int gamestate=SCROLLLEVELDOWN;
  187. //static int gamestate=INGAME;
  188. static int aiaddtime=10;
  189. static int aimax = 3;
  190. static int restarttime;
  191. fx = screenWidth/2;
  192. fy = -200;
  193. // Main game loop
  194. while (!WindowShouldClose()) // Detect window close button or ESC key
  195. {
  196. // Update
  197. //----------------------------------------------------------------------------------
  198. switch (gamestate){
  199. case INGAME:
  200. if(aimax>0)aiaddtime-=1;
  201. if(aiaddtime==0 && aimax>0){
  202. addai(10*tileWidth,tileHeight+5);
  203. aiaddtime=20;
  204. aimax-=1;
  205. }
  206. updateplayers();
  207. updateplayers();
  208. updateplayers();
  209. updateplayergravity();
  210. updatebubbles();
  211. bubbleaicollision();
  212. updateai();
  213. playeraicollision();
  214. playerbubblecollision();
  215. updatepickups();
  216. updatepickupeffects();
  217. playerpickupcollision();
  218. //see if there are no more ai then countdown and reset.
  219. restarttime+=1;
  220. for(int i=0;i<MAX_AI;i++){
  221. if(arr_ai[i].active)restarttime=0;
  222. }
  223. if(gameover==true || restarttime>60*10){
  224. fx = p[PLAYER1].x;
  225. fy = p[PLAYER1].y;
  226. inilevel();
  227. inigame();
  228. aiaddtime=10;
  229. aimax = 3;
  230. restarttime=0;
  231. offsety = -(mapHeight*tileHeight);
  232. gamestate = SCROLLLEVELDOWN;
  233. gameover = false;
  234. }
  235. break;
  236. }
  237. //----------------------------------------------------------------------------------
  238. // Draw
  239. //----------------------------------------------------------------------------------
  240. BeginDrawing();
  241. ClearBackground(BLACK);
  242. switch (gamestate){
  243. case SCROLLLEVELDOWN:
  244. offsety+=4;
  245. drawmap(0,offsety);
  246. drawplayerscolling();
  247. for(int i=0;i<5;i++){
  248. if(fx>p[PLAYER1].x)fx-=1;
  249. if(fy<p[PLAYER1].y)fy+=1;
  250. if(fx<p[PLAYER1].x)fx+=1;
  251. if(fy>p[PLAYER1].y)fy-=1;
  252. }
  253. if(offsety>=0)gamestate=INGAME;
  254. break;
  255. case INGAME:
  256. drawmap(0,0);
  257. drawplayerbar();
  258. drawpickups();
  259. drawpickupeffects();
  260. drawplayers();
  261. drawai();
  262. drawbubbles();
  263. break;
  264. }
  265. // DrawTexturePro(spritebobble1.texture, (Rectangle){0,0,spritebobble1.texture.width,
  266. // spritebobble1.texture.height},
  267. // (Rectangle){50,
  268. // 50,
  269. // tileWidth,tileHeight},
  270. // (Vector2){0,0},0,WHITE);
  271. EndDrawing();
  272. //----------------------------------------------------------------------------------
  273. }
  274. // De-Initialization
  275. //--------------------------------------------------------------------------------------
  276. UnloadRenderTexture(tilepurple);
  277. UnloadRenderTexture(spritebobble1);
  278. UnloadRenderTexture(spritebobble2);
  279. UnloadRenderTexture(spriteai1);
  280. UnloadRenderTexture(spriteai2);
  281. UnloadRenderTexture(spritefruit1);
  282. UnloadRenderTexture(spritefruit2);
  283. UnloadRenderTexture(spritefruit3);
  284. UnloadRenderTexture(spritefruit4);
  285. UnloadRenderTexture(spritefruit5);
  286. CloseWindow(); // Close window and OpenGL context
  287. //--------------------------------------------------------------------------------------
  288. return 0;
  289. }
  290. void drawmap(int offsetx,int offsety){
  291. for(int y=0;y<mapHeight;y++){
  292. for(int x=0;x<mapWidth;x++){
  293. if(map[y][x]==1 || map[y][x]==2){
  294. DrawTexturePro(tilepurple.texture, (Rectangle){0,0,tilepurple.texture.width,tilepurple.texture.height},
  295. (Rectangle){x*tileWidth+offsetx,y*tileHeight+offsety,
  296. tileWidth,tileHeight},
  297. (Vector2){0,0},0,WHITE);
  298. }
  299. }}
  300. }
  301. // Read the level.
  302. void inilevel(void){
  303. // 3 = map tile and start of enemies.
  304. mapWidth = 20;
  305. mapHeight = 15;
  306. tileWidth = abs((float)screenWidth/(float)mapWidth);
  307. tileHeight = abs((float)screenHeight/(float)mapHeight);
  308. //
  309. int temp[15][20] = { {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2},
  310. {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2},
  311. {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2},
  312. {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2},
  313. {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2},
  314. {2,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,2},
  315. {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2},
  316. {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2},
  317. {2,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,2},
  318. {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2},
  319. {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2},
  320. {2,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,2},
  321. {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2},
  322. {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2},
  323. {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2}};
  324. // copy the temp into the main map array.
  325. for(int y=0;y<mapHeight;y++){
  326. for(int x=0;x<mapWidth;x++){
  327. map[y][x] = temp[y][x];
  328. }}
  329. }
  330. void drawplayers(void){
  331. for(int i=0;i<MAX_PLAYERS;i++){
  332. if(p[i].active==false)continue;
  333. //DrawRectangle(p[i].x,p[i].y,p[i].w,p[i].h,GREEN);
  334. if(p[i].shotfiredtime>-2)p[i].shotfiredtime-=1;
  335. if(p[i].facing==RIGHT){
  336. if(p[i].shotfiredtime>0){
  337. DrawTexturePro(spritebobble2.texture, (Rectangle){0,0,spritebobble2.texture.width,
  338. spritebobble2.texture.height},
  339. (Rectangle){p[i].x,
  340. p[i].y,
  341. p[i].w,p[i].h},
  342. (Vector2){0,0},0,WHITE);
  343. }else{
  344. DrawTexturePro(spritebobble1.texture, (Rectangle){0,0,spritebobble1.texture.width,
  345. spritebobble1.texture.height},
  346. (Rectangle){p[i].x,
  347. p[i].y,
  348. p[i].w,p[i].h},
  349. (Vector2){0,0},0,WHITE);
  350. }
  351. }else{
  352. if(p[i].shotfiredtime>0){
  353. DrawTexturePro(spritebobble2.texture, (Rectangle){0,0,-spritebobble2.texture.width,
  354. spritebobble2.texture.height},
  355. (Rectangle){p[i].x,
  356. p[i].y,
  357. p[i].w,p[i].h},
  358. (Vector2){0,0},0,WHITE);
  359. }else{
  360. DrawTexturePro(spritebobble1.texture, (Rectangle){0,0,-spritebobble1.texture.width,
  361. spritebobble1.texture.height},
  362. (Rectangle){p[i].x,
  363. p[i].y,
  364. p[i].w,p[i].h},
  365. (Vector2){0,0},0,WHITE);
  366. }
  367. }
  368. }
  369. }
  370. //Unit collide with solid blocks true/false
  371. // num = player
  372. bool playertilecollide(int num,int tile,int offsetx,int offsety){
  373. if(p[num].active==false)return false;
  374. int cx = (p[num].x+offsetx)/tileWidth;
  375. int cy = (p[num].y+offsety)/tileHeight;
  376. for(int y2=cy-1; y2<cy+2;y2++){//Note that the - and + are to be set differently with differently sized players
  377. for(int x2=cx-1; x2<cx+2;x2++){
  378. if(x2>=0 && x2<mapWidth && y2>=0 && y2<mapHeight){
  379. if(map[y2][x2] == tile){
  380. int x3 = (x2)*tileWidth;
  381. int y3 = (y2)*tileHeight;
  382. if(rectsoverlap(p[num].x+offsetx,p[num].y+offsety,p[num].w,p[num].h,x3,y3,tileWidth,tileHeight)){
  383. return true;
  384. }
  385. }
  386. if(tile==99){//collide with any tile mode
  387. if(map[y2][x2] > 0){
  388. int x3 = (x2)*tileWidth;
  389. int y3 = (y2)*tileHeight;
  390. if(rectsoverlap(p[num].x+offsetx,p[num].y+offsety,p[num].w,p[num].h,x3,y3,tileWidth,tileHeight)){
  391. return true;
  392. }
  393. }
  394. }
  395. }
  396. }}
  397. return false;
  398. }
  399. //Unit collide with solid blocks true/false
  400. // num = player
  401. bool bubbletilecollide(int num,int offsetx,int offsety){
  402. if(arr_bubble[num].active==false)return false;
  403. int cx = (arr_bubble[num].x+offsetx)/tileWidth;
  404. int cy = (arr_bubble[num].y+offsety)/tileHeight;
  405. for(int y2=cy-1; y2<cy+2;y2++){//Note that the - and + are to be set differently with differently sized players
  406. for(int x2=cx-1; x2<cx+2;x2++){
  407. if(x2>=0 && x2<mapWidth && y2>=0 && y2<mapHeight){
  408. if(map[y2][x2] > 0 ){
  409. int x3 = (x2)*tileWidth;
  410. int y3 = (y2)*tileHeight;
  411. if(circlerectcollide( arr_bubble[num].x+offsetx,
  412. arr_bubble[num].y+offsety,
  413. arr_bubble[num].r,
  414. x3,y3,tileWidth,tileHeight)){
  415. return true;
  416. }
  417. }
  418. }
  419. }}
  420. return false;
  421. }
  422. // Rectangles overlap
  423. bool rectsoverlap(int x1,int y1,int w1,int h1,int x2,int y2,int w2,int h2){
  424. if(x1 >= (x2 + w2) || (x1 + w1) <= x2) return false;
  425. if(y1 >= (y2 + h2) || (y1 + h1) <= y2) return false;
  426. return true;
  427. }
  428. void updateplayers(void){
  429. for(int num=0;num<MAX_PLAYERS;num++){
  430. if(num==0){ //player 1
  431. // move left and right while jumping up.
  432. if(p[num].canjump==false &&
  433. p[num].jumpforce<0 &&
  434. IsKeyDown(KEY_LEFT) &&
  435. playertilecollide(num,2,-1,0)==false){
  436. p[num].x-=1;
  437. p[num].facing=LEFT;
  438. }
  439. if(p[num].canjump==false &&
  440. p[num].jumpforce<0 &&
  441. IsKeyDown(KEY_RIGHT) &&
  442. playertilecollide(num,2,1,0)==false){
  443. p[num].x+=1;
  444. p[num].facing=RIGHT;
  445. }
  446. //move left and right while falling down
  447. if(p[num].canjump==false &&
  448. p[num].jumpforce>0 &&
  449. IsKeyDown(KEY_LEFT) &&
  450. playertilecollide(num,99,-1,0)==false){
  451. p[num].x-=1;
  452. p[num].facing=LEFT;
  453. p[num].facing=RIGHT;
  454. }
  455. if(p[num].canjump==false &&
  456. p[num].jumpforce>0 &&
  457. IsKeyDown(KEY_RIGHT) &&
  458. playertilecollide(num,99,1,0)==false){
  459. p[num].x+=1;
  460. p[num].facing=RIGHT;
  461. }
  462. //move left and right normal
  463. if(p[num].canjump &&
  464. IsKeyDown(KEY_LEFT) &&
  465. playertilecollide(num,99,-1,0)==false){
  466. p[num].x-=1;
  467. p[num].facing=LEFT;
  468. }
  469. if(p[num].canjump &&
  470. IsKeyDown(KEY_RIGHT) &&
  471. playertilecollide(num,99,1,0)==false){
  472. p[num].x+=1;
  473. p[num].facing=RIGHT;
  474. }
  475. if(IsKeyDown(KEY_SPACE) && p[num].canjump){
  476. p[num].canjump = false; // We are now jumping.
  477. p[num].jumpforce = -MAX_JUMP; // How high we jump.
  478. }
  479. }
  480. }
  481. }
  482. void updateplayergravity(){
  483. for(int num=0;num<MAX_PLAYERS;num++){
  484. // JUMPING
  485. // if hanging in the air then fall down
  486. if(playertilecollide(num,99,0,1)==false)p[num].canjump=false;
  487. // If we are currently not jumping and if the player presses space.
  488. // If we are currently in a jump.
  489. if(p[num].canjump==false){
  490. // Here we update the player y position.
  491. // We want to move 1 pixel at a time. This for collision detection(Not going through tiles.)
  492. for(int i=0;i<abs((int)p[num].jumpforce);i++){
  493. // If we are still jumping then update the position.☺
  494. if(p[num].canjump==false){
  495. p[num].y += p[num].jumpforce;
  496. }
  497. if(p[num].jumpforce<0 && playertilecollide(num,2,0,-1)==true){
  498. p[num].jumpforce = 0.1;
  499. break;
  500. }
  501. // if we touch the ground then reset out position and set canjump to true.
  502. if(p[num].jumpforce>0 && playertilecollide(num,99,0,1)==true){
  503. p[num].y = p[num].y-2;
  504. p[num].canjump = true;
  505. break;
  506. }
  507. }
  508. // Here we add to the jumpforce. It will go from - to +.
  509. p[num].jumpforce += 0.2f;
  510. if(p[num].jumpforce>MAX_FALL_SPEED)p[num].jumpforce=MAX_FALL_SPEED;
  511. }
  512. }
  513. }
  514. void shootbubble(int player, int direction){
  515. for(int i=0;i<MAX_BUBBLES;i++){
  516. if(arr_bubble[i].active==true)continue;
  517. arr_bubble[i].active = true;
  518. arr_bubble[i].contains = false;
  519. arr_bubble[i].timeout = BUBBLE_LIFE; //how long does the bubble stay alive
  520. arr_bubble[i].r = tileWidth/2;//radius of our bullet.
  521. if(direction==LEFT){
  522. arr_bubble[i].mx=-BUBBLE_SHOOTFORCE;
  523. arr_bubble[i].x = p[player].x;
  524. }
  525. if(direction==RIGHT){
  526. arr_bubble[i].mx=BUBBLE_SHOOTFORCE;
  527. arr_bubble[i].x = p[player].x+p[player].w;
  528. }
  529. arr_bubble[i].y = p[player].y+5;
  530. arr_bubble[i].state = SHOT;
  531. return;
  532. }
  533. }
  534. void drawbubbles(){
  535. for(int i=0;i<MAX_BUBBLES;i++){
  536. if(arr_bubble[i].active==false)continue;
  537. int radius = arr_bubble[i].r;
  538. int x = arr_bubble[i].x+arr_bubble[i].shakex;
  539. int y = arr_bubble[i].y+arr_bubble[i].shakey;
  540. if(arr_bubble[i].contains){//contains a ai
  541. //DrawRectangle(x-radius+6,y-radius+6,radius*2-12,radius*2-8,(Color){200,0,0,200});
  542. DrawTexturePro(spriteai1.texture, (Rectangle){0,0,spriteai1.texture.width,
  543. spriteai1.texture.height},
  544. (Rectangle){x-radius+6,
  545. y-radius+6,
  546. spriteai1.texture.width,
  547. spriteai1.texture.height},
  548. (Vector2){0,0},0,BLUE);
  549. }
  550. DrawCircle(x,y,radius,(Color){0,50,0,40});
  551. DrawCircleLines(x,y,radius,(Color){0,200,0,100});
  552. DrawCircle(x-radius+(radius/1.5),y-radius+(radius/1.5),6,(Color){200,255,200,200});
  553. DrawCircle(x+(radius/2.1),y+(radius/2.1),2,(Color){200,255,200,200});
  554. }
  555. }
  556. void updatebubbles(){
  557. //player(s) shoot bubbles
  558. for(int i=0;i<MAX_PLAYERS;i++){
  559. if(p[i].active==false)continue;
  560. if(i==0){
  561. if(IsKeyPressed(KEY_LEFT_ALT)){
  562. if(p[i].facing==LEFT){
  563. shootbubble(i,LEFT);
  564. p[i].shotfiredtime=10;
  565. }else{
  566. shootbubble(i,RIGHT);
  567. p[i].shotfiredtime=10;
  568. }
  569. }
  570. }
  571. }
  572. // Bubbles movement and interaction
  573. for(int i=0;i<MAX_BUBBLES;i++){
  574. if(arr_bubble[i].active==false)continue;
  575. // decrease the player push bubble effect/
  576. if(arr_bubble[i].pushtime>-1)arr_bubble[i].pushtime--;
  577. //timeout
  578. arr_bubble[i].timeout-=1;
  579. if(arr_bubble[i].timeout<0){
  580. arr_bubble[i].active=false;
  581. if(arr_bubble[i].contains==true){
  582. int newai;
  583. for(newai=0;newai<MAX_AI;newai++){
  584. if(arr_ai[newai].active==true)continue;
  585. arr_bubble[i].contains=false;
  586. arr_ai[newai].active=true;
  587. arr_ai[newai].x=arr_bubble[i].x;
  588. arr_ai[newai].y=arr_bubble[i].y-4;
  589. arr_ai[newai].w=tileWidth;
  590. arr_ai[newai].h=tileHeight;
  591. arr_ai[newai].canjump = false;
  592. arr_ai[newai].state = DAMAGED;
  593. arr_ai[newai].facing = LEFT;
  594. arr_ai[newai].timedamaged=RESTOREFROMDAMAGED;
  595. break;
  596. }
  597. }
  598. }
  599. //shake bubble
  600. if(arr_bubble[i].state==FLOAT){
  601. if(GetRandomValue(0,30)<2){
  602. arr_bubble[i].shakex = GetRandomValue(-3,3);
  603. arr_bubble[i].shakey = GetRandomValue(-3,3);
  604. }
  605. }
  606. //
  607. if(arr_bubble[i].state==FLOATUP){
  608. // if containing a ai then count down and release.
  609. if(arr_bubble[i].contains==true){
  610. if(arr_bubble[i].timeout>-2)arr_bubble[i].timeout-=1;
  611. // release the ai again but faster and killable.
  612. if(arr_bubble[i].timeout<0){
  613. arr_bubble[i].active=false;
  614. int newai;
  615. for(newai=0;newai<MAX_AI;newai++){
  616. if(arr_ai[newai].active==true)continue;
  617. arr_ai[newai].active=true;
  618. arr_ai[newai].x=arr_bubble[i].x;
  619. arr_ai[newai].y=arr_bubble[i].y-4;
  620. arr_ai[newai].w=tileWidth;
  621. arr_ai[newai].h=tileHeight;
  622. arr_ai[newai].canjump = false;
  623. arr_ai[newai].state = DAMAGED;
  624. arr_ai[newai].facing = LEFT;
  625. arr_ai[newai].timedamaged=RESTOREFROMDAMAGED;
  626. break;
  627. }
  628. }
  629. }
  630. // float it up to center top screen and then shake it.
  631. if(arr_bubble[i].y>2.5*tileHeight){
  632. arr_bubble[i].y-=1;
  633. }
  634. if(arr_bubble[i].y<3*tileHeight){
  635. if(arr_bubble[i].x<screenWidth/2){
  636. arr_bubble[i].x+=1;
  637. }
  638. if(arr_bubble[i].x>screenWidth/2){
  639. arr_bubble[i].x-=1;
  640. }
  641. if(rectsoverlap( arr_bubble[i].x,arr_bubble[i].y,arr_bubble[i].r,arr_bubble[i].r,
  642. screenWidth/2-5,0,10,100)){
  643. for(int z=0;z<MAX_BUBBLES;z++){
  644. if(z!=i && arr_bubble[z].active==false)continue;
  645. if(rectsoverlap(arr_bubble[z].x,
  646. arr_bubble[z].y,
  647. arr_bubble[z].r,
  648. arr_bubble[z].r,
  649. arr_bubble[i].x,
  650. arr_bubble[z].y,
  651. arr_bubble[z].r,
  652. arr_bubble[z].r)){
  653. arr_bubble[i].state = FLOAT;
  654. }
  655. }
  656. }
  657. }
  658. }
  659. // If the bubble was just shot!
  660. if(arr_bubble[i].state==SHOT){
  661. for(int step=0;step<abs((int)arr_bubble[i].mx);step+=1){
  662. bool ex=false;
  663. if(arr_bubble[i].mx<0.0f ){
  664. arr_bubble[i].x -= 1;
  665. if(bubbletilecollide(i,-1,0)){//if bubble collides then change state;
  666. arr_bubble[i].mx=0;
  667. arr_bubble[i].state = FLOATUP;
  668. ex=true;
  669. }
  670. }
  671. if(arr_bubble[i].mx>0.0f){
  672. arr_bubble[i].x += 1;
  673. if(bubbletilecollide(i,1,0)){
  674. arr_bubble[i].mx=0;
  675. arr_bubble[i].state = FLOATUP;
  676. ex=true;
  677. }
  678. }
  679. if(ex)break;
  680. }
  681. if(arr_bubble[i].mx<0){
  682. arr_bubble[i].mx+=0.2f;
  683. }else{
  684. arr_bubble[i].mx-=0.2f;
  685. }
  686. // If the bubble slows down enough then change state to FLOAT;
  687. if(arr_bubble[i].mx>-0.3f && arr_bubble[i].mx < 0.3f){
  688. arr_bubble[i].mx = 0;
  689. arr_bubble[i].state = FLOATUP;
  690. }
  691. }
  692. }
  693. }
  694. bool circlerectcollide(int cx,int cy,int cr, int rx, int ry,int rw,int rh){
  695. float closestx = Clamp(cx, rx, rx+rw);
  696. float closesty = Clamp(cy, ry, ry+rh);
  697. float distancex = cx - closestx;
  698. float distancey = cy - closesty;
  699. float distancesquared = (distancex * distancex) + (distancey * distancey);
  700. return distancesquared < (cr * cr);
  701. }
  702. // Clamp float value
  703. float Clamp(float value, float min, float max)
  704. {
  705. const float res = value < min ? min : value;
  706. return res > max ? max : res;
  707. }
  708. void drawai(){
  709. for(int i=0;i<MAX_AI;i++){
  710. if(arr_ai[i].active==false)continue;
  711. int x = arr_ai[i].x;
  712. int y = arr_ai[i].y;
  713. int w = arr_ai[i].w;
  714. int h = arr_ai[i].h;
  715. // animation
  716. arr_ai[i].animframetime-=1;
  717. if(arr_ai[i].animframetime<0)arr_ai[i].animframetime=30;
  718. //
  719. // if the ai is currently spinning then rotate him.
  720. float rotation=0;
  721. if(arr_ai[i].state==TRAJECTORY){
  722. arr_ai[i].rotation+=20;
  723. rotation = arr_ai[i].rotation;
  724. }
  725. // When the ai goes into a spin make sure the rotation is around the center.
  726. float centerx=tileWidth/2;
  727. float centery=tileHeight/2;
  728. // if the ai is currently not spinning then draw the sprites from left top offset.
  729. if(arr_ai[i].state!=TRAJECTORY){
  730. centerx = 0;
  731. centery = 0;
  732. }
  733. //
  734. if(arr_ai[i].state==DAMAGED || arr_ai[i].state==TRAJECTORY){
  735. //DrawRectangle(x,y,w,h,BLUE);
  736. if(arr_ai[i].animframetime<15){
  737. if(arr_ai[i].facing==RIGHT){
  738. DrawTexturePro(spriteai1.texture, (Rectangle){0,0,spriteai1.texture.width,
  739. spriteai1.texture.height},
  740. (Rectangle){x,
  741. y,
  742. w,h},
  743. (Vector2){centerx,centery},rotation,BLUE);
  744. }else{
  745. DrawTexturePro(spriteai1.texture, (Rectangle){0,0,-spriteai1.texture.width,
  746. spriteai1.texture.height},
  747. (Rectangle){x,
  748. y,
  749. w,h},
  750. (Vector2){centerx,centery},rotation,BLUE);
  751. }
  752. }else{
  753. if(arr_ai[i].facing==RIGHT){
  754. DrawTexturePro(spriteai2.texture, (Rectangle){0,0,spriteai2.texture.width,
  755. spriteai2.texture.height},
  756. (Rectangle){x,
  757. y,
  758. w,h},
  759. (Vector2){centerx,centery},rotation,BLUE);
  760. }else{
  761. DrawTexturePro(spriteai2.texture, (Rectangle){0,0,-spriteai2.texture.width,
  762. spriteai2.texture.height},
  763. (Rectangle){x,
  764. y,
  765. w,h},
  766. (Vector2){centerx,centery},rotation,BLUE);
  767. }
  768. }
  769. }else{
  770. //DrawRectangle(x,y,w,h,RED);
  771. if(arr_ai[i].animframetime<15){
  772. if(arr_ai[i].facing==RIGHT){
  773. DrawTexturePro(spriteai1.texture, (Rectangle){0,0,spriteai1.texture.width,
  774. spriteai1.texture.height},
  775. (Rectangle){x,
  776. y,
  777. w,h},
  778. (Vector2){centerx,centery},rotation,WHITE);
  779. }else{
  780. DrawTexturePro(spriteai1.texture, (Rectangle){0,0,-spriteai1.texture.width,
  781. spriteai1.texture.height},
  782. (Rectangle){x,
  783. y,
  784. w,h},
  785. (Vector2){centerx,centery},rotation,WHITE);
  786. }
  787. }else{
  788. if(arr_ai[i].facing==RIGHT){
  789. DrawTexturePro(spriteai2.texture, (Rectangle){0,0,spriteai2.texture.width,
  790. spriteai2.texture.height},
  791. (Rectangle){x,
  792. y,
  793. w,h},
  794. (Vector2){centerx,centery},rotation,WHITE);
  795. }else{
  796. DrawTexturePro(spriteai2.texture, (Rectangle){0,0,-spriteai2.texture.width,
  797. spriteai2.texture.height},
  798. (Rectangle){x,
  799. y,
  800. w,h},
  801. (Vector2){centerx,centery},rotation,WHITE);
  802. }
  803. }
  804. }
  805. }
  806. }
  807. void addai(int x,int y){
  808. for(int i=0;i<MAX_AI;i++){
  809. if(arr_ai[i].active==true)continue;
  810. arr_ai[i].active = true;
  811. arr_ai[i].x = x;
  812. arr_ai[i].y = y;
  813. arr_ai[i].rotation = 0;
  814. arr_ai[i].w = tileWidth;
  815. arr_ai[i].h = tileHeight;
  816. arr_ai[i].canjump = false;
  817. arr_ai[i].state = ROAMING;
  818. arr_ai[i].facing = LEFT;
  819. return;
  820. }
  821. }
  822. void updateai(){
  823. for(int num=0;num<MAX_AI;num++){
  824. if(arr_ai[num].active==false)continue;
  825. // handle the trajectory of the ai. (if they got busted)
  826. if(arr_ai[num].state==TRAJECTORY){
  827. int speed=AI_SPEED;
  828. //If the ai is damaged than speed it it.
  829. for(int z=0;z<speed;z++){
  830. if(arr_ai[num].facing==LEFT){
  831. arr_ai[num].x-=1;
  832. if(arr_ai[num].x<tileWidth){
  833. arr_ai[num].facing=RIGHT;
  834. }
  835. }
  836. if(arr_ai[num].facing==RIGHT){
  837. arr_ai[num].x+=1;
  838. if(arr_ai[num].x>screenWidth-(tileWidth*2)){
  839. arr_ai[num].facing=LEFT;
  840. }
  841. }
  842. }
  843. // gravity on the trajectory
  844. if(arr_ai[num].trajtime>-2)arr_ai[num].trajtime-=1;
  845. for(int z=0;z<abs((int)arr_ai[num].my);z++){
  846. if(arr_ai[num].my<0){
  847. arr_ai[num].y+=1;//arr_ai[num].my;
  848. }else{
  849. arr_ai[num].y-=1;//arr_ai[num].my;
  850. }
  851. // If falling down long enough then end and drop loot
  852. if(arr_ai[num].y>tileHeight){
  853. if(arr_ai[num].my<0 && arr_ai[num].y>screenHeight-(tileHeight*3))arr_ai[num].trajtime=-1;
  854. if(arr_ai[num].trajtime<0){
  855. if( aitilecollide(num,99,0,1)==true &&
  856. aitilecollide(num,99,0,0)==false &&
  857. aitilecollide(num,99,-1,0)==false &&
  858. aitilecollide(num,99,1,0)==false){
  859. arr_ai[num].active=false;
  860. addpickup(arr_ai[num].x,arr_ai[num].y);
  861. break;
  862. }
  863. }
  864. }
  865. }
  866. arr_ai[num].my-=0.07f;
  867. //
  868. }
  869. // If ai is roaming or damaged (Moving around)
  870. if(arr_ai[num].state==ROAMING || arr_ai[num].state==DAMAGED){
  871. // restore from damages if time up.
  872. if(arr_ai[num].timedamaged>-2)arr_ai[num].timedamaged-=1;
  873. if(arr_ai[num].timedamaged<0 && bubbletilecollide(num,0,0)==false){
  874. arr_ai[num].state = ROAMING;
  875. }
  876. if(arr_ai[num].canjump==true){
  877. int speed=AI_SPEED;
  878. //If the ai is damaged than speed it it.
  879. if(arr_ai[num].state==DAMAGED)speed+=1;
  880. for(int z=0;z<speed;z++){
  881. if(arr_ai[num].facing==LEFT){
  882. arr_ai[num].x-=1;
  883. if(aitilecollide(num,99,-1,0)){
  884. arr_ai[num].facing=RIGHT;
  885. }
  886. }
  887. if(arr_ai[num].facing==RIGHT){
  888. arr_ai[num].x+=1;
  889. if(aitilecollide(num,99,1,0)){
  890. arr_ai[num].facing=LEFT;
  891. }
  892. }
  893. }
  894. // Jump the ai
  895. // jump up randomly if player is above us.
  896. if(GetRandomValue(0,400)<2){
  897. if(aitilecollide(num,99,0,-(tileHeight*1.1)) && arr_ai[num].y > p[PLAYER1].y){
  898. arr_ai[num].jumpforce = -MAX_JUMP;
  899. arr_ai[num].canjump = false;
  900. arr_ai[num].lastjump=0;
  901. }
  902. }
  903. // Jump randomly if a platform is reachable.
  904. if(GetRandomValue(0,400)<2){
  905. if(aitilecollide(num,99,0,-(tileHeight*1.1))){
  906. arr_ai[num].jumpforce = -MAX_JUMP;
  907. arr_ai[num].canjump = false;
  908. arr_ai[num].lastjump=0;
  909. }
  910. }
  911. // This is a jump fast after the first jump
  912. if(arr_ai[num].lastjump<100)arr_ai[num].lastjump+=1;
  913. if(arr_ai[num].lastjump<100 && GetRandomValue(0,100)<2){
  914. if(aitilecollide(num,99,0,-(tileHeight*1.1))){
  915. arr_ai[num].jumpforce = -MAX_JUMP;
  916. arr_ai[num].canjump = false;
  917. arr_ai[num].lastjump=101;
  918. }
  919. }
  920. }
  921. // if hanging in the air then fall down
  922. if(aitilecollide(num,99,0,1)==false)arr_ai[num].canjump=false;
  923. // If we are currently not jumping and if the player presses space.
  924. // If we are currently in a jump.
  925. if(arr_ai[num].canjump==false){
  926. // Here we update the player y position.
  927. // We want to move 1 pixel at a time. This for collision detection(Not going through tiles.)
  928. for(int i=0;i<abs((int)arr_ai[num].jumpforce);i++){
  929. bool exit=false;
  930. // If we are still jumping then update the position.
  931. if(arr_ai[num].canjump==false){
  932. arr_ai[num].y += arr_ai[num].jumpforce;
  933. }
  934. if(arr_ai[num].jumpforce<0 && aitilecollide(num,2,0,-1)==true){
  935. arr_ai[num].jumpforce = 0.1;
  936. break;
  937. }
  938. // if we touch the ground then reset out position and set canjump to true.
  939. if(arr_ai[num].jumpforce>0 && aitilecollide(num,99,0,1)==true){
  940. arr_ai[num].y = arr_ai[num].y-1;
  941. arr_ai[num].canjump = true;
  942. // look if the player is left or right and adjust direction.
  943. if(arr_ai[num].state==DAMAGED){
  944. if(arr_ai[num].x<p[PLAYER1].x){
  945. arr_ai[num].facing=LEFT;
  946. }else{
  947. arr_ai[num].facing=RIGHT;
  948. }
  949. }else{
  950. if(arr_ai[num].x>p[PLAYER1].x){
  951. arr_ai[num].facing=LEFT;
  952. }else{
  953. arr_ai[num].facing=RIGHT;
  954. }
  955. if(GetRandomValue(0,10)<5){
  956. if(GetRandomValue(0,10)<5){
  957. arr_ai[num].facing=LEFT;
  958. }else{
  959. arr_ai[num].facing=RIGHT;
  960. }
  961. }
  962. }
  963. exit=true;
  964. break;
  965. }
  966. if(exit)break;
  967. }
  968. // Here we add to the jumpforce. It will go from - to +.
  969. arr_ai[num].jumpforce += 0.2f;
  970. if(arr_ai[num].jumpforce>MAX_FALL_SPEED)arr_ai[num].jumpforce=MAX_FALL_SPEED;
  971. }
  972. }
  973. }
  974. }
  975. //Unit collide with solid blocks true/false
  976. // num = player
  977. bool aitilecollide(int num,int tile,int offsetx,int offsety){
  978. if(arr_ai[num].active==false)return false;
  979. int cx = (arr_ai[num].x+offsetx)/tileWidth;
  980. int cy = (arr_ai[num].y+offsety)/tileHeight;
  981. for(int y2=cy-1; y2<cy+2;y2++){//Note that the - and + are to be set differently with differently sized players
  982. for(int x2=cx-1; x2<cx+2;x2++){
  983. if(x2>=0 && x2<mapWidth && y2>=0 && y2<mapHeight){
  984. if(map[y2][x2] == tile){
  985. int x3 = (x2)*tileWidth;
  986. int y3 = (y2)*tileHeight;
  987. if(rectsoverlap(arr_ai[num].x+offsetx,arr_ai[num].y+offsety,arr_ai[num].w,arr_ai[num].h,x3,y3,tileWidth,tileHeight)){
  988. return true;
  989. }
  990. }
  991. if(tile==99){//collide with any tile mode
  992. if(map[y2][x2] > 0){
  993. int x3 = (x2)*tileWidth;
  994. int y3 = (y2)*tileHeight;
  995. if(rectsoverlap(arr_ai[num].x+offsetx,arr_ai[num].y+offsety,arr_ai[num].w,arr_ai[num].h,x3,y3,tileWidth,tileHeight)){
  996. return true;
  997. }
  998. }
  999. }
  1000. }
  1001. }}
  1002. return false;
  1003. }
  1004. void bubbleaicollision(){
  1005. // If bubble touches ai
  1006. for(int i=0;i<MAX_BUBBLES;i++){
  1007. if(arr_bubble[i].active==false || arr_bubble[i].state!=SHOT || arr_bubble[i].contains)continue;
  1008. // ai In a bubble than pop it
  1009. for(int ii=0;ii<MAX_AI;ii++){
  1010. if(arr_ai[ii].active==false || arr_ai[ii].state!=ROAMING)continue;
  1011. int x1=arr_bubble[i].x;
  1012. int y1=arr_bubble[i].y;
  1013. int r=arr_bubble[i].r;
  1014. int x2=arr_ai[ii].x;
  1015. int y2=arr_ai[ii].y;
  1016. int w=arr_ai[ii].w;
  1017. int h=arr_ai[ii].h;
  1018. if(circlerectcollide(x1,y1,r,x2,y2,w,h)){//if bubble colides with ai than float it.
  1019. arr_ai[ii].active=false;
  1020. arr_bubble[i].contains=true;
  1021. arr_bubble[i].state=FLOATUP;
  1022. arr_bubble[i].x = x2+tileWidth/2;
  1023. arr_bubble[i].timeout=CAPTURED_TIMEOUT;
  1024. break;
  1025. }
  1026. }
  1027. // AI damaged than it im
  1028. for(int ii=0;ii<MAX_AI;ii++){
  1029. if(arr_ai[ii].active==false || arr_ai[ii].state!=DAMAGED)continue;
  1030. int x1=arr_bubble[i].x;
  1031. int y1=arr_bubble[i].y;
  1032. int r=arr_bubble[i].r;
  1033. int x2=arr_ai[ii].x;
  1034. int y2=arr_ai[ii].y;
  1035. int w=arr_ai[ii].w;
  1036. int h=arr_ai[ii].h;
  1037. if(circlerectcollide(x1,y1,r,x2,y2,w,h)){//if bubble colides with ai than float it.
  1038. arr_ai[ii].active=false;
  1039. arr_bubble[i].active=false;
  1040. createaitrajectory(arr_ai[ii].x,arr_ai[ii].y,p[i].facing);
  1041. break;
  1042. }
  1043. }
  1044. }
  1045. }
  1046. void playeraicollision(){
  1047. for(int i=0;i<MAX_PLAYERS;i++){
  1048. if(p[i].active==false)continue;
  1049. //Collide with player and DAMAGED ai..// ai gets launched
  1050. for(int ii=0;ii<MAX_AI;ii++){
  1051. if(arr_ai[ii].active==false)continue;
  1052. if(arr_ai[ii].state==DAMAGED || arr_ai[ii].state==TRAPPED){
  1053. if(rectsoverlap( p[i].x,
  1054. p[i].y,
  1055. p[i].w,
  1056. p[i].h,
  1057. arr_ai[ii].x,
  1058. arr_ai[ii].y,
  1059. arr_ai[ii].w,
  1060. arr_ai[ii].h)){
  1061. arr_ai[ii].active=false;
  1062. createaitrajectory(arr_ai[ii].x,arr_ai[ii].y,p[i].facing);
  1063. }}
  1064. if(arr_ai[ii].state==ROAMING && CHEATMODE==false){
  1065. if(rectsoverlap( p[i].x,
  1066. p[i].y,
  1067. p[i].w,
  1068. p[i].h,
  1069. arr_ai[ii].x,
  1070. arr_ai[ii].y,
  1071. arr_ai[ii].w,
  1072. arr_ai[ii].h)){
  1073. gameover=true;
  1074. }}
  1075. }
  1076. }
  1077. }
  1078. void playerbubblecollision(){
  1079. for(int i=0;i<MAX_PLAYERS;i++){
  1080. if(p[i].active==false)continue;
  1081. for(int ii=0;ii<MAX_BUBBLES;ii++){
  1082. if(arr_bubble[ii].active==false || arr_bubble[ii].contains==false)continue;
  1083. int r=arr_bubble[ii].r;
  1084. if(circlerectcollide( arr_bubble[ii].x,
  1085. arr_bubble[ii].y,
  1086. r,
  1087. p[i].x,
  1088. p[i].y,
  1089. p[i].w,
  1090. p[i].h)){
  1091. arr_bubble[ii].pushtime+=2;
  1092. if(arr_bubble[ii].pushtime>BUBBLE_PUSHTIME){//frametime used
  1093. arr_bubble[ii].active=false;
  1094. createaitrajectory(arr_bubble[ii].x,arr_bubble[ii].y,p[i].facing);
  1095. }else{//push bubble away from player
  1096. float an=getangle( arr_bubble[ii].x,
  1097. arr_bubble[ii].y,
  1098. p[i].x,
  1099. p[i].y);
  1100. int oldx = arr_bubble[ii].x;
  1101. int oldy = arr_bubble[ii].y;
  1102. arr_bubble[ii].x -= cos(an)*3;
  1103. arr_bubble[ii].y -= sin(an)*3;
  1104. if(bubbletilecollide(ii,0,0)){
  1105. arr_bubble[ii].x = oldx;
  1106. arr_bubble[ii].y = oldy;
  1107. }
  1108. }
  1109. }
  1110. }
  1111. }
  1112. }
  1113. void createaitrajectory(int x,int y,int facing){
  1114. for(int i=0;i<MAX_AI;i++){
  1115. if(arr_ai[i].active)continue;
  1116. arr_ai[i].active=true;
  1117. arr_ai[i].x = x;
  1118. arr_ai[i].y = y;
  1119. arr_ai[i].state = TRAJECTORY;
  1120. arr_ai[i].facing = facing;
  1121. arr_ai[i].w = tileWidth;
  1122. arr_ai[i].h = tileHeight;
  1123. if(arr_ai[i].facing==LEFT){
  1124. arr_ai[i].mx=-3;
  1125. }else{
  1126. arr_ai[i].mx=3;
  1127. }
  1128. arr_ai[i].my=AI_LAUNCHFORCE;
  1129. arr_ai[i].trajtime = AI_TRAJTIME;
  1130. return;
  1131. }
  1132. }
  1133. static void inigfx(){
  1134. int tile1[8][8] = {
  1135. {4,4,10,10,4,4,10,10},
  1136. {10,4,4,10,10,4,4,10},
  1137. {10,10,4,4,10,10,4,4},
  1138. {4,10,10,4,4,10,10,4},
  1139. {4,4,10,10,4,4,10,10},
  1140. {10,4,4,10,10,4,4,10},
  1141. {10,10,4,4,10,10,4,4},
  1142. {4,10,10,4,4,10,10,4}};
  1143. // Clear our texture(image) before entering the game loop
  1144. BeginTextureMode(tilepurple);
  1145. ClearBackground(BLANK); // Make the entire Sprite Transparent.
  1146. EndTextureMode();
  1147. // Draw something on it.
  1148. for (int y=0;y<8;y++)
  1149. {
  1150. for (int x=0;x<8; x++)
  1151. {
  1152. // Our sprite color 1
  1153. if (tile1[y][x]==4)
  1154. {
  1155. BeginTextureMode(tilepurple);
  1156. DrawRectangle(x*4,y*4,4,4,(Color){200,100,0,255});
  1157. EndTextureMode();
  1158. }
  1159. // Our sprite color 2
  1160. if (tile1[y][x]==10)
  1161. {
  1162. BeginTextureMode(tilepurple);
  1163. DrawRectangle(x*4,y*4,4,8,(Color){100,50,0,255});
  1164. EndTextureMode();
  1165. }
  1166. }
  1167. }
  1168. //
  1169. // bobble frame 1
  1170. int bframe1[8][8] = {
  1171. {5,5,5,2,2,9,2,2},
  1172. {0,5,5,5,2,1,2,0},
  1173. {0,2,2,5,5,5,5,13},
  1174. {0,1,5,5,0,1,0,0},
  1175. {1,1,5,5,1,5,1,13},
  1176. {0,5,5,1,6,5,6,1},
  1177. {1,1,5,5,1,5,1,0},
  1178. {0,0,0,5,5,13,0,0}};
  1179. int bframe2[8][8] = {
  1180. {5,5,5,2,2,9,2,2},
  1181. {0,5,5,5,2,1,2,0},
  1182. {0,2,2,5,5,5,5,0},
  1183. {1,1,5,5,0,0,0,0},
  1184. {0,1,5,5,1,0,0,0},
  1185. {1,5,5,1,6,5,0,0},
  1186. {0,13,5,1,13,6,13,0},
  1187. {0,0,0,5,5,13,0,0}};
  1188. int aiframe1[8][8] = {
  1189. {0,0,0,2,2,0,0,0},
  1190. {12,12,2,2,2,2,12,0},
  1191. {2,12,12,12,12,12,12,12},
  1192. {2,11,2,11,11,0,0,0},
  1193. {1,2,2,1,15,1,15,1},
  1194. {0,1,1,15,6,15,6,1},
  1195. {0,1,1,1,1,1,1,1},
  1196. {0,0,0,1,1,1,1,0}};
  1197. int aiframe2[8][8] = {
  1198. {0,0,0,2,2,2,0,0},
  1199. {0,12,2,2,2,12,12,0},
  1200. {12,12,12,12,12,12,12,12},
  1201. {2,2,2,11,0,0,0,0},
  1202. {2,2,2,1,15,1,15,1},
  1203. {0,1,1,15,6,15,6,1},
  1204. {0,1,1,1,1,1,1,1},
  1205. {0,0,1,1,1,1,1,0}};
  1206. // Clear our texture(image) before entering the game loop
  1207. BeginTextureMode(spritebobble1);
  1208. ClearBackground(BLANK); // Make the entire Sprite Transparent.
  1209. EndTextureMode();
  1210. BeginTextureMode(spritebobble2);
  1211. ClearBackground(BLANK); // Make the entire Sprite Transparent.
  1212. EndTextureMode();
  1213. BeginTextureMode(spriteai1);
  1214. ClearBackground(BLANK); // Make the entire Sprite Transparent.
  1215. EndTextureMode();
  1216. BeginTextureMode(spriteai2);
  1217. ClearBackground(BLANK); // Make the entire Sprite Transparent.
  1218. EndTextureMode();
  1219. c64color[0] = (Color){0,0,0,0};
  1220. // Draw something on it.
  1221. for (int y=0;y<8;y++)
  1222. {
  1223. for (int x=0;x<8; x++)
  1224. {
  1225. BeginTextureMode(spriteai1);
  1226. DrawRectangle(x*4,y*4,4,4,c64color[aiframe1[y][x]]);
  1227. EndTextureMode();
  1228. BeginTextureMode(spriteai2);
  1229. DrawRectangle(x*4,y*4,4,4,c64color[aiframe2[y][x]]);
  1230. EndTextureMode();
  1231. BeginTextureMode(spritebobble1);
  1232. DrawRectangle(x*4,y*4,4,4,c64color[bframe1[y][x]]);
  1233. EndTextureMode();
  1234. BeginTextureMode(spritebobble2);
  1235. DrawRectangle(x*4,y*4,4,4,c64color[bframe2[y][x]]);
  1236. EndTextureMode();
  1237. }
  1238. }
  1239. int fruit1[8][8] = {
  1240. {0,4,2,4,0,0,0,0},
  1241. {4,2,4,2,4,2,0,0},
  1242. {4,4,4,4,2,4,2,0},
  1243. {4,8,10,4,4,2,4,0},
  1244. {0,4,4,1,4,4,5,13},
  1245. {0,0,0,4,8,4,13,0},
  1246. {0,0,0,0,5,13,13,5},
  1247. {0,0,0,0,13,0,0,13}};
  1248. int fruit2[8][8] = {
  1249. {10,10,0,0,0,0,0,0},
  1250. {0,10,10,4,0,0,0,0},
  1251. {0,10,15,10,4,0,0,0},
  1252. {0,0,10,1,10,4,0,13},
  1253. {0,0,0,10,10,10,13,13},
  1254. {0,0,0,0,10,13,5,0},
  1255. {0,0,0,0,13,5,13,13},
  1256. {0,0,0,13,13,0,13,13}};
  1257. int fruit3[8][8] = {
  1258. {0,0,10,10,12,0,0,0},
  1259. {0,0,10,15,10,0,0,0},
  1260. {0,0,0,10,15,10,0,0},
  1261. {0,0,0,9,9,9,0,0},
  1262. {10,10,10,10,10,10,10,10},
  1263. {10,8,10,10,10,10,10,10},
  1264. {0,10,15,8,10,10,10,0},
  1265. {0,0,10,10,10,10,0,0}};
  1266. int fruit4[8][8] = {
  1267. {11,2,2,2,11,0,0,0},
  1268. {2,8,2,2,2,2,2,0},
  1269. {2,2,2,2,2,2,2,2},
  1270. {2,2,2,8,2,2,2,2},
  1271. {11,8,2,2,13,13,2,13},
  1272. {0,1,2,2,13,13,5,13},
  1273. {0,2,1,2,2,5,13,0},
  1274. {0,0,2,2,13,13,0,13}};
  1275. int fruit5[8][8] = {
  1276. {0,9,11,9,11,0,0,0},
  1277. {9,8,9,8,9,11,0,0},
  1278. {8,9,8,9,8,9,0,0},
  1279. {8,8,8,8,9,9,0,0},
  1280. {8,15,8,8,8,1,0,0},
  1281. {0,8,8,8,1,1,1,1},
  1282. {0,0,0,0,0,1,1,1},
  1283. {0,0,0,0,0,1,1,0}};
  1284. // Clear our texture(image) before entering the game loop
  1285. BeginTextureMode(spritefruit1);
  1286. ClearBackground(BLANK); // Make the entire Sprite Transparent.
  1287. EndTextureMode();
  1288. BeginTextureMode(spritefruit2);
  1289. ClearBackground(BLANK); // Make the entire Sprite Transparent.
  1290. EndTextureMode();
  1291. BeginTextureMode(spritefruit3);
  1292. ClearBackground(BLANK); // Make the entire Sprite Transparent.
  1293. EndTextureMode();
  1294. BeginTextureMode(spritefruit4);
  1295. ClearBackground(BLANK); // Make the entire Sprite Transparent.
  1296. EndTextureMode();
  1297. BeginTextureMode(spritefruit5);
  1298. ClearBackground(BLANK); // Make the entire Sprite Transparent.
  1299. EndTextureMode();
  1300. c64color[0] = (Color){0,0,0,0};
  1301. // Draw something on it.
  1302. for (int y=0;y<8;y++)
  1303. {
  1304. for (int x=0;x<8; x++)
  1305. {
  1306. BeginTextureMode(spritefruit1);
  1307. DrawRectangle(x*4,y*4,4,4,c64color[fruit1[y][x]]);
  1308. EndTextureMode();
  1309. BeginTextureMode(spritefruit2);
  1310. DrawRectangle(x*4,y*4,4,4,c64color[fruit2[y][x]]);
  1311. EndTextureMode();
  1312. BeginTextureMode(spritefruit3);
  1313. DrawRectangle(x*4,y*4,4,4,c64color[fruit3[y][x]]);
  1314. EndTextureMode();
  1315. BeginTextureMode(spritefruit4);
  1316. DrawRectangle(x*4,y*4,4,4,c64color[fruit4[y][x]]);
  1317. EndTextureMode();
  1318. BeginTextureMode(spritefruit5);
  1319. DrawRectangle(x*4,y*4,4,4,c64color[fruit5[y][x]]);
  1320. EndTextureMode();
  1321. }
  1322. }
  1323. }
  1324. // Return the angle from - to in float
  1325. float getangle(float x1,float y1,float x2,float y2){
  1326. return (float)atan2(y2-y1, x2-x1);
  1327. }
  1328. void drawpickups(){
  1329. for(int i=0;i<MAX_PICKUP;i++){
  1330. if(arr_pickup[i].active==false)continue;
  1331. //Color col = arr_pickup[i].col;
  1332. //DrawRectangle(arr_pickup[i].x,arr_pickup[i].y,arr_pickup[i].w,arr_pickup[i].h,col);
  1333. int x = arr_pickup[i].x;
  1334. int y = arr_pickup[i].y;
  1335. int w = arr_pickup[i].w;
  1336. int h = arr_pickup[i].h;
  1337. if(arr_pickup[i].type==0){
  1338. DrawTexturePro(spritefruit1.texture, (Rectangle){0,0,spritefruit1.texture.width,
  1339. spritefruit1.texture.height},
  1340. (Rectangle){x,
  1341. y,
  1342. w,h},
  1343. (Vector2){0,0},0,WHITE);
  1344. }
  1345. if(arr_pickup[i].type==1){
  1346. DrawTexturePro(spritefruit2.texture, (Rectangle){0,0,spritefruit2.texture.width,
  1347. spritefruit2.texture.height},
  1348. (Rectangle){x,
  1349. y,
  1350. w,h},
  1351. (Vector2){0,0},0,WHITE);
  1352. }
  1353. if(arr_pickup[i].type==2){
  1354. DrawTexturePro(spritefruit3.texture, (Rectangle){0,0,spritefruit3.texture.width,
  1355. spritefruit3.texture.height},
  1356. (Rectangle){x,
  1357. y,
  1358. w,h},
  1359. (Vector2){0,0},0,WHITE);
  1360. }
  1361. if(arr_pickup[i].type==3){
  1362. DrawTexturePro(spritefruit4.texture, (Rectangle){0,0,spritefruit4.texture.width,
  1363. spritefruit4.texture.height},
  1364. (Rectangle){x,
  1365. y,
  1366. w,h},
  1367. (Vector2){0,0},0,WHITE);
  1368. }
  1369. if(arr_pickup[i].type==4){
  1370. DrawTexturePro(spritefruit5.texture, (Rectangle){0,0,spritefruit5.texture.width,
  1371. spritefruit5.texture.height},
  1372. (Rectangle){x,
  1373. y,
  1374. w,h},
  1375. (Vector2){0,0},0,WHITE);
  1376. }
  1377. }
  1378. }
  1379. void updatepickups(){
  1380. for(int i=0;i<MAX_PICKUP;i++){
  1381. if(arr_pickup[i].active==false)continue;
  1382. arr_pickup[i].timedisappear+=1;
  1383. // If the pickup its time has come.
  1384. if(arr_pickup[i].timedisappear>PICKUP_TIMEDISAPPEAR){
  1385. arr_pickup[i].active=false;
  1386. }
  1387. }
  1388. }
  1389. void addpickup(int x, int y){
  1390. for(int i=0;i<MAX_PICKUP;i++){
  1391. if(arr_pickup[i].active)continue;
  1392. arr_pickup[i].active=true;
  1393. arr_pickup[i].x = x;
  1394. arr_pickup[i].y = y;
  1395. arr_pickup[i].w = tileWidth;
  1396. arr_pickup[i].h = tileHeight;
  1397. arr_pickup[i].timedisappear = 0;
  1398. arr_pickup[i].type = GetRandomValue(0,4);
  1399. switch (arr_pickup[i].type){
  1400. case 0:
  1401. arr_pickup[i].col = (Color){200,0,0,255};
  1402. break;
  1403. case 1:
  1404. arr_pickup[i].col = (Color){0,200,0,255};
  1405. break;
  1406. case 2:
  1407. arr_pickup[i].col = (Color){0,0,200,255};
  1408. break;
  1409. case 3:
  1410. arr_pickup[i].col = (Color){200,200,0,255};
  1411. break;
  1412. case 4:
  1413. arr_pickup[i].col = (Color){200,0,200,255};
  1414. break;
  1415. case 5:
  1416. arr_pickup[i].col = (Color){200,200,200,255};
  1417. break;
  1418. }
  1419. return;
  1420. }
  1421. }
  1422. void playerpickupcollision(){
  1423. for(int i=0;i<MAX_PLAYERS;i++){
  1424. if(p[i].active==false)continue;
  1425. for(int ii=0;ii<MAX_PICKUP;ii++){
  1426. if(arr_pickup[ii].active==false)continue;
  1427. if(rectsoverlap( p[i].x,
  1428. p[i].y,
  1429. p[i].w,
  1430. p[i].h,
  1431. arr_pickup[ii].x,
  1432. arr_pickup[ii].y,
  1433. arr_pickup[ii].w,
  1434. arr_pickup[ii].h)){
  1435. arr_pickup[ii].active=false;
  1436. p[i].score+=getscore(arr_pickup[ii].type);
  1437. addpickupeffect(arr_pickup[ii].type,arr_pickup[ii].x,arr_pickup[ii].y);
  1438. // ADD effect here.
  1439. }
  1440. }
  1441. }
  1442. }
  1443. void updatepickupeffects(){
  1444. for(int i=0;i<MAX_PICKUPEFFECT;i++){
  1445. if(arr_pueffect[i].active==false)continue;
  1446. // If on screen to long than disappear.
  1447. arr_pueffect[i].timedisappear-=1;
  1448. if(arr_pueffect[i].timedisappear<0){
  1449. arr_pueffect[i].active=false;
  1450. }
  1451. arr_pueffect[i].y-=arr_pueffect[i].my;
  1452. if(arr_pueffect[i].alpha>-1)arr_pueffect[i].alpha -= 1;
  1453. }
  1454. }
  1455. void drawpickupeffects(){
  1456. for(int i=0;i<MAX_PICKUPEFFECT;i++){
  1457. if(arr_pueffect[i].active==false)continue;
  1458. int score=0;
  1459. switch (arr_pueffect[i].type){
  1460. case 0:
  1461. score = POINT1;
  1462. break;
  1463. case 1:
  1464. score = POINT2;
  1465. break;
  1466. case 2:
  1467. score = POINT3;
  1468. break;
  1469. case 3:
  1470. score = POINT4;
  1471. break;
  1472. case 4:
  1473. score = POINT5;
  1474. break;
  1475. }
  1476. DrawText( FormatText("%i",score),
  1477. arr_pueffect[i].x,arr_pueffect[i].y,
  1478. tileWidth/2.5,(Color){255,255,255,arr_pueffect[i].alpha});
  1479. }
  1480. }
  1481. void addpickupeffect(int type,int x, int y){
  1482. for(int i=0;i<MAX_PICKUPEFFECT;i++){
  1483. if(arr_pueffect[i].active)continue;
  1484. arr_pueffect[i].active = true;
  1485. arr_pueffect[i].x = x;
  1486. arr_pueffect[i].y = y;
  1487. arr_pueffect[i].alpha = 255;
  1488. arr_pueffect[i].type = type;
  1489. arr_pueffect[i].my = PICKUPEFFECT_MY;
  1490. arr_pueffect[i].timedisappear = PICKUPEFFECT_DISAPPEAR;
  1491. return;
  1492. }
  1493. }
  1494. int getscore(int type){
  1495. switch (type){
  1496. case 0:
  1497. return POINT1;
  1498. break;
  1499. case 1:
  1500. return POINT2;
  1501. break;
  1502. case 2:
  1503. return POINT3;
  1504. break;
  1505. case 3:
  1506. return POINT4;
  1507. break;
  1508. case 4:
  1509. return POINT5;
  1510. break;
  1511. }
  1512. return 0;
  1513. }
  1514. void drawplayerbar(){
  1515. DrawRectangle(0,0,150,20,BLACK);
  1516. DrawText(FormatText("%i",p[0].score),20,1,20,WHITE);
  1517. if(p[1].active==false)return;
  1518. DrawRectangle(screenWidth/2,0,150,20,BLACK);
  1519. DrawText(FormatText("%i",p[1].score),screenWidth/2+20,1,20,WHITE);
  1520. }
  1521. void inigame(){
  1522. for(int i=0;i<MAX_PICKUP;i++){
  1523. arr_pickup[i].active=false;
  1524. }
  1525. for(int i=0;i<MAX_AI;i++){
  1526. arr_ai[i].active=false;
  1527. }
  1528. for(int i=0;i<MAX_BUBBLES;i++){
  1529. arr_bubble[i].active=false;
  1530. arr_bubble[i].contains=false;
  1531. }
  1532. for(int i=0;i<MAX_PICKUP;i++){
  1533. arr_pickup[i].active=false;
  1534. }
  1535. for(int i=0;i<MAX_PICKUPEFFECT;i++){
  1536. arr_pueffect[i].active=false;
  1537. }
  1538. p[PLAYER1].active = true;
  1539. p[PLAYER1].x = 2*tileWidth;
  1540. p[PLAYER1].y = 12*tileHeight;
  1541. p[PLAYER1].w = tileWidth;
  1542. p[PLAYER1].h = tileHeight;
  1543. p[PLAYER1].canjump = true;
  1544. p[PLAYER2].active=false;
  1545. p[PLAYER2].score=0;
  1546. p[PLAYER2].x = 5*tileWidth;
  1547. p[PLAYER2].y = 12*tileHeight;
  1548. p[PLAYER2].w = tileWidth;
  1549. p[PLAYER2].h = tileHeight;
  1550. p[PLAYER2].canjump = true;
  1551. }
  1552. void inic64colors(void){
  1553. c64color[0 ] = (Color){0 , 0 , 0 , 255 };//Black
  1554. c64color[1 ] = (Color){255,255,255, 255 };//White
  1555. c64color[2 ] = (Color){136,0 ,0 , 255 };//Red
  1556. c64color[3 ] = (Color){170,255,238, 255 };//Cyan
  1557. c64color[4 ] = (Color){204,68 ,204, 255 };//Violet / Purple
  1558. c64color[5 ] = (Color){0 ,204,85 , 255 };//Green
  1559. c64color[6 ] = (Color){0 ,0 ,170, 255 };//Blue
  1560. c64color[7 ] = (Color){238,238,119, 255 };//Yellow
  1561. c64color[8 ] = (Color){221,136,85 , 255 };//Orange
  1562. c64color[9 ] = (Color){102,68 ,0 , 255 };//Brown
  1563. c64color[10] = (Color){255,119,119, 255 };//Light red
  1564. c64color[11] = (Color){51 ,51 ,51 , 255 };//Dark grey / Grey 1
  1565. c64color[12] = (Color){119,119,119, 255 };//Grey 2
  1566. c64color[13] = (Color){170,255,102, 255 };//Light green
  1567. c64color[14] = (Color){0 ,136,255, 255 };//Light blue
  1568. c64color[15] = (Color){187,187,187, 255 };//Light grey / grey 3
  1569. }
  1570. void drawplayerscolling(){
  1571. int x=fx+p[PLAYER1].w/2;
  1572. int y=fy+p[PLAYER1].h/2;
  1573. int radius=tileWidth/1.8;
  1574. DrawTexturePro(spritebobble1.texture, (Rectangle){0,0,spritebobble1.texture.width,
  1575. spritebobble1.texture.height},
  1576. (Rectangle){x-p[PLAYER1].w/2,
  1577. y-p[PLAYER1].h/2,
  1578. p[PLAYER1].w,p[PLAYER1].h},
  1579. (Vector2){0,0},0,WHITE);
  1580. DrawCircle(x,y,radius,(Color){0,50,0,40});
  1581. DrawCircleLines(x,y,radius,(Color){255,255,255,255});
  1582. DrawCircle(x-radius+(radius/1.5),y-radius+(radius/1.5),6,(Color){200,255,200,200});
  1583. DrawCircle(x+(radius/2.1),y+(radius/2.1),2,(Color){200,255,200,200});
  1584. }