diff --git a/.gitignore b/.gitignore index 1cea2a2..809b115 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,4 @@ thumbs.db *.aseprite media_work resources -source/old bin \ No newline at end of file diff --git a/source/old/volcano.pas b/source/old/volcano.pas new file mode 100644 index 0000000..fff7345 --- /dev/null +++ b/source/old/volcano.pas @@ -0,0 +1,2704 @@ +program Volcano; +{$IFDEF DARWIN} + {$linkframework Cocoa} + {$linkframework SDL2} + {$linkframework OpenGL} + {$linkframework SDL2_image} + {$linkframework SDL2_mixer} +{$ELSE} + {$APPTYPE GUI} +{$ENDIF} + + +// 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 + +uses sdl2, SDL2_image, SDL2_mixer; + +const + GAME_SPEED = 24; //16 = normal-rapid, 24 = normal. Quan menor, més ràpid + + UP = 0; + DOWN = 2; + RIGHT = 1; + LEFT = 3; + NONE = 4; + + MAP_TILE_HEIGHT = 16; + MAP_TILE_WIDTH = 16; + + ROOM_WIDTH_IN_TILES = 20; + ROOM_HEIGHT_IN_TILES = 14; + + GAME_WINDOW_WIDTH = 320; + GAME_WINDOW_HEIGHT = 234; + + TEST_ROOM = 118; + STARTING_ROOM = 161;//TEST_ROOM; + STARTING_PLAYER_TILE_X = 5; + STARTING_PLAYER_TILE_Y = 11; + ENEMY_HITBOX_REDUCTION = 4; + COOLDOWN_TIME = 50; + GRAVITY = 1; + MAX_SPEED_Y = 5; + BASE_SPEED = 1; + MAX_SPEED = 8; + RATIO_SPEED = 8; + DROP_TIMER = 100; + + TOP_COLLISION = 0; + BOTTOM_COLLISION = 1; + LEFT_COLLISION = 2; + RIGHT_COLLISION = 3; + NO_COLLISION = 4; + + MAX_ACTORS = 50; + + KIND_FLYING_ENEMY = 0; + KIND_COIN = 1; + KIND_HEART = 2; + KIND_STATIC_ENEMY = 3; + KIND_MOBILE_PLATFORM = 4; + KIND_WALKING_ENEMY = 5; + KIND_DROP_GENERATOR = 6; + KIND_DROP_ENEMY = 7; + KIND_DROP_SPLAT = 8; + KIND_SPEED_ENEMY = 9; + KIND_KEY = 10; + KIND_LOCK = 11; + + CODE_ENEMY_V1U = 208; + CODE_ENEMY_V2U = 209; + CODE_ENEMY_V3U = 210; + CODE_ENEMY_V1D = 211; + CODE_ENEMY_V2D = 212; + CODE_ENEMY_V3D = 213; + + CODE_ENEMY_H1L = 214; + CODE_ENEMY_H2L = 215; + CODE_ENEMY_H3L = 216; + CODE_ENEMY_H1R = 217; + CODE_ENEMY_H2R = 218; + CODE_ENEMY_H3R = 219; + + CODE_ENEMY_W1L = 224; + CODE_ENEMY_W2L = 225; + CODE_ENEMY_W3L = 226; + CODE_ENEMY_W1R = 227; + CODE_ENEMY_W2R = 228; + CODE_ENEMY_W3R = 229; + + CODE_ENEMY_DRP = 230; + + CODE_ENEMY_SPL = 231; + CODE_ENEMY_SPR = 232; + + CODE_COIN = 240; + CODE_HEART = 241; + CODE_KEY_RED = 242; + CODE_LOCK_RED = 243; + CODE_KEY_BLUE = 244; + CODE_LOCK_BLUE = 245; + CODE_KEY_GREEN = 246; + CODE_LOCK_GREEN = 247; + CODE_KEY_YELLOW = 248; + CODE_LOCK_YELLOW = 249; + + MAX_ANIMATED_TILES = 200; + + TILE_BACKGROUND = 0; + TILE_PLATFORM = 1; + TILE_KILLING_PLATFORM = 2; + TILE_ACTOR = 3; + TILE_TRAVESABLE_PLATFORM = 4; + + PLAYER_ANIMATION_STANDING_LEFT = 0; + PLAYER_ANIMATION_STANDING_RIGHT = 1; + PLAYER_ANIMATION_WALKING_LEFT = 2; + PLAYER_ANIMATION_WALKING_RIGHT = 3; + PLAYER_ANIMATION_JUMPING_LEFT = 4; + PLAYER_ANIMATION_JUMPING_RIGHT = 5; + PLAYER_ANIMATION_DYING_LEFT = 6; + PLAYER_ANIMATION_DYING_RIGHT = 7; + + SECTION_MENU = 0; + SECTION_GAME = 1; + SECTION_QUIT = 2; + + MENU_SECTION_MAIN = 0; + MENU_SECTION_CREDITS = 1; + MENU_SECTION_ANIMATION = 2; + + ZONE_SURFACE = 0; + ZONE_VOLCANO = 1; + + WINDOW_TITLE = 'Volcano v0005'; + BUILD = '.05'; + FILE_MAP_VOLCANO = './data/volcano.map'; + FILE_TILES_VOLCANO = './data/gfx/tiles_volcano.png'; + FILE_TILES_SURFACE = './data/gfx/tiles_surface.png'; + FILE_BKG_SURFACE = './data/gfx/bkg_surface.png'; + FILE_MENU = './data/gfx/menu.png'; + FILE_MENU_ANIMATION = './data/gfx/menu_animation.png'; + FILE_ACTORS = './data/gfx/actors.png'; + FILE_PLAYER = './data/gfx/player.png'; + FILE_HUD = './data/gfx/hud.png'; + FILE_FILTER = './data/gfx/filter.png'; + FILE_SOUND_JUMP = './data/sound/sound_player_jump.wav'; + FILE_SOUND_DEATH = './data/sound/sound_player_death.wav'; + FILE_SOUND_COIN = './data/sound/sound_player_coin.wav'; + FILE_SOUND_MENU_LOGO = './data/sound/sound_menu_logo.wav'; + FILE_SOUND_MENU_START = './data/sound/sound_menu_start.wav'; + FILE_SOUND_DROP_ENEMY = './data/sound/sound_drop_enemy.wav'; + FILE_SOUND_DROP_SPLAT = './data/sound/sound_drop_splat.wav'; + FILE_MUSIC_SURFACE = './data/music/music_surface.mp3'; + FILE_MUSIC_VOLCANO = './data/music/music_volcano.mp3'; + FILE_MUSIC_MENU = './data/music/music_menu.mp3'; + +type + Tanimation = record + num_frames: byte; + index: byte; + speed: byte; + timer: longword; + loops: boolean; // salta a TRUE quan la animació es reinicia + frame: array [0 .. 49] of byte; + end; + + Tprogram = record + music_enabled: boolean; + filter: boolean; + section: byte; + debug: boolean; + sprite: PSDL_Texture; + src_rect: TSDL_Rect; + dst_rect: TSDL_Rect; + end; + + Tgame = record + zone: byte; // Zona en la que estem + music: PMix_Music; + enabled: boolean; + sound_drop_enemy: PMix_Chunk; + sound_drop_splat: PMix_Chunk; + end; + + Tmenu = record + section: byte; + sprite: PSDL_Texture; + sprite_animation: PSDL_Texture; + src_rect_fondo: TSDL_Rect; + dst_rect_fondo: TSDL_Rect; + src_rect_logo: TSDL_Rect; + dst_rect_logo: TSDL_Rect; + dst_rect_logo_zoom: TSDL_Rect; + src_rect_text: TSDL_Rect; + dst_rect_text: TSDL_Rect; + src_rect_text2: TSDL_Rect; + dst_rect_text2: TSDL_Rect; + music: PMix_Music; + sound_logo: PMix_Chunk; + sound_start: PMix_Chunk; + frame: integer; + enabled: boolean; + timer: integer; + animation: array [0..1] of Tanimation; + src_rect_animation: TSDL_Rect; + dst_rect_animation: TSDL_Rect; + end; + + Tplayer = record + sprite: PSDL_Texture; + src_rect: TSDL_Rect; + dst_rect: TSDL_Rect; + direction: byte; // Sentit del desplaçament + speed_x, + speed_y: integer; // Quantitat de pixels a desplaçar + jumpforce: integer; // Quantitat de pixels a desplaçar i velocitat que pilla al saltar + active_animation: byte; // Index per al array d'animació + animation: array [0 .. 7] of Tanimation; + can_jump: boolean; // Indica si el jugador pot saltar (FALSE si ja està saltant) + jump_pressed_now, + jump_pressed_before: boolean; // Indica si el botó de saltar està apretat, per evitar el autofire + standing: boolean; // Indica si el jugador está quet. + respawn_x, + respawn_y: integer; // Coordenades per a reviure + respawn_direction: byte; // Per a reviure en la mateixa direcció que s'entra a la habitació + enabled: boolean; // Indica si pot rebre ordres + cooldown: integer; // Temps d'inhabilitació + lifes: byte; // Quantitat de vides + coins: integer; // Quantitat de monedes + key: array [0..5] of boolean; + sound_jump: PMix_Chunk; + sound_death: PMix_Chunk; + sound_coin: PMix_Chunk; + was_on_background: boolean; // Ens guardem si en l'anterior loop el tile sobre el qual teniem els nostres peus era background [27/05/2016] [DOC] + end; + + Tactor = record + src_rect: TSDL_Rect; + dst_rect: TSDL_Rect; + //animation: Tanimation; + kind: byte; // Tipus d'actor: enemic, moneda, clau, plataforma ... + direction: byte; // Sentit del desplaçament + id: byte; + speed_x, + speed_y: integer; // Velocitat = quantitat de pixels a desplaçar + frame: integer; + timer: integer; + enabled: boolean; + parent: byte; // Index al pare de l'actor + end; + + Tanimated_tile = record + enabled: boolean; + x, y: integer; + index: integer; + frame: byte; + end; + + Thud = record + sprite: PSDL_Texture; + src_rect: TSDL_Rect; + dst_rect: TSDL_Rect; + num_src_rect: TSDL_Rect; + num_dst_rect: TSDL_Rect; + bignum_src_rect: TSDL_Rect; + bignum_dst_rect: TSDL_Rect; + end; + + Pmap = ^Tmap; + Tmap = record + sprite_tile: PSDL_Texture; + sprite_actor: PSDL_Texture; + background: PSDL_Texture; + src_rect: TSDL_Rect; + dst_rect: TSDL_Rect; + tile: array of byte; + actor: array of byte; + w, h: byte; + room: byte; + end; + +var + fullscreen: boolean; + window: PSDL_Window; + renderer: PSDL_Renderer; + prog: Tprogram; + menu: Tmenu; + game: Tgame; + player: Tplayer; + map: Tmap; + hud: Thud; + actor: array [0..MAX_ACTORS - 1] of Tactor; + animated_tile: array [0..MAX_ANIMATED_TILES - 1] of Tanimated_tile; + e: TSDL_Event; + keys: PUInt8; + quit: boolean; + delta_time: Uint32; + i: byte; + +function max(a,b:integer):integer; +begin + if a > b then max:=a else max:=b; +end; + +function min(a,b:integer):integer; +begin + if a < b then min:=a else min:=b; +end; + +function OpenPicture(name: PChar) : PSDL_Texture; +var + image: PSDL_Surface; + texture: PSDL_Texture; +begin + image := IMG_Load(name); + texture := SDL_CreateTextureFromSurface(renderer, image); + SDL_FreeSurface(image); + OpenPicture := texture; +end; + +procedure CloseSound(var sound: PMix_Chunk); +begin + if sound <> nil then + Mix_FreeChunk(sound); + sound := nil; +end; + +procedure CloseMusic(var music: PMix_Music); +begin + if music <> nil then + Mix_FreeMusic(music); + music := nil; +end; + +procedure ClosePicture(var picture: PSDL_Texture); +begin + if picture <> nil then + SDL_DestroyTexture(picture); + picture := nil; +end; + +function GetTile(x, y: byte): byte; +// Entrada: coordenades en tiles relatives a la habitació actual +// Eixida: el valor del byte +var + room_x, room_y: byte; +begin + room_x := (map.room mod 12) * ROOM_WIDTH_IN_TILES; + room_y := (map.room div 12) * ROOM_HEIGHT_IN_TILES; + GetTile := map.tile[(room_x + x ) + (room_y + y) * map.w]; +end; + +function ReadMapTile(x, y: byte): byte; +begin + case GetTile(x,y) of + 000 .. 063: ReadMapTile := TILE_BACKGROUND; + 064 .. 143: ReadMapTile := TILE_PLATFORM; + 144 .. 175: ReadMapTile := TILE_TRAVESABLE_PLATFORM; + 176 .. 207: ReadMapTile := TILE_KILLING_PLATFORM; + 208 .. 255: ReadMapTile := TILE_ACTOR; + else ReadMapTile := TILE_BACKGROUND; + end; +end; + +function GetActor(x, y: byte): byte; +var + room_x, room_y : byte; +begin + room_x := (map.room mod 12) * ROOM_WIDTH_IN_TILES; + room_y := (map.room div 12) * ROOM_HEIGHT_IN_TILES; + GetActor := map.actor[(room_x + x) + (room_y + y) * map.w]; +end; + +Procedure SetActor(x, y, valor: byte); +var + room_x, room_y : byte; +begin + room_x := (map.room mod 12) * ROOM_WIDTH_IN_TILES; + room_y := (map.room div 12) * ROOM_HEIGHT_IN_TILES; + map.actor[(room_x + x) + (room_y + y) * map.w] := valor; +end; + +procedure SetMapGFX(zone: byte); +begin + case zone of + ZONE_SURFACE: + begin + map.sprite_tile := OpenPicture(FILE_TILES_SURFACE); + map.background := OpenPicture(FILE_BKG_SURFACE); + end; + + ZONE_VOLCANO: + begin + map.sprite_tile := OpenPicture(FILE_TILES_VOLCANO); + map.background := OpenPicture(FILE_BKG_SURFACE); + end; + end; +end; + +procedure SetMapMusic(zone: byte); +begin + case zone of + ZONE_SURFACE: + game.music := Mix_LoadMUS(FILE_MUSIC_SURFACE); + + ZONE_VOLCANO: + game.music := Mix_LoadMUS(FILE_MUSIC_VOLCANO); + end; +end; + +function CheckZoneChange(room: integer): boolean; +var + zone: byte; +begin + case room of + 0 .. 23: + zone := ZONE_SURFACE; + 24 .. 255: + zone := ZONE_VOLCANO; + end; + + if (zone = game.zone) then + CheckZoneChange := FALSE + else + CheckZoneChange := TRUE; +end; + +procedure SetZone(room: integer); +begin + case room of + 0 .. 23: + game.zone := ZONE_SURFACE; + + 24 .. 255: + game.zone := ZONE_VOLCANO; + end; + + SetMapGFX(game.zone); + SetMapMusic(game.zone); + Mix_PlayMusic(game.music, -1); +end; + +procedure SetPlayerAnimation(anim: byte); +begin + if (anim <> player.active_animation) then + begin + 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; + end; +end; + +procedure Animate(var a:Tanimation; var s:TSDL_Rect); +begin + // 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) then + a.loops := TRUE + else + a.loops := FALSE; + + a.timer := (a.timer + 1) mod (a.num_frames * a.speed); + a.index := a.timer div a.speed; + s.x := (a.frame[a.index]) * s.w; +end; + +procedure AnimateIntroMenu(var a:Tanimation; var s:TSDL_Rect); +begin + // 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) then + a.loops := TRUE + else + a.loops := FALSE; + + a.timer := (a.timer + 1) mod (a.num_frames * a.speed); + a.index := a.timer div a.speed; + s.x := (a.frame[a.index] mod 4) * s.w; + s.y := (a.frame[a.index] div 4) * s.h; +end; + +procedure CreateActor(var a : Tactor; kind, id : byte; dstx, dsty, dstw, dsth, srcx, srcy, sx, sy, timer, frame : smallint; direction, parent : byte); +begin + 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; +end; + +procedure LoadMap(map:Pmap); +var + f: File; + numread: Word; + size: array[0..1] of byte; +begin + Assign(f, FILE_MAP_VOLCANO); + Reset(f, 1); + BlockRead(f, size, 2, numread); + map^.w := size[0]; + map^.h := size[1]; + SetLength(map^.tile, map^.w * map^.h); + SetLength(map^.actor, map^.w * map^.h); + BlockRead(f, map^.tile[0], map^.w * map^.h, numread); + BlockRead(f, map^.actor[0], map^.w * map^.h, numread); + Close(f); +end; + +procedure LoadRoom(num:integer); +var + i, j, k: integer; +begin + if (CheckZoneChange(num)) then + begin + SetZone(num); + end; + + // 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 i:=0 to MAX_ANIMATED_TILES - 1 do + animated_tile[i].enabled := FALSE; + + // Escanejem la habitació en busca de tiles animats + k := 0; + for i:=0 to (ROOM_WIDTH_IN_TILES - 1) do + for j:=0 to (ROOM_HEIGHT_IN_TILES - 1) do + case GetTile(i, j) of + 48 .. 63, 128 .. 143, 160..175, 192..207: + begin + 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; + inc(k); + end; + end; + + // Esborrem la llista d'actors actius + for i:=0 to MAX_ACTORS - 1 do + actor[i].enabled := FALSE; + + // Escanejem la habitació en busca d'actors per afegirlos a la llista d'actors actius + k := 0; + for i:=0 to (ROOM_WIDTH_IN_TILES - 1) do + for j:=0 to (ROOM_HEIGHT_IN_TILES - 1) do + begin + case GetActor(i, j) of + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + 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); + + else + dec(k); + end; + inc(k); + end; +end; + +procedure IniMenu(); +begin + menu.enabled := TRUE; + menu.section := MENU_SECTION_ANIMATION; + + menu.music := Mix_LoadMUS(FILE_MUSIC_MENU); + menu.sound_logo := Mix_LoadWAV(FILE_SOUND_MENU_LOGO); + menu.sound_start := Mix_LoadWAV(FILE_SOUND_MENU_START); + + menu.sprite := OpenPicture(FILE_MENU); + 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) div 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) div 2; + menu.dst_rect_text2.y := 210; + menu.dst_rect_text2.w := 55; + menu.dst_rect_text2.h := 5; + + // Animació + menu.sprite_animation := OpenPicture(FILE_MENU_ANIMATION); + + 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; +end; + +procedure EndMenu(); +begin + CloseSound(menu.sound_logo); + CloseSound(menu.sound_start); + CloseMusic(menu.music); + ClosePicture(menu.sprite); + ClosePicture(menu.sprite_animation); + menu.enabled:= FALSE; +end; + +procedure IniActors(); +var + i: byte; +begin + for i:=0 to MAX_ACTORS - 1 do + actor[i].enabled := FALSE; + map.sprite_actor := OpenPicture(FILE_ACTORS); +end; + +procedure IniAnimatedTiles(); +var + i: byte; +begin + for i:=0 to MAX_ANIMATED_TILES - 1 do + animated_tile[i].enabled := FALSE; +end; + +procedure IniMap(); +begin + 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(@map); +end; + +procedure EndMap(); +begin + ClosePicture(map.sprite_tile); + ClosePicture(map.sprite_actor); + ClosePicture(map.background); +end; + +procedure IniPlayer(); +var + i: byte; +begin + player.sprite := OpenPicture(FILE_PLAYER); + 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 i:=0 to 5 do player.key[i] := FALSE; + player.sound_jump := Mix_LoadWAV(FILE_SOUND_JUMP); + player.sound_death := Mix_LoadWAV(FILE_SOUND_DEATH); + player.sound_coin := Mix_LoadWAV(FILE_SOUND_COIN); + + 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]; +end; + +procedure EndPlayer(); +begin + ClosePicture(player.sprite); + CloseSound(player.sound_jump); + CloseSound(player.sound_death); + CloseSound(player.sound_coin); +end; + +procedure IniHud(); +begin + hud.sprite := OpenPicture(FILE_HUD); + 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; +end; + +procedure EndHud(); +begin + ClosePicture(hud.sprite); +end; + +procedure IniGame(zone: byte); +begin + game.sound_drop_enemy := Mix_LoadWAV(FILE_SOUND_DROP_ENEMY); + game.sound_drop_splat := Mix_LoadWAV(FILE_SOUND_DROP_SPLAT); + game.enabled := TRUE; + game.zone := zone; + + // Inicialitzar jugador + IniPlayer(); + + // Inicialitza hud + IniHud(); + + // Establir el color d'esborrat + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + + // Inicialitza actors + IniActors(); + + // Inicialitza tiles animats + IniAnimatedTiles(); + + // Inicialitza mapa + IniMap(); + SetMapGFX(zone); + SetMapMusic(zone); +end; + +procedure EndGame(); +begin + EndPlayer(); + EndHud(); + EndMap(); + CloseSound(game.sound_drop_enemy); + CloseSound(game.sound_drop_splat); + CloseMusic(game.music); + game.enabled := FALSE; +end; + +procedure KillPlayer(); +begin + player.enabled := FALSE; + player.cooldown := COOLDOWN_TIME; + + // Establir animació de mort + if (player.direction = LEFT) then + SetPlayerAnimation(PLAYER_ANIMATION_DYING_LEFT) + else + SetPlayerAnimation(PLAYER_ANIMATION_DYING_RIGHT); + + + Mix_PlayChannel(-1, player.sound_death, 0); +end; + +function OnFloor():boolean; +//[27/08/2016] [DOC] [BEGIN] +var + tile_on_right_foot, tile_on_left_foot, + tile_under_right_foot, tile_under_left_foot : byte; + + i_am_above_platform, i_am_above_travesable, + i_am_on_background : boolean; +begin + tile_under_left_foot := ReadMapTile((player.dst_rect.x + 3 ) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div MAP_TILE_HEIGHT); + tile_under_right_foot := ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div MAP_TILE_HEIGHT); + + i_am_above_platform := (tile_under_left_foot = TILE_PLATFORM) or (tile_under_right_foot = TILE_PLATFORM); + i_am_above_travesable := (tile_under_left_foot = TILE_TRAVESABLE_PLATFORM) or (tile_under_right_foot = TILE_TRAVESABLE_PLATFORM); + + tile_on_left_foot := ReadMapTile((player.dst_rect.x + 3 ) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h-1) div MAP_TILE_HEIGHT); + tile_on_right_foot := ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h-1) div MAP_TILE_HEIGHT); + + i_am_on_background := (tile_on_left_foot = TILE_BACKGROUND) and (tile_on_right_foot = TILE_BACKGROUND); + + if ( ( i_am_above_platform or i_am_above_travesable ) and i_am_on_background ) then + OnFloor := TRUE + else + OnFloor := FALSE; +//[27/08/2016] [DOC] [END] + + {if (ReadMapTile((player.dst_rect.x + 3 ) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div MAP_TILE_HEIGHT) = TILE_PLATFORM) + or (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div MAP_TILE_HEIGHT) = TILE_PLATFORM) + or (ReadMapTile((player.dst_rect.x + 3 ) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div MAP_TILE_HEIGHT) = TILE_TRAVESABLE_PLATFORM) + or (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div MAP_TILE_HEIGHT) = TILE_TRAVESABLE_PLATFORM) then + OnFloor := TRUE + else + OnFloor := FALSE;} +end; + +procedure MoveActors(); +var + i, k: byte; +begin + for i:=0 to MAX_ACTORS - 1 do + if actor[i].enabled then + case actor[i].kind of + KIND_FLYING_ENEMY: + begin + case actor[i].direction of + RIGHT: + begin + // 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) then + 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) div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) + or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then + begin + actor[i].dst_rect.x := actor[i].dst_rect.x - ((actor[i].dst_rect.x + actor[i].dst_rect.w) mod MAP_TILE_WIDTH); + actor[i].direction := LEFT; + end; + end; + + LEFT: + begin + // 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 then + 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 div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) + or (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then + begin + actor[i].dst_rect.x := actor[i].dst_rect.x + (MAP_TILE_WIDTH - (actor[i].dst_rect.x mod MAP_TILE_WIDTH)); + actor[i].direction := RIGHT; + end; + end; + + DOWN: + begin + // 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) then + 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 div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) + or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then + begin + actor[i].dst_rect.y := actor[i].dst_rect.y - ((actor[i].dst_rect.y + actor[i].dst_rect.h) mod MAP_TILE_WIDTH); + actor[i].direction := UP; + end; + end; + + UP: + begin + // 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) then + 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 div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) + or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then + begin + actor[i].dst_rect.y := actor[i].dst_rect.y + (MAP_TILE_WIDTH - (actor[i].dst_rect.y mod MAP_TILE_WIDTH)); + actor[i].direction := DOWN; + end; + end; + end; + + actor[i].frame := (actor[i].frame + 1) mod 24; + if (actor[i].direction = UP) then + actor[i].src_rect.y := 4 * 16; + if (actor[i].direction = DOWN) then + actor[i].src_rect.y := 5 * 16; + if (actor[i].direction = LEFT) then + actor[i].src_rect.y := 7 * 16; + if (actor[i].direction = RIGHT) then + actor[i].src_rect.y := 6 * 16; + actor[i].src_rect.x := (actor[i].frame div 4) * actor[i].dst_rect.w; + end; + + KIND_WALKING_ENEMY: + begin + case actor[i].direction of + RIGHT: + begin + // 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) then + 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) div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) + or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then + begin + actor[i].dst_rect.x := actor[i].dst_rect.x - ((actor[i].dst_rect.x + actor[i].dst_rect.w) mod MAP_TILE_WIDTH); + actor[i].direction := LEFT; + end; + + // 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) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h) div MAP_TILE_HEIGHT) <> TILE_PLATFORM) then + actor[i].direction := LEFT; + end; + + LEFT: + begin + // 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 then + 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 div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) + or (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then + begin + actor[i].dst_rect.x := actor[i].dst_rect.x + (MAP_TILE_WIDTH - (actor[i].dst_rect.x mod MAP_TILE_WIDTH)); + actor[i].direction := RIGHT; + end; + + // Arriba a la vora, correcció a l'ultim pixel bo i canvi de sentit + if (ReadMapTile((actor[i].dst_rect.x + 3) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h) div MAP_TILE_HEIGHT) <> TILE_PLATFORM) then + actor[i].direction := RIGHT; + end; + end; + + // Animacio + actor[i].frame := (actor[i].frame + 1) mod 48; + if (actor[i].direction = LEFT) then + actor[i].src_rect.y := 1 * 16 + else + actor[i].src_rect.y := 0 * 16; + actor[i].src_rect.x := (actor[i].frame div 8) * actor[i].dst_rect.w; + end; + + KIND_SPEED_ENEMY: + begin + case actor[i].direction of + RIGHT: + begin + // 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) + and (actor[i].dst_rect.y + 8 < player.dst_rect.y + player.dst_rect.h - 1) + and (player.can_jump) then + 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) then + 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) div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) + or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then + begin + actor[i].dst_rect.x := actor[i].dst_rect.x - ((actor[i].dst_rect.x + actor[i].dst_rect.w) mod MAP_TILE_WIDTH); + actor[i].direction := LEFT; + end; + + // 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) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h) div MAP_TILE_HEIGHT) <> TILE_PLATFORM) then + actor[i].direction := LEFT; + end; + + LEFT: + begin + // 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) + and (actor[i].dst_rect.y + 8 < player.dst_rect.y + player.dst_rect.h - 1) + and (player.can_jump) then + 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 then + 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 div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) + or (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then + begin + actor[i].dst_rect.x := actor[i].dst_rect.x + (MAP_TILE_WIDTH - (actor[i].dst_rect.x mod MAP_TILE_WIDTH)); + actor[i].direction := RIGHT; + end; + + // Arriba a la vora, correcció a l'ultim pixel bo i canvi de sentit + if (ReadMapTile((actor[i].dst_rect.x + 3) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h) div MAP_TILE_HEIGHT) <> TILE_PLATFORM) then + actor[i].direction := RIGHT; + end; + end; + + // Animacio + actor[i].frame := (actor[i].frame + 1) mod 48; + if (actor[i].direction = LEFT) then + actor[i].src_rect.y := 2 * 16 + else + actor[i].src_rect.y := 3 * 16; + actor[i].src_rect.x := (actor[i].frame div 8) * actor[i].dst_rect.w; + end; + + KIND_MOBILE_PLATFORM: + begin + case actor[i].direction of + RIGHT: + begin + // 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) then + 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) div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) + or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then + begin + actor[i].dst_rect.x := actor[i].dst_rect.x - ((actor[i].dst_rect.x + actor[i].dst_rect.w) mod MAP_TILE_WIDTH); + actor[i].direction := LEFT; + end; + end; + + LEFT: + begin + // 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) then + actor[i].direction := RIGHT; + + // Colisió amb el mapa, correcció al ultim pixel bo i canvi de sentit + if (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) + or (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then + begin + actor[i].dst_rect.x := actor[i].dst_rect.x + (MAP_TILE_WIDTH - (actor[i].dst_rect.x mod MAP_TILE_WIDTH)); + actor[i].direction := RIGHT; + end; + end; + + DOWN: + begin + // 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) then + actor[i].direction := UP; + + // Colisió amb el mapa, correcció al ultim pixel bo i canvi de sentit + if (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) + or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then + begin + actor[i].dst_rect.y := actor[i].dst_rect.y - ((actor[i].dst_rect.y + actor[i].dst_rect.h) mod MAP_TILE_WIDTH); + actor[i].direction := UP; + end; + end; + + UP: + begin + // 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) then + actor[i].direction := DOWN; + + // Colisió amb el mapa, correcció al ultim pixel bo i canvi de sentit + if (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) + or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, actor[i].dst_rect.y div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then + begin + actor[i].dst_rect.y := actor[i].dst_rect.y + (MAP_TILE_WIDTH - (actor[i].dst_rect.y mod MAP_TILE_WIDTH)); + actor[i].direction := DOWN; + end; + end; + end; + end; + + KIND_DROP_GENERATOR: + begin + if (actor[i].timer > 0) then + dec(actor[i].timer) + else + // Si el contador arriba a 0, creem un actor KIND_DROP_ENEMY + begin + actor[i].timer := 32000; + k := 0; + while (actor[k].enabled) do inc(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); + end; + + // Animacio + actor[i].frame := (actor[i].frame + 1) mod 24; + if (actor[i].timer > (DROP_TIMER - 25)) then + // 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 div 4) * actor[i].dst_rect.w; + end; + + KIND_DROP_ENEMY: + begin + // 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) then + begin + actor[i].enabled := FALSE; + actor[actor[i].parent].timer := DROP_TIMER; + end; + + // Colisió amb el mapa, correcció al ultim pixel bo, transforma en KIND_DROP_SPLAT + if (ReadMapTile(actor[i].dst_rect.x div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) + or (ReadMapTile((actor[i].dst_rect.x + actor[i].dst_rect.w - 1) div MAP_TILE_WIDTH, (actor[i].dst_rect.y + actor[i].dst_rect.h - 1) div MAP_TILE_HEIGHT) <> TILE_BACKGROUND) then + begin + actor[i].dst_rect.y := actor[i].dst_rect.y - ((actor[i].dst_rect.y + actor[i].dst_rect.h) mod 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); + end; + + // Animacio + actor[i].frame := (actor[i].frame + 1) mod 24; + actor[i].src_rect.x := (actor[i].frame div 4) * actor[i].dst_rect.w; + end; + + KIND_DROP_SPLAT: + begin + //if (actor[i].timer > 0) then + if (actor[i].frame < 23) then + // Si encara te temps, pintem la animació + begin + dec(actor[i].timer); + actor[i].frame := (actor[i].frame + 1) mod 24; + actor[i].src_rect.x := ((actor[i].frame div 4) + 0) * actor[i].dst_rect.w; + end + else + begin + actor[i].enabled := FALSE; + actor[actor[i].parent].timer := DROP_TIMER; + end; + end; + + KIND_COIN: + begin + actor[i].frame := (actor[i].frame + 1) mod 32; + actor[i].src_rect.x := (actor[i].frame div 4) * actor[i].dst_rect.w; + end; + + KIND_HEART: + begin + actor[i].frame := (actor[i].frame + 1) mod 32; + actor[i].src_rect.x := (actor[i].frame div 4) * actor[i].dst_rect.w; + end; + + KIND_KEY: + begin + //actor[i].frame := (actor[i].frame + 1) mod 32; + //actor[i].src_rect.x := (actor[i].frame div 32) * actor[i].dst_rect.w; + end; + + KIND_LOCK: + begin + //actor[i].frame := (actor[i].frame + 1) mod 32; + //actor[i].src_rect.x := (actor[i].frame div 32) * actor[i].dst_rect.w; + end; + end; +end; + +procedure SetPlayerDirection(direction: integer); +begin + if (direction <> player.direction) then + begin + player.direction := direction; + player.speed_x := 0; + end; +end; + +procedure MovePlayer(direction: integer); +begin + case direction of + UP: + begin + // Si pot saltar, aleshores + if (OnFloor and player.can_jump) then + begin + // 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); + end; + + // Nou frame d'animació + if (player.direction = LEFT) then + SetPlayerAnimation(PLAYER_ANIMATION_JUMPING_LEFT) + else + if (player.direction = RIGHT) then + SetPlayerAnimation(PLAYER_ANIMATION_JUMPING_RIGHT); + end; + + RIGHT: + begin + // 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 div RATIO_SPEED) + 1); + + // Selecció de l'animació + if (player.speed_y = 0) then + // Animació de caminar + SetPlayerAnimation(PLAYER_ANIMATION_WALKING_RIGHT) + else + // Animació de saltar + SetPlayerAnimation(PLAYER_ANIMATION_JUMPING_RIGHT); + end; + + LEFT : + begin + // 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 div RATIO_SPEED) + 1); + + // Selecció de l'animació + if (player.speed_y = 0) then + // Animació de caminar + SetPlayerAnimation(PLAYER_ANIMATION_WALKING_LEFT) + else + // Animació de saltar + SetPlayerAnimation(PLAYER_ANIMATION_JUMPING_LEFT); + end; + end; + + // Calcul del frame d'animació + Animate(player.animation[player.active_animation], player.src_rect); +end; + +procedure ApplyGravity(); +begin + // Si toca piso aleshores + if (OnFloor) then + begin + // Totes les forces verticals paren + player.speed_y := 0; + // Podem saltar + player.can_jump := TRUE; + end + else + begin + // 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; + end; +end; + +procedure DrawSprite (sprite:PSDL_Texture; src_rect, dst_rect: TSDL_Rect); +begin + SDL_RenderCopy(renderer, sprite, @src_rect, @dst_rect); +end; + +procedure DrawMap(map:Tmap); +var + i, j: byte; + src_rect1: TSDL_Rect; + dst_rect1: TSDL_Rect; +begin + 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 i:=0 to (ROOM_WIDTH_IN_TILES - 1) do + for j:=0 to (ROOM_HEIGHT_IN_TILES - 1) do + begin + src_rect1.x := (GetTile(i, j) mod 16) * MAP_TILE_WIDTH; + src_rect1.y := (GetTile(i, j) div 16) * MAP_TILE_HEIGHT; + dst_rect1.x := i * MAP_TILE_WIDTH; + dst_rect1.y := j * MAP_TILE_HEIGHT; + SDL_RenderCopy(renderer, map.sprite_tile, @src_rect1, @dst_rect1); + end; + + i := 0; + while animated_tile[i].enabled do + begin + src_rect1.x := ((animated_tile[i].index mod 16) * MAP_TILE_WIDTH) + ((animated_tile[i].frame div 8) * MAP_TILE_WIDTH); + src_rect1.y := (animated_tile[i].index div 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) mod 16; + SDL_RenderCopy(renderer, map.sprite_tile, @src_rect1, @dst_rect1); + inc(i); + end; +end; + +procedure DrawHud(); +begin + // 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 mod 100) div 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 mod 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 div 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 mod 100) div 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 mod 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 then + begin + // Pinta el valor x,y del jugador + hud.num_src_rect.x := (player.dst_rect.x div 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 mod 100) div 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 mod 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 div 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 mod 100) div 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 mod 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) then + 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) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div 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) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h) div 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 div 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 mod 100) div 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 mod 10) * hud.num_src_rect.w; + hud.num_dst_rect.x := 57; + DrawSprite(hud.sprite, hud.num_src_rect, hud.num_dst_rect); + end; +end; + +procedure CheckPlayerCollisionWithMap(); +var + tile_on_left_foot, tile_on_right_foot : byte; // [27/05/2016] [DOC] + i_am_on_platform, i_am_on_travesable : boolean; // [27/05/2016] [DOC] +begin + // Si eix per baix, recalcula posició i canvi de pantalla + if (player.dst_rect.y > GAME_WINDOW_HEIGHT) then + begin + // Coloquem al jugador dalt de tot + player.dst_rect.y := 1; + + // Canvi de pantalla + LoadRoom(map.room + 12); + end; + + // Si eix per dalt, recalcula posició i canvi de pantalla + if ((player.dst_rect.y + player.dst_rect.h - 1) < 0) then + begin + // Recoloca el personat + player.dst_rect.y := GAME_WINDOW_HEIGHT - player.dst_rect.h; + + // Canvi de pantalla + LoadRoom(map.room - 12); + end; + + // Si eix per la vora, recalcula posició i canvi de pantalla + if (player.dst_rect.x > GAME_WINDOW_WIDTH) then + begin + // Coloquem al jugador en la entrada de la nova pantalla + player.dst_rect.x := 0; + + // Canvi de pantalla + LoadRoom(map.room + 1); + end; + + // Si eix per la vora, recalcula posició i canvi de pantalla + if ((player.dst_rect.x + player.dst_rect.w - 1) < 0) then + begin + // El posem al borde dret + player.dst_rect.x := GAME_WINDOW_WIDTH - player.dst_rect.w; + + // Canvi de pantalla + LoadRoom(map.room - 1); + end; + + // Mirem si colisionem cap avall i corregim + //[27/05/2016] [DOC] [BEGIN] + tile_on_left_foot := ReadMapTile((player.dst_rect.x + 3) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT); + tile_on_right_foot := ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT); + + i_am_on_platform := (tile_on_left_foot = TILE_PLATFORM) or (tile_on_right_foot = TILE_PLATFORM); + i_am_on_travesable := (tile_on_left_foot = TILE_TRAVESABLE_PLATFORM) or (tile_on_right_foot = TILE_TRAVESABLE_PLATFORM); + + if ( (player.was_on_background) and (player.speed_y > 0) and ( i_am_on_platform or i_am_on_travesable ) ) then + begin + // Corregim la posicio + player.dst_rect.y := player.dst_rect.y - ((player.dst_rect.y + player.dst_rect.h - 1) mod MAP_TILE_HEIGHT) - 1; + + // Ja podem saltar + player.can_jump := TRUE; + end; + + player.was_on_background := (tile_on_left_foot = TILE_BACKGROUND) and (tile_on_right_foot = TILE_BACKGROUND); + //[27/05/2016] [DOC] [END] + + {if player.speed_y > 0 then + if (ReadMapTile((player.dst_rect.x + 3) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT) = TILE_TRAVESABLE_PLATFORM) + or (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT) = TILE_TRAVESABLE_PLATFORM) then + begin + // Corregim la posicio + player.dst_rect.y := player.dst_rect.y - ((player.dst_rect.y + player.dst_rect.h - 1) mod MAP_TILE_HEIGHT) - 1; + + // Ja podem saltar + player.can_jump := TRUE; + end; + + if (ReadMapTile((player.dst_rect.x + 3) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT) = TILE_PLATFORM) + or (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT) = TILE_PLATFORM) then + begin + // Corregim la posicio + player.dst_rect.y := player.dst_rect.y - ((player.dst_rect.y + player.dst_rect.h - 1) mod MAP_TILE_HEIGHT) - 1; + + // Ja podem saltar + player.can_jump := TRUE; + end;} + + // Mirem si colisionem cap amunt i corregim + if (ReadMapTile((player.dst_rect.x + 3) div MAP_TILE_WIDTH, player.dst_rect.y div MAP_TILE_HEIGHT) = TILE_PLATFORM) + or (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 4) div MAP_TILE_WIDTH, player.dst_rect.y div MAP_TILE_HEIGHT) = TILE_PLATFORM) then + // Corregim la posicio + player.dst_rect.y := player.dst_rect.y + (MAP_TILE_HEIGHT - (player.dst_rect.y mod 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 div MAP_TILE_WIDTH, player.dst_rect.y div MAP_TILE_HEIGHT) = TILE_PLATFORM) + or (ReadMapTile(player.dst_rect.x div MAP_TILE_WIDTH, (player.dst_rect.y + (player.dst_rect.h div 2)) div MAP_TILE_HEIGHT) = TILE_PLATFORM) + or (ReadMapTile(player.dst_rect.x div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT) = TILE_PLATFORM) then + player.dst_rect.x := player.dst_rect.x + (MAP_TILE_WIDTH - (player.dst_rect.x mod MAP_TILE_WIDTH)); + + if (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 1) div MAP_TILE_WIDTH, player.dst_rect.y div MAP_TILE_HEIGHT) = TILE_PLATFORM) + or (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 1) div MAP_TILE_WIDTH, (player.dst_rect.y + (player.dst_rect.h div 2)) div MAP_TILE_HEIGHT) = TILE_PLATFORM) + or (ReadMapTile((player.dst_rect.x + player.dst_rect.w - 1) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 1) div MAP_TILE_HEIGHT) = TILE_PLATFORM) then + player.dst_rect.x := player.dst_rect.x - ((player.dst_rect.x + player.dst_rect.w) mod MAP_TILE_WIDTH); + + // Comprovar si toca alguna part del mapa de les que maten + if (ReadMapTile((player.dst_rect.x + 8) div MAP_TILE_WIDTH, (player.dst_rect.y + player.dst_rect.h - 12) div MAP_TILE_HEIGHT) = TILE_KILLING_PLATFORM) then + if player.enabled then + KillPlayer(); +end; + +{procedure CheckPlayerCollisionWithActors(); +var + i, collision: byte; + //collision_top, collision_bottom, collision_left, collision_right: boolean; +begin + for i:=0 to MAX_ACTORS - 1 do + if actor[i].enabled then + begin + collision := NO_COLLISION; + if ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then + collision := LEFT_COLLISION; + + if((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then + collision := RIGHT_COLLISION; + + if ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then + collision := LEFT_COLLISION; + + if ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then + collision := RIGHT_COLLISION; + + if (collision <> NO_COLLISION) then + case actor[i].kind of + KIND_FLYING_ENEMY, KIND_WALKING_ENEMY, KIND_DROP_ENEMY, KIND_SPEED_ENEMY: + begin + if (player.enabled) then + KillPlayer(); + end; + + KIND_COIN: + begin + inc(player.coins); + actor[i].enabled := FALSE; + SetActor((actor[i].dst_rect.x div 16), (actor[i].dst_rect.y div 16), 0); + Mix_PlayChannel(-1, player.sound_coin, 0); + end; + + KIND_HEART: + begin + inc(player.lifes); + actor[i].enabled := FALSE; + SetActor((actor[i].dst_rect.x div 16), (actor[i].dst_rect.y div 16), 0); + Mix_PlayChannel(-1, player.sound_coin, 0); + end; + + KIND_KEY: + begin + player.key[0] := TRUE;; + actor[i].enabled := FALSE; + SetActor((actor[i].dst_rect.x div 16), (actor[i].dst_rect.y div 16), 0); + Mix_PlayChannel(-1, player.sound_coin, 0); + end; + + KIND_LOCK: + begin + // Si tenim clau + if (player.key[0]) then + begin + actor[i].enabled := FALSE; + SetActor((actor[i].dst_rect.x div MAP_TILE_WIDTH), (actor[i].dst_rect.y div MAP_TILE_HEIGHT), 0); + end + else + begin + if collision = LEFT_COLLISION then + begin + player.dst_rect.x := player.dst_rect.x + (MAP_TILE_WIDTH - (player.dst_rect.x mod MAP_TILE_WIDTH)); + end + else + begin + player.dst_rect.x := player.dst_rect.x - ((player.dst_rect.x + player.dst_rect.w) mod MAP_TILE_WIDTH); + end; + end; + end; + end; + end; +end;} + +procedure CheckPlayerCollisionWithActors(); +var + i: byte; +begin + for i:=0 to MAX_ACTORS - 1 do + if actor[i].enabled then + case actor[i].kind of + KIND_FLYING_ENEMY, KIND_WALKING_ENEMY, KIND_DROP_ENEMY, KIND_SPEED_ENEMY: + begin + if ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) + or + ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) + or + ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) + or + ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then + if (player.enabled) then + KillPlayer(); + end; + + KIND_COIN: + begin + if ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) + or + ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) + or + ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) + or + ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then + begin + inc(player.coins); + actor[i].enabled := FALSE; + SetActor((actor[i].dst_rect.x div 16), (actor[i].dst_rect.y div 16), 0); + Mix_PlayChannel(-1, player.sound_coin, 0); + end; + end; + + KIND_HEART: + begin + if ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) + or + ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) + or + ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) + or + ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then + begin + inc(player.lifes); + actor[i].enabled := FALSE; + SetActor((actor[i].dst_rect.x div 16), (actor[i].dst_rect.y div 16), 0); + Mix_PlayChannel(-1, player.sound_coin, 0); + end; + end; + + KIND_KEY: + begin + if ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) + or + ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h - ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) + or + ((actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w - ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) + or + ((actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION > player.dst_rect.x) and (actor[i].dst_rect.x + ENEMY_HITBOX_REDUCTION < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION > player.dst_rect.y) and (actor[i].dst_rect.y + ENEMY_HITBOX_REDUCTION < player.dst_rect.y + player.dst_rect.h)) then + begin + player.key[actor[i].id] := TRUE;; + actor[i].enabled := FALSE; + SetActor((actor[i].dst_rect.x div 16), (actor[i].dst_rect.y div 16), 0); + Mix_PlayChannel(-1, player.sound_coin, 0); + end; + end; + + KIND_LOCK: + // Les colisions amb aquest actor no tenen en compte el ENEMY_HITBOX_REDUCTION + begin + // 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) and (actor[i].dst_rect.x + actor[i].dst_rect.w < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + actor[i].dst_rect.h > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h < player.dst_rect.y + player.dst_rect.h)) + or + ((actor[i].dst_rect.x + actor[i].dst_rect.w > player.dst_rect.x) and (actor[i].dst_rect.x + actor[i].dst_rect.w < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y > player.dst_rect.y) and (actor[i].dst_rect.y < player.dst_rect.y + player.dst_rect.h)) then + // Si tenim clau + if (player.key[actor[i].id]) then + begin + actor[i].enabled := FALSE; + SetActor((actor[i].dst_rect.x div MAP_TILE_WIDTH), (actor[i].dst_rect.y div MAP_TILE_HEIGHT), 0); + end + // Si no tenim clau + else + begin + player.dst_rect.x := player.dst_rect.x + (MAP_TILE_WIDTH - (player.dst_rect.x mod MAP_TILE_WIDTH)); + end; + + // El jugador colisiona amb el actor per la dreta del jugador + if ((actor[i].dst_rect.x > player.dst_rect.x) and (actor[i].dst_rect.x < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y + actor[i].dst_rect.h > player.dst_rect.y) and (actor[i].dst_rect.y + actor[i].dst_rect.h < player.dst_rect.y + player.dst_rect.h)) + or + ((actor[i].dst_rect.x > player.dst_rect.x) and (actor[i].dst_rect.x < player.dst_rect.x + player.dst_rect.w) and + (actor[i].dst_rect.y > player.dst_rect.y) and (actor[i].dst_rect.y < player.dst_rect.y + player.dst_rect.h)) then + // Si tenim clau + if (player.key[actor[i].id]) then + begin + actor[i].enabled := FALSE; + SetActor((actor[i].dst_rect.x div MAP_TILE_WIDTH), (actor[i].dst_rect.y div MAP_TILE_HEIGHT), 0); + end + // Si no tenim clau + else + begin + player.dst_rect.x := player.dst_rect.x - ((player.dst_rect.x + player.dst_rect.w) mod MAP_TILE_WIDTH); + end; + end; + end; +end; + +procedure SetProgSection(section:byte); +begin + case section of + SECTION_MENU: + begin + prog.section := SECTION_MENU; + IniMenu(); + EndGame(); + end; + + SECTION_GAME: + begin + prog.section := SECTION_GAME; + IniGame(ZONE_VOLCANO); + EndMenu; + end; + + SECTION_QUIT: + begin + prog.section := SECTION_QUIT; + EndGame; + EndMenu; + end; + end; +end; + +procedure IniProgram(); +begin + prog.music_enabled := TRUE; + prog.filter := TRUE; + SetProgSection(SECTION_MENU); + prog.debug := FALSE; + + if (prog.music_enabled) then + Mix_VolumeMusic(100) + else + Mix_VolumeMusic(0); + + prog.sprite := OpenPicture(FILE_FILTER); + + 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; +end; + +procedure EndProgram(); +begin + ClosePicture(prog.sprite); + EndGame(); + EndMenu(); +end; + +begin + // Inicialitzar SDL en general i el video en particular + fullscreen := false; + SDL_Init(SDL_INIT_EVERYTHING); + window := SDL_CreateWindow(WINDOW_TITLE + BUILD, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN); + renderer := SDL_CreateRenderer(window, -1, 0); + SDL_RenderSetLogicalSize(renderer, 320, 240); + + // Inicialitzar SDL_Image (càrrega de PNGs) + IMG_Init(IMG_INIT_PNG); + + // Inicialitzar audio + Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024); + Mix_AllocateChannels(8); + + // Inicialitzar el programa + IniProgram(); + + // Establir el color d'esborrat + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); + + // Inicialitza variables generals + quit := false; + delta_time := SDL_GetTicks(); + + // Bucle de programa + while not quit do + begin + case prog.section of + SECTION_GAME: + begin + // Inicialitza habitació + LoadRoom(STARTING_ROOM); + + // Conecta la musica + Mix_PlayMusic(game.music, -1); + + // Bucle de joc + while game.enabled do + begin + while SDL_PollEvent(@e) > 0 do + begin + // Si arriva el event de tancar la aplicació, eixim del bucle + if (e.type_ = SDL_QUITEV) then + begin + quit := true; + SetProgSection(SECTION_MENU); + break; + end + else + if ((e.type_ = SDL_KEYDOWN) and (e.key._repeat = 0)) then + case e.key.keysym.scancode of + SDL_SCANCODE_ESCAPE: + begin + SetProgSection(SECTION_MENU); + end; + + SDL_SCANCODE_F: + begin + if ( fullscreen ) then + begin + SDL_SetWindowFullscreen(window, 0); + SDL_ShowCursor(1); + fullscreen := false; + end + else + begin + SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); + SDL_ShowCursor(0); + fullscreen := true; + end; + end; + + SDL_SCANCODE_W: + begin + LoadRoom(map.room - 12); + end; + + SDL_SCANCODE_A: + begin + LoadRoom(map.room - 1); + end; + + SDL_SCANCODE_S: + begin + LoadRoom(map.room + 12); + end; + + SDL_SCANCODE_D: + begin + LoadRoom(map.room + 1); + end; + + SDL_SCANCODE_G: + begin + player.lifes := 255; + end; + + SDL_SCANCODE_M: + begin + prog.music_enabled := not(prog.music_enabled); + if (prog.music_enabled) then + Mix_VolumeMusic(100) + else + Mix_VolumeMusic(0); + end; + + SDL_SCANCODE_T: + begin + IniPlayer(); + LoadRoom(TEST_ROOM); + end; + + SDL_SCANCODE_F1: + begin + prog.debug := not(prog.debug); + end; + + SDL_SCANCODE_F2: + begin + prog.filter := not(prog.filter); + end; + end; + end; + + if ((SDL_GetTicks() - delta_time) > GAME_SPEED) then + begin + // Agafar el array de tecles + keys := SDL_GetKeyboardState(nil); + + // Mirem si esta apretant el botó de saltar. Per tal d'evitar repeticions en aquest boto + if (keys[SDL_SCANCODE_UP] = 0) then + 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 not(player.enabled) then + if (player.cooldown > 0) then + begin + dec(player.cooldown); + Animate(player.animation[player.active_animation], player.src_rect); + end + else + // Ha acabat el temps d'estar mort. Revivim al jugador + begin + player.enabled := TRUE; + + // Coloquem al jugador en el sentit que tenia quan va entrar a la habitació + if (player.respawn_direction = LEFT) then + begin + SetPlayerAnimation(PLAYER_ANIMATION_STANDING_LEFT); + player.direction := LEFT; + end; + if (player.respawn_direction = RIGHT) then + begin + SetPlayerAnimation(PLAYER_ANIMATION_STANDING_RIGHT); + player.direction := RIGHT; + end; + + // 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) then + // Descontem una vida + dec(player.lifes) + else + // Si no li queden vides, eixim al menu + SetProgSection(SECTION_MENU); + end; + + // Comprovem les tecles que ens interesen i actuem en consequència + if (keys[SDL_SCANCODE_RIGHT] = 1) and (player.enabled) then + MovePlayer(RIGHT); + if (keys[SDL_SCANCODE_LEFT] = 1) and (keys[SDL_SCANCODE_RIGHT] = 0) and (player.enabled) then + MovePlayer(LEFT); + if (keys[SDL_SCANCODE_UP] = 1) and (player.enabled) and not(player.jump_pressed_before) then + 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) and (keys[SDL_SCANCODE_LEFT] = 0) and (player.enabled)) then + begin + player.speed_x := 0; + + // Estem quets + player.standing := TRUE; + + // Posem la animació d'estar quet si no estem saltant + //if (player.speed_y = 0) then + if (player.can_jump) then + begin + if (player.direction = LEFT) then + SetPlayerAnimation(PLAYER_ANIMATION_STANDING_LEFT) + else + if (player.direction = RIGHT) then + SetPlayerAnimation(PLAYER_ANIMATION_STANDING_RIGHT); + Animate(player.animation[player.active_animation], player.src_rect); + end; + end; + + // Moure els actors + MoveActors(); + + // Apliquem la gravetat + if (player.enabled) then ApplyGravity(); + + // Comprovar colisions amb els actors + if (player.enabled) then 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(map); + + // Pintem el jugador + DrawSprite(player.sprite, player.src_rect, player.dst_rect); + + // Pintem els actors + for i:=0 to MAX_ACTORS - 1 do + if (actor[i].enabled) then + DrawSprite(map.sprite_actor, actor[i].src_rect, actor[i].dst_rect); + + // Pintem el marcador + DrawHud(); + + // Posem el filtro de pantalla + if prog.filter then + begin + SDL_RenderSetLogicalSize(renderer, 640, 480); + DrawSprite(prog.sprite, prog.src_rect, prog.dst_rect); + end; + + // Mostrem la pantalla + SDL_RenderPresent(renderer); + + delta_time := SDL_GetTicks(); + end; + end; + end; + + SECTION_MENU: + begin + // Establir el color d'esborrat + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); + + // Apaga la musica + Mix_HaltMusic(); + + while menu.enabled do + begin + // Bucle del menu + while SDL_PollEvent(@e) > 0 do + begin + // Si arriva el event de tancar la aplicació, eixim del bucle + if (e.type_ = SDL_QUITEV) then + begin + quit := true; + menu.enabled := FALSE; + break; + end + else + if ((e.type_ = SDL_KEYDOWN) and (e.key._repeat = 0)) then + case e.key.keysym.scancode of + SDL_SCANCODE_ESCAPE: + begin + quit := true; + SetProgSection(SECTION_QUIT); + break; + end; + + // (Des)Activa el mode de pantalla completa + SDL_SCANCODE_F: + begin + if ( fullscreen ) then + begin + SDL_SetWindowFullscreen(window, 0); + SDL_ShowCursor(1); + fullscreen := false; + end + else + begin + SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); + SDL_ShowCursor(0); + fullscreen := true; + end; + end; + + // (Des)Activa la musica + SDL_SCANCODE_M: + begin + prog.music_enabled := not(prog.music_enabled); + if (prog.music_enabled) then + Mix_VolumeMusic(100) + else + Mix_VolumeMusic(0); + end; + + // (Des)Activa les scanlines + SDL_SCANCODE_F2: + begin + prog.filter := not(prog.filter); + end; + + // Inicia el joc + SDL_SCANCODE_RETURN: + begin + if (menu.timer > 99) then + begin + menu.timer := 99; + Mix_HaltMusic(); + Mix_HaltChannel(-1); + Mix_PlayChannel(-1, menu.sound_start, 0); + menu.frame := 0; + end; + end; + end; + end; + + if ((SDL_GetTicks() - delta_time) > GAME_SPEED) then + begin + case menu.section of + {MENU_SECTION_MAIN: + begin + if menu.timer > 100 then + // Menu normal + begin + menu.frame := (menu.frame + 1) mod 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 div 4) then + Mix_PlayChannel(-1, menu.sound_logo, 0); + if menu.frame = (300 div 4) then + // Conecta la musica + Mix_PlayMusic(menu.music, -1); + + if menu.frame > (300 div 4) then + begin + // Pintem el text: PRESS RETURN TO START + if ((menu.frame mod 64) < 32) then + 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); + end; + end + else + // Menu havent apretat START/RETURN + begin + dec(menu.timer); + menu.frame := (menu.frame + 1) mod 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 mod 8) < 4) then + 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 then + begin + //prog.section := SECTION_GAME; + //menu.enabled := FALSE; + //game.enabled := TRUE; + //menu.section := MENU_SECTION_ANIMATION; + //menu.timer := 100 + end; + end; + + // Posem el filtro de pantalla + if prog.filter then + begin + SDL_RenderSetLogicalSize(renderer, 640, 480); + DrawSprite(prog.sprite, prog.src_rect, prog.dst_rect); + end; + + // Mostrem la pantalla + SDL_RenderPresent(renderer); + + delta_time := SDL_GetTicks(); + end;} + + MENU_SECTION_ANIMATION: + begin + // No hem pulsat el botó d'start + if menu.timer > 100 then + // Animació inicial + if not(menu.animation[0].loops) then + begin + // 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 then + begin + SDL_RenderSetLogicalSize(renderer, 640, 480); + DrawSprite(prog.sprite, prog.src_rect, prog.dst_rect); + end; + + // Mostrem la pantalla + SDL_RenderPresent(renderer); + + delta_time := SDL_GetTicks(); + end + else + // Animació segona en loop + begin + if Mix_PlayingMusic() = 0 then + 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 mod 64) < 32) then + 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 then + begin + SDL_RenderSetLogicalSize(renderer, 640, 480); + DrawSprite(prog.sprite, prog.src_rect, prog.dst_rect); + end; + + // Mostrem la pantalla + SDL_RenderPresent(renderer); + + delta_time := SDL_GetTicks(); + end + else + // Hem pulsat el botó d'start + begin + 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 mod 8) < 4) then + 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 then + begin + SDL_RenderSetLogicalSize(renderer, 640, 480); + DrawSprite(prog.sprite, prog.src_rect, prog.dst_rect); + end; + + // Mostrem la pantalla + SDL_RenderPresent(renderer); + + delta_time := SDL_GetTicks(); + + dec(menu.timer); + if menu.timer = 0 then + begin + SetProgSection(SECTION_GAME); + menu.timer := 200; + end; + end; + end; + end; + end; + end; + end; + end; + end; + + // 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(); + + // Finalitzar SDL_Image + IMG_Quit(); + + // 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); + + // Destruir la finestra + SDL_DestroyWindow(window); + + // Finalitzar SDL + SDL_Quit(); +end.