Experimento con emscripten y SDL
#include "engine.h"12void snake_render_handler(actor *a)3{4snake_actor *sn = (snake_actor *)a;56int i;7for (i = 0; i < sn->num_segments; i++) {8sprite_render(&(sn->snake_sprites[i]));9}10}1112void snake_direction_to_vector(snake_actor *sn, int *r)13{14switch (sn->direction) {15case DIRECTION_N:16r[0] = 0;17r[1] = -1;18break;19case DIRECTION_E:20r[0] = 1;21r[1] = 0;22break;23case DIRECTION_S:24r[0] = 0;25r[1] = 1;26break;27case DIRECTION_W:28r[0] = -1;29r[1] = 0;30break;31}32}3334SPRITES_DECALS snake_get_neck_decal(snake_actor *sn, DIRECTION old_direction)35{36switch (sn->direction) {37case DIRECTION_N:38switch (old_direction) {39case DIRECTION_W:40return BODY_NE;41case DIRECTION_E:42return BODY_NW;43default:44return BODY_N;45}46case DIRECTION_E:47switch (old_direction) {48case DIRECTION_N:49return BODY_SE;50case DIRECTION_S:51return BODY_NE;52default:53return BODY_E;54}55case DIRECTION_S:56switch (old_direction) {57case DIRECTION_W:58return BODY_SE;59case DIRECTION_E:60return BODY_SW;61default:62return BODY_N;63}64return BODY_N;65case DIRECTION_W:66switch (old_direction) {67case DIRECTION_N:68return BODY_SW;69case DIRECTION_S:70return BODY_NW;71default:72return BODY_E;73}74}75return BODY_N;76}7778SPRITES_DECALS snake_get_head_decal(snake_actor *sn)79{80switch (sn->direction) {81case DIRECTION_N:82return HEAD_N;83case DIRECTION_E:84return HEAD_E;85case DIRECTION_S:86return HEAD_S;87case DIRECTION_W:88return HEAD_W;89}90return HEAD_N;91}9293SPRITES_DECALS snake_get_tail_decal(snake_actor *sn)94{95unsigned int next_to_tail_index = (sn->tail_index + 1) % sn->num_segments;9697if (sn->snake_sprites[next_to_tail_index].r[0] > sn->snake_sprites[sn->tail_index].r[0]) {98if (sn->snake_sprites[next_to_tail_index].r[0] - sn->snake_sprites[sn->tail_index].r[0] > sn->segment_w) {99return TAIL_W;100}101return TAIL_E;102}103104if (sn->snake_sprites[next_to_tail_index].r[0] < sn->snake_sprites[sn->tail_index].r[0]) {105if (sn->snake_sprites[sn->tail_index].r[0] - sn->snake_sprites[next_to_tail_index].r[0] > sn->segment_w) {106return TAIL_E;107}108return TAIL_W;109}110111if (sn->snake_sprites[next_to_tail_index].r[1] > sn->snake_sprites[sn->tail_index].r[1]) {112if (sn->snake_sprites[next_to_tail_index].r[1] - sn->snake_sprites[sn->tail_index].r[1] > sn->segment_h) {113return TAIL_N;114}115return TAIL_S;116}117118if (sn->snake_sprites[sn->tail_index].r[1] - sn->snake_sprites[next_to_tail_index].r[1] > sn->segment_h) {119return TAIL_S;120}121return TAIL_N;122}123124sprite *snake_get_head_sprite(snake_actor *sn)125{126int head_index = ((sn->tail_index - 1 + sn->num_segments) % sn->num_segments);127return &sn->snake_sprites[head_index];128}129130void snake_apple_collision_detect(snake_actor *sn)131{132sprite *snake_head = snake_get_head_sprite(sn);133if (snake_head->r[0] == eng.apple_actor.sprite.r[0]134&& snake_head->r[1] == eng.apple_actor.sprite.r[1]) {135apple_replace(&eng.apple_actor);136sn->needs_to_grow = true;137eng.score += 1;138background_actor_update_scoreboard(&eng.background_actor);139140float seconds_per_update = INITIAL_SNAKE_SECONDS_PER_UPDATE141- (float)eng.score * SNAKE_SECONDS_PER_UPDATE_INCREMENT;142if (seconds_per_update < MINIMUM_SNAKE_SECONDS_PER_UPDATE)143{144seconds_per_update = MINIMUM_SNAKE_SECONDS_PER_UPDATE;145}146147sn->snake_frame_ratio = eng.fps * seconds_per_update;148}149}150151void snake_grow(snake_actor *sn)152{153sn->num_segments += 1;154sprite_init(155&(sn->snake_sprites[sn->num_segments - 1]),156sn->segment_w,157sn->segment_h,158&(eng.sprites_decals[BODY_N]));159160sprite *new_segment = &(sn->snake_sprites[sn->num_segments - 1]);161162int i;163for (i = sn->num_segments - 1; i > sn->tail_index; i--) {164sn->snake_sprites[i].r[0] = sn->snake_sprites[i-1].r[0];165sn->snake_sprites[i].r[1] = sn->snake_sprites[i-1].r[1];166sprite_set_decal(&sn->snake_sprites[i], sn->snake_sprites[i-1].d);167}168169unsigned int grid_x = new_segment->r[0] / TILE_DIMENSION;170unsigned int grid_y = new_segment->r[1] / TILE_DIMENSION - STATUS_BAR_HEIGHT;171eng.occupied_gridpoints[grid_x + eng.grid_width * grid_y] = true;172173}174175void snake_logic_handler(actor *a)176{177snake_actor * sn = (snake_actor *)a;178if (eng.current_frame % sn->snake_frame_ratio == 0) {179DIRECTION old_direction = sn->direction;180181if (is_state_active(GS_N)) {182deactivate_state(GS_N);183if (sn->direction != DIRECTION_S)184{185sn->direction = DIRECTION_N;186}187} else if (is_state_active(GS_E)) {188deactivate_state(GS_E);189if (sn->direction != DIRECTION_W)190{191sn->direction = DIRECTION_E;192}193} else if (is_state_active(GS_S)) {194deactivate_state(GS_S);195if (sn->direction != DIRECTION_N)196{197sn->direction = DIRECTION_S;198}199} else if (is_state_active(GS_W)) {200deactivate_state(GS_W);201202if (sn->direction != DIRECTION_E)203{204sn->direction = DIRECTION_W;205}206}207208if (sn->needs_to_grow && sn->num_segments < MAX_SNAKE_SEGMENTS) {209snake_grow(sn);210sn->needs_to_grow = false;211}212213sprite *old_head = snake_get_head_sprite(sn);214SPRITES_DECALS decal = snake_get_neck_decal(sn, old_direction);215sprite_set_decal(old_head, &(eng.sprites_decals[decal]));216217int new_head_index = sn->tail_index;218sprite *new_head = &sn->snake_sprites[new_head_index];219220int old_grid_coords[2];221engine_get_grid_coord(new_head->r, old_grid_coords);222223int snake_direction[2];224snake_direction_to_vector(sn, snake_direction);225226int new_grid_coords[2];227engine_get_grid_coord(old_head->r, new_grid_coords);228new_grid_coords[0] += snake_direction[0];229new_grid_coords[1] += snake_direction[1];230engine_apply_boundary_conditions(new_grid_coords);231232engine_get_pixel_coord(new_grid_coords, new_head->r);233234if (eng.occupied_gridpoints[new_grid_coords[0] + eng.grid_width * new_grid_coords[1]]) {235engine_reset();236return;237}238eng.occupied_gridpoints[old_grid_coords[0] + eng.grid_width * old_grid_coords[1]] = false;239eng.occupied_gridpoints[new_grid_coords[0] + eng.grid_width * new_grid_coords[1]] = true;240241decal = snake_get_head_decal(sn);242sprite_set_decal(new_head, &(eng.sprites_decals[decal]));243244sn->tail_index = (sn->tail_index + 1) % sn->num_segments;245246decal = snake_get_tail_decal(sn);247sprite_set_decal(&sn->snake_sprites[sn->tail_index], &(eng.sprites_decals[decal]));248249snake_apple_collision_detect(sn);250}251}252253snake_actor *snake_actor_init(snake_actor *sn)254{255sn->num_segments = 3;256sn->segment_w = TILE_DIMENSION;257sn->segment_h = TILE_DIMENSION;258sn->needs_to_grow = false;259260actor_init(&(sn->a), snake_render_handler, snake_logic_handler);261int i;262SPRITES_DECALS snake_init_config[] = {TAIL_E, BODY_E, HEAD_E};263int tail_pos[2];264int tail_grid_pos[2] = {4,4};265engine_get_pixel_coord(tail_grid_pos, tail_pos);266267for (i = 0; i < sn->num_segments; i++) {268sprite_init(269&(sn->snake_sprites[i]),270sn->segment_w,271sn->segment_h,272&(eng.sprites_decals[snake_init_config[i]]));273sn->snake_sprites[i].r[0] = tail_pos[0] + i * sn->segment_w;274sn->snake_sprites[i].r[1] = tail_pos[1];275276unsigned int grid_x = sn->snake_sprites[i].r[0] / TILE_DIMENSION;277unsigned int grid_y = sn->snake_sprites[i].r[1] / TILE_DIMENSION - STATUS_BAR_HEIGHT;278eng.occupied_gridpoints[grid_x + eng.grid_width * grid_y] = true;279}280sn->direction = DIRECTION_E;281282float seconds_per_update = INITIAL_SNAKE_SECONDS_PER_UPDATE;283sn->snake_frame_ratio = eng.fps * seconds_per_update;284285sn->tail_index = 0;286return sn;287}288289290