DX: skins, config.lua i chuleta del ROM
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
+22
@@ -0,0 +1,22 @@
|
||||
-- Configuracio del Pepe Runner DX
|
||||
-- Aquest fitxer es carrega amb dofile() al iniciar el joc.
|
||||
-- Si no existeix o te errors, s'usen els valors per defecte.
|
||||
-- Comenta una linia (--) per a deixar el seu valor per defecte.
|
||||
|
||||
-- ====================================================================
|
||||
-- ASPECTE GRAFIC
|
||||
-- ====================================================================
|
||||
|
||||
-- Skin: quina familia de glifs s'utilitza per a pintar el joc.
|
||||
--
|
||||
-- "custom" — Redefinim els caracters CP437 (estil del Pascal original):
|
||||
-- bloc solid █, escala ═ doble, corda ─, cara ☻ del Pepe...
|
||||
-- Es el look "fidel a l'original de 2000".
|
||||
--
|
||||
-- "native" — Usem els glifs ja dibuixats al ROM d'ascii, sense redefinir
|
||||
-- cap. Per a vore quin glif te cada codi, mira la
|
||||
-- chuleta_font_ascii.png. Estil mes fantasy console.
|
||||
--
|
||||
-- (En els dos casos el char 0 es reescriu a zeros, perque el ROM d'ascii
|
||||
-- hi te una caixa hueca que taparia tot el mapa.)
|
||||
skin = "native"
|
||||
@@ -0,0 +1,676 @@
|
||||
-- Pepe Runner DX — versio millorada del port amb QoL i extres.
|
||||
-- Carrega config.lua si existeix per a sobreescriure els valors per defecte.
|
||||
|
||||
-- ====================================================================
|
||||
-- VALORS PER DEFECTE DE CONFIGURACIO (sobreescriuibles per config.lua)
|
||||
-- ====================================================================
|
||||
skin = "custom" -- "custom" | "native" (vore config.lua per descripcio)
|
||||
|
||||
-- Codis CP437 dels sprites del joc original (de TIPOS.PAS).
|
||||
-- Els usem com a IDs logics de tipus de cel·la (i coincideixen amb el
|
||||
-- format binari dels .map). El codi de glif real per a pintar surt
|
||||
-- de la taula glif[] segons la skin activa.
|
||||
BUIT = 0
|
||||
DINERS = 36
|
||||
PEDRA = 219
|
||||
ESCALA = 205
|
||||
CORDA = 196
|
||||
BLOC1 = 176
|
||||
BLOC2 = 177
|
||||
BLOC3 = 178
|
||||
PEPE_C = 2
|
||||
MALO_C = 88
|
||||
|
||||
-- Skins: cada skin es una taula tile_id → codi_de_glif_a_pintar.
|
||||
-- "custom" usa els mateixos codis CP437 (redibuixats amb setchar).
|
||||
-- "native" remapeja als glifs que ja existeixen al ROM d'ascii
|
||||
-- (mira chuleta_font_ascii.png per a identificar-los).
|
||||
SKINS = {
|
||||
custom = {
|
||||
[BUIT]=0, [DINERS]=36, [PEDRA]=219, [ESCALA]=205, [CORDA]=196,
|
||||
[BLOC1]=176, [BLOC2]=177, [BLOC3]=178,
|
||||
[PEPE_C]=2, [MALO_C]=88,
|
||||
},
|
||||
native = {
|
||||
[BUIT]=0, [DINERS]=36, [PEDRA]=233, [ESCALA]=61, [CORDA]=45,
|
||||
[BLOC1]=216, [BLOC2]=218, [BLOC3]=220,
|
||||
[PEPE_C]=224,[MALO_C]=88,
|
||||
},
|
||||
}
|
||||
glif = SKINS.custom -- s'actualitza a init() segons la config
|
||||
|
||||
-- Colors (de TIPOS.PAS, paleta CGA — coincideix amb la d'ascii)
|
||||
COL_PEDRA = COLOR_BROWN -- 6
|
||||
COL_DINERS = COLOR_YELLOW -- 14
|
||||
COL_ESCALA = COLOR_LIGHT_GRAY -- 7
|
||||
COL_CORDA = COLOR_LIGHT_GRAY -- 7
|
||||
COL_BUIT = COLOR_BLACK -- 0
|
||||
|
||||
-- Estats (de TIPOS.PAS — son bitflags per a SelectEstat dels enemics)
|
||||
NORMAL = 0
|
||||
PUJAR = 0x01
|
||||
BAIXAR = 0x02
|
||||
CAENT = 4
|
||||
ESQUERRA = 0x10
|
||||
DRETA = 0x20
|
||||
|
||||
-- Constants del joc
|
||||
MAP_W = 40
|
||||
MAP_H = 25
|
||||
BLOC_OUT = 100 -- temps que dura un forat obert (de TIPOS.PAS)
|
||||
TICS = 6 -- frames per tick de joc (60fps / 6 = 10 Hz)
|
||||
NUM_MALOS = 3
|
||||
TEMPS_IA = 30 -- iteracions del malo entre canvis de direccio
|
||||
MALO_RATIO = 4 -- els malos van 1/4 del ritme del Pepe (com en RUNNER.PAS)
|
||||
NUM_FASES = 10 -- mapes 1..10 (el 0 esta reservat per al titol)
|
||||
VIDES_INI = 3 -- l'original arrancava amb 0 (1 vida); 3 es mes raonable
|
||||
|
||||
-- Estats del joc (maquina d'estats global)
|
||||
ESTAT_TITLE = "title"
|
||||
ESTAT_PLAYING = "playing"
|
||||
ESTAT_GAMEOVER = "gameover"
|
||||
ESTAT_ENTERNAME = "entername"
|
||||
|
||||
-- Estat global
|
||||
mapa = {} -- mapa[x][y] = { tipo=, color=, temps= }
|
||||
level = 1
|
||||
pepe = { x=19, y=23, dibuix=PEPE_C, color=COLOR_WHITE, vides=VIDES_INI, estat=NORMAL }
|
||||
malos = {}
|
||||
score = 0
|
||||
diners_pantalla = 0
|
||||
game_tic = 0
|
||||
hi_score = 0
|
||||
nom_hi_score = "AAA"
|
||||
estat_joc = ESTAT_TITLE
|
||||
estat_inici = 0
|
||||
enter_name_idx = 1
|
||||
|
||||
function definir_glifs()
|
||||
-- Char 0 sempre buit (el ROM d'ascii hi te una caixa que taparia el mapa)
|
||||
setchar(0, 0,0,0,0,0,0,0,0)
|
||||
|
||||
-- Nomes la skin "custom" redibuixa els glifs CP437. La "native" usa
|
||||
-- els que ja existeixen al ROM d'ascii (cap setchar mes).
|
||||
if skin ~= "custom" then return end
|
||||
|
||||
setchar(219, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF) -- PEDRA █
|
||||
setchar(36, 0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00) -- DINERS $
|
||||
setchar(205, 0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00) -- ESCALA ═
|
||||
setchar(196, 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00) -- CORDA ─
|
||||
setchar(176, 0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11) -- BLOC1 ░
|
||||
setchar(177, 0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55) -- BLOC2 ▒
|
||||
setchar(178, 0xBB,0xEE,0xBB,0xEE,0xBB,0xEE,0xBB,0xEE) -- BLOC3 ▓
|
||||
setchar(2, 0x7E,0x81,0xA5,0x81,0xBD,0x99,0x81,0x7E) -- PEPE ☻
|
||||
setchar(88, 0x00,0xC3,0x66,0x3C,0x18,0x3C,0x66,0xC3) -- MALO X
|
||||
end
|
||||
|
||||
-- ====================================================================
|
||||
-- SFX (l'original no tenia so — afegim els minims raonables)
|
||||
-- ====================================================================
|
||||
function sfx_coin() sound(2000, 40) end
|
||||
function sfx_dig() play("l0o2c") end
|
||||
function sfx_die() play("l1o4cl0o3bagfed") end
|
||||
function sfx_malo_die() play("l0o3ao4c") end
|
||||
function sfx_level() play("l1o4ceg") end
|
||||
function sfx_gameover() play("l1o3bal0gfedco2c") end
|
||||
|
||||
function color_de(tipo)
|
||||
if tipo == PEDRA then return COL_PEDRA end
|
||||
if tipo == DINERS then return COL_DINERS end
|
||||
if tipo == ESCALA then return COL_ESCALA end
|
||||
if tipo == CORDA then return COL_CORDA end
|
||||
return COL_BUIT
|
||||
end
|
||||
|
||||
-- Helper segur per llegir el tipus d'una cel·la (fora de mapa = pedra virtual)
|
||||
function tipo_a(x, y)
|
||||
if x < 0 or x >= MAP_W or y < 0 or y >= MAP_H then return PEDRA end
|
||||
return mapa[x][y].tipo
|
||||
end
|
||||
|
||||
function carregar_mapa(num)
|
||||
filein("maps/"..tostr(num)..".map", 0, MAP_W*MAP_H)
|
||||
diners_pantalla = 0
|
||||
for x = 0, MAP_W-1 do
|
||||
mapa[x] = {}
|
||||
for y = 0, MAP_H-1 do
|
||||
local tipo = peek(x*MAP_H + y)
|
||||
mapa[x][y] = { tipo=tipo, color=color_de(tipo), temps=-1 }
|
||||
if tipo == DINERS then diners_pantalla = diners_pantalla + 1 end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function pintar_mapa()
|
||||
for x = 0, MAP_W-1 do
|
||||
for y = 0, MAP_H-1 do
|
||||
local c = mapa[x][y]
|
||||
if c.tipo ~= BUIT then
|
||||
color(c.color, COL_BUIT)
|
||||
print(chr(glif[c.tipo]), x, y)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function pintar_pepe()
|
||||
color(pepe.color, COL_BUIT)
|
||||
print(chr(glif[pepe.dibuix]), pepe.x, pepe.y)
|
||||
end
|
||||
|
||||
-- Marca una cel·la com a forat (sols si actualment es pedra)
|
||||
function foradar(x, y)
|
||||
if tipo_a(x, y) == PEDRA then
|
||||
mapa[x][y].temps = BLOC_OUT
|
||||
end
|
||||
end
|
||||
|
||||
-- Pot Pepe cavar a esquerra/dreta? Condicions del MouPepe original:
|
||||
-- - la cel·la diagonal-baix ha de ser pedra (per a obrir-hi forat)
|
||||
-- - la cel·la lateral no pot ser pedra (per a que Pepe s'hi puga assomar)
|
||||
-- - Pepe ha d'estar en estat normal (no caent)
|
||||
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
|
||||
end
|
||||
|
||||
-- Tic de joc del Pepe: input de moviment, gravetat, recollir diners, emparedat
|
||||
function tic_pepe()
|
||||
local actual = tipo_a(pepe.x, pepe.y)
|
||||
local sotto = tipo_a(pepe.x, pepe.y+1)
|
||||
|
||||
-- Moviment vertical: Q/A (com en RUNNER.PAS, son if/else)
|
||||
if btn(KEY_Q) then
|
||||
if actual == ESCALA then pepe.y = pepe.y - 1 end
|
||||
elseif btn(KEY_A) then
|
||||
if sotto == ESCALA or sotto == BUIT or sotto == DINERS then
|
||||
pepe.y = pepe.y + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Moviment horitzontal: O/P (no es pot moure si esta caent)
|
||||
if btn(KEY_O) then
|
||||
if tipo_a(pepe.x-1, pepe.y) ~= PEDRA and pepe.estat ~= CAENT then
|
||||
pepe.x = pepe.x - 1
|
||||
end
|
||||
elseif btn(KEY_P) then
|
||||
if tipo_a(pepe.x+1, pepe.y) ~= PEDRA and pepe.estat ~= CAENT then
|
||||
pepe.x = pepe.x + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Si no passa res especial, estat = normal (gravetat pot canviar-ho mes avall)
|
||||
pepe.estat = NORMAL
|
||||
|
||||
-- Final pantalla: si arriba a la fila 1, passa al nivel seguent
|
||||
if pepe.y == 1 then
|
||||
fase_nova()
|
||||
return
|
||||
end
|
||||
|
||||
-- Emparedat: si la cel·la actual s'ha tornat pedra, Pepe mor
|
||||
if tipo_a(pepe.x, pepe.y) == PEDRA then
|
||||
mort_pepe()
|
||||
return
|
||||
end
|
||||
|
||||
-- Recollir diners
|
||||
if tipo_a(pepe.x, pepe.y) == DINERS then
|
||||
mapa[pepe.x][pepe.y].tipo = BUIT
|
||||
score = score + 1
|
||||
diners_pantalla = diners_pantalla - 1
|
||||
sfx_coin()
|
||||
end
|
||||
|
||||
-- Bordes X
|
||||
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
|
||||
actual = tipo_a(pepe.x, pepe.y)
|
||||
sotto = tipo_a(pepe.x, pepe.y+1)
|
||||
if (sotto ~= ESCALA and sotto ~= PEDRA)
|
||||
and (actual == BUIT or actual == DINERS) then
|
||||
pepe.y = pepe.y + 1
|
||||
pepe.estat = CAENT
|
||||
end
|
||||
|
||||
-- Bordes Y
|
||||
if pepe.y < 0 then pepe.y = 0 end
|
||||
if pepe.y > MAP_H-1 then pepe.y = MAP_H-1 end
|
||||
end
|
||||
|
||||
function mort_pepe()
|
||||
pepe.vides = pepe.vides - 1
|
||||
pepe.x = 19
|
||||
pepe.y = 23
|
||||
pepe.estat = NORMAL
|
||||
sfx_die()
|
||||
end
|
||||
|
||||
-- Inicialitza tot per a una nova partida (reset complet)
|
||||
function inicialitzacio()
|
||||
level = 1
|
||||
score = 0
|
||||
pepe.vides = VIDES_INI
|
||||
pepe.x = 19; pepe.y = 23; pepe.estat = NORMAL
|
||||
carregar_mapa(level)
|
||||
init_malos()
|
||||
game_tic = 0
|
||||
end
|
||||
|
||||
-- Avanca al nivell seguent (sense reset de score ni vides)
|
||||
function fase_nova()
|
||||
level = level + 1
|
||||
if level > NUM_FASES then level = 1 end
|
||||
pepe.x = 19; pepe.y = 23; pepe.estat = NORMAL
|
||||
carregar_mapa(level)
|
||||
init_malos()
|
||||
sfx_level()
|
||||
end
|
||||
|
||||
-- ====================================================================
|
||||
-- ESTATS DEL JOC (title / playing / game over / enter name)
|
||||
-- ====================================================================
|
||||
|
||||
function set_estat(nou)
|
||||
estat_joc = nou
|
||||
estat_inici = cnt()
|
||||
end
|
||||
|
||||
function temps_estat() return cnt() - estat_inici end
|
||||
|
||||
-- Records I/O. Usem io.open (estandard de Lua) en lloc de filein/fileout
|
||||
-- per a poder gestionar el cas de fitxer inexistent sense petar.
|
||||
-- Format: 6 bytes = 3 (centenes, desenes, unitats del score) + 3 (lletres nom)
|
||||
function carregar_records()
|
||||
local f = io.open("records", "rb")
|
||||
if not f then return end
|
||||
local data = f:read(6)
|
||||
f:close()
|
||||
if not data or #data < 6 then return end
|
||||
local b = { string.byte(data, 1, 6) }
|
||||
hi_score = b[1]*100 + b[2]*10 + b[3]
|
||||
-- Validar que les lletres del nom siguen imprimibles
|
||||
if b[4] >= 32 and b[4] < 127
|
||||
and b[5] >= 32 and b[5] < 127
|
||||
and b[6] >= 32 and b[6] < 127 then
|
||||
nom_hi_score = string.char(b[4], b[5], b[6])
|
||||
end
|
||||
end
|
||||
|
||||
function guardar_records()
|
||||
local f = io.open("records", "wb")
|
||||
if not f then return end
|
||||
f:write(string.char(
|
||||
flr(hi_score / 100),
|
||||
flr((hi_score % 100) / 10),
|
||||
hi_score % 10,
|
||||
string.byte(nom_hi_score, 1) or 65,
|
||||
string.byte(nom_hi_score, 2) or 65,
|
||||
string.byte(nom_hi_score, 3) or 65
|
||||
))
|
||||
f:close()
|
||||
end
|
||||
|
||||
-- Quina lletra A-Z s'ha pulsat este frame (escaneig manual amb btnp,
|
||||
-- perque ascii no exposa whichbtn() al Lua malgrat estar al ascii.h).
|
||||
function lletra_pulsada()
|
||||
for sc = KEY_A, KEY_Z do
|
||||
if btnp(sc) then
|
||||
return string.char(65 + sc - KEY_A)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- ----- TITLE -----
|
||||
function init_title()
|
||||
carregar_mapa(0) -- mapa 0 es l'art del titol
|
||||
end
|
||||
|
||||
function update_title()
|
||||
if btnp(KEY_SPACE) then
|
||||
inicialitzacio()
|
||||
set_estat(ESTAT_PLAYING)
|
||||
return
|
||||
end
|
||||
|
||||
cls()
|
||||
pintar_mapa()
|
||||
|
||||
-- "PRESS SPACE TO PLAY" parpadejant
|
||||
if flr(cnt() / 30) % 2 == 0 then
|
||||
color(COLOR_WHITE, COLOR_BLACK)
|
||||
print("PRESS SPACE TO PLAY", 10, 22)
|
||||
end
|
||||
|
||||
pintar_hud()
|
||||
end
|
||||
|
||||
-- ----- GAME OVER -----
|
||||
function update_gameover()
|
||||
-- Render congelat: ultim estat del joc + overlay "GAME OVER"
|
||||
cls()
|
||||
pintar_mapa()
|
||||
pintar_malos()
|
||||
pintar_pepe()
|
||||
|
||||
color(COLOR_LIGHT_RED, COLOR_BLACK)
|
||||
print("G A M E O V E R", 11, 12)
|
||||
|
||||
pintar_hud()
|
||||
|
||||
-- Despres de 2 segons (120 frames), transicio
|
||||
if temps_estat() > 120 then
|
||||
if score > hi_score then
|
||||
hi_score = score
|
||||
nom_hi_score = "AAA"
|
||||
enter_name_idx = 1
|
||||
set_estat(ESTAT_ENTERNAME)
|
||||
else
|
||||
init_title()
|
||||
set_estat(ESTAT_TITLE)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ----- ENTER NAME -----
|
||||
function update_entername()
|
||||
cls()
|
||||
color(COLOR_LIGHT_RED, COLOR_BLACK)
|
||||
print("NOU RECORD!", 14, 10)
|
||||
color(COLOR_YELLOW, COLOR_BLACK)
|
||||
print("SCORE "..string.format("%03d", hi_score), 15, 12)
|
||||
color(COLOR_WHITE, COLOR_BLACK)
|
||||
print("NOM: "..nom_hi_score, 16, 15)
|
||||
print("(A-Z)", 17, 17)
|
||||
|
||||
pintar_hud()
|
||||
|
||||
local lletra = lletra_pulsada()
|
||||
if lletra then
|
||||
nom_hi_score = string.sub(nom_hi_score, 1, enter_name_idx-1)
|
||||
..lletra..
|
||||
string.sub(nom_hi_score, enter_name_idx+1)
|
||||
enter_name_idx = enter_name_idx + 1
|
||||
if enter_name_idx > 3 then
|
||||
guardar_records()
|
||||
init_title()
|
||||
set_estat(ESTAT_TITLE)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ----- PLAYING -----
|
||||
function update_playing()
|
||||
-- Cavar es immediat (un sol forat per pulsacio)
|
||||
if pepe.estat == NORMAL then
|
||||
if btnp(KEY_SPACE) and pot_cavar(-1) then foradar(pepe.x-1, pepe.y+1); sfx_dig() end
|
||||
if btnp(KEY_M) and pot_cavar( 1) then foradar(pepe.x+1, pepe.y+1); sfx_dig() end
|
||||
end
|
||||
|
||||
-- Logica del joc: cada TICS frames
|
||||
if (cnt() % TICS) == 0 then
|
||||
game_tic = game_tic + 1
|
||||
tic_pepe()
|
||||
check_mort_per_malos()
|
||||
if (game_tic % MALO_RATIO) == 0 then
|
||||
tic_malos()
|
||||
check_mort_per_malos()
|
||||
end
|
||||
check_mapa()
|
||||
if pepe.vides < 0 then
|
||||
sfx_gameover()
|
||||
set_estat(ESTAT_GAMEOVER)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- Render
|
||||
cls()
|
||||
pintar_mapa()
|
||||
pintar_malos()
|
||||
pintar_pepe()
|
||||
pintar_hud()
|
||||
end
|
||||
|
||||
-- ====================================================================
|
||||
-- ENEMICS
|
||||
-- ====================================================================
|
||||
|
||||
function init_malos()
|
||||
malos = {
|
||||
{ x= 9, y=2, color=COLOR_CYAN, estat=ESQUERRA, iaclock=0, carrega={ok=false, x=0, y=0} },
|
||||
{ x=20, y=2, color=COLOR_CYAN, estat=ESQUERRA, iaclock=0, carrega={ok=false, x=0, y=0} },
|
||||
{ x=39, y=2, color=COLOR_CYAN, estat=ESQUERRA, iaclock=0, carrega={ok=false, x=0, y=0} },
|
||||
}
|
||||
end
|
||||
|
||||
function pintar_malos()
|
||||
for i = 1, NUM_MALOS do
|
||||
local m = malos[i]
|
||||
color(m.color, COL_BUIT)
|
||||
print(chr(glif[MALO_C]), m.x, m.y)
|
||||
end
|
||||
end
|
||||
|
||||
-- Tria una nova direccio per a un enemic (port de SelectEstat de RUNNER.PAS).
|
||||
-- 50% prob persegueix Pepe, 50% prob direccio aleatoria entre les valides.
|
||||
-- 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 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
|
||||
|
||||
local sestat = 0
|
||||
if nou == 0 then sestat = 10 end -- atrapat: valor que cap case reconeix
|
||||
|
||||
local pX = (m.x > pepe.x) and ESQUERRA or DRETA
|
||||
local pY = (m.y > pepe.y) and PUJAR or BAIXAR
|
||||
|
||||
if rnd(100) < 50 and (((nou & pX) == pX) or ((nou & pY) == pY)) then
|
||||
if (nou & pX) == pX then sestat = pX else sestat = pY end
|
||||
else
|
||||
local x = rnd(4)
|
||||
while sestat == 0 do
|
||||
if x == 0 and (nou & DRETA) == DRETA then sestat = DRETA
|
||||
elseif x == 1 and (nou & ESQUERRA) == ESQUERRA then sestat = ESQUERRA
|
||||
elseif x == 2 and (nou & PUJAR) == PUJAR then sestat = PUJAR
|
||||
elseif x == 3 and (nou & BAIXAR) == BAIXAR then sestat = BAIXAR
|
||||
end
|
||||
x = (x + 1) & 3
|
||||
end
|
||||
end
|
||||
|
||||
-- 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
|
||||
|
||||
return sestat
|
||||
end
|
||||
|
||||
-- Si va horitzontal i hi ha escala adalt/abaix, 80% prob s'enganxa
|
||||
function agafar_escala(m)
|
||||
if m.estat == DRETA or m.estat == ESQUERRA then
|
||||
if rnd(100) < 80 then
|
||||
if tipo_a(m.x, m.y) == ESCALA then return PUJAR
|
||||
elseif tipo_a(m.x, m.y+1) == ESCALA then return BAIXAR
|
||||
end
|
||||
end
|
||||
end
|
||||
return m.estat
|
||||
end
|
||||
|
||||
-- Mort d'un enemic (per emparedat). Respawn a (39, 1).
|
||||
-- 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.
|
||||
if m.carrega.ok then
|
||||
local c = mapa[m.carrega.x][m.carrega.y]
|
||||
c.tipo = DINERS
|
||||
c.color = COL_DINERS
|
||||
end
|
||||
m.x = 39; m.y = 1
|
||||
m.color = COLOR_CYAN
|
||||
m.estat = CAENT
|
||||
m.iaclock = 0
|
||||
m.carrega.ok = false
|
||||
m.carrega.x = 0
|
||||
m.carrega.y = 0
|
||||
sfx_malo_die()
|
||||
end
|
||||
|
||||
function tic_malos()
|
||||
for i = 1, NUM_MALOS do
|
||||
local m = malos[i]
|
||||
|
||||
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)
|
||||
|
||||
-- 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)
|
||||
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
|
||||
end
|
||||
|
||||
-- bordes X (rebot)
|
||||
if m.x < 0 then m.x = 0; m.estat = DRETA end
|
||||
if m.x > MAP_W-1 then m.x = MAP_W-1; m.estat = ESQUERRA end
|
||||
-- bordes Y (clamp)
|
||||
if m.y < 0 then m.y = 0 end
|
||||
if m.y > MAP_H-1 then m.y = MAP_H-1 end
|
||||
|
||||
-- agafar diners
|
||||
if tipo_a(m.x, m.y) == DINERS and not m.carrega.ok then
|
||||
mapa[m.x][m.y].tipo = BUIT
|
||||
m.color = COLOR_LIGHT_CYAN
|
||||
m.carrega.ok = true
|
||||
m.carrega.x = m.x
|
||||
m.carrega.y = m.y
|
||||
end
|
||||
|
||||
-- emparedat → mort
|
||||
if tipo_a(m.x, m.y) == PEDRA then
|
||||
mort_malo(m)
|
||||
end
|
||||
|
||||
m.iaclock = m.iaclock + 1
|
||||
if m.iaclock == TEMPS_IA then m.iaclock = 0 end
|
||||
end
|
||||
end
|
||||
|
||||
function check_mort_per_malos()
|
||||
for i = 1, NUM_MALOS do
|
||||
if malos[i].x == pepe.x and malos[i].y == pepe.y then
|
||||
mort_pepe()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Si Pepe ha recollit tots els diners, fa apareixer una escala a la columna 0
|
||||
-- des de la fila 1 cap avall, parant si troba pedra. (CheckMapaComplet)
|
||||
function check_mapa_complet()
|
||||
if diners_pantalla > 0 then return end
|
||||
for j = 1, MAP_H-2 do
|
||||
if mapa[0][j].tipo == PEDRA then break end
|
||||
mapa[0][j].tipo = ESCALA
|
||||
mapa[0][j].color = COL_ESCALA
|
||||
end
|
||||
end
|
||||
|
||||
-- Anima els forats: decrementa temps i cambia el tipus segons la fase
|
||||
-- (idem case statement de CheckMapa al RUNNER.PAS)
|
||||
function check_mapa()
|
||||
for x = 0, MAP_W-1 do
|
||||
for y = 0, MAP_H-1 do
|
||||
local c = mapa[x][y]
|
||||
local t = c.temps
|
||||
if t == 0 then
|
||||
c.temps = -1
|
||||
c.tipo = PEDRA
|
||||
c.color = COL_PEDRA
|
||||
elseif t == 1 or t == BLOC_OUT-1 then
|
||||
c.tipo = BLOC3; c.color = COL_PEDRA; c.temps = t - 1
|
||||
elseif t == 2 or t == BLOC_OUT-2 then
|
||||
c.tipo = BLOC2; c.color = COL_PEDRA; c.temps = t - 1
|
||||
elseif t == 3 or t == BLOC_OUT-3 then
|
||||
c.tipo = BLOC1; c.color = COL_PEDRA; c.temps = t - 1
|
||||
elseif t == 4 or t == BLOC_OUT-4 then
|
||||
c.tipo = BUIT; c.color = COL_BUIT; c.temps = t - 1
|
||||
elseif t > 0 then
|
||||
c.temps = t - 1
|
||||
end
|
||||
-- t == -1 → idle, no fer res
|
||||
end
|
||||
end
|
||||
check_mapa_complet()
|
||||
end
|
||||
|
||||
-- HUD: rotul inferior amb level/score/vides/hi-score sobre banda blava
|
||||
function pintar_hud()
|
||||
color(COLOR_LIGHT_GRAY, COLOR_BLUE)
|
||||
local blank = " "
|
||||
print(blank, 0, 25)
|
||||
print(blank, 0, 26)
|
||||
print(blank, 0, 27)
|
||||
print(" LEVEL "..string.format("%02d", level), 0, 26)
|
||||
print("SCORE "..string.format("%03d", score), 14, 26)
|
||||
print("LIVES "..tostr(pepe.vides), 28, 26)
|
||||
print("HI-SCORE "..string.format("%03d", hi_score).." "..nom_hi_score, 9, 27)
|
||||
end
|
||||
|
||||
-- Carrega config.lua si existeix. Si falta o te errors, queden els defaults.
|
||||
function carregar_config()
|
||||
pcall(dofile, "config.lua")
|
||||
end
|
||||
|
||||
function init()
|
||||
carregar_config()
|
||||
glif = SKINS[skin] or SKINS.custom
|
||||
mode(1)
|
||||
border(COLOR_BLUE)
|
||||
color(COLOR_LIGHT_GRAY, COLOR_BLACK)
|
||||
definir_glifs()
|
||||
carregar_records()
|
||||
init_title()
|
||||
set_estat(ESTAT_TITLE)
|
||||
cls()
|
||||
end
|
||||
|
||||
function update()
|
||||
if estat_joc == ESTAT_TITLE then update_title()
|
||||
elseif estat_joc == ESTAT_PLAYING then update_playing()
|
||||
elseif estat_joc == ESTAT_GAMEOVER then update_gameover()
|
||||
elseif estat_joc == ESTAT_ENTERNAME then update_entername()
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user