kenney.ino 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. #include <EEPROM.h>
  2. #include <SPI.h>
  3. #include <GD2.h>
  4. #include "kenney_assets.h"
  5. #define PLAYER1_SIZE (PLAYER1_HEIGHT + 8)
  6. #define HEART_SZ (HEART_HEIGHT + 14)
  7. static void rotate_player(int a)
  8. {
  9. GD.cmd_loadidentity();
  10. GD.cmd_translate(F16(PLAYER1_SIZE / 2),F16(PLAYER1_SIZE / 2));
  11. GD.cmd_rotate(a);
  12. GD.cmd_translate(F16(-PLAYER1_WIDTH / 2),F16(-PLAYER1_HEIGHT / 2));
  13. GD.cmd_setmatrix();
  14. }
  15. static void rotate_heart(int a)
  16. {
  17. GD.cmd_loadidentity();
  18. GD.cmd_translate(F16(HEART_SZ / 2),F16(HEART_SZ / 2));
  19. GD.cmd_rotate(a);
  20. GD.cmd_translate(F16(-HEART_WIDTH / 2),F16(-HEART_HEIGHT / 2));
  21. GD.cmd_setmatrix();
  22. }
  23. #define BLOBS 32
  24. class Trail {
  25. public:
  26. int idx;
  27. int x[BLOBS];
  28. int y[BLOBS];
  29. int sz[BLOBS];
  30. void add(int nx, int ny) {
  31. x[idx] = nx;
  32. y[idx] = ny;
  33. sz[idx] = 192;
  34. idx = (idx + 1) % BLOBS;
  35. }
  36. void draw(int sy) {
  37. for (int i = 0; i < BLOBS; i++) {
  38. if (sz[i]) {
  39. GD.PointSize(sz[i]);
  40. GD.Vertex2f(x[i], -(sy << 4) + y[i]);
  41. sz[i] -= 1;
  42. y[i] += 12;
  43. }
  44. }
  45. }
  46. };
  47. struct xy {
  48. int x, y;
  49. };
  50. struct {
  51. xy p[3];
  52. Trail trail[3];
  53. xy hearts[20];
  54. xy clouds[20];
  55. } state;
  56. static void polar(uint16_t th, int r)
  57. {
  58. int x, y;
  59. GD.polar(x, y, r, th);
  60. GD.Vertex2f(16 * 240 + x, 16 * 136 + y);
  61. }
  62. #define RAYS 7
  63. #define RAYSIZE (65536 / RAYS)
  64. #define RAYEDGE (4 * 16)
  65. static void ray(uint16_t th, int r0, int r1)
  66. {
  67. polar(th, r0);
  68. polar(th, r1);
  69. polar(th + RAYSIZE / 2, r1);
  70. polar(th + RAYSIZE / 2, r0);
  71. polar(th, r0);
  72. }
  73. // c1 is edge color, c2 is interior color
  74. static void burst(uint16_t th, int r, uint32_t c1, uint32_t c2)
  75. {
  76. GD.Clear(0,1,0);
  77. GD.ColorMask(0,0,0,0);
  78. GD.StencilOp(KEEP, INVERT);
  79. GD.StencilFunc(ALWAYS, 255, 255);
  80. for (int i = 0; i < RAYS; i++) {
  81. GD.Begin(EDGE_STRIP_A);
  82. ray(th + (i * RAYSIZE), r / 4, r + (r >> 4));
  83. }
  84. GD.ColorMask(1,1,1,1);
  85. GD.StencilFunc(EQUAL, 255, 255);
  86. GD.StencilOp(KEEP, KEEP);
  87. GD.Begin(POINTS);
  88. GD.ColorRGB(c1);
  89. GD.PointSize(r);
  90. GD.Vertex2ii(240, 136);
  91. GD.ColorRGB(c2);
  92. GD.PointSize(r - RAYEDGE);
  93. GD.Vertex2ii(240, 136);
  94. GD.ColorRGB(c1);
  95. GD.PointSize((r / 4) + RAYEDGE);
  96. GD.Vertex2ii(240, 136);
  97. GD.StencilFunc(ALWAYS, 255, 255);
  98. GD.LineWidth(RAYEDGE / 2);
  99. for (int i = 0; i < RAYS; i++) {
  100. GD.Begin(LINES);
  101. ray(th + (i * RAYSIZE), r / 4 + (RAYEDGE / 2), r - (RAYEDGE / 2));
  102. }
  103. }
  104. static void sunrise(int t)
  105. {
  106. static int r = 0, v = 0;
  107. // yellow 0xffcc00
  108. // reddish 0xe86a17
  109. // blue 0x1ea7e1
  110. // green 0x73cd4b
  111. GD.ColorRGB(C1B);
  112. GD.PointSize((r * 3) >> 4);
  113. GD.Begin(POINTS);
  114. GD.Vertex2f(16 * 240, 16 * 136);
  115. // GD.ColorA(min(255, t * 6));
  116. if (t == 0) {
  117. r = 0;
  118. v = 0;
  119. }
  120. burst(t * -261, r + (r >> 1), C2B, C2);
  121. burst(t * 335, r, C1B, C1);
  122. int f = ((16L * 130) - r) / 29;
  123. v = ((v + f) * 243L) >> 8;
  124. r += v;
  125. }
  126. static void draw(int t)
  127. {
  128. int y = 1648 - t;
  129. // GD.finish(); long t0 = micros();
  130. // GD.ClearColorRGB(0xd0f4f7); GD.Clear();
  131. GD.cmd_gradient(0, 0, 0xa0a4f7, //' gradient{
  132. 0, 272, 0xd0f4f7); //' }gradient
  133. if (360 <= t) {
  134. GD.RestoreContext();
  135. sunrise(t - 360);
  136. }
  137. GD.Begin(BITMAPS); //' clouds{
  138. GD.BlendFunc(ONE, ONE_MINUS_SRC_ALPHA);
  139. GD.BitmapHandle(CLOUD_HANDLE);
  140. GD.Cell(0);
  141. for (int i = 0; i < 20; i++) {
  142. byte lum = 128 + 5 * i;
  143. GD.ColorA(lum);
  144. GD.ColorRGB(lum, lum, lum);
  145. GD.Vertex2f(state.clouds[i].x, state.clouds[i].y);
  146. state.clouds[i].y += (4 + (i >> 3));
  147. if (state.clouds[i].y > (16 * 272))
  148. state.clouds[i].y -= 16 * (272 + CLOUD_HEIGHT);
  149. } //' }clouds
  150. GD.RestoreContext();
  151. GD.BlendFunc(ONE, ONE_MINUS_SRC_ALPHA);
  152. GD.Begin(BITMAPS); //' tiles{
  153. GD.BitmapHandle(TILES_HANDLE);
  154. const PROGMEM uint8_t *src = layer1_map + (y >> 5) * 15;
  155. byte yo = y & 31;
  156. for (byte j = 0; j < 10; j++)
  157. for (byte i = 0; i < 15; i++) {
  158. byte t = pgm_read_byte_near(src++);
  159. if (t != 0) {
  160. GD.Cell(t - 1);
  161. GD.Vertex2f(16 * 32 * i, 16 * ((32 * j) - yo));
  162. }
  163. } //' }tiles
  164. // GD.BlendFunc(SRC_ALPHA, ZERO);
  165. uint16_t a = t * 100;
  166. uint16_t a2 = a << 1;
  167. uint16_t a3 = a2 << 1;
  168. state.p[0].x = 16 * 240 + GD.rsin(16 * 120, a) + GD.rsin(16 * 120, a2);
  169. state.p[0].y = 16 * 136 + GD.rsin(16 * 70, a3);
  170. state.p[1].x = 16 * 240 + GD.rsin(16 * 240, a);
  171. state.p[1].y = 16 * 100 + GD.rsin(16 * 36, a2);
  172. state.p[2].x = 16 * 240 + GD.rsin(16 * 240, a2);
  173. state.p[2].y = 16 * 135 + GD.rsin(16 * 10, a) + GD.rsin(16 * 18, a3);
  174. for (int i = 0; i < 3; i++) {
  175. if ((t & 3) == 0) {
  176. state.trail[i].add(state.p[i].x, (y << 4) + state.p[i].y);
  177. }
  178. GD.BlendFunc(SRC_ALPHA, ONE_MINUS_SRC_ALPHA);
  179. GD.Begin(POINTS);
  180. GD.ColorA(0x90);
  181. uint32_t colors[3] = {0x8bcfba, 0x8db5e7, 0xf19cb7};
  182. GD.ColorRGB(colors[i]);
  183. state.trail[i].draw(y);
  184. }
  185. GD.ColorRGB(0xffffff);
  186. GD.ColorA(0xff);
  187. GD.BlendFunc(ONE, ONE_MINUS_SRC_ALPHA);
  188. GD.BitmapHandle(PLAYER1_HANDLE); //' player{
  189. GD.Begin(BITMAPS);
  190. for (int i = 0; i < 3; i++) {
  191. rotate_player(a + i * 0x7000);
  192. GD.Cell(i);
  193. GD.Vertex2f(state.p[i].x - (16 * PLAYER1_SIZE / 2),
  194. state.p[i].y - (16 * PLAYER1_SIZE / 2));
  195. } //' }player
  196. if (t > 480) {
  197. GD.BlendFunc(SRC_ALPHA, ONE_MINUS_SRC_ALPHA);
  198. GD.ColorA(min((t - 480) * 4, 255));
  199. GD.Begin(BITMAPS);
  200. GD.BitmapHandle(HEART_HANDLE);
  201. GD.Cell(0);
  202. for (int i = 0; i < 20; i++) {
  203. if ((i & 3) == 0)
  204. rotate_heart(a + (i << 12));
  205. GD.Vertex2f(state.hearts[i].x - (16 * HEART_SZ / 2), state.hearts[i].y);
  206. state.hearts[i].y += 30 + (i << 2);
  207. if (state.hearts[i].y > (16 * 272))
  208. state.hearts[i].y -= 16 * (272 + HEART_SZ);
  209. }
  210. }
  211. // GD.RestoreContext(); GD.cmd_number(0, 0, 26, 6, micros() - t0);
  212. GD.swap();
  213. }
  214. void setup()
  215. {
  216. GD.begin();
  217. Serial.begin(1000000);
  218. // GD.wr32(REG_PWM_HZ, 18000); GD.wr(REG_PWM_DUTY, 64);
  219. GD.Clear();
  220. LOAD_ASSETS();
  221. // Handle Graphic
  222. // 0 Tiles
  223. byte hy[] = {36, 12, 144, 204, 216, 120, 48, 168, 192, 84, 72, 60, 24, 180, 0, 108, 228, 132, 156, 96};
  224. for (int i = 0; i < 20; i++) {
  225. state.hearts[i].x = random(16 * 480);
  226. state.hearts[i].y = 16 * hy[i];
  227. state.clouds[i].x = 16 * (random(480) - (CLOUD_WIDTH / 2));
  228. state.clouds[i].y = 16 * hy[i];
  229. }
  230. }
  231. void loop()
  232. {
  233. for (int t = 0; t < 720; t++) {
  234. draw(t);
  235. }
  236. }