main.c 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690
  1. /*
  2. James William Fletcher (github.com/mrbid)
  3. December 2021
  4. Info:
  5. Space Miner, a simple 3D space mining game.
  6. Keyboard:
  7. F = FPS to console
  8. P = Player stats to console
  9. N = New Game
  10. Q = Break Asteroid
  11. E = Stop all nearby Asteroids
  12. R = Repel all nearby Asteroids
  13. W = Thrust Forward
  14. A = Turn Left
  15. S = Thrust Backward
  16. D = Turn Right
  17. Shift = Thrust Down
  18. Space = Thrust Up
  19. Mouse:
  20. Left Click = Break Asteroid
  21. Right Click = Repel Asteroid
  22. Mouse 4 Click = Stop all Asteroids nearby
  23. Scroll = Zoom in/out
  24. Notes:
  25. Frustum Culling:
  26. In a game like this by introducing frustum culling all you are doing is introducing
  27. frame rate instability, the fewer asteroids on-screen with frustum culling the more frames
  28. per second the game will get, and vice-versa. But in a game like this, you could get all
  29. asteroids in the frame at once, or even just very varied amounts. Frame rate instability is
  30. always worse than having a stable, but lower, frame rate.
  31. I've never been a great fan of frustum culling, mainly because it only makes sense in a
  32. very niche avenue of 3D games, albeit the most popular niche, FPS games.
  33. The popularity of First-Person can hamper creativity, other 3D camera systems are rarely
  34. ever explored and partly this is due to there only being four main 3D camera systems;
  35. Fixed Camera, Ghost/Chase Camera, Orbit Camera, and First Person Camera.
  36. */
  37. #include <math.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <time.h>
  42. #define uint GLushort
  43. #define sint GLshort
  44. #define f32 GLfloat
  45. #include "gl.h"
  46. #define GLFW_INCLUDE_NONE
  47. #include "glfw3.h"
  48. #include "esAux4.h"
  49. #include "res.h"
  50. #include "assets/rock1.h"
  51. #include "assets/rock2.h"
  52. #include "assets/rock3.h"
  53. #include "assets/rock4.h"
  54. #include "assets/rock5.h"
  55. #include "assets/rock6.h"
  56. #include "assets/rock7.h"
  57. #include "assets/rock8.h"
  58. #include "assets/rock9.h"
  59. #include "assets/face.h"
  60. #include "assets/body.h"
  61. #include "assets/arms.h"
  62. #include "assets/left_flame.h"
  63. #include "assets/right_flame.h"
  64. #include "assets/legs.h"
  65. #include "assets/fuel.h"
  66. #include "assets/shield.h"
  67. #include "assets/pbreak.h"
  68. #include "assets/pshield.h"
  69. #include "assets/pslow.h"
  70. #include "assets/prepel.h"
  71. //*************************************
  72. // globals
  73. //*************************************
  74. GLFWwindow* window;
  75. uint winw = 1024;
  76. uint winh = 768;
  77. double t = 0; // time
  78. f32 dt = 0; // delta time
  79. double fc = 0; // frame count
  80. double lfct = 0;// last frame count time
  81. f32 aspect;
  82. double x,y,lx,ly;
  83. double rww, ww, rwh, wh, ww2, wh2;
  84. double uw, uh, uw2, uh2; // normalised pixel dpi
  85. // render state id's
  86. GLint projection_id;
  87. GLint modelview_id;
  88. GLint position_id;
  89. GLint lightpos_id;
  90. GLint color_id;
  91. GLint opacity_id;
  92. GLint normal_id;
  93. // render state matrices
  94. mat projection;
  95. mat view;
  96. mat model;
  97. mat modelview;
  98. // render state inputs
  99. vec lightpos = {0.f, 0.f, 0.f};
  100. // models
  101. sint bindstate = -1;
  102. sint bindstate2 = -1;
  103. uint keystate[6] = {0};
  104. ESModel mdlRock[9];
  105. ESModel mdlFace;
  106. ESModel mdlBody;
  107. ESModel mdlArms;
  108. ESModel mdlLeftFlame;
  109. ESModel mdlRightFlame;
  110. ESModel mdlLegs;
  111. ESModel mdlFuel;
  112. ESModel mdlShield;
  113. ESModel mdlPbreak;
  114. ESModel mdlPshield;
  115. ESModel mdlPslow;
  116. ESModel mdlPrepel;
  117. // game vars
  118. #define NEWGAME_SEED 1337
  119. #define THRUST_POWER 0.09f
  120. #define NECK_ANGLE 0.6f
  121. #define ROCK_DARKNESS 0.412f
  122. #define MAX_ROCK_SCALE 12.f
  123. const f32 RECIP_MAX_ROCK_SCALE = 1.f/(MAX_ROCK_SCALE+10.f);
  124. #define FUEL_DRAIN_RATE 0.023f
  125. #define SHIELD_DRAIN_RATE 0.06f
  126. #define REFINARY_YEILD 0.13f
  127. #ifdef __arm__
  128. #define ARRAY_MAX 2048 // 8 Megabytes of Asteroids
  129. const f32 FAR_DISTANCE = (float)ARRAY_MAX / 2.f;
  130. #else
  131. #define ARRAY_MAX 16384 // 64 Megabytes of Asteroids
  132. f32 FAR_DISTANCE = (float)ARRAY_MAX / 2.f;
  133. #endif
  134. typedef struct
  135. {
  136. // since we have the room
  137. int free; // fast free checking
  138. int nores;// no mineral resources
  139. // rock vars
  140. f32 scale;
  141. vec pos;
  142. vec vel;
  143. // +6 bytes
  144. uint rnd;
  145. f32 rndf;
  146. // rock colour array
  147. f32 colors[720];
  148. // mineral amounts
  149. f32 qshield;
  150. f32 qbreak;
  151. f32 qslow;
  152. f32 qrepel;
  153. f32 qfuel;
  154. } gi; // 4+4+4+16+16+2+4+2880+4+4+4+4+4 = 2950 bytes = 4096 padded (4 kilobyte)
  155. gi array_rocks[ARRAY_MAX] = {0};
  156. // gets a free/unused rock
  157. /*
  158. // the original idea was to dynamically pop out ores when rocks are mined
  159. // which then you need to manually float to and collect but, I went off the idea.
  160. sint freeRock()
  161. {
  162. for(sint i = 0; i < ARRAY_MAX; i++)
  163. if(array_rocks[i].free == 1)
  164. return i;
  165. return -1;
  166. }
  167. */
  168. // camera vars
  169. uint focus_cursor = 0;
  170. double sens = 0.003f;
  171. f32 xrot = 0.f;
  172. f32 yrot = 0.f;
  173. f32 zoom = -25.f;
  174. // player vars
  175. f32 so; // shield on (closest distance)
  176. uint ct;// thrust signal
  177. f32 pr; // rotation
  178. vec pp; // position
  179. vec pv; // velocity
  180. vec pd; // thust direction
  181. f32 lgr = 0.f; // last good head rotation
  182. vec pld;// look direction
  183. vec pfd;// face direction
  184. f32 pf; // fuel
  185. f32 pb; // break
  186. f32 ps; // shield
  187. f32 psp;// speed
  188. f32 psl;// slow
  189. f32 pre;// repel
  190. uint lf;// last fuel
  191. uint pm;// mined asteroid count
  192. double st=0; // start time
  193. char tts[32];// time taken string
  194. //*************************************
  195. // utility functions
  196. //*************************************
  197. void timestamp(char* ts)
  198. {
  199. const time_t tt = time(0);
  200. strftime(ts, 16, "%H:%M:%S", localtime(&tt));
  201. }
  202. static inline f32 fzero(f32 f)
  203. {
  204. if(f < 0.f){f = 0.f;}
  205. return f;
  206. }
  207. static inline f32 fone(f32 f)
  208. {
  209. if(f > 1.f){f = 1.f;}
  210. return f;
  211. }
  212. static inline f32 fsat(f32 f)
  213. {
  214. if(f < 0.f){f = 0.f;}
  215. if(f > 1.f){f = 1.f;}
  216. return f;
  217. }
  218. void timeTaken(uint ss)
  219. {
  220. if(ss == 1)
  221. {
  222. const double tt = t-st;
  223. if(tt < 60.0)
  224. sprintf(tts, "%.2f Sec", tt);
  225. else if(tt < 3600.0)
  226. sprintf(tts, "%.2f Min", tt * 0.016666667);
  227. else if(tt < 216000.0)
  228. sprintf(tts, "%.2f Hr", tt * 0.000277778);
  229. else if(tt < 12960000.0)
  230. sprintf(tts, "%.2f Days", tt * 0.00000463);
  231. }
  232. else
  233. {
  234. const double tt = t-st;
  235. if(tt < 60.0)
  236. sprintf(tts, "%.2f Seconds", tt);
  237. else if(tt < 3600.0)
  238. sprintf(tts, "%.2f Minutes", tt * 0.016666667);
  239. else if(tt < 216000.0)
  240. sprintf(tts, "%.2f Hours", tt * 0.000277778);
  241. else if(tt < 12960000.0)
  242. sprintf(tts, "%.2f Days", tt * 0.00000463);
  243. }
  244. }
  245. //*************************************
  246. // render functions
  247. //*************************************
  248. void rRock(uint i, f32 dist)
  249. {
  250. static const uint rcs = ARRAY_MAX / 9;
  251. static const f32 rrcs = 1.f / (f32)rcs;
  252. mIdent(&model);
  253. mTranslate(&model, array_rocks[i].pos.x, array_rocks[i].pos.y, array_rocks[i].pos.z);
  254. if(array_rocks[i].rnd < 500)
  255. {
  256. f32 mag = vMag(array_rocks[i].vel)*array_rocks[i].rndf*t;
  257. if(array_rocks[i].rnd < 100)
  258. mRotY(&model, mag);
  259. if(array_rocks[i].rnd < 200)
  260. mRotZ(&model, mag);
  261. if(array_rocks[i].rnd < 300)
  262. mRotX(&model, mag);
  263. }
  264. if(array_rocks[i].free == 2)
  265. {
  266. array_rocks[i].scale -= 32.f*dt;
  267. if(array_rocks[i].scale <= 0.f)
  268. array_rocks[i].free = 1;
  269. mScale(&model, array_rocks[i].scale, array_rocks[i].scale, array_rocks[i].scale);
  270. }
  271. else
  272. mScale(&model, array_rocks[i].scale, array_rocks[i].scale, array_rocks[i].scale);
  273. mMul(&modelview, &model, &view);
  274. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (f32*)&modelview.m[0][0]);
  275. glUniform1f(opacity_id, 1.0f);
  276. // unique colour arrays for each rock within visible distance
  277. if(array_rocks[i].nores == 0 && dist < 333.f)
  278. {
  279. glBindBuffer(GL_ARRAY_BUFFER, mdlRock[0].cid);
  280. glBufferData(GL_ARRAY_BUFFER, sizeof(rock1_colors), array_rocks[i].colors, GL_STATIC_DRAW);
  281. glVertexAttribPointer(color_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  282. glEnableVertexAttribArray(color_id);
  283. bindstate2 = 0;
  284. }
  285. else
  286. {
  287. if(bindstate2 != 1)
  288. {
  289. glBindBuffer(GL_ARRAY_BUFFER, mdlRock[1].cid);
  290. glVertexAttribPointer(color_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  291. glEnableVertexAttribArray(color_id);
  292. bindstate2 = 1;
  293. }
  294. }
  295. // this is a super efficient way to render 9 different types of asteroid
  296. uint nbs = i * rrcs;
  297. if(nbs > 8){nbs = 8;}
  298. if(nbs != bindstate)
  299. {
  300. glBindBuffer(GL_ARRAY_BUFFER, mdlRock[nbs].vid);
  301. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  302. glEnableVertexAttribArray(position_id);
  303. glBindBuffer(GL_ARRAY_BUFFER, mdlRock[nbs].nid);
  304. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  305. glEnableVertexAttribArray(normal_id);
  306. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlRock[nbs].iid);
  307. bindstate = nbs;
  308. }
  309. glDrawElements(GL_TRIANGLES, rock1_numind, GL_UNSIGNED_SHORT, 0);
  310. }
  311. void rLegs(f32 x, f32 y, f32 z, f32 rx)
  312. {
  313. bindstate = -1;
  314. mIdent(&model);
  315. mTranslate(&model, x, y, z);
  316. mRotX(&model, -rx);
  317. f32 mag = psp*32.f;
  318. if(mag > 0.4f)
  319. mag = 0.4f;
  320. mRotY(&model, mag);
  321. mMul(&modelview, &model, &view);
  322. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (f32*)&modelview.m[0][0]);
  323. glUniform1f(opacity_id, 1.0f);
  324. glUniform3f(color_id, 1.f, 1.f, 1.f);
  325. glBindBuffer(GL_ARRAY_BUFFER, mdlLegs.vid);
  326. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  327. glEnableVertexAttribArray(position_id);
  328. glBindBuffer(GL_ARRAY_BUFFER, mdlLegs.nid);
  329. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  330. glEnableVertexAttribArray(normal_id);
  331. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlLegs.iid);
  332. glDrawElements(GL_TRIANGLES, legs_numind, GL_UNSIGNED_SHORT, 0);
  333. }
  334. void rBody(f32 x, f32 y, f32 z, f32 rx)
  335. {
  336. bindstate = -1;
  337. mIdent(&model);
  338. mTranslate(&model, x, y, z);
  339. mRotX(&model, -rx);
  340. // returns new player direction
  341. mGetDirZ(&pld, model);
  342. vInv(&pld);
  343. if(ct > 0)
  344. {
  345. mGetDirZ(&pd, model);
  346. vInv(&pd);
  347. ct = 0;
  348. }
  349. mMul(&modelview, &model, &view);
  350. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (f32*)&modelview.m[0][0]);
  351. glUniform1f(opacity_id, 1.0f);
  352. glUniform3f(color_id, 1.f, 1.f, 1.f);
  353. glBindBuffer(GL_ARRAY_BUFFER, mdlBody.vid);
  354. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  355. glEnableVertexAttribArray(position_id);
  356. glBindBuffer(GL_ARRAY_BUFFER, mdlBody.nid);
  357. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  358. glEnableVertexAttribArray(normal_id);
  359. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlBody.iid);
  360. glDrawElements(GL_TRIANGLES, body_numind, GL_UNSIGNED_SHORT, 0);
  361. }
  362. void rFuel(f32 x, f32 y, f32 z, f32 rx)
  363. {
  364. bindstate = -1;
  365. mIdent(&model);
  366. mTranslate(&model, x, y, z);
  367. mRotX(&model, -rx);
  368. mMul(&modelview, &model, &view);
  369. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (f32*)&modelview.m[0][0]);
  370. glUniform1f(opacity_id, 1.0f);
  371. glUniform3f(color_id, fone(0.062f+(1.f-pf)), fone(1.f+(1.f-pf)), fone(0.873f+(1.f-pf)));
  372. glBindBuffer(GL_ARRAY_BUFFER, mdlFuel.vid);
  373. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  374. glEnableVertexAttribArray(position_id);
  375. glBindBuffer(GL_ARRAY_BUFFER, mdlFuel.nid);
  376. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  377. glEnableVertexAttribArray(normal_id);
  378. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlFuel.iid);
  379. glDrawElements(GL_TRIANGLES, fuel_numind, GL_UNSIGNED_SHORT, 0);
  380. }
  381. void rArms(f32 x, f32 y, f32 z, f32 rx)
  382. {
  383. bindstate = -1;
  384. mIdent(&model);
  385. mTranslate(&model, x, y, z);
  386. mRotX(&model, -rx);
  387. f32 mag = psp*32.f;
  388. if(mag > 0.4f)
  389. mag = 0.4f;
  390. mRotY(&model, mag);
  391. mMul(&modelview, &model, &view);
  392. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (f32*)&modelview.m[0][0]);
  393. glUniform1f(opacity_id, 1.0f);
  394. glUniform3f(color_id, 1.f, 1.f, 1.f);
  395. glBindBuffer(GL_ARRAY_BUFFER, mdlArms.vid);
  396. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  397. glEnableVertexAttribArray(position_id);
  398. glBindBuffer(GL_ARRAY_BUFFER, mdlArms.nid);
  399. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  400. glEnableVertexAttribArray(normal_id);
  401. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlArms.iid);
  402. glDrawElements(GL_TRIANGLES, arms_numind, GL_UNSIGNED_SHORT, 0);
  403. }
  404. void rLeftFlame(f32 x, f32 y, f32 z, f32 rx)
  405. {
  406. bindstate = -1;
  407. mIdent(&model);
  408. mTranslate(&model, x, y, z);
  409. mRotX(&model, -rx);
  410. f32 mag = psp*32.f;
  411. if(mag > 0.4f)
  412. mag = 0.4f;
  413. mRotY(&model, mag);
  414. mMul(&modelview, &model, &view);
  415. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (f32*)&modelview.m[0][0]);
  416. glUniform1f(opacity_id, 1.0f);
  417. //glUniform3f(color_id, 1.f, 0.f, 0.f);
  418. glUniform3f(color_id, 0.062f, 1.f, 0.873f);
  419. glBindBuffer(GL_ARRAY_BUFFER, mdlLeftFlame.vid);
  420. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  421. glEnableVertexAttribArray(position_id);
  422. glBindBuffer(GL_ARRAY_BUFFER, mdlLeftFlame.nid);
  423. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  424. glEnableVertexAttribArray(normal_id);
  425. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlLeftFlame.iid);
  426. glDrawElements(GL_TRIANGLES, left_flame_numind, GL_UNSIGNED_SHORT, 0);
  427. }
  428. void rRightFlame(f32 x, f32 y, f32 z, f32 rx)
  429. {
  430. bindstate = -1;
  431. mIdent(&model);
  432. mTranslate(&model, x, y, z);
  433. mRotX(&model, -rx);
  434. f32 mag = psp*32.f;
  435. if(mag > 0.4f)
  436. mag = 0.4f;
  437. mRotY(&model, mag);
  438. mMul(&modelview, &model, &view);
  439. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (f32*)&modelview.m[0][0]);
  440. glUniform1f(opacity_id, 1.0f);
  441. glUniform3f(color_id, 0.062f, 1.f, 0.873f);
  442. glBindBuffer(GL_ARRAY_BUFFER, mdlRightFlame.vid);
  443. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  444. glEnableVertexAttribArray(position_id);
  445. glBindBuffer(GL_ARRAY_BUFFER, mdlRightFlame.nid);
  446. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  447. glEnableVertexAttribArray(normal_id);
  448. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlRightFlame.iid);
  449. glDrawElements(GL_TRIANGLES, right_flame_numind, GL_UNSIGNED_SHORT, 0);
  450. }
  451. void rFace(f32 x, f32 y, f32 z, f32 rx)
  452. {
  453. bindstate = -1;
  454. mIdent(&model);
  455. mTranslate(&model, x, y, z);
  456. mRotX(&model, -xrot);
  457. mGetDirZ(&pfd, model);
  458. vInv(&pfd);
  459. const f32 dot = vDot(pfd, pld);
  460. if(dot < NECK_ANGLE)
  461. {
  462. mIdent(&model);
  463. mTranslate(&model, x, y, z);
  464. mRotX(&model, -lgr);
  465. }
  466. else
  467. {
  468. lgr = xrot;
  469. }
  470. mMul(&modelview, &model, &view);
  471. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (f32*)&modelview.m[0][0]);
  472. glUniform1f(opacity_id, 1.0f);
  473. glUniform3f(color_id, 1.f, 1.f, 1.f);
  474. glBindBuffer(GL_ARRAY_BUFFER, mdlFace.vid);
  475. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  476. glEnableVertexAttribArray(position_id);
  477. glBindBuffer(GL_ARRAY_BUFFER, mdlFace.nid);
  478. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  479. glEnableVertexAttribArray(normal_id);
  480. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlFace.iid);
  481. glDrawElements(GL_TRIANGLES, face_numind, GL_UNSIGNED_SHORT, 0);
  482. }
  483. void rBreak(f32 x, f32 y, f32 z, f32 rx)
  484. {
  485. bindstate = -1;
  486. mIdent(&model);
  487. mTranslate(&model, x, y, z);
  488. mRotX(&model, -xrot);
  489. vec dir;
  490. mGetDirZ(&dir, model);
  491. vInv(&dir);
  492. const f32 dot = vDot(dir, pld);
  493. if(dot < NECK_ANGLE)
  494. {
  495. mIdent(&model);
  496. mTranslate(&model, x, y, z);
  497. mRotX(&model, -lgr);
  498. }
  499. else
  500. {
  501. lgr = xrot;
  502. }
  503. mMul(&modelview, &model, &view);
  504. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (f32*)&modelview.m[0][0]);
  505. glUniform1f(opacity_id, 1.0f);
  506. glUniform3f(color_id, fone(0.644f+(1.f-pb)), fone(0.209f+(1.f-pb)), fone(0.f+(1.f-pb)));
  507. glBindBuffer(GL_ARRAY_BUFFER, mdlPbreak.vid);
  508. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  509. glEnableVertexAttribArray(position_id);
  510. glBindBuffer(GL_ARRAY_BUFFER, mdlPbreak.nid);
  511. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  512. glEnableVertexAttribArray(normal_id);
  513. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlPbreak.iid);
  514. glDrawElements(GL_TRIANGLES, pbreak_numind, GL_UNSIGNED_SHORT, 0);
  515. }
  516. void rShield(f32 x, f32 y, f32 z, f32 rx)
  517. {
  518. bindstate = -1;
  519. mIdent(&model);
  520. mTranslate(&model, x, y, z);
  521. mRotX(&model, -xrot);
  522. vec dir;
  523. mGetDirZ(&dir, model);
  524. vInv(&dir);
  525. const f32 dot = vDot(dir, pld);
  526. if(dot < NECK_ANGLE)
  527. {
  528. mIdent(&model);
  529. mTranslate(&model, x, y, z);
  530. mRotX(&model, -lgr);
  531. }
  532. else
  533. {
  534. lgr = xrot;
  535. }
  536. mMul(&modelview, &model, &view);
  537. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (f32*)&modelview.m[0][0]);
  538. glUniform1f(opacity_id, 1.0f);
  539. glUniform3f(color_id, fone(0.f+(1.f-ps)), fone(0.8f+(1.f-ps)), fone(0.28f+(1.f-ps)));
  540. glBindBuffer(GL_ARRAY_BUFFER, mdlPshield.vid);
  541. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  542. glEnableVertexAttribArray(position_id);
  543. glBindBuffer(GL_ARRAY_BUFFER, mdlPshield.nid);
  544. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  545. glEnableVertexAttribArray(normal_id);
  546. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlPshield.iid);
  547. glDrawElements(GL_TRIANGLES, pshield_numind, GL_UNSIGNED_SHORT, 0);
  548. }
  549. void rSlow(f32 x, f32 y, f32 z, f32 rx)
  550. {
  551. bindstate = -1;
  552. mIdent(&model);
  553. mTranslate(&model, x, y, z);
  554. mRotX(&model, -xrot);
  555. vec dir;
  556. mGetDirZ(&dir, model);
  557. vInv(&dir);
  558. const f32 dot = vDot(dir, pld);
  559. if(dot < NECK_ANGLE)
  560. {
  561. mIdent(&model);
  562. mTranslate(&model, x, y, z);
  563. mRotX(&model, -lgr);
  564. }
  565. else
  566. {
  567. lgr = xrot;
  568. }
  569. mMul(&modelview, &model, &view);
  570. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (f32*)&modelview.m[0][0]);
  571. glUniform1f(opacity_id, 1.0f);
  572. glUniform3f(color_id, fone(0.429f+(1.f-psl)), fone(0.f+(1.f-psl)), fone(0.8f+(1.f-psl)));
  573. glBindBuffer(GL_ARRAY_BUFFER, mdlPslow.vid);
  574. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  575. glEnableVertexAttribArray(position_id);
  576. glBindBuffer(GL_ARRAY_BUFFER, mdlPslow.nid);
  577. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  578. glEnableVertexAttribArray(normal_id);
  579. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlPslow.iid);
  580. glDrawElements(GL_TRIANGLES, pslow_numind, GL_UNSIGNED_SHORT, 0);
  581. }
  582. void rRepel(f32 x, f32 y, f32 z, f32 rx)
  583. {
  584. bindstate = -1;
  585. mIdent(&model);
  586. mTranslate(&model, x, y, z);
  587. mRotX(&model, -xrot);
  588. vec dir;
  589. mGetDirZ(&dir, model);
  590. vInv(&dir);
  591. const f32 dot = vDot(dir, pld);
  592. if(dot < NECK_ANGLE)
  593. {
  594. mIdent(&model);
  595. mTranslate(&model, x, y, z);
  596. mRotX(&model, -lgr);
  597. }
  598. else
  599. {
  600. lgr = xrot;
  601. }
  602. mMul(&modelview, &model, &view);
  603. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (f32*)&modelview.m[0][0]);
  604. glUniform1f(opacity_id, 1.0f);
  605. glUniform3f(color_id, fone(0.095f+(1.f-pre)), fone(0.069f+(1.f-pre)), fone(0.041f+(1.f-pre)));
  606. glBindBuffer(GL_ARRAY_BUFFER, mdlPrepel.vid);
  607. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  608. glEnableVertexAttribArray(position_id);
  609. glBindBuffer(GL_ARRAY_BUFFER, mdlPrepel.nid);
  610. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  611. glEnableVertexAttribArray(normal_id);
  612. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlPrepel.iid);
  613. glDrawElements(GL_TRIANGLES, prepel_numind, GL_UNSIGNED_SHORT, 0);
  614. }
  615. void rShieldElipse(f32 x, f32 y, f32 z, f32 rx, f32 opacity)
  616. {
  617. bindstate = -1;
  618. mIdent(&model);
  619. mTranslate(&model, x, y, z);
  620. mRotX(&model, -rx);
  621. mMul(&modelview, &model, &view);
  622. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (f32*)&modelview.m[0][0]);
  623. glUniform1f(opacity_id, opacity);
  624. glUniform3f(color_id, 0.f, 0.717, 0.8f);
  625. glBindBuffer(GL_ARRAY_BUFFER, mdlShield.vid);
  626. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  627. glEnableVertexAttribArray(position_id);
  628. glBindBuffer(GL_ARRAY_BUFFER, mdlShield.nid);
  629. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  630. glEnableVertexAttribArray(normal_id);
  631. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlShield.iid);
  632. glEnable(GL_BLEND);
  633. glDrawElements(GL_TRIANGLES, shield_numind, GL_UNSIGNED_SHORT, 0);
  634. glDisable(GL_BLEND);
  635. }
  636. void rPlayer(f32 x, f32 y, f32 z, f32 rx)
  637. {
  638. psp = vMag(pv);
  639. rLegs(x, y, z, rx);
  640. rBody(x, y, z, rx);
  641. rFuel(x, y, z, rx);
  642. rArms(x, y+2.6f, z, rx);
  643. uint lf=0, rf=0;
  644. if(keystate[0] == 1)
  645. rf = 1;
  646. if(keystate[1] == 1)
  647. lf = 1;
  648. if(keystate[2] == 1)
  649. rf = 1, lf = 1;
  650. if(keystate[3] == 1)
  651. rf = 1, lf = 1;
  652. if(keystate[4] == 1)
  653. rf = 1, lf = 1;
  654. if(keystate[5] == 1)
  655. rf = 1, lf = 1;
  656. if(lf == 1)
  657. rLeftFlame(x, y+2.6f, z, rx);
  658. if(rf == 1)
  659. rRightFlame(x, y+2.6f, z, rx);
  660. rFace(x, y+3.4f, z, rx);
  661. rBreak(x, y+3.4f, z, rx);
  662. rShield(x, y+3.4f, z, rx);
  663. rSlow(x, y+3.4f, z, rx);
  664. rRepel(x, y+3.4f, z, rx);
  665. if(so > 0.f)
  666. {
  667. const f32 ss = 1.f-(so*RECIP_MAX_ROCK_SCALE);
  668. if(ps == 0.f)
  669. {
  670. pf -= FUEL_DRAIN_RATE * ss * dt;
  671. pf = fzero(pf);
  672. }
  673. else
  674. {
  675. ps -= SHIELD_DRAIN_RATE * ss * dt;
  676. ps = fzero(ps);
  677. //pv = (vec){0.f,0.f,0.f};
  678. //vReflect(&pv, pv, pd);
  679. rShieldElipse(x, y+1.f, z, rx, fsat(ss));
  680. }
  681. //printf("s: %g\n", ps);
  682. }
  683. }
  684. //*************************************
  685. // game functions
  686. //*************************************
  687. void newGame(unsigned int seed)
  688. {
  689. srand(seed);
  690. char strts[16];
  691. timestamp(&strts[0]);
  692. printf("\n[%s] Game Start [%u].\n", strts, seed);
  693. glfwSetWindowTitle(window, "Space Miner");
  694. f32 FDGD = FAR_DISTANCE;
  695. #ifndef __arm__
  696. const f32 scalar = esRandFloat(8.f, 12.f);
  697. FDGD = (float)ARRAY_MAX / scalar;
  698. //printf("Far Distance Divisor: %g\n", scalar);
  699. #endif
  700. pp = (vec){0.f, 0.f, 0.f};
  701. pv = (vec){0.f, 0.f, 0.f};
  702. pd = (vec){0.f, 0.f, 0.f};
  703. pld = (vec){0.f, 0.f, 0.f};
  704. st = 0;
  705. lf = 100;
  706. ct = 0;
  707. pm = 0;
  708. so = 0.f;
  709. pr = 0.f;
  710. lgr = 0.f;
  711. pf = 1.f;
  712. pb = 1.f;
  713. ps = 1.f;
  714. psl = 0.f;
  715. pre = 0.f;
  716. psp = 0.f;
  717. for(uint i = 0; i < ARRAY_MAX; i++)
  718. {
  719. array_rocks[i].free = 0;
  720. array_rocks[i].scale = esRandFloat(0.1f, MAX_ROCK_SCALE);
  721. array_rocks[i].pos.x = esRandFloat(-FDGD, FDGD);
  722. array_rocks[i].pos.y = esRandFloat(-FDGD, FDGD);
  723. array_rocks[i].pos.z = esRandFloat(-FDGD, FDGD);
  724. array_rocks[i].rnd = esRand(0, 1000);
  725. array_rocks[i].rndf = esRandFloat(0.05f, 0.3f);
  726. if(esRand(0, 1000) < 500)
  727. {
  728. array_rocks[i].qshield = esRandFloat(0.f, 1.f);
  729. array_rocks[i].qbreak = esRandFloat(0.f, 1.f);
  730. array_rocks[i].qslow = esRandFloat(0.f, 1.f);
  731. array_rocks[i].qrepel = esRandFloat(0.f, 1.f);
  732. array_rocks[i].qfuel = esRandFloat(0.f, 1.f);
  733. }
  734. else
  735. {
  736. array_rocks[i].qshield = 0.f;
  737. array_rocks[i].qbreak = 0.f;
  738. array_rocks[i].qslow = 0.f;
  739. array_rocks[i].qrepel = 0.f;
  740. array_rocks[i].qfuel = 0.f;
  741. array_rocks[i].nores = 1;
  742. }
  743. for(uint j = 0; j < 717; j += 3)
  744. {
  745. uint set = 0;
  746. #define CLR_CHANCE 0.01f
  747. // break
  748. if(esRandFloat(0.f, 1.f) < array_rocks[i].qbreak*CLR_CHANCE)
  749. {
  750. array_rocks[i].colors[j] = 0.644f;
  751. array_rocks[i].colors[j+1] = 0.209f;
  752. array_rocks[i].colors[j+2] = 0.f;
  753. set = 1;
  754. }
  755. // shield
  756. if(set == 0 && esRandFloat(0.f, 1.f) < array_rocks[i].qshield*CLR_CHANCE)
  757. {
  758. array_rocks[i].colors[j] = 0.f;
  759. array_rocks[i].colors[j+1] = 0.8f;
  760. array_rocks[i].colors[j+2] = 0.28f;
  761. set = 1;
  762. }
  763. // slow
  764. if(set == 0 && esRandFloat(0.f, 1.f) < array_rocks[i].qslow*CLR_CHANCE)
  765. {
  766. array_rocks[i].colors[j] = 0.429f;
  767. array_rocks[i].colors[j+1] = 0.f;
  768. array_rocks[i].colors[j+2] = 0.8f;
  769. set = 1;
  770. }
  771. // repel
  772. if(set == 0 && esRandFloat(0.f, 1.f) < array_rocks[i].qrepel*CLR_CHANCE)
  773. {
  774. array_rocks[i].colors[j] = 0.095f;
  775. array_rocks[i].colors[j+1] = 0.069f;
  776. array_rocks[i].colors[j+2] = 0.041f;
  777. set = 1;
  778. }
  779. // fuel
  780. if(set == 0 && esRandFloat(0.f, 1.f) < array_rocks[i].qfuel*CLR_CHANCE)
  781. {
  782. array_rocks[i].colors[j] = 0.062f;
  783. array_rocks[i].colors[j+1] = 1.f;
  784. array_rocks[i].colors[j+2] = 0.873f;
  785. set = 1;
  786. }
  787. // else
  788. if(set == 0)
  789. {
  790. array_rocks[i].colors[j] = ROCK_DARKNESS;
  791. array_rocks[i].colors[j+1] = ROCK_DARKNESS;
  792. array_rocks[i].colors[j+2] = ROCK_DARKNESS;
  793. }
  794. }
  795. vRuv(&array_rocks[i].vel);
  796. }
  797. st = t;
  798. }
  799. //*************************************
  800. // update & render
  801. //*************************************
  802. void main_loop()
  803. {
  804. //*************************************
  805. // time delta for interpolation
  806. //*************************************
  807. static double lt = 0;
  808. dt = t-lt;
  809. lt = t;
  810. //*************************************
  811. // keystates
  812. //*************************************
  813. if(pf == 0.f) // disable thrust control on fuel empty
  814. memset(&keystate[0], 0x00, sizeof(uint)*6);
  815. if(keystate[0] == 1)
  816. {
  817. pr += 3.f * dt;
  818. lgr = pr;
  819. pf -= FUEL_DRAIN_RATE * dt;
  820. pf = fzero(pf);
  821. }
  822. if(keystate[1] == 1)
  823. {
  824. pr -= 3.f * dt;
  825. lgr = pr;
  826. pf -= FUEL_DRAIN_RATE * dt;
  827. pf = fzero(pf);
  828. }
  829. if(keystate[2] == 1)
  830. {
  831. ct = 1;
  832. pf -= FUEL_DRAIN_RATE * dt;
  833. pf = fzero(pf);
  834. }
  835. if(keystate[3] == 1)
  836. {
  837. ct = 2;
  838. pf -= FUEL_DRAIN_RATE * dt;
  839. pf = fzero(pf);
  840. }
  841. if(keystate[4] == 1)
  842. {
  843. pv.y -= THRUST_POWER * dt;
  844. pf -= FUEL_DRAIN_RATE * dt;
  845. pf = fzero(pf);
  846. }
  847. if(keystate[5] == 1)
  848. {
  849. pv.y += THRUST_POWER * dt;
  850. pf -= FUEL_DRAIN_RATE * dt;
  851. pf = fzero(pf);
  852. }
  853. static double ltut = 3.0;
  854. const uint nf = pf*100.f;
  855. if(nf != lf)
  856. {
  857. char strts[16];
  858. timestamp(&strts[0]);
  859. printf("[%s] Fuel: %.2f - Speed: %g\n", strts, pf, psp*100.f);
  860. }
  861. if(nf != lf || t > ltut)
  862. {
  863. timeTaken(1);
  864. char title[256];
  865. //sprintf(title, "Space Miner - Fuel %u - Mined %u - Time %s", nf, pm, tts);
  866. sprintf(title, "| %s | Fuel %u | Speed %.2f | Mined %u |", tts, (uint)(pf*100.f), psp*100.f, pm);
  867. glfwSetWindowTitle(window, title);
  868. lf = nf;
  869. ltut = t + 3.0;
  870. }
  871. // increment player direction
  872. if(ct > 0)
  873. {
  874. vec inc;
  875. if(ct == 1)
  876. vMulS(&inc, pd, THRUST_POWER * dt);
  877. else if(ct == 2)
  878. vMulS(&inc, pd, -THRUST_POWER * dt);
  879. vAdd(&pv, pv, inc);
  880. }
  881. vAdd(&pp, pp, pv);
  882. //*************************************
  883. // camera
  884. //*************************************
  885. if(focus_cursor == 1)
  886. {
  887. glfwGetCursorPos(window, &x, &y);
  888. xrot += (lx-x)*sens;
  889. yrot += (ly-y)*sens;
  890. if(yrot > 0.7f)
  891. yrot = 0.7f;
  892. if(yrot < -0.7f)
  893. yrot = -0.7f;
  894. lx = x, ly = y;
  895. }
  896. mIdent(&view);
  897. mTranslate(&view, 0.f, -1.5f, zoom);
  898. mRotate(&view, yrot, 1.f, 0.f, 0.f);
  899. mRotate(&view, xrot, 0.f, 1.f, 0.f);
  900. mTranslate(&view, -pp.x, -pp.y, -pp.z);
  901. //*************************************
  902. // begin render
  903. //*************************************
  904. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  905. //*************************************
  906. // main render
  907. //*************************************
  908. // render player
  909. shadeLambert1(&position_id, &projection_id, &modelview_id, &lightpos_id, &normal_id, &color_id, &opacity_id);
  910. glUniformMatrix4fv(projection_id, 1, GL_FALSE, (f32*)&projection.m[0][0]);
  911. glUniform3f(lightpos_id, lightpos.x, lightpos.y, lightpos.z);
  912. rPlayer(pp.x, pp.y, pp.z, pr);
  913. // render asteroids
  914. shadeLambert3(&position_id, &projection_id, &modelview_id, &lightpos_id, &normal_id, &color_id, &opacity_id);
  915. glUniformMatrix4fv(projection_id, 1, GL_FALSE, (f32*)&projection.m[0][0]);
  916. glUniform3f(lightpos_id, lightpos.x, lightpos.y, lightpos.z);
  917. so = 0.f;
  918. for(uint i = 0; i < ARRAY_MAX; i++)
  919. {
  920. if(array_rocks[i].free != 1)
  921. {
  922. vec inc;
  923. vMulS(&inc, array_rocks[i].vel, dt);
  924. vAdd(&array_rocks[i].pos, array_rocks[i].pos, inc);
  925. const f32 dist = vDist(pp, array_rocks[i].pos);
  926. if(dist < 10.f + array_rocks[i].scale)
  927. if(so == 0.f || dist < so){so = dist;}
  928. rRock(i, dist);
  929. }
  930. }
  931. //*************************************
  932. // swap buffers / display render
  933. //*************************************
  934. glfwSwapBuffers(window);
  935. }
  936. //*************************************
  937. // Input Handelling
  938. //*************************************
  939. static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
  940. {
  941. // control
  942. if(action == GLFW_PRESS)
  943. {
  944. if(key == GLFW_KEY_A || key == GLFW_KEY_LEFT){ keystate[0] = 1; }
  945. else if(key == GLFW_KEY_D || key == GLFW_KEY_RIGHT){ keystate[1] = 1; }
  946. else if(key == GLFW_KEY_W || key == GLFW_KEY_UP){ keystate[2] = 1; }
  947. //else if(key == GLFW_KEY_S){ keystate[3] = 1; }
  948. else if(key == GLFW_KEY_LEFT_SHIFT){ keystate[4] = 1; }
  949. else if(key == GLFW_KEY_SPACE){ keystate[5] = 1; }
  950. // new game
  951. else if(key == GLFW_KEY_N)
  952. {
  953. // end
  954. timeTaken(0);
  955. char strts[16];
  956. timestamp(&strts[0]);
  957. printf("[%s] Stats: Fuel %.2f - Break %.2f - Shield %.2f - Stop %.2f - Repel %.2f - Mined %u\n", strts, pf, pb, ps, psl, pre, pm);
  958. printf("[%s] Time-Taken: %s or %g Seconds\n", strts, tts, t-st);
  959. printf("[%s] Game End.\n", strts);
  960. // new
  961. newGame(time(0));
  962. }
  963. // stats
  964. else if(key == GLFW_KEY_P)
  965. {
  966. char strts[16];
  967. timestamp(&strts[0]);
  968. printf("[%s] Stats: Fuel %.2f - Break %.2f - Shield %.2f - Stop %.2f - Repel %.2f - Mined %u\n", strts, pf, pb, ps, psl, pre, pm);
  969. }
  970. // break rocks
  971. else if(key == GLFW_KEY_Q && pb > 0.f)
  972. {
  973. for(uint i = 0; i < ARRAY_MAX; i++)
  974. {
  975. if(array_rocks[i].free == 0)
  976. {
  977. const f32 dist = vDist(pp, array_rocks[i].pos);
  978. if(dist < 30.f + array_rocks[i].scale)
  979. {
  980. pb -= 0.06f;
  981. pb = fzero(pb); // hack, yes user could mine beyond pb == 0.f in this loop, take it as a last chance
  982. pf += array_rocks[i].qfuel * REFINARY_YEILD * 3.f;
  983. pb += array_rocks[i].qbreak * REFINARY_YEILD;
  984. ps += array_rocks[i].qshield * REFINARY_YEILD;
  985. psl += array_rocks[i].qslow * REFINARY_YEILD;
  986. pre += array_rocks[i].qrepel * REFINARY_YEILD;
  987. pf = fone(pf);
  988. pb = fone(pb);
  989. ps = fone(ps);
  990. psl = fone(psl);
  991. pre = fone(pre);
  992. array_rocks[i].free = 2;
  993. pm++;
  994. timeTaken(1);
  995. char title[256];
  996. //sprintf(title, "Space Miner - Fuel %u - Mined %u - Time %s", (uint)(pf*100.f), pm, tts);
  997. sprintf(title, "| %s | Fuel %u | Speed %.2f | Mined %u |", tts, (uint)(pf*100.f), psp*100.f, pm);
  998. glfwSetWindowTitle(window, title);
  999. char strts[16];
  1000. timestamp(&strts[0]);
  1001. printf("[%s] Break %.2f - Shield %.2f - Stop %.2f - Repel %.2f\n", strts, pb, ps, psl, pre);
  1002. printf("[%s] Mined: %u\n", strts, pm);
  1003. }
  1004. }
  1005. }
  1006. }
  1007. // stop all rocks
  1008. else if(key == GLFW_KEY_E && psl > 0.f)
  1009. {
  1010. for(uint i = 0; i < ARRAY_MAX; i++)
  1011. {
  1012. if(array_rocks[i].free == 0 && array_rocks[i].rndf != 0.f)
  1013. {
  1014. const f32 dist = vDist(pp, array_rocks[i].pos);
  1015. if(dist < 333.f + array_rocks[i].scale)
  1016. {
  1017. psl -= 0.06f;
  1018. if(psl <= 0.f)
  1019. {
  1020. psl = 0.f;
  1021. break;
  1022. }
  1023. array_rocks[i].vel = (vec){0.f, 0.f, 0.f};
  1024. array_rocks[i].rndf = 0.f;
  1025. char strts[16];
  1026. timestamp(&strts[0]);
  1027. printf("[%s] Repel %.2f\n", strts, psl);
  1028. }
  1029. }
  1030. }
  1031. }
  1032. // repel rock
  1033. else if(key == GLFW_KEY_R && pre > 0.f)
  1034. {
  1035. for(uint i = 0; i < ARRAY_MAX; i++)
  1036. {
  1037. if(array_rocks[i].free == 0)
  1038. {
  1039. const f32 dist = vDist(pp, array_rocks[i].pos);
  1040. if(dist < 30.f + array_rocks[i].scale)
  1041. {
  1042. //vRuv(&array_rocks[i].vel);
  1043. pre -= 0.06f;
  1044. if(pre <= 0.f)
  1045. {
  1046. pre = 0.f;
  1047. break;
  1048. }
  1049. array_rocks[i].vel = pfd;
  1050. vMulS(&array_rocks[i].vel, array_rocks[i].vel, 42.f);
  1051. char strts[16];
  1052. timestamp(&strts[0]);
  1053. printf("[%s] Stop %.2f\n", strts, pre);
  1054. }
  1055. }
  1056. }
  1057. }
  1058. // toggle mouse focus
  1059. if(key == GLFW_KEY_ESCAPE)
  1060. {
  1061. focus_cursor = 0;
  1062. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
  1063. glfwGetCursorPos(window, &lx, &ly);
  1064. }
  1065. }
  1066. else if(action == GLFW_RELEASE)
  1067. {
  1068. if(key == GLFW_KEY_A || key == GLFW_KEY_LEFT){ keystate[0] = 0; }
  1069. else if(key == GLFW_KEY_D || key == GLFW_KEY_RIGHT){ keystate[1] = 0; }
  1070. else if(key == GLFW_KEY_W || key == GLFW_KEY_UP){ keystate[2] = 0; }
  1071. //else if(key == GLFW_KEY_S){ keystate[3] = 0; }
  1072. else if(key == GLFW_KEY_LEFT_SHIFT){ keystate[4] = 0; }
  1073. else if(key == GLFW_KEY_SPACE){ keystate[5] = 0; }
  1074. }
  1075. // show average fps
  1076. if(key == GLFW_KEY_F)
  1077. {
  1078. if(t-lfct > 2.0)
  1079. {
  1080. char strts[16];
  1081. timestamp(&strts[0]);
  1082. printf("[%s] FPS: %g\n", strts, fc/(t-lfct));
  1083. lfct = t;
  1084. fc = 0;
  1085. }
  1086. }
  1087. }
  1088. void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
  1089. {
  1090. if(yoffset < 0.0)
  1091. zoom += 0.06f * zoom;
  1092. else
  1093. zoom -= 0.06f * zoom;
  1094. if(zoom > -15.f){zoom = -15.f;}
  1095. }
  1096. void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
  1097. {
  1098. if(action == GLFW_PRESS)
  1099. {
  1100. if(focus_cursor == 0)
  1101. {
  1102. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
  1103. glfwGetCursorPos(window, &lx, &ly);
  1104. focus_cursor = 1;
  1105. }
  1106. if(button == GLFW_MOUSE_BUTTON_LEFT && pb > 0.f)
  1107. {
  1108. for(uint i = 0; i < ARRAY_MAX; i++)
  1109. {
  1110. if(array_rocks[i].free == 0)
  1111. {
  1112. const f32 dist = vDist(pp, array_rocks[i].pos);
  1113. if(dist < 30.f + array_rocks[i].scale)
  1114. {
  1115. pb -= 0.06f;
  1116. pb = fzero(pb); // hack, yes user could mine beyond pb == 0.f in this loop, take it as a last chance
  1117. pf += array_rocks[i].qfuel * REFINARY_YEILD * 3.f;
  1118. pb += array_rocks[i].qbreak * REFINARY_YEILD;
  1119. ps += array_rocks[i].qshield * REFINARY_YEILD;
  1120. psl += array_rocks[i].qslow * REFINARY_YEILD;
  1121. pre += array_rocks[i].qrepel * REFINARY_YEILD;
  1122. pf = fone(pf);
  1123. pb = fone(pb);
  1124. ps = fone(ps);
  1125. psl = fone(psl);
  1126. pre = fone(pre);
  1127. array_rocks[i].free = 2;
  1128. pm++;
  1129. timeTaken(1);
  1130. char title[256];
  1131. //sprintf(title, "Space Miner - Fuel %u - Mined %u - Time %s", (uint)(pf*100.f), pm, tts);
  1132. sprintf(title, "| %s | Fuel %u | Speed %.2f | Mined %u |", tts, (uint)(pf*100.f), psp*100.f, pm);
  1133. glfwSetWindowTitle(window, title);
  1134. char strts[16];
  1135. timestamp(&strts[0]);
  1136. printf("[%s] Break %.2f - Shield %.2f - Stop %.2f - Repel %.2f\n", strts, pb, ps, psl, pre);
  1137. printf("[%s] Mined: %u\n", strts, pm);
  1138. }
  1139. }
  1140. }
  1141. }
  1142. if(button == GLFW_MOUSE_BUTTON_RIGHT && pre > 0.f)
  1143. {
  1144. for(uint i = 0; i < ARRAY_MAX; i++)
  1145. {
  1146. if(array_rocks[i].free == 0)
  1147. {
  1148. const f32 dist = vDist(pp, array_rocks[i].pos);
  1149. if(dist < 30.f + array_rocks[i].scale)
  1150. {
  1151. //vRuv(&array_rocks[i].vel);
  1152. pre -= 0.06f;
  1153. if(pre <= 0.f)
  1154. {
  1155. pre = 0.f;
  1156. break;
  1157. }
  1158. array_rocks[i].vel = pfd;
  1159. vMulS(&array_rocks[i].vel, array_rocks[i].vel, 42.f);
  1160. char strts[16];
  1161. timestamp(&strts[0]);
  1162. printf("[%s] Repel %.2f\n", strts, pre);
  1163. }
  1164. }
  1165. }
  1166. }
  1167. if(button == GLFW_MOUSE_BUTTON_4 && psl > 0.f)
  1168. {
  1169. for(uint i = 0; i < ARRAY_MAX; i++)
  1170. {
  1171. if(array_rocks[i].free == 0 && array_rocks[i].rndf != 0.f)
  1172. {
  1173. const f32 dist = vDist(pp, array_rocks[i].pos);
  1174. if(dist < 333.f + array_rocks[i].scale)
  1175. {
  1176. psl -= 0.06f;
  1177. if(psl <= 0.f)
  1178. {
  1179. psl = 0.f;
  1180. break;
  1181. }
  1182. array_rocks[i].vel = (vec){0.f, 0.f, 0.f};
  1183. array_rocks[i].rndf = 0.f;
  1184. char strts[16];
  1185. timestamp(&strts[0]);
  1186. printf("[%s] Stop %.2f\n", strts, psl);
  1187. }
  1188. }
  1189. }
  1190. }
  1191. }
  1192. }
  1193. void window_size_callback(GLFWwindow* window, int width, int height)
  1194. {
  1195. winw = width;
  1196. winh = height;
  1197. glViewport(0, 0, winw, winh);
  1198. aspect = (f32)winw / (f32)winh;
  1199. ww = winw;
  1200. wh = winh;
  1201. rww = 1.0/ww;
  1202. rwh = 1.0/wh;
  1203. ww2 = ww/2.0;
  1204. wh2 = wh/2.0;
  1205. uw = (double)aspect / ww;
  1206. uh = 1.0/wh;
  1207. uw2 = (double)aspect / ww2;
  1208. uh2 = 1.0/wh2;
  1209. mIdent(&projection);
  1210. mPerspective(&projection, 60.0f, aspect, 1.0f, FAR_DISTANCE);
  1211. }
  1212. //*************************************
  1213. // Process Entry Point
  1214. //*************************************
  1215. int main(int argc, char** argv)
  1216. {
  1217. // allow custom msaa level
  1218. int msaa = 16;
  1219. if(argc >= 2){msaa = atoi(argv[1]);}
  1220. // help
  1221. printf("----\n");
  1222. printf("Space Miner\n");
  1223. printf("----\n");
  1224. printf("James William Fletcher (github.com/mrbid)\n");
  1225. printf("----\n");
  1226. printf("There is only one command line argument, and that is the MSAA level 0-16.\n");
  1227. printf("----\n");
  1228. printf("~ Keyboard Input:\n");
  1229. printf("ESCAPE = Release mouse lock\n");
  1230. printf("F = FPS to console\n");
  1231. printf("P = Player stats to console\n");
  1232. printf("N = New Game\n");
  1233. printf("Q = Break Asteroid\n");
  1234. printf("E = Stop all nearby Asteroids\n");
  1235. printf("R = Repel all nearby Asteroids\n");
  1236. printf("W = Thrust Forward\n");
  1237. printf("A = Turn Left\n");
  1238. printf("D = Turn Right\n");
  1239. printf("Shift = Thrust Down\n");
  1240. printf("Space = Thrust Up\n");
  1241. printf("----\n");
  1242. printf("~ Mouse Input:\n");
  1243. printf("Left Click = Break Asteroid\n");
  1244. printf("Right Click = Repel Asteroid\n");
  1245. printf("Mouse 4 Click = Stop all Asteroids nearby\n");
  1246. printf("Scroll = Zoom in/out\n");
  1247. printf("----\n");
  1248. // init glfw
  1249. if(!glfwInit()){exit(EXIT_FAILURE);}
  1250. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
  1251. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
  1252. glfwWindowHint(GLFW_SAMPLES, msaa);
  1253. window = glfwCreateWindow(winw, winh, "Space Miner", NULL, NULL);
  1254. if(!window)
  1255. {
  1256. glfwTerminate();
  1257. exit(EXIT_FAILURE);
  1258. }
  1259. const GLFWvidmode* desktop = glfwGetVideoMode(glfwGetPrimaryMonitor());
  1260. glfwSetWindowPos(window, (desktop->width/2)-(winw/2), (desktop->height/2)-(winh/2)); // center window on desktop
  1261. glfwSetWindowSizeCallback(window, window_size_callback);
  1262. glfwSetKeyCallback(window, key_callback);
  1263. glfwSetMouseButtonCallback(window, mouse_button_callback);
  1264. glfwSetScrollCallback(window, scroll_callback);
  1265. glfwMakeContextCurrent(window);
  1266. gladLoadGL(glfwGetProcAddress);
  1267. glfwSwapInterval(1); // 0 for immediate updates, 1 for updates synchronized with the vertical retrace, -1 for adaptive vsync
  1268. // set icon
  1269. glfwSetWindowIcon(window, 1, &(GLFWimage){16, 16, (unsigned char*)&icon_image.pixel_data});
  1270. //*************************************
  1271. // projection
  1272. //*************************************
  1273. window_size_callback(window, winw, winh);
  1274. //*************************************
  1275. // bind vertex and index buffers
  1276. //*************************************
  1277. // ***** BIND FACE *****
  1278. esBind(GL_ARRAY_BUFFER, &mdlFace.vid, face_vertices, sizeof(face_vertices), GL_STATIC_DRAW);
  1279. esBind(GL_ARRAY_BUFFER, &mdlFace.nid, face_normals, sizeof(face_normals), GL_STATIC_DRAW);
  1280. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlFace.iid, face_indices, sizeof(face_indices), GL_STATIC_DRAW);
  1281. // ***** BIND BODY *****
  1282. esBind(GL_ARRAY_BUFFER, &mdlBody.vid, body_vertices, sizeof(body_vertices), GL_STATIC_DRAW);
  1283. esBind(GL_ARRAY_BUFFER, &mdlBody.nid, body_normals, sizeof(body_normals), GL_STATIC_DRAW);
  1284. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlBody.iid, body_indices, sizeof(body_indices), GL_STATIC_DRAW);
  1285. // ***** BIND ARMS *****
  1286. esBind(GL_ARRAY_BUFFER, &mdlArms.vid, arms_vertices, sizeof(arms_vertices), GL_STATIC_DRAW);
  1287. esBind(GL_ARRAY_BUFFER, &mdlArms.nid, arms_normals, sizeof(arms_normals), GL_STATIC_DRAW);
  1288. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlArms.iid, arms_indices, sizeof(arms_indices), GL_STATIC_DRAW);
  1289. // ***** BIND LEFT FLAME *****
  1290. esBind(GL_ARRAY_BUFFER, &mdlLeftFlame.vid, left_flame_vertices, sizeof(left_flame_vertices), GL_STATIC_DRAW);
  1291. esBind(GL_ARRAY_BUFFER, &mdlLeftFlame.nid, left_flame_normals, sizeof(left_flame_normals), GL_STATIC_DRAW);
  1292. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlLeftFlame.iid, left_flame_indices, sizeof(left_flame_indices), GL_STATIC_DRAW);
  1293. // ***** BIND RIGHT FLAME *****
  1294. esBind(GL_ARRAY_BUFFER, &mdlRightFlame.vid, right_flame_vertices, sizeof(right_flame_vertices), GL_STATIC_DRAW);
  1295. esBind(GL_ARRAY_BUFFER, &mdlRightFlame.nid, right_flame_normals, sizeof(right_flame_normals), GL_STATIC_DRAW);
  1296. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlRightFlame.iid, right_flame_indices, sizeof(right_flame_indices), GL_STATIC_DRAW);
  1297. // ***** BIND LEGS *****
  1298. esBind(GL_ARRAY_BUFFER, &mdlLegs.vid, legs_vertices, sizeof(legs_vertices), GL_STATIC_DRAW);
  1299. esBind(GL_ARRAY_BUFFER, &mdlLegs.nid, legs_normals, sizeof(legs_normals), GL_STATIC_DRAW);
  1300. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlLegs.iid, legs_indices, sizeof(legs_indices), GL_STATIC_DRAW);
  1301. // ***** BIND FUEL *****
  1302. esBind(GL_ARRAY_BUFFER, &mdlFuel.vid, fuel_vertices, sizeof(fuel_vertices), GL_STATIC_DRAW);
  1303. esBind(GL_ARRAY_BUFFER, &mdlFuel.nid, fuel_normals, sizeof(fuel_normals), GL_STATIC_DRAW);
  1304. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlFuel.iid, fuel_indices, sizeof(fuel_indices), GL_STATIC_DRAW);
  1305. // ***** BIND SHIELD *****
  1306. esBind(GL_ARRAY_BUFFER, &mdlShield.vid, shield_vertices, sizeof(shield_vertices), GL_STATIC_DRAW);
  1307. esBind(GL_ARRAY_BUFFER, &mdlShield.nid, shield_normals, sizeof(shield_normals), GL_STATIC_DRAW);
  1308. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlShield.iid, shield_indices, sizeof(shield_indices), GL_STATIC_DRAW);
  1309. // ***** BIND P-BREAK *****
  1310. esBind(GL_ARRAY_BUFFER, &mdlPbreak.vid, pbreak_vertices, sizeof(pbreak_vertices), GL_STATIC_DRAW);
  1311. esBind(GL_ARRAY_BUFFER, &mdlPbreak.nid, pbreak_normals, sizeof(pbreak_normals), GL_STATIC_DRAW);
  1312. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlPbreak.iid, pbreak_indices, sizeof(pbreak_indices), GL_STATIC_DRAW);
  1313. // ***** BIND P-SHIELD *****
  1314. esBind(GL_ARRAY_BUFFER, &mdlPshield.vid, pshield_vertices, sizeof(pshield_vertices), GL_STATIC_DRAW);
  1315. esBind(GL_ARRAY_BUFFER, &mdlPshield.nid, pshield_normals, sizeof(pshield_normals), GL_STATIC_DRAW);
  1316. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlPshield.iid, pshield_indices, sizeof(pshield_indices), GL_STATIC_DRAW);
  1317. // ***** BIND P-SLOW *****
  1318. esBind(GL_ARRAY_BUFFER, &mdlPslow.vid, pslow_vertices, sizeof(pslow_vertices), GL_STATIC_DRAW);
  1319. esBind(GL_ARRAY_BUFFER, &mdlPslow.nid, pslow_normals, sizeof(pslow_normals), GL_STATIC_DRAW);
  1320. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlPslow.iid, pslow_indices, sizeof(pslow_indices), GL_STATIC_DRAW);
  1321. // ***** BIND P-REPEL *****
  1322. esBind(GL_ARRAY_BUFFER, &mdlPrepel.vid, prepel_vertices, sizeof(prepel_vertices), GL_STATIC_DRAW);
  1323. esBind(GL_ARRAY_BUFFER, &mdlPrepel.nid, prepel_normals, sizeof(prepel_normals), GL_STATIC_DRAW);
  1324. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlPrepel.iid, prepel_indices, sizeof(prepel_indices), GL_STATIC_DRAW);
  1325. /// ---
  1326. // ***** BIND ROCK1 *****
  1327. esBind(GL_ARRAY_BUFFER, &mdlRock[0].vid, rock1_vertices, sizeof(rock1_vertices), GL_STATIC_DRAW);
  1328. esBind(GL_ARRAY_BUFFER, &mdlRock[0].nid, rock1_normals, sizeof(rock1_normals), GL_STATIC_DRAW);
  1329. esBind(GL_ARRAY_BUFFER, &mdlRock[0].cid, rock1_colors, sizeof(rock1_colors), GL_STATIC_DRAW);
  1330. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlRock[0].iid, rock1_indices, sizeof(rock1_indices), GL_STATIC_DRAW);
  1331. // ***** BIND ROCK2 *****
  1332. esBind(GL_ARRAY_BUFFER, &mdlRock[1].vid, rock2_vertices, sizeof(rock2_vertices), GL_STATIC_DRAW);
  1333. esBind(GL_ARRAY_BUFFER, &mdlRock[1].nid, rock2_normals, sizeof(rock2_normals), GL_STATIC_DRAW);
  1334. esBind(GL_ARRAY_BUFFER, &mdlRock[1].cid, rock2_colors, sizeof(rock2_colors), GL_STATIC_DRAW);
  1335. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlRock[1].iid, rock2_indices, sizeof(rock2_indices), GL_STATIC_DRAW);
  1336. // ***** BIND ROCK3 *****
  1337. esBind(GL_ARRAY_BUFFER, &mdlRock[2].vid, rock3_vertices, sizeof(rock3_vertices), GL_STATIC_DRAW);
  1338. esBind(GL_ARRAY_BUFFER, &mdlRock[2].nid, rock3_normals, sizeof(rock3_normals), GL_STATIC_DRAW);
  1339. esBind(GL_ARRAY_BUFFER, &mdlRock[2].cid, rock3_colors, sizeof(rock3_colors), GL_STATIC_DRAW);
  1340. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlRock[2].iid, rock3_indices, sizeof(rock3_indices), GL_STATIC_DRAW);
  1341. // ***** BIND ROCK4 *****
  1342. esBind(GL_ARRAY_BUFFER, &mdlRock[3].vid, rock4_vertices, sizeof(rock4_vertices), GL_STATIC_DRAW);
  1343. esBind(GL_ARRAY_BUFFER, &mdlRock[3].nid, rock4_normals, sizeof(rock4_normals), GL_STATIC_DRAW);
  1344. esBind(GL_ARRAY_BUFFER, &mdlRock[3].cid, rock4_colors, sizeof(rock4_colors), GL_STATIC_DRAW);
  1345. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlRock[3].iid, rock4_indices, sizeof(rock4_indices), GL_STATIC_DRAW);
  1346. // ***** BIND ROCK5 *****
  1347. esBind(GL_ARRAY_BUFFER, &mdlRock[4].vid, rock5_vertices, sizeof(rock5_vertices), GL_STATIC_DRAW);
  1348. esBind(GL_ARRAY_BUFFER, &mdlRock[4].nid, rock5_normals, sizeof(rock5_normals), GL_STATIC_DRAW);
  1349. esBind(GL_ARRAY_BUFFER, &mdlRock[4].cid, rock5_colors, sizeof(rock5_colors), GL_STATIC_DRAW);
  1350. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlRock[4].iid, rock5_indices, sizeof(rock5_indices), GL_STATIC_DRAW);
  1351. // ***** BIND ROCK6 *****
  1352. esBind(GL_ARRAY_BUFFER, &mdlRock[5].vid, rock6_vertices, sizeof(rock6_vertices), GL_STATIC_DRAW);
  1353. esBind(GL_ARRAY_BUFFER, &mdlRock[5].nid, rock6_normals, sizeof(rock6_normals), GL_STATIC_DRAW);
  1354. esBind(GL_ARRAY_BUFFER, &mdlRock[5].cid, rock6_colors, sizeof(rock6_colors), GL_STATIC_DRAW);
  1355. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlRock[5].iid, rock6_indices, sizeof(rock6_indices), GL_STATIC_DRAW);
  1356. // ***** BIND ROCK7 *****
  1357. esBind(GL_ARRAY_BUFFER, &mdlRock[6].vid, rock7_vertices, sizeof(rock7_vertices), GL_STATIC_DRAW);
  1358. esBind(GL_ARRAY_BUFFER, &mdlRock[6].nid, rock7_normals, sizeof(rock7_normals), GL_STATIC_DRAW);
  1359. esBind(GL_ARRAY_BUFFER, &mdlRock[6].cid, rock7_colors, sizeof(rock7_colors), GL_STATIC_DRAW);
  1360. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlRock[6].iid, rock7_indices, sizeof(rock7_indices), GL_STATIC_DRAW);
  1361. // ***** BIND ROCK8 *****
  1362. esBind(GL_ARRAY_BUFFER, &mdlRock[7].vid, rock8_vertices, sizeof(rock8_vertices), GL_STATIC_DRAW);
  1363. esBind(GL_ARRAY_BUFFER, &mdlRock[7].nid, rock8_normals, sizeof(rock8_normals), GL_STATIC_DRAW);
  1364. esBind(GL_ARRAY_BUFFER, &mdlRock[7].cid, rock8_colors, sizeof(rock8_colors), GL_STATIC_DRAW);
  1365. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlRock[7].iid, rock8_indices, sizeof(rock8_indices), GL_STATIC_DRAW);
  1366. // ***** BIND ROCK9 *****
  1367. esBind(GL_ARRAY_BUFFER, &mdlRock[8].vid, rock9_vertices, sizeof(rock9_vertices), GL_STATIC_DRAW);
  1368. esBind(GL_ARRAY_BUFFER, &mdlRock[8].nid, rock9_normals, sizeof(rock9_normals), GL_STATIC_DRAW);
  1369. esBind(GL_ARRAY_BUFFER, &mdlRock[8].cid, rock9_colors, sizeof(rock9_colors), GL_STATIC_DRAW);
  1370. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlRock[8].iid, rock9_indices, sizeof(rock9_indices), GL_STATIC_DRAW);
  1371. //*************************************
  1372. // compile & link shader programs
  1373. //*************************************
  1374. makeLambert1();
  1375. makeLambert3();
  1376. //*************************************
  1377. // configure render options
  1378. //*************************************
  1379. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  1380. glEnable(GL_CULL_FACE);
  1381. glEnable(GL_DEPTH_TEST);
  1382. glClearColor(0.f, 0.f, 0.f, 0.f);
  1383. //*************************************
  1384. // execute update / render loop
  1385. //*************************************
  1386. // init
  1387. newGame(NEWGAME_SEED);
  1388. // reset
  1389. t = glfwGetTime();
  1390. lfct = t;
  1391. // event loop
  1392. while(!glfwWindowShouldClose(window))
  1393. {
  1394. t = glfwGetTime();
  1395. glfwPollEvents();
  1396. main_loop();
  1397. fc++;
  1398. }
  1399. // end
  1400. timeTaken(0);
  1401. char strts[16];
  1402. timestamp(&strts[0]);
  1403. printf("[%s] Stats: Fuel %.2f - Break %.2f - Shield %.2f - Stop %.2f - Repel %.2f - Mined %u\n", strts, pf, pb, ps, psl, pre, pm);
  1404. printf("[%s] Time-Taken: %s or %g Seconds\n", strts, tts, t-st);
  1405. printf("[%s] Game End.\n\n", strts);
  1406. // done
  1407. glfwDestroyWindow(window);
  1408. glfwTerminate();
  1409. exit(EXIT_SUCCESS);
  1410. return 0;
  1411. }