Trasteando con el Lua Player de Saturn (Tutorial) »  Mostrar los mensajes de    a     

SEGASaturno - Saturn, SEGA y Videojuegos


Desarrollo - Trasteando con el Lua Player de Saturn (Tutorial)



Indiket [ 13 Mayo 2014, 11:55 PM ]
Título del mensajeRe: Trasteando con el Lua Player de Saturn (Tutorial)
Gracias Wesker, ese era jeje.

Para que os animéis un poco, algo de homebrew Saturnero que encontré: http://vieille.merde.free.fr/
Son juegos programados directamente en SGL pero ya aviso que no es un camino de rosas! xD


FacundoARG [ 14 Mayo 2014, 03:09 AM ]
Título del mensajeRe: Trasteando Con El Lua Player De Saturn (Tutorial)
Indiket escribió: [Ver mensaje]

Sabéis si Rockin-B publica los códigos fuentes de los ports? Dónde se puede obtener ese wrapper, aunque sea con SGL y
no libyaul? Sería interesante ver que libs usó y cómo lo hizo, para tener ideas!!!


Indiket, el wrapper esta publicado en segaxtreme. Es el que vbt usó con el Wofl3D, le envié un mensaje privado hace 1 año más o menos y nunca me contestó.

Fijate si tenes suerte en compilarlo, no parece difícil pero no tengo mucho tiempo.


Ryo Suzuki [ 16 Mayo 2014, 02:15 PM ]
Título del mensajeRe: Trasteando con el Lua Player de Saturn (Tutorial)
Indiket escribió: [Ver mensaje]
Que interesante es el USB Data Link!! Ryo, sabes si es fácil obtenerlo? Vale para todos los Action Replay?? Me interesaría tener uno ya!!!


Es facil. Vienes a verme y te lo dejo junto a un Action Replay de los antiguos que tiene puerto para conectarlo.

Quiero que el bueno de Indiket se meta en Saturn, este hombre es un crack de los ports, etc...

FacundoARG escribió: [Ver mensaje]

Indiket, el wrapper esta publicado en segaxtreme. Es el que vbt usó con el Wofl3D, le envié un mensaje privado hace 1 año más o menos y nunca me contestó.

Fijate si tenes suerte en compilarlo, no parece difícil pero no tengo mucho tiempo.


Tenemos que mirar lo del SDL Wrapper a fondo. Facundo enviale un privado desde aqui mismo si puedes, que el bueno de vbt anda por aqui por el foro y he hablado con el hace poco.

Bueno, sigo con mis tutoriales. ¿Que pensabais que os iba a dejar en paz?



Más estructuras de control: while

Hemos visto y usado estructuras de control como el if. Ahora vamos a ver otra que es el buqle while cuyo propósito es repetir un bloque de código mientras una condición se mantenga verdadera.

Imaginate, por poner un ejemplo practico de la vida real, que tienes un juego de segunda mano para vender y piensas "por menos de 10 euros no lo vendo". Varios amigos te van haciendo ofertas, te doy 3 euros, te doy 7, te doy...

Entonces llega uno que te ofrece 11 leuros y automaticamente se lo vendes. O sea que mientras(while) que no te ofrezcan al menos 10 euros tu no lo soltabas

Pues esto es lo mismo que hace el comando while en Lua. Te mete en un bucle en el que se ejecuta un bloque de codigo hasta que no se cumpla esa condicion.

Citar:
- while loop

while condition do
block
end


Vamos a verlo con un caso practico con el Lua Player de Saturn. He vuelto a perpetrar un codigo de los mios, aqui lo teneis:

Código: [Ocultar] [Seleccionar]
--/***************************************************
--
-- WHILE SAMPLE SATURNO TUTORIAL
--
--***************************************************/

local variable_numerica = 1

local variable_saltolinea = 4

slInitSystem(TV_320x240,NULL,1)

slPrint("- EJEMPLO DE WHILE -", 12, 1)


while variable_numerica<10 do

slPrint(variable_numerica, 3, variable_saltolinea)
variable_numerica = variable_numerica + 1
variable_saltolinea = variable_saltolinea + 2

end


slPrint("Ryo Suzuki para www.segasaturno.com", 3, 25)

while true do slSynch() end


Generamos la iso como siempre y lo probamos en el emulador. Nos aparece esto:

while

Ha funcionado. Le hemos dicho que vaya imprimiendo una variable numerica en pantalla y que esa variable se vaya incrementando +1 cada vez y la vaya mostrando en pantalla en ese proceso, MIENTRAS sea menor de 10. Cuando sea mayor o igual a 10 ya el bucle del while deja de ejecutarse y en este caso el programa termina.

Vamos a ver el codigo comentado para que quede mas claro y explicar las instrucciones y como lo he montado:

Código: [Ocultar] [Seleccionar]
--/***************************************************
--
-- WHILE SAMPLE SATURNO TUTORIAL
--
--***************************************************/

local variable_numerica = 1 -- creamos la variable que vamos a imprimir en pantalla y vamos a ir incrementando hasta que llega a 10

local variable_saltolinea = 4 -- esto es una variable extra que no se va a ver pero nos va a servir para que imprima cada vez la variable anterior en una linea diferente porque si no no veriamos como se incrementra en pantalla (seria instantaneo a nuestros ojos)

slInitSystem(TV_320x240,NULL,1)

slPrint("- EJEMPLO DE WHILE -", 12, 1)


while variable_numerica<10 do -- comienzo de la estructura de control while, le estamos diciendo como veis que mientras la variable numerica sea menor de 10 que haga el siguiente bucle

slPrint(variable_numerica, 3, variable_saltolinea) -- *comienzo del bucle, imprime la variable con el valor que tenga en ese momento, el 3 son tres espacios en la linea que le toque, la variable salto de linea es en la linea de la pantalla que la queremos (empezara en la 4)
variable_numerica = variable_numerica + 1 -- incrementamos la variable numerica en uno, cada vez le sumamos uno en este bucle
variable_saltolinea = variable_saltolinea + 2 -- incrementamos la variable salto de linea dos, para que cada vez imprima la variable numerica dos lineas mas abajo y no se pise con la anterior impresion en pantalla *fin del bucle

end -- fin del while


slPrint("Ryo Suzuki para www.segasaturno.com", 3, 25)

while true do slSynch() end


Creo que habra quedado bastante claro. Como el if el while nos puede servir de mucho a la hora de programar cualquier cosa que hagamos. Luego le doy una vuelta de tuerca a este mismo ejemplo si puedo, que voy mal de tiempo ahora mismo y me tengo que ir a comer.

Un saludo y que no se anime tanta gente a probar estos tutoriales y a trastear con Lua que estoy desbordado de preguntas


Indiket [ 18 Mayo 2014, 11:46 PM ]
Título del mensajeRe: Trasteando con el Lua Player de Saturn (Tutorial)
Mientras Ryo se prepara para la siguiente clase de programación 101, os comunico que he estado estos días trasteando con la libyaul

LibYaul es una nueva librería para programar en Saturn, con la diferencia que es 100% opensource! Y eso atrae mucho amigos, es como el KOS de Dreamcast!!

https://github.com/ijacquez/libyaul

Conseguí compilar mi tool-chain saturnera, la librería y el ejemplo gracias a la ayuda del mismo Piratero ;) . En los próximos días pondré un nuevo hilo con todos los detalles para que os la podáis compilar y algunas capturas interesantes ^.^


Raizing [ 19 Mayo 2014, 08:00 PM ]
Título del mensajeRe: Trasteando Con El Lua Player De Saturn (Tutorial)
Muy buen curro Ryo.

A raíz de ver este hilo me he puesto a leer las documentación que todo kiski tiene sobre la SBL y la SGL (los manuales i tal) y me estaban dando ganas de toquetear xD.

Indiket, tengo ganas de ese post... el LibYaul pinta bien, en qué estado estaba? es que creo que desde 2012 no había mucho movimiento, no?

Saludos,


Indiket [ 19 Mayo 2014, 11:47 PM ]
Título del mensajeRe: Trasteando con el Lua Player de Saturn (Tutorial)
Cierto Raizing, no hubo mucho movimiento. Pero recientemente contacte con Piratero y me comentó que hizo muchos cambios internos. Algunas cosas están rotas, pero pinta muy bien!!

Mañana redacto el tutorial, espero que os guste!


Indiket [ 20 Mayo 2014, 10:56 PM ]
Título del mensajeRe: Trasteando con el Lua Player de Saturn (Tutorial)
Lo prometido es deuda Raizing!! Aquí tenéis el tuto ;)

http://www.segasaturno.com/portal/t...370.html#p78370


Ryo Suzuki [ 24 Mayo 2014, 03:19 PM ]
Título del mensajeRe: Trasteando Con El Lua Player De Saturn (Tutorial)
Raizing escribió: [Ver mensaje]
Muy buen curro Ryo.
A raíz de ver este hilo me he puesto a leer las documentación que todo kiski tiene sobre la SBL y la SGL (los manuales i tal) y me estaban dando ganas de toquetear xD.


A ver si os animáis. Yo voy haciendo mis pruebas tratando de aprender un poco.


El azar de Lua

Si antes vimos la función azar de la librería de SEGA slRandom() que nos devolvía un número al azar con bastantes decimales, ahora he estado echándole un ojo a esta misma función pero desde Lua. Es la ventaja que tenemos con este Lua Player tan particular para Saturn, en ocasiones podemos usar cosas de las librerías oficiales de SEGA, pero también podemos hacer uso del lenguaje Lua en esta particular mezcla que es el Lua Player.

La función para azar es math.random
Citar:

math.random ([m [, n]])

Esta función es un interface a rand, generador simple de números pseudo-aleatorios proporcionado por el ANSI C. (Sin garantías de sus propiedades estadísticas.)

Cuando se invoca sin argumentos devuelve un número pseudoaleatorio real uniforme en el rango [0,1). Cuando se invoca con un número entero m, math.random devuelve un número pseudoaleatorio entero uniforme en el rango [1, m]. Cuando se invoca con dos argumentos m y n enteros, math.random devuelve un número pseudoaleatorio entero uniforme en el rango [m, n].


Imaginemos que necesitamos un número entero al azar del 1 al 10. Creo que debería usar el comando:

Código: [Ocultar] [Seleccionar]
math.random(1,10)


Lo pruebo haciendo un pequeño programa que genere e imprima en pantalla varios números al azar, como ya sabemos y obtengo esto:

azar_saturn_lua

No os pego el código simple porque ya sabéis hacerlo. Como veis, ha funcionad. Lo de pseudoaleatorio al final va a ser verdad porque parece ser que tiende a repetir números... cosas del azar?

Con Lua, en este sentido, vemos que tenemos más flexibilidad, ya que con el de la librería de SEGA el rango de azar era solo entre 0.0 y el 1 con 14 decimales y ahora podemos definir nosotros más el azar a nuestras necesidades:

azar500

Ahora le he dicho math.random(0,500) y me ha generado números al azar desde el 0 al 500 -ambos incluidos-, también como habréis visto se me ha olvidado editar el título del programa... soy un programador chapucero


Funciones no usadas por SEGA en la Saturn

Quizás pensáis que es osado que yo que no tengo ni idea de estos temas crea haber descubierto algo así, pero me parece a mi que es cierto. Por lo que he estado viendo hay varias funcionalidadades de la Saturn que estoy comprobando que nunca se han usado en ningún juego comercial a pesar de que la consola era capaz de ello.

Una de ellas es la posibilidad de en los juegos multilenguaje no obligarte a seleccionar el idioma y por el contrario coger esa información de cómo tenemos configuradad nuestra máquina y mostrar el idioma correspondiente, como hicieron consolas posteriores como la Dreamcast, PlayStation 2, etc...

Podríamos determinar que la Saturn se adelantó a su tiempo en esta posibilidad, aunque nunca se llegó a usar

Esto se podría hacer con el comando slGetLanguage() que obtiene el número de lenguaje almacenado en la bios de la consola. Con eso y con algo como el IF que hemos aprendido ya podríamos derivar a nuestro programa -o juego comercial, como decía- a que muestre un idioma u otro en pantalla según nos interese.

Pero no solo eso, podemos con un programa a "obligar" a nuestra Saturn a configurarse con un lenguaje concreto que nos convenga. Por ejemplo tenemos la consola configurada en inglés y podemos forzarla a que se ponga en español.

Esto se haría con este comando de la librería SEGA:

Citar:
slSetLanguage(numero del lenguaje que queramos)


Por ejemplo, yo creo un pequeño programa que ejecute: slSetLanguage(3)
Con esta orden pondría la bios de la consola en castellano, con independencia de qué idioma tuviese configurado. Como digo, algo que ningún juego comercial ha hecho y por lo tanto una funcionalidad no usada en la Saturn...

El problema es que en cuanto hacemos reset se va a tomar viento, ya que no hemos almacenado este cambio. Edito mi código con otro comando nuevo que sirve para precisamente eso, que no es otro que:

Citar:
slSetSmpcMemory()


Le estoy diciendo que tras cambiar a castellano guarde los cambios del estado como está en ese momento la SmpcMemory que es toda la info de configuración de la bios.

Os pongo el programita para que lo veais:

Código: [Ocultar] [Seleccionar]
slInitSystem(TV_320x240,NULL,1)


slPrint("Lenguaje de la Bios en castellano", 3, 1)

slSetLanguage(3) -- pone la bios de la Saturn en spanish, que es el numero 3
slPrint("- OK, ahora es SPANISH", 3, 15)

slSetSmpcMemory() -- guarda la bios tal y como esta en este momento, en este caso guardaria el cambio de lenguaje que hemos hecho
slPrint("- OK, guardo los cambios", 3, 17)

slPrint("Aunque hagas reset o ", 3, 20)
slPrint("apagues la consola sera asi.", 3, 21)

slPrint("Ryo Suzuki de www.segasaturno.com", 3, 27)


while true do slSynch() end


Le hemos dicho que poga el lenguaje 3, que es el castellano. He comprobado que el 4 es el italiano y el 5 el japonés. Los demás podéis probadlos vosotros mismos...

Ejecuto el tema y sale esto:

language_saturn_dev

Podeis comprobadlo en el emulador que efectivamente funciona. Hace lo que dice incluso en consola real, a no ser -claro está- que no tengáis pila en vuestra consola

Podeis configurar la bios en el SSF con cualquier idioma diferente al español y comprobar que tras ejecutar esta iso que generemos y volver a la bios del emulador, la consola queda configurada en castellano.

Un pequeño ejemplo de que hay funciones de las librerías de SEGA que nunca fueron usadas en la vida comercial de la SEGA Saturn.

Eso es todo por el momento, ya seguiré con más "lecciones" si os apetecen. Un saludo!!



P.D: De momento continuaré con el Lua Player hasta que pueda avanzar más y pueda migrar al YAUL que ha posteado el bueno de Indiket

P.D2: Os pongo otra página con buena info sobre Lua y varios samples que la estoy consultando en busca de info: http://lua-users.org


Wesker [ 24 Mayo 2014, 05:23 PM ]
Título del mensajeRe: Trasteando con el Lua Player de Saturn (Tutorial)
Ryo, la función de que la consola detecte el idioma de la bios y configure el arranque de los juegos de acuerdo a ese idioma sí que se llegó a utilizar. Sin ir más lejos, hay juegos como las versiones PAL de Panzer Dragoon y Exhumed que se inician directamente en castellano si la consola detecta el castellano como idioma de la bios.

Incluso hay juegos que sólo salieron en Japón como The King of Fighters '96 que se inicia directamente en castellano (o pseudo-castellano según se interprete las traducciones chusqueras que hacía SNK ) si la bios está en castellano, o Final Fight Revenge que se inicia en inglés si detecta en la bios cualquier idioma que no sea japonés.

Hay muchos más, sobre todo los típicos juegos multi-idioma que son de third parties. Se podría hacer el típico listado para tenerlos referenciados.


Ryo Suzuki [ 25 Mayo 2014, 11:20 PM ]
Título del mensajeRe: Trasteando con el Lua Player de Saturn (Tutorial)
Veis lo que me pasa a veces? Que soy un bocazas

Es cierto que haciendo memoria sí que conocía al menos el Panzer Dragoon que lo tengo japonés y europeo en mi colección y que efectivamente tenía que haber recordado que es un juego que hace uso de esta funcionalidad (el PAL, of course).

Además, como estuvimos hablando luego, creo que la Saturn es la consola pionera en este sentido de tener una bios configurable con opciones como idioma, fecha, hora, etc; y que guarda esa información por medio de una pila. Si estoy confundido y hubo otra antes que alguien me desmienta esta info...

En cuanto a lo de funciones no usadas, en mi defensa diré -y tras la metedura de pata- que slSetLanguage sí que estoy casi seguro que no lo usa ningún juego. De hecho no tiene mucho sentido que un juego te cambie esa configuración, o al menos yo personalmente no le veo razón de ser... pero en fin, que el comando ahí está....


Bueno, sigo avanzando un poco más en mis devaneos con el Lua Player. Voy a abordar una lección que acabo de improvisar hace unos minutos. Hoy toca el turno de:


Detectando el pad y periféricos conectados

Para esto me he documentado mirando este hilo del amigo y maestro saturnero FacundoARG. Ahí explicaba como controlar un cuadrado blanco con el mando bajo Saturn Orbit y me ha servido de mucho ya que adaptando un poco en ocasiones la sintaxis a este Lua Player he conseguido que me funcione, al menos hasta cierto punto.

Cito al bueno de Facundo que explicó muy bien como administra la Saturn este tema:

Citar:
Primero vamos a entender como se manejan los pads.
El SMPC(System Manager & Pheriperal Control) Sistema de administración y Control de Periféricos, tiene como una de sus tantas tareas controlar nuesotros joysticks.

Tenemos dos constantes Per_Connect1 y Per_Connect2 que contienen el estado de los periféricos/puertos 1 y 2 respectivamente.
El resultado/valor que se puede obtener en todo momento (lo asigna el SMPC) son:

0 Si hay algo conectado al puerto.
1 Si no esta conectado algún pad al puerto.


Con esta valiosa información y ajustando un poco los condicionales a Lua, lo pongo en práctica:

Código: [Ocultar] [Seleccionar]
slInitSystem(TV_720x576,NULL,1)


slPrint("- SAMPLE DE ESTADO DE PUERTOS 1 Y 2 -", 2, 2)

if Per_Connect1()==0 then slPrint("-Puerto 1: Nada conectado", 2, 6) else slPrint("-Puerto 1: Algo conectado", 2, 6)
end

if Per_Connect2()==1 then slPrint("-Puerto 2: Algo conectado", 2, 8)
else slPrint("-Puerto 2: Nada conectado", 2, 8)
end


slPrint("www.segasaturno.com", 10, 25)

while true do slSynch() end

Creamos la iso correspondiente como siempre, ejectuamos en el el emulador y obtenemos este resultado:

01_mandos

Parece haber funcionado bien. Vamos a cercionárnos de que sea correcto y esté detectando bien. Configuramos en emulador y en el puerto dos le decimos, por enchufar algo virtual, que tenemos metido un ratón de Saturn:

02_mandos

Volvemos a ejecutar la iso en el Yabause para comprobar que todo haya ido bien:

03_mandos

Como dirían los ingleses, so far so good. Volvamos a las enseñanzas saturneras del master FacundoARG:

Citar:
Por otro lado tenemos Smpc_Peripheral[] que es un array, donde el indice del arreglo/vector es el número de pad. Que van desde el 0 al 11.
Recuerden que podemos conectar 12 joysticks con el multitap; 6 por cada puerto.

Tenemos 3 tipos de datos en la estructura del array Smpc_Peripheral[].
data (es el metodo conocido como Pressed que significa persionado constantemente ó mantener presionado)

push (es el metodo conocido como press, que significa que ejecuta la accion apenas presionamos el boton)

pull (es el metodo conocido como release, que significa que se ejecuta la accion una vez soltado el boton que hayamos presionado)


Los botones:

PER_DGT_ST
PER_DGT_KU
PER_DGT_KR
PER_DGT_KD
PER_DGT_KL

PER_DGT_TA
PER_DGT_TB
PER_DGT_TC

PER_DGT_TX
PER_DGT_TY
PER_DGT_TZ

PER_DGT_TL
PER_DGT_TR


Supongo que PER_DGT significa Peripheral_Didital, TA = Trigger A, KU = Keypad Up , ST = Start .


Genial, vamos a añadir esto a nuestro pequeño programa que hemos creado antes para detectar si los puertos uno y dos tenían algo conectado.

Imaginemos que queremos detectar y que nos informe en pantalla si estamos pulsando el boton A del mando 1.

A Lua, yo lo adaptaría así:

Citar:
if bit.band(data, PER_DGT_TA) == 0 then slPrint("Estas pulsando A en el mando 1", 5, 12)
end


Cambia ligeramente de como lo hacía Facundo en el Saturn Orbit. Lo he mirado de los ejemplos de Lua que usan la gestión y detección del mando. Por lo que veo necesitamos hacer también esto antes de dar ese condicional para detectar que botón estamos pulsando:

Citar:
id,ext,data = Smpc_Peripheral(0)


Por lo que entiendo son como tres variables asociadas al system managament y al periferical control. Con esto y la linea que he puesto arriba podemos detectar en este caso si estamos pulsando A (fijaos que hemos puesto PER_DGT_TA) y poner un mensaje en pantalla en cuanto lo hagas.


Integrando con todo lo aprendido

Voy a poneros un código que he hecho usando la detección del mando y pulsación de un botón concreto y a la vez tratándolo de unificar con todo lo que he ido aprendiendo anteriormente (variables, condicionales, bucles whiles, etc). Por lo que estoy intuyendo en el tema este de la programación es importante ir adquiriendo conocimientos y tener la capacidad de integrarlos todos y hacer buen uso de ellos.

Ahí va mi nuevo programa:

Código: [Ocultar] [Seleccionar]
slInitSystem(TV_320x240,NULL,1)

local bucle = 3

local variablepad = 0.25

local variableautoincremento = 0

slPrint("- VARIABLES LOCAS Y TAL -", 7, 1)


while bucle < 30000000000 do

slPrint("-Esta variable va subiendo", 1, 6)
slPrint(" al pulsar A", 1, 7)

slPrint(variablepad, 20, 7)

slPrint("-Sin embargo esta se incrementa ", 1, 9)
slPrint(" por la puta cara", 1, 10)

slPrint(variableautoincremento, 20, 10)

variableautoincremento = variableautoincremento + 0.02

id,ext,data = Smpc_Peripheral(0)
if bit.band(data, PER_DGT_TA) == 0 then variablepad = variablepad + 0.25
end
if bit.band(data, PER_DGT_TA) == 0 then slPrint("----Pulsando----", 10, 16) else slPrint("--No Pulsando---", 10, 16)
end

slPrint("Ryo Suzuki de www.segasaturno.com", 3, 25)
end

while true do slSynch() end


Si lo miráis detalladamente no es muy complicado, ¿no? Luce tal que así:

variables_locas

Como veis y podéis probar si compiláis este código y creáis la correspondiente iso, este pequeño programa muestra dos variables en pantalla. Una de ellas se incrementa cuando pulsamos el bóton A, mientras que la otra va subiendo de valor sin que hagamos nada.

También podéis comprobar que tenemos un "chivato" que nos indica si estamos o no pulsado el bóton, para decorar un poco.

Creo que es bastante entendible, pero aun así lo comento que puede venir bien por si alguno se pierde:

Código: [Ocultar] [Seleccionar]
slInitSystem(TV_320x240,NULL,1)

local bucle = 3 -- creo esta variable que la voy a usar para crear el bucle principal del while del programa

local variablepad = 0.25 -- esta es la variable que se va a incrementar con la pulsación del pad

local variableautoincremento = 0 -- ahora defino la variable que como su nombre indica se auntoincrementa automaticamente

slPrint("- VARIABLES LOCAS Y TAL -", 7, 1)


while bucle < 30000000000 do -- bucle del while principal, hasta que no llega a un numero muy alto haz esto...

slPrint("-Esta variable va subiendo", 1, 6)
slPrint(" al pulsar A", 1, 7)

slPrint(variablepad, 20, 7) -- muestro en pantalla la variable del pad

slPrint("-Sin embargo esta se incrementa ", 1, 9)
slPrint(" por la puta cara", 1, 10)

slPrint(variableautoincremento, 20, 10) -- muestro en pantalla la variable que va subiendo de valor sola

variableautoincremento = variableautoincremento + 0.02 -- comoe esta dentro del bucle a cada pasada la variable autoincremento va a subir 0.02

id,ext,data = Smpc_Peripheral(0) -- necesito hacer esto que no se bien lo que es para detectar el pad, es valido solo para el mando uno porque hemos puesto 0, como hemos explicado antes

if bit.band(data, PER_DGT_TA) == 0 then variablepad = variablepad + 0.25 -- Si pulsamos A, la variable pad de incrementea 0.25
end -- esto es el end de este if, ¿queda claro?

if bit.band(data, PER_DGT_TA) == 0 then slPrint("----Pulsando----", 10, 16) else slPrint("--No Pulsando---", 10, 16) -- aqui lo que hago es usando el mismo condicional además de sumar 0.25 como ha hecho antes que imprima si estas pulsando o no (gracias al uso del else que ya hemos aprendido). Tengo que tener cuidado con la colocación del texto para que uno "pise" a otro y quede bien
end -- end de este if, NOTA: esto se podria hacer con un If combinado que a la vez que sume imprima, seria algo asi if con then "haz esto" y "haz esto otro tambien", como no se hacerlo aun o no encuentro la sintaxis correcta tengo que usar dos ifs :(

slPrint("Ryo Suzuki de www.segasaturno.com", 3, 25) -- A lo Cristiano Ronaldo
end -- Para los despistados este es el end de nuestro bucle principal while

while true do slSynch() end


No está nada mal la fusión de conocimientos que he aplicado. Sin embargo tiene una pequeña pega. Si lo probáis vereis que pulsando A, aunque lo hagamos muy ligeramente la variable se incrementa de golpe bastante -como 1 y pico cada vez-, o sea no podemos ver el incremento de 0.25 a cada pequeña pulsación. Esto no sé como afinarlo bien, aunque supongo que se debe poder hacer... Si teneis idea o podéis ayudarme, ya sabéis...

En fin, que eso es todo por hoy. Añado en esta ocasión la iso de este último sample por si os apetece probarlo y no os animáis a compilarlo por vosotros mismos.

Pronto +


Ryo Suzuki [ 10 Junio 2014, 07:03 PM ]
Título del mensajeRe: Trasteando con el Lua Player de Saturn (Tutorial)
Después del arrollador éxito (es lo que esperaba, jeje) sigo con este tema.

Antes de nada os comentaré dos cosas. La primera es este framework para hacer juegos 2D con Lua que acabo de descubrir:

https://www.love2d.org/

En principio no nos sirve para nada con el Lua de la Saturn, pero ahí lo dejo para investigarlo porque puede ser interesante.

También, como documentación y os lo pongo ahora todo junto que luego me lío con el rollo y se me olvida, es muy bueno esto:

http://www.rockin-b.de/saturn/satur...ameTutorial.htm

Podríamos decir que es la biblia de la programación en Sega Saturn de la mano del maestro The Rockin'-B'. Aunque es para Orbit, muchos conceptos son aplicables a lo que podamos hacer con Lua. Esto lo deberíamos guardar a buen recaudo para consultar en cualquier momento.

Y bueno, voy a la lección de hoy que se me hace tarde...


¿Donde están las subrutinas?

A medida que iba haciendo mis pruebas y chapucillas para intentar aprender algo de programación en Saturn con este Lua Player una duda se iba planteando en mi cabeza. Hasta ahora hemos hecho cosas como imprimir texto en pantalla, manejar movidas con condicionales y actuar en consecuencia, trato con variables, detectar qué pasaba con el mando, etc... El que caso es que siempre pensé qué sucedería cuando el código se fuese complicando un poco más y a su vez fuese creciendo.

Es decir, recordando los buenos tiempos de BASIC para los veteranos del lugar, ¿dónde están las rutinas y subrutinas? Trozos de código a los que llamabas con GOTO O GOSUB y luego retornabas con RETURN. O sea, partes de código que se encarguen de una cosa en concreto y que podamos llamar desde el programa principal a nuestro gusto.

Para que me entendáis con un ejemplo práctico, imaginaos que tenemos una porción de código -como hemos visto en los ejemplos que he ido creando- que se encargue de comprobar si una variables es mayor que tal número, u otro que chequeé si hay un mando conectado en el puerto 2, o quizás una parte de código que genere dos valores al azar y se los asigne a una variable...

El meollo es, vamos a suponer que esto lo necesitamos hacer varias veces en nuestro programa. Cada vez que necesitemos realizar estas operaciones tendremos que volver a escribir/colocar ese código con los comandos correspondientes... ¿No sería mejor llamar a esa rutina cuando nos haga falta y que lo haga las veces que sea necesario y cuando nos convenga manejándolo nosotros?

En BASIC, y creo que en otros lenguajes antiguos, a esto se llamaba rutinas. En Lua, se llaman funciones (queda más cool) y vamos a explicarlo con un pequeño y sencillo ejemplo que he creado:

Código: [Ocultar] [Seleccionar]
slInitSystem(TV_320x240,NULL,1)


function PRUEBA()
slPrint("Esto es la funcion PRUEBA", 1, 1)
end

function MIERDA()
slPrint("Esto es la funcion MIERDA", 2, 3)
end

function NOSEUSA()
slPrint("Esto es la funcion NOSEUSA", 3, 5)
end

PRUEBA()
MIERDA()

while true do slSynch() end


Ejecutamos en el emu como ya sabemos y obtenemos algo tan espectacular como esto:

funciones_lua_saturn

Puede parecer una tontería pero nos resuelve el problema que teníamos antes y nos dará mucha vida en el futuro. Podemos invocar a rutinas que tengamos hechas cuando queramos y acceder a ellas cuantas veces las necesitemos.

Además podemos dividir nuestro código en diferentes parte más definidas y a la hora de abordar lo que queramos hacer será mucho mejor y más organizado.

Lo que hemos realizado en este ejemplo que he puesto es definir tres sencillas funciones con su código específico y luego hemos llamado solo a dos de ellas.

Lo comento aunque salte a la vista:

Código: [Ocultar] [Seleccionar]
slInitSystem(TV_320x240,NULL,1) -- Inicia el sistema SGL


function PRUEBA() -- Definimos la función llamada PRUEBA
slPrint("Esto es la funcion PRUEBA", 1, 1) -- Esto para no liaros es el código simple de esta función, podría ser mucho más complicado, ya veréis más adelante...
end -- Finalizamos lo que contiene esa función

function MIERDA() -- Ahora defino otra función que se llama MIERDA
slPrint("Esto es la funcion MIERDA", 2, 3) -- Lo mismo, la función tiene un print sencillo
end -- Hasta aquí llega esta función

function NOSEUSA() -- Definimos una función que no vamos a usar en este programa, es para que se vea que la podemos llamar si queremos o no...
slPrint("Esto es la funcion NOSEUSA", 3, 5) -- Una cosa que no se va a llegar a ver que es lo que tiene esta función de código
end -- Se acabó esta función, amigos

PRUEBA() -- Invocamos a esta función, así se hace. Esto es lo primero que ejecuta este programa, el código que haya en esa función
MIERDA() -- después invocamos a esta segunda función llama MIERDA y que hemos definido antes

while true do slSynch() end-- Lo mete en el bucle infinito que tanto nos gusta



Lua puede llamar (y manejar) funciones escritas en su propio lenguaje. Pero no solo eso, además puede ejecutar funciones escritas en C!! Esto es algo que todavía no sé bien cómo va, pero que he visto en los ejemplos que vienen con el Lua Player que en ocasiones hacen uso de funciones en C... De hecho, creo que llaman a cosas hechas con el Saturn Orbit.

Pero no nos desviemos del tema. Esta es la forma más simple de definir funciones e invocarlas, pero luego me temo que se pueden hacer llamadas con argumentos y demás, que ya tocaré más adelante cuando lo domine más...


Un ejemplo un poco más elaborado

Por si acaso no habéis pillado bien para que podemos usar las funciones o pensáis que esto es una soberana chorrada, lo voy a mostrar con un ejemplo que por lo común que es y al que estamos todos muy habituados lo vais a coger sin duda el concepto y para qué nos va a servir.

He perpetrado/improvisado este código:

Código: [Ocultar] [Seleccionar]
function OPCIONES()
slTVOff()
slInitSystem(TV_320x240,NULL,1)
slTVOn()
slPrint("Esto serian las OPCIONES", 2, 2)
while true do slSynch() end
end


function CREDITOS()
slTVOff()
slInitSystem(TV_320x240,NULL,1)
slTVOn()
slPrint("Esto serian los CREDITOS", 2, 2)
while true do slSynch() end
end


function JUGAR()
slTVOff()
slInitSystem(TV_320x240,NULL,1)
slTVOn()
slPrint("Esto seria el JUEGO en si", 2, 2)
while true do slSynch() end
end



local bucle = 1

slInitSystem(TV_320x240,NULL,1)

slPrint("----JUEGO TRAPERO----", 6, 5)
slPrint("Imaginaos unos graficos que te cagas xD", 1, 10)


while bucle < 2 do

slPrint("Pulsa A para OPCIONES", 1, 19)
slPrint("Pulsa X para CREDITOS", 1, 21)
slPrint("Pulsa START para JUGAR", 1, 23)

id,ext,data = Smpc_Peripheral(0)
if bit.band(data, PER_DGT_TA) == 0 then OPCIONES()
end
if bit.band(data, PER_DGT_TX) == 0 then CREDITOS()
end

if bit.band(data, PER_DGT_ST) == 0 then JUGAR()
end


end



while true do slSynch() end


Al ejecutarlo nos aparecerá esto:

juego_saturn_lua

Tendréis que echarle algo de imaginación. Imaginaos un juego simple que tiene un menú con tres opciones como veis, lo típico que hemos visto tantas y tantas veces.

Supongamos que pulsamos la X para ver los créditos del juego y ver a sus programadores:

creditos_lua

Lo mismo pasa con las demás opciones, el programa nos lleva a cada una de ellas. Lo hemos hecho a través de las funciones. En juego en sí sería un código muy complicado que estaría dentro de la función JUEGO y al que llamaríamos cuando el jugador pulse START.

Comento el código por si las moscas:

Código: [Ocultar] [Seleccionar]
function OPCIONES() -- defino lo que serán las opciones con esta función
slTVOff() -- esto es para limpirar la pantalla luego lo comento mejor
slInitSystem(TV_320x240,NULL,1) -- vuelvo a poner el SGL
slTVOn() -- y enciendo, esto son nuevas librerías de SEGA que ahora explicaré
slPrint("Esto serian las OPCIONES", 2, 2) -- Aqui estaría todo el código de las opciones pertinente
while true do slSynch() end -- Lo meto en un bucle para que no salga de aquí, pero podríamos e incluso deberíamos poder regresar al menú principal, para no complicarlo más lo dejo así.
end -- se acaba aquí la función OPCIONES


function CREDITOS() -- Definimos la función CREDITOS, todo lo demás es igual
slTVOff()
slInitSystem(TV_320x240,NULL,1)
slTVOn()
slPrint("Esto serian los CREDITOS", 2, 2)
while true do slSynch() end
end


function JUGAR() -- Ahora el juego en sí, que seria la función JUGAR
slTVOff()
slInitSystem(TV_320x240,NULL,1)
slTVOn()
slPrint("Esto seria el JUEGO en si", 2, 2) -- Aquí estaría todo el código y el meollo del juego
while true do slSynch() end
end



local bucle = 1 -- Lo voy a meter en un bucle con esta variable para detectar la pulsación del mando

slInitSystem(TV_320x240,NULL,1) -- Esto es lo primero que se va a ejecutar ya que hemos definido las funciones pero aun no hemos llamado a ninguna de ellas

slPrint("----JUEGO TRAPERO----", 6, 5) -- Esto seria el Main Menu del juego típico
slPrint("Imaginaos unos graficos que te cagas xD", 1, 10)


while bucle < 2 do -- Le pongo una condición que será infinita porque nunca cambiaría y siempre será así, si sabéis alguna manera mejor de hacerlo... soy todo oídos!

slPrint("Pulsa A para OPCIONES", 1, 19)
slPrint("Pulsa X para CREDITOS", 1, 21)
slPrint("Pulsa START para JUGAR", 1, 23)

id,ext,data = Smpc_Peripheral(0) -- Detectamos lo que pulse el jugador como aprendimos en los otros ejemplos que puse
if bit.band(data, PER_DGT_TA) == 0 then OPCIONES() -- Si pulsa A lo mandamos a la función OPCIONES
end
if bit.band(data, PER_DGT_TX) == 0 then CREDITOS() -- Si pulsa X lo mandamos a la funcion CREDITOS,
end

if bit.band(data, PER_DGT_ST) == 0 then JUGAR() -- Fijaos que estamos usando funciones combinandolas con condicionales, aquí lo mando a el juego en sí que sería la función JUGAR que definimos antes
end


end -- fin del while eterno en el que le he metido para que este todo el rato mostrando el menú principal y esperando que pulsemos alguna cosa



while true do slSynch() end -- lo de siempre


Y listo, ahora veis mejor tal vez para que podemos usar las funciones. Solo faltaría hacer un juegazo con unos gráficos y sonido tremendos y meterlo en la función JUGAR

Una cosa, he aprovechado para meter algunos comandos nuevos de librerías de SEGA que repaso fugazmente:

slTVOff()
Aquí necesitaba algo así como un CLS de BASIC (clear screen) para limpiar la pantalla y he usado esto. Por lo que veo según SEGA:

Citar:
Drawing end declaration - This function turns off scroll drawing processing in the monitor


Esto me ha funcionado, va acompañado inevitablemente de:

slTVOn()

Citar:
Drawing start declaration - This function starts drawing in the scroll screen monitor -


Y eso es todo. Con eso he conseguido que cada vez que llamemos a una función limpie la pantalla para que no se vea nada de la anterior.


Pues nada, eso es todo por hoy. Necesito, o sigo necesitando más bien, manejar gráficos ya.. pero todavía no lo he conseguido. Pido a algún alma caricativa que me eche una mano, jaja

Nos vemos en las próximas lecciones. Un saludo!


Ryo Suzuki [ 21 Junio 2014, 03:18 AM ]
Título del mensajeRe: Trasteando con el Lua Player de Saturn (Tutorial)
Muy buenas amijos, amantes de la Saturn. Por aquí sigo con mi pequeño curso de programación con el SLP (Saturn Lua Player) del gran Rockin'-B.

Le voy echando un vistazo de vez en cuando en los momentos en que las obligaciones me lo permiten. Ir escribiendo en este post con estas particulares "lecciones" me obliga de alguna forma a seguir y a plasmar lo que voy aprendiendo.

En ocasiones me cuesta bastante avanzar ya que no hay practicamente nada de documentación de este port del player para Saturn, el original como ya habré comentado era para PSP.

Los ejemplos que vienen apenas estan comentados y son de un nivel ya bastante alto, rollo lo que le puede parecer fácil a Rockin'-B , además me da la nariz que está pensado para gente que ya se maneja desarrollando para la Saturn con el Orbit y quiera saltar a este SLP... está claro que yo no tenía ni idea


Virtual LUA

Bueno, hoy vamos a poner polígonos en pantalla. Me ha costado lo suyo conseguir averiguar cómo se hace con este Lua Player. He conseguido entender y separar qué es lo que hace cada cosa de los ejemplos hasta poder aislar la parte de poner una figura poligonal en pantalla. También he conseguido usar figuras poligonales que no estaban en los samples, e incluso exportar modelos tridimensionales que pueda hacer yo mismo con un software 3D gratuíto, como es el Blender...

Pero el tema es bastante complicado, así que hoy explicaré sólo cómo se hace de forma relativamente simple, desde uno de los ejemplos y ya en futuros posts veréis cómo lo hago compilando mis propios datos de modelos poligonales que también nos servirá para otras cosas como sprites y demás.

Vamos a coger el ejemplo de la carpeta samples llamado S_3_2. Con el objetivo, como ya dije, de aprovechar el modelo poligonal de este ejemplo y no tener que hacer todo el proceso de crear e importar el modelo 3D por nosotros mismos.

Copiamos la carpeta S_3_2 haciendo un duplicado y le cambiamos el nombre por otro que nos guste más y que la diferencie (yo he puesto POLIGONEO). Ya que hemos clonado ese sample para editarlo vamos como es habitual a editar el código de Lua que está almacenado como siempre en 0_orig.lua. Abrimos ese archivo con el notepad y nos preparamos para crear nuestro propio código, os iré guiando.


Intermedio

Hablando del notepad. Es algo que os quería recomendar, es preferible usar un editor de texto más orientado a temas de programación que son mucho más visuales y tal ya que reconocen las cosas y las organizan mejor para que de un vistazo identifiquemos con más comodidad el código.

Ahora estoy utilizando uno que se llama CODEMAX y que os recomiendo. Es gratuito: http://codemax.luaforge.net/

Fijaos como se ve el código ahora con este editor:

codemax_lua

Mucho más visual y ordenado con los colores para diferenciar cada cosa, ahora siempre usaré este CodeMAX para código del Lua Player.


Poniendo Polígonos en pantalla

Vamos al grano y a dejarnos de intermedios. Hoy, para innovar un poco, lo voy a hacer del revés. Primero pongo el código linea a linea comentado y luego adjunto todo el código final para que lo copiéis/peguéis a 0_orig.lua y lo probéis o trastéis con él modificando, o lo que queráis.

Vamos allá. Empezamos:

Código: [Ocultar] [Seleccionar]
--/*----------------------------------------------------------------------*/
--/* Primeros poligonos en pantalla */
--/*----------------------------------------------------------------------*/


Primero pongo un comentario con el título y tal... (como ya aprendimos con los --)

Seguimos con:
Código: [Ocultar] [Seleccionar]
local ang, pos = {}, {}

Esto es nuevo, declaramos de esta manera un tanto especial estas variables con valores vacios. ang y pos parecen ser varibales globales ya predefinidas y si no hacemos esto nos saltará un error diciéndonos que intentamos indexar un valor nil.

Un valor nil en Lua es:

Citar:
Nil es el tipo del valor nil, cuya principal propiedad es ser diferente de cualquier otro valor; normalmente representa la ausencia de un valor útil.


O para que nos quede más claro:

Citar:
Nil is a type with a single value, nil, whose main property is to be different from any other value. As we have seen, a global variable has a nil value by default, before a first assignment, and you can assign nil to a global variable to delete it. Lua uses nil as a kind of non-value, to represent the absence of a useful value.


Creo que lo que estamos haciendo con local ang, pos = {}, {} es decir que esas variables globales(me parece que aunque las pongamos no son locales) las vamos a asignar un valor y no van a ser nil. El caso es que si no hacemos esto tendremos este error (podeis intentar omitir esta linea y vereis lo que sucede...):roll:

P.D: Como habréis supuesto, ang se refiere a angulo mientras pos hace referencia a la posición. Dos valores importantes de nuestro primer modelo poligonal que vamos a mostrar en pantalla.

Seguimos con esto:

Código: [Ocultar] [Seleccionar]
slInitSystem(TV_320x224,NULL,1)

Vale, nada nuevo bajo el sol. Inciamos el sistema con la resolución y demás como ya tenemos masterizado de otras lecciones.

Continuamos con más cosas nuevas:
Código: [Ocultar] [Seleccionar]
ang.X = DEGtoANG(20.0)
ang.Y = DEGtoANG(22.0)
ang.Z = DEGtoANG( 5.0)

pos.X = 5.0
pos.Y = 8.0
pos.Z = 190.0

Quedaos con la copla que la variable ang tiene tres subvalores por así decirlo. En las coordenadas Y, Z y X.
No solo eso, sino que se definen con algo que parece propio de las libreías de SEGA, ese DEGtoANG() y el valor entre los parentesis del ángulo.

Le hemos dado 20 grados en X, 22 en Y y 5 en el eje Z. Nuestro modelo poligonal estará girado en esos angulos esos grados cuando se vea en screen por primera vez.

Luego tenemos la variable pos, que volvemos a ver que el tema de que al definirla con el . detrás podemos asignarle varias subvariables, si no entiendo mal. En este caso, como comprenderéis se trata de la posición de la pantalla en la que aparecerá nuestro objeto poligonal Saturnero.

Podéis cambiar esos valores luego para hacer pruebas de colocación como he hecho yo. El tema parece ir, en el eje de la X si le das un valor positivo es hacia la derecha, 0 es el centro, etc...
En el eje de la Y un valor negativo es arriba, positivo abajo, evidentemente.
El el eje de la Z un valor positivo implica enviar el objeto más atrás, negativo traerlo hacia adelante.

Pero no quiero alejarme con explicaciones, continuo con mi código:

Código: [Ocultar] [Seleccionar]
local datoscd = GFS_Load_name("DATA.BIN", 0, CPU_WRAM_LO, CPU_WRAM_LO_LEN)

Otra cosa nueva a la par que interesante e importante. Creamos la variable llamada datoscd y le decimos que es igual a un archivo del CDROM que le obligamos a cargar justo en ese momento que la declaramos y que como veis se llama DATA.BIN.

Efectivamente, si vais al ejemplo os dareis cuenta que entre los archivos, además de nuestro querido 0_orig.lua, 0.bin (que creo que no lo he comentado pero es el binario que lee la Saturn primero y hace de interprete y ejecuta nuestro código .lua) y demás files está precisamente data.bin.

Como imaginaréis, en ese archivo está la información matemática de nuestro modelo polígonal que vamos a mostrar en este ejemplo. Ya os daré más explicaciones de cómo es su estructura y demás pero ahora sigo adelante...

Bien, es la primera vez que cargamos algo desde CD. Hasta ahora nuestro código solo se ejecutaba a sí mismo y no hacía uso de otros recursos. Pero en un futuro tendremos que cargar imagenes, modelos polígonales, música y demás cosas... así que no os habrá extrañado.

Vamos a mirar con un poco de detalle qué he hecho y trato de explicarlo en la medida de lo posible.

GFS_Load_name("DATA.BIN", 0, CPU_WRAM_LO, CPU_WRAM_LO_LEN)
Ok, GFS_Load_name es parte del manejo de files del Cd de las librerías de la Saturn. Nada que ver con Lua, ya os lo digo. GFS_ ese prefijo hace referencia a manipulación del CDROM de la 32 bits de SEGA. Va seguido en este caso de Load_name, que no hace falta ser muy listo para adivinar que lo carga en memoria sin ejecutarlo, como los loads de toda la vida (os acordáis de las cintas del Spectrum )

O sea, le estamos diciendo que cargue DATA.BIN y que lo meta en 0, CPU_WRAM_LO, CPU_WRAM_LO_LEN. Esto puede sonar más a marcianada, pero yo entiendo que lo emplaza en la posición 0, WRAM debe ser algo así como working ram si mi intuición no me falla y veo que hay LO y LO_LEN, que deber ser con len referido quizás a longitud (length). Y LO pues igual algo así como LOW, vete tú a saber que a demasiado llego... jeje

Bien hecho, hemos cargado el archivo DATA.BIN que contiene nuestros poligonos en la ram de la Saturn, está listo para ser llamado y ser puesto en pantalla, cuando sea necesario.
Código: [Ocultar] [Seleccionar]
if datoscd == nil or datoscd <= 0 then
slPrint("Error cargando DATA.BIN desde el CD!", 2, 15)
end

Esto puede parecer un poco paranoico, pero es lo suyo. Los condicionales nos iban a valer para muchas cosas como anticipé. Aquí lo que hago es comprobar si el archivo del CD lo ha cargado bien la Saturn. Imaginaos yo que sé.. que por cualquier cosa falle la carga (CD no lee bien, etc...) es un mensaje de error que estaría bien mostrar.

Como apreciaréis le estamos diciendo que si la variable datoscd tiene un valor nil(que ya hemos aprendido lo que es) o es igual o menor que 0 -lo que significaría que no ha cargado el archivo porque por poco que pese en la RAM no será nil ni igual o menor que 0- entonces nos imprima en pantalla avisándonos que ha habido un problema con la carga del archivo desde el CDROM.

Esto en principio nunca lo veremos pero saldría esto si llega a suceder:

error_loading

Si sois muy puntillosos podeis montar la iso quitando DATA.BIN o cambiar el nombre o lo que sea y comprobaréis que funciona como es debido. Así nos cercionamos con este condicional que la Saturn cargue bien el archivo en su ram desde el CD.

Sigo, que me estoy enrrollando como una persiana pero es que es inevitable ya que hay muchos conceptos nuevos:

Código: [Ocultar] [Seleccionar]
local CUBOMODELO = CPU_WRAM_LO

Aquí lo que estoy haciendo es creando la variable CUBOMODELO que va a ser nuestro modelo poligonal -y si no lo he dicho ya por su nombre intuiréis que se trata de un cubo en 3D- y la asigno a la CPU_WRAM_LO. Como decía antes debe ser la working ram en la que acabamos de cargar el archivo data.bin.

En esta ocasión es porque en data.bin solo está nuestro modelo poligonal del cubo, en un futuro os enseñaré que puede contener más cosas y entonces será algo más complicado llamarlo y saber en qué posición de la RAM se encuentra. En ese caso, lo que hago es decirle a la Saturn que lo que tienes en la ram que acabas de cargar desde el CDROM es mi CUBOMODELO.

Prosigo:

Código: [Ocultar] [Seleccionar]
slPrint("Primeros poligonos" , 9, 2)
slPrint("Saturn Lua Player tutorial", 9, 3)
slPrint("by Ryo Suzuki", 9, 4)
slPrint("www.segasaturno.com", 9, 5)

No es necesario explicar el autobombo que ya conocemos, ¿verdad?
Código: [Ocultar] [Seleccionar]
while true do
slPushMatrix()

De acuerdo, lo meto en el bucle principal del programa que va mostrar el cubo con el "while sea verdad", que va a ser siempre, haz todo esto que te detallo a continuación...

Empezamos con slPushMatrix()

Citar:
slPushMatrix Temporary storage of matrix (up to 20 matrices can be nested)

Vale, sé que los temas 3D tienen que ir sobre una matriz.

Citar:
This function advances the matrix buffer pointer, copies the previous current matrix
to the stack, and makes that the new current matrix.
If pointer allocation failed, the function returns the FALSE value.
Up to 20 matrices can be nested in the buffer. If an attempt is made to nest more than 20 matrices in the matrix buffer, the
function returns the FALSE value.

Buff, da un poco de miedo. Yo no quiero 20, de momento con una me vale. Es inevitable y necesitamos tener la matriz.

NOTA: Os sonará igual de temas de programación el stack o pila de ejecución. Aquí teneis más info, pero parece claro que con este slPushMatrix estamos apilando esta matriz.

Seguimos ya casi para bingo:
Código: [Ocultar] [Seleccionar]
slTranslate(pos.X,pos.Y,pos.Z)

Otro nuevo comando de las librerías de SEGA. Como podréis intuir lo traslada a una posición. Más que trasladar en este caso es el punto inicial en cuanto a posición en el cual estará nuestro objeto 3D. Fijaos que son las variables que pusimos antes (5 en el eje de la x, 8 en el de la Y y 190 en el eje Z), pero no pueden ser expresadas con números directamente sino que hay que asignarlo así.

Es necesario definir esto, de lo contrario la Saturn no sabría donde poner nuestro cubo poligonal en pantalla.

Más:
Código: [Ocultar] [Seleccionar]
slRotX(ang.X)
slRotY(ang.Y)
slRotZ(ang.Z)

Esto es opcional, que quede claro. Pero como ya veríais venir de antemano ibamos a rotarlo x grados en los tres ejes, que para algo hicimos antes las variables!!

Sega nos dice (o mejor dicho les decía a los pobres programadores profesionales que en su día lidiaban con el infernal sistema) sobre este comando:
Citar:
slRotX
Description: Adding rotation around X axis to current matrix
Format: void slRotX(angx)
ANGLEangx;
Parameters: angx Angle of rotation around X axis
FunctionThis function multiplies an X axis rotation matrix with the current matrix. The
rotation matrix is expressed below

Como comprenderéis slRotY y slRotZ hacen lo propio en sus respectivos ejes.

El caso es que giro un poco el cubo en esos ángulos no solo por capricho, sino también para que se vea mejor. De lo contrario, saldría completamente recto y solo veriamos una cara, que sería muy triste para nuestro primer modelo 3D en pantalla

Y ya por fin:
Código: [Ocultar] [Seleccionar]
slPutPolygon(CUBOMODELO)

Argghh! Que valle de lágrimas. Finalmente ponemos nuestro modelo poligonal de un cubo en pantalla. En esas posiciones que hemos definido en los ejes x,y,z y con los angulos en x,y,z también. El comando slPutPolygon como su propio nombre indica pone el polígono, entre parentesis está nuestra variable CUBOMODELO que como recordaréis es el archivo DATA.BIN, con los datos de geometría del cubo de marras que tenemos cargado en la ram de la consola.

Ya finalizo, hay que cerrar el bucle y darle a la matriz caña:
Código: [Ocultar] [Seleccionar]
slPopMatrix()
slSynch()
end


Con slPopMatrix() he hecho la operación inversa de lo que hice antes con slPushMatrix, es decir, retirar (o desapilar, con pop) del stack.

slSynch() es el pan nuestro de cada código con la sincronización con el evento. Y por último el end del bucle while en el que le habiamos metido, que no se nos puede olvidar.

Y ya lo tenemos. Generamos la iso y vamos a ver esto:

poligonos_lua

Disfrutad como si no hubiese un mañana de ese cubito 3D que está mostrando la Saturn, jaja. Nuestro -o mejor dicho, mi- primer objeto poligonal puesto en la screen con bastante sudor con este Lua Player.

Os pongo el código completo, ahora ya está debidamente explicado todo:

Código: [Ocultar] [Seleccionar]
--/*----------------------------------------------------------------------*/
--/* Primeros poligonos en pantalla */
--/*----------------------------------------------------------------------*/


local ang, pos = {}, {}

slInitSystem(TV_320x224,NULL,1)

ang.X = DEGtoANG(20.0)
ang.Y = DEGtoANG(22.0)
ang.Z = DEGtoANG( 5.0)
pos.X = 5.0
pos.Y = 8.0
pos.Z = 190.0


local datoscd = GFS_Load_name("DATA.BIN", 0, CPU_WRAM_LO, CPU_WRAM_LO_LEN)
if datoscd == nil or datoscd <= 0 then
slPrint("Error cargando DATA.BIN desde el CD!", 2, 15)
end

local CUBOMODELO = CPU_WRAM_LO


slPrint("Primeros poligonos" , 9, 2)
slPrint("Saturn Lua Player tutorial", 9, 3)
slPrint("by Ryo Suzuki", 9, 4)
slPrint("www.segasaturno.com", 9, 5)


while true do
slPushMatrix()

slTranslate(pos.X,pos.Y,pos.Z)
slRotX(ang.X)
slRotY(ang.Y)
slRotZ(ang.Z)
slPutPolygon(CUBOMODELO)

slPopMatrix()
slSynch()
end


Como os decía al principio, sigo investigando y ya sé como poner otros modelos de distinas procedencias e incluso creados por mi mismo, pero eso ya os lo cuento otro día porque para ilustrar esta pequeña tontería me ha dado mucho trabajo para que quede entendible y claro así que temo lo que puede ser lo otro... Espero que haya sido fácil para vosotros, para mi con la documentación que había... no lo fue


Fase Bonus

No, no me refiero al programa de nuestros amigos. Me parece que queda un poco desangelado el cubo ahí tan triste en pantalla. Vamos a moverlo un poco con lo que hemos aprendido en otros ejemplso de sumar valores a variables dentro de un bucle. En su momento podía parecer una parida, pero ahora nos viene bien porque lo trasladará y rotará en el bucle del while.

Añadid esto despues del slPutPolygon(CUBOMODELO)

Código: [Ocultar] [Seleccionar]
pos.X = pos.X+0.1
ang.Z = ang.Z+10
ang.X = ang.X+40

Luego ya el slPopMatrix() y demás como estaba en el código de antes...

Con eso la liamos parda porque lo desplazamos lentamente hacia la derecha (el eje de las X, valores positivos cada vez más) y lo rotamos algo más rápido en el eje de la z y de la x, para que podamos ver todas sus caras con diferentes colores y tal...

Además, apreciaremos que la Saturn falla más que una escopeta de feria a la hora de mostrar polígonos, por lo visto. ¿Es cosa mía o hay bastantes errores de perspectiva y cosas raras? Os pongo la iso directamente por si la quereis bajar y probar en el emulador para ver cómo se mueve y me contais.

cubista_lua

Eso es todo por hoy. ¿Da mucho miedo y nadie se atreve a trastear con el Lua de Saturn?


FacundoARG [ 21 Junio 2014, 05:16 AM ]
Título del mensajeRe: Trasteando Con El Lua Player De Saturn (Tutorial)
Excelente, luego te comparto el modelo 3D de Sonic


Fdx [ 06 Junio 2017, 11:11 PM ]
Título del mensajeRe: Trasteando Con El Lua Player De Saturn (Tutorial)
Muy buen Post!! Me atrae la idea de programar en saturn mas alla de que no se nada de esto salvo algo de VisiualBatari basic y algun juego a medias para la Atari 2600. Ya me estoy leyendo todo


Ryo Suzuki [ 11 Junio 2017, 08:51 PM ]
Título del mensajeRe: Trasteando con el Lua Player de Saturn (Tutorial)
Por desgracia Rockin'-B parece que hace mucho que está fuera del mundillo y no llegó a sacar más versiones de este Lua.

Yo te recomendaría que si vas a programar para la Saturn optases por la nueva posibilidad que ofrece Johannes Fetz con su Jo Engine.

http://www.jo-engine.org/

Va realmente bien, da soporte y tiene muchísimas más posibilidades diría yo que cualquier otra opción que pueda haber para esta consola. Además va a quitar ahora las SGL así que sería incluso totalmente legal si se hiciesen en un futuro juegos comerciales...


ULTIM4TEGAM3RPR0 [ 25 Septiembre 2017, 09:32 PM ]
Título del mensajeRe: Trasteando Con El Lua Player De Saturn (Tutorial)
Habrá que ir probando este incipiente dev indie saturnino




Powered by Icy Phoenix