Files
volcano_2016/source/old/volcano.pas
2021-02-21 12:14:06 +01:00

2705 lines
94 KiB
ObjectPascal

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.