ola quisiera hacer un juego para lua MH7 compatible con la version 5.00m33-6 de la slim teneis algun tutorial? por ahi me gustaria acerlo llevo mucho tiempo intentando querer acer uno y me gustaria aprender como
El lua PGE, está diseñado principalmente para juegos, pues no posee funciones tales como controlar la velocidad de la cpu o buses.
Por otra parte, tienes el hm7(homemister7, pues homemister es el autor) Que engloba mas la parte de juegos y apps, pero carece de algunas funciones que si tiene el pge como el zoom, rotar y demas.
Saludos
¡Iníciate en Linux fácilmente! Sólo entra aquíy comprueba que distribución se adapta mejor a tí.
Lo digo más que nada porque en la distribución "normal" del HM7 tienes un archivo llamado "filebrowser.lua"; y dentro del filebrowser.lua, hay esta bonita función:
function scaleImage(newX, newY, theImage)
resizedImage = Image.createEmpty(newX, newY)for x =1, newX dofor y =1, newY do
resizedImage:blit(x,y , theImage,
math.floor(x*(theImage:width()/newX)),
math.floor(y*(theImage:height()/newY)),1,1)endendreturn resizedImage
end
Y lo de rotar imágenes, la verdad, no tiene mucho secreto una vez sabes usar coordenadas polares...
Será más lento y tal porque no viene integrado en biblioteca C y tal y cual... pero que se puede hacer, desde luego.
Y desde luego, que no te venga en una función preparada, empaquetada y lista para llevar, no significa que no pueda hacerse...
Al fin y al cabo, esto va de homebrew, "hacérselo uno mismo en casa", ¿no?
Strength is irrelevant. Resistance is future. We wish to improve ourselves.
La fuerza es irrelevante. La resistencia es futuro. Queremos mejorarnos.
Siempre es buena cosa hurgar por los ejemplos de código, allí siempre se encuentra uno "joyitas" inesperadas, y como mínimo puede entender mejor "cómo se supone que se hacen las cosas". Aunque esta implementación en concreto tiene algún defectillo importante, que ya comentaré...
Empezando por el principio, la función se basa en el buen uso del método blit, que puede emplearse con cualquier par de imágenes (es decir, puedes "blitear" cualquier imagen sobre cualquier otra, sin que se necesite que una de ambas sea screen; de hecho, screen es una "imagen especial", una Image con algún método añadido). Utiliza los parámetros "poco conocidos" del método blit, a saber: no es necesario blitear las imágenes enteras; puedes blitear sólo un área rectangular (o cuadrada) de un ancho y alto determinado, que empiece en unas coordenadas dadas de la imagen origen.
Aparte, algo que hace muy bien es que en realidad no modifica (escala) la imagen, sino que te devuelve una imagen nueva, que es la "vieja" cambiada de tamaño. Esto va bien porque, si lo que quieres es modificar una imagen y no crear una nueva, tienes el recurso de hacer miImagen=scaleImage(nuevoAncho, nuevoAlto, miImagen), y ya modificas la imagen, sin crear una nueva (en principio... si no fuera por uno de los "fallitos" que digo).
function scaleImage(newX, newY, theImage): Aquí se definen los tres parámetros o argumentos que necesitará la función para trabajar: el nuevo ancho, el nuevo alto, y la imagen que escalaremos.
resizedImage = Image.createEmpty(newX, newY): Se crea la nueva imagen que se devolverá... y primer fallito. El problema, aquí, es que la variable resizedImage ("imagenEscalada" o "cambiada de tamaño") es de ámbito global, porque lo que no se declara como local, en Lua es global. Que sea de ámbito global significa, entre otras cosas, que esta imagen nueva seguirá usando espacio aun cuando en realidad no la utilicemos, porque la variable global resizedImage sigue apuntando a esta imagen; y si en Lua hay un puntero que apunta a un valor (y una variable es exactamente eso), el valor se mantiene y sigue ocupando espacio, aun cuando se limpie la memoria con collectgarbage() o su variante System.memclean(): para Lua, esa imagen que "no utilizamos", sí que se utiliza (y se seguirá utilizando hasta que se vuelva a llamar a la función, y resizedImage cambie de valor). Para decirle a Lua que no utilizamos un valor (imagen, cadena, número, etc.), tenemos que eliminar todos sus punteros; las variables locales se eliminan automáticamente al terminar la función (pero el valor que es la imagen redimensionada se mantendrá, porque la habremos pasado a otra variable o lugar, así que habrá otro puntero. Sí, ya sé que suena un poco "raro" esto de que "una imagen es un valor" :)... las máquinas son así).
Sigamos: for x =1, newX dofor y =1, newY do: Los junto aquí porque "van juntos". Estos dos bucles que empiezan sirven para recorrer, píxel a píxel, la nueva imagen; después (en la siguiente línea) se mirará qué es lo que tiene que ir en ese píxel, y se pondrá (con blit, que es más rápido que hacerlo con el método Image:pixel). Y aquí hay dos fallitos más: uno, que sigue sin declarar como locales las variables x e y (y ojo, que son nombres que pueden usarse mucho... si usabas x o y antes de llamar a la función, ¡te cambiará su valor!). El otro es más sutil, pero causaría un descuadre en el escalado: resulta que las coordenadas del primer píxel no son (1, 1), sino (0,0), así que habría que empezar por 0, no 1; y el último píxel de una imagen de, pongamos, 128x128 no es el 128, 128, ¡sino el 127, 127!. Así que para funcionar perfectamente, tendría que ser algo tipo for x=0, newX-1 for y=0, newY-1...
resizedImage:blit(x,y , theImage, ...: Empieza aquí la función de blit, que nos servirá para poner en las coordenadas x, y de resizedImage, la nueva imagen, "lo que corresponda" de la imagen origen. Los siguientes parámetros de blit buscan a qué coordenadas de theImage, la imagen origen a escalar, corresponden las coordenadas nuevas de la nueva imagen, y seleccionan de la imagen origen un cuadrado de 1x1 píxeles (recordemos que estamos pintando la nueva imagen píxel a píxel).
...math.floor(x*(theImage:width()/newX)), math.floor(y*(theImage:height()/newY)),1,1): Vale, aquí la parte difícil, supongo, es lo de "math.floor" y las divisiones, queda un tanto oscuro por qué se hacen. Empecemos por (theImage:width()/newX) y (theImage:height()/newY). Esto, lo que hace, es encontrar la proporción relativa entre ambas imágenes, y sirve para (empezar a) encontrar a qué punto de la imagen origen corresponde cada punto (par de coordenadas) de la imagen destino. Es otro de los fallitos: la proporción entre ambas imágenes no cambia, así que bastaría con calcularla una sola vez. Pero aquí la recalcula con cada bucle... lo que significa que, por ejemplo, para una imagen de 128x128, ¡hace 16.383 multiplicaciones innecesarias! Esto ralentiza soberanamente la función. El math.floor redondea hacia abajo: se redondea porque los píxeles son enteros, no hay un píxel en las coordenadas (0.5, 0.5): ese corresponde al (0,0).
Esta parte de las proporciones es sin duda la más abstrusa y difícil. Para intentar aclarar dudas, recurro a una técnica usada por dibujantes para escalar imágenes, y que también encontrabas en los libros y revistas de pasatiempos de hace 20 o 30 años, cuando yo era un chaval (snif...): la técnica de la cuadrícula. Coges la imagen origen, y le plantas encima una cuadrícula. Luego dibujas una cuadrícula mayor, con el mismo número de casillas, y rehaces el dibujo proporcionalmente, viendo dónde caen las líneas. Si no te ha quedado aún lo bastante claro, prueba esto de la cuadrícula con lápiz y papel, y seguro que algo más te aclara.
El resto de la función es bastante directo: con endendreturn resizedImage end se marca el fin de ambos bucles, se devuelve la imagen final y se cierra la función.
Entonces, recapitulando, para mejorarla, tendríamos que:
Pasar a locales las variables globales.
Calcular las proporciones una sola vez, y emplearlas en el bucle
Así nos queda todo de lo más rápido posible con este método, y bien "embolsado" para que cuando pase el basurero lo recoja, y no les ocupe espacio innecesario; además no modifica ninguna variable externa a la función. Pueden Vds. (todos) usar esta función según los términos de la licencia Creative Commons by-nc-sa (la que rige en Scenebeta, vaya; tienen enlace al fin de la página). Ahora bien, como a alguien se le olvide el reconocimiento de la licencia (que puede ser "donde a Vds. les quepa" :), tampoco pido una letra Impact de 72 puntos...), me voy a enfadar, y ya saben que cuando me enfado soy peor que una ducha de ácido clorhídrico. (Y si alguien está pensando que no me enteraré si "compila" el código fuente, que sepa que sí me voy a enterar igualmente, que sé hacer un dump de mis funciones... y entonces aún me enfadaré más, porque habrán infringido doblemente la licencia: no les estoy dando la función precompilada, sino en código fuente, para que puedan modificarla a su conveniencia... avisados están).
Y para usarlo (pongamos, poner algo a 128x128):miImagenReescalada=EscalaImagen(128, 128, miImagenOriginal);
Si se prefiere emplear porcentajes... bueno, podemos añadir otra función que los recalcule:
function EscalaPorCiento(porcentajeAncho, porcentajeAlto, imagenOrigen)local anchoOriginal, altoOriginal=imagenOrigen:width(), imagenOrigen:height();return EscalaImagen(math.floor(anchoOriginal*porcentajeAncho*.01), math.floor(altoOriginal*porcentajeAlto*.01), imagenOrigen);end
(Aquí no es necesario, en realidad, pasar el ancho y alto original a variables, se puede hacer directamente, pero lo he puesto para un pelín más de claridad)
Pero, para terminar... a ver, el reescalado (y basta, o sea, sin más) de una imagen es una cutrada. Sobre todo, si las proporciones finales no son enteras (o sea, amplías una imagen al 150%, por ejemplo). Un píxel al 200% es un cuadrado de 2x2, y basta. Por eso, para que queden bien -o medianamente bien- lo suyo es aplicarles algún tipo de filtro después de escalarlas (que esto no lo hace esta función, pero tampoco el PGE, que yo sepa): algún difuminado, interpolado, dithering, desenfoque, lo que sea, pero algo que suavice esos pedazo de bloques de Lego que te quedan cuando amplías, o esos bordes tan marcados y raros que aparecen cuando reduces. Una función de este tipo es ya más compleja (hay muchas maneras distintas, y todas tienen su qué...).
Strength is irrelevant. Resistance is future. We wish to improve ourselves.
La fuerza es irrelevante. La resistencia es futuro. Queremos mejorarnos.
Eso es documentar bien una función y lo demás es tontería. Me ha aclarado muchas dudas que tenía (y sigo teniendo sobre Lua)
+5 Scenebitos.
Sólo una pregunta. ¿Lua (o Lua XXX) puede manejar punteros a datos (siendo dato cualquier estructura) directamente?. Puntero en el sentido que pueda en tener C/C++ ó FreePascal por ejemplo.
Pues aquí ya me has pillado, porque no sé si sé cómo es un puntero en C++/FreePascal. Digamos que, si son del estilo de lo que se hacía en el siglo pasado con la interfaz BASIC de ensamblador de Z80, algo tipo:
PUNTERO=PEEK(&H1000): POKE PUNTERO, &H00
...la respuesta es que por lo que sé, de entrada no, pero habría "rodeos"; uno sería usar la API de C, que también te permite cosas de malloc() y demás (pero ya sabemos cómo es el API...). Otra vía iría por toquetear el garbage collector, que puede deshabilitarse, sustituirse, etc.
*Creo* que esto se debe, básicamente, a que el garbage collector (fatal documentado, por cierto) mueve las cosas "de sitio" (léase bloque de memoria). Lo deduzco porque la función tostring (que en realidad, función de metatabla -o sea, método de clase- __tostring) de las tablas devuelve "table "+un número en hexa que *supongo* es o su dirección (¿o un puntero de uso interno?, eso tendría menos sentido, creo), y ese número a veces cambia. Por lo cual, creo que el recogedor de basura también actúa de "desfragmentador", y no sólo marca las direcciones vaciables (funciona por algoritmo de mark and sweep), sino también a partir de dónde debe trabajar.
O eso, o algo totalmente diferente y seguramente aún más estrambótico...
Y cuando digo que "fatal documentado" me refiero a cosas como que tiene un umbral a partir del cual se activa, y trabaja por bloques de "determinado tamaño", que puede modificarse, y el umbral también, y si el umbral es "demasiado bajo" el gc está continuamente en uso, y si es "demasiado alto", se deshabilita la recogida de basura a efectos prácticos. Hasta aquí, muy bien. Ahora bien, el tamaño de los bloques no se especifica en bytes ni nada de eso, sino por un número relativo a no-se-sabe-muy-bien-qué y, literalmente, te dicen que ¡vayas probando a ver cuál te funciona! (Un número ¿en qué intervalo? Pues... ¡buena pregunta!). Tres cuartos de lo mismo para el umbral de activación del collector: seguro que en una FAT, para el HM7, p.e., 13 MB es "demasiado grande", por la simple razón que el intérprete ocupa unos 20+ MB (!!!), y seguro que 0 es "demasiado pequeño", pero aparte de eso...
No sólo eso... agárrate, que vienen curvas. La función collectgarbage(), al llamarla con el argumento "count", te devuelve el espacio ocupado por el programa de Lua (intérprete aparte) con una precisión mayor que... milésimas de bit. (Teóricamente, te lo devuelve en bytes, y he llegado a ver hasta más de cinco decimales... y lo mismo gcinfo, que sirve para más o menos lo mismo, pero en kB, y con la misma imposible precisión).
Eso sí, eppur si muove. Metiéndole cosas bastante memory intensive (que no sé exactamente cuánto, porque ya ves cómo cuenta, y las imágenes además son harina de otro costal... pero sabiendo que era algo BESTIA, así, con mayusculotas: tipo crear enormes animaciones procedurales de partículas y mezclarlas entre sí -alpha blending, por supuesto-, que si no forzaba el ciclo de recogida, el player se cerraba por falta de memoria, o leer un .CSV de 5 megas, pasarlo a un motor de base de datos y ordenarlo todo sin pestañear), apenas me cayó 1-2 fps con el procesador a 166. Ni puñetera idea de cómo lo hacen, y seguramente sea de esas cosas que un programador jamás aceptaría en público y que hace porque es joven y necesita el dinero o algo... pero tengo que seguro que, lo que es funcionar, funciona y bien.
Así que si consigues desentrañar algo por tu parte y me lo cuentas, desde luego que te lo agradecería... porque de las muchas rarezas que tiene Lua, lo de la gestión exacta de la memoria y la recogida de la basura es de las que se lleva la palma.
Strength is irrelevant. Resistance is future. We wish to improve ourselves.
La fuerza es irrelevante. La resistencia es futuro. Queremos mejorarnos.
¿Quieres hacer un juego con el intérprete y motor PGE, o con el intérprete HM7? :)
Por lo de la versión del cfw, no te preocupes...
Personalmente, te recomendaría que empezaras por el Lua "puro y duro", que empezarás sin coger vicios (o no demasiados, al menos), y tiene la ventaja de la compatibilidad con otras plataformas/intérpretes (por ejemplo, el player para Windows).
Y sí, haberlos, haylos (los tutos)... puedes mirar en la sección "Tutoriales". El menú de arriba...
Strength is irrelevant. Resistance is future. We wish to improve ourselves.
La fuerza es irrelevante. La resistencia es futuro. Queremos mejorarnos.
Si vas a empezar, empieza por ahí... que al fin y al cabo, las bibliotecas estándar de Lua, que es por donde hay que empezar :), son comunes a todos los intérpretes. Incluso buena parte de las no estándar.
Se suma igual en uno que otro, el manejo de las tablas es el mismo... y en el caso del HM7, incluso las bibliotecas de imágenes funcionan igual que en el 0.20/Win.
Las cosas más específicas ya son más "secundarias", en tanto que "vienen después". Cosas como el objeto System, para gestión de fecha/hora, gestión simplificada de archivos, etc.
Aparte, el HM7 ya viene con su documentación específica, aunque en inglés. El programador pipagerardo había traducido y ampliado con su experiencia buena parte de esa documentación (no tengo el enlace a mano, pero se puede "googlear", o buscar su perfil por aquí -izquierda, Staff, subsección "coders"-, creo que ahí tenía un enlace a su página).
Juegos de naves, de rol, videoaventuras, un Civilization... poder, poder, se puede.
El tipo de juego y su calidad y complejidad y tal... bueno, pues ya depende de cada uno, su tiempo, etc. Obviamente, no harás un Civilization en una tarde. Pero tampoco con el PGE, ni el LPHMv2, ni el de Windows, ni... :)
Strength is irrelevant. Resistance is future. We wish to improve ourselves.
La fuerza es irrelevante. La resistencia es futuro. Queremos mejorarnos.
A ver, te explico: El lua
A ver, te explico:
El lua PGE, está diseñado principalmente para juegos, pues no posee funciones tales como controlar la velocidad de la cpu o buses.
Por otra parte, tienes el hm7(homemister7, pues homemister es el autor) Que engloba mas la parte de juegos y apps, pero carece de algunas funciones que si tiene el pge como el zoom, rotar y demas.
Saludos
¡Iníciate en Linux fácilmente! Sólo entra aquí y comprueba que distribución se adapta mejor a tí.
Mi review: iPod Touch 4G
¿Tú no te has mirado muy a fondo el HM7, verdad?
Lo digo más que nada porque en la distribución "normal" del HM7 tienes un archivo llamado "filebrowser.lua"; y dentro del filebrowser.lua, hay esta bonita función:
Y lo de rotar imágenes, la verdad, no tiene mucho secreto una vez sabes usar coordenadas polares...
Será más lento y tal porque no viene integrado en biblioteca C y tal y cual... pero que se puede hacer, desde luego.
Y desde luego, que no te venga en una función preparada, empaquetada y lista para llevar, no significa que no pueda hacerse...
Al fin y al cabo, esto va de homebrew, "hacérselo uno mismo en casa", ¿no?
Strength is irrelevant. Resistance is future. We wish to improve ourselves.
La fuerza es irrelevante. La resistencia es futuro. Queremos mejorarnos.
No comprendo, llevo buscando
No comprendo, llevo buscando algo así un mes, y ahora lo encuentroas Deberías cambiarte el nick a google2ZX3D XDXD
De todos modos, podrías explicarla? así no la entiendo..:p
¡Iníciate en Linux fácilmente! Sólo entra aquí y comprueba que distribución se adapta mejor a tí.
Mi review: iPod Touch 4G
Escalando, peldaño a peldaño
Siempre es buena cosa hurgar por los ejemplos de código, allí siempre se encuentra uno "joyitas" inesperadas, y como mínimo puede entender mejor "cómo se supone que se hacen las cosas". Aunque esta implementación en concreto tiene algún defectillo importante, que ya comentaré...
Empezando por el principio, la función se basa en el buen uso del método blit, que puede emplearse con cualquier par de imágenes (es decir, puedes "blitear" cualquier imagen sobre cualquier otra, sin que se necesite que una de ambas sea screen; de hecho, screen es una "imagen especial", una Image con algún método añadido). Utiliza los parámetros "poco conocidos" del método blit, a saber: no es necesario blitear las imágenes enteras; puedes blitear sólo un área rectangular (o cuadrada) de un ancho y alto determinado, que empiece en unas coordenadas dadas de la imagen origen.
Aparte, algo que hace muy bien es que en realidad no modifica (escala) la imagen, sino que te devuelve una imagen nueva, que es la "vieja" cambiada de tamaño. Esto va bien porque, si lo que quieres es modificar una imagen y no crear una nueva, tienes el recurso de hacer miImagen=scaleImage(nuevoAncho, nuevoAlto, miImagen), y ya modificas la imagen, sin crear una nueva (en principio... si no fuera por uno de los "fallitos" que digo).
function scaleImage(newX, newY, theImage)
: Aquí se definen los tres parámetros o argumentos que necesitará la función para trabajar: el nuevo ancho, el nuevo alto, y la imagen que escalaremos.resizedImage = Image.createEmpty(newX, newY)
: Se crea la nueva imagen que se devolverá... y primer fallito. El problema, aquí, es que la variableresizedImage
("imagenEscalada" o "cambiada de tamaño") es de ámbito global, porque lo que no se declara como local, en Lua es global. Que sea de ámbito global significa, entre otras cosas, que esta imagen nueva seguirá usando espacio aun cuando en realidad no la utilicemos, porque la variable globalresizedImage
sigue apuntando a esta imagen; y si en Lua hay un puntero que apunta a un valor (y una variable es exactamente eso), el valor se mantiene y sigue ocupando espacio, aun cuando se limpie la memoria concollectgarbage()
o su varianteSystem.memclean()
: para Lua, esa imagen que "no utilizamos", sí que se utiliza (y se seguirá utilizando hasta que se vuelva a llamar a la función, yresizedImage
cambie de valor). Para decirle a Lua que no utilizamos un valor (imagen, cadena, número, etc.), tenemos que eliminar todos sus punteros; las variables locales se eliminan automáticamente al terminar la función (pero el valor que es la imagen redimensionada se mantendrá, porque la habremos pasado a otra variable o lugar, así que habrá otro puntero. Sí, ya sé que suena un poco "raro" esto de que "una imagen es un valor" :)... las máquinas son así).Sigamos:
for x = 1, newX do for y = 1, newY do
: Los junto aquí porque "van juntos". Estos dos bucles que empiezan sirven para recorrer, píxel a píxel, la nueva imagen; después (en la siguiente línea) se mirará qué es lo que tiene que ir en ese píxel, y se pondrá (conblit
, que es más rápido que hacerlo con el métodoImage:pixel
). Y aquí hay dos fallitos más: uno, que sigue sin declarar como locales las variables x e y (y ojo, que son nombres que pueden usarse mucho... si usabas x o y antes de llamar a la función, ¡te cambiará su valor!). El otro es más sutil, pero causaría un descuadre en el escalado: resulta que las coordenadas del primer píxel no son (1, 1), sino (0,0), así que habría que empezar por 0, no 1; y el último píxel de una imagen de, pongamos, 128x128 no es el 128, 128, ¡sino el 127, 127!. Así que para funcionar perfectamente, tendría que ser algo tipo for x=0, newX-1 for y=0, newY-1...resizedImage:blit(x,y , theImage, ...
: Empieza aquí la función deblit
, que nos servirá para poner en las coordenadas x, y deresizedImage
, la nueva imagen, "lo que corresponda" de la imagen origen. Los siguientes parámetros deblit
buscan a qué coordenadas detheImage
, la imagen origen a escalar, corresponden las coordenadas nuevas de la nueva imagen, y seleccionan de la imagen origen un cuadrado de 1x1 píxeles (recordemos que estamos pintando la nueva imagen píxel a píxel)....math.floor(x*(theImage:width()/newX)), math.floor(y*(theImage:height()/newY)),1,1)
: Vale, aquí la parte difícil, supongo, es lo de "math.floor" y las divisiones, queda un tanto oscuro por qué se hacen. Empecemos por(theImage:width()/newX)
y(theImage:height()/newY)
. Esto, lo que hace, es encontrar la proporción relativa entre ambas imágenes, y sirve para (empezar a) encontrar a qué punto de la imagen origen corresponde cada punto (par de coordenadas) de la imagen destino. Es otro de los fallitos: la proporción entre ambas imágenes no cambia, así que bastaría con calcularla una sola vez. Pero aquí la recalcula con cada bucle... lo que significa que, por ejemplo, para una imagen de 128x128, ¡hace 16.383 multiplicaciones innecesarias! Esto ralentiza soberanamente la función. Elmath.floor
redondea hacia abajo: se redondea porque los píxeles son enteros, no hay un píxel en las coordenadas (0.5, 0.5): ese corresponde al (0,0).Esta parte de las proporciones es sin duda la más abstrusa y difícil. Para intentar aclarar dudas, recurro a una técnica usada por dibujantes para escalar imágenes, y que también encontrabas en los libros y revistas de pasatiempos de hace 20 o 30 años, cuando yo era un chaval (snif...): la técnica de la cuadrícula. Coges la imagen origen, y le plantas encima una cuadrícula. Luego dibujas una cuadrícula mayor, con el mismo número de casillas, y rehaces el dibujo proporcionalmente, viendo dónde caen las líneas. Si no te ha quedado aún lo bastante claro, prueba esto de la cuadrícula con lápiz y papel, y seguro que algo más te aclara.
El resto de la función es bastante directo: con
end end return resizedImage end
se marca el fin de ambos bucles, se devuelve la imagen final y se cierra la función.Entonces, recapitulando, para mejorarla, tendríamos que:
Una vez hecho, nos quedaría algo más o menos así:
Así nos queda todo de lo más rápido posible con este método, y bien "embolsado" para que cuando pase el basurero lo recoja, y no les ocupe espacio innecesario; además no modifica ninguna variable externa a la función. Pueden Vds. (todos) usar esta función según los términos de la licencia Creative Commons by-nc-sa (la que rige en Scenebeta, vaya; tienen enlace al fin de la página). Ahora bien, como a alguien se le olvide el reconocimiento de la licencia (que puede ser "donde a Vds. les quepa" :), tampoco pido una letra Impact de 72 puntos...), me voy a enfadar, y ya saben que cuando me enfado soy peor que una ducha de ácido clorhídrico. (Y si alguien está pensando que no me enteraré si "compila" el código fuente, que sepa que sí me voy a enterar igualmente, que sé hacer un dump de mis funciones... y entonces aún me enfadaré más, porque habrán infringido doblemente la licencia: no les estoy dando la función precompilada, sino en código fuente, para que puedan modificarla a su conveniencia... avisados están).
Y para usarlo (pongamos, poner algo a 128x128):
miImagenReescalada=EscalaImagen(128, 128, miImagenOriginal);
Si se prefiere emplear porcentajes... bueno, podemos añadir otra función que los recalcule:
(Aquí no es necesario, en realidad, pasar el ancho y alto original a variables, se puede hacer directamente, pero lo he puesto para un pelín más de claridad)
Pero, para terminar... a ver, el reescalado (y basta, o sea, sin más) de una imagen es una cutrada. Sobre todo, si las proporciones finales no son enteras (o sea, amplías una imagen al 150%, por ejemplo). Un píxel al 200% es un cuadrado de 2x2, y basta. Por eso, para que queden bien -o medianamente bien- lo suyo es aplicarles algún tipo de filtro después de escalarlas (que esto no lo hace esta función, pero tampoco el PGE, que yo sepa): algún difuminado, interpolado, dithering, desenfoque, lo que sea, pero algo que suavice esos pedazo de bloques de Lego que te quedan cuando amplías, o esos bordes tan marcados y raros que aparecen cuando reduces. Una función de este tipo es ya más compleja (hay muchas maneras distintas, y todas tienen su qué...).
Strength is irrelevant. Resistance is future. We wish to improve ourselves.
La fuerza es irrelevante. La resistencia es futuro. Queremos mejorarnos.
Gracias
Eso es documentar bien una función y lo demás es tontería. Me ha aclarado muchas dudas que tenía (y sigo teniendo sobre Lua)
+5 Scenebitos.
Sólo una pregunta. ¿Lua (o Lua XXX) puede manejar punteros a datos (siendo dato cualquier estructura) directamente?. Puntero en el sentido que pueda en tener C/C++ ó FreePascal por ejemplo.
Un saludo.
LuaDiE: Crea en Lua sin teclear código. Compatible HM7, HMv2, LuaPlayer, LuaDEV y PGE.
Aquí ya me has pillado
Pues aquí ya me has pillado, porque no sé si sé cómo es un puntero en C++/FreePascal. Digamos que, si son del estilo de lo que se hacía en el siglo pasado con la interfaz BASIC de ensamblador de Z80, algo tipo:
PUNTERO=PEEK(&H1000): POKE PUNTERO, &H00
...la respuesta es que por lo que sé, de entrada no, pero habría "rodeos"; uno sería usar la API de C, que también te permite cosas de malloc() y demás (pero ya sabemos cómo es el API...). Otra vía iría por toquetear el garbage collector, que puede deshabilitarse, sustituirse, etc.
*Creo* que esto se debe, básicamente, a que el garbage collector (fatal documentado, por cierto) mueve las cosas "de sitio" (léase bloque de memoria). Lo deduzco porque la función tostring (que en realidad, función de metatabla -o sea, método de clase- __tostring) de las tablas devuelve "table "+un número en hexa que *supongo* es o su dirección (¿o un puntero de uso interno?, eso tendría menos sentido, creo), y ese número a veces cambia. Por lo cual, creo que el recogedor de basura también actúa de "desfragmentador", y no sólo marca las direcciones vaciables (funciona por algoritmo de mark and sweep), sino también a partir de dónde debe trabajar.
O eso, o algo totalmente diferente y seguramente aún más estrambótico...
Y cuando digo que "fatal documentado" me refiero a cosas como que tiene un umbral a partir del cual se activa, y trabaja por bloques de "determinado tamaño", que puede modificarse, y el umbral también, y si el umbral es "demasiado bajo" el gc está continuamente en uso, y si es "demasiado alto", se deshabilita la recogida de basura a efectos prácticos. Hasta aquí, muy bien. Ahora bien, el tamaño de los bloques no se especifica en bytes ni nada de eso, sino por un número relativo a no-se-sabe-muy-bien-qué y, literalmente, te dicen que ¡vayas probando a ver cuál te funciona! (Un número ¿en qué intervalo? Pues... ¡buena pregunta!). Tres cuartos de lo mismo para el umbral de activación del collector: seguro que en una FAT, para el HM7, p.e., 13 MB es "demasiado grande", por la simple razón que el intérprete ocupa unos 20+ MB (!!!), y seguro que 0 es "demasiado pequeño", pero aparte de eso...
No sólo eso... agárrate, que vienen curvas. La función collectgarbage(), al llamarla con el argumento "count", te devuelve el espacio ocupado por el programa de Lua (intérprete aparte) con una precisión mayor que... milésimas de bit. (Teóricamente, te lo devuelve en bytes, y he llegado a ver hasta más de cinco decimales... y lo mismo gcinfo, que sirve para más o menos lo mismo, pero en kB, y con la misma imposible precisión).
Eso sí, eppur si muove. Metiéndole cosas bastante memory intensive (que no sé exactamente cuánto, porque ya ves cómo cuenta, y las imágenes además son harina de otro costal... pero sabiendo que era algo BESTIA, así, con mayusculotas: tipo crear enormes animaciones procedurales de partículas y mezclarlas entre sí -alpha blending, por supuesto-, que si no forzaba el ciclo de recogida, el player se cerraba por falta de memoria, o leer un .CSV de 5 megas, pasarlo a un motor de base de datos y ordenarlo todo sin pestañear), apenas me cayó 1-2 fps con el procesador a 166. Ni puñetera idea de cómo lo hacen, y seguramente sea de esas cosas que un programador jamás aceptaría en público y que hace porque es joven y necesita el dinero o algo... pero tengo que seguro que, lo que es funcionar, funciona y bien.
Así que si consigues desentrañar algo por tu parte y me lo cuentas, desde luego que te lo agradecería... porque de las muchas rarezas que tiene Lua, lo de la gestión exacta de la memoria y la recogida de la basura es de las que se lleva la palma.
Strength is irrelevant. Resistance is future. We wish to improve ourselves.
La fuerza es irrelevante. La resistencia es futuro. Queremos mejorarnos.
Usando
Las funciones del 3D se puede rotar una imagen en el HM7
¿En qué quedamos?
¿Quieres hacer un juego con el intérprete y motor PGE, o con el intérprete HM7? :)
Por lo de la versión del cfw, no te preocupes...
Personalmente, te recomendaría que empezaras por el Lua "puro y duro", que empezarás sin coger vicios (o no demasiados, al menos), y tiene la ventaja de la compatibilidad con otras plataformas/intérpretes (por ejemplo, el player para Windows).
Y sí, haberlos, haylos (los tutos)... puedes mirar en la sección "Tutoriales". El menú de arriba...
Strength is irrelevant. Resistance is future. We wish to improve ourselves.
La fuerza es irrelevante. La resistencia es futuro. Queremos mejorarnos.
con el hm7 perdon que me
con el hm7 perdon que me habia equivocado
ok gracias empezare con el hm7 desde cero.. no sabes ningun link?
GRACIAS
con el hm7 perdon que me
con el hm7 perdon que me habia equivocado
ok gracias empezare con el hm7 desde cero.. no sabes ningun link?
GRACIAS
Alguno...
Por ejemplo, éste: http://psp.scenebeta.com/tutorial/tutoriales-para-programar-...
Si vas a empezar, empieza por ahí... que al fin y al cabo, las bibliotecas estándar de Lua, que es por donde hay que empezar :), son comunes a todos los intérpretes. Incluso buena parte de las no estándar.
Se suma igual en uno que otro, el manejo de las tablas es el mismo... y en el caso del HM7, incluso las bibliotecas de imágenes funcionan igual que en el 0.20/Win.
Las cosas más específicas ya son más "secundarias", en tanto que "vienen después". Cosas como el objeto System, para gestión de fecha/hora, gestión simplificada de archivos, etc.
Aparte, el HM7 ya viene con su documentación específica, aunque en inglés. El programador pipagerardo había traducido y ampliado con su experiencia buena parte de esa documentación (no tengo el enlace a mano, pero se puede "googlear", o buscar su perfil por aquí -izquierda, Staff, subsección "coders"-, creo que ahí tenía un enlace a su página).
Y, aparte, la referencia de Lua 5.1 (en español, aquí)
Strength is irrelevant. Resistance is future. We wish to improve ourselves.
La fuerza es irrelevante. La resistencia es futuro. Queremos mejorarnos.
gracias .. entonces se
gracias .. entonces se podria hacer juegos con el no?
Por supuesto
Juegos de naves, de rol, videoaventuras, un Civilization... poder, poder, se puede.
El tipo de juego y su calidad y complejidad y tal... bueno, pues ya depende de cada uno, su tiempo, etc. Obviamente, no harás un Civilization en una tarde. Pero tampoco con el PGE, ni el LPHMv2, ni el de Windows, ni... :)
Strength is irrelevant. Resistance is future. We wish to improve ourselves.
La fuerza es irrelevante. La resistencia es futuro. Queremos mejorarnos.