DX: malos atrapats als forats, com en Lode Runner classic
This commit is contained in:
@@ -43,6 +43,7 @@ skin = "native"
|
||||
-- colors.pepe_invuln = COLOR_LIGHT_GREEN -- parpadeig en invulnerabilitat
|
||||
-- colors.malo = COLOR_LIGHT_RED -- enemics
|
||||
-- colors.malo_carrega = COLOR_LIGHT_MAGENTA -- enemic portant diners
|
||||
-- colors.malo_atrapat = COLOR_BROWN -- enemic atrapat en un forat
|
||||
-- colors.hud_text = COLOR_WHITE -- text del rotul inferior
|
||||
-- colors.hud_bg = COLOR_BLACK -- fons del rotul inferior
|
||||
-- colors.border = COLOR_BLUE -- vora exterior de la finestra
|
||||
|
||||
+126
-44
@@ -79,6 +79,7 @@ colors = {
|
||||
pepe_invuln = COLOR_LIGHT_GREEN, -- parpadeig de Pepe quan es invulnerable
|
||||
malo = COLOR_LIGHT_RED,
|
||||
malo_carrega = COLOR_LIGHT_MAGENTA, -- enemic portant diners
|
||||
malo_atrapat = COLOR_BROWN, -- enemic atrapat en un forat (color de pedra)
|
||||
hud_text = COLOR_WHITE,
|
||||
hud_bg = COLOR_BLACK,
|
||||
border = COLOR_BLUE,
|
||||
@@ -307,6 +308,23 @@ function tipo_a(x, y)
|
||||
return mapa[x][y].tipo
|
||||
end
|
||||
|
||||
-- Es comporta com una paret (impedeix passar lateralment, fa de suport):
|
||||
-- PEDRA, qualsevol fase de forat tancant-se (BLOC1/2/3) o un malo atrapat.
|
||||
-- Aço unifica el comportament: "rellenat" o "rellenant" → solid.
|
||||
function es_paret(x, y)
|
||||
local t = tipo_a(x, y)
|
||||
if t == PEDRA or t == BLOC1 or t == BLOC2 or t == BLOC3 then return true end
|
||||
for i = 1, NUM_MALOS do
|
||||
if malos[i].atrapat and malos[i].x == x and malos[i].y == y then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Es comporta com a suport per a no caure (paret + escala).
|
||||
function es_suport(x, y)
|
||||
return es_paret(x, y) or tipo_a(x, y) == ESCALA
|
||||
end
|
||||
|
||||
function carregar_mapa(num)
|
||||
filein("maps/"..tostr(num)..".map", 0, MAP_W*MAP_H)
|
||||
diners_pantalla = 0
|
||||
@@ -390,7 +408,7 @@ end
|
||||
function pot_cavar(dx)
|
||||
return pepe.estat == NORMAL
|
||||
and tipo_a(pepe.x+dx, pepe.y+1) == PEDRA
|
||||
and tipo_a(pepe.x+dx, pepe.y) ~= PEDRA
|
||||
and not es_paret(pepe.x+dx, pepe.y)
|
||||
end
|
||||
|
||||
-- Tic de joc del Pepe: input de moviment, gravetat, recollir diners, emparedat
|
||||
@@ -398,22 +416,26 @@ function tic_pepe()
|
||||
local actual = tipo_a(pepe.x, pepe.y)
|
||||
local sotto = tipo_a(pepe.x, pepe.y+1)
|
||||
|
||||
-- Moviment vertical (com en RUNNER.PAS, son if/else)
|
||||
-- Moviment vertical (com en RUNNER.PAS, son if/else).
|
||||
-- Bloquegem entrar dins de qualsevol cel·la "paret" (inclou malos atrapats).
|
||||
if btn(keys.up) then
|
||||
if actual == ESCALA then pepe.y = pepe.y - 1 end
|
||||
if actual == ESCALA and not es_paret(pepe.x, pepe.y-1) then
|
||||
pepe.y = pepe.y - 1
|
||||
end
|
||||
elseif btn(keys.down) then
|
||||
if sotto == ESCALA or sotto == BUIT or sotto == DINERS then
|
||||
if not es_paret(pepe.x, pepe.y+1)
|
||||
and (sotto == ESCALA or sotto == BUIT or sotto == DINERS) then
|
||||
pepe.y = pepe.y + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Moviment horitzontal (no es pot moure si esta caent)
|
||||
if btn(keys.left) then
|
||||
if tipo_a(pepe.x-1, pepe.y) ~= PEDRA and pepe.estat ~= CAENT then
|
||||
if not es_paret(pepe.x-1, pepe.y) and pepe.estat ~= CAENT then
|
||||
pepe.x = pepe.x - 1
|
||||
end
|
||||
elseif btn(keys.right) then
|
||||
if tipo_a(pepe.x+1, pepe.y) ~= PEDRA and pepe.estat ~= CAENT then
|
||||
if not es_paret(pepe.x+1, pepe.y) and pepe.estat ~= CAENT then
|
||||
pepe.x = pepe.x + 1
|
||||
end
|
||||
end
|
||||
@@ -446,10 +468,9 @@ function tic_pepe()
|
||||
if pepe.x < 0 then pepe.x = 0 end
|
||||
if pepe.x > MAP_W-1 then pepe.x = MAP_W-1 end
|
||||
|
||||
-- Gravetat: si la cel·la actual es buit/diners i la de baix no es escala/pedra → cau
|
||||
-- Gravetat: si la cel·la actual es buit/diners i la de baix no fa de suport → cau
|
||||
actual = tipo_a(pepe.x, pepe.y)
|
||||
sotto = tipo_a(pepe.x, pepe.y+1)
|
||||
if (sotto ~= ESCALA and sotto ~= PEDRA)
|
||||
if not es_suport(pepe.x, pepe.y+1)
|
||||
and (actual == BUIT or actual == DINERS) then
|
||||
pepe.y = pepe.y + 1
|
||||
pepe.estat = CAENT
|
||||
@@ -726,11 +747,12 @@ end
|
||||
-- ====================================================================
|
||||
|
||||
function init_malos()
|
||||
malos = {
|
||||
{ x= 9, y=2, color=colors.malo, estat=ESQUERRA, iaclock=0, carrega={ok=false, x=0, y=0} },
|
||||
{ x=20, y=2, color=colors.malo, estat=ESQUERRA, iaclock=0, carrega={ok=false, x=0, y=0} },
|
||||
{ x=39, y=2, color=colors.malo, estat=ESQUERRA, iaclock=0, carrega={ok=false, x=0, y=0} },
|
||||
}
|
||||
local function novo(x, y)
|
||||
return { x=x, y=y, color=colors.malo, estat=ESQUERRA, iaclock=0,
|
||||
carrega={ok=false, x=0, y=0}, atrapat=false,
|
||||
dropped_x=nil, dropped_y=nil }
|
||||
end
|
||||
malos = { novo(9, 2), novo(20, 2), novo(39, 2) }
|
||||
end
|
||||
|
||||
function pintar_malos()
|
||||
@@ -746,8 +768,8 @@ end
|
||||
-- Si no te suport sota els peus, override a CAENT.
|
||||
function select_estat(m)
|
||||
local nou = 0
|
||||
if tipo_a(m.x+1, m.y) ~= PEDRA then nou = nou | DRETA end
|
||||
if tipo_a(m.x-1, m.y) ~= PEDRA then nou = nou | ESQUERRA end
|
||||
if not es_paret(m.x+1, m.y) then nou = nou | DRETA end
|
||||
if not es_paret(m.x-1, m.y) then nou = nou | ESQUERRA end
|
||||
if tipo_a(m.x, m.y) == ESCALA then nou = nou | PUJAR end
|
||||
if tipo_a(m.x, m.y+1) == ESCALA then nou = nou | BAIXAR end
|
||||
|
||||
@@ -773,8 +795,7 @@ function select_estat(m)
|
||||
|
||||
-- override de caiguda (igual que en el Pascal — no comprova corda aci,
|
||||
-- la comprovacio amb corda es fa al tic_malos)
|
||||
local sotto = tipo_a(m.x, m.y+1)
|
||||
if sotto ~= PEDRA and sotto ~= ESCALA then sestat = CAENT end
|
||||
if not es_suport(m.x, m.y+1) then sestat = CAENT end
|
||||
|
||||
return sestat
|
||||
end
|
||||
@@ -795,56 +816,106 @@ end
|
||||
-- A diferencia del Pascal, sols solta diners si en duia (l'original sempre
|
||||
-- escrivia diners a (carrega.x, carrega.y), deixant un $ a (0,0) com a bug).
|
||||
function mort_malo(m)
|
||||
-- El comptador diners_pantalla NO canvia: l'enemic agafant/soltant es
|
||||
-- transitori, sols compta el que el Pepe recull definitivament.
|
||||
-- Cas A: encara duu carrega (no era atrapat) → solta al lloc original.
|
||||
-- Cas B: era atrapat i ja havia soltat la carrega sobre la cabeça →
|
||||
-- si l'has sepultat (cel·la torna a ser pedra), restaura al
|
||||
-- lloc original perque el mapa segueix sent acabable.
|
||||
if m.carrega.ok then
|
||||
local c = mapa[m.carrega.x][m.carrega.y]
|
||||
c.tipo = DINERS
|
||||
c.color = colors.diners
|
||||
elseif m.dropped_x then
|
||||
local t = mapa[m.dropped_x][m.dropped_y].tipo
|
||||
-- BUIT = Pepe la va recollir; DINERS = encara hi es; pedra/bloc = sepultada
|
||||
if t ~= BUIT and t ~= DINERS then
|
||||
local c = mapa[m.carrega.x][m.carrega.y]
|
||||
c.tipo = DINERS
|
||||
c.color = colors.diners
|
||||
end
|
||||
end
|
||||
m.x = 39; m.y = 1
|
||||
m.color = colors.malo
|
||||
m.estat = CAENT
|
||||
m.iaclock = 0
|
||||
m.atrapat = false
|
||||
m.carrega.ok = false
|
||||
m.carrega.x = 0
|
||||
m.carrega.y = 0
|
||||
m.dropped_x = nil
|
||||
m.dropped_y = nil
|
||||
sfx_malo_die()
|
||||
end
|
||||
|
||||
-- Marca un enemic com a atrapat en un forat obert. Es queda quiet fins
|
||||
-- que la cel·la es rellena (i llavors mor per emparedat). Solta la carrega
|
||||
-- de forma immediata sobre la cabeça (o al lloc original si la cabeça no
|
||||
-- pot acollir-la).
|
||||
function atrapar(m)
|
||||
if m.atrapat then return end
|
||||
m.atrapat = true
|
||||
m.estat = NORMAL
|
||||
m.color = colors.malo_atrapat
|
||||
|
||||
if m.carrega.ok then
|
||||
local cy = m.y - 1
|
||||
if cy >= 0 and mapa[m.x][cy].tipo == BUIT and mapa[m.x][cy].temps <= 0 then
|
||||
mapa[m.x][cy].tipo = DINERS
|
||||
mapa[m.x][cy].color = colors.diners
|
||||
m.dropped_x = m.x
|
||||
m.dropped_y = cy
|
||||
else
|
||||
-- cabeça ocupada o fora de mapa: fallback al lloc original
|
||||
mapa[m.carrega.x][m.carrega.y].tipo = DINERS
|
||||
mapa[m.carrega.x][m.carrega.y].color = colors.diners
|
||||
m.dropped_x = m.carrega.x
|
||||
m.dropped_y = m.carrega.y
|
||||
end
|
||||
m.carrega.ok = false
|
||||
end
|
||||
end
|
||||
|
||||
function tic_malos()
|
||||
for i = 1, NUM_MALOS do
|
||||
local m = malos[i]
|
||||
|
||||
-- Malo atrapat: nomes comprovem si la cel·la s'ha rellenat (emparedat).
|
||||
-- No es mou, no agafa diners, no reaccionara fins que muiga.
|
||||
if m.atrapat then
|
||||
if tipo_a(m.x, m.y) == PEDRA then mort_malo(m) end
|
||||
goto seguent
|
||||
end
|
||||
|
||||
if m.iaclock == 0 then m.estat = select_estat(m) end
|
||||
m.estat = agafar_escala(m)
|
||||
|
||||
local actual = tipo_a(m.x, m.y)
|
||||
local sotto = tipo_a(m.x, m.y+1)
|
||||
do
|
||||
local actual = tipo_a(m.x, m.y)
|
||||
|
||||
-- caiguda (aquesta SI comprova corda — els malos s'agafen a la corda)
|
||||
if sotto ~= PEDRA and sotto ~= ESCALA and actual ~= CORDA then
|
||||
m.estat = CAENT
|
||||
end
|
||||
-- si toca terra i venia caent → reconsidera
|
||||
if (sotto == PEDRA or sotto == ESCALA) and m.estat == CAENT then
|
||||
m.estat = select_estat(m)
|
||||
end
|
||||
-- si vol pujar pero no esta en escala → reconsidera
|
||||
if actual == BUIT and m.estat == PUJAR then
|
||||
m.estat = select_estat(m)
|
||||
end
|
||||
-- si vol baixar pero te pedra sota → reconsidera
|
||||
if sotto == PEDRA and m.estat == BAIXAR then
|
||||
m.estat = select_estat(m)
|
||||
-- caiguda (aquesta SI comprova corda — els malos s'agafen a la corda)
|
||||
if not es_suport(m.x, m.y+1) and actual ~= CORDA then
|
||||
m.estat = CAENT
|
||||
end
|
||||
-- si toca terra i venia caent → reconsidera
|
||||
if es_suport(m.x, m.y+1) and m.estat == CAENT then
|
||||
m.estat = select_estat(m)
|
||||
end
|
||||
-- si vol pujar pero no esta en escala → reconsidera
|
||||
if actual == BUIT and m.estat == PUJAR then
|
||||
m.estat = select_estat(m)
|
||||
end
|
||||
-- si vol baixar pero te paret sota → reconsidera
|
||||
if es_paret(m.x, m.y+1) and m.estat == BAIXAR then
|
||||
m.estat = select_estat(m)
|
||||
end
|
||||
end
|
||||
|
||||
-- aplicar moviment
|
||||
if m.estat == DRETA then m.x = m.x + 1
|
||||
elseif m.estat == ESQUERRA then m.x = m.x - 1
|
||||
elseif m.estat == PUJAR then m.y = m.y - 1
|
||||
elseif m.estat == BAIXAR then m.y = m.y + 1
|
||||
elseif m.estat == CAENT then m.y = m.y + 1
|
||||
-- aplicar moviment (nomes si la cel·la desti no es paret;
|
||||
-- aixi els malos no es fiquen dins d'altres malos atrapats)
|
||||
if m.estat == DRETA and not es_paret(m.x+1, m.y) then m.x = m.x + 1
|
||||
elseif m.estat == ESQUERRA and not es_paret(m.x-1, m.y) then m.x = m.x - 1
|
||||
elseif m.estat == PUJAR and not es_paret(m.x, m.y-1) then m.y = m.y - 1
|
||||
elseif m.estat == BAIXAR and not es_paret(m.x, m.y+1) then m.y = m.y + 1
|
||||
elseif m.estat == CAENT and not es_paret(m.x, m.y+1) then m.y = m.y + 1
|
||||
end
|
||||
|
||||
-- bordes X (rebot)
|
||||
@@ -863,11 +934,21 @@ function tic_malos()
|
||||
m.carrega.y = m.y
|
||||
end
|
||||
|
||||
-- caure dins d'un forat obert (BUIT cavat) → atrapat. No comprovem
|
||||
-- suport sota: en el Lode Runner classic el malo queda agarrat al
|
||||
-- vora del forat encara que sota hi haja aire (forats "flotants"
|
||||
-- a una planta amb buit a sota també atrapen el malo que cau).
|
||||
if mapa[m.x][m.y].tipo == BUIT and mapa[m.x][m.y].temps > 0 then
|
||||
atrapar(m)
|
||||
end
|
||||
|
||||
-- emparedat → mort
|
||||
if tipo_a(m.x, m.y) == PEDRA then
|
||||
mort_malo(m)
|
||||
end
|
||||
|
||||
::seguent::
|
||||
|
||||
m.iaclock = m.iaclock + 1
|
||||
if m.iaclock == TEMPS_IA then m.iaclock = 0 end
|
||||
end
|
||||
@@ -876,7 +957,8 @@ end
|
||||
function check_mort_per_malos()
|
||||
if pepe.invuln_t > 0 or pepe.mort_t > 0 then return end
|
||||
for i = 1, NUM_MALOS do
|
||||
if malos[i].x == pepe.x and malos[i].y == pepe.y then
|
||||
local m = malos[i]
|
||||
if not m.atrapat and m.x == pepe.x and m.y == pepe.y then
|
||||
mort_pepe()
|
||||
return
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user