fase 3: gravetat, escales, cordes i forats
This commit is contained in:
+148
-43
@@ -1,5 +1,5 @@
|
|||||||
-- Pepe Runner — port a ascii/Lua del joc original en Turbo Pascal (JailDesigner, 2000)
|
-- Pepe Runner — port a ascii/Lua del joc original en Turbo Pascal (JailDesigner, 2000)
|
||||||
-- Fase 1: render estatic d'un mapa
|
-- Fase 3: gravetat, escales, cordes, forats
|
||||||
|
|
||||||
-- Codis CP437 dels sprites del joc original (de TIPOS.PAS)
|
-- Codis CP437 dels sprites del joc original (de TIPOS.PAS)
|
||||||
BUIT = 0
|
BUIT = 0
|
||||||
@@ -20,44 +20,36 @@ COL_ESCALA = COLOR_LIGHT_GRAY -- 7
|
|||||||
COL_CORDA = COLOR_LIGHT_GRAY -- 7
|
COL_CORDA = COLOR_LIGHT_GRAY -- 7
|
||||||
COL_BUIT = COLOR_BLACK -- 0
|
COL_BUIT = COLOR_BLACK -- 0
|
||||||
|
|
||||||
-- Mida del mapa (del joc original)
|
-- Estats del Pepe (com en TIPOS.PAS)
|
||||||
MAP_W = 40
|
NORMAL = 0
|
||||||
MAP_H = 25
|
CAENT = 4
|
||||||
|
|
||||||
-- Estat
|
-- Constants del joc
|
||||||
mapa = {} -- mapa[x][y] = { tipo=, color=, temps= }
|
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)
|
||||||
|
|
||||||
|
-- Estat global
|
||||||
|
mapa = {} -- mapa[x][y] = { tipo=, color=, temps= }
|
||||||
level = 1
|
level = 1
|
||||||
pepe = { x=19, y=23, dibuix=PEPE_C, color=COLOR_WHITE, vides=0, estat=0 }
|
pepe = { x=19, y=23, dibuix=PEPE_C, color=COLOR_WHITE, vides=0, estat=NORMAL }
|
||||||
|
score = 0
|
||||||
|
diners_pantalla = 0
|
||||||
|
|
||||||
function definir_glifs()
|
function definir_glifs()
|
||||||
-- Cel·la buida (sobreescrivim el glif 0 del ROM, que no es buit)
|
|
||||||
setchar(BUIT, 0,0,0,0,0,0,0,0)
|
setchar(BUIT, 0,0,0,0,0,0,0,0)
|
||||||
|
|
||||||
-- Pedra (█) — bloc solid
|
|
||||||
setchar(PEDRA, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF)
|
setchar(PEDRA, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF)
|
||||||
|
|
||||||
-- Diners ($) — signe dolar classic
|
|
||||||
setchar(DINERS, 0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00)
|
setchar(DINERS, 0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00)
|
||||||
|
|
||||||
-- Escala (═) — doble linia horitzontal
|
|
||||||
setchar(ESCALA, 0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00)
|
setchar(ESCALA, 0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x00)
|
||||||
|
|
||||||
-- Corda (─) — linia horitzontal simple
|
|
||||||
setchar(CORDA, 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00)
|
setchar(CORDA, 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00)
|
||||||
|
setchar(BLOC1, 0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11)
|
||||||
-- Blocs degradats (per al fade dels forats)
|
setchar(BLOC2, 0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55)
|
||||||
setchar(BLOC1, 0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11) -- ░ light
|
setchar(BLOC3, 0xBB,0xEE,0xBB,0xEE,0xBB,0xEE,0xBB,0xEE)
|
||||||
setchar(BLOC2, 0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55) -- ▒ medium
|
|
||||||
setchar(BLOC3, 0xBB,0xEE,0xBB,0xEE,0xBB,0xEE,0xBB,0xEE) -- ▓ dark
|
|
||||||
|
|
||||||
-- Pepe (cara feliç tipus CP437 char 2 ☻)
|
|
||||||
setchar(PEPE_C, 0x7E,0x81,0xA5,0x81,0xBD,0x99,0x81,0x7E)
|
setchar(PEPE_C, 0x7E,0x81,0xA5,0x81,0xBD,0x99,0x81,0x7E)
|
||||||
|
|
||||||
-- Enemic — una 'X' marcada
|
|
||||||
setchar(MALO_C, 0x00,0xC3,0x66,0x3C,0x18,0x3C,0x66,0xC3)
|
setchar(MALO_C, 0x00,0xC3,0x66,0x3C,0x18,0x3C,0x66,0xC3)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Retorna el color associat a un tipus de cel·la
|
|
||||||
function color_de(tipo)
|
function color_de(tipo)
|
||||||
if tipo == PEDRA then return COL_PEDRA end
|
if tipo == PEDRA then return COL_PEDRA end
|
||||||
if tipo == DINERS then return COL_DINERS end
|
if tipo == DINERS then return COL_DINERS end
|
||||||
@@ -66,16 +58,21 @@ function color_de(tipo)
|
|||||||
return COL_BUIT
|
return COL_BUIT
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Carrega un mapa des d'un fitxer .map (1000 bytes, column-major: byte[x*25+y])
|
-- Helper segur per llegir el tipus d'una cel·la (fora de mapa = pedra virtual)
|
||||||
-- Estrategia: filein() a l'adreca 0 (sobreescriu char_screen), llegim amb peek()
|
function tipo_a(x, y)
|
||||||
-- a una taula Lua, i despres fem cls() per netejar la pantalla.
|
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)
|
function carregar_mapa(num)
|
||||||
filein("maps/"..tostr(num)..".map", 0, MAP_W*MAP_H)
|
filein("maps/"..tostr(num)..".map", 0, MAP_W*MAP_H)
|
||||||
|
diners_pantalla = 0
|
||||||
for x = 0, MAP_W-1 do
|
for x = 0, MAP_W-1 do
|
||||||
mapa[x] = {}
|
mapa[x] = {}
|
||||||
for y = 0, MAP_H-1 do
|
for y = 0, MAP_H-1 do
|
||||||
local tipo = peek(x*MAP_H + y)
|
local tipo = peek(x*MAP_H + y)
|
||||||
mapa[x][y] = { tipo=tipo, color=color_de(tipo), temps=-1 }
|
mapa[x][y] = { tipo=tipo, color=color_de(tipo), temps=-1 }
|
||||||
|
if tipo == DINERS then diners_pantalla = diners_pantalla + 1 end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -97,32 +94,140 @@ function pintar_pepe()
|
|||||||
print(chr(pepe.dibuix), pepe.x, pepe.y)
|
print(chr(pepe.dibuix), pepe.x, pepe.y)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Pepe pot entrar a una cel·la si no es pedra (de moment).
|
-- Marca una cel·la com a forat (sols si actualment es pedra)
|
||||||
-- Mes endavant afegirem regles d'escala, cuerda, gravetat, etc.
|
function foradar(x, y)
|
||||||
function pot_entrar(x, y)
|
if tipo_a(x, y) == PEDRA then
|
||||||
if x < 0 or x >= MAP_W or y < 0 or y >= MAP_H then return false end
|
mapa[x][y].temps = BLOC_OUT
|
||||||
return mapa[x][y].tipo ~= PEDRA
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function mou_pepe()
|
-- Pot Pepe cavar a esquerra/dreta? Condicions del MouPepe original:
|
||||||
-- Tecles originals: Q=amunt, A=avall, O=esquerra, P=dreta
|
-- - la cel·la diagonal-baix ha de ser pedra (per a obrir-hi forat)
|
||||||
if btnp(KEY_Q) and pot_entrar(pepe.x, pepe.y-1) then pepe.y = pepe.y - 1 end
|
-- - la cel·la lateral no pot ser pedra (per a que Pepe s'hi puga assomar)
|
||||||
if btnp(KEY_A) and pot_entrar(pepe.x, pepe.y+1) then pepe.y = pepe.y + 1 end
|
-- - Pepe ha d'estar en estat normal (no caent)
|
||||||
if btnp(KEY_O) and pot_entrar(pepe.x-1, pepe.y) then pepe.x = pepe.x - 1 end
|
function pot_cavar(dx)
|
||||||
if btnp(KEY_P) and pot_entrar(pepe.x+1, pepe.y) then pepe.x = pepe.x + 1 end
|
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
|
||||||
|
|
||||||
|
-- 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
|
||||||
|
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
|
||||||
|
|
||||||
|
-- De moment, mort = respawn (vides i game over van en la Fase 5)
|
||||||
|
function mort_pepe()
|
||||||
|
pepe.vides = pepe.vides - 1
|
||||||
|
pepe.x = 19
|
||||||
|
pepe.y = 23
|
||||||
|
pepe.estat = NORMAL
|
||||||
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
function init()
|
function init()
|
||||||
mode(1) -- 40x30 chars, color per cel·la
|
mode(1)
|
||||||
border(COLOR_BLUE)
|
border(COLOR_BLUE)
|
||||||
color(COLOR_LIGHT_GRAY, COLOR_BLACK)
|
color(COLOR_LIGHT_GRAY, COLOR_BLACK)
|
||||||
definir_glifs()
|
definir_glifs()
|
||||||
carregar_mapa(level)
|
carregar_mapa(level)
|
||||||
cls() -- neteja despres del filein (que ha escrit a char_screen)
|
cls()
|
||||||
end
|
end
|
||||||
|
|
||||||
function update()
|
function update()
|
||||||
mou_pepe()
|
-- 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) end
|
||||||
|
if btnp(KEY_M) and pot_cavar( 1) then foradar(pepe.x+1, pepe.y+1) end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Logica del joc: cada TICS frames
|
||||||
|
if (cnt() % TICS) == 0 then
|
||||||
|
tic_pepe()
|
||||||
|
check_mapa()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Render: cada frame
|
||||||
cls()
|
cls()
|
||||||
pintar_mapa()
|
pintar_mapa()
|
||||||
pintar_pepe()
|
pintar_pepe()
|
||||||
|
|||||||
Reference in New Issue
Block a user