#include #include "basic/basic.h" #include "lcd/lcd.h" #include "usetable.h" #define O_FIXED 1023 #define SPP 10 static void draw_rakett (int x, int y, int scale, int angle); static int my_gray (int x, int y, void *data); static int o_sin(int x); static int o_cos(int x); static int frame_no = 0; #define ANIM(start_val, end_val) \ (((start_val) * (1000-(t))) / 1000 + ((end_val) * ((t))) /1000) void ram (void) { char test[512]; /* scratch space */ o_init (test, sizeof(test)); int frame_dir = 1; int inpt; o_set_shader (my_gray, NULL); int x; int y; int angle; int scale; int velocity = 0; frame_no=0; while ((inpt = getInputRaw()) != BTN_ENTER) { int t; o_identity (); /* reset tranforms */ o_set_gray (0); o_rectangle (0,0,RESX, RESY); /* fill background with black */ o_fill (); /* fill with 50% gray */ if (frame_no < 800) { o_set_gray (250); o_rectangle (0,RESY-7,RESX, 10); /* fill background with black */ o_fill (); /* fill with 50% gray */ } if (frame_no < 100) { t = frame_no * 1000 / 100; x = ANIM(-60 * 10, 100 * 10); y = RESY/2 * 10; angle = ANIM(500, 300); scale = ANIM(1200, 700); } else if (frame_no < 300) { t = (frame_no - 100) * 1000 / 200; x = ANIM(100 * 10, 10 * RESX/2); y = ANIM((RESY/2) * 10, (RESY/2 - 10) * 10); angle = ANIM(300, 0); scale = ANIM(700, 300); } else if (frame_no < 600) { t = (frame_no - 300) * 1000 / 300; x = RESX/2 * 10; y = ANIM((RESY/2-10) * 10, (RESY-14) * 10); angle = 0; scale = 300; } else { /* flying time */ if (inpt == BTN_UP) { velocity ++; } else if (inpt == BTN_DOWN) { velocity --; } else if (inpt == BTN_LEFT) { angle -= 5; } else if (inpt == BTN_RIGHT) { angle += 5; } if (velocity > 10) velocity = 10; if (velocity < -10) velocity = -10; { int c = o_cos ((angle - 900) * 4 * 8192 / 3600) / 4; int s = o_sin ((angle - 900) * 4 * 8192 / 3600) / 4; x += (c / 100) * velocity / 10; y += (s / 100) * velocity / 10; } y++; if (y > (RESY-14) * 10) y = (RESY-14) * 10; } draw_rakett (x, y, scale, angle); frame_no += frame_dir; lcdDisplay(); } } static int my_gray (int x, int y, void *data) { int value = (int)(data); switch (value) { case 0: /* 0.0 */ return 0; case 1: /* 0.16 */ return (x%3==0) ? (y %2)? 0:0: (x%3==1) ? (y %2)? 0:0: (y %2)? 0:1; case 2: /* 0.25 */ switch (frame_no % 4) { case 0: return (x%2) ? (y %2)? 1:0: (y %2)? 0:0; case 1: return (x%2) ? (y %2)? 0:1: (y %2)? 0:0; case 2: return (x%2) ? (y %2)? 0:0: (y %2)? 0:1; case 3: return (x%2) ? (y %2)? 0:0: (y %2)? 1:0; } case 3: /* 0.33 */ return (x%3==0) ? (y %2)? 1:0: (x%3==1) ? (y %2)? 0:0: (y %2)? 0:1; case 4: /* 0.50 */ if (frame_no %2) return (x%2==0) ? (y %2)? 1:0: (y %2)? 0:1; else return (x%2==0) ? (y %2)? 0:1: (y %2)? 1:0; case 5: /* 0.66 */ return (x%3==0) ? (y %2)? 0:1: (x%3==1) ? (y %2)? 1:1: (y %2)? 1:0; case 6: /* 0.75 */ return (x%2) ? (y %2)? 1:0: (y %2)? 1:1; case 7: /* 0.85 */ return (x%3==0) ? (y %2)? 1:1: (x%3==1) ? (y %2)? 1:0: (y %2)? 1:1; case 8: /* 1.0 */ return 1; default: // return ((char)(rnd1())) < value; /* XXX: use a faster "random" source for this fallback */ break; } return 0; } /* This is a very simple vector drawing of heart of gold encoded in a * string (search and replace regexp-fu on an SVG made in inkscape was * used to create the strings) * * to reduce size, all coordinates are encoded as bytes, 'g'ray values * are in the range 0-100. */ static signed char rakett[] = { ' ', 'm',38,6, 'c',38,6,36,13,36,15, 'c',24,22,23,26,21,32,'c',19,41,23,61,23,61,'c',15,73,14,95,17,110,'l',26,109,'c',26,102,26,87,30,83,'c',30,83,30,88,30,95,'c',31,103,31,108,31,108,'l',36,108,'c',36,108,35,98,36,91,'c',37,83,38,80,38,80,'c',41,79,43,80,47,79,'c',56,85,56,89,58,99,'c',58,103,58,108,58,108,'l',68,108,'c',67,89,69,73,54,58,'c',54,58,56,41,53,31,'c',50,21,40,15,40,15,'l',38,6,'z','g',100,'f','g',100,'s', ' ', 'm',33,20,'c',31,20,29,21,27,22,'c',25,24,23,27,22,29,'c',20,35,21,38,21,38,'c',26,38,29,36,34,33,'c',38,31,42,24,34,21,'c',34,21,33,20,33,20,'z','g', 50,'f','.' }; static const signed char * o_process_op (const signed char *g) { switch (*g++) { case ' ': o_path_new (); break; /* all of these path commands are directly in integer coordinates */ case 'm': o_move_to (g[0], g[1]); g += 2; break; case 'l': o_line_to (g[0], g[1]); g += 2; break; case 'c': o_curve_to (g[0], g[1], g[2], g[3], g[4], g[5]); g += 6; break; case 'z': o_close (); break; case 'g': o_set_gray (g[0]*10); g ++; break; case 'f': o_fill (); break; case 's': break; //case 's': o_stroke (); break; /* 1 = 1 10 = 10 100 = 100 */ #if 0 case '!': o_identity (); break; case 'T': o_translate (g[0] * 100, g[1] * 100); g+=2; break; /* 1 = 0.01 10 = 0.1 50 = 0.5 100 = 10x */ case 'S': o_scale (g[0] * 10, g[1] * 10); g+=2; break; /* -128 = -360 64 = 180 128 = 360 */ case 'R': o_rotate ((g[0] * 3600)/127); g+=1; break; #endif default: case '\0': case '.': /* end */ return NULL; } return g; } static void orender (const signed char *g) { for (; g; g = o_process_op (g)); } void o_rectangle (int x0, int y0, int width, int height) { o_path_new (); o_move_to (x0, y0); o_line_to (x0 + width, y0); o_line_to (x0 + width, y0+height); o_line_to (x0, y0+height); o_close (); } static int o_sin(int x) { #define qN 13 #define qA 12 #define qP 15 #define qR (2*qN-qP) #define qS (qN+qP+1-qA) x= x<<(30-qN); // shift to full s32 range (Q13->Q30) if( (x^(x<<1)) < 0) // test for quadrant 1 or 2 x= (1<<31) - x; x= x>>(30-qN); return (x * ( (3<>qR) ) >> qS ); } static inline int o_cos(int x) { return o_sin(x + 8192); } static void draw_rakett (int x, int y, int scale, int angle) { /* directly including the matrices used to build up the transform, the fudging factors depend on internal values of o to add up properly */ OMatrix mtranslate = {{{O_FIXED,0}, {0,O_FIXED}, {x * 100 * SPP * O_FIXED / 1000, y * 100 * SPP * O_FIXED / 1000}}}; int c = o_cos (angle * 4 * 8192 / 3600) / 4; int s = o_sin (angle * 4 * 8192 / 3600) / 4; OMatrix mrotate = {{{c,s}, {-s,c}, {0, 0}}}; OMatrix mscale = {{{scale * O_FIXED / 1000, 0}, {0,scale * O_FIXED / 1000}, {0,0}}}; OMatrix mtranslate2 = {{{O_FIXED,0}, {0,O_FIXED}, {-37000 * SPP * O_FIXED / 1000, -60000 * SPP * O_FIXED / 1000}}}; o_transform (&mtranslate, 1); /* passing 1 as second arg sets the transform to this */ o_transform (&mrotate, 0); /* passing 0 adds this transformaiton */ o_transform (&mscale, 0); /* again (it is multiplying the matrices internally) */ o_transform (&mtranslate2, 0); /* the final translate (first actually) sets the local origin. */ orender (rakett); /* render the rocket data */ }