main.c 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797
  1. /*
  2. James William Fletcher (github.com/mrbid)
  3. June 2020 - November 2023
  4. Two of the application 16x16 icons are from http://www.forrestwalter.com/icons/
  5. A Helpful Colour Converter: https://www.easyrgb.com/en/convert.php
  6. I released the original game back in November 2020 as a webgl game:
  7. http://snowball.mobi
  8. Controls:
  9. Mouse 1 (Left) = Toggle Control
  10. Mouse 2 (Right) = Change View
  11. Mouse X1 = Decrease mouse speed
  12. Mouse X2 = Increase mouse speed
  13. */
  14. #include <math.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <time.h>
  19. #define uint unsigned int
  20. #include "gl.h"
  21. #define GLFW_INCLUDE_NONE
  22. #include "glfw3.h"
  23. #ifndef __x86_64__
  24. #define NOSSE
  25. #endif
  26. #define SEIR_RAND
  27. #include "esAux2.h"
  28. #include "res.h"
  29. #include "assets/icogrid.h"
  30. #include "assets/icosmooth2.h"
  31. #include "assets/tree.h"
  32. #include "assets/sadply.h"
  33. #include "assets/cat.h"
  34. #include "assets/heart.h"
  35. #include "assets/intro.h"
  36. #include "assets/tele.h"
  37. //*************************************
  38. // globals
  39. //*************************************
  40. GLFWwindow* window;
  41. uint winw = 1024; //1920
  42. uint winh = 768; //1080
  43. double t = 0;
  44. GLfloat aspect;
  45. GLfloat sens = 0.3f;
  46. GLfloat sens_mul = 0.2f;
  47. double ww, wh, ww2, wh2;
  48. double uw, uh, uw2, uh2; // normalised pixel dpi
  49. // mouse input
  50. double x=0, y=0, sx=0, sy=0;
  51. uint md = 0;
  52. // ui
  53. uint show_ui = 0;
  54. uint menu_focus = 0;
  55. uint seed_bits[27] = {0};
  56. uint uhi = 0;
  57. GLuint tex_menu;
  58. GLuint tex_mouse;
  59. double msx = -999;
  60. double js1 = -999;
  61. double js2 = -999;
  62. // joystick input
  63. uint doublestick = 1;
  64. GLfloat ss1 = 1.f;
  65. GLfloat ss2 = 1.5f;
  66. GLint projection_id;
  67. GLint modelview_id;
  68. GLint position_id;
  69. GLint lightpos_id;
  70. GLint color_id;
  71. GLint opacity_id;
  72. GLint normal_id;
  73. GLint texcoord_id;
  74. GLint sampler_id;
  75. GLuint bindstate = 0;
  76. GLuint bindstate2 = 0; //Just for rTree() color array change
  77. //It's unlikely there's going to be many color state changes
  78. //so I did not split the arrays into iced and regular passes.
  79. // - this is also true with the rPole (the obelisk) color
  80. // state changes here just happen at the end of the level
  81. // on just three rPole calls.
  82. // Hindsight says, I could have reduced state changes more
  83. // but not significantly so, aka this is negligible.
  84. mat projection;
  85. mat view;
  86. mat model;
  87. mat modelview;
  88. vec lightpos = {0.f, 0.f, 0.f};
  89. GLfloat xrot = 0.f;
  90. GLfloat yrot = 0.f;
  91. GLfloat zoom = -20.0f;
  92. ESModel mdlPlane;
  93. ESModel mdlGrid;
  94. ESModel mdlSphere;
  95. ESModel mdlTree;
  96. GLuint mdlTree_iced;
  97. ESModel mdlCat;
  98. GLuint mdlCat_aura;
  99. ESModel mdlSad;
  100. GLfloat sfd = -1.01f;
  101. GLfloat sfa = 0.0f;
  102. GLfloat sfs = 0.0f;
  103. ESModel mdlIntro;
  104. double inrot = 0;
  105. ESModel mdlHeart;
  106. double hrt = 0;
  107. ESModel mdlTele;
  108. #define max_tree 768
  109. uint tp[max_tree];
  110. char tpi[max_tree] = {0};
  111. #define max_snow 768
  112. uint sp[max_snow];
  113. #define max_gold 128
  114. uint gp[max_gold];
  115. double sround = 0;
  116. uint level = 0;
  117. uint sport = 0;
  118. uint rounds = 33;
  119. uint seed = 1337;
  120. double points = 0.f;
  121. GLfloat drag = 0.0023f;
  122. GLfloat maxspeed = 0.f;
  123. #define minspeed 0.22f
  124. GLfloat start = 0;
  125. uint psw = 0;
  126. vec pp;
  127. GLfloat pscale = 1.0f;
  128. mat pm;
  129. GLfloat ps = minspeed;
  130. GLfloat pr = 1.0f, pg = 1.0f, pb = 1.0f;
  131. GLfloat msca = 6.0f;
  132. //*************************************
  133. // utility functions
  134. //*************************************
  135. void timestamp(char* ts)
  136. {
  137. const time_t tt = time(0);
  138. strftime(ts, 16, "%H:%M:%S", localtime(&tt));
  139. }
  140. uint qRand(const uint min, const uint max)
  141. {
  142. static float rndmax = 1.f/(float)RAND_MAX;
  143. return (((float)rand()) * rndmax) * (max-min) + min;
  144. }
  145. uint qRandSeed(const uint seed, const uint min, const uint max)
  146. {
  147. srand(seed);
  148. return qRand(min, max);
  149. }
  150. float qRandFloat(const float min, const float max)
  151. {
  152. static float rndmax = 1.f/(float)RAND_MAX;
  153. return ( (((float)rand()) * rndmax) * (max-min) ) + min;
  154. }
  155. float qRandFloatSeed(const uint seed, const float min, const float max)
  156. {
  157. srand(seed);
  158. return qRandFloat(min, max);
  159. }
  160. float distance(const vec a, const uint16_t b)
  161. {
  162. const float xm = (a.x - icogrid_vertices[b]);
  163. const float ym = (a.y - icogrid_vertices[b+1]);
  164. const float zm = (a.z - icogrid_vertices[b+2]);
  165. return sqrt(xm*xm + ym*ym + zm*zm);
  166. }
  167. void resetGame(char sf)
  168. {
  169. if(sf == 2)
  170. level++;
  171. srand(seed+level);
  172. char strts[16];
  173. timestamp(&strts[0]);
  174. printf("[%s] Level Seed: %d\n", strts, seed+level);
  175. for(int i = 0; i < max_tree; i++)
  176. {
  177. uint ni = qRand(0, icogrid_numvert-2)*3;
  178. while(ni == 330 || ni == 132)
  179. ni = qRand(0, icogrid_numvert-2)*3;
  180. uint ex = 0;
  181. for(int j = 0; j < max_tree; j++)
  182. {
  183. if(tp[j] == ni)
  184. {
  185. ex = 1;
  186. break;
  187. }
  188. }
  189. if(ex == 0)
  190. tp[i] = ni;
  191. tpi[i] = 0;
  192. }
  193. for(int i = 0; i < max_snow; i++)
  194. {
  195. const uint ni = qRand(0, icogrid_numvert-2)*3;
  196. uint ex = 0;
  197. for(int j = 0; j < max_snow; j++)
  198. {
  199. if(sp[j] == ni)
  200. {
  201. ex = 1;
  202. break;
  203. }
  204. }
  205. if(ex == 0)
  206. sp[i] = ni;
  207. }
  208. for(int i = 0; i < max_gold; i++)
  209. {
  210. const uint ni = qRand(0, icogrid_numvert-2)*3;
  211. uint ex = 0;
  212. for(int j = 0; j < max_gold; j++)
  213. {
  214. if(gp[j] == ni)
  215. {
  216. ex = 1;
  217. break;
  218. }
  219. }
  220. if(ex == 0)
  221. gp[i] = ni;
  222. }
  223. if(sf != 4)
  224. {
  225. pscale = 1.0f;
  226. mIdent(&view);
  227. mIdent(&model);
  228. mIdent(&modelview);
  229. mIdent(&pm);
  230. xrot = 0;
  231. yrot = 0;
  232. const uint pstart = 330;
  233. pp.x = icogrid_vertices[pstart];
  234. pp.y = icogrid_vertices[pstart+1];
  235. pp.z = icogrid_vertices[pstart+2];
  236. }
  237. if(sf == 1 || sf == 3)
  238. {
  239. glfwSetWindowTitle(window, "Snowball.mobi");
  240. sfd = -1.01f;
  241. sfa = 0.0f;
  242. if(sf == 1)
  243. sfs = 1.0f;
  244. pr = 1.0f, pg = 1.0f, pb = 1.0f;
  245. level = 0;
  246. ps = minspeed;
  247. psw = 0;
  248. msca = 6.0f;
  249. points = 0;
  250. start = t;
  251. char strts[16];
  252. timestamp(&strts[0]);
  253. printf("[%s] Snowball Destroyed. Game over.\n", strts);
  254. }
  255. else if(sf == 0)
  256. {
  257. inrot = t+3.3;
  258. }
  259. else if(sf == 2)
  260. {
  261. if(psw)
  262. {
  263. pr = qRandFloatSeed(seed+level, 0.3f, 1.f);
  264. pg = qRandFloat(0.3f, 1.f);
  265. pb = qRandFloat(0.3f, 1.f);
  266. }
  267. else
  268. {
  269. pb -= 0.22f;
  270. if(pb < 0.0f)
  271. {
  272. pr = 0.f;
  273. pg = 0.34117f;
  274. pb = 0.49412f;
  275. psw = 1;
  276. }
  277. }
  278. hrt = t+1.6;
  279. msca += 0.33f;
  280. char title[256];
  281. sprintf(title, "Level %d - Points %.2f - Time %.2f mins - Score %.2f", level, points, ((double)(t-start))/60.0, (points / sqrt(t-start))*100);
  282. glfwSetWindowTitle(window, title);
  283. char strts[16];
  284. timestamp(&strts[0]);
  285. printf("[%s] Level %d - Points %f - Time %f mins - Score %f\n", strts, level, points, ((double)(t-start))/60.0, (points / sqrt(t-start))*100);
  286. }
  287. sround = t + 6.0; //Immune from tree's in the first 6 seconds of a round starting
  288. }
  289. //*************************************
  290. // render functions
  291. //*************************************
  292. void rGrid()
  293. {
  294. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (GLfloat*) &view.m[0][0]);
  295. glUniform3f(color_id, 1.0f, 1.0f, 1.0f);
  296. glUniform3f(lightpos_id, lightpos.x, lightpos.y, lightpos.z);
  297. glUniform1f(opacity_id, 1.0f);
  298. glBindBuffer(GL_ARRAY_BUFFER, mdlGrid.vid);
  299. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  300. glEnableVertexAttribArray(position_id);
  301. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlGrid.iid);
  302. glDrawElements(GL_TRIANGLES, icogrid_numind, GL_UNSIGNED_SHORT, 0);
  303. }
  304. void rTree(const uint pos, const GLfloat scale, const char iced)
  305. {
  306. mIdent(&model);
  307. vec v;
  308. v.x = icogrid_vertices[pos];
  309. v.y = icogrid_vertices[pos+1];
  310. v.z = icogrid_vertices[pos+2];
  311. vNorm(&v);
  312. mLookAt(&model, (vec){icogrid_vertices[pos], icogrid_vertices[pos+1], icogrid_vertices[pos+2]}, (vec){v.x, v.y, v.z});
  313. mScale(&model, scale, scale, scale);
  314. mMul(&modelview, &model, &view);
  315. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (GLfloat*) &modelview.m[0][0]);
  316. glUniform3f(lightpos_id, lightpos.x, lightpos.y, lightpos.z);
  317. glUniform1f(opacity_id, 1.0f);
  318. if(bindstate != 2)
  319. {
  320. glBindBuffer(GL_ARRAY_BUFFER, mdlTree.vid);
  321. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  322. glEnableVertexAttribArray(position_id);
  323. glBindBuffer(GL_ARRAY_BUFFER, mdlTree.nid);
  324. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  325. glEnableVertexAttribArray(normal_id);
  326. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlTree.iid);
  327. glBindBuffer(GL_ARRAY_BUFFER, mdlTree.cid);
  328. glVertexAttribPointer(color_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  329. glEnableVertexAttribArray(color_id);
  330. bindstate = 2;
  331. }
  332. //eh, I should have split the rendering arrays for this but it's not a big deal
  333. if(iced == 0)
  334. {
  335. if(bindstate2 != 1)
  336. {
  337. glBindBuffer(GL_ARRAY_BUFFER, mdlTree.cid);
  338. glVertexAttribPointer(color_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  339. glEnableVertexAttribArray(color_id);
  340. bindstate2 = 1;
  341. }
  342. }
  343. else
  344. {
  345. if(bindstate2 != 2)
  346. {
  347. glBindBuffer(GL_ARRAY_BUFFER, mdlTree_iced);
  348. glVertexAttribPointer(color_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  349. glEnableVertexAttribArray(color_id);
  350. bindstate2 = 2;
  351. }
  352. }
  353. glDrawElements(GL_TRIANGLES, tree_numind, GL_UNSIGNED_SHORT, 0);
  354. }
  355. void rSphere(const uint pos, const GLfloat scale, const GLfloat r, const GLfloat g, const GLfloat b)
  356. {
  357. mIdent(&model);
  358. vec v;
  359. v.x = icogrid_vertices[pos];
  360. v.y = icogrid_vertices[pos+1];
  361. v.z = icogrid_vertices[pos+2];
  362. vNorm(&v);
  363. mLookAt(&model, (vec){icogrid_vertices[pos], icogrid_vertices[pos+1], icogrid_vertices[pos+2]}, (vec){v.x, v.y, v.z});
  364. if(scale != 1.0)
  365. mScale(&model, scale, scale, scale);
  366. mMul(&modelview, &model, &view);
  367. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (GLfloat*) &modelview.m[0][0]);
  368. glUniform3f(lightpos_id, lightpos.x, lightpos.y, lightpos.z);
  369. glUniform3f(color_id, r, g, b);
  370. glUniform1f(opacity_id, 1.0f);
  371. if(bindstate != 3)
  372. {
  373. glBindBuffer(GL_ARRAY_BUFFER, mdlSphere.vid);
  374. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  375. glEnableVertexAttribArray(position_id);
  376. glBindBuffer(GL_ARRAY_BUFFER, mdlSphere.nid);
  377. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  378. glEnableVertexAttribArray(normal_id);
  379. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlSphere.iid);
  380. bindstate = 3;
  381. }
  382. glDrawElements(GL_TRIANGLES, icosmooth2_numind, GL_UNSIGNED_SHORT, 0);
  383. }
  384. void rPole(const uint pos, const GLfloat scale, const GLfloat yaw, const char aura)
  385. {
  386. mIdent(&model);
  387. vec v;
  388. v.x = icogrid_vertices[pos];
  389. v.y = icogrid_vertices[pos+1];
  390. v.z = icogrid_vertices[pos+2];
  391. vNorm(&v);
  392. mLookAt(&model, (vec){icogrid_vertices[pos], icogrid_vertices[pos+1], icogrid_vertices[pos+2]}, (vec){v.x, v.y, v.z});
  393. //mRotate(&model, yaw * DEG2RAD, 0.f, 0.f, 1.f);
  394. mRotX(&model, yaw * DEG2RAD);
  395. if(scale != 1.0f)
  396. mScale(&model, scale, scale, scale);
  397. mMul(&modelview, &model, &view);
  398. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (GLfloat*) &modelview.m[0][0]);
  399. glUniform3f(lightpos_id, lightpos.x, lightpos.y, lightpos.z);
  400. glUniform1f(opacity_id, 1.0);
  401. if(bindstate != 4)
  402. {
  403. glBindBuffer(GL_ARRAY_BUFFER, mdlCat.vid);
  404. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  405. glEnableVertexAttribArray(position_id);
  406. glBindBuffer(GL_ARRAY_BUFFER, mdlCat.nid);
  407. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  408. glEnableVertexAttribArray(normal_id);
  409. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlCat.iid);
  410. bindstate = 4;
  411. }
  412. if(aura == 0)
  413. {
  414. glBindBuffer(GL_ARRAY_BUFFER, mdlCat.cid);
  415. glVertexAttribPointer(color_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  416. glEnableVertexAttribArray(color_id);
  417. }
  418. else
  419. {
  420. glBindBuffer(GL_ARRAY_BUFFER, mdlCat_aura);
  421. glVertexAttribPointer(color_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  422. glEnableVertexAttribArray(color_id);
  423. }
  424. glDrawElements(GL_TRIANGLES, cat_numind, GL_UNSIGNED_SHORT, 0);
  425. }
  426. void rTele(const uint pos, const GLfloat scale, const GLfloat yaw)
  427. {
  428. mIdent(&model);
  429. vec v;
  430. v.x = icogrid_vertices[pos];
  431. v.y = icogrid_vertices[pos+1];
  432. v.z = icogrid_vertices[pos+2];
  433. vNorm(&v);
  434. mLookAt(&model, (vec){icogrid_vertices[pos], icogrid_vertices[pos+1], icogrid_vertices[pos+2]}, (vec){v.x, v.y, v.z});
  435. //mRotate(&model, yaw * DEG2RAD, 0.f, 0.f, 1.f);
  436. mRotX(&model, yaw * DEG2RAD);
  437. if(scale != 1.0f)
  438. mScale(&model, scale, scale, scale);
  439. mMul(&modelview, &model, &view);
  440. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (GLfloat*) &modelview.m[0][0]);
  441. glUniform3f(lightpos_id, lightpos.x, lightpos.y, lightpos.z);
  442. glUniform1f(opacity_id, 1.0f);
  443. if(bindstate != 5)
  444. {
  445. glBindBuffer(GL_ARRAY_BUFFER, mdlTele.vid);
  446. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  447. glEnableVertexAttribArray(position_id);
  448. glBindBuffer(GL_ARRAY_BUFFER, mdlTele.nid);
  449. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  450. glEnableVertexAttribArray(normal_id);
  451. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlTele.iid);
  452. bindstate = 5;
  453. }
  454. glBindBuffer(GL_ARRAY_BUFFER, mdlTele.cid);
  455. glVertexAttribPointer(color_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  456. glEnableVertexAttribArray(color_id);
  457. glDrawElements(GL_TRIANGLES, tele_numind, GL_UNSIGNED_SHORT, 0);
  458. }
  459. void rPlayer(const GLfloat dt, vec ndir, const vec nup, const GLfloat scale)
  460. {
  461. static vec lpp;
  462. static mat lpm;
  463. static GLfloat lrot = 0;
  464. static GLfloat rot = 0;
  465. // rotation
  466. float sscale = scale*100.f;
  467. if(sscale > 900.f){sscale = 900.f;}
  468. const float rd = (-(1300.f-sscale)*vDist(lpp, pp)) * dt;
  469. rot += rd;
  470. //printf("%f %f\n", rd, dt);
  471. // speed drag
  472. ps -= drag*dt;
  473. if(ps < minspeed){ps = minspeed;}
  474. // render
  475. mIdent(&pm);
  476. // dont render if in epsilon motion increments (basically not moving)
  477. if(vDist(lpp, pp) > 0.001f)
  478. {
  479. mTranslate(&pm, pp.x, pp.y, pp.z);
  480. vec c;
  481. vCross(&c, nup, ndir);
  482. vNorm(&c);
  483. vec rup;
  484. vCross(&rup, ndir, c);
  485. pm.m[0][0] = c.x;
  486. pm.m[0][1] = c.y;
  487. pm.m[0][2] = c.z;
  488. pm.m[1][0] = rup.x;
  489. pm.m[1][1] = rup.y;
  490. pm.m[1][2] = rup.z;
  491. pm.m[2][0] = ndir.x;
  492. pm.m[2][1] = ndir.y;
  493. pm.m[2][2] = ndir.z;
  494. }
  495. else
  496. {
  497. pp.x = lpm.m[3][0];
  498. pp.y = lpm.m[3][1];
  499. pp.z = lpm.m[3][2];
  500. rot = lrot;
  501. mCopy(&pm, &lpm);
  502. }
  503. mCopy(&lpm, &pm);
  504. vCopy(&lpp, pp);
  505. lrot = rot;
  506. mCopy(&model, &pm);
  507. if(scale != 1.0f)
  508. mScale(&model, scale, scale, scale);
  509. //mRotate(&model, rot * DEG2RAD, 1.f, 0.f, 0.f);
  510. mRotY(&model, rot * DEG2RAD);
  511. mMul(&modelview, &model, &view);
  512. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (GLfloat*) &modelview.m[0][0]);
  513. glUniform3f(lightpos_id, lightpos.x, lightpos.y, lightpos.z);
  514. // this only re-binds if necessary
  515. if(bindstate != 3)
  516. {
  517. glBindBuffer(GL_ARRAY_BUFFER, mdlSphere.vid);
  518. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  519. glEnableVertexAttribArray(position_id);
  520. glBindBuffer(GL_ARRAY_BUFFER, mdlSphere.nid);
  521. glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  522. glEnableVertexAttribArray(normal_id);
  523. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlSphere.iid);
  524. bindstate = 3;
  525. }
  526. // transparent (start round) or not
  527. if(t < sround)
  528. {
  529. if(sport == 0)
  530. glUniform3f(color_id, 0.50588f, 0.84705f, 1.0f);
  531. else
  532. glUniform3f(color_id, 0.54118f, 0.16863f, 0.88627f);
  533. glUniform1f(opacity_id, 0.5f);
  534. glEnable(GL_BLEND);
  535. glDrawElements(GL_TRIANGLES, icosmooth2_numind, GL_UNSIGNED_SHORT, 0);
  536. glDisable(GL_BLEND);
  537. return;
  538. }
  539. // indicate round complete
  540. if(pscale >= msca)
  541. {
  542. const float peelspeed = 0.03f;
  543. static float r=0.349f, g=0.773f, b=0.471f, inv=1.f;
  544. r += peelspeed * dt * inv;
  545. g += peelspeed * dt * inv;
  546. b += peelspeed * dt * inv;
  547. if(g > 1.f)
  548. inv = -1.f;
  549. else if(g < 0.773f)
  550. inv = 1.f;
  551. glUniform3f(color_id, r, g, b);
  552. glUniform1f(opacity_id, 1.0f);
  553. glDrawElements(GL_TRIANGLES, icosmooth2_numind, GL_UNSIGNED_SHORT, 0);
  554. return;
  555. }
  556. // normal colouring
  557. if(sport == 0)
  558. glUniform3f(color_id, pr, pg, pb);
  559. else
  560. glUniform3f(color_id, 0.753874f, 0.329309f, 0.896980f);
  561. glUniform1f(opacity_id, 1.0f);
  562. glDrawElements(GL_TRIANGLES, icosmooth2_numind, GL_UNSIGNED_SHORT, 0);
  563. }
  564. void rSad(const GLfloat dt)
  565. {
  566. mIdent(&modelview);
  567. mTranslate(&modelview, 0.f, 0.f, sfd);
  568. //mRotate(&modelview, sfa * DEG2RAD, 1.f, 0.f, 0.f);
  569. mRotY(&modelview, sfa * DEG2RAD);
  570. mScale(&modelview, sfs, sfs, sfs);
  571. sfd -= 0.16f * dt;
  572. sfa += 9.0f * dt;
  573. if(sfs > 0.0f)
  574. sfs -= 0.02f * dt;
  575. else
  576. sfs = 0;
  577. if(sfd <= -20.0f)
  578. {
  579. sfd = -1.01f;
  580. sfa = 0.0f;
  581. sfs = 1.0f;
  582. }
  583. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (GLfloat*) &modelview.m[0][0]);
  584. glUniform3f(color_id, 0.7f, 0.1f, 0.0f);
  585. glUniform1f(opacity_id, 1.0f);
  586. glBindBuffer(GL_ARRAY_BUFFER, mdlSad.vid);
  587. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  588. glEnableVertexAttribArray(position_id);
  589. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlSad.iid);
  590. glDisable(GL_CULL_FACE);
  591. glDrawElements(GL_TRIANGLES, sad_numind, GL_UNSIGNED_SHORT, 0);
  592. glEnable(GL_CULL_FACE);
  593. }
  594. void rIntro(const GLfloat opacity)
  595. {
  596. mIdent(&modelview);
  597. mTranslate(&modelview, 0.f, 0.f, -1.01f);
  598. //0.21
  599. GLfloat ns = 0.14f * aspect * 0.5f;
  600. if(ns < 0.14f)
  601. ns = 0.14f;
  602. mScale(&modelview, ns, ns, ns);
  603. glEnable(GL_BLEND);
  604. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (GLfloat*) &modelview.m[0][0]);
  605. glUniform3f(color_id, 0.f, 0.f, 0.f);
  606. glUniform1f(opacity_id, opacity*0.5f);
  607. glBindBuffer(GL_ARRAY_BUFFER, mdlIntro.vid);
  608. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  609. glEnableVertexAttribArray(position_id);
  610. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlIntro.iid);
  611. glDrawElements(GL_TRIANGLES, intro_numind, GL_UNSIGNED_SHORT, 0);
  612. mIdent(&modelview);
  613. mTranslate(&modelview, 0.f, 0.f, -1.01f);
  614. //0.20
  615. ns = 0.133f * aspect * 0.5f;
  616. if(ns < 0.133f)
  617. ns = 0.133f;
  618. mScale(&modelview, ns, ns, ns);
  619. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (GLfloat*) &modelview.m[0][0]);
  620. glUniform3f(color_id, 0.53f, 0.80f, 0.92f);
  621. glUniform1f(opacity_id, opacity);
  622. glBindBuffer(GL_ARRAY_BUFFER, mdlIntro.vid);
  623. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  624. glEnableVertexAttribArray(position_id);
  625. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlIntro.iid);
  626. glDrawElements(GL_TRIANGLES, intro_numind, GL_UNSIGNED_SHORT, 0);
  627. glDisable(GL_BLEND);
  628. }
  629. void rHeart(const GLfloat opacity)
  630. {
  631. mIdent(&modelview);
  632. mTranslate(&modelview, 0.f, 0.f, -1.01f);
  633. mScale(&modelview, 4.2f, 4.2f, 4.2f);
  634. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (GLfloat*) &modelview.m[0][0]);
  635. glUniform3f(color_id, 0.67059f, 0.12157f, 0.12157f);
  636. glUniform1f(opacity_id, opacity);
  637. glBindBuffer(GL_ARRAY_BUFFER, mdlHeart.vid);
  638. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  639. glEnableVertexAttribArray(position_id);
  640. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlHeart.iid);
  641. glEnable(GL_BLEND);
  642. glDrawElements(GL_TRIANGLES, heart_numind, GL_UNSIGNED_SHORT, 0);
  643. glDisable(GL_BLEND);
  644. }
  645. void rMenuHighlight(const GLfloat x, const GLfloat y)
  646. {
  647. mIdent(&modelview);
  648. mTranslate(&modelview, x, y, -1.730f);
  649. mScale(&modelview, uw*28.f, uh*28.f, 0);
  650. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (GLfloat*) &modelview.m[0][0]);
  651. glUniform3f(color_id, 0.39608f, 0.70196f, 0.07059f);
  652. glUniform1f(opacity_id, 1.0f);
  653. glBindBuffer(GL_ARRAY_BUFFER, mdlPlane.vid);
  654. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  655. glEnableVertexAttribArray(position_id);
  656. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlPlane.iid);
  657. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
  658. }
  659. void rMenuMouse(const GLfloat x, const GLfloat y)
  660. {
  661. shadeFullbrightT(&position_id, &projection_id, &modelview_id, &texcoord_id, &sampler_id);
  662. glUniformMatrix4fv(projection_id, 1, GL_FALSE, (GLfloat*) &projection.m[0][0]);
  663. mIdent(&modelview);
  664. mTranslate(&modelview, x, y, -1.730f);
  665. mScale(&modelview, uw*36.f, uh*27.f, 0);
  666. glUniformMatrix4fv(projection_id, 1, GL_FALSE, (GLfloat*)&projection.m[0][0]);
  667. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (GLfloat*)&modelview.m[0][0]);
  668. glBindBuffer(GL_ARRAY_BUFFER, mdlPlane.tid);
  669. glVertexAttribPointer(texcoord_id, 2, GL_FLOAT, GL_FALSE, 0, 0);
  670. glEnableVertexAttribArray(texcoord_id);
  671. glActiveTexture(GL_TEXTURE0);
  672. glBindTexture(GL_TEXTURE_2D, tex_mouse);
  673. glUniform1i(sampler_id, 0);
  674. glBindBuffer(GL_ARRAY_BUFFER, mdlPlane.vid);
  675. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  676. glEnableVertexAttribArray(position_id);
  677. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlPlane.iid);
  678. glEnable(GL_BLEND);
  679. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
  680. glDisable(GL_BLEND);
  681. }
  682. void setBaseSensitivity()
  683. {
  684. if(zoom == -16.0f)
  685. sens = 0.1f*sens_mul;
  686. else if(zoom == -20.0)
  687. sens = 0.2f*sens_mul;
  688. else if(zoom == -26.0f)
  689. sens = 0.3f*sens_mul;
  690. else if(zoom == -27.0f)
  691. sens = 0.3f*sens_mul;
  692. }
  693. //*************************************
  694. // update & render
  695. //*************************************
  696. void main_loop()
  697. {
  698. //*************************************
  699. // time delta for interpolation
  700. //*************************************
  701. static double lt = 0;
  702. const float deltaTime = (float)((t-lt)*15.0);
  703. lt = t;
  704. //*************************************
  705. // orbit / mouse control scaling
  706. //*************************************
  707. if(show_ui == 0)
  708. {
  709. double xd=0, yd=0;
  710. if(md == 1)
  711. {
  712. glfwGetCursorPos(window, &x, &y);
  713. xd = (sx-x), yd = (sy-y);
  714. sx = x, sy = y;
  715. }
  716. //printf("%f %f | %f %f | %f %f\n", x, y, sx, sy, xd, yd);
  717. if(glfwJoystickPresent(GLFW_JOYSTICK_1) == 1)
  718. {
  719. int count;
  720. const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &count);
  721. if(count >= 2) // && fabs(axes[0]) > 0.00001f && fabs(axes[1]) > 0.00001f
  722. {
  723. if(sens < 0.f)
  724. {
  725. xd = axes[0]*50.f*ss1*sens;
  726. yd = axes[1]*50.f*ss1*sens;
  727. }
  728. else
  729. {
  730. xd = -axes[0]*50.f*ss1*sens;
  731. yd = -axes[1]*50.f*ss1*sens;
  732. }
  733. //printf("%f %f\n", axes[0], axes[1]);
  734. }
  735. if(doublestick == 1)
  736. {
  737. if(sens < 0.f)
  738. {
  739. xd += axes[3]*50.f*ss2*sens;
  740. yd += axes[4]*50.f*ss2*sens;
  741. }
  742. else
  743. {
  744. xd += -axes[3]*50.f*ss2*sens;
  745. yd += -axes[4]*50.f*ss2*sens;
  746. }
  747. //printf("%f %f\n", axes[3], axes[4]);
  748. }
  749. static float bt = 0;
  750. if(t > bt)
  751. {
  752. const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &count);
  753. if(count >= 3)
  754. {
  755. if(buttons[0] == GLFW_PRESS)
  756. {
  757. sens_mul -= 0.03f;
  758. setBaseSensitivity();
  759. char strts[16];
  760. timestamp(&strts[0]);
  761. printf("[%s] Sens: %.3f\n", strts, sens_mul);
  762. bt = t + 0.3f;
  763. }
  764. else if(buttons[1] == GLFW_PRESS)
  765. {
  766. sens_mul += 0.03f;
  767. setBaseSensitivity();
  768. char strts[16];
  769. timestamp(&strts[0]);
  770. printf("[%s] Sens: %.3f\n", strts, sens_mul);
  771. bt = t + 0.3f;
  772. }
  773. else if(buttons[2] == GLFW_PRESS || buttons[9] == GLFW_PRESS || buttons[10] == GLFW_PRESS)
  774. {
  775. if(zoom == -20.0f)
  776. {
  777. zoom = -16.0f;
  778. setBaseSensitivity();
  779. sport = 0;
  780. }
  781. else if(zoom == -16.0f)
  782. {
  783. zoom = -26.0f;
  784. setBaseSensitivity();
  785. sport = 0;
  786. }
  787. else if(zoom == -26.0f)
  788. {
  789. zoom = -27.0f;
  790. setBaseSensitivity();
  791. sport = 1;
  792. }
  793. else if(zoom == -27.0)
  794. {
  795. zoom = -20.0f;
  796. setBaseSensitivity();
  797. sport = 0;
  798. }
  799. bt = t + 0.3f;
  800. }
  801. }
  802. }
  803. }
  804. xrot += xd*sens;
  805. yrot += yd*sens;
  806. // prevent pole inversion
  807. if(yrot > 180.0f){yrot = 180.0f;}else if(yrot < -0.0f){yrot = -0.0f;}
  808. }
  809. //*************************************
  810. // camera control
  811. //*************************************
  812. mIdent(&view);
  813. mTranslate(&view, 0.f, 0.f, zoom);
  814. mRotate(&view, -yrot * DEG2RAD, 1.f, 0.f, 0.f);
  815. mRotate(&view, xrot * DEG2RAD, 0.f, 0.f, 1.f);
  816. //*************************************
  817. // camera look vector
  818. //*************************************
  819. vec ray_eye;
  820. ray_eye.x = view.m[0][2];
  821. ray_eye.y = view.m[1][2];
  822. ray_eye.z = view.m[2][2]; // already normalised
  823. vec dp;
  824. vCopy(&dp, ray_eye);
  825. vMulS(&dp, dp, ps*deltaTime); // cast out
  826. vAdd(&pp, pp, dp);
  827. vec pn;
  828. vCopy(&pn, pp);
  829. vNorm(&pn);
  830. vec vn;
  831. vMulS(&vn, pn, 12.55f + ((pscale*0.5f)*0.1f));
  832. vCopy(&pp, vn);
  833. //*************************************
  834. // begin render
  835. //*************************************
  836. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  837. //*************************************
  838. // render grid
  839. //*************************************
  840. glEnable(GL_DEPTH_TEST);
  841. // --
  842. shadeLambert(&position_id, &projection_id, &modelview_id, &lightpos_id, &color_id, &opacity_id);
  843. glUniformMatrix4fv(projection_id, 1, GL_FALSE, (GLfloat*) &projection.m[0][0]);
  844. rGrid();
  845. // --
  846. shadeLambert3(&position_id, &projection_id, &modelview_id, &lightpos_id, &normal_id, &color_id, &opacity_id);
  847. glUniformMatrix4fv(projection_id, 1, GL_FALSE, (GLfloat*) &projection.m[0][0]);
  848. // poles
  849. if(pscale >= msca)
  850. {
  851. if(distance(pp, 0) <= pscale*0.14f || distance(pp, 132) <= pscale*0.14f)
  852. resetGame(2);
  853. rTele(0.f, 1.0f, 0.f);
  854. rTele(132.f, 1.0f, 0.f);
  855. }
  856. else
  857. {
  858. char aura = 0;
  859. if(distance(pp, 0) <= 4.0f || distance(pp, 132) <= 4.0f)
  860. aura = 1;
  861. rPole(0.f, 2.6f, 0.f, aura);
  862. rPole(132.f, 2.6f, 0.f, aura);
  863. }
  864. // tree's
  865. for(int i = 0; i < max_tree; i++)
  866. {
  867. if(tp[i] == 0)
  868. continue;
  869. GLfloat ns = 1;
  870. if(level >= 1)
  871. {
  872. ns = (float)qRandSeed(seed+tp[i]+level, 1, 2);
  873. if(ns == 2.f)
  874. ns = 1.6f;
  875. }
  876. if(t > sround)
  877. {
  878. if(pscale >= ns*4.0f && distance(pp, tp[i]) <= pscale*0.3f)
  879. ns *= 0.5f;
  880. if(distance(pp, tp[i]) <= pscale*0.1)
  881. {
  882. static double lt = 0;
  883. if(t > lt)
  884. {
  885. if(ns == 1.6f)
  886. {
  887. ps -= ps * 0.43f;
  888. char strts[16];
  889. timestamp(&strts[0]);
  890. if(ps < minspeed){ps = minspeed;}
  891. printf("[%s] Big Tree Collision: %.3f\n", strts, ps);
  892. }
  893. else
  894. {
  895. ps -= ps * 0.2f;
  896. char strts[16];
  897. timestamp(&strts[0]);
  898. if(ps < minspeed){ps = minspeed;}
  899. printf("[%s] Small Tree Collision: %.3f\n", strts, ps);
  900. }
  901. lt = t + 0.3;
  902. }
  903. if(pscale >= ns*4.0f)
  904. {
  905. pscale += 0.01f;
  906. tp[i] = 0;
  907. continue;
  908. }
  909. else
  910. {
  911. if(tpi[i] != 1)
  912. pscale -= 0.3f;
  913. tpi[i] = 1;
  914. }
  915. }
  916. }
  917. rTree(tp[i], ns, tpi[i]);
  918. }
  919. // --
  920. shadeLambert1(&position_id, &projection_id, &modelview_id, &lightpos_id, &normal_id, &color_id, &opacity_id);
  921. glUniformMatrix4fv(projection_id, 1, GL_FALSE, (GLfloat*) &projection.m[0][0]);
  922. for(int i = 0; i < max_snow; i++)
  923. {
  924. if(sp[i] == 0)
  925. continue;
  926. if(distance(pp, sp[i]) <= pscale*0.1f)
  927. {
  928. const float ss = qRandFloatSeed(seed+sp[i]+level, 0.3f, 1.0f);
  929. sp[i] = 0;
  930. ps += 0.06f*ss;
  931. pscale += ss*0.03f;
  932. points += 0.06f*ss;
  933. char strts[16];
  934. timestamp(&strts[0]);
  935. printf("[%s] Snow: %.3f, %.3f, %.3f\n", strts, points, pscale, ps);
  936. continue;
  937. }
  938. if(sport == 0)
  939. rSphere(sp[i], qRandFloatSeed(seed+sp[i]+level, 0.5f, 1.0f), 1.0f, 1.0f, 1.0f);
  940. else
  941. rSphere(sp[i], qRandFloatSeed(seed+sp[i]+level, 0.5f, 1.0f), 0.f, 1.f, 1.f);
  942. }
  943. for(int i = 0; i < max_gold; i++)
  944. {
  945. if(gp[i] == 0)
  946. continue;
  947. if(distance(pp, gp[i]) <= pscale*0.1f)
  948. {
  949. const float ss = qRandFloatSeed(seed+gp[i]+level, 0.3f, 1.0f);
  950. gp[i] = 0;
  951. ps += 0.12f*ss;
  952. pscale += ss*0.12f;
  953. points += 0.12f*ss;
  954. char strts[16];
  955. timestamp(&strts[0]);
  956. printf("[%s] Gold: %.3f, %.3f, %.3f\n", strts, points, pscale, ps);
  957. continue;
  958. }
  959. if(sport == 0)
  960. rSphere(gp[i], qRandFloatSeed(seed+gp[i]+level, 0.4f, 0.65f), 1.0f, 1.0f, 0.0f);
  961. else
  962. rSphere(gp[i], qRandFloatSeed(seed+gp[i]+level, 0.4f, 0.65f), 1.0f, 0.f, 0.f);
  963. }
  964. // --
  965. if(pscale < 1.0f)
  966. resetGame(1); //dead
  967. if(pscale > msca)
  968. pscale = msca;
  969. if(maxspeed != 0 && ps > maxspeed) //speed limiter
  970. ps = maxspeed;
  971. rPlayer(deltaTime, ray_eye, pn, pscale);
  972. // --
  973. glDisable(GL_DEPTH_TEST);
  974. if(sfs != 0)
  975. {
  976. shadeFullbright(&position_id, &projection_id, &modelview_id, &color_id, &opacity_id);
  977. glUniformMatrix4fv(projection_id, 1, GL_FALSE, (GLfloat*) &projection.m[0][0]);
  978. rSad(deltaTime);
  979. }
  980. else if(t < inrot)
  981. {
  982. shadeFullbright(&position_id, &projection_id, &modelview_id, &color_id, &opacity_id);
  983. glUniformMatrix4fv(projection_id, 1, GL_FALSE, (GLfloat*) &projection.m[0][0]);
  984. rIntro((inrot-t)*0.3);
  985. }
  986. else if(t < hrt)
  987. {
  988. shadeFullbright(&position_id, &projection_id, &modelview_id, &color_id, &opacity_id);
  989. glUniformMatrix4fv(projection_id, 1, GL_FALSE, (GLfloat*) &projection.m[0][0]);
  990. rHeart((hrt-t)*0.3);
  991. }
  992. //*************************************
  993. // Draw UI
  994. //*************************************
  995. if(show_ui == 1)
  996. {
  997. glfwGetCursorPos(window, &x, &y);
  998. // DRAW MENU BG
  999. shadeFullbrightT(&position_id, &projection_id, &modelview_id, &texcoord_id, &sampler_id);
  1000. glUniformMatrix4fv(projection_id, 1, GL_FALSE, (GLfloat*) &projection.m[0][0]);
  1001. mIdent(&modelview);
  1002. mTranslate(&modelview, 0.f, 0.f, -1.730f);
  1003. mScale(&modelview, uw*370.f, uh*197.f, 0);
  1004. glUniformMatrix4fv(projection_id, 1, GL_FALSE, (GLfloat*)&projection.m[0][0]);
  1005. glUniformMatrix4fv(modelview_id, 1, GL_FALSE, (GLfloat*)&modelview.m[0][0]);
  1006. glBindBuffer(GL_ARRAY_BUFFER, mdlPlane.tid);
  1007. glVertexAttribPointer(texcoord_id, 2, GL_FLOAT, GL_FALSE, 0, 0);
  1008. glEnableVertexAttribArray(texcoord_id);
  1009. glActiveTexture(GL_TEXTURE0);
  1010. glBindTexture(GL_TEXTURE_2D, tex_menu);
  1011. glUniform1i(sampler_id, 0);
  1012. glBindBuffer(GL_ARRAY_BUFFER, mdlPlane.vid);
  1013. glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 0, 0);
  1014. glEnableVertexAttribArray(position_id);
  1015. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mdlPlane.iid);
  1016. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
  1017. // DRAW SEED SELECTOR
  1018. shadeFullbright(&position_id, &projection_id, &modelview_id, &color_id, &opacity_id);
  1019. glUniformMatrix4fv(projection_id, 1, GL_FALSE, (GLfloat*) &projection.m[0][0]);
  1020. double rx = uw2*(x-ww2);
  1021. double ry = uh2*-(y-wh2);
  1022. rx += uw2*14;
  1023. ry += uw2*14;
  1024. //rMenuHighlight(rx, ry);
  1025. menu_focus = 0;
  1026. double xo = -172;
  1027. double yo = -92;
  1028. for(uint i = 0; i < 3; i++)
  1029. {
  1030. double iyo = yo + (62 * i);
  1031. if(i == 0)
  1032. iyo -= 1.5;
  1033. else if(i == 1)
  1034. iyo -= 1.5;
  1035. for(uint j = 0; j < 9; j++)
  1036. {
  1037. double ixo = xo + (62 * j);
  1038. if(j > 5)
  1039. ixo += 8;
  1040. else if(j > 2)
  1041. ixo += 4;
  1042. //rMenuHighlight(uw*ixo, uw*-iyo);
  1043. if(rx > uw*ixo && rx < uw*(ixo+59) && ry > uh*-iyo && ry < uh*(-iyo+59))
  1044. {
  1045. rMenuHighlight(uw*ixo, uw*-iyo);
  1046. uhi = (i*9)+j;
  1047. menu_focus = 1;
  1048. }
  1049. if(seed_bits[(i*9)+j] == 1)
  1050. rMenuHighlight(uw*ixo, uw*-iyo);
  1051. }
  1052. }
  1053. // DRAW SENSITIVITY SLIDERS
  1054. shadeFullbrightT(&position_id, &projection_id, &modelview_id, &texcoord_id, &sampler_id);
  1055. glUniformMatrix4fv(projection_id, 1, GL_FALSE, (GLfloat*) &projection.m[0][0]);
  1056. //rMenuMouse(uw2*-162, uw2*80);
  1057. //printf("%.3f %.3f\n", rx, ry);
  1058. // master sensitivity
  1059. if(ry > uh2*77 && ry < uh2*107 && rx > uw2*-162 && rx < uw2*194)
  1060. {
  1061. uint jammed = 0;
  1062. if(rx < (uw2*-162)+(uw2*14))
  1063. {
  1064. const double nx = uw2*-162;
  1065. rMenuMouse(nx, uh2*80);
  1066. msx = nx;
  1067. jammed = 1;
  1068. }
  1069. else if(rx > (uw2*162)+(uw2*14))
  1070. {
  1071. const double nx = uw2*162;
  1072. rMenuMouse(nx, uh2*80);
  1073. msx = nx;
  1074. jammed = 1;
  1075. }
  1076. if(jammed == 0)
  1077. {
  1078. const double nx = rx-(uw2*15);
  1079. rMenuMouse(nx, uh2*80);
  1080. msx = nx;
  1081. }
  1082. //printf("%.3f\n", msx);
  1083. const GLfloat mb = uw2*162.f;
  1084. GLfloat ns = (GLfloat)( (msx+mb)/(mb*2.f) );
  1085. if(ns <= 0.077f)
  1086. sens_mul = -(0.3f - (ns*7.5f));
  1087. else
  1088. sens_mul = ns;
  1089. //printf("%.3f %.3f %.3f\n", msx, sens_mul, mb);
  1090. setBaseSensitivity();
  1091. static double tc = 0;
  1092. static GLfloat tls = 0;
  1093. if(t > tc && tls != sens_mul)
  1094. {
  1095. char strts[16];
  1096. timestamp(&strts[0]);
  1097. printf("[%s] Sens: %.3f\n", strts, sens_mul);
  1098. tls = sens_mul;
  1099. tc = t+0.1;
  1100. }
  1101. }
  1102. else
  1103. {
  1104. rMenuMouse(msx, uh2*80);
  1105. }
  1106. // joy1 sensitivity
  1107. if(ry > uh2*-51 && ry < uh2*-21 && rx > uw2*-50 && rx < uw2*194)
  1108. {
  1109. uint jammed = 0;
  1110. if(rx < (uw2*-49.8)+(uw2*14))
  1111. {
  1112. const double nx = uw2*-49.8;
  1113. rMenuMouse(nx, uh2*-48);
  1114. js1 = nx;
  1115. jammed = 1;
  1116. }
  1117. else if(rx > (uw2*162)+(uw2*14))
  1118. {
  1119. const double nx = uw2*162;
  1120. rMenuMouse(nx, uh2*-48);
  1121. js1 = nx;
  1122. jammed = 1;
  1123. }
  1124. if(jammed == 0)
  1125. {
  1126. const double nx = rx-(uw2*15);
  1127. rMenuMouse(nx, uh2*-48);
  1128. js1 = nx;
  1129. }
  1130. const GLfloat lmb = uw2*50.f;
  1131. const GLfloat rmb = uw2*162.f;
  1132. GLfloat ns = (GLfloat)( (js1+lmb)/(lmb+rmb) );
  1133. ss1 = ns*2.f;
  1134. //printf("%.3f %.3f %.3f %.3f\n", js1, ss1, lmb, rmb);
  1135. static double tc = 0;
  1136. static GLfloat tls = 0;
  1137. if(t > tc && tls != ss1)
  1138. {
  1139. char strts[16];
  1140. timestamp(&strts[0]);
  1141. printf("[%s] JS1 Sens: %.3f\n", strts, ss1);
  1142. tls = ss1;
  1143. tc = t+0.1;
  1144. }
  1145. }
  1146. else
  1147. {
  1148. rMenuMouse(js1, uh2*-48);
  1149. }
  1150. // joy2 sensitivity
  1151. if(ry > uh2*-81 && ry < uh2*-53 && rx > uw2*-50 && rx < uw2*194)
  1152. {
  1153. uint jammed = 0;
  1154. if(rx < (uw2*-49.8)+(uw2*14))
  1155. {
  1156. const double nx = uw2*-49.8;
  1157. rMenuMouse(nx, uh2*-79);
  1158. js2 = nx;
  1159. jammed = 1;
  1160. }
  1161. else if(rx > (uw2*162)+(uw2*14))
  1162. {
  1163. const double nx = uw2*162;
  1164. rMenuMouse(nx, uh2*-79);
  1165. js2 = nx;
  1166. jammed = 1;
  1167. }
  1168. if(jammed == 0)
  1169. {
  1170. const double nx = rx-(uw2*15);
  1171. rMenuMouse(nx, uh2*-79);
  1172. js2 = nx;
  1173. }
  1174. const GLfloat lmb = uw2*50.f;
  1175. const GLfloat rmb = uw2*162.f;
  1176. GLfloat ns = (GLfloat)( (js2+lmb)/(lmb+rmb) );
  1177. ss2 = ns*2.f;
  1178. //printf("%.3f %.3f %.3f %.3f\n", js1, ss1, lmb, rmb);
  1179. static double tc = 0;
  1180. static GLfloat tls = 0;
  1181. if(t > tc && tls != ss2)
  1182. {
  1183. char strts[16];
  1184. timestamp(&strts[0]);
  1185. printf("[%s] JS2 Sens: %.3f\n", strts, ss2);
  1186. tls = ss2;
  1187. tc = t+0.1;
  1188. }
  1189. }
  1190. else
  1191. {
  1192. rMenuMouse(js2, uh2*-79);
  1193. }
  1194. }
  1195. //*************************************
  1196. // swap buffers / display render
  1197. //*************************************
  1198. glfwSwapBuffers(window);
  1199. }
  1200. //*************************************
  1201. // Input Handelling
  1202. //*************************************
  1203. static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
  1204. {
  1205. if(action != GLFW_PRESS){return;}
  1206. // toggle ui
  1207. show_ui = 1 - show_ui;
  1208. if(show_ui == 1)
  1209. {
  1210. char strts[16];
  1211. timestamp(&strts[0]);
  1212. printf("[%s] Menu Opened.\n", strts);
  1213. // set master sense pos
  1214. const GLfloat mb = uw2*162.f;
  1215. msx = (sens_mul * (mb*2.f)) - mb;
  1216. if(msx > mb)
  1217. msx = mb;
  1218. else if(msx <= -mb)
  1219. msx = -mb;
  1220. // set joy 1&2 sense pos
  1221. const GLfloat lmb = uw2*50.f;
  1222. const GLfloat rmb = uw2*162.f;
  1223. js1 = ((ss1*0.5f) * (lmb+rmb)) - lmb;
  1224. if(js1 > rmb)
  1225. js1 = rmb;
  1226. else if(js1 <= -lmb)
  1227. js1 = -lmb;
  1228. js2 = ((ss2*0.5f) * (lmb+rmb)) - lmb;
  1229. if(js2 > rmb)
  1230. js2 = rmb;
  1231. else if(js2 <= -lmb)
  1232. js2 = -lmb;
  1233. }
  1234. else
  1235. {
  1236. char strts[16];
  1237. timestamp(&strts[0]);
  1238. printf("[%s] Menu Closed.\n", strts);
  1239. }
  1240. // restore game mouse focus state
  1241. static uint sv = 0;
  1242. if(show_ui == 1)
  1243. {
  1244. sv = md;
  1245. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
  1246. glfwGetCursorPos(window, &sx, &sy);
  1247. md = 0;
  1248. }
  1249. else if(sv == 1)
  1250. {
  1251. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
  1252. glfwGetCursorPos(window, &sx, &sy);
  1253. md = 1;
  1254. }
  1255. }
  1256. void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
  1257. {
  1258. float fi = 0.f;
  1259. if(yoffset > 0)
  1260. {
  1261. if(sport == 1){sport = 0;return;}
  1262. fi = 0.5f;
  1263. }
  1264. else
  1265. {
  1266. fi = -0.5f;
  1267. }
  1268. zoom += fi;
  1269. if(zoom < -27.f)
  1270. {
  1271. zoom = -27.f;
  1272. sport = 1;
  1273. }
  1274. else if(zoom > -16.f)
  1275. {
  1276. zoom = -16.f;
  1277. }
  1278. setBaseSensitivity();
  1279. }
  1280. void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
  1281. {
  1282. if(button == GLFW_MOUSE_BUTTON_LEFT)
  1283. {
  1284. if(action == GLFW_PRESS)
  1285. {
  1286. if(show_ui == 0)
  1287. {
  1288. if(md == 0)
  1289. {
  1290. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
  1291. glfwGetCursorPos(window, &sx, &sy);
  1292. md = 1;
  1293. }
  1294. else
  1295. {
  1296. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
  1297. glfwGetCursorPos(window, &sx, &sy);
  1298. md = 0;
  1299. }
  1300. }
  1301. else
  1302. {
  1303. if(menu_focus == 1)
  1304. {
  1305. seed_bits[uhi] = 1 - seed_bits[uhi];
  1306. seed = 1337;
  1307. for(int i = 0; i < 27; i++)
  1308. seed ^= seed_bits[i] << i;
  1309. char strts[16];
  1310. timestamp(&strts[0]);
  1311. printf("[%s] Seed: %u\n", strts, seed);
  1312. srand(seed);
  1313. resetGame(4);
  1314. }
  1315. }
  1316. }
  1317. }
  1318. else if(action == GLFW_PRESS && show_ui == 0)
  1319. {
  1320. if(button == GLFW_MOUSE_BUTTON_4)
  1321. {
  1322. sens_mul -= 0.1f;
  1323. setBaseSensitivity();
  1324. char strts[16];
  1325. timestamp(&strts[0]);
  1326. printf("[%s] Sens: %.3f\n", strts, sens_mul);
  1327. }
  1328. else if(button == GLFW_MOUSE_BUTTON_5)
  1329. {
  1330. sens_mul += 0.1f;
  1331. setBaseSensitivity();
  1332. char strts[16];
  1333. timestamp(&strts[0]);
  1334. printf("[%s] Sens: %.3f\n", strts, sens_mul);
  1335. }
  1336. else if(button == GLFW_MOUSE_BUTTON_RIGHT)
  1337. {
  1338. if(zoom == -20.0f)
  1339. {
  1340. zoom = -16.0f;
  1341. setBaseSensitivity();
  1342. sport = 0;
  1343. }
  1344. else if(zoom == -16.0f)
  1345. {
  1346. zoom = -26.0f;
  1347. setBaseSensitivity();
  1348. sport = 0;
  1349. }
  1350. else if(zoom == -26.0f)
  1351. {
  1352. zoom = -27.0f;
  1353. setBaseSensitivity();
  1354. sport = 1;
  1355. }
  1356. else if(zoom == -27.0)
  1357. {
  1358. zoom = -20.0f;
  1359. setBaseSensitivity();
  1360. sport = 0;
  1361. }
  1362. else
  1363. {
  1364. zoom = -20.0f;
  1365. setBaseSensitivity();
  1366. sport = 0;
  1367. }
  1368. }
  1369. }
  1370. }
  1371. void window_size_callback(GLFWwindow* window, int width, int height)
  1372. {
  1373. winw = width;
  1374. winh = height;
  1375. glViewport(0, 0, winw, winh);
  1376. aspect = (GLfloat)winw / (GLfloat)winh;
  1377. ww = winw;
  1378. wh = winh;
  1379. ww2 = ww/2;
  1380. wh2 = wh/2;
  1381. uw = (double)aspect / ww;
  1382. uh = 1 / wh;
  1383. uw2 = (double)aspect / ww2;
  1384. uh2 = 1 / wh2;
  1385. mIdent(&projection);
  1386. mPerspective(&projection, 60.0f, aspect, 1.0f, 60.0f);
  1387. }
  1388. //*************************************
  1389. // Process Entry Point
  1390. //*************************************
  1391. int main(int argc, char** argv)
  1392. {
  1393. // should I be using getopt? I prefer this.
  1394. uint noborder = 0, msaa = 16;
  1395. if(argc >= 2){seed = atof(argv[1]);}
  1396. if(argc >= 3){msaa = atoi(argv[2]);}
  1397. if(argc >= 4){noborder = atoi(argv[3]);}
  1398. if(argc >= 5){winw = atoi(argv[4]);}
  1399. if(argc >= 6){winh = atoi(argv[5]);}
  1400. if(argc >= 7){sens_mul = atof(argv[6]);}
  1401. if(argc >= 8){doublestick = atoi(argv[7]);}
  1402. if(argc >= 9){ss1 = atof(argv[8]);}
  1403. if(argc >= 10){ss2 = atof(argv[9]);}
  1404. // help
  1405. printf("Snowball by James William Fletcher (github.com/mrbid)\n");
  1406. printf("A novel speed run game akin to a platform loop/buzz wire game.\n\n");
  1407. printf("CONTROLS:\n");
  1408. printf("Mouse 1 (Left) = Toggle Control\n");
  1409. printf("Mouse 2 (Right) = Change View\n");
  1410. printf("Mouse X1 = Decrease mouse speed\n");
  1411. printf("Mouse X2 = Increase mouse speed\n\n");
  1412. printf("COMMAND LINE:\n");
  1413. printf("./snowball <random seed> <msaa 0-16> <noborder 0-1> <width> <height> <master input/mouse sensitivity> <double joy stick> <joy 1 sensitivity> <joy 2 sensitivity>\n\n");
  1414. printf("Specify a mouse sensitivity of -x such as -1.0 to invert the mouse.\n\n");
  1415. printf("A web version of the game: http://snowball.mobi\n\n");
  1416. printf("HOW TO:\n");
  1417. printf("You have to roll around collecting snow and avoiding trees until your snowball is large enough to continue to the next level.\n\n");
  1418. printf("Once you have accumulated a large enough snowball, the poles (obelisks) will turn into teleportation pads to the next round; the aim is to complete each level or a sequence of levels with the highest score in the shortest time.\n\n");
  1419. printf("The larger the snowballs you collect higher the score. Gold snow is double the reward of white. Picking up snow increases your speed temporarily; the idea is to enter a flow of collecting snow so that your speed stays up.\n\n");
  1420. printf("Try not to hit the trees as they will slow you down and reduce the mass of your snowball, unless your snowball is large enough to consume them, then they slow you down but also add to the mass of your snowball. Trees will shrink slightly as you approach them to show that they can be consumed.\n\n");
  1421. printf("Your score is updated in the program title bar at the end of each level.\n\n");
  1422. // settings
  1423. printf("Argv Settings:\n");
  1424. printf("SEED: %u\n", seed);
  1425. printf("MSAA: %u\n", msaa);
  1426. printf("NoBorder: %u\n", noborder);
  1427. if(noborder == 1){winh = winw;}
  1428. printf("Resolution: %ux%u\n", winw, winh);
  1429. printf("Master Sensitivity: %.3f\n", sens_mul);
  1430. printf("DoubleStick: %u\n", doublestick);
  1431. printf("SS1: %.3f\n", ss1);
  1432. printf("SS2: %.3f\n\n", ss2);
  1433. // init glfw
  1434. if(!glfwInit()){exit(EXIT_FAILURE);}
  1435. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
  1436. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
  1437. #ifndef __arm__
  1438. if(noborder == 1)
  1439. glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, 1);
  1440. else
  1441. glfwWindowHint(GLFW_SAMPLES, msaa);
  1442. #endif
  1443. window = glfwCreateWindow(winw, winh, "Snowball.mobi", NULL, NULL);
  1444. if(!window)
  1445. {
  1446. glfwTerminate();
  1447. exit(EXIT_FAILURE);
  1448. }
  1449. const GLFWvidmode* desktop = glfwGetVideoMode(glfwGetPrimaryMonitor());
  1450. glfwSetWindowPos(window, (desktop->width/2)-(winw/2), (desktop->height/2)-(winh/2)); // center window on desktop
  1451. setBaseSensitivity(); // important
  1452. #ifndef __arm__
  1453. if(noborder == 1)
  1454. {
  1455. glfwSetWindowAttrib(window, GLFW_DECORATED, GLFW_FALSE);
  1456. zoom = -28.0f;
  1457. }
  1458. #endif
  1459. glfwSetWindowSizeCallback(window, window_size_callback);
  1460. glfwSetKeyCallback(window, key_callback);
  1461. glfwSetMouseButtonCallback(window, mouse_button_callback);
  1462. glfwSetScrollCallback(window, scroll_callback);
  1463. glfwMakeContextCurrent(window);
  1464. gladLoadGL(glfwGetProcAddress);
  1465. glfwSwapInterval(1); // 0 for immediate updates, 1 for updates synchronized with the vertical retrace, -1 for adaptive vsync
  1466. // set random icon
  1467. unsigned char* ipd = (unsigned char*)&icon_image2.pixel_data;
  1468. const uint r = qRandSeed(time(0), 0, 2);
  1469. if(r == 0) {ipd = (unsigned char*)&icon_image.pixel_data;}
  1470. else if(r == 1) {ipd = (unsigned char*)&icon_image1.pixel_data;}
  1471. else {ipd = (unsigned char*)&icon_image2.pixel_data;}
  1472. glfwSetWindowIcon(window, 1, &(GLFWimage){16, 16, ipd});
  1473. // seed random
  1474. srand(seed);
  1475. //*************************************
  1476. // projection
  1477. //*************************************
  1478. window_size_callback(window, winw, winh);
  1479. if(aspect < 1.0f){zoom = -26.0f;} // aspect correction
  1480. //*************************************
  1481. // bind vertex and index buffers
  1482. //*************************************
  1483. // ***** BIND MENU PLANE *****
  1484. GLfloat plane_vert[] = {1.000000,-1.000000,0.000000,-1.000000,1.000000,0.000000,-1.000000,-1.000000,0.000000,1.000000,1.000000,0.000000};
  1485. GLushort plane_indi[] = {0,1,2,0,3,1};
  1486. esBindModel(&mdlPlane, plane_vert, 9, plane_indi, 6);
  1487. GLfloat plane_texc[] = {1.f,1.f, 0.f,0.f, 0.f,1.f, 1.f,0.f};
  1488. esBind(GL_ARRAY_BUFFER, &mdlPlane.tid, plane_texc, sizeof(plane_texc), GL_STATIC_DRAW);
  1489. tex_menu = esLoadTexture(menu_image.width, menu_image.height, &menu_image.pixel_data[0]);
  1490. tex_mouse = esLoadTextureA(mouse_image.width, mouse_image.height, &mouse_image.pixel_data[0]);
  1491. // ***** BIND ICOGRID *****
  1492. esBindModel(&mdlGrid, icogrid_vertices, icogrid_numvert, icogrid_indices, icogrid_numind);
  1493. // ***** BIND SADPLY *****
  1494. esBindModel(&mdlSad, sad_vertices, sad_numvert, sad_indices, sad_numind);
  1495. // ***** BIND HEART *****
  1496. esBindModel(&mdlHeart, heart_vertices, heart_numvert, heart_indices, heart_numind);
  1497. // ***** BIND INTRO *****
  1498. esBindModel(&mdlIntro, intro_vertices, intro_numvert, intro_indices, intro_numind);
  1499. // ***** BIND TREE *****
  1500. esBind(GL_ARRAY_BUFFER, &mdlTree.vid, tree_vertices, sizeof(tree_vertices), GL_STATIC_DRAW);
  1501. esBind(GL_ARRAY_BUFFER, &mdlTree.cid, tree_colors, sizeof(tree_colors), GL_STATIC_DRAW);
  1502. esBind(GL_ARRAY_BUFFER, &mdlTree_iced, tree_iced_colors, sizeof(tree_iced_colors), GL_STATIC_DRAW);
  1503. esBind(GL_ARRAY_BUFFER, &mdlTree.nid, tree_normals, sizeof(tree_normals), GL_STATIC_DRAW);
  1504. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlTree.iid, tree_indices, sizeof(tree_indices), GL_STATIC_DRAW);
  1505. // ***** BIND POLE / OBELISK *****
  1506. esBind(GL_ARRAY_BUFFER, &mdlTele.vid, tele_vertices, sizeof(tele_vertices), GL_STATIC_DRAW);
  1507. esBind(GL_ARRAY_BUFFER, &mdlTele.nid, tele_normals, sizeof(tele_normals), GL_STATIC_DRAW);
  1508. esBind(GL_ARRAY_BUFFER, &mdlTele.cid, tele_colors, sizeof(tele_colors), GL_STATIC_DRAW);
  1509. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlTele.iid, tele_indices, sizeof(tele_indices), GL_STATIC_DRAW);
  1510. // ***** BIND TELE *****
  1511. esBind(GL_ARRAY_BUFFER, &mdlCat.vid, cat_vertices, sizeof(cat_vertices), GL_STATIC_DRAW);
  1512. esBind(GL_ARRAY_BUFFER, &mdlCat.nid, cat_normals, sizeof(cat_normals), GL_STATIC_DRAW);
  1513. esBind(GL_ARRAY_BUFFER, &mdlCat_aura, cat_aura_colors, sizeof(cat_aura_colors), GL_STATIC_DRAW);
  1514. esBind(GL_ARRAY_BUFFER, &mdlCat.cid, cat_colors, sizeof(cat_colors), GL_STATIC_DRAW);
  1515. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlCat.iid, cat_indices, sizeof(cat_indices), GL_STATIC_DRAW);
  1516. // ***** BIND SPHERE *****
  1517. esBind(GL_ARRAY_BUFFER, &mdlSphere.vid, icosmooth2_vertices, sizeof(icosmooth2_vertices), GL_STATIC_DRAW);
  1518. esBind(GL_ARRAY_BUFFER, &mdlSphere.nid, icosmooth2_normals, sizeof(icosmooth2_normals), GL_STATIC_DRAW);
  1519. esBind(GL_ELEMENT_ARRAY_BUFFER, &mdlSphere.iid, icosmooth2_indices, sizeof(icosmooth2_indices), GL_STATIC_DRAW);
  1520. //*************************************
  1521. // compile & link shader program
  1522. //*************************************
  1523. makeLambert();
  1524. makeLambert1();
  1525. makeLambert3();
  1526. makeFullbright();
  1527. makeFullbrightT();
  1528. //*************************************
  1529. // configure render options
  1530. //*************************************
  1531. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  1532. glEnable(GL_CULL_FACE);
  1533. glClearColor(0.0, 0.0, 0.0, 0.0);
  1534. //*************************************
  1535. // execute update / render loop
  1536. //*************************************
  1537. // reset game
  1538. t = glfwGetTime();
  1539. resetGame(0);
  1540. // event loop
  1541. double lt = t + 16, fc = 0;
  1542. double tp = 0, tpc = 0;
  1543. while(!glfwWindowShouldClose(window))
  1544. {
  1545. t = glfwGetTime();
  1546. glfwPollEvents();
  1547. main_loop();
  1548. fc++;
  1549. if(t > lt)
  1550. {
  1551. static double lp = 0;
  1552. char strts[16];
  1553. timestamp(&strts[0]);
  1554. printf("[%s] FPS: %f\n", strts, fc/16);
  1555. const double pps = (points-lp)/16;
  1556. printf("[%s] PPS: %f\n", strts, pps);
  1557. tp += pps;
  1558. tpc += 1;
  1559. fc = 0;
  1560. lp = points;
  1561. lt = t + 16;
  1562. }
  1563. }
  1564. // final score
  1565. char strts[16];
  1566. timestamp(&strts[0]);
  1567. printf("[%s] Level %d - Points %f - Time %f mins - Score %f - Avg PPS %f\n", strts, level, points, ((double)(t-start))/60.0, (points / sqrt(t-start))*100, tp / tpc);
  1568. // done
  1569. glfwDestroyWindow(window);
  1570. glfwTerminate();
  1571. exit(EXIT_SUCCESS);
  1572. return 0;
  1573. }