// Volcano (abans "Rise of the Bal1") // Programat i dissenyat per Sergio Valor @JailDesigner // Editor, música i suport técnic per Raimon Zamora @JailDoc // Gràfics per Diego Valor @JailBrother // Començat un 19 de febrer de 2016 // Repres un 14 de febrer de 2021 #include "volcano.h" void allocatePointers() { // Textures hud.sprite = new LTexture(); map.background = new LTexture(); map.sprite_actor = new LTexture(); map.sprite_tile = new LTexture(); menu.sprite = new LTexture(); menu.sprite_animation = new LTexture(); player.sprite = new LTexture(); prog.sprite = new LTexture(); // Sounds game.sound_drop_enemy = new Mix_Chunk(); game.sound_drop_splat = new Mix_Chunk(); menu.sound_logo = new Mix_Chunk(); menu.sound_start = new Mix_Chunk(); player.sound_coin = new Mix_Chunk(); player.sound_death = new Mix_Chunk(); player.sound_jump = new Mix_Chunk(); // Music //game.music = new Mix_Music(); //menu.music = new Mix_Music(); } void deletePointers() { // Textures delete hud.sprite; delete map.background; delete map.sprite_actor; delete map.sprite_tile; delete menu.sprite; delete menu.sprite_animation; delete player.sprite; delete prog.sprite; // Sounds delete game.sound_drop_enemy; delete game.sound_drop_splat; delete menu.sound_logo; delete menu.sound_start; delete player.sound_coin; delete player.sound_death; delete player.sound_jump; // Music //game.music = new Mix_Music(); //menu.music = new Mix_Music(); delete[] map.tile; delete[] map.actor; } // Carga un archivo de imagen en una textura bool loadTextureFromFile(LTexture *texture, std::string path, SDL_Renderer *renderer) { bool success = true; if (!texture->loadFromFile(path, renderer)) { printf("Failed to load %s texture!\n", path.c_str()); success = false; } return success; } void CloseSound(Mix_Chunk *sound) { if (sound != nullptr) Mix_FreeChunk(sound); sound = nullptr; } void CloseMusic(Mix_Music *music) { if (music != nullptr) Mix_FreeMusic(music); music = nullptr; } void ClosePicture(LTexture *picture) { picture->free(); } Uint8 GetTile(Uint8 x, Uint8 y) // Entrada: coordenades en tiles relativas a la habitación actual // Salida: el valor del byte { Uint8 room_x = (map.room % 12) * ROOM_WIDTH_IN_TILES; Uint8 room_y = (map.room / 12) * ROOM_HEIGHT_IN_TILES; return map.tile[(room_x + x) + (room_y + y) * map.w]; } Uint8 ReadMapTile(Uint8 x, Uint8 y) { if (GetTile(x, y) >= 0 && GetTile(x, y) <= 63) return TILE_BACKGROUND; else if (GetTile(x, y) >= 64 && GetTile(x, y) <= 143) return TILE_PLATFORM; else if (GetTile(x, y) >= 144 && GetTile(x, y) <= 175) return TILE_TRAVESABLE_PLATFORM; else if (GetTile(x, y) >= 176 && GetTile(x, y) <= 207) return TILE_KILLING_PLATFORM; else if (GetTile(x, y) >= 208 && GetTile(x, y) <= 255) return TILE_ACTOR; else return 0; } Uint8 GetActor(Uint8 x, Uint8 y) { Uint8 room_x = (map.room % 12) * ROOM_WIDTH_IN_TILES; Uint8 room_y = (map.room / 12) * ROOM_HEIGHT_IN_TILES; return map.actor[(room_x + x) + (room_y + y) * map.w]; } void SetActor(Uint8 x, Uint8 y, Uint8 valor) { Uint8 room_x = (map.room % 12) * ROOM_WIDTH_IN_TILES; Uint8 room_y = (map.room / 12) * ROOM_HEIGHT_IN_TILES; map.actor[(room_x + x) + (room_y + y) * map.w] = valor; } void SetMapGFX(Uint8 zone) { switch (zone) { case ZONE_SURFACE: loadTextureFromFile(map.sprite_tile, FILE_TILES_SURFACE.c_str(), renderer); loadTextureFromFile(map.background, FILE_BKG_SURFACE.c_str(), renderer); break; case ZONE_VOLCANO: loadTextureFromFile(map.sprite_tile, FILE_TILES_VOLCANO.c_str(), renderer); loadTextureFromFile(map.background, FILE_BKG_SURFACE.c_str(), renderer); break; } } void SetMapMusic(Uint8 zone) { switch (zone) { case ZONE_SURFACE: game.music = Mix_LoadMUS(FILE_MUSIC_SURFACE.c_str()); break; case ZONE_VOLCANO: game.music = Mix_LoadMUS(FILE_MUSIC_VOLCANO.c_str()); break; } } bool CheckZoneChange(int room) { Uint8 zone = 0; if ((room >= 0) && (room <= 23)) zone = ZONE_SURFACE; else if ((room >= 24) && (room <= 255)) zone = ZONE_VOLCANO; if (zone == game.zone) return false; else return true; } void SetZone(int room) { if ((room >= 0) && (room <= 23)) game.zone = ZONE_SURFACE; else if ((room >= 24) && (room <= 255)) game.zone = ZONE_VOLCANO; SetMapGFX(game.zone); SetMapMusic(game.zone); Mix_PlayMusic(game.music, -1); } void SetPlayerAnimation(Uint8 anim) { if (anim != player.active_animation) { player.active_animation = anim; player.src_rect.y = anim * player.src_rect.h; player.animation[anim].index = 0; player.animation[anim].timer = 0; player.animation[anim].loops = false; } } void Animate(Tanimation &a, SDL_Rect &s) { // Mirem si estem en el penultim frame per avisar de que anem a pintar el ultim if (a.timer == (a.num_frames * a.speed) - 2) a.loops = true; else a.loops = false; a.timer = (a.timer + 1) % (a.num_frames * a.speed); a.index = a.timer / a.speed; s.x = (a.frame[a.index]) * s.w; } void AnimateIntroMenu(Tanimation &a, SDL_Rect &s) { // Mirem si estem en el penultim frame per avisar de que anem a pintar el ultim if (a.timer == ((a.num_frames) * (a.speed)) - 2) a.loops = true; else a.loops = false; a.timer = (a.timer + 1) % (a.num_frames * a.speed); a.index = a.timer / a.speed; s.x = (a.frame[a.index] % 4) * s.w; s.y = (a.frame[a.index] / 4) * s.h; } void CreateActor(Tactor &a, Uint8 kind, Uint8 id, Sint16 dstx, Sint16 dsty, Sint16 dstw, Sint16 dsth, Sint16 srcx, Sint16 srcy, Sint16 sx, Sint16 sy, Sint16 timer, Sint16 frame, Uint8 direction, Uint8 parent) { a.kind = kind; a.id = id; a.dst_rect.x = dstx; a.dst_rect.y = dsty; a.dst_rect.w = dstw; a.dst_rect.h = dsth; a.src_rect.x = srcx; a.src_rect.y = srcy; a.src_rect.w = a.dst_rect.w; a.src_rect.h = a.dst_rect.h; a.direction = direction; a.speed_x = sx; a.speed_y = sy; a.timer = timer; a.frame = frame; a.enabled = true; a.parent = parent; } void setExecutablePath(std::string path) { executablePath = path.substr(0, path.find_last_of("\\/")); } void LoadMap() { std::string p = executablePath + "/" + FILE_MAP_VOLCANO.c_str(); std::string filename = p.substr(p.find_last_of("\\/") + 1); SDL_RWops *file = SDL_RWFromFile(p.c_str(), "r+b"); const int file_size = SDL_RWsize(file); Uint8 *buf = new Uint8[file_size]; if (file == NULL) { printf("Warning: Unable to open %s file\n", filename.c_str()); } else { printf("Reading file %s\n", filename.c_str()); SDL_RWread(file, buf, sizeof(Uint8), file_size); SDL_RWclose(file); Uint16 size = (buf[0]) * (buf[1]); map.tile = new Uint8(size); map.actor = new Uint8(size); for (Uint16 i = 0; i < size; i++) map.tile[i] = buf[i]; for (Uint16 i = 0; i < size; i++) map.actor[i] = buf[i]; } delete[] buf; } void LoadRoom(int num) { if (CheckZoneChange(num)) SetZone(num); // Coloquem el numero d'habitaci� corresponent al mapa map.room = max(0, num); // Guardem les coordenades i el sentit que te el jugador al entrar a la habitaci� player.respawn_x = player.dst_rect.x; player.respawn_y = player.dst_rect.y; player.respawn_direction = player.direction; // Esborrem la llista de tiles animats for (Uint8 i = 0; i < MAX_ANIMATED_TILES; i++) animated_tile[i].enabled = false; // Escanejem la habitaci en busca de tiles animats Uint8 k = 0; for (Uint8 i = 0; i < ROOM_WIDTH_IN_TILES; i++) for (Uint8 j = 0; j < ROOM_HEIGHT_IN_TILES; j++) if (((GetTile(i, j) >= 48) && (GetTile(i, j) <= 63)) || ((GetTile(i, j) >= 128) && (GetTile(i, j) <= 143)) || ((GetTile(i, j) >= 160) && (GetTile(i, j) <= 175)) || ((GetTile(i, j) >= 192) && (GetTile(i, j) <= 207))) { animated_tile[k].enabled = true; animated_tile[k].x = i * MAP_TILE_WIDTH; animated_tile[k].y = j * MAP_TILE_HEIGHT; animated_tile[k].index = GetTile(i, j); animated_tile[k].frame = 0; k++; } // Esborrem la llista d'actors actius for (Uint8 i = 0; i < MAX_ACTORS; i++) actor[i].enabled = false; // Escanejem la habitaci� en busca d'actors per afegirlos a la llista d'actors actius k = 0; for (Uint8 i = 0; i < ROOM_WIDTH_IN_TILES; i++) for (Uint8 j = 0; j < ROOM_HEIGHT_IN_TILES; j++) { switch (GetActor(i, j)) { case CODE_ENEMY_V1U: CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 0, 1, 0, 0, UP, k); break; case CODE_ENEMY_V2U: CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 0, 2, 0, 0, UP, k); break; case CODE_ENEMY_V3U: CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 0, 3, 0, 0, UP, k); break; case CODE_ENEMY_V1D: CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 0, 1, 0, 0, DOWN, k); break; case CODE_ENEMY_V2D: CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 0, 2, 0, 0, DOWN, k); break; case CODE_ENEMY_V3D: CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 0, 3, 0, 0, DOWN, k); break; case CODE_ENEMY_H1L: CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 1, 0, 0, 0, LEFT, k); break; case CODE_ENEMY_H2L: CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 2, 0, 0, 0, LEFT, k); break; case CODE_ENEMY_H3L: CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 3, 0, 0, 0, LEFT, k); break; case CODE_ENEMY_H1R: CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 1, 0, 0, 0, RIGHT, k); break; case CODE_ENEMY_H2R: CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 2, 0, 0, 0, RIGHT, k); break; case CODE_ENEMY_H3R: CreateActor(actor[k], KIND_FLYING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 4 * 16, 3, 0, 0, 0, RIGHT, k); break; case CODE_ENEMY_W1L: CreateActor(actor[k], KIND_WALKING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 1 * 16, 1, 0, 0, 0, LEFT, k); break; case CODE_ENEMY_W2L: CreateActor(actor[k], KIND_WALKING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 1 * 16, 2, 0, 0, 0, LEFT, k); break; case CODE_ENEMY_W3L: CreateActor(actor[k], KIND_WALKING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 1 * 16, 3, 0, 0, 0, LEFT, k); break; case CODE_ENEMY_W1R: CreateActor(actor[k], KIND_WALKING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 0 * 16, 1, 0, 0, 0, RIGHT, k); break; case CODE_ENEMY_W2R: CreateActor(actor[k], KIND_WALKING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 0 * 16, 2, 0, 0, 0, RIGHT, k); break; case CODE_ENEMY_W3R: CreateActor(actor[k], KIND_WALKING_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 0 * 16, 3, 0, 0, 0, RIGHT, k); break; case CODE_ENEMY_SPL: CreateActor(actor[k], KIND_SPEED_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 3 * 16, 1, 0, 0, 0, RIGHT, k); break; case CODE_ENEMY_SPR: CreateActor(actor[k], KIND_SPEED_ENEMY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 2 * 16, 1, 0, 0, 0, RIGHT, k); break; case CODE_ENEMY_DRP: CreateActor(actor[k], KIND_DROP_GENERATOR, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 10 * 16, 0, 0, DROP_TIMER, 0, NONE, k); break; case CODE_COIN: CreateActor(actor[k], KIND_COIN, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 12 * 16, 0, 0, 0, 0, NONE, k); break; case CODE_HEART: CreateActor(actor[k], KIND_HEART, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 13 * 16, 1, 0, 0, 0, NONE, k); break; case CODE_KEY_RED: CreateActor(actor[k], KIND_KEY, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 14 * 16, 1, 0, 0, 0, NONE, k); break; case CODE_LOCK_RED: CreateActor(actor[k], KIND_LOCK, 0, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 0, 15 * 16, 1, 0, 0, 0, NONE, k); break; case CODE_KEY_BLUE: CreateActor(actor[k], KIND_KEY, 1, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 1 * 16, 14 * 16, 1, 0, 0, 0, NONE, k); break; case CODE_LOCK_BLUE: CreateActor(actor[k], KIND_LOCK, 1, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 1 * 16, 15 * 16, 1, 0, 0, 0, NONE, k); break; case CODE_KEY_GREEN: CreateActor(actor[k], KIND_KEY, 2, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 2 * 16, 14 * 16, 1, 0, 0, 0, NONE, k); break; case CODE_LOCK_GREEN: CreateActor(actor[k], KIND_LOCK, 2, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 2 * 16, 15 * 16, 1, 0, 0, 0, NONE, k); break; case CODE_KEY_YELLOW: CreateActor(actor[k], KIND_KEY, 3, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 3 * 16, 14 * 16, 1, 0, 0, 0, NONE, k); break; case CODE_LOCK_YELLOW: CreateActor(actor[k], KIND_LOCK, 3, i * MAP_TILE_WIDTH, j * MAP_TILE_HEIGHT, 16, 16, 3 * 16, 15 * 16, 1, 0, 0, 0, NONE, k); break; default: k--; break; } k++; } } void IniMenu() { menu.enabled = true; menu.section = MENU_SECTION_ANIMATION; menu.music = Mix_LoadMUS(FILE_MUSIC_MENU.c_str()); menu.sound_logo = Mix_LoadWAV(FILE_SOUND_MENU_LOGO.c_str()); menu.sound_start = Mix_LoadWAV(FILE_SOUND_MENU_START.c_str()); loadTextureFromFile(menu.sprite, FILE_MENU.c_str(), renderer); menu.frame = 0; menu.timer = 200; // Fondo menu.src_rect_fondo.x = 0; menu.src_rect_fondo.y = 0; menu.src_rect_fondo.w = 320; menu.src_rect_fondo.h = 240; menu.dst_rect_fondo.x = 0; menu.dst_rect_fondo.y = 0; menu.dst_rect_fondo.w = 320; menu.dst_rect_fondo.h = 240; // Logo menu.src_rect_logo.x = 0; menu.src_rect_logo.y = 240; menu.src_rect_logo.w = 260; menu.src_rect_logo.h = 154; menu.dst_rect_logo.x = 30; menu.dst_rect_logo.y = 30; menu.dst_rect_logo.w = 260; menu.dst_rect_logo.h = 154; menu.dst_rect_logo_zoom.x = 0; menu.dst_rect_logo_zoom.y = 0; menu.dst_rect_logo_zoom.w = 0; menu.dst_rect_logo_zoom.h = 0; // PRESS RETURN TO START menu.src_rect_text.x = 0; menu.src_rect_text.y = 394; menu.src_rect_text.w = 125; menu.src_rect_text.h = 7; menu.dst_rect_text.x = (320 - 125) / 2; menu.dst_rect_text.y = 195; menu.dst_rect_text.w = 125; menu.dst_rect_text.h = 7; // JAILGAMES 2016 menu.src_rect_text2.x = 0; menu.src_rect_text2.y = 394 + 7; menu.src_rect_text2.w = 55; menu.src_rect_text2.h = 5; menu.dst_rect_text2.x = (320 - 55) / 2; menu.dst_rect_text2.y = 210; menu.dst_rect_text2.w = 55; menu.dst_rect_text2.h = 5; // Animación loadTextureFromFile(menu.sprite_animation, FILE_MENU_ANIMATION.c_str(), renderer); menu.src_rect_animation.x = 0; menu.src_rect_animation.y = 0; menu.src_rect_animation.w = 320; menu.src_rect_animation.h = 240; menu.dst_rect_animation.x = 0; menu.dst_rect_animation.y = 0; menu.dst_rect_animation.w = 320; menu.dst_rect_animation.h = 240; menu.animation[0].num_frames = 29; menu.animation[0].index = 0; menu.animation[0].timer = 0; menu.animation[0].speed = 9; menu.animation[0].loops = false; menu.animation[0].frame[0] = 0; menu.animation[0].frame[1] = 1; menu.animation[0].frame[2] = 0; menu.animation[0].frame[3] = 1; menu.animation[0].frame[4] = 2; menu.animation[0].frame[5] = 3; menu.animation[0].frame[6] = 4; menu.animation[0].frame[7] = 5; menu.animation[0].frame[8] = 6; menu.animation[0].frame[9] = 7; menu.animation[0].frame[10] = 8; menu.animation[0].frame[11] = 9; menu.animation[0].frame[12] = 10; menu.animation[0].frame[13] = 11; menu.animation[0].frame[14] = 12; menu.animation[0].frame[15] = 13; menu.animation[0].frame[16] = 14; menu.animation[0].frame[17] = 15; menu.animation[0].frame[18] = 16; menu.animation[0].frame[19] = 17; menu.animation[0].frame[20] = 18; menu.animation[0].frame[21] = 19; menu.animation[0].frame[22] = 20; menu.animation[0].frame[23] = 21; menu.animation[0].frame[24] = 22; menu.animation[0].frame[25] = 23; menu.animation[0].frame[26] = 24; menu.animation[0].frame[27] = 25; menu.animation[0].frame[28] = 26; menu.animation[1].num_frames = 23; menu.animation[1].index = 0; menu.animation[1].timer = 0; menu.animation[1].speed = 9; menu.animation[1].loops = false; menu.animation[1].frame[0] = 18; menu.animation[1].frame[1] = 26; menu.animation[1].frame[2] = 18; menu.animation[1].frame[3] = 26; menu.animation[1].frame[4] = 18; menu.animation[1].frame[5] = 26; menu.animation[1].frame[6] = 18; menu.animation[1].frame[7] = 26; menu.animation[1].frame[8] = 18; menu.animation[1].frame[9] = 26; menu.animation[1].frame[10] = 18; menu.animation[1].frame[11] = 26; menu.animation[1].frame[12] = 18; menu.animation[1].frame[13] = 26; menu.animation[1].frame[14] = 18; menu.animation[1].frame[15] = 19; menu.animation[1].frame[16] = 20; menu.animation[1].frame[17] = 21; menu.animation[1].frame[18] = 22; menu.animation[1].frame[19] = 23; menu.animation[1].frame[20] = 24; menu.animation[1].frame[21] = 25; menu.animation[1].frame[22] = 26; } void EndMenu() { CloseSound(menu.sound_logo); CloseSound(menu.sound_start); CloseMusic(menu.music); ClosePicture(menu.sprite); ClosePicture(menu.sprite_animation); menu.enabled = false; } void IniActors() { for (Uint8 i = 0; i < MAX_ACTORS; i++) actor[i].enabled = false; loadTextureFromFile(map.sprite_actor, FILE_ACTORS.c_str(), renderer); } void IniAnimatedTiles() { for (Uint8 i = 0; i < MAX_ANIMATED_TILES; i++) animated_tile[i].enabled = false; } void IniMap() { map.src_rect.x = 0; map.src_rect.y = 0; map.src_rect.w = 320; map.src_rect.h = 240; map.dst_rect.x = 0; map.dst_rect.y = 0; map.dst_rect.w = 320; map.dst_rect.h = 240; LoadMap(); } void EndMap() { ClosePicture(map.sprite_tile); ClosePicture(map.sprite_actor); ClosePicture(map.background); } void IniPlayer() { loadTextureFromFile(player.sprite, FILE_PLAYER.c_str(), renderer); player.dst_rect.x = MAP_TILE_WIDTH * STARTING_PLAYER_TILE_X; player.dst_rect.y = MAP_TILE_HEIGHT * STARTING_PLAYER_TILE_Y; player.dst_rect.w = 16; player.dst_rect.h = 24; player.src_rect.x = 0; player.src_rect.y = 0; player.src_rect.w = player.dst_rect.w; player.src_rect.h = player.dst_rect.h; player.direction = RIGHT; player.respawn_x = player.dst_rect.x; player.respawn_y = player.dst_rect.y; player.respawn_direction = player.direction; player.speed_x = BASE_SPEED; player.speed_y = 0; player.can_jump = true; player.jump_pressed_now = false; player.jump_pressed_before = false; player.standing = true; player.jumpforce = 10; player.active_animation = 0; player.enabled = true; player.cooldown = 0; player.lifes = 10; player.coins = 0; for (Uint8 i = 0; i < 6; i++) player.key[i] = false; player.sound_jump = Mix_LoadWAV(FILE_SOUND_JUMP.c_str()); player.sound_death = Mix_LoadWAV(FILE_SOUND_DEATH.c_str()); player.sound_coin = Mix_LoadWAV(FILE_SOUND_COIN.c_str()); player.animation[0].num_frames = 33; player.animation[0].index = 0; player.animation[0].timer = 0; player.animation[0].speed = 6; player.animation[0].loops = false; player.animation[0].frame[0] = 0; player.animation[0].frame[1] = 1; player.animation[0].frame[2] = 2; player.animation[0].frame[3] = 2; player.animation[0].frame[4] = 1; player.animation[0].frame[5] = 0; player.animation[0].frame[6] = 0; player.animation[0].frame[7] = 1; player.animation[0].frame[8] = 2; player.animation[0].frame[9] = 2; player.animation[0].frame[10] = 1; player.animation[0].frame[11] = 0; player.animation[0].frame[12] = 0; player.animation[0].frame[13] = 1; player.animation[0].frame[14] = 2; player.animation[0].frame[15] = 2; player.animation[0].frame[16] = 1; player.animation[0].frame[17] = 0; player.animation[0].frame[18] = 0; player.animation[0].frame[19] = 1; player.animation[0].frame[20] = 2; player.animation[0].frame[21] = 3; player.animation[0].frame[22] = 4; player.animation[0].frame[23] = 4; player.animation[0].frame[24] = 5; player.animation[0].frame[25] = 5; player.animation[0].frame[26] = 4; player.animation[0].frame[27] = 4; player.animation[0].frame[28] = 5; player.animation[0].frame[29] = 5; player.animation[0].frame[30] = 6; player.animation[0].frame[31] = 6; player.animation[0].frame[32] = 7; player.animation[1] = player.animation[0]; player.animation[2].num_frames = 8; player.animation[2].index = 0; player.animation[2].speed = 4; player.animation[2].loops = false; player.animation[2].frame[0] = 0; player.animation[2].frame[1] = 1; player.animation[2].frame[2] = 2; player.animation[2].frame[3] = 3; player.animation[2].frame[4] = 4; player.animation[2].frame[5] = 5; player.animation[2].frame[6] = 6; player.animation[2].frame[7] = 7; player.animation[3] = player.animation[2]; player.animation[4] = player.animation[2]; player.animation[5] = player.animation[2]; player.animation[6].num_frames = 20; player.animation[6].index = 0; player.animation[6].speed = 6; player.animation[6].loops = false; player.animation[6].frame[0] = 0; player.animation[6].frame[1] = 1; player.animation[6].frame[2] = 2; player.animation[6].frame[3] = 3; player.animation[6].frame[4] = 4; player.animation[6].frame[5] = 5; player.animation[6].frame[6] = 6; player.animation[6].frame[7] = 7; player.animation[6].frame[8] = 7; player.animation[6].frame[9] = 7; player.animation[6].frame[10] = 7; player.animation[6].frame[11] = 7; player.animation[6].frame[12] = 7; player.animation[6].frame[13] = 7; player.animation[6].frame[14] = 7; player.animation[6].frame[15] = 7; player.animation[6].frame[16] = 7; player.animation[6].frame[17] = 7; player.animation[6].frame[18] = 7; player.animation[6].frame[19] = 7; player.animation[7] = player.animation[6]; } void EndPlayer() { ClosePicture(player.sprite); CloseSound(player.sound_jump); CloseSound(player.sound_death); CloseSound(player.sound_coin); } void IniHud() { loadTextureFromFile(hud.sprite, FILE_HUD.c_str(), renderer); hud.src_rect.x = 0; hud.src_rect.y = 0; hud.src_rect.w = 320; hud.src_rect.h = 16; hud.dst_rect.x = 0; hud.dst_rect.y = 224; hud.dst_rect.w = 320; hud.dst_rect.h = 16; hud.num_src_rect.x = 0; hud.num_src_rect.y = 16; hud.num_src_rect.w = 5; hud.num_src_rect.h = 5; hud.num_dst_rect.x = 0; hud.num_dst_rect.y = 16; hud.num_dst_rect.w = 5; hud.num_dst_rect.h = 5; hud.bignum_src_rect.x = 0; hud.bignum_src_rect.y = 21; hud.bignum_src_rect.w = 7; hud.bignum_src_rect.h = 7; hud.bignum_dst_rect.x = 0; hud.bignum_dst_rect.y = 21; hud.bignum_dst_rect.w = 7; hud.bignum_dst_rect.h = 7; } void EndHud() { ClosePicture(hud.sprite); } void IniGame(Uint8 zone) { game.sound_drop_enemy = Mix_LoadWAV(FILE_SOUND_DROP_ENEMY.c_str()); game.sound_drop_splat = Mix_LoadWAV(FILE_SOUND_DROP_SPLAT.c_str()); game.enabled = true; game.zone = zone; // Establir el color d'esborrat SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // Inicialitzar jugador IniPlayer(); // Inicialitza mapa IniMap(); SetMapGFX(zone); SetMapMusic(zone); // Inicialitza hud IniHud(); // Inicialitza actors IniActors(); // Inicialitza tiles animats IniAnimatedTiles(); } void EndGame() { EndPlayer(); EndHud(); EndMap(); CloseSound(game.sound_drop_enemy); CloseSound(game.sound_drop_splat); CloseMusic(game.music); game.enabled = false; } void KillPlayer() { player.enabled = false; player.cooldown = COOLDOWN_TIME; // Establece la animación de morir if (player.direction == LEFT) SetPlayerAnimation(PLAYER_ANIMATION_DYING_LEFT); else SetPlayerAnimation(PLAYER_ANIMATION_DYING_RIGHT); Mix_PlayChannel(-1, player.sound_death, 0); } bool OnFloor() { Uint8 tile_on_right_foot; Uint8 tile_on_left_foot; Uint8 tile_under_right_foot; Uint8 tile_under_left_foot; bool i_am_above_platform; bool i_am_above_travesable; bool i_am_on_background; tile_under_left_foot = ReadMapTile((player.dst_rect.x + 3) / MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) / MAP_TILE_HEIGHT); tile_under_right_foot = ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) / MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) / MAP_TILE_HEIGHT); i_am_above_platform = ((tile_under_left_foot = TILE_PLATFORM) || (tile_under_right_foot = TILE_PLATFORM)); i_am_above_travesable = ((tile_under_left_foot = TILE_TRAVESABLE_PLATFORM) || (tile_under_right_foot = TILE_TRAVESABLE_PLATFORM)); tile_on_left_foot = ReadMapTile((player.dst_rect.x + 3) / MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) / MAP_TILE_HEIGHT); tile_on_right_foot = ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) / MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) / MAP_TILE_HEIGHT); i_am_on_background = ((tile_on_left_foot = TILE_BACKGROUND) && (tile_on_right_foot = TILE_BACKGROUND)); if (((i_am_above_platform) || (i_am_above_travesable)) && (i_am_on_background)) return true; else return false; } void MoveActors() { for (Uint8 i = 0; i < MAX_ACTORS; i++) if (actor[i].enabled) switch (actor[i].kind) { case KIND_FLYING_ENEMY: switch (actor[i].direction) { case RIGHT: // Calculem la nova posici� actor[i].dst_rect.x = actor[i].dst_rect.x + actor[i].speed_x; // Si eix per la vora, canvi de sentit if (actor[i].dst_rect.x + actor[i].dst_rect.w > GAME_WINDOW_WIDTH) actor[i].direction = LEFT; // Colisi� amb el mapa, correcci� a l'ultim pixel bo i canvi de sentit if ((ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) / MAP_TILE_WIDTH, actor[i].dst_rect.y / MAP_TILE_HEIGHT) != TILE_BACKGROUND) || (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) / MAP_TILE_HEIGHT) != TILE_BACKGROUND)) { actor[i].dst_rect.x = actor[i].dst_rect.x - ((actor[i].dst_rect.x + actor[i].dst_rect.w) % MAP_TILE_WIDTH); actor[i].direction = LEFT; } break; case LEFT: // Calculem la nova posici� actor[i].dst_rect.x = actor[i].dst_rect.x - actor[i].speed_x; // Si eix per la vora, canvi de sentit if (actor[i].dst_rect.x < 0) actor[i].direction = RIGHT; // Colisi� amb el mapa, correcci� a l'ultim pixel bo i canvi de sentit if ((ReadMapTile(actor[i].dst_rect.x / MAP_TILE_WIDTH, actor[i].dst_rect.y / MAP_TILE_HEIGHT) != TILE_BACKGROUND) || (ReadMapTile(actor[i].dst_rect.x / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) / MAP_TILE_HEIGHT) != TILE_BACKGROUND)) { actor[i].dst_rect.x = actor[i].dst_rect.x + (MAP_TILE_WIDTH - (actor[i].dst_rect.x % MAP_TILE_WIDTH)); actor[i].direction = RIGHT; } break; case DOWN: // Calculem la nova posici� actor[i].dst_rect.y = actor[i].dst_rect.y + actor[i].speed_y; // Si eix per la vora, canvi de sentit if (actor[i].dst_rect.y + actor[i].dst_rect.h > GAME_WINDOW_HEIGHT) actor[i].direction = UP; // Colisi� amb el mapa, correcci� a l'ultim pixel bo i canvi de sentit if ((ReadMapTile(actor[i].dst_rect.x / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) / MAP_TILE_HEIGHT) != TILE_BACKGROUND) || (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) / MAP_TILE_HEIGHT) != TILE_BACKGROUND)) { actor[i].dst_rect.y = actor[i].dst_rect.y - ((actor[i].dst_rect.y + actor[i].dst_rect.h) % MAP_TILE_WIDTH); actor[i].direction = UP; } break; case UP: // Calculem la nova posici� actor[i].dst_rect.y = actor[i].dst_rect.y - actor[i].speed_y; // Si eix per la vora, canvi de sentit if (actor[i].dst_rect.y < 0) actor[i].direction = DOWN; // Colisi� amb el mapa, correcci� a l'ultim pixel bo i canvi de sentit if ((ReadMapTile(actor[i].dst_rect.x / MAP_TILE_WIDTH, actor[i].dst_rect.y / MAP_TILE_HEIGHT) != TILE_BACKGROUND) || (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) / MAP_TILE_WIDTH, actor[i].dst_rect.y / MAP_TILE_HEIGHT) != TILE_BACKGROUND)) { actor[i].dst_rect.y = actor[i].dst_rect.y + (MAP_TILE_WIDTH - (actor[i].dst_rect.y % MAP_TILE_WIDTH)); actor[i].direction = DOWN; } break; } actor[i].frame = (actor[i].frame + 1) % 24; if (actor[i].direction == UP) actor[i].src_rect.y = 4 * 16; if (actor[i].direction == DOWN) actor[i].src_rect.y = 5 * 16; if (actor[i].direction == LEFT) actor[i].src_rect.y = 7 * 16; if (actor[i].direction == RIGHT) actor[i].src_rect.y = 6 * 16; actor[i].src_rect.x = (actor[i].frame / 4) * actor[i].dst_rect.w; break; case KIND_WALKING_ENEMY: switch (actor[i].direction) { case RIGHT: // Calculem la nova posici� actor[i].dst_rect.x = actor[i].dst_rect.x + actor[i].speed_x; // Si eix per la vora, canvi de sentit if (actor[i].dst_rect.x + actor[i].dst_rect.w > GAME_WINDOW_WIDTH) actor[i].direction = LEFT; // Colisi� amb el mapa, correcci� a l'ultim pixel bo i canvi de sentit if ((ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) / MAP_TILE_WIDTH, actor[i].dst_rect.y / MAP_TILE_HEIGHT) != TILE_BACKGROUND) || (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) / MAP_TILE_HEIGHT) != TILE_BACKGROUND)) { actor[i].dst_rect.x = actor[i].dst_rect.x - ((actor[i].dst_rect.x + actor[i].dst_rect.w) % MAP_TILE_WIDTH); actor[i].direction = LEFT; } // Arriba a la vora, correcci� a l'ultim pixel bo i canvi de sentit if (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 3) / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h) / MAP_TILE_HEIGHT) != TILE_PLATFORM) actor[i].direction = LEFT; break; case LEFT: // Calculem la nova posici� actor[i].dst_rect.x = actor[i].dst_rect.x - actor[i].speed_x; // Si eix per la vora, canvi de sentit if (actor[i].dst_rect.x < 0) actor[i].direction = RIGHT; // Colisi� amb el mapa, correcci� a l'ultim pixel bo i canvi de sentit if ((ReadMapTile(actor[i].dst_rect.x / MAP_TILE_WIDTH, actor[i].dst_rect.y / MAP_TILE_HEIGHT) != TILE_BACKGROUND) || (ReadMapTile(actor[i].dst_rect.x / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) / MAP_TILE_HEIGHT) != TILE_BACKGROUND)) { actor[i].dst_rect.x = actor[i].dst_rect.x + (MAP_TILE_WIDTH - (actor[i].dst_rect.x % MAP_TILE_WIDTH)); actor[i].direction = RIGHT; } // Arriba a la vora, correcci� a l'ultim pixel bo i canvi de sentit if (ReadMapTile((actor[i].dst_rect.x + 3) / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h) / MAP_TILE_HEIGHT) != TILE_PLATFORM) actor[i].direction = RIGHT; break; } // Animacio actor[i].frame = (actor[i].frame + 1) % 48; if (actor[i].direction == LEFT) actor[i].src_rect.y = 1 * 16; else actor[i].src_rect.y = 0 * 16; actor[i].src_rect.x = (actor[i].frame / 8) * actor[i].dst_rect.w; break; case KIND_SPEED_ENEMY: switch (actor[i].direction) { case RIGHT: // Mirem si estem en la mateixa altura que el jugador i fem que es meneje m�s r�pid if ((actor[i].dst_rect.y + 8 > player.dst_rect.y) && (actor[i].dst_rect.y + 8 < player.dst_rect.y + player.dst_rect.h - 1) && (player.can_jump)) actor[i].speed_x = 3; else actor[i].speed_x = 1; // Calculem la nova posici� actor[i].dst_rect.x = actor[i].dst_rect.x + actor[i].speed_x; // Si eix per la vora, canvi de sentit if (actor[i].dst_rect.x + actor[i].dst_rect.w > GAME_WINDOW_WIDTH) actor[i].direction = LEFT; // Colisi� amb el mapa, correcci� a l'ultim pixel bo i canvi de sentit if ((ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) / MAP_TILE_WIDTH, actor[i].dst_rect.y / MAP_TILE_HEIGHT) != TILE_BACKGROUND) || (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) / MAP_TILE_HEIGHT) != TILE_BACKGROUND)) { actor[i].dst_rect.x = actor[i].dst_rect.x - ((actor[i].dst_rect.x + actor[i].dst_rect.w) % MAP_TILE_WIDTH); actor[i].direction = LEFT; } // Arriba a la vora, correcci� a l'ultim pixel bo i canvi de sentit if (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 3) / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h) / MAP_TILE_HEIGHT) != TILE_PLATFORM) actor[i].direction = LEFT; break; case LEFT: // Mirem si estem en la mateixa altura que el jugador i fem que es meneje m�s r�pid if ((actor[i].dst_rect.y + 8 > player.dst_rect.y) && (actor[i].dst_rect.y + 8 < player.dst_rect.y + player.dst_rect.h - 1) && (player.can_jump)) actor[i].speed_x = 3; else actor[i].speed_x = 1; // Calculem la nova posici� actor[i].dst_rect.x = actor[i].dst_rect.x - actor[i].speed_x; // Si eix per la vora, canvi de sentit if (actor[i].dst_rect.x < 0) actor[i].direction = RIGHT; // Colisi� amb el mapa, correcci� a l'ultim pixel bo i canvi de sentit if ((ReadMapTile(actor[i].dst_rect.x / MAP_TILE_WIDTH, actor[i].dst_rect.y / MAP_TILE_HEIGHT) != TILE_BACKGROUND) || (ReadMapTile(actor[i].dst_rect.x / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) / MAP_TILE_HEIGHT) != TILE_BACKGROUND)) { actor[i].dst_rect.x = actor[i].dst_rect.x + (MAP_TILE_WIDTH - (actor[i].dst_rect.x % MAP_TILE_WIDTH)); actor[i].direction = RIGHT; } // Arriba a la vora, correcci� a l'ultim pixel bo i canvi de sentit if (ReadMapTile((actor[i].dst_rect.x + 3) / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h) / MAP_TILE_HEIGHT) != TILE_PLATFORM) actor[i].direction = RIGHT; break; } // Animacio actor[i].frame = (actor[i].frame + 1) % 48; if (actor[i].direction == LEFT) actor[i].src_rect.y = 2 * 16; else actor[i].src_rect.y = 3 * 16; actor[i].src_rect.x = (actor[i].frame / 8) * actor[i].dst_rect.w; break; case KIND_MOBILE_PLATFORM: switch (actor[i].direction) { case RIGHT: // Calculem la nova posici� actor[i].dst_rect.x = actor[i].dst_rect.x + actor[i].speed_x; // Si eix per la vora, canvi de sentit if (actor[i].dst_rect.x + actor[i].dst_rect.w > GAME_WINDOW_WIDTH) actor[i].direction = LEFT; // Colisi� amb el mapa, correcci� al ultim pixel bo i canvi de sentit if ((ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) / MAP_TILE_WIDTH, actor[i].dst_rect.y / MAP_TILE_HEIGHT) != TILE_BACKGROUND) || (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) / MAP_TILE_HEIGHT) != TILE_BACKGROUND)) { actor[i].dst_rect.x = actor[i].dst_rect.x - ((actor[i].dst_rect.x + actor[i].dst_rect.w) % MAP_TILE_WIDTH); actor[i].direction = LEFT; } break; case LEFT: // Calculem la nova posici� actor[i].dst_rect.x = actor[i].dst_rect.x - actor[i].speed_x; // Si eix per la vora, canvi de sentit if (actor[i].dst_rect.x < 0) actor[i].direction = RIGHT; // Colisi� amb el mapa, correcci� al ultim pixel bo i canvi de sentit if ((ReadMapTile(actor[i].dst_rect.x / MAP_TILE_WIDTH, actor[i].dst_rect.y / MAP_TILE_HEIGHT) != TILE_BACKGROUND) || (ReadMapTile(actor[i].dst_rect.x / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) / MAP_TILE_HEIGHT) != TILE_BACKGROUND)) { actor[i].dst_rect.x = actor[i].dst_rect.x + (MAP_TILE_WIDTH - (actor[i].dst_rect.x % MAP_TILE_WIDTH)); actor[i].direction = RIGHT; } break; case DOWN: // Calculem la nova posici� actor[i].dst_rect.y = actor[i].dst_rect.y + actor[i].speed_y; // Si eix per la vora, canvi de sentit if (actor[i].dst_rect.y + actor[i].dst_rect.h > GAME_WINDOW_HEIGHT) actor[i].direction = UP; // Colisi� amb el mapa, correcci� al ultim pixel bo i canvi de sentit if ((ReadMapTile(actor[i].dst_rect.x / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) / MAP_TILE_HEIGHT) != TILE_BACKGROUND) || (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) / MAP_TILE_HEIGHT) != TILE_BACKGROUND)) { actor[i].dst_rect.y = actor[i].dst_rect.y - ((actor[i].dst_rect.y + actor[i].dst_rect.h) % MAP_TILE_WIDTH); actor[i].direction = UP; } break; case UP: // Calculem la nova posici� actor[i].dst_rect.y = actor[i].dst_rect.y - actor[i].speed_y; // Si eix per la vora, canvi de sentit if (actor[i].dst_rect.y < 0) actor[i].direction = DOWN; // Colisi� amb el mapa, correcci� al ultim pixel bo i canvi de sentit if ((ReadMapTile(actor[i].dst_rect.x / MAP_TILE_WIDTH, actor[i].dst_rect.y / MAP_TILE_HEIGHT) != TILE_BACKGROUND) || (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) / MAP_TILE_WIDTH, actor[i].dst_rect.y / MAP_TILE_HEIGHT) != TILE_BACKGROUND)) { actor[i].dst_rect.y = actor[i].dst_rect.y + (MAP_TILE_WIDTH - (actor[i].dst_rect.y % MAP_TILE_WIDTH)); actor[i].direction = DOWN; } break; } break; case KIND_DROP_GENERATOR: if (actor[i].timer > 0) actor[i].timer--; else // Si el contador arriba a 0, creem un actor KIND_DROP_ENEMY { actor[i].timer = 32000; Uint8 k = 0; while (actor[k].enabled) k++; CreateActor(actor[k], KIND_DROP_ENEMY, 0, actor[i].dst_rect.x, actor[i].dst_rect.y, 16, 16, 0, 8 * 16, 0, 2, 0, 0, DOWN, i); Mix_PlayChannel(-1, game.sound_drop_enemy, 0); } // Animacio actor[i].frame = (actor[i].frame + 1) % 24; if (actor[i].timer > (DROP_TIMER - 25)) // no el pintem. Posem el frame 6 que est� buit actor[i].src_rect.x = (6 * actor[i].dst_rect.w); else actor[i].src_rect.x = (actor[i].frame / 4) * actor[i].dst_rect.w; break; case KIND_DROP_ENEMY: // Calculem la nova posici� actor[i].dst_rect.y = actor[i].dst_rect.y + actor[i].speed_y; // Si eix per la vora, adios i avisa al pare if (actor[i].dst_rect.y + actor[i].dst_rect.h > GAME_WINDOW_HEIGHT) { actor[i].enabled = false; actor[actor[i].parent].timer = DROP_TIMER; } // Colisi� amb el mapa, correcci� al ultim pixel bo, transforma en KIND_DROP_SPLAT if ((ReadMapTile(actor[i].dst_rect.x / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) / MAP_TILE_HEIGHT) != TILE_BACKGROUND) || (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) / MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) / MAP_TILE_HEIGHT) != TILE_BACKGROUND)) { actor[i].dst_rect.y = actor[i].dst_rect.y - ((actor[i].dst_rect.y + actor[i].dst_rect.h) % MAP_TILE_WIDTH); actor[i].kind = KIND_DROP_SPLAT; actor[i].frame = 0; actor[i].timer = 30; actor[i].src_rect.y = 11 * 16; Mix_PlayChannel(-1, game.sound_drop_splat, 0); } // Animacio actor[i].frame = (actor[i].frame + 1) % 24; actor[i].src_rect.x = (actor[i].frame / 4) * actor[i].dst_rect.w; break; case KIND_DROP_SPLAT: //if (actor[i].timer > 0) then if (actor[i].frame < 23) // Si encara te temps, pintem la animaci� { actor[i].timer--; actor[i].frame = (actor[i].frame + 1) % 24; actor[i].src_rect.x = ((actor[i].frame / 4) + 0) * actor[i].dst_rect.w; } else { actor[i].enabled = false; actor[actor[i].parent].timer = DROP_TIMER; } break; case KIND_COIN: actor[i].frame = (actor[i].frame + 1) % 32; actor[i].src_rect.x = (actor[i].frame / 4) * actor[i].dst_rect.w; break; case KIND_HEART: actor[i].frame = (actor[i].frame + 1) % 32; actor[i].src_rect.x = (actor[i].frame / 4) * actor[i].dst_rect.w; break; case KIND_KEY: //actor[i].frame = (actor[i].frame + 1) % 32; //actor[i].src_rect.x = (actor[i].frame / 32) * actor[i].dst_rect.w; break; case KIND_LOCK: //actor[i].frame = (actor[i].frame + 1) % 32; //actor[i].src_rect.x = (actor[i].frame / 32) * actor[i].dst_rect.w; break; } } void SetPlayerDirection(int direction) { if (player.direction != direction) { player.direction = direction; player.speed_x = 0; } } void MovePlayer(int direction) { switch (direction) { case UP: // Si pot saltar, aleshores if ((OnFloor()) && (player.can_jump)) { // Salta i ja no pot saltar (fins que toque terra i/o soltes el bot�) player.can_jump = false; // No estem quets player.standing = false; // Pilla velocitat negativa per a pujar cap amunt player.speed_y = -(player.jumpforce); // Calculem la nova posici� player.dst_rect.y = player.dst_rect.y + player.speed_y; // Soroll de saltar Mix_PlayChannel(-1, player.sound_jump, 0); } // Nou frame d'animaci� if (player.direction == LEFT) SetPlayerAnimation(PLAYER_ANIMATION_JUMPING_LEFT); else if (player.direction == RIGHT) SetPlayerAnimation(PLAYER_ANIMATION_JUMPING_RIGHT); break; case RIGHT: // Per a poder dibuixar el bot en el sentit que toca SetPlayerDirection(RIGHT); // No estem quets player.standing = false; // Incrementem la velocitat horitzontal player.speed_x = min(player.speed_x + 1, MAX_SPEED); // Calculem la nova posici� player.dst_rect.x = player.dst_rect.x + ((player.speed_x / RATIO_SPEED) + 1); // Selecci� de l'animaci� if (player.speed_y == 0) // Animaci� de caminar SetPlayerAnimation(PLAYER_ANIMATION_WALKING_RIGHT); else // Animaci� de saltar SetPlayerAnimation(PLAYER_ANIMATION_JUMPING_RIGHT); break; case LEFT: // Per a poder dibuixar el bot en el sentit que toca SetPlayerDirection(LEFT); // No estem quets player.standing = false; // Incrementem la velocitat horitzontal player.speed_x = min(player.speed_x + 1, MAX_SPEED); // Calculem la nova posici� player.dst_rect.x = player.dst_rect.x - ((player.speed_x / RATIO_SPEED) + 1); // Selecci� de l'animaci� if (player.speed_y == 0) // Animaci� de caminar SetPlayerAnimation(PLAYER_ANIMATION_WALKING_LEFT); else // Animaci� de saltar SetPlayerAnimation(PLAYER_ANIMATION_JUMPING_LEFT); break; } // Calcul del frame d'animaci� Animate(player.animation[player.active_animation], player.src_rect); } void ApplyGravity() { // Si toca piso aleshores if (OnFloor()) { // Totes les forces verticals paren player.speed_y = 0; // Podem saltar player.can_jump = true; } else { // Si no toca piso aleshores s'incrementa la velocitat vertical player.speed_y = player.speed_y + GRAVITY; // La velocitat no pot ser mai superior a la altura d'un tile del mapa, per a que no els atravesse //player.speed_y = max(min(player.speed_y, MAX_SPEED_Y), -(MAX_SPEED_Y)); player.speed_y = min(player.speed_y, MAX_SPEED_Y); // Calculem la nova posici� player.dst_rect.y = player.dst_rect.y + player.speed_y; } } void DrawSprite(LTexture *sprite, SDL_Rect src_rect, SDL_Rect dst_rect) { sprite->render(renderer, dst_rect.x, dst_rect.y, &src_rect); } void DrawMap() { SDL_Rect src_rect1; SDL_Rect dst_rect1; src_rect1.w = MAP_TILE_WIDTH; src_rect1.h = MAP_TILE_HEIGHT; dst_rect1.w = MAP_TILE_WIDTH; dst_rect1.h = MAP_TILE_HEIGHT; for (Uint8 i = 0; i < ROOM_WIDTH_IN_TILES; i++) for (Uint8 j = 0; j < ROOM_HEIGHT_IN_TILES; j++) { src_rect1.x = (GetTile(i, j) % 16) * MAP_TILE_WIDTH; src_rect1.y = (GetTile(i, j) / 16) * MAP_TILE_HEIGHT; dst_rect1.x = i * MAP_TILE_WIDTH; dst_rect1.y = j * MAP_TILE_HEIGHT; map.sprite_tile->render(renderer, dst_rect1.x, dst_rect1.y); } Uint8 i = 0; while (animated_tile[i].enabled) { src_rect1.x = ((animated_tile[i].index % 16) * MAP_TILE_WIDTH) + ((animated_tile[i].frame / 8) * MAP_TILE_WIDTH); src_rect1.y = (animated_tile[i].index / 16) * MAP_TILE_HEIGHT; dst_rect1.x = animated_tile[i].x; dst_rect1.y = animated_tile[i].y; animated_tile[i].frame = (animated_tile[i].frame + 1) % 16; map.sprite_tile->render(renderer, dst_rect1.x, dst_rect1.y); i++; } } void DrawHud() { // Pinta el fondo del marcador DrawSprite(hud.sprite, hud.src_rect, hud.dst_rect); // Pinta el numero de vides hud.bignum_src_rect.x = ((player.lifes % 100) / 10) * hud.bignum_src_rect.w; hud.bignum_dst_rect.y = 229; hud.bignum_dst_rect.x = 88; DrawSprite(hud.sprite, hud.bignum_src_rect, hud.bignum_dst_rect); hud.bignum_src_rect.x = (player.lifes % 10) * hud.bignum_src_rect.w; hud.bignum_dst_rect.x = 96; DrawSprite(hud.sprite, hud.bignum_src_rect, hud.bignum_dst_rect); // Pinta el numero de monedes hud.bignum_src_rect.x = (player.coins / 100) * hud.bignum_src_rect.w; hud.bignum_dst_rect.y = 229; hud.bignum_dst_rect.x = 258; DrawSprite(hud.sprite, hud.bignum_src_rect, hud.bignum_dst_rect); hud.bignum_src_rect.x = ((player.coins % 100) / 10) * hud.bignum_src_rect.w; hud.bignum_dst_rect.x = 258 + 8; DrawSprite(hud.sprite, hud.bignum_src_rect, hud.bignum_dst_rect); hud.bignum_src_rect.x = (player.coins % 10) * hud.bignum_src_rect.w; hud.bignum_dst_rect.x = 258 + 16; DrawSprite(hud.sprite, hud.bignum_src_rect, hud.bignum_dst_rect); if (prog.debug) { // Pinta el valor x,y del jugador hud.num_src_rect.x = (player.dst_rect.x / 100) * hud.num_src_rect.w; hud.num_dst_rect.y = 1; hud.num_dst_rect.x = 1; DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); hud.num_src_rect.x = ((player.dst_rect.x % 100) / 10) * hud.num_src_rect.w; hud.num_dst_rect.x = 5; DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); hud.num_src_rect.x = (player.dst_rect.x % 10) * hud.num_src_rect.w; hud.num_dst_rect.x = 9; DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); hud.num_src_rect.x = (player.dst_rect.y / 100) * hud.num_src_rect.w; hud.num_dst_rect.x = 17; DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); hud.num_src_rect.x = ((player.dst_rect.y % 100) / 10) * hud.num_src_rect.w; hud.num_dst_rect.x = 21; DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); hud.num_src_rect.x = (player.dst_rect.y % 10) * hud.num_src_rect.w; hud.num_dst_rect.x = 25; DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); // Pinta el valor de onfloor if (OnFloor()) hud.num_src_rect.x = 1 * hud.num_src_rect.w; else hud.num_src_rect.x = 0 * hud.num_src_rect.w; hud.num_dst_rect.y = 1; hud.num_dst_rect.x = 33; DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); hud.num_src_rect.x = (ReadMapTile((player.dst_rect.x + 3) / MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) / MAP_TILE_HEIGHT)) * hud.num_src_rect.w; hud.num_dst_rect.x = 37; DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); hud.num_src_rect.x = (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) / MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) / MAP_TILE_HEIGHT)) * hud.num_src_rect.w; hud.num_dst_rect.x = 41; DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); // Pinta el numero d'habitaci� hud.num_src_rect.x = (map.room / 100) * hud.num_src_rect.w; hud.num_dst_rect.y = 1; hud.num_dst_rect.x = 49; DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); hud.num_src_rect.x = ((map.room % 100) / 10) * hud.num_src_rect.w; hud.num_dst_rect.x = 53; DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); hud.num_src_rect.x = (map.room % 10) * hud.num_src_rect.w; hud.num_dst_rect.x = 57; DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); } } void CheckPlayerCollisionWithMap() { // Si eix per baix, recalcula posici� i canvi de pantalla if (player.dst_rect.y > GAME_WINDOW_HEIGHT) { // Coloquem al jugador dalt de tot player.dst_rect.y = 1; // Canvi de pantalla LoadRoom(map.room + 12); } // Si eix per dalt, recalcula posici� i canvi de pantalla if ((player.dst_rect.y + player.dst_rect.h - 1) < 0) { // Recoloca el personat player.dst_rect.y = GAME_WINDOW_HEIGHT - player.dst_rect.h; // Canvi de pantalla LoadRoom(map.room - 12); } // Si eix per la vora, recalcula posici� i canvi de pantalla if (player.dst_rect.x > GAME_WINDOW_WIDTH) { // Coloquem al jugador en la entrada de la nova pantalla player.dst_rect.x = 0; // Canvi de pantalla LoadRoom(map.room + 1); } // Si eix per la vora, recalcula posici� i canvi de pantalla if ((player.dst_rect.x + player.dst_rect.w - 1) < 0) { // El posem al borde dret player.dst_rect.x = GAME_WINDOW_WIDTH - player.dst_rect.w; // Canvi de pantalla LoadRoom(map.room - 1); } // Mirem si colisionem cap avall i corregim Uint8 tile_on_left_foot = ReadMapTile((player.dst_rect.x + 3) / MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) / MAP_TILE_HEIGHT); Uint8 tile_on_right_foot = ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) / MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) / MAP_TILE_HEIGHT); bool i_am_on_platform = (tile_on_left_foot = TILE_PLATFORM) || (tile_on_right_foot = TILE_PLATFORM); bool i_am_on_travesable = (tile_on_left_foot = TILE_TRAVESABLE_PLATFORM) || (tile_on_right_foot = TILE_TRAVESABLE_PLATFORM); if ((player.was_on_background) && (player.speed_y > 0) && ((i_am_on_platform) || (i_am_on_travesable))) { // Corregim la posicio player.dst_rect.y = player.dst_rect.y - ((player.dst_rect.y + player.dst_rect.h - 1) % MAP_TILE_HEIGHT) - 1; // Ja podem saltar player.can_jump = true; } player.was_on_background = ((tile_on_left_foot = TILE_BACKGROUND) && (tile_on_right_foot = TILE_BACKGROUND)); // Mirem si colisionem cap amunt i corregim if ((ReadMapTile((player.dst_rect.x + 3) / MAP_TILE_WIDTH, player.dst_rect.y / MAP_TILE_HEIGHT) == TILE_PLATFORM) || (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) / MAP_TILE_WIDTH, player.dst_rect.y / MAP_TILE_HEIGHT) == TILE_PLATFORM)) // Corregim la posicio player.dst_rect.y = player.dst_rect.y + (MAP_TILE_HEIGHT - (player.dst_rect.y % MAP_TILE_HEIGHT)); // Una vegada em permes la colisi� amunt o avall, al haver un marge de 3 pixels pot ser que estiguem dins d'una paret. S'ha de corregir aquest offset // Mirem les colisions laterals if ((ReadMapTile(player.dst_rect.x / MAP_TILE_WIDTH, player.dst_rect.y / MAP_TILE_HEIGHT) == TILE_PLATFORM) || (ReadMapTile(player.dst_rect.x / MAP_TILE_WIDTH, (player.dst_rect.y + (player.dst_rect.h / 2)) / MAP_TILE_HEIGHT) == TILE_PLATFORM) || (ReadMapTile(player.dst_rect.x / MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) / MAP_TILE_HEIGHT) == TILE_PLATFORM)) player.dst_rect.x = player.dst_rect.x + (MAP_TILE_WIDTH - (player.dst_rect.x % MAP_TILE_WIDTH)); if ((ReadMapTile((player.dst_rect.x + player.dst_rect.w - 1) / MAP_TILE_WIDTH, player.dst_rect.y / MAP_TILE_HEIGHT) == TILE_PLATFORM) || (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 1) / MAP_TILE_WIDTH, (player.dst_rect.y + (player.dst_rect.h / 2)) / MAP_TILE_HEIGHT) == TILE_PLATFORM) || (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 1) / MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) / MAP_TILE_HEIGHT) == TILE_PLATFORM)) player.dst_rect.x = player.dst_rect.x - ((player.dst_rect.x + player.dst_rect.w) % MAP_TILE_WIDTH); // Comprovar si toca alguna part del mapa de les que maten if (ReadMapTile((player.dst_rect.x + 8) / MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 12) / MAP_TILE_HEIGHT) == TILE_KILLING_PLATFORM) if (player.enabled) KillPlayer(); } void CheckPlayerCollisionWithActors() { for (Uint8 i = 0; i < MAX_ACTORS; i++) if (actor[i].enabled) switch (actor[i].kind) { case KIND_FLYING_ENEMY: case KIND_WALKING_ENEMY: case KIND_DROP_ENEMY: case KIND_SPEED_ENEMY: if (((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) || ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) || ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) || ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h))) if (player.enabled) KillPlayer(); break; case KIND_COIN: if (((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) || ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) || ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) || ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h))) { player.coins++; actor[i].enabled = false; SetActor((actor[i].dst_rect.x / 16), (actor[i].dst_rect.y / 16), 0); Mix_PlayChannel(-1, player.sound_coin, 0); } break; case KIND_HEART: if (((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) || ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) || ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) || ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h))) { player.lifes++; actor[i].enabled = false; SetActor((actor[i].dst_rect.x / 16), (actor[i].dst_rect.y / 16), 0); Mix_PlayChannel(-1, player.sound_coin, 0); } break; case KIND_KEY: if (((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) || ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) || ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) || ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) && (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) && (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h))) { player.key[actor[i].id] = true; actor[i].enabled = false; SetActor((actor[i].dst_rect.x / 16), (actor[i].dst_rect.y / 16), 0); Mix_PlayChannel(-1, player.sound_coin, 0); } break; case KIND_LOCK: // Les colisions amb aquest actor no tenen en compte el ENEMY_HITBOX_REDUCTION // El jugador colisiona amb el actor per l'esquerra del jugador if (((actor[i].dst_rect.x + actor[i].dst_rect.w > player.dst_rect.x) && (actor[i].dst_rect.x + actor[i].dst_rect.w < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + actor[i].dst_rect.h > player.dst_rect.y) && (actor[i].dst_rect.y + actor[i].dst_rect.h < player.dst_rect.y + player.dst_rect.h)) || ((actor[i].dst_rect.x + actor[i].dst_rect.w > player.dst_rect.x) && (actor[i].dst_rect.x + actor[i].dst_rect.w < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y > player.dst_rect.y) && (actor[i].dst_rect.y < player.dst_rect.y + player.dst_rect.h))) { // Si tenim clau if (player.key[actor[i].id]) { actor[i].enabled = false; SetActor((actor[i].dst_rect.x / MAP_TILE_WIDTH), (actor[i].dst_rect.y / MAP_TILE_HEIGHT), 0); } // Si no tenim clau else player.dst_rect.x = player.dst_rect.x + (MAP_TILE_WIDTH - (player.dst_rect.x % MAP_TILE_WIDTH)); } // El jugador colisiona amb el actor per la dreta del jugador if (((actor[i].dst_rect.x > player.dst_rect.x) && (actor[i].dst_rect.x < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y + actor[i].dst_rect.h > player.dst_rect.y) && (actor[i].dst_rect.y + actor[i].dst_rect.h < player.dst_rect.y + player.dst_rect.h)) || ((actor[i].dst_rect.x > player.dst_rect.x) && (actor[i].dst_rect.x < player.dst_rect.x + player.dst_rect.w) && (actor[i].dst_rect.y > player.dst_rect.y) && (actor[i].dst_rect.y < player.dst_rect.y + player.dst_rect.h))) { // Si tenim clau if (player.key[actor[i].id]) { actor[i].enabled = false; SetActor((actor[i].dst_rect.x / MAP_TILE_WIDTH), (actor[i].dst_rect.y / MAP_TILE_HEIGHT), 0); } // Si no tenim clau else player.dst_rect.x = player.dst_rect.x - ((player.dst_rect.x + player.dst_rect.w) % MAP_TILE_WIDTH); } break; } } void SetProgSection(Uint8 section) { switch (section) { case SECTION_MENU: prog.section = SECTION_MENU; IniMenu(); EndGame(); break; case SECTION_GAME: prog.section = SECTION_GAME; IniGame(ZONE_VOLCANO); EndMenu(); break; case SECTION_QUIT: prog.section = SECTION_QUIT; EndGame(); EndMenu(); break; } } void IniProgram() { event = new SDL_Event(); prog.music_enabled = true; prog.filter = true; SetProgSection(SECTION_MENU); prog.debug = false; if (prog.music_enabled) Mix_VolumeMusic(100); else Mix_VolumeMusic(0); loadTextureFromFile(prog.sprite, FILE_FILTER.c_str(), renderer); prog.src_rect.x = 0; prog.src_rect.y = 0; prog.src_rect.w = 640; prog.src_rect.h = 480; prog.dst_rect.x = 0; prog.dst_rect.y = 0; prog.dst_rect.w = 640; prog.dst_rect.h = 480; } void EndProgram() { delete event; ClosePicture(prog.sprite); EndGame(); EndMenu(); } int main(int argc, char *args[]) { setExecutablePath(args[0]); fullscreen = false; // Inicializa SDL SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_HAPTIC); window = SDL_CreateWindow((WINDOW_TITLE + BUILD).c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN); renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); SDL_RenderSetLogicalSize(renderer, 320, 240); // Inicializa el audio Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 2048); allocatePointers(); // Inicializa el programa IniProgram(); // Color de relleno SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); // Inicializa las variables generales quit = false; delta_time = SDL_GetTicks(); // Bucle del programa while (!quit) { switch (prog.section) { case SECTION_GAME: { // Inicialitza habitaci� LoadRoom(STARTING_ROOM); // Conecta la musica Mix_PlayMusic(game.music, -1); // Bucle de joc while (game.enabled) { while (SDL_PollEvent(event) > 0) { // Si arriva el event de tancar la aplicaci�, eixim del bucle if (event->type == SDL_QUIT) { quit = true; SetProgSection(SECTION_MENU); break; } else if ((event->type == SDL_KEYDOWN) && (event->key.repeat == 0)) switch (event->key.keysym.scancode) { case SDL_SCANCODE_ESCAPE: SetProgSection(SECTION_MENU); break; case SDL_SCANCODE_F: if (fullscreen) { SDL_SetWindowFullscreen(window, 0); SDL_ShowCursor(1); fullscreen = false; } else { SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); SDL_ShowCursor(0); fullscreen = true; } break; case SDL_SCANCODE_W: LoadRoom(map.room - 12); break; case SDL_SCANCODE_A: LoadRoom(map.room - 1); break; case SDL_SCANCODE_S: LoadRoom(map.room + 12); break; case SDL_SCANCODE_D: LoadRoom(map.room + 1); break; case SDL_SCANCODE_G: player.lifes = 255; break; case SDL_SCANCODE_M: prog.music_enabled = !prog.music_enabled; if (prog.music_enabled) Mix_VolumeMusic(100); else Mix_VolumeMusic(0); break; case SDL_SCANCODE_T: IniPlayer(); LoadRoom(TEST_ROOM); break; case SDL_SCANCODE_F1: prog.debug = !prog.debug; break; case SDL_SCANCODE_F2: prog.filter = !prog.filter; break; default: break; } } if ((SDL_GetTicks() - delta_time) > GAME_SPEED) { // Agafar el array de tecles keys = SDL_GetKeyboardState(nullptr); // Mirem si esta apretant el bot� de saltar. Per tal d'evitar repeticions en aquest boto if (keys[SDL_SCANCODE_UP] == 0) player.jump_pressed_now = false; else player.jump_pressed_now = true; // Si el jugador est� deshabilitat, anem reduint el temps d'espera i canviant el frame de la animaci� de mort if (!player.enabled) { if (player.cooldown > 0) { player.cooldown--; Animate(player.animation[player.active_animation], player.src_rect); } else // Ha acabat el temps d'estar mort. Revivim al jugador { player.enabled = true; // Coloquem al jugador en el sentit que tenia quan va entrar a la habitaci� if (player.respawn_direction == LEFT) { SetPlayerAnimation(PLAYER_ANIMATION_STANDING_LEFT); player.direction = LEFT; } if (player.respawn_direction == RIGHT) { SetPlayerAnimation(PLAYER_ANIMATION_STANDING_RIGHT); player.direction = RIGHT; } // Coloquem al jugador en les coordenades per on va entrar player.dst_rect.x = min(player.respawn_x, GAME_WINDOW_WIDTH - player.dst_rect.w); player.dst_rect.y = player.respawn_y; // Recarreguem la habitaci� LoadRoom(map.room); if (player.lifes > 0) // Descontem una vida player.lifes--; else // Si no li queden vides, eixim al menu SetProgSection(SECTION_MENU); } } // Comprovem les tecles que ens interesen i actuem en consequ�ncia if ((keys[SDL_SCANCODE_RIGHT] == 1) && (player.enabled)) MovePlayer(RIGHT); if ((keys[SDL_SCANCODE_LEFT] == 1) && (keys[SDL_SCANCODE_RIGHT] == 0) && (player.enabled)) MovePlayer(LEFT); if ((keys[SDL_SCANCODE_UP] == 1) && (player.enabled) && (!player.jump_pressed_before)) MovePlayer(UP); player.jump_pressed_before = player.jump_pressed_now; // Mirem si no estem fent cap a cap costat i reduim la velocitat horitzontal if ((keys[SDL_SCANCODE_RIGHT] == 0) && (keys[SDL_SCANCODE_LEFT] == 0) && (player.enabled)) { player.speed_x = 0; // Estem quets player.standing = true; // Posem la animaci� d'estar quet si no estem saltant if (player.can_jump) { if (player.direction == LEFT) SetPlayerAnimation(PLAYER_ANIMATION_STANDING_LEFT); else if (player.direction == RIGHT) SetPlayerAnimation(PLAYER_ANIMATION_STANDING_RIGHT); Animate(player.animation[player.active_animation], player.src_rect); } } // Moure els actors MoveActors(); // Apliquem la gravetat if (player.enabled) ApplyGravity(); // Comprovar colisions amb els actors if (player.enabled) CheckPlayerCollisionWithActors(); // Comprovar colisions amb el mapejat CheckPlayerCollisionWithMap(); SDL_RenderSetLogicalSize(renderer, 320, 240); // Borrem pantalla SDL_RenderClear(renderer); // Pintem el fondo DrawSprite(map.background, map.src_rect, map.dst_rect); // Pinta el mapa DrawMap(); // Pintem el jugador DrawSprite(player.sprite, player.src_rect, player.dst_rect); // Pintem els actors for (Uint8 i = 0; i < MAX_ACTORS; i++) if (actor[i].enabled) DrawSprite(map.sprite_actor, actor[i].src_rect, actor[i].dst_rect); // Pintem el marcador DrawHud(); // Posem el filtro de pantalla if (prog.filter) { SDL_RenderSetLogicalSize(renderer, 640, 480); DrawSprite(prog.sprite, prog.src_rect, prog.dst_rect); } // Mostrem la pantalla SDL_RenderPresent(renderer); delta_time = SDL_GetTicks(); } } break; } case SECTION_MENU: { // Establir el color d'esborrat SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); // Apaga la musica Mix_HaltMusic(); while (menu.enabled) { // Bucle del menu while (SDL_PollEvent(event) > 0) { // Si arriva el event de tancar la aplicaci�, eixim del bucle if (event->type == SDL_QUIT) { quit = true; menu.enabled = false; break; } else if ((event->type == SDL_KEYDOWN) and (event->key.repeat == 0)) switch (event->key.keysym.scancode) { case SDL_SCANCODE_ESCAPE: quit = true; SetProgSection(SECTION_QUIT); break; break; // (Des)Activa el mode de pantalla completa case SDL_SCANCODE_F: if (fullscreen) { SDL_SetWindowFullscreen(window, 0); SDL_ShowCursor(1); fullscreen = false; } else { SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); SDL_ShowCursor(0); fullscreen = true; } break; // (Des)Activa la musica case SDL_SCANCODE_M: prog.music_enabled = !prog.music_enabled; if (prog.music_enabled) Mix_VolumeMusic(100); else Mix_VolumeMusic(0); break; // (Des)Activa les scanlines case SDL_SCANCODE_F2: prog.filter = !prog.filter; break; // Inicia el joc case SDL_SCANCODE_RETURN: if (menu.timer > 99) { menu.timer = 99; Mix_HaltMusic(); Mix_HaltChannel(-1); Mix_PlayChannel(-1, menu.sound_start, 0); menu.frame = 0; } break; default: break; } } if ((SDL_GetTicks() - delta_time) > GAME_SPEED) { switch (menu.section) { case MENU_SECTION_MAIN: { if (menu.timer > 100) // Menu normal { menu.frame = (menu.frame + 1) % 30000; SDL_RenderSetLogicalSize(renderer, 320, 240); // Borrem pantalla SDL_RenderClear(renderer); // Pintem el fondo del menu //DrawSprite(menu.sprite, menu.src_rect_fondo, menu.dst_rect_fondo); // Pintem el logo DESPLEGA menu.dst_rect_logo_zoom.w = menu.dst_rect_logo.w; menu.dst_rect_logo_zoom.h = min(menu.dst_rect_logo_zoom.h + 4, menu.dst_rect_logo.h); menu.dst_rect_logo_zoom.x = menu.dst_rect_logo.x; menu.dst_rect_logo_zoom.y = menu.dst_rect_logo.y; DrawSprite(menu.sprite, menu.src_rect_logo, menu.dst_rect_logo_zoom); if (menu.frame == (154 / 4)) Mix_PlayChannel(-1, menu.sound_logo, 0); if (menu.frame == (300 / 4)) // Conecta la musica Mix_PlayMusic(menu.music, -1); if (menu.frame > (300 / 4)) { // Pintem el text: PRESS RETURN TO START if ((menu.frame % 64) < 32) DrawSprite(menu.sprite, menu.src_rect_text, menu.dst_rect_text); // Pintem el text: JAILGAMES 2016 DrawSprite(menu.sprite, menu.src_rect_text2, menu.dst_rect_text2); } } else // Menu havent apretat START/RETURN { menu.timer--; menu.frame = (menu.frame + 1) % 30000; // Borrem pantalla SDL_RenderSetLogicalSize(renderer, 320, 240); SDL_RenderClear(renderer); // Pintem el fondo del menu //DrawSprite(menu.sprite, menu.src_rect_fondo, menu.dst_rect_fondo); // Pintem el logo DrawSprite(menu.sprite, menu.src_rect_logo, menu.dst_rect_logo); // Pintem el text: PRESS RETURN TO START if ((menu.frame % 8) < 4) DrawSprite(menu.sprite, menu.src_rect_text, menu.dst_rect_text); // Pintem el text: JAILGAMES 2016 DrawSprite(menu.sprite, menu.src_rect_text2, menu.dst_rect_text2); if (menu.timer == 0) { //prog.section = SECTION_GAME; //menu.enabled = false; //game.enabled = true; //menu.section = MENU_SECTION_ANIMATION; //menu.timer = 100; } } // Posem el filtro de pantalla if (prog.filter) { SDL_RenderSetLogicalSize(renderer, 640, 480); DrawSprite(prog.sprite, prog.src_rect, prog.dst_rect); } // Mostrem la pantalla SDL_RenderPresent(renderer); delta_time = SDL_GetTicks(); } case MENU_SECTION_ANIMATION: { // No hem pulsat el bot� d'start if (menu.timer > 100) // Animaci� inicial if (!menu.animation[0].loops) { // Borrem pantalla SDL_RenderSetLogicalSize(renderer, 320, 240); SDL_RenderClear(renderer); AnimateIntroMenu(menu.animation[0], menu.src_rect_animation); // Pintem la animacio DrawSprite(menu.sprite_animation, menu.src_rect_animation, menu.dst_rect_animation); // Posem el filtro de pantalla if (prog.filter) { SDL_RenderSetLogicalSize(renderer, 640, 480); DrawSprite(prog.sprite, prog.src_rect, prog.dst_rect); } // Mostrem la pantalla SDL_RenderPresent(renderer); delta_time = SDL_GetTicks(); } else // Animaci� segona en loop { if (Mix_PlayingMusic() == 0) Mix_PlayMusic(menu.music, -1); // Borrem pantalla SDL_RenderSetLogicalSize(renderer, 320, 240); SDL_RenderClear(renderer); AnimateIntroMenu(menu.animation[1], menu.src_rect_animation); // Pintem la animacio DrawSprite(menu.sprite_animation, menu.src_rect_animation, menu.dst_rect_animation); // Pintem el text: PRESS RETURN TO START if ((menu.animation[1].timer % 64) < 32) DrawSprite(menu.sprite, menu.src_rect_text, menu.dst_rect_text); // Pintem el text: JAILGAMES 2016 DrawSprite(menu.sprite, menu.src_rect_text2, menu.dst_rect_text2); // Posem el filtro de pantalla if (prog.filter) { SDL_RenderSetLogicalSize(renderer, 640, 480); DrawSprite(prog.sprite, prog.src_rect, prog.dst_rect); } // Mostrem la pantalla SDL_RenderPresent(renderer); delta_time = SDL_GetTicks(); } else // Hem pulsat el bot� d'start { Mix_HaltMusic(); // Borrem pantalla SDL_RenderSetLogicalSize(renderer, 320, 240); SDL_RenderClear(renderer); AnimateIntroMenu(menu.animation[1], menu.src_rect_animation); // Pintem la animacio DrawSprite(menu.sprite_animation, menu.src_rect_animation, menu.dst_rect_animation); // Pintem el text: PRESS RETURN TO START if ((menu.animation[1].timer % 8) < 4) DrawSprite(menu.sprite, menu.src_rect_text, menu.dst_rect_text); // Pintem el text: JAILGAMES 2016 DrawSprite(menu.sprite, menu.src_rect_text2, menu.dst_rect_text2); // Posem el filtro de pantalla if (prog.filter) { SDL_RenderSetLogicalSize(renderer, 640, 480); DrawSprite(prog.sprite, prog.src_rect, prog.dst_rect); } // Mostrem la pantalla SDL_RenderPresent(renderer); delta_time = SDL_GetTicks(); menu.timer--; if (menu.timer == 0) { SetProgSection(SECTION_GAME); menu.timer = 200; } } break; } } } } } // Finalitzar la m�sica, els samples i el audio CloseSound(player.sound_jump); CloseSound(player.sound_death); CloseSound(player.sound_coin); CloseSound(menu.sound_logo); CloseSound(menu.sound_start); CloseSound(game.sound_drop_enemy); CloseSound(game.sound_drop_splat); Mix_HaltMusic(); CloseMusic(game.music); CloseMusic(menu.music); Mix_CloseAudio(); EndProgram(); // Destruir els sprites ClosePicture(prog.sprite); ClosePicture(player.sprite); ClosePicture(map.sprite_tile); ClosePicture(map.sprite_actor); ClosePicture(map.background); ClosePicture(menu.sprite); ClosePicture(menu.sprite_animation); ClosePicture(hud.sprite); deletePointers(); // Destruir la finestra SDL_DestroyWindow(window); // Finalitzar SDL SDL_Quit(); } } return 0; }