Hello, can someone translate this code to Naalaa so I can have it as a base template? Thanks in advance.
Code:
-------------------------------------------------
-- CONSTANTES DE ESTADO
-------------------------------------------------
local STATE_MENU = 1
local STATE_PLAYING = 2
local STATE_GAMEOVER = 3
-------------------------------------------------
-- VARIABLES GLOBALES DEL JUEGO
-------------------------------------------------
local gameState = STATE_MENU
local width, height
local stars = {}
local defaultFont, titleFont
-- Variables del jugador
local player = {
x = 0, y = 0,
width = 50, height = 30,
speed = 300,
shootCooldown = 0,
lives = 2,
invincibleTime = 0
}
-- Variables de juego
local bullets = {}
local enemies = {}
local score = 0
local level = 1
local enemiesDestroyed = 0
local enemySpeedBase = 100
local enemySpawnRate = 1.0
local enemySpawnTimer = 0
-------------------------------------------------
-- LOVE CALLBACKS
-------------------------------------------------
function love.load()
width = love.graphics.getWidth()
height = love.graphics.getHeight()
loadFonts()
createStars()
end
function love.update(dt)
updateStars(dt)
if gameState == STATE_PLAYING then
updateGame(dt)
end
end
function love.draw()
drawStars()
if gameState == STATE_MENU then
drawMenu()
elseif gameState == STATE_PLAYING then
drawGame()
elseif gameState == STATE_GAMEOVER then
drawGameOver()
end
end
function love.keypressed(key)
if key == "return" or key == "kpenter" then
if gameState == STATE_MENU then
startGame()
elseif gameState == STATE_GAMEOVER then
gameState = STATE_MENU
end
end
end
-------------------------------------------------
-- FUNCIONES DE INICIALIZACIÓN
-------------------------------------------------
function loadFonts()
defaultFont = love.graphics.newFont(14)
titleFont = love.graphics.newFont(24)
love.graphics.setFont(defaultFont)
end
function createStars()
stars = {}
for i = 1, 100 do
table.insert(stars, {
x = math.random(0, width),
y = math.random(0, height),
speed = math.random(50, 150),
size = math.random(1, 3)
})
end
end
function startGame()
-- Reiniciar jugador
player.x = width / 2 - 25
player.y = height - 60
player.width = 50
player.height = 30
player.speed = 300
player.shootCooldown = 0
player.lives = 2
player.invincibleTime = 0
-- Reiniciar listas
bullets = {}
enemies = {}
-- Reiniciar puntuación y nivel
score = 0
level = 1
enemiesDestroyed = 0
-- Reiniciar spawn
enemySpeedBase = 100
enemySpawnRate = 1.0
enemySpawnTimer = 0
gameState = STATE_PLAYING
end
-------------------------------------------------
-- FUNCIONES DE UPDATE
-------------------------------------------------
function updateGame(dt)
updatePlayer(dt)
updateBullets(dt)
updateEnemies(dt)
handleSpawning(dt)
end
function updateStars(dt)
for _, star in ipairs(stars) do
star.y = star.y + star.speed * dt
if star.y > height then
star.y = 0
star.x = math.random(0, width)
end
end
end
function updatePlayer(dt)
-- Movimiento
if love.keyboard.isDown("left", "a") then
player.x = player.x - player.speed * dt
end
if love.keyboard.isDown("right", "d") then
player.x = player.x + player.speed * dt
end
-- Limitar al área de juego
player.x = math.max(0, math.min(width - player.width, player.x))
-- Cooldown de disparo
if player.shootCooldown > 0 then
player.shootCooldown = player.shootCooldown - dt
end
-- Tiempo de invencibilidad
if player.invincibleTime > 0 then
player.invincibleTime = player.invincibleTime - dt
end
-- Disparar
if love.keyboard.isDown("space") and player.shootCooldown <= 0 then
table.insert(bullets, {
x = player.x + player.width/2 - 2.5,
y = player.y,
width = 5,
height = 10,
speed = 500
})
player.shootCooldown = 0.25
end
end
function updateBullets(dt)
for i = #bullets, 1, -1 do
local b = bullets[i]
b.y = b.y - b.speed * dt
if b.y < -10 then
table.remove(bullets, i)
end
end
end
function updateEnemies(dt)
local currentSpeed = enemySpeedBase + (level * 25)
for i = #enemies, 1, -1 do
local e = enemies[i]
e.y = e.y + currentSpeed * dt
local hit = false
-- Colisión bala vs enemigo
for j = #bullets, 1, -1 do
if checkCollision(bullets[j], e) then
table.remove(bullets, j)
hit = true
score = score + 10
enemiesDestroyed = enemiesDestroyed + 1
if enemiesDestroyed % 10 == 0 then
level = level + 1
end
break
end
end
if hit then
table.remove(enemies, i)
elseif player.invincibleTime <= 0 and checkCollision(e, player) then
table.remove(enemies, i)
player.lives = player.lives - 1
player.invincibleTime = 2
if player.lives <= 0 then
gameState = STATE_GAMEOVER
end
elseif e.y > height then
table.remove(enemies, i)
end
end
end
function handleSpawning(dt)
enemySpawnTimer = enemySpawnTimer - dt
if enemySpawnTimer <= 0 then
spawnEnemy()
enemySpawnTimer = enemySpawnRate
end
end
function spawnEnemy()
local width = 40
table.insert(enemies, {
x = math.random(0, width - width),
y = -50,
width = width,
height = 30
})
end
-------------------------------------------------
-- FUNCIONES DE DIBUJO
-------------------------------------------------
function drawStars()
love.graphics.setColor(1, 1, 1)
for _, star in ipairs(stars) do
love.graphics.circle("fill", star.x, star.y, star.size)
end
end
function drawMenu()
love.graphics.setColor(0, 0, 0, 0.5)
love.graphics.rectangle("fill", 0, 0, width, height)
love.graphics.setColor(1, 1, 1)
love.graphics.setFont(titleFont)
love.graphics.printf("INICIA JUEGO", 0, 200, width, "center")
love.graphics.setFont(defaultFont)
love.graphics.printf("Pulsa ENTER", 0, 280, width, "center")
end
function drawGame()
drawPlayer()
drawBullets()
drawEnemies()
drawUI()
end
function drawPlayer()
if player.invincibleTime > 0 and math.floor(player.invincibleTime * 10) % 2 ~= 0 then
return
end
love.graphics.setColor(0, 1, 0)
love.graphics.polygon("fill",
player.x + player.width / 2, player.y,
player.x, player.y + player.height,
player.x + player.width, player.y + player.height)
end
function drawBullets()
love.graphics.setColor(0, 1, 1)
for _, b in ipairs(bullets) do
love.graphics.rectangle("fill", b.x, b.y, b.width, b.height)
end
end
function drawEnemies()
love.graphics.setColor(1, 0, 0)
for _, e in ipairs(enemies) do
love.graphics.rectangle("fill", e.x, e.y, e.width, e.height)
end
end
function drawUI()
love.graphics.setColor(1, 1, 1)
love.graphics.print("Puntos: " .. score, 10, 10)
love.graphics.print("Fase: " .. level, 10, 30)
love.graphics.print("Vidas: " .. player.lives, 10, 50)
end
function drawGameOver()
love.graphics.setColor(0, 0, 0, 0.7)
love.graphics.rectangle("fill", 0, 0, width, height)
love.graphics.setColor(1, 0, 0)
love.graphics.setFont(titleFont)
love.graphics.printf("GAME OVER", 0, 200, width, "center")
love.graphics.setFont(defaultFont)
love.graphics.setColor(1, 1, 1)
love.graphics.printf("Puntuación: " .. score, 0, 260, width, "center")
end
-------------------------------------------------
-- FUNCIONES UTILITARIAS
-------------------------------------------------
function checkCollision(a, b)
return a.x < b.x + b.width and
a.x + a.width > b.x and
a.y < b.y + b.height and
a.y + a.height > b.y
end
Code:
' -------------------------------------------------
' CONSTANTES DE ESTADO
' -------------------------------------------------
constant STATE_MENU = 1
constant STATE_PLAYING = 2
constant STATE_GAMEOVER = 3
' -------------------------------------------------
' VARIABLES GLOBALES DEL JUEGO (declaradas como visible)
' -------------------------------------------------
visible gameState = STATE_MENU
visible screenWidth = 800
visible screenHeight = 600
visible dt = 0.016 ' Simulando 60 FPS aprox (1/60)
' Variables del jugador
visible player_x = 0
visible player_y = 0
visible player_w = 50.0
visible player_h = 30.0
visible player_speed = 300.0
visible player_shootCooldown = 0.0
visible player_lives = 2
visible player_invincibleTime = 0.0
' Variables de juego
visible score = 0
visible level = 1
visible enemiesDestroyed = 0
visible enemySpeedBase = 100.0
visible enemySpawnRate = 1.0
visible enemySpawnTimer = 0.0
' -------------------------------------------------
' POOLS DE OBJETOS (arrays globales)
' -------------------------------------------------
visible MAX_STARS = 100
visible star_x
visible star_y
visible star_speed
visible star_size
visible MAX_BULLETS = 50
visible bullet_x
visible bullet_y
visible bullet_w = 5.0
visible bullet_h = 10.0
visible bullet_speed = 500.0
visible bullet_active
visible MAX_ENEMIES = 50
visible enemy_x
visible enemy_y
visible enemy_w = 40.0
visible enemy_h = 30.0
visible enemy_active
' Inicialización de arrays (después de declararlos como visible)
star_x = fill(0, MAX_STARS)
star_y = fill(0, MAX_STARS)
star_speed = fill(0, MAX_STARS)
star_size = fill(0, MAX_STARS)
bullet_x = fill(0, MAX_BULLETS)
bullet_y = fill(0, MAX_BULLETS)
bullet_active = fill(0, MAX_BULLETS)
enemy_x = fill(0, MAX_ENEMIES)
enemy_y = fill(0, MAX_ENEMIES)
enemy_active = fill(0, MAX_ENEMIES)
' -------------------------------------------------
' CONFIGURACIÓN INICIAL Y BUCLE PRINCIPAL
' -------------------------------------------------
set window "Space Shooter", screenWidth, screenHeight
set redraw off
createStars()
' Bucle Principal (Game Loop)
do
' Calcular físicas / lógica
updateStars()
if gameState = STATE_MENU then
if keydown(KEY_RETURN, 1) then
startGame()
endif
elseif gameState = STATE_PLAYING then
updateGame()
elseif gameState = STATE_GAMEOVER then
if keydown(KEY_RETURN, 1) then
gameState = STATE_MENU
wait 200 ' Pequeña pausa para no saltar directo al juego
endif
endif
' Dibujado general
set color 0, 0, 0
draw rect 0, 0, screenWidth, screenHeight, true ' Limpiar fondo
drawStars()
if gameState = STATE_MENU then
drawMenu()
elseif gameState = STATE_PLAYING then
drawGame()
elseif gameState = STATE_GAMEOVER then
drawGameOver()
endif
redraw
fwait 60 ' Pausa para mantener 60 frames por segundo
until keydown(KEY_ESCAPE, 1) ' Salir cuando se presione ESCAPE
' -------------------------------------------------
' FUNCIONES DE INICIALIZACIÓN
' -------------------------------------------------
function createStars()
for i = 0 to MAX_STARS - 1
star_x[i] = rnd(0, screenWidth)
star_y[i] = rnd(0, screenHeight)
star_speed[i] = rnd(50, 150)
star_size[i] = rnd(1, 3)
next
endfunc
function startGame()
' Reiniciar jugador
player_x = screenWidth / 2 - 25
player_y = screenHeight - 60
player_lives = 2
player_shootCooldown = 0.0
player_invincibleTime = 0.0
' Reiniciar pools
for i = 0 to MAX_BULLETS - 1
bullet_active[i] = 0
next
for i = 0 to MAX_ENEMIES - 1
enemy_active[i] = 0
next
' Reiniciar puntuación y nivel
score = 0
level = 1
enemiesDestroyed = 0
enemySpeedBase = 100.0
enemySpawnRate = 1.0
enemySpawnTimer = 0.0
gameState = STATE_PLAYING
endfunc
' -------------------------------------------------
' FUNCIONES DE UPDATE
' -------------------------------------------------
function updateGame()
updatePlayer()
updateBullets()
updateEnemies()
handleSpawning()
endfunc
function updateStars()
for i = 0 to MAX_STARS - 1
star_y[i] = star_y[i] + star_speed[i] * dt
if star_y[i] > screenHeight then
star_y[i] = 0
star_x[i] = rnd(0, screenWidth)
endif
next
endfunc
function updatePlayer()
' Movimiento - flechas y teclas WASD
if keydown(KEY_LEFT) or keydown(KEY_A) then
player_x = player_x - player_speed * dt
endif
if keydown(KEY_RIGHT) or keydown(KEY_D) then
player_x = player_x + player_speed * dt
endif
' Limitar al área de juego
if player_x < 0 then player_x = 0
if player_x > screenWidth - player_w then player_x = screenWidth - player_w
' Timers
if player_shootCooldown > 0.0 then
player_shootCooldown = player_shootCooldown - dt
endif
if player_invincibleTime > 0.0 then
player_invincibleTime = player_invincibleTime - dt
endif
' Disparar - barra espaciadora (se mantiene KEY_SPACE para disparar)
if keydown(KEY_SPACE) and player_shootCooldown <= 0.0 then
for i = 0 to MAX_BULLETS - 1
if bullet_active[i] = 0 then
bullet_x[i] = player_x + player_w / 2 - bullet_w / 2
bullet_y[i] = player_y
bullet_active[i] = 1
player_shootCooldown = 0.25
break
endif
next
endif
endfunc
function updateBullets()
for i = 0 to MAX_BULLETS - 1
if bullet_active[i] = 1 then
bullet_y[i] = bullet_y[i] - bullet_speed * dt
if bullet_y[i] < -10.0 then
bullet_active[i] = 0
endif
endif
next
endfunc
function updateEnemies()
currentSpeed = enemySpeedBase + (level * 25)
for i = 0 to MAX_ENEMIES - 1
if enemy_active[i] = 1 then
enemy_y[i] = enemy_y[i] + currentSpeed * dt
hit = 0
' Colisión bala vs enemigo
for j = 0 to MAX_BULLETS - 1
if bullet_active[j] = 1 then
if checkCollision(bullet_x[j], bullet_y[j], bullet_w, bullet_h, enemy_x[i], enemy_y[i], enemy_w, enemy_h) = 1 then
bullet_active[j] = 0
hit = 1
score = score + 10
enemiesDestroyed = enemiesDestroyed + 1
if enemiesDestroyed % 10 = 0 then
level = level + 1
endif
break
endif
endif
next
' Resolución de colisiones
if hit = 1 then
enemy_active[i] = 0
elseif player_invincibleTime <= 0.0 and checkCollision(enemy_x[i], enemy_y[i], enemy_w, enemy_h, player_x, player_y, player_w, player_h) = 1 then
enemy_active[i] = 0
player_lives = player_lives - 1
player_invincibleTime = 2.0
if player_lives <= 0 then
gameState = STATE_GAMEOVER
endif
elseif enemy_y[i] > screenHeight then
enemy_active[i] = 0
endif
endif
next
endfunc
function handleSpawning()
enemySpawnTimer = enemySpawnTimer - dt
if enemySpawnTimer <= 0.0 then
spawnEnemy()
enemySpawnTimer = enemySpawnRate
endif
endfunc
function spawnEnemy()
for i = 0 to MAX_ENEMIES - 1
if enemy_active[i] = 0 then
enemy_x[i] = rnd(0, screenWidth - enemy_w)
enemy_y[i] = -50.0
enemy_active[i] = 1
break
endif
next
endfunc
' -------------------------------------------------
' FUNCIONES DE DIBUJO
' -------------------------------------------------
function drawStars()
set color 255, 255, 255
for i = 0 to MAX_STARS - 1
' En Nala se usa draw ellipse para círculos/elipses
draw ellipse star_x[i], star_y[i], star_size[i], star_size[i], true
next
endfunc
function drawMenu()
set color 255, 255, 255
set caret screenWidth / 2 - 60, 200
write "INICIA JUEGO"
set caret screenWidth / 2 - 70, 280
write "Pulsa ENTER"
endfunc
function drawGame()
drawPlayer()
drawBullets()
drawEnemies()
drawUI()
endfunc
function drawPlayer()
' Parpadeo por invencibilidad
if player_invincibleTime > 0.0 then
if (int(player_invincibleTime * 10) % 2) <> 0 then
return
endif
endif
set color 0, 255, 0
' Dibujar la nave como un rectángulo verde
draw rect player_x, player_y, player_w, player_h, true
endfunc
function drawBullets()
set color 0, 255, 255
for i = 0 to MAX_BULLETS - 1
if bullet_active[i] = 1 then
draw rect bullet_x[i], bullet_y[i], bullet_w, bullet_h, true
endif
next
endfunc
function drawEnemies()
set color 255, 0, 0
for i = 0 to MAX_ENEMIES - 1
if enemy_active[i] = 1 then
draw rect enemy_x[i], enemy_y[i], enemy_w, enemy_h, true
endif
next
endfunc
function drawUI()
set color 255, 255, 255
set caret 10, 10
write "Puntos: " + str(score)
set caret 10, 30
write "Fase: " + str(level)
set caret 10, 50
write "Vidas: " + str(player_lives)
endfunc
function drawGameOver()
set color 255, 0, 0
set caret screenWidth / 2 - 40, 200
write "GAME OVER"
set color 255, 255, 255
set caret screenWidth / 2 - 70, 260
write "Pulsa ENTER"
set caret screenWidth / 2 - 50, 290
write "Puntuacion: " + str(score)
endfunc
' -------------------------------------------------
' FUNCIONES UTILITARIAS
' -------------------------------------------------
function checkCollision(ax, ay, aw, ah, bx, by, bw, bh)
if ax < bx + bw and ax + aw > bx and ay < by + bh and ay + ah > by then
return 1
endif
return 0
endfunc