Subversion Repositories Kolibri OS

Rev

Rev 5237 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include "rsgame.h"
  2.  
  3. #include "rsgametext.h"
  4.  
  5. #include "rsgamemenu.h"
  6.  
  7. #include "rsgamedraw.h"
  8.  
  9. #include "rskos.h"
  10.  
  11. #include "rsgentex.h"
  12. #include "rssoundgen.h"
  13. #include "rsnoise.h"
  14.  
  15. #include "rs/rsplatform.h"
  16.  
  17.  
  18. #ifdef RS_USE_C_LIBS // linux version
  19.     #include <math.h>
  20.     #include <stdlib.h>
  21.     #include <string.h>
  22.    
  23.     #include "rs/rskeyboard.h"
  24. #endif
  25.  
  26.  
  27.  
  28. rs_game_t game;
  29.  
  30.  
  31. void texture_init(rs_texture_t *tex, int w, int h) {
  32.     tex->status = 1;
  33.     tex->w = w;
  34.     tex->h = h;
  35.     tex->data = malloc(w*h*4); // BGRA BGRA
  36. };
  37.  
  38. void texture_free(rs_texture_t *tex) {
  39.     free(tex->data);
  40.     tex->status = 0;
  41. };
  42.  
  43. void texture_clear(rs_texture_t *tex, unsigned int color) {
  44.     int i;
  45.     for (i = 0; i < tex->w * tex->h; i++) {
  46.         *((unsigned int*)(&tex->data[i*4])) = color;
  47.     };
  48. };
  49.  
  50. void texture_draw(rs_texture_t *dest, rs_texture_t *src, int x, int y, int mode) {
  51.    
  52.     int i; // y
  53.     int j; // x
  54.     int k; // color component
  55.    
  56.     int istart = (y < 0) ? -y : 0;
  57.     int iend = src->h - (( (y + src->h) > dest->h) ? (y + src->h - dest->h) : 0);
  58.    
  59.     int jstart = (x < 0) ? -x : 0;
  60.     int jend = src->w - (( (x + src->w) > dest->w) ? (x + src->w - dest->w) : 0);
  61.    
  62.     int ishift = 0;
  63.     int jshift = 0;
  64.    
  65.     float a; // alpha value
  66.    
  67.     if (mode & DRAW_TILED_FLAG) {
  68.         jshift = x;
  69.         ishift = y;
  70.         x = y = istart = jstart = 0;
  71.         iend = dest->h;
  72.         jend = dest->w;
  73.     };
  74.    
  75.     mode = mode & DRAW_MODE_MASK;
  76.    
  77.     int modvalue = (src->w*src->h*4);
  78.    
  79.     if (mode == DRAW_MODE_REPLACE) {
  80.         for (i = istart; i < iend; i++) {
  81.             for (j = jstart; j < jend; j++) {
  82.                 for (k = 0; k < 4; k++) {
  83.                     dest->data[ 4 * ( (y+i)*dest->w + (x+j) ) + k ] = src->data[ (4*(i*src->w + j) + k) % modvalue ];
  84.                 };
  85.             };
  86.         };
  87.     }
  88.     else if (mode == DRAW_MODE_ADDITIVE) {
  89.         for (i = istart; i < iend; i++) {
  90.             for (j = jstart; j < jend; j++) {
  91.                 for (k = 0; k < 3; k++) { // Alpha channel is not added
  92.                     dest->data[ 4 * ( (y+i)*dest->w + (x+j) ) + k ] =
  93.                         clamp_byte( dest->data[ 4 * ( (y+i)*dest->w + (x+j) ) + k ] + src->data[ (4*((i+ishift)*src->w + j + jshift) + k) % modvalue] );
  94.                 };
  95.             };
  96.         };
  97.     }
  98.     else if (mode == DRAW_MODE_MULT) {
  99.         for (i = istart; i < iend; i++) {
  100.             for (j = jstart; j < jend; j++) {
  101.                 for (k = 0; k < 3; k++) { // Alpha channel is not added
  102.                     dest->data[ 4 * ( (y+i)*dest->w + (x+j) ) + k ] =
  103.                         clamp_byte( dest->data[ 4 * ( (y+i)*dest->w + (x+j) ) + k ] * src->data[ (4*((i+ishift)*src->w + j + jshift) + k) % modvalue] / 255 );
  104.                 };
  105.             };
  106.         };
  107.     }
  108.     else if (mode == DRAW_MODE_ALPHA) {
  109.         for (i = istart; i < iend; i++) {
  110.             for (j = jstart; j < jend; j++) {
  111.                 for (k = 0; k < 3; k++) {
  112.                     a = (1.0 * src->data[ (4*(i*src->w + j) + 3) % modvalue ] / 255.0);
  113.                     dest->data[ 4 * ( (y+i)*dest->w + (x+j) ) + k ] =
  114.                          (unsigned char) ( (1.0-a) * dest->data[ 4 * ( (y+i)*dest->w + (x+j) ) + k ]
  115.                                           + a*src->data[ (4*((i+ishift)*src->w + j + jshift) + k) % modvalue] );
  116.                 };
  117.             };
  118.         };
  119.     };
  120.    
  121. };
  122.  
  123.  
  124.  
  125. void texture_set_pixel(rs_texture_t *tex, int x, int y, unsigned int color) {
  126.     *((unsigned int*) &tex->data[ 4 * ( (y)*tex->w + (x) ) + 0 ]) = color;
  127. };
  128.  
  129. void texture_draw_vline(rs_texture_t *tex, int x, int y, int l, unsigned int color) {
  130.     int i;
  131.     if (y+l >= tex->h) {
  132.         l = tex->h - y;
  133.     };
  134.     for (i = 0; i < l; i++) {
  135.         *((unsigned int*) &tex->data[ 4 * ( (y+i)*tex->w + (x) ) + 0 ]) = color;
  136.     };    
  137. };
  138.  
  139.  
  140.  
  141. void soundbuf_init(rs_soundbuf_t *snd, int length_samples) {
  142.     snd->status = 1;
  143.     snd->length_samples = length_samples;
  144.     snd->data = malloc(length_samples*2);
  145.     rskos_snd_create_buffer(&snd->hbuf, snd->data, length_samples);
  146. };
  147.  
  148. void soundbuf_free(rs_soundbuf_t *snd) {
  149.     snd->status = 0;
  150.     free(snd->data);
  151. };
  152.  
  153. void soundbuf_fill(rs_soundbuf_t *snd, int amp, int freq_div) {
  154.     int i;
  155.     for (i = 0; i < snd->length_samples; i++) {
  156.                 snd->data[i] = -amp/2 + amp/2*( ( (i % freq_div) > freq_div/2 ) ? 1 : 0 );
  157.         };
  158.         rskos_snd_update_buffer(&snd->hbuf, snd->data, snd->length_samples);
  159. };
  160.  
  161. void soundbuf_sin(rs_soundbuf_t *snd, float freq) {
  162.     int i;
  163.     int amp = 29000;
  164.     for (i = 0; i < snd->length_samples; i++) {
  165.                 snd->data[i] = ( 1.0 - 1.0*i/snd->length_samples ) * sin(freq*i) * amp;
  166.         };
  167.         rskos_snd_update_buffer(&snd->hbuf, snd->data, snd->length_samples);
  168. };
  169.  
  170. void soundbuf_sin_fade(rs_soundbuf_t *snd, float freq) {
  171.     int i;
  172.     int amp = 29000;
  173.     for (i = 0; i < snd->length_samples; i++) {
  174.                 snd->data[i] = ( 1.0 - 1.0*i/snd->length_samples ) * sin( ( (1.0 - 0.48*i/snd->length_samples) * freq ) *i) * amp;
  175.         };
  176.        
  177.        
  178.         /*
  179.        
  180.         // ok
  181.        
  182.         rs_sgen_init(2, snd->length_samples);
  183.         rs_sgen_func_pm(1, 880.0, 21.0, 0.3, 110.0, 0.3);
  184.         rs_sgen_func_normalize(1, 1.0);
  185.         rs_sgen_func_lowpass(0, 1, 1.0, 0.0, 1.0);
  186.         rs_sgen_wave_out(0);
  187.        
  188.         memcpy(snd->data, rs_sgen_reg.wave_out, snd->length_samples*2 );
  189.        
  190.         rs_sgen_term();
  191.        
  192.         */
  193.        
  194.         rskos_snd_update_buffer(&snd->hbuf, snd->data, snd->length_samples);
  195. };
  196.  
  197. void soundbuf_play(rs_soundbuf_t *snd) {
  198.     rskos_snd_play(&snd->hbuf, 0);
  199. };
  200.  
  201. void soundbuf_stop(rs_soundbuf_t *snd) {
  202.     rskos_snd_stop(&snd->hbuf);
  203. };
  204.  
  205.  
  206.  
  207. unsigned char clamp_byte(int value) {
  208.     value = value * (1 - (value >> 31)); // negative to zero
  209.     return (value > 255) ? 255 : value;
  210. };
  211.  
  212.  
  213. void game_reg_init() {
  214.    
  215.     game.loader_counter = 0;
  216.    
  217.     game.score = 0;
  218.     game.time = 0;
  219.  
  220.     game.selected = 0;
  221.     game.selected_x = game.selected_y = 0;
  222.    
  223.     game.explosions_count = 0;
  224.    
  225.     game.tx = 0;
  226.     game.ty = 0;
  227.     game.tz = 0;
  228.  
  229. //    int i;
  230. //    for (i = 0; i < BULLETS_COUNT; i++) {
  231. //        game.bullet_x[i] = 0;
  232. //        game.bullet_y[i] = 0;
  233. //    };
  234. //    game.bullet_index = 0;
  235.    
  236.     game.status = STATUS_LOADING;
  237.  
  238.     game.window_scale = 1;
  239.    
  240. //    game.window_scale = 2;
  241. //    #ifndef RS_KOS
  242. //        game.window_scale = 3;
  243. //        window_scale_str[3] = '3';
  244. //    #endif
  245.    
  246.     game.keyboard_state = 0;
  247.    
  248.     game.menu_index = 0;
  249.     game.menu_item_index = 0;
  250. };
  251.  
  252.  
  253. int is_key_pressed(int mask) {
  254.     return IS_BIT_SET(game.keyboard_state, mask) ? 1 : 0;
  255. };
  256.  
  257. int seed = 0;
  258. int get_random_crystal() {
  259.     seed += 2;
  260.     return ( (seed + (get_time() & 0xFFFF) ) % CRYSTALS_COUNT) | CRYSTAL_VISIBLE_BIT;
  261. };
  262.  
  263. int game_check_and_explode() {
  264.     int x, y, i, item, match_count, found;
  265.     found = 0;
  266.    
  267.     // vertical lines
  268.     for (x = 0; x < FIELD_WIDTH; x++) {
  269.         match_count = 0;
  270.         item = 0xFF;
  271.         for (y = FIELD_HEIGHT-1; y >= 0; y--) {
  272.                
  273.             if ( IS_BIT_SET( FIELD_ITEM(x,y), CRYSTAL_MOVING_BIT ) || IS_BIT_CLEARED( FIELD_ITEM(x,y), CRYSTAL_VISIBLE_BIT) ) {
  274.                 item = 0xFF;
  275.                 match_count = 0;
  276.                 continue;
  277.             };
  278.            
  279.             if ( (FIELD_ITEM(x,y) & CRYSTAL_INDEX_MASK) == item) {
  280.                 match_count++;
  281.             }
  282.             else {
  283.                 if (match_count >= 2) {
  284.                     found = 1;
  285. //                    DEBUG10f("found vert (x %d, y %d, count %d) \n", x, y, match_count);
  286.                     for (i = y+1; i < y+1+match_count+1; i++) {
  287.                         BIT_SET( FIELD_ITEM(x, i), CRYSTAL_EXPLODED_BIT );
  288.                     };
  289.                 }
  290.                 item = FIELD_ITEM(x,y) & CRYSTAL_INDEX_MASK;
  291.                 match_count = 0;
  292.             };
  293.         };
  294.         if (match_count >= 2) { // last
  295.             found = 1;
  296.             for (i = y+1; i < y+1+match_count+1; i++) {
  297.                 BIT_SET( FIELD_ITEM(x, i), CRYSTAL_EXPLODED_BIT );
  298.             };
  299.         };
  300.     };
  301.    
  302.     // horizontal lines
  303.     for (y = 0; y < FIELD_HEIGHT; y++) {
  304.            
  305.         match_count = 0;
  306.         item = 0xFF;
  307.         for (x = FIELD_WIDTH-1; x >= 0; x--) {
  308.  
  309.             if ( IS_BIT_SET( FIELD_ITEM(x,y), CRYSTAL_MOVING_BIT ) || IS_BIT_CLEARED( FIELD_ITEM(x,y), CRYSTAL_VISIBLE_BIT) ) {
  310.                 item = 0xFF;
  311.                 match_count = 0;
  312.                 continue;
  313.             };
  314.  
  315.             if ( (FIELD_ITEM(x,y) & CRYSTAL_INDEX_MASK) == item) {
  316.                 match_count++;
  317.             }
  318.             else {
  319.                 if (match_count >= 2) {
  320.                     found = 1;
  321. //                    DEBUG10f("found horiz (x %d, y %d, count %d) \n", x, y, match_count);
  322.                     for (i = x+1; i < x+1+match_count+1; i++) {
  323.                         BIT_SET( FIELD_ITEM(i, y), CRYSTAL_EXPLODED_BIT );
  324.                     };
  325.                 }
  326.                 item = FIELD_ITEM(x,y) & CRYSTAL_INDEX_MASK;
  327.                 match_count = 0;
  328.             };
  329.         };
  330.         if (match_count >= 2) { // last
  331.             found = 1;
  332. //            DEBUG10("found horiz (2)");
  333.             for (i = x+1; i < x+1+match_count+1; i++) {
  334.                 BIT_SET( FIELD_ITEM(i, y), CRYSTAL_EXPLODED_BIT );
  335.             };
  336.         };
  337.     };
  338.  
  339.     for (i = 0; i < FIELD_LENGTH; i++) {
  340.         if (IS_BIT_SET(game.field[i], CRYSTAL_EXPLODED_BIT)) {
  341.             game.field[i] = 0;
  342.             game.score++;
  343.             if (game.explosions_count < EXPLOSIONS_MAX_COUNT-1) {
  344.                 game.explosions[game.explosions_count] = ( i % FIELD_WIDTH ) | ( (i / FIELD_WIDTH) << 8);
  345.                 game.explosions_count++;
  346.             };
  347.         };
  348.     };
  349.    
  350.     if (game.score > 99) {
  351.         game.status = STATUS_MENU;
  352.     };
  353.    
  354. //    DEBUG10f("found = %d \n", found);
  355.     return found;
  356. };
  357.  
  358. void game_fall() {
  359.     int x, y, fall;
  360.     for (x = 0; x < FIELD_WIDTH; x++) {
  361.         fall = 0;
  362.         for (y = FIELD_HEIGHT-1; y > 0; y--) {
  363.             fall |= !(FIELD_ITEM(x, y) & CRYSTAL_VISIBLE_BIT);
  364.             if (fall) {
  365.                 FIELD_ITEM(x, y) = FIELD_ITEM(x, y-1) | CRYSTAL_MOVING_BIT;
  366.             }
  367.             else {
  368.                 BIT_CLEAR( FIELD_ITEM(x, y), CRYSTAL_MOVING_BIT );
  369.             };
  370.         };
  371.         if ( (fall) || ( IS_BIT_CLEARED(FIELD_ITEM(x,0), CRYSTAL_VISIBLE_BIT) ) ) {
  372.             FIELD_ITEM(x, 0) = get_random_crystal();
  373.         };
  374.     };
  375. };
  376.  
  377. int process_timer = 0;
  378.  
  379. void GameProcess() {
  380.    
  381.     if (game.status == STATUS_LOADING) {
  382.         game.loader_counter++;
  383.         if (game.loader_counter == 2) {
  384.                
  385. //            texture_clear(&game.tex_bg, COLOR_SILVER);
  386. //             /*
  387.                
  388.             rs_gen_init(6, 512);
  389.             rs_gen_func_perlin(0, 8, 5, 0.5, 1100);
  390.             rs_gen_func_normalize(0, 0.0, 1.0);
  391.             rs_gen_func_perlin(1, 8, 5, 0.5, 1700);
  392.             rs_gen_func_normalize(1, 0.0, 1.0);
  393.             rs_gen_func_cell(2, 1360, 50, NULL, 1.0, 0.887, -0.333, 1.0, 0.0, 4.0);
  394.             rs_gen_func_normalize(2, 0.0, 0.5);
  395.  
  396.             rs_gen_func_adr(3, 2, 0, 1, 1.0, 0.3);
  397.            
  398.             rs_gen_func_inv(3, 3, 7.5);
  399.             rs_gen_func_normalize(3, 0.0, 1.0);
  400.  
  401. //            signed short c[] = { 0, 250, 250, 0, 500, 250, 250, 500};
  402.             signed short c[] = { 0, 0, 0, 512, 512, 0, 512, 512};
  403. //            signed short c[] = { 128, 128, 128, 384, 384, 128, 384, 384};
  404.             //rs_gen_func_cell(4, 0, 4, c, 0.0, 0.3, 1.0, 0.5, 0.0, 0.30);
  405.             rs_gen_func_cell(4, 0, 4, c, 1.0, 0.3, 0.0, 0.95, 0.0, 0.30);
  406.             rs_gen_func_normalize(4, 0.0, 1.0);
  407.  
  408. //            rs_gen_func_radial(5, 0.5, 0.5, 0.60, 1.0, 4.0);
  409. //            rs_gen_func_add(4, 4, 5, 0.5, 0.5);
  410. //
  411.             rs_gen_func_mult(4, 4, 3);
  412.            
  413.             // coloring...
  414.             rs_gen_func_mult_add_value(0, 4, 0.8, 0.0);
  415.             rs_gen_func_add(0, 4, 1, 0.95, 0.05);
  416.             rs_gen_func_add(3, 4, 2, 0.95, 0.05);
  417.  
  418.            
  419.             rs_gen_tex_out_rgba(4, 0, 3, -1, 0.9, 0.9, 0.9, 1.0);
  420.             memcpy(game.tex_bg.data, rs_gen_reg.tex_out, 512*512*4 );
  421.             rs_gen_term();
  422.            
  423.             // */
  424.            
  425.            
  426.        
  427.             game.status = STATUS_MENU;
  428.  
  429.         };
  430.     }
  431.     else if (game.status == STATUS_PLAYING) {
  432.            
  433.            
  434.         process_timer++;
  435.  
  436.         if (process_timer > 3) {
  437.             game_check_and_explode();
  438.             game_fall();
  439.             process_timer = 0;
  440.         };
  441.        
  442.         int i;
  443.         for (i = 0; i < game.explosions_count; i++) {
  444.             game.explosions[i] = (game.explosions[i] & 0xFFFF) | ( ((game.explosions[i]>>16)+1) << 16 );
  445.             if ( (game.explosions[i] >> 16) >= EXPLOSION_FRAMES_COUNT ) {
  446.                 game.explosions[i] = game.explosions[game.explosions_count-1];
  447.                 game.explosions_count--;
  448.                 i--;
  449.             };
  450.         };
  451.        
  452.         game.time++;
  453.  
  454.     };
  455.  
  456.     game_draw();
  457.  
  458. }
  459.  
  460.  
  461.  
  462.  
  463.  
  464. void GameInit() {
  465.  
  466.     game_reg_init();
  467.    
  468.     game.field = malloc( FIELD_LENGTH );
  469.     int i;
  470.     for (i = 0; i < FIELD_LENGTH; i++) {
  471.         game.field[i] = (unsigned char) (0.99 * fabs(rs_noise(i, 10)) * CRYSTALS_COUNT) | CRYSTAL_VISIBLE_BIT;
  472.     };
  473. //    memset( game.field, 0, FIELD_LENGTH );
  474.    
  475.     game.scaled_framebuffer = malloc(GAME_WIDTH*game.window_scale * GAME_HEIGHT*game.window_scale * 3);
  476.     DEBUG10f("scaled framebuffer: %d (window_scale = %d) \n", game.window_scale * GAME_WIDTH * GAME_HEIGHT * 3, game.window_scale);
  477.    
  478.     game_font_init();
  479.    
  480.     texture_init(&game.framebuffer, GAME_WIDTH, GAME_HEIGHT);
  481.    
  482. //    texture_init(&game.tex, 64, 64);
  483. //    rs_gen_init(1, 64);
  484. //    rs_gen_func_set(0, 0.0);
  485. //    rs_gen_func_cell(0, 1200, 10, NULL, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0);
  486. //    rs_gen_func_normalize(0, 0.0, 1.0);
  487. //    rs_gen_func_posterize(0, 5);
  488. //    rs_gen_tex_out_rgba(0, 0, 0, -1, 1.0, 1.0, 1.0, 1.0);
  489. //    memcpy(game.tex.data, rs_gen_reg.tex_out, 64*64*4 );
  490. //    rs_gen_term();
  491.    
  492.     texture_init(&game.tex_clouds, 128, 128);
  493.     rs_gen_init(1, 128);
  494.     rs_gen_func_perlin(0, 8, 5, 0.5, 1100);
  495.     rs_gen_func_normalize(0, 0.0, 1.0);
  496.     rs_gen_func_posterize(0, 6);
  497.     rs_gen_func_mult_add_value(0, 0, 0.6, 0.4);
  498. //    rs_gen_func_set(0, 1.0);
  499.     rs_gen_tex_out_rgba(0, 0, 0, -1, 1.0, 1.0, 1.0, 1.0);
  500.     memcpy(game.tex_clouds.data, rs_gen_reg.tex_out, 128*128*4 );
  501.     rs_gen_term();
  502.  
  503.  
  504.    
  505.  
  506.     texture_init(&game.tex_logo, GAME_WIDTH, 128);
  507.     texture_clear(&game.tex_logo, COLOR_TRANSPARENT);
  508.    
  509.     game_textout_adv( &game.tex_logo, GAME_WIDTH/2 - 192, 3, 1, DRAW_MODE_REPLACE, "MARBLE");
  510.     game_textout_adv( &game.tex_logo, GAME_WIDTH/2 - 192, 63, 1, DRAW_MODE_REPLACE, "MATCH3");
  511.     texture_draw(&game.tex_logo, &game.tex_clouds, 0, 0, DRAW_MODE_MULT | DRAW_TILED_FLAG);
  512.     game_textout_adv( &game.tex_logo, GAME_WIDTH/2 - 192 - 4, 0, 1, DRAW_MODE_MULT, "MARBLE");
  513.     game_textout_adv( &game.tex_logo, GAME_WIDTH/2 - 192 - 4, 60, 1, DRAW_MODE_MULT, "MATCH3");
  514.    
  515. //    rs_gen_init(1, 128);
  516. //    rs_gen_func_perlin(0, 8, 5, 0.5, 1100);
  517. //    rs_gen_func_normalize(0, 0.0, 1.0);
  518. //    rs_gen_func_posterize(0, 4);
  519. //    rs_gen_func_normalize(0, 0.0, 0.50);
  520. //    rs_gen_tex_out_rgba(0, 0, 0, -1, 0.9, 0.7, 0.5, 1.0);
  521. //    memcpy(game.tex_clouds.data, rs_gen_reg.tex_out, 128*128*4 );
  522. //    rs_gen_term();
  523.  
  524.    
  525.     texture_init(&game.tex_bg, 512, 512);
  526.     texture_clear(&game.tex_bg, COLOR_SILVER);
  527.    
  528.     texture_init(&game.tex_cursor, CRYSTAL_SIZE, CRYSTAL_SIZE);
  529.     texture_clear(&game.tex_cursor, COLOR_SEMI_TRANSPARENT);
  530.  
  531.    
  532.  
  533.    
  534. //    float cr_r[CRYSTALS_COUNT] = { 0.8, 0.2, 0.1, 0.6, 0.7, 0.0, 0.7 };
  535. //    float cr_g[CRYSTALS_COUNT] = { 0.1, 0.6, 0.4, 0.0, 0.6, 0.0, 0.8 };
  536. //    float cr_b[CRYSTALS_COUNT] = { 0.1, 0.1, 0.7, 0.7, 0.0, 0.3, 0.9 };
  537.  
  538. //    float cr_r[CRYSTALS_COUNT] = { 0.9, 0.3, 0.1, 0.7, 0.8, 0.0, 0.8 };
  539. //    float cr_g[CRYSTALS_COUNT] = { 0.1, 0.8, 0.5, 0.0, 0.7, 0.0, 0.8 };
  540. //    float cr_b[CRYSTALS_COUNT] = { 0.0, 0.1, 0.9, 0.8, 0.0, 0.5, 0.9 };
  541.    
  542.     float cr_r[CRYSTALS_COUNT] = { 1.0, 0.4, 0.1, 0.9, 0.9, 0.2, 0.8 };
  543.     float cr_g[CRYSTALS_COUNT] = { 0.1, 1.0, 0.6, 0.1, 0.8, 0.2, 0.8 };
  544.     float cr_b[CRYSTALS_COUNT] = { 0.0, 0.1, 1.0, 1.0, 0.0, 0.9, 0.9 };
  545.    
  546.  
  547.     rs_gen_init(5, CRYSTAL_SIZE);
  548.     for (i = 0; i < CRYSTALS_COUNT; i++) {
  549.    
  550.         texture_init(&(game.tex_crystals[i]), CRYSTAL_SIZE, CRYSTAL_SIZE);
  551.        
  552.         rs_gen_func_set(0, 0.0);
  553.         rs_gen_func_radial(0, 0.5, 0.5, 0.5, 0.75, 10.0);
  554.  
  555. //        rs_gen_func_perlin(2, 33, 4, 0.5, 350+i);
  556. //        rs_gen_func_normalize(2, 0.0, 1.0);
  557. //        rs_gen_func_posterize(2, 4);
  558. //        
  559. //        rs_gen_func_cell(1, 410+i, 50, NULL, -2.0, 1.0, 1.0, 1.0, 0.0, 1.0);
  560. //        rs_gen_func_posterize(1, 2);
  561. //        rs_gen_func_normalize(1, 0.0, 1.0);
  562. //        rs_gen_func_add(1, 1, 2, 1.0, 0.5);
  563. //        rs_gen_func_normalize(1, 0.0, 1.0);
  564. //        rs_gen_func_posterize(1, 4);
  565. //
  566. //        rs_gen_func_add(1, 0, 1, 1.0, 1.0);
  567. //        rs_gen_func_normalize(1, 0.0, 1.0);
  568. //        rs_gen_func_mult(1, 0, 1);
  569. //        rs_gen_func_normalize(1, 0.0, 1.0);
  570. //        rs_gen_func_posterize(1, 4);
  571.        
  572.         rs_gen_func_set(1, 0.0);
  573.         rs_gen_func_cell(1, 110+100*i, 7+i, NULL, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0);
  574.         rs_gen_func_normalize(1, 0.0, 1.0);
  575. //        rs_gen_func_mult_add_value(1, 1, 0.9, 0.1);
  576.        
  577. //        rs_gen_func_normalmap(2, 3, 3, 1, 1.0);
  578. //        rs_gen_func_mult(1, 1, 2);
  579.        
  580.         //rs_gen_tex_out_rgba_set(0.0, 0.0, 0.0, 0.0);
  581.         //rs_gen_tex_out_rgba(1, 1, 1, 1, 0.5+ 0.03*(i%2), 0.7+ 0.03*(i%3) , 0.9, 1.0);
  582. //        rs_gen_tex_out_rgba_set(0.2 + 0.2*(i/3), 0.2 + 0.1*(i%5), 0.2 + 0.1*(i%7), 0.0);
  583. //        rs_gen_tex_out_rgba(1, 1, 1, 1, 0.0, 0.0, 0.0, 1.0);
  584.        
  585.         rs_gen_tex_out_rgba_set(0.0, 0.0, 0.0, 0.0);
  586. //        rs_gen_tex_out_rgba_set( cr_b[i], cr_g[i], cr_r[i], 0.0);
  587.         rs_gen_tex_out_rgba(1, 1, 1, 0, cr_b[i], cr_g[i], cr_r[i], 1.0);
  588.  
  589.         memcpy(game.tex_crystals[i].data, rs_gen_reg.tex_out, CRYSTAL_SIZE*CRYSTAL_SIZE*4 );
  590.     };
  591.     rs_gen_term();
  592.    
  593.    
  594.    
  595.     rs_gen_init(3, EXPLOSION_SIZE);
  596.     for (i = 0; i < EXPLOSION_FRAMES_COUNT; i++) {
  597.            
  598.         texture_init(&(game.tex_explosion[i]), EXPLOSION_SIZE, EXPLOSION_SIZE);
  599.  
  600.         rs_gen_func_set(0, 1.0);
  601. //        rs_gen_func_radial(0, 0.5, 0.5, 0.3 + 0.5*i/EXPLOSION_FRAMES_COUNT, 0.975, 4.0);
  602. //        rs_gen_func_set(0, 1.0);
  603.  
  604.         rs_gen_func_set(1, 0.0);
  605.         rs_gen_func_radial(1, 0.5, 0.5, 0.1 + 0.4*i/EXPLOSION_FRAMES_COUNT, 1.0 - 1.0*i/EXPLOSION_FRAMES_COUNT, 2.5 + i%5);
  606.  
  607.         rs_gen_tex_out_rgba_set( 0.0, 0.0, 0.0, 0.0);
  608.         rs_gen_tex_out_rgba(0, 0, 0, 1, 1.0, 1.0, 1.0, 1.0);
  609.  
  610.         memcpy(game.tex_explosion[i].data, rs_gen_reg.tex_out, EXPLOSION_SIZE*EXPLOSION_SIZE*4 );
  611.     };
  612.     rs_gen_term();
  613.    
  614.    
  615.  
  616.     #ifndef RS_KOS
  617.         rs_audio_init(RS_AUDIO_FMT_MONO16, RS_AUDIO_FREQ_16000, 0);
  618.     #endif
  619.  
  620.     soundbuf_init(&game.sound_test1, 2048);
  621. //    soundbuf_fill(&game.sound_test1, 2, 50);
  622.     soundbuf_sin_fade(&game.sound_test1, 0.7);
  623.  
  624.     soundbuf_init(&game.sound_test2, 1024);
  625.     //soundbuf_fill(&game.sound_test2, 8, 40);
  626.     soundbuf_sin(&game.sound_test2, 0.48);
  627.  
  628.     soundbuf_init(&game.sound_test3, 1024);
  629.     //soundbuf_fill(&game.sound_test3, 12, 60);
  630.     soundbuf_sin(&game.sound_test3, 0.24);
  631.  
  632.  
  633. };
  634.  
  635.  
  636. void GameTerm() {
  637.  
  638.  
  639.     DEBUG10("--- Game Term ---");
  640.    
  641.     free(game.field);
  642.  
  643.     #ifndef RS_KOS
  644.         rs_audio_term();
  645.     #endif
  646.  
  647.     game_font_term();
  648.    
  649.     free(game.scaled_framebuffer);
  650.    
  651.     texture_free(&game.framebuffer);
  652.     texture_free(&game.tex_logo);
  653.     texture_free(&game.tex_clouds);
  654.     texture_free(&game.tex_bg);
  655.    
  656. //    texture_free(&game.tex_gui_line);
  657.    
  658. //    int i;
  659. //    for (i = 0; i < ROCKS_COUNT; i++) {
  660. //        texture_free(&game.tex_rocks[i]);
  661. //    };
  662.    
  663.     soundbuf_free(&game.sound_test1);
  664.     soundbuf_free(&game.sound_test2);
  665.     soundbuf_free(&game.sound_test3);
  666.    
  667.  
  668. };
  669.  
  670. // ------------ #Event Functions ------------
  671.  
  672.  
  673.  
  674.  
  675.  
  676.  
  677. void GameKeyDown(int key, int first) {
  678.    
  679.    
  680.     switch (key) {
  681.         case RS_KEY_LEFT:
  682.             BIT_SET(game.keyboard_state, RS_ARROW_LEFT_MASK);
  683.             break;
  684.         case RS_KEY_RIGHT:
  685.             BIT_SET(game.keyboard_state, RS_ARROW_RIGHT_MASK);
  686.             break;
  687.         case RS_KEY_UP:
  688.             BIT_SET(game.keyboard_state, RS_ARROW_UP_MASK);
  689.             break;
  690.         case RS_KEY_DOWN:
  691.             BIT_SET(game.keyboard_state, RS_ARROW_DOWN_MASK);
  692.             break;
  693.         case RS_KEY_A:
  694.             BIT_SET(game.keyboard_state, RS_ATTACK_KEY_MASK);
  695. //            game.shoot_keypressed = 1;
  696.             break;
  697.     };
  698.    
  699.    
  700.     if (game.status == STATUS_MENU) {
  701.    
  702.         switch (key) {
  703.             case RS_KEY_LEFT:
  704.                 BIT_SET(game.keyboard_state, RS_ARROW_LEFT_MASK);
  705.                 //PlayBuffer(hBuff, 0);
  706.                 break;
  707.             case RS_KEY_RIGHT:
  708.                 BIT_SET(game.keyboard_state, RS_ARROW_RIGHT_MASK);
  709.                 //StopBuffer(hBuff);
  710.                 break;
  711.             case RS_KEY_UP:
  712.                 BIT_SET(game.keyboard_state, RS_ARROW_UP_MASK);
  713.                 menu_cursor_up();
  714.                 //ResetBuffer(hBuff, 0);
  715.                 break;
  716.             case RS_KEY_DOWN:
  717.                 BIT_SET(game.keyboard_state, RS_ARROW_DOWN_MASK);
  718.                 menu_cursor_down();
  719.                 break;
  720.             case RS_KEY_RETURN:
  721.                 menu_cursor_click();
  722.                 break;
  723.             case RS_KEY_ESCAPE:
  724.                 menu_open(0);
  725.                 break;
  726.         };
  727.  
  728.     };
  729.    
  730.     if (game.status == STATUS_PLAYING) {
  731.        
  732.         if (key == RS_KEY_A) {
  733.        
  734.            
  735.            
  736.         };
  737.        
  738.         if (key == RS_KEY_SPACE) {
  739.            
  740.             // Check and explode match-3
  741.        
  742.            
  743.             game.score = 101;
  744.            
  745.            
  746.         };
  747.        
  748.            
  749. //        switch (key) {
  750. //            
  751. //            case RS_KEY_ESCAPE:
  752. //                game.status = STATUS_MENU;
  753. //                menu_open(0);
  754. //                break;
  755. //            case RS_KEY_A:
  756. //                
  757. ////                if ( (game.tx > 0) && (game.ty > 5) && (game.tx < GAME_WIDTH-20) && (game.ty < GAME_HEIGHT-10) ) {
  758. ////                
  759. ////                    soundbuf_play(&game.sound_test1);
  760. ////                    
  761. ////                    game.bullet_index++;
  762. ////                    game.bullet_index %= BULLETS_COUNT;
  763. ////                    game.bullet_x[game.bullet_index] = game.tx + 12;
  764. ////                    game.bullet_y[game.bullet_index] = game.ty + 3;
  765. ////                };
  766. //                
  767. //                break;
  768. //            
  769. //        };
  770.     };
  771.  
  772. };
  773.  
  774. void GameKeyUp(int key) {
  775.  
  776.     switch (key) {
  777.         case RS_KEY_LEFT:
  778.             BIT_CLEAR(game.keyboard_state, RS_ARROW_LEFT_MASK);
  779.             break;
  780.         case RS_KEY_RIGHT:
  781.             BIT_CLEAR(game.keyboard_state, RS_ARROW_RIGHT_MASK);
  782.             break;
  783.         case RS_KEY_UP:
  784.             BIT_CLEAR(game.keyboard_state, RS_ARROW_UP_MASK);
  785.             break;
  786.         case RS_KEY_DOWN:
  787.             BIT_CLEAR(game.keyboard_state, RS_ARROW_DOWN_MASK);
  788.             break;
  789.         case RS_KEY_A:
  790.             BIT_CLEAR(game.keyboard_state, RS_ATTACK_KEY_MASK);
  791.             break;
  792.     };
  793.  
  794. };
  795.  
  796. void GameMouseDown(int x, int y) {
  797.     game.tx = x;
  798.     game.ty = y;
  799.    
  800.     if (game.status == STATUS_MENU) {
  801.         game.time = 0;
  802.         game.score = 0;
  803.         game.status = STATUS_PLAYING;
  804.         return;
  805.     };
  806.    
  807.     if (game.status == STATUS_PLAYING) {
  808.        
  809.         unsigned int field_x = (unsigned int) (x - FIELD_X0) / CRYSTAL_SIZE;
  810.         if (field_x != rs_clamp_i(field_x, 0, FIELD_WIDTH-1)) {
  811.             return;
  812.         };
  813.        
  814.         unsigned int field_y = (unsigned int) (y - FIELD_Y0) / CRYSTAL_SIZE;
  815.         if (field_y != rs_clamp_i(field_y, 0, FIELD_HEIGHT-1)) {
  816.             return;
  817.         };
  818.        
  819.         //FIELD_ITEM(field_x, field_y) = 0;
  820.        
  821.         if (!game.selected) {
  822.             game.selected = 1;
  823.             game.selected_x = field_x;
  824.             game.selected_y = field_y;                                                                      
  825.            
  826.         }
  827.         else {
  828.            
  829.             if ( abs(game.selected_x - field_x) + abs(game.selected_y - field_y) == 1 ) {
  830.                 game.selected = 0;
  831.                
  832.                 // Trying to swap
  833.                 int temp_crystal = FIELD_ITEM(field_x, field_y);
  834.                 FIELD_ITEM(field_x, field_y) = FIELD_ITEM(game.selected_x, game.selected_y);
  835.                 FIELD_ITEM(game.selected_x, game.selected_y) = temp_crystal;
  836.                
  837.                 if ( !game_check_and_explode() ) {
  838.                     FIELD_ITEM(game.selected_x, game.selected_y) = FIELD_ITEM(field_x, field_y);
  839.                     FIELD_ITEM(field_x, field_y) = temp_crystal;
  840.                 }
  841.                 else {
  842.                     // success
  843.                     process_timer = 0;
  844.                 };
  845.                
  846.             }
  847.             else {
  848.                 if ( (game.selected_x != field_x) && (game.selected_y != field_y) ) {
  849.                     game.selected_x = field_x;
  850.                     game.selected_y = field_y;
  851.                 }
  852.                 else {
  853.                     game.selected = 0;
  854.                 };
  855.             };
  856.            
  857.         };
  858.        
  859. //        int i;
  860. //        for (i = field_y; i > 0; i--) {
  861. //            FIELD_ITEM(field_x, i) = FIELD_ITEM(field_x, (i-1) );
  862. //        };
  863. //        FIELD_ITEM(field_x, 0) = 0;
  864.        
  865.     };
  866.    
  867. };
  868.  
  869. void GameMouseUp(int x, int y) {
  870.     //
  871. };
  872.  
  873.  
  874. void game_ding(int i) {
  875.    
  876.     switch (i) {
  877.         case 0:
  878.             soundbuf_play(&game.sound_test2);
  879.             break;
  880.         case 1:
  881.             soundbuf_play(&game.sound_test3);
  882.             break;
  883.     };
  884.    
  885. };
  886.