Enemics, vides i animació de mort
This commit is contained in:
+334
-61
@@ -1,48 +1,72 @@
|
|||||||
-- Pepe el Pintor — port a ascii/Lua del joc original en Turbo Pascal
|
-- Pepe el Pintor — port a ascii/Lua del joc original en Turbo Pascal
|
||||||
-- (Sergi Valor Martínez, 1999). Base: PINTOR3.PAS.
|
-- (Sergi Valor Martínez, 1999). Base: PINTOR3.PAS.
|
||||||
--
|
--
|
||||||
-- ITER 1: motor mínim — fase única (la 3 = rectangle gran), Pepe es mou amb
|
-- ITER 2: motor base + enemics + vides.
|
||||||
-- O P Q A, pinta el fons al pas, gasta el pot de pintura i el recarrega al
|
-- - Fase única (la 3 = rectangle gran)
|
||||||
-- tornar a la posició inicial. Sense enemics, vides ni transicions.
|
-- - O P Q A per a moure, pinta al pas, gasta el pot
|
||||||
|
-- - Recàrrega al tornar al pot (fidel al Pascal: sound(i*10))
|
||||||
|
-- - 3 enemics amb spawn diferit per llindar de blocs pintats
|
||||||
|
-- - Moviment IA dels enemics fidel a moure_malos (random eix + perseguir)
|
||||||
|
-- - 5 vides, animació de mort, game over, victòria
|
||||||
|
|
||||||
-- ====================================================================
|
-- ====================================================================
|
||||||
-- CONSTANTS
|
-- CONSTANTS
|
||||||
-- ====================================================================
|
-- ====================================================================
|
||||||
MAP_W, MAP_H = 40, 25
|
MAP_W, MAP_H = 40, 25
|
||||||
HUD_Y0 = 25 -- HUD ocupa files 25..29
|
HUD_Y0 = 25
|
||||||
|
|
||||||
-- Glifs (codis CP437 originals). Els redefinim amb setchar per a fidelitat.
|
-- Glifs (codis CP437). Els redefinim amb setchar per a fidelitat.
|
||||||
PEPE_PLE = 2 -- ☻ Pepe amb pintura (cara plena)
|
PEPE_PLE = 2 -- ☻ Pepe amb pintura
|
||||||
PEPE_BUIT = 1 -- ☺ Pepe sense pintura (cara buida)
|
PEPE_BUIT = 1 -- ☺ Pepe sense pintura
|
||||||
PARED = 0xB1 -- ▒ paret
|
PARED = 0xB1 -- ▒ paret
|
||||||
FONS = 0xDB -- █ fons (sense pintar i pintat, distingit per atribut)
|
FONS = 0xDB -- █ fons (sense pintar / pintat = distingit per `pintat`)
|
||||||
POT_GLIF = 232 -- ◘ marca visual del pot
|
POT_GLIF = 232 -- ◘ marca visual del pot
|
||||||
|
MALO_GLIF = 88 -- 'X' enemic
|
||||||
|
|
||||||
-- Constants del joc
|
-- Constants del joc
|
||||||
POT_MAX = 90
|
POT_MAX = 90
|
||||||
PEPE_INI_X = 37 -- cambra del pot, 1 cel·la sortint del marc a la dreta (fidel al PINTOR3)
|
PEPE_INI_X = 37 -- cambra del pot (sortint 1 cel·la del marc a la dreta)
|
||||||
PEPE_INI_Y = 11
|
PEPE_INI_Y = 11
|
||||||
TICS_MOVIMENT = 5 -- frames entre intents de moviment (60/5 = 12 Hz)
|
TICS_MOVIMENT = 5 -- frames per tic de moviment (60/5 = 12 Hz)
|
||||||
TICS_OMPLIR = 3 -- frames entre +1 de pot al recarregar
|
TICS_OMPLIR = 3 -- frames entre +1 de pot al recarregar
|
||||||
|
|
||||||
|
NUM_MALOS = 3
|
||||||
|
VIDES_INI = 5
|
||||||
|
|
||||||
|
-- Llindars d'aparició dels enemics (proporcionals al PINTOR3 escalat als
|
||||||
|
-- nostres ~829 blocs). Apareixen quan total_blocs baixa per sota d'aquests.
|
||||||
|
BLOCS_SPAWN = { 750, 520, 370 }
|
||||||
|
|
||||||
|
-- Animació de mort: 10000 Hz → 1000 Hz, restant 250 cada pas
|
||||||
|
MORT_FREQ_INI = 10000
|
||||||
|
MORT_FREQ_END = 1000
|
||||||
|
MORT_FREQ_STEP = 250
|
||||||
|
MORT_FRAMES = 36 -- ~600 ms d'animació de mort
|
||||||
|
|
||||||
|
-- Estats
|
||||||
|
ESTAT_PLAYING = "playing"
|
||||||
|
ESTAT_MURIGUENT = "muriguent"
|
||||||
|
ESTAT_GAMEOVER = "gameover"
|
||||||
|
ESTAT_VICTORIA = "victoria"
|
||||||
|
|
||||||
-- ====================================================================
|
-- ====================================================================
|
||||||
-- ESTAT
|
-- ESTAT GLOBAL
|
||||||
-- ====================================================================
|
-- ====================================================================
|
||||||
mapa = {} -- mapa[x][y] = { tipo=, pintat=bool }
|
mapa = {}
|
||||||
pepe = { x=PEPE_INI_X, y=PEPE_INI_Y, pinta=true }
|
pepe = { x=PEPE_INI_X, y=PEPE_INI_Y, pinta=true }
|
||||||
pot = POT_MAX
|
pot = POT_MAX
|
||||||
total_blocs = 0 -- es calcula al carregar mapa
|
total_blocs = 0
|
||||||
omplint = false -- en mig d'una recàrrega?
|
omplint = false
|
||||||
omplir_i = 0 -- comptador del bucle de recàrrega (fidel al Pascal)
|
omplir_i = 0
|
||||||
omplir_max = 0 -- valor de (90-pot) en el moment d'entrar al pot
|
omplir_max = 0
|
||||||
|
|
||||||
-- Buffer d'edges d'input direccional.
|
malos = {} -- { {x, y, viu=bool, aparegut=bool}, ... }
|
||||||
-- update() corre a 60 fps però la lògica del Pepe avança cada TICS_MOVIMENT
|
vides = VIDES_INI
|
||||||
-- frames. Si l'usuari fa un tap curt entre dos tics, btn() al moment del tic
|
|
||||||
-- ja no detecta la pulsació. Bufferitzem només l'edge (btnp), així un tap
|
estat_joc = ESTAT_PLAYING
|
||||||
-- ràpid sempre genera UN moviment. El moviment "mantingut" segueix funcionant
|
estat_t = 0 -- contador de frames dins de l'estat actual
|
||||||
-- per btn() directe al tic. Buffer binari: si poses 3 taps en un tic, només
|
|
||||||
-- compta com 1 — no se sobren moviments al pròxim tic.
|
-- Buffer d'edges d'input direccional (vore explicació a l'iter 1).
|
||||||
input_buf = { up=false, down=false, left=false, right=false }
|
input_buf = { up=false, down=false, left=false, right=false }
|
||||||
|
|
||||||
function sample_input()
|
function sample_input()
|
||||||
@@ -60,16 +84,14 @@ end
|
|||||||
-- GLIFS CUSTOM (bitmaps CP437)
|
-- GLIFS CUSTOM (bitmaps CP437)
|
||||||
-- ====================================================================
|
-- ====================================================================
|
||||||
function definir_glifs()
|
function definir_glifs()
|
||||||
-- Pepe ple (CP437 chr 2 — smiley relleno)
|
|
||||||
setchar(PEPE_PLE, 0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E)
|
setchar(PEPE_PLE, 0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E)
|
||||||
-- Pepe buit (CP437 chr 1 — smiley contorn)
|
|
||||||
setchar(PEPE_BUIT, 0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E)
|
setchar(PEPE_BUIT, 0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E)
|
||||||
-- Paret ▒ (CP437 chr 177 — half-tone gris)
|
|
||||||
setchar(PARED, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11)
|
setchar(PARED, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11)
|
||||||
-- Fons █ ple
|
|
||||||
setchar(FONS, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)
|
setchar(FONS, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)
|
||||||
-- Pot de pintura: un trapezoide amb pintura dins (sprite propi)
|
|
||||||
setchar(POT_GLIF, 0x00, 0x7E, 0x7E, 0x42, 0x66, 0x7E, 0x3C, 0x00)
|
setchar(POT_GLIF, 0x00, 0x7E, 0x7E, 0x42, 0x66, 0x7E, 0x3C, 0x00)
|
||||||
|
-- L'enemic 'X' del CP437 ja és coherent al ROM nadiu d'ascii, però el
|
||||||
|
-- redefinim igualment per a controlar-ho.
|
||||||
|
setchar(MALO_GLIF, 0x00, 0xC3, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0xC3)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ====================================================================
|
-- ====================================================================
|
||||||
@@ -80,6 +102,21 @@ function tipo_a(x, y)
|
|||||||
return mapa[x][y].tipo
|
return mapa[x][y].tipo
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Una cel·la és "pintada" si Pepe o un malo hi han passat. Els malos només
|
||||||
|
-- es poden moure per cel·les pintades (fidel al Pascal: a_v(destí) == bg).
|
||||||
|
function pintat_a(x, y)
|
||||||
|
if x < 0 or x >= MAP_W or y < 0 or y >= MAP_H then return false end
|
||||||
|
return mapa[x][y].pintat
|
||||||
|
end
|
||||||
|
|
||||||
|
function hi_ha_malo(x, y)
|
||||||
|
for i = 1, NUM_MALOS do
|
||||||
|
local m = malos[i]
|
||||||
|
if m.viu and m.x == x and m.y == y then return true end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
function carregar_mapa(num)
|
function carregar_mapa(num)
|
||||||
filein("maps/"..tostr(num)..".map", 0, MAP_W*MAP_H)
|
filein("maps/"..tostr(num)..".map", 0, MAP_W*MAP_H)
|
||||||
total_blocs = 0
|
total_blocs = 0
|
||||||
@@ -91,8 +128,7 @@ function carregar_mapa(num)
|
|||||||
if b == FONS then total_blocs = total_blocs + 1 end
|
if b == FONS then total_blocs = total_blocs + 1 end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- La cel·la del pot no es pinta: la marquem com "ja pintada" i la traiem
|
-- La cel·la del pot no es pinta: ja "pintada" per a la condició de victòria
|
||||||
-- del compte, així `total_blocs == 0` és assolible com a condició de victòria.
|
|
||||||
mapa[PEPE_INI_X][PEPE_INI_Y].pintat = true
|
mapa[PEPE_INI_X][PEPE_INI_Y].pintat = true
|
||||||
total_blocs = total_blocs - 1
|
total_blocs = total_blocs - 1
|
||||||
end
|
end
|
||||||
@@ -108,13 +144,11 @@ function pintar_mapa()
|
|||||||
color(COLOR_BROWN, COLOR_BLACK)
|
color(COLOR_BROWN, COLOR_BLACK)
|
||||||
print(chr(FONS), x, y)
|
print(chr(FONS), x, y)
|
||||||
end
|
end
|
||||||
-- FONS no pintat: deixem la cel·la negra (cls); no es dibuixa res
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function pintar_pot()
|
function pintar_pot()
|
||||||
-- Dibuixem la marca visual del pot només si Pepe NO hi és damunt
|
|
||||||
if not (pepe.x == PEPE_INI_X and pepe.y == PEPE_INI_Y) then
|
if not (pepe.x == PEPE_INI_X and pepe.y == PEPE_INI_Y) then
|
||||||
color(COLOR_YELLOW, COLOR_BROWN)
|
color(COLOR_YELLOW, COLOR_BROWN)
|
||||||
print(chr(POT_GLIF), PEPE_INI_X, PEPE_INI_Y)
|
print(chr(POT_GLIF), PEPE_INI_X, PEPE_INI_Y)
|
||||||
@@ -124,7 +158,9 @@ end
|
|||||||
function pintar_pepe()
|
function pintar_pepe()
|
||||||
local glif = pepe.pinta and PEPE_PLE or PEPE_BUIT
|
local glif = pepe.pinta and PEPE_PLE or PEPE_BUIT
|
||||||
local fons_color
|
local fons_color
|
||||||
if mapa[pepe.x][pepe.y].pintat then
|
if pepe.x == PEPE_INI_X and pepe.y == PEPE_INI_Y then
|
||||||
|
fons_color = COLOR_BROWN -- damunt del pot
|
||||||
|
elseif mapa[pepe.x][pepe.y].pintat then
|
||||||
fons_color = COLOR_BROWN
|
fons_color = COLOR_BROWN
|
||||||
else
|
else
|
||||||
fons_color = COLOR_BLACK
|
fons_color = COLOR_BLACK
|
||||||
@@ -133,6 +169,18 @@ function pintar_pepe()
|
|||||||
print(chr(glif), pepe.x, pepe.y)
|
print(chr(glif), pepe.x, pepe.y)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function pintar_malos()
|
||||||
|
for i = 1, NUM_MALOS do
|
||||||
|
local m = malos[i]
|
||||||
|
if m.viu then
|
||||||
|
-- Color enemic: cian clar (107 = 0x6B → bg 6 marró + fg 11 cian)
|
||||||
|
color(COLOR_LIGHT_CYAN, COLOR_BROWN)
|
||||||
|
print(chr(MALO_GLIF), m.x, m.y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- HUD: pintura, blocs restants, vides (com a ☻), controls
|
||||||
function pintar_hud()
|
function pintar_hud()
|
||||||
color(COLOR_LIGHT_GRAY, COLOR_BLUE)
|
color(COLOR_LIGHT_GRAY, COLOR_BLUE)
|
||||||
local blank = " "
|
local blank = " "
|
||||||
@@ -140,31 +188,40 @@ function pintar_hud()
|
|||||||
|
|
||||||
color(COLOR_WHITE, COLOR_BLUE)
|
color(COLOR_WHITE, COLOR_BLUE)
|
||||||
print("PINTURA "..string.format("%02d", pot).."/"..tostr(POT_MAX), 1, 26)
|
print("PINTURA "..string.format("%02d", pot).."/"..tostr(POT_MAX), 1, 26)
|
||||||
|
|
||||||
color(COLOR_YELLOW, COLOR_BLUE)
|
color(COLOR_YELLOW, COLOR_BLUE)
|
||||||
print("BLOCS "..string.format("%04d", total_blocs), 22, 26)
|
print("BLOCS "..string.format("%04d", total_blocs), 17, 26)
|
||||||
|
|
||||||
|
color(COLOR_LIGHT_RED, COLOR_BLUE)
|
||||||
|
for i = 1, vides do
|
||||||
|
print(chr(PEPE_PLE), 32 + i, 26)
|
||||||
|
end
|
||||||
|
|
||||||
color(COLOR_LIGHT_CYAN, COLOR_BLUE)
|
color(COLOR_LIGHT_CYAN, COLOR_BLUE)
|
||||||
print("O P Q A: moure", 1, 28)
|
print("O P Q A: moure", 1, 28)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ====================================================================
|
-- ====================================================================
|
||||||
-- LÒGICA DEL JOC
|
-- LÒGICA DEL PEPE
|
||||||
-- ====================================================================
|
-- ====================================================================
|
||||||
|
|
||||||
-- Intent de moviment en (dx, dy). Si la cel·la destí és paret, no es mou.
|
|
||||||
-- Si és fons no pintat i hi ha pintura, la pinta i descompta del pot.
|
|
||||||
function intent_moviment(dx, dy)
|
function intent_moviment(dx, dy)
|
||||||
local nx, ny = pepe.x + dx, pepe.y + dy
|
local nx, ny = pepe.x + dx, pepe.y + dy
|
||||||
local t = tipo_a(nx, ny)
|
local t = tipo_a(nx, ny)
|
||||||
if t == PARED then return end
|
if t == PARED then return end
|
||||||
if t ~= FONS then return end
|
if t ~= FONS then return end
|
||||||
|
|
||||||
|
-- Detecció de mort: si la cel·la destí té un malo (fidel a "a_v=bicho")
|
||||||
|
if hi_ha_malo(nx, ny) then
|
||||||
|
mort_pepe()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
pepe.x, pepe.y = nx, ny
|
pepe.x, pepe.y = nx, ny
|
||||||
local c = mapa[nx][ny]
|
local c = mapa[nx][ny]
|
||||||
|
|
||||||
-- La cel·la del pot no es pinta mai (es queda neta per a la recàrrega)
|
-- El pot no es pinta
|
||||||
if nx == PEPE_INI_X and ny == PEPE_INI_Y then
|
if nx == PEPE_INI_X and ny == PEPE_INI_Y then
|
||||||
sound(2000, 4)
|
sound(2000, 3)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -176,30 +233,29 @@ function intent_moviment(dx, dy)
|
|||||||
sound(5000, 3)
|
sound(5000, 3)
|
||||||
pepe.pinta = (pot > 0)
|
pepe.pinta = (pot > 0)
|
||||||
else
|
else
|
||||||
sound(800, 3)
|
sound(1000, 3) -- so més greu quan no hi ha pintura (fidel: nota=1000)
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
sound(5000, 3)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function tic_pepe()
|
function tic_pepe()
|
||||||
if omplint then return end -- bloquejat durant l'animació de recàrrega
|
if omplint then return end
|
||||||
-- Cada direcció: edge bufferitzat (tap curt) OR tecla mantinguda al moment del tic.
|
|
||||||
if input_buf.up or btn(KEY_Q) then intent_moviment( 0, -1)
|
if input_buf.up or btn(KEY_Q) then intent_moviment( 0, -1)
|
||||||
elseif input_buf.down or btn(KEY_A) then intent_moviment( 0, 1)
|
elseif input_buf.down or btn(KEY_A) then intent_moviment( 0, 1)
|
||||||
elseif input_buf.left or btn(KEY_O) then intent_moviment(-1, 0)
|
elseif input_buf.left or btn(KEY_O) then intent_moviment(-1, 0)
|
||||||
elseif input_buf.right or btn(KEY_P) then intent_moviment( 1, 0)
|
elseif input_buf.right or btn(KEY_P) then intent_moviment( 1, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Arribar al pot dispara la recàrrega
|
|
||||||
if pepe.x == PEPE_INI_X and pepe.y == PEPE_INI_Y and pot < POT_MAX then
|
if pepe.x == PEPE_INI_X and pepe.y == PEPE_INI_Y and pot < POT_MAX then
|
||||||
omplint = true
|
omplint = true
|
||||||
omplir_i = 0
|
omplir_i = 0
|
||||||
omplir_max = POT_MAX - pot -- (90 - pot) en el moment d'entrar
|
omplir_max = POT_MAX - pot
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Fidel al Pascal original: `for i:=0 to 90-pot do sound(i*10); pot:=pot+1;`
|
-- Fidel al Pascal: sound(i*10) on i és el comptador del bucle
|
||||||
-- El so depèn del comptador del bucle (sempre arranca a 0 Hz), no del nivell del pot.
|
|
||||||
function tic_omplir()
|
function tic_omplir()
|
||||||
if not omplint then return end
|
if not omplint then return end
|
||||||
sound(omplir_i * 10, 2)
|
sound(omplir_i * 10, 2)
|
||||||
@@ -213,6 +269,231 @@ function tic_omplir()
|
|||||||
pepe.pinta = true
|
pepe.pinta = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- ====================================================================
|
||||||
|
-- ENEMICS — moure_malos del PINTOR3.PAS
|
||||||
|
-- ====================================================================
|
||||||
|
function init_malos()
|
||||||
|
malos = {}
|
||||||
|
for i = 1, NUM_MALOS do
|
||||||
|
malos[i] = { x=0, y=0, viu=false, aparegut=false }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- naiximent: busca totes les cel·les pintades (= chr 219 en el Pascal) i
|
||||||
|
-- en tria una aleatòria. Reservem el pot perquè no naixi el malo damunt.
|
||||||
|
function naiximent()
|
||||||
|
local llocs = {}
|
||||||
|
for x = 0, MAP_W-1 do
|
||||||
|
for y = 0, MAP_H-1 do
|
||||||
|
if mapa[x][y].pintat
|
||||||
|
and not (x == PEPE_INI_X and y == PEPE_INI_Y)
|
||||||
|
and not (x == pepe.x and y == pepe.y) then
|
||||||
|
llocs[#llocs+1] = { x=x, y=y }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #llocs == 0 then return PEPE_INI_X, PEPE_INI_Y end -- fallback (impossible si jugues)
|
||||||
|
local pick = llocs[rnd(#llocs) + 1]
|
||||||
|
return pick.x, pick.y
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Jingle "música malos" del Pascal (sound creixent i decreixent en bucle)
|
||||||
|
function jingle_malo()
|
||||||
|
play("l0o3cdefgab>cl0o3cdefgab>c")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check spawn: si total_blocs ha baixat per sota del llindar i el malo no
|
||||||
|
-- ha aparegut encara, el fem aparèixer.
|
||||||
|
function check_spawn()
|
||||||
|
for i = 1, NUM_MALOS do
|
||||||
|
local m = malos[i]
|
||||||
|
if not m.aparegut and total_blocs <= BLOCS_SPAWN[i] then
|
||||||
|
m.x, m.y = naiximent()
|
||||||
|
m.viu = true
|
||||||
|
m.aparegut = true
|
||||||
|
jingle_malo()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Decisió de direcció del malo (fidel a moure_malos del Pascal):
|
||||||
|
-- random(2): 0 = perseguir en eix X, 1 = perseguir en eix Y. La direcció és:
|
||||||
|
-- meneja=0 esquerra, 1 dreta, 2 dalt, 3 baix.
|
||||||
|
-- Retorna una de les 4 direccions (o nil si no s'aplica cap).
|
||||||
|
function decidir_direccio(m)
|
||||||
|
local meneja = nil
|
||||||
|
if rnd(2) == 0 then
|
||||||
|
if pepe.x - m.x > 0 then meneja = 1 -- pepe a la dreta del malo
|
||||||
|
elseif pepe.x - m.x < 0 then meneja = 0 -- pepe a l'esquerra
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if pepe.y - m.y > 0 then meneja = 3 -- pepe avall
|
||||||
|
elseif pepe.y - m.y < 0 then meneja = 2 -- pepe amunt
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return meneja
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Intenta moure un malo en la direcció `meneja`. Fidel al Pascal:
|
||||||
|
-- requereix que la cel·la destí (a) no siga paret, (b) no tinga un altre
|
||||||
|
-- malo, i (c) siga "bg" (= cel·la pintada). Aquesta tercera condició limita
|
||||||
|
-- els malos a la zona ja pintada pel Pepe.
|
||||||
|
function moure_malo(m, meneja)
|
||||||
|
if meneja == nil then return end
|
||||||
|
local dx, dy = 0, 0
|
||||||
|
if meneja == 0 then dx = -1
|
||||||
|
elseif meneja == 1 then dx = 1
|
||||||
|
elseif meneja == 2 then dy = -1
|
||||||
|
elseif meneja == 3 then dy = 1
|
||||||
|
end
|
||||||
|
local nx, ny = m.x + dx, m.y + dy
|
||||||
|
if tipo_a(nx, ny) == PARED then return end
|
||||||
|
if hi_ha_malo(nx, ny) then return end
|
||||||
|
if not pintat_a(nx, ny) then return end
|
||||||
|
m.x, m.y = nx, ny
|
||||||
|
end
|
||||||
|
|
||||||
|
function tic_malos()
|
||||||
|
for i = 1, NUM_MALOS do
|
||||||
|
local m = malos[i]
|
||||||
|
if m.viu then
|
||||||
|
moure_malo(m, decidir_direccio(m))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function check_mort_per_malo()
|
||||||
|
for i = 1, NUM_MALOS do
|
||||||
|
local m = malos[i]
|
||||||
|
if m.viu and m.x == pepe.x and m.y == pepe.y then
|
||||||
|
mort_pepe()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ====================================================================
|
||||||
|
-- MORT + ESTATS DE TRANSICIÓ
|
||||||
|
-- ====================================================================
|
||||||
|
function set_estat(nou)
|
||||||
|
estat_joc = nou
|
||||||
|
estat_t = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function mort_pepe()
|
||||||
|
vides = vides - 1
|
||||||
|
set_estat(ESTAT_MURIGUENT)
|
||||||
|
end
|
||||||
|
|
||||||
|
function reset_partida()
|
||||||
|
pot = POT_MAX
|
||||||
|
total_blocs = 0
|
||||||
|
vides = VIDES_INI
|
||||||
|
omplint = false
|
||||||
|
pepe.x, pepe.y = PEPE_INI_X, PEPE_INI_Y
|
||||||
|
pepe.pinta = true
|
||||||
|
init_malos()
|
||||||
|
carregar_mapa(3)
|
||||||
|
reset_input()
|
||||||
|
set_estat(ESTAT_PLAYING)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Respawn després de mort (sense reset complet, sols Pepe a casa i pot ple)
|
||||||
|
function respawn_pepe()
|
||||||
|
pepe.x, pepe.y = PEPE_INI_X, PEPE_INI_Y
|
||||||
|
pepe.pinta = true
|
||||||
|
pot = POT_MAX
|
||||||
|
omplint = false
|
||||||
|
reset_input()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ====================================================================
|
||||||
|
-- LÒGICA PER ESTAT
|
||||||
|
-- ====================================================================
|
||||||
|
function update_playing()
|
||||||
|
sample_input()
|
||||||
|
|
||||||
|
if omplint and (cnt() % TICS_OMPLIR) == 0 then tic_omplir() end
|
||||||
|
|
||||||
|
if not omplint and (cnt() % TICS_MOVIMENT) == 0 then
|
||||||
|
tic_pepe()
|
||||||
|
check_mort_per_malo()
|
||||||
|
if estat_joc ~= ESTAT_PLAYING then reset_input(); return end
|
||||||
|
tic_malos()
|
||||||
|
check_mort_per_malo()
|
||||||
|
check_spawn()
|
||||||
|
reset_input()
|
||||||
|
|
||||||
|
if total_blocs <= 0 then
|
||||||
|
set_estat(ESTAT_VICTORIA)
|
||||||
|
play("l3o4ceg>c")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
cls()
|
||||||
|
pintar_mapa()
|
||||||
|
pintar_pot()
|
||||||
|
pintar_malos()
|
||||||
|
pintar_pepe()
|
||||||
|
pintar_hud()
|
||||||
|
end
|
||||||
|
|
||||||
|
function update_muriguent()
|
||||||
|
-- Animació de mort: so descendent + parpadeig del Pepe
|
||||||
|
local pas = flr(estat_t / 3)
|
||||||
|
local freq = MORT_FREQ_INI - pas * MORT_FREQ_STEP
|
||||||
|
if freq < MORT_FREQ_END then freq = MORT_FREQ_END end
|
||||||
|
sound(freq, 2)
|
||||||
|
|
||||||
|
cls()
|
||||||
|
pintar_mapa()
|
||||||
|
pintar_pot()
|
||||||
|
pintar_malos()
|
||||||
|
if (estat_t // 4) % 2 == 0 then pintar_pepe() end
|
||||||
|
pintar_hud()
|
||||||
|
|
||||||
|
if estat_t >= MORT_FRAMES then
|
||||||
|
nosound()
|
||||||
|
if vides <= 0 then
|
||||||
|
set_estat(ESTAT_GAMEOVER)
|
||||||
|
else
|
||||||
|
respawn_pepe()
|
||||||
|
set_estat(ESTAT_PLAYING)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function update_gameover()
|
||||||
|
cls()
|
||||||
|
pintar_mapa()
|
||||||
|
pintar_pot()
|
||||||
|
pintar_malos()
|
||||||
|
pintar_hud()
|
||||||
|
color(COLOR_WHITE, COLOR_RED)
|
||||||
|
print(" A D E U ", 15, 11)
|
||||||
|
|
||||||
|
if estat_t > 120 and btnp(KEY_SPACE) then
|
||||||
|
reset_partida()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function update_victoria()
|
||||||
|
cls()
|
||||||
|
pintar_mapa()
|
||||||
|
pintar_pot()
|
||||||
|
pintar_pepe()
|
||||||
|
pintar_hud()
|
||||||
|
if (estat_t // 10) % 2 == 0 then
|
||||||
|
color(COLOR_GREEN, COLOR_BLACK)
|
||||||
|
print("ENHORABONA!", 14, 11)
|
||||||
|
end
|
||||||
|
|
||||||
|
if estat_t > 180 and btnp(KEY_SPACE) then
|
||||||
|
reset_partida()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- ====================================================================
|
-- ====================================================================
|
||||||
-- BUCLE PRINCIPAL
|
-- BUCLE PRINCIPAL
|
||||||
-- ====================================================================
|
-- ====================================================================
|
||||||
@@ -220,24 +501,16 @@ function init()
|
|||||||
mode(1)
|
mode(1)
|
||||||
border(COLOR_BLUE)
|
border(COLOR_BLUE)
|
||||||
definir_glifs()
|
definir_glifs()
|
||||||
|
init_malos()
|
||||||
carregar_mapa(3)
|
carregar_mapa(3)
|
||||||
cls()
|
cls()
|
||||||
end
|
end
|
||||||
|
|
||||||
function update()
|
function update()
|
||||||
-- Sample d'edges d'input cada frame (mentre el joc està actiu i no en recàrrega)
|
estat_t = estat_t + 1
|
||||||
if not omplint then sample_input() end
|
if estat_joc == ESTAT_PLAYING then update_playing()
|
||||||
|
elseif estat_joc == ESTAT_MURIGUENT then update_muriguent()
|
||||||
if omplint and (cnt() % TICS_OMPLIR) == 0 then tic_omplir() end
|
elseif estat_joc == ESTAT_GAMEOVER then update_gameover()
|
||||||
|
elseif estat_joc == ESTAT_VICTORIA then update_victoria()
|
||||||
if not omplint and (cnt() % TICS_MOVIMENT) == 0 then
|
|
||||||
tic_pepe()
|
|
||||||
reset_input() -- descartem edges acumulats després de processar el tic
|
|
||||||
end
|
end
|
||||||
|
|
||||||
cls()
|
|
||||||
pintar_mapa()
|
|
||||||
pintar_pot()
|
|
||||||
pintar_pepe()
|
|
||||||
pintar_hud()
|
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user