Trasteando con el Lua Player de Saturn (Tutorial)


Ir a la página Anterior  1, 2, 3, 4

Objetivo: Re: 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:

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: :mrgreen:

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:

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:

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:

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 :twisted:

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 :roll:

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

Objetivo: Re: 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 :mrgreen: , 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:

--/*----------------------------------------------------------------------*/
--/* Primeros poligonos en pantalla */
--/*----------------------------------------------------------------------*/


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

Seguimos con:
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:

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:
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:

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 :mrgreen: )

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.
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:

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:

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?
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:
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:
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 :twisted:

Y ya por fin:
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:
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:

--/*----------------------------------------------------------------------*/
--/* 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 :lol:


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)

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? 8)

Objetivo: Re: Trasteando Con El Lua Player De Saturn (Tutorial)
Excelente, luego te comparto el modelo 3D de Sonic :P

Perfil MP  
Objetivo: Re: 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

Perfil MP  
Objetivo: Re: 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...

Objetivo: Re: Trasteando Con El Lua Player De Saturn (Tutorial)
Habrá que ir probando este incipiente dev indie saturnino :)

Ir a la página Anterior  1, 2, 3, 4

Página 4 de 4


  
No puede crear mensajes
No puede responder temas
No puede editar sus mensajes
No puede borrar sus mensajes
No puede votar en encuestas
No puede adjuntar archivos
No puede descargar archivos
Puede publicar eventos en el calendario

   

Está utilizando la versión (Lo-Fi). Para ver la versión completa del foro, haga clic aquí.

Powered by Icy Phoenix based on phpBB
Design by DiDiDaDo

Página generada en:: 0.0936s (PHP: 20% SQL: 80%)
Consultas SQL: 12 - Debug off - GZIP Desactivado