Вы находитесь на странице: 1из 10

Yorddy

Lua
Antes de nada, el lenguaje Lua, es un lenguaje de programacion muy versatil y potente, se a implementado un lanzador de lua, (LuaPlayer) que puede ejecutar cualquier archivo de codigo fuente escrito en Lua, uno de los aspectos mas interesantes del lua es que no hay que compilar nada, lo que hace mas facil el dessaroyo de aplicaciones, y por esta misma razon, cada programa de en lua, es su propio codigo fuente. Asi que cuando no sabemos como implementar algo, siempre podemos hechar un ojo a cualquier programa que haga una funcion parecida. El lua player es un lanzador de aplicaciones, por defecto nos lanza el Lowser, que es un Browser para lua, desde el que podremos explorar la memory y lanzar cualquier aplicacion en lua. Si introducimos el codigo de nuestro programa con el nombre script.lua en el directorio raiz del LuaPlayer, en vez del lowser ejecutara nuestro codigo, si en vez de eso, en la carpeta de aplicaciones, creamos una subcarpeta con el nombre deseado para el programa y lo introducimos en esta con el nombre de index.lua podremos lanzarlo desde el Lowser Para probar nuestro programa y evitar el tener que conectar el usb, copiar desde el ordenador, desactivar usb, arrancar el lua.... existen dos alternativas, la primera y mas comoda, es usar la version para windows del lanzador de Lua, LuaPlayer for Windows y probar nuestro codigo desde el, la manera correcta es crear un archivo de texto, con la extension .cmd que contenga la siguiente linea: luaplayer nombre_del_programa.lua, y tener tanto el .cmd, como el .lua en la carpeta del luaPlayer for windows. Muy util para experimentos en Lua puro es LuaIDE, donde puedes introducir los programas y ejecutarlos paso a paso, observando los cambios en las variables. Otra manera es descargar la version independiente de Lua (lua.exe para windows) abrir el interprete de comandos e iniciar lua.exe, donde podremos introducir expresiones en Lua como por ejemplo for i=1,10 do io.write(i .. \n) end.

Mostrando cosas por pantalla: Hola Mundo!


Bueno vamos a comenzar ya con el tutorial propiamente dicho, y como mejor que con un primer ejemplo muy basico:
-- crear un nuevo objeto de color verde = Color.new(0, 255, 0) -- mostrar el texto "hola mundo" en el offscreen screen:print(200, 100, "Hola mundo!", verde) -- volver visible el offscreen screen.flip() -- esperar infinitamente while true do screen.waitVblankStart() end Salva este archivo como script.lua en el mismo directorio de la PSP, donde esta EBOOT.PBP. Cuando arranques luaPlayer veras una imagen en negro con las letras verdes escritas Hola mundo!

La resolucion de la PSP es de 480 pixels de ancho y 272 pixels de alto. Color.new crea un nuevo objeto de color. Los argumentos son rojo, verde, azul y alpha (opcional),Que tienen un rango desde 0 hasta 255 para intensidad maxima. Esto es conocido como el modelo de color RGB. screen:print dibuja un texto en la pantalla, donde los 2 primeros argumentos son las coordenadas x e y en la pantalla, despues el texto como cadena de caracteres y un color opcional (negro por defecto). La coordenada X comienza en la derecha y la Y en la parte superior.

Manual Bsico de Lua

Yorddy
Existen dos buffers de pantalla: Uno visible y otro invisible. Todas las funciones de dibujo/escritura van al bufer no visible. Esto significa que lo que escribes no es visible hasta que llamas a screen.flip(), Que intercambia los dos buffers de pantalla. Esto es conocido como el double-buffering. Finalmente el bucle while llama a waitVblankStart en un bucle infinito. Si no escribes algo asi al final, tu script finalizara y no veras el resultado impreso en pantalla, esto es debido a que arranco desde Lowser, el GUI Lowser se mostrara y si se inicio como un script independiente la pregunta de reiniciar sera mostrada. Si no escribes la funcion de espera, pero usas un bucle infinito vacio, este generaria mucho uso de CPU, esto es debido a que la funcion da la opcion al kernel de dormir.

Animaciones
Comprender como se representan los pixeles en pantalla es importante para escribir juegos. La pantalla de la PSP, como muchas otras pantallas, tiene el mismo concepto que los antiguos tubos de imagen: Un haz de electrones comienza a barrer desde la esquina superior izquierda de la pantalla y va abanzando escaneando todas las lineas de arriba a abajo. (el amigo abismo que es electronico podra explicarlo mejor), cuando llega abajo necesita algun tiempo para volver al comienzo, esto es llamado vertical blank (vBlank), Por supuesto, en la PSP no existe realmente este haz de electrones, pero podemos pensar que funciona de esta manera, con el script "screen.waitVblankStart" hace que el programa espere hasta que comience el proximo barrido, durante esta espera, ningun pixel es escrito en la pantalla, lo que te da la oportunidad de intercambiar la screen y el offscreen para evitar parpadeos o destellos. Vamos a ver como mostrar una animacion haciendo uso del intercambio sincronizado de pantallas: --Activa el usb (esto no es realmente necesario) System.usbDiskModeActivate() --creamos un nuevo objeto de color verde green = Color.new(0, 255, 0) --variable time inicializada a cero time = 0 --pi almacena 3,14... arcotangente de 1 (radian) * 4 pi = math.atan(1) * 4 --bucle infinito while true do --limpia la pantalla al comienzo de cada barrido screen:clear() --vamos calculando el seno para cada momento time x = math.sin(pi * 2 / 360 * time) * 150 + 192.5 --mostramos hola mundo en la posicion seno(time) screen:print(x, 100, "Hello World!", green) --incrementamos tiempo time = time + 1 --volvemos a cero cuando el time supera 360 if time >= 360 then time = 0 end --esperamos al proximo escaneo screen.waitVblankStart() --intercambiamos las pantallas screen.flip() --si se pulsa start se sale del script pad = Controls.read() if pad:start() then break end end En el bucle while, primero se limpia el offscreen. Despues el texto se dibuja en la pantalla, se espera al siguente escaneo de pantalla, se intercambia el screen y el offscreen. En la PSP la velocidad de refresco es 60Hz, lo que significa que eltexto necesita 6 segundos para volver a empezar desde la misma posicion. (la funcion seno tiene un periodo de 2*pi, asi que para un periodo completo "time" necesita ir desde 0 a 360 y "time" se incrementa 60 veces por segundo, lo que significa que un periodo son 6 segundos). Finalmente se comprueba si se a pulsado start, que sale del bucle. Puedes usar este codigo como comienzo para tus propios programas. La funcion "System.usbDiskModeActivate" al comienzo activa el USB, y la comprobacion de la tecla start sale del bucle. Si cargas este programa como script.lua desde el directorio raiz del Lua player, la tecla start reiniciara el

Manual Bsico de Lua

Yorddy
programa, asi podras acceder al archivo,modificarlo con un editor de textos y reiniciarlo para ver los cambios. mientras que si lo ejecutas desde lowser te debolvera a este mismo. Ahora lo haremos con imagenes, primero copia esta imagen como "background.png" en tu PSP:

y despues esta otra como "smiley.png":

Ahora un programa para animar el smiley:


--activa el usb System.usbDiskModeActivate() --objeto de color verde green = Color.new(0, 255, 0) --variable time puesta a cero time = 0 --pi almacena 3,14.. pi = math.atan(1) * 4 --carga las imagenes(deben estar en la misma carpeta del codigo) background = Image.load("background.png") smiley = Image.load("smiley.png") while true do --coloca la imagen background en las coordenadas 0,0 screen:blit(0, 0, background, 0, 0, background:width(), background:height(), false) --calcula x e y para cada momento de time x = math.sin(pi * 2 / 250 * time) * 200 + 220.5 y = 172 - math.abs(math.sin(pi * 2 / 125 * time) * 150) --coloca smiley en las coordenadas calculadas x,y segun la funcion seno screen:blit(x, y, smiley) --varia time para tomar nuevas coordenadas time = time + 1 --vuelve a poner el ciclo a cero if time >= 500 then time = 0 end screen.waitVblankStart() screen.flip() pad = Controls.read() if pad:start() then break end end Puedes ver que la estructura general del bucle principal es muy parecida a la del ejercicio anterior. Pero en vez de llamar a "screen:clear()" se llama a "screen:blit" que dibuja una imagen de fondo, despues se llama a screen:blit"(x, y, smiley)" que dibuja otra imagen encima del fondo. Este tiene menos argumentos, esto es porque se utilizan los argumentos por defecto, lo que indica que alpha es true que indica que todos los pixeles transparentes de la imagen no son mostrados. Si vas a crear varios objetos en pantalla, seria mas rapido usar una tecnica de varias capas: Crea una imagen vacia con "Image.createEmpty" (las imagenes vacias son creadas por defecto con todos los pixeles

Manual Bsico de Lua

Yorddy
transparentes) dibuja las partes estaticas de tu juego en esta imagen y en cada bucle despues del vblank, primero dibuje el fondo en pantalla, despues la imagen con las partes estaticas y finalmente las partes dinamicas. Mira el juego de la serpiente como ejemplo de esto.

Controles
Puedes usar los controles de la PSP con la clase Controls. "Control.read()" lee el estado actual de un boton determinado, como por ejemplo la cruz. El resultado sera true si el boton cruz es pulsado, y falso en cualquier otro caso. analogX y analogY retorna la posicion del pad analogico. El rango va desde -128 a 127, pero los valores por debajo de 32 pueden ser producidos aunque el pad este centrado. En el ejemplo de un programa de dibujo, usamos el analogico para mover el cursor, mantener pulsada la cruz dibujara una linea, select guardara la imagen y start terminara.
red = Color.new(255, 0, 0); black = Color.new(0, 0, 0); white = Color.new(255, 255, 255);   canvas = Image.createEmpty(480, 272) canvas:clear(white)   brush = {} eraser = {}   x0 = 0 y0 = 0 x1 = 0 y1 = 0   while true do   pad = Controls.read()   dx = pad:analogX()   if math.abs(dx) > 32 then     x0 = x0 + dx / 64   end   dy = pad:analogY()   if math.abs(dy) > 32 then     y0 = y0 + dy / 64   end   if pad:cross() then     canvas:drawLine(x0, y0, x1, y1, black)   end   x1 = x0   y1 = y0   screen:blit(0, 0, canvas, 0, 0, canvas:width(), canvas:height(), false)   screen:drawLine(x1 - 5, y1, x1 + 5, y1, red)   screen:drawLine(x1, y1 - 5, x1, y1 + 5, red)   screen.waitVblankStart()   screen.flip()   if pad:start() then     break   end   if pad:select() then     screen:save("screenshot.tga")   end end

En lugar del comando drawLine con el color rojo para la cruz, puedes usar screen:blit(x1, y1, yourCursorImage) para dibujar una imagen con tu cursor y puedes eliminar el drawLine cuando se pulsa la cruz, si no quieres implementar un programa de dibujo. Puedes detener la repeticion en los controles aadiendo la siguiente linea de codigo.
Manual Bsico de Lua

Yorddy
function controls()   pad = Controls.read()   if pad ~= oldPad then     --yourcodehere   end   oldPad = pad end

Sonido
Lua Player soporta sonidos en formato WAV y musica en los formatos MOD: UNI, IT, XM, S3M, MOD, MTM, STM, DSM, MED, FAR, ULT y 669. Reproducir musica es simple: Por ejemplo, para reproducir el archivo stranglehold.xm (composed by Jeroen Tel, (C) 1995 Maniacs of Noise) para el juego de la serouente (Jeroen permite que la usemos en este juego), que esta incluido en la distrubucion estandart de Lua Player, solamente llama a "Music.playFile("stranglehold.xm", true)". Si lo especificas "false" en vez de "true", el sonido no se repetira. Llama "Music.stop()" para detener la musica.

Entrada y salida de archivos


La entrada y salida de es una funcion estandard. Un ejemplo simple del juego de la serpiente es la carga y salvado de la puntuacion.
red = Color.new(255, 0, 0); black = Color.new(0, 0, 0); white = Color.new(255, 255, 255); canvas = Image.createEmpty(480, 272) canvas:clear(white) brush = {} eraser = {} x0 = 0 y0 = 0 x1 = 0 y1 = 0 while true do pad = Controls.read() dx = pad:analogX() if math.abs(dx) > 32 then x0 = x0 + dx / 64 end dy = pad:analogY() if math.abs(dy) > 32 then y0 = y0 + dy / 64 end if pad:cross() then canvas:drawLine(x0, y0, x1, y1, black) end x1 = x0 y1 = y0 screen:blit(0, 0, canvas, 0, 0, canvas:width(), canvas:height(), false) screen:drawLine(x1 - 5, y1, x1 + 5, y1, red) screen:drawLine(x1, y1 - 5, x1, y1 + 5, red) screen.waitVblankStart() screen.flip() if pad:start() then break end if pad:select() then screen:save("screenshot.tga") end end

Manual Bsico de Lua

Yorddy
Donde "high" es una variable global, que contiene el record actual. Mira Manual Lua para ms detalles de que parmetros puedes usar para las funciones de lectura/Escritura. Para un ejemplo mas complicado se podr

Ultima entrega de LUA


Ahora vamos a escribir un juego simple en 2d, puedes editar mapas para distintos niveles. En C64 habia conjuntos de 254 caracteres de 8x8 pixeles que heran los bloques constructores del mapa. Podemos salvar este "bloque constructor" en una imagen, tambien conocido como tile set, o azulejo. Aqui hay un ejemplo para un juego de tuneles, tipo Pac-man:

Las baldosas:

Vamos a numerarlas de la 'a' a la 'p': abcd efgh ijkl mnop


Ahora podemos dibujar un mapa con ellas y mostrarlo con un poco de codigo Lua: System.usbDiskModeActivate() tiles = Image.load("tiles.png") map = { "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "mmeaaaaaaaaaaaaaaaaaaaaaaaafmm", "mmdpnnnnnnnnnnnnnnnnnnnnnnpbmm", "mmdokcccccclnkccccccccccclnbmm", "mmdojaaaaafdnbmmmmmmmmmmmdnbmm", "mmdooooooobdnbmmmmmmmmmmmdnbmm", "mmdokccclobdnbmmmmmmmmmmmdnbmm", "mmdobmmmdobdnbmmmmmmmmmmmdnbmm", "mmdobmmmdobdnjaaaaaaaaaafdnbmm", "mmdobmmmdpbdnnnnnnnnnnnnbdnbmm", "mmdobmmmhcghcccccccccclnbdnbmm", "mmdojaaaaaaaaaaaaaaaaainjinbmm", "mmdpnnnnnnnnnnnnnnnnnnnnnnpbmm", "mmhccccccccccccccccccccccccgmm", "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm" } function drawTile(tile, x, y) local tileX = math.mod(tile, 4) local tileY = math.floor(tile / 4) screen:blit(16 * x, 16 * y, tiles, 17 * tileX + 1, 17 * tileY + 1, 16, 16, false) end while true do pad = Controls.read() if pad:start() then break end screen:clear() for y = 1, 17 do line = map[y] for x = 1, 30 do tile = string.byte(line, x) - string.byte("a")

Manual Bsico de Lua

Yorddy
end drawTile(tile, x - 1, y - 1) end screen.waitVblankStart() screen:flip()

end

Este es el resultado:

El modo USB hace mas facil editar el mapa, porque te permite abrir tu editor salvar y recargarlo pulsando "start" Ahora necesitamos alguna animacion:

El programa que muestra el jugador y le permite moverse, comiendo puntos y aadiendo puntuacion: -- cargar imagenes tiles = Image.load("tiles.png") figure = Image.load("figure.png") -- el mapa mapSource = { "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "mmeaaaaaaaaaaaaaaaaaaaaaaaafmm", "mmdpnnnnnnnnnnnnnnnnnnnnnnpbmm", "mmdokcccccclnkccccccccccclnbmm", "mmdojaaaaafdnbmmmmmmmmmmmdnbmm", "mmdooooooobdnbmmmmmmmmmmmdnbmm", "mmdokccclobdnbmmmmmmmmmmmdnbmm", "mmdobmmmdobdnbmmmmmmmmmmmdnbmm", "mmdobmmmdobdnjaaaaaaaaaafdnbmm", "mmdobmmmdpbdnnnnnnnnnnnnbdnbmm", "mmdobmmmhcghcccccccccclnbdnbmm", "mmdojaaaaaaaaaaaaaaaaainjinbmm", "mmdpnnnnnnnnnnnnnnnnnnnnnnpbmm", "mmhccccccccccccccccccccccccgmm", "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm", "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmm" } -- imagen en el offsreen, donde dibujamos el mapa board = Image.createEmpty(480, 272) -- dibuja una baldosa en el mapa: function drawTile(tile, x, y) tile = string.byte(tile, 1) - string.byte("a") local tileX = math.mod(tile, 4) local tileY = math.floor(tile / 4) board:blit(16 * x, 16 * y, tiles, 17 * tileX + 1, 17 * tileY + 1, 16, 16, false) end

Manual Bsico de Lua

Yorddy
-- copia el mapa fuente a un vector para facilitar el acceso y dibujarlo en el offscreen map = {} for y = 1, 17 do line = mapSource[y] map[y] = {} for x = 1, 30 do tile = string.sub(line, x, x) map[y][x] = tile drawTile(tile, x - 1, y - 1) end end -- posicion actual del jugador playerX = 6 playerY = 14 -- imagen actual de animacion del jugador animation = 0 -- 1 = incremento en la animacion, -1: decremento animationDirection = 1 -- contador de freno de la animacion animationSlowDown = 0 -- control de la velocidad de movimiento. a speedStep == 0, el -- ultimo movimiento sera evaluado, los otros movimientos solamente seran -- salvados speedStep = 0 -- ultima direccion del pad dx = 0 dy = 0 -- puntuacion actual score = 0 -- color del texto white = Color.new(255, 255, 255) while true do -- lectura del pad pad = Controls.read() if pad:start() then -- salirse al lowser / reiniciar aplicacion dependiendo de como se cargara este break end if speedStep == 0 then -- salva la posicion anterior del jugador oldPlayerX = playerX oldPlayerY = playerY -- aadir ultimo movimiento playerX = playerX + dx playerY = playerY + dy -- comprobar el nuevo valdosin newTile = map[playerY][playerX]

Manual Bsico de Lua

Yorddy
-- si la posicion no esta permitida, reestablece la posicion anterior if newTile ~= "n" and newTile ~= "p" and newTile ~= "o" then playerX = oldPlayerX playerY = oldPlayerY end -if if if S esta en una baldosa que puede ser comida,la come: newTile == "p" then score = score + 5 end newTile == "o" then score = score + 1 end newTile == "p" or newTile == "o" then -- pone el fondo map[playerY][playerX] = "n" -- dibuja el fondo drawTile("n", playerX - 1, playerY - 1)

end

-- reestablece la ultima posicion dx = 0 dy = 0 else -- comprobar el pad if pad:up() then dy = -1 elseif pad:down() then dy = 1 elseif pad:left() then dx = -1 elseif pad:right() then dx = 1 end

end

-- incrementar el contador de velocidad de pasos speedStep = speedStep + 1 if speedStep == 5 then speedStep = -1 end -- dibuja en el offscreen screen:blit(0, 0, board, 0, 0, board:width(), board:height(), false) -- dibuja la animacion actual del jugador screen:blit((playerX - 1) * 16 - 4, (playerY - 1) * 16 - 4, figure, 1 + 25 * animation, 1, 24, 24) -- calcula la proxima imagen de animacion animationSlowDown = animationSlowDown + 1 if animationSlowDown == 3 then animationSlowDown = 0 animation = animation + animationDirection if animation == 4 then animationDirection = -1 elseif animation == 0 then animationDirection = 1 end end -- imprime puntuacion screen:print(10, 260, "Score: " .. score, white) -- espera el proximo refresco de pantalla para dibujar el offscreen screen.waitVblankStart()

Manual Bsico de Lua

Yorddy
end screen:flip()

Notar que las baldosas son dibujadas en el offscreen, debido a que dibujar multiples baldosas es mas lento que dibujar una imagen del mismo tamao que todas las baldosas. Con este truco podemos alcanzar los 60fps. Algunas modificaciones posibles son algunos oponentes, usar un fondo transparente para los azulejos y dibujar estos sobre un fondo predefinido, o usar multiples mascaras con multiples fondos o mapas que coordi

Manual Bsico de Lua

Вам также может понравиться