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.