Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





J2me Dibujar Fragmentos De Imagenes

Iniciado por bnl, 20 de Febrero de 2006, 12:41:13 AM

« anterior - próximo »

bnl

 Buenas
¿Cual pensais que es la forma mas eficiente de dibujar fragmentos de imagenes con j2me?
Seria por ejemplo para dibujar un mapa a base de tiles de un tileset que es una unica imagen y de la cual habria que ir recortando trozos para dibujar el mapa.
Mi web: http://www.brausoft.com/
No sabían que era imposible, así que lo hicieron.

_XUTI_H_

 mmm, weno, creo que este tema se ha tratado unas cuantas veces en otros hilos.
Otro hilo...

Con el MIDP 1.0 no puedes dibujar trozos de una imagen, a no ser que utilices SetClip para definir la parte de esta que quieres dibujar. Pero esta ultima opción es un poco lenta. Aun así se utiliza si no tienes que cambiar muchas veces el Clip.
Para un fondo con mapeado de tiles creo que será bastante lentilla. Aun así siempre podrias probar a ordenar los tiles por numero, quiero decir, minimizar el coste de SetClip dibujando seguidos todos los tiles con el mismo numero.
Quedaria algo así:
1 + Cambiar de numero de tile.
2 + Usar setClip para este tile.
3 + Dibujar todos los tiles con este numero.
4 * SI quedan más tiles volver a 1 SINO FIN


Otra opción bastante comentada y que resulta ser la más rápida es particionar tu tileset en imagenes independientes para cada tile individual. Para solventar el problema de memoria (debido al espacio que ocupan las cabeceras de los PNGs) en el .jar deberias realizar esta partición en tiempo de ejecución, creando imagenes individuales a partir de tu tileset, aquí si deberias utilizar setClip para particionar la imagen general.

De todas formas aquí hay más problemas, si utilizas el ultimo método no podrás tener transparencia en tus imagenes, ya que la perderás al particionar la imagen general. Las alternativas son:

1 - utilizar las apis especificas de algunos modelos, que te permitirán crear imagenes con fondo en transparente en vez de fondo blanco.
2 - (esta es la mejor, xo la más difícil y costosa) Crear un formato propio para almacenar la información de las imagenes. Más tarde cuando leas el recurso que contiene la información deberás cargarlo en memoria con "Image createImage(byte[] imageData, int imageOffset, int imageLength)".

Sin duda alguna, para mi, la mejor es la ultima formula. Con esta puedes llegar a tener un control total de como tienes la información almacenada, puedes crear espejos de imagenes a partir de los datos de un solo archivo, puedes cambiar la paleta de los graficos antes de cargarla en memoria, etc, etc, etc. El incoveniente es que necesita un "poquito" más de trabajo, conocimientos y paciencia ;)

Bueno, salu2, espero que esto te ayude.  
UTI

zupervaca

 Esta clase que hice hace lustros es la que uso para el semiremake de nosferatu y me ha dado muy buen resultado desde hace lustros tambien ;)

// ImageList.java
// Clase para contener una imagen que contiene subimagenes separadas verticalmente

// Paquete
package Img;

// Paquetes
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import java.io.IOException;
import Kernel.Kernel;

// Declaración de la clase
/**
* Nos permite controlar imagenes de forma sencilla
* @author David Inclán
* @version 1.0
*/
public class ImageList
{
   // Propiedades de la clase
   /**
    * Ancho de cada subimagen
    */
   public int width;
   /**
    * Alto de cada subimagen
    */
   public int height;
   /**
    * Número de imagenes en la lista
    */
   public int numImages;
   /**
    * Imagen que contiene todas las subimagenes
    */
   public Image image;

   // Miembros privados de la clase
   private int numImagesPerLine;
   private int imageWidth, imageHeight;

   // Constructor
   /**
    * Crear una lista de imagenes apartir de una unica imagen
    * @param strFileName Nombre del archivo
    * @param width Ancho de las subimagenes
    * @param height Alto de las subimagenes
    */
   public ImageList( String strFileName, int width, int height )
   {
       // Crear las imagenes
       try
       {
           this.image = Image.createImage( strFileName );
           this.width = width;
           this.height = height;
           this.imageWidth = this.image.getWidth();
           this.imageHeight = this.image.getHeight();
           this.numImages = (this.imageWidth * this.imageHeight) / (this.width * this.height);
           this.numImagesPerLine = this.imageWidth / this.width;
       }
       catch( IOException ie )
       {
       }
   }

   // Dibujar una imagen indicando un indice
   /**
    * Permite renderizar una imagen en un dispositivo de contexto
    * @param dc Dispositivo de contexto donde se renderizara la imagen
    * @param x Coordenada X
    * @param y Coordenada Y
    * @param index Indice númerico de la subimagen a renderizar
    */
   public void draw( Graphics dc, int x, int y, int index )
   {
       // Mirar si esta dentro de la pantalla
       if( x + this.width >= 0 && y + this.height >= 0 && x <= Kernel.kernel.canvasWidth && y <= Kernel.kernel.canvasHeight &&
               index >= 0 && index <= this.numImages )
       {
           // Aplicar el clip
           dc.setClip( x, y, this.width, this.height );
           // Calcular el bloque de la imagen a pintar
           dc.drawImage( this.image,
                   -(index % this.numImagesPerLine) * this.width + x,
                   -(index / this.numImagesPerLine) * this.height + y,
                   Graphics.TOP | Graphics.LEFT );
       }
   }
}

Su manejo es la mar de sencillo, creamos la clase indicando la imagen que contiene todas las imagenes, el ancho y alto de cada subimagen y luego llamamos a la funcion draw para dibujar la subimagen que queramos, se podria optimizar si pusieramos una funcion en la que indicamos la imagen a renderizar y otra para su posicion y memorizar estos valores para asi luego cuando llamemos a draw no tenga que hacer mas calculos, pero que carallo es mas comodo el draw (ole)
Se me olvidaba, las variables Kernel.kernel.canvasWidth y Kernel.kernel.canvasHeight son el ancho y alto de la pantalla del movil, yo tengo otra clase que las memoriza como variables ya que es mas rapido que pedirlas cada dos por tres.
Tambien te daras cuenta que las variables son publicas y se pueden modificar, pues no las modifiques ya que las hago publicas y que se tengan acceso a ellas por que asi es mucho mas rapido que tener que llamar a una funcion para obtenerlas, esto te dara una pista de como optimizar el codigo ;)

bnl

 Gracias a ambos por las respuestas.

Yo estaba dudando entre el setclip y el drawRegion, todavia no me he decidido sobre si usare midp1 o midp2. Sabia q el drawRegion no se podia usar en midp1, pero no tenia ni idea de q el rendimiento del setClip era peor. De momento he implementado las dos para probar.

Xuti H lo de dividir una imagen en varias en tiempo de ejecucion ¿no consumiria mucha memoria? Habria que tener cargada en memoria 30 pequeñas imagenes (si tuvieramos 30 casillas en el tileset)

Voy a hacer algunas pruebas de rendimiento a ver que tal se comportan las dos opciones.
Mi web: http://www.brausoft.com/
No sabían que era imposible, así que lo hicieron.

zupervaca

 Otro consejo, las pruebas finales hazlas sobre un movil por que las cosas cambian mucho, pero ya te digo que la mejor opcion es el setClip, ahorras tiempo y dolores de cabeza aunque pierdas de pintar 10 imagenes de 32x32 en comparacion a pintar sin setClip, por lo menos en un nokia 3650.
Otra cosa ¿has pensado en meterte con flash mobile? son juegos que se crean desde flash, no sirve para todos los moviles, pero el resultado grafico es muy bueno, ademas estaria bien que alguien pusiera algo de informacion de como empezar con ello si esta usando este sistema.

Suerte tiu

sés

Soy indeciso... ¿o no?

zupervaca

 Creo que no has leido bien el anterior post y te has lanzado a postear sin mas, leetelo bien.
Como dije en el anterior post el setClip es lento y en algunos moviles es peor que lento, pero por suerte en el nokia3650 pierdo pocas fps despues de haberlo actualizado y borrado el virus que estoy seguro que se me colo con tu juego :P

A otro tema, no logro entender por que siempre que estoy ayudando a una persona salta alguien del foro en plan caza de brujas, ¿por que no me dejais en paz y empezais a subir codigos del mes y ayudar a las personas? Es que empiezo a cansarme la verdad. ¿Por que no pones el codigo que usas tu ses para estas cosas y nos sorprendes a todos?

Ahora saltara alguien diciendo que soy un troll, pues bien soy un troll que pone codigos, que hace minitutoriales por los foros y siempre ayudo en lo que puedo, ademas de haber aguantado todo tipo de insultos y haberme controlado el 90% de las veces.

chechocossa

 
CitarAhora saltara alguien diciendo que soy un troll

zupervaca es un troll

Oye... estoy haciendo algo con MIDP 2.0
Trabajo con TiledLayer y Sprite.
El fondo tiene algunos tiles animados.
No puedo probarlo sobre un móvil. Sólo en emuladores Nokia y el mpowerplayer.
Chequeo una colisión con collidesWith( backGround, true )
Si esa colisión es con un tile animado, en el emulador de Nokia o en el Wireless TollKit me salta una exception de ArrayIndexOutOfBoundsException (supongo que será porque los tiles animados tienen un índice negativo...  O_O )
En el mpowerplayer funciona correctamente...

Busqué en algunos foros sobre ese error y no encontré nada que indique lo que ocurre...

¿Te ha pasado algo así?
¿Serán sólo los emuladores que fallan?

Saludos y gracias por la info que vas bajando, que siempre sirve.

Edit: cuando la colisión es a través de collidesWith( backGround, false ), es decir, no por pixel, no ocurre esa excepción.
ergio Cossa

http://www.fatherjoe.com.ar - Father Joe Mobile
http://www.fantasticzone.blogspot.com - Fantastic Zone Blog
http://www.fantasticzone.com.ar - Fantastic Zone Page
Argentina

zupervaca

 Sobre midp 2.0 no tengo mucha idea, pero la funcion esa se lanza desde un sprite mirando sus coordenas X e Y, por lo que puede ser que ese sprite este fuera de las dimensiones del TiledLayer y de ahi que diga esa excepcion, es decir, dependiendo del emulador o api del movil unos comprobaran si el sprite esta dentro del mapa o no, si es esto te recomiendo poner un par de ifs antes de llamar a esta funcion, ademas tendras que ajustar el tamaño de la comprobacion del sprite si se pasa del mapa con la funcion defineCollisionRectangle.

Hecha un vistazo a esta web, explican en español como usar midp 2.0 y ademas al final del articulo pone algunos ejemplos.

Flint

 
Cita de: "zupervaca"Ahora saltara alguien diciendo que soy un troll, pues bien soy un troll que pone codigos, que hace minitutoriales por los foros y siempre ayudo en lo que puedo, ademas de haber aguantado todo tipo de insultos y haberme controlado el 90% de las veces.

Juas. Además de echarte flores, podrías añadir que en todas las ocasiones en las que alguien ha salido haciéndote ver la incorrección de tus argumentos en diversos temas (cuando así ha sido), no has hecho caso alguno, encadenando estupideces una detrás de otra. Es realmente contradictorio que en tus posts siempre pidas a los demás que lean, cuando tú eres el que menos lo hace.  ;)

Lo siento por el off-topic, pero es que si se va provocando pasa lo que pasa.

_XUTI_H_

 argg! un troll!!!! hechizo flecha llameante!!!! ataque con arco élfico antiguo!!!
O_O  ups, parece que juego demasiado ultimamente

CitarXuti H lo de dividir una imagen en varias en tiempo de ejecucion ¿no consumiria mucha memoria? Habria que tener cargada en memoria 30 pequeñas imagenes (si tuvieramos 30 casillas en el tileset)
Si, consumiria más memoria por la cabeceras del PNG, 8kb cada imagen creo recordar que se comento anteriormente por estos foros ... pero puede que ganes velocidad.
EDIT: y para que no comenceis a atacarme - lo de la cabecera es en el jar seguro. Puede que en memoria principal vaya de otro modo, sobretodo dependiendo del dispositivo, cada uno es diferente.
Ciertamente los problemas más típicos con la asociación memoria-imagen están en los Nokia. Es muy facil encontrar que un telefono nokia no libere NUNCA de forma adecuada la memoria que ocupaba un objeto Image. Ya puedes poner la referencia a null, hacer 1001 Garbage Collectors, golpear insistentemente el móvil contra la mesa, .... es lo que hay.
Lo de tener setClip y drawRegion escritas a la vez es una buena idea, ya que comentando y descomentando un par de lineas puedes cambiar de modo, entre midp1 y 2.  (ole)  Pero claramente funcionará más rápido (al menos tendria que hacerlo) drawRegion en los MIDP2.
Son solo consejos, ya que la verdad del juego para móvil es que hay así como unos 1000 modelos diferentes de dispositivos. Cada uno de ellos irá peor en una cosa :( encontrar el equilibrio entre tamaño del jar, velocidad del juego y no quedarte sin memoria principal = ufffff (nooo).

En cuanto a la pregunta de chechocossa creo que si que es por el tema de tener tiles animados (concretamente si la api tiene que buscar los pixeles de la imagen que corresponderian al current-tile de esa animación). Pero no sabria como solucionarlo, muy probablemente que funcione o no en un móvil dependerá de como haya implementado la api para java el fabricante de este dispositivo. Personalmente no utilizaria tiledLayer. Ya sé que es un coñazo tener que implementarte un sistema de mapeado de tiles, colisiones, etc. pero si realmente quieres que la cosa vaya en moviles con MIDP2, utiliza drawRegion, y adelante.

Y hablando de mini-tutos y cosas de estas. Yo dejé hace bastantes meses un COTW que estaba haciendo sobre este tema precisamente. Nunca lo acabé y (logicamente) nunca lo subí, a ver si saco tiempo y me pongo ...

Un salu2 y no os insulteis muxo :P
UTI

zupervaca

Cita de: "Flint"Juas. Además de echarte flores, podrías añadir que en todas las ocasiones en las que alguien ha salido haciéndote ver la incorrección de tus argumentos en diversos temas (cuando así ha sido), no has hecho caso alguno, encadenando estupideces una detrás de otra. Es realmente contradictorio que en tus posts siempre pidas a los demás que lean, cuando tú eres el que menos lo hace.  ;)

Lo siento por el off-topic, pero es que si se va provocando pasa lo que pasa.
No me hecho flores, es la verdad, ¿cuando has hecho tu algo por alguien en este foro? solo sabes criticarme, la prueba esta en que detras de un post mio hay uno tuyo diciendo lo contrario o diciendo alguna tonteria como esta.
¿Estupideces? ¿Como aquella vez que todos decian que los arrays no se segmentan? Pillaros el compilador de borland de c++ en ms-dos y mira a ver si dan soporte a mas de 64kb incluso existiendo esa limitacion, ya veras si se segmentan o no.
¿Contradictorio quie pida que la gente lea? Pues fijate que pido que LEAS otra vez para que LEAS quien ha empezado a provocar en este hilo que estaba limpio de tonterias hasta que ses posteo.
Lo mas gracioso es que son cuatro personas las que dicen que miento o digo chorradas y son personas que no colaboran en este foro y solo saben que insultar y criticar a los demas.

Flint

 
CitarNo me hecho flores

Arggghh... talibán ortográfico, eso duele.

Citar¿cuando has hecho tu algo por alguien en este foro?

Puedes ver todos los mensajes de todos los miembros del foro. Hazlo conmigo y verás que, dentro de mis limitadas posibilidades, he ayudado en lo que he podido. No soy muy posteador ni lo pretendo, el problema está en que personajillos como tú me obligan a escribir de vez en cuando.

Citar¿Estupideces? ¿Como aquella vez que todos decian que los arrays no se segmentan?

No, como aquella vez en la que dijiste que un registro es una variable.

Citar¿Contradictorio quie pida que la gente lea? Pues fijate que pido que LEAS otra vez para que LEAS quien ha empezado a provocar en este hilo que estaba limpio de tonterias hasta que ses posteo.

Sés ha escrito:  "Curiosa respuesta después de aquel otro hilo." Sólo eso, y tú lo conviertes en drama y lo exageras de una manera ridícula. Por lo visto tienes mucho tiempo libre, o mucho tiempo que perder, y te aburres. Enhorabuena.

CitarLo mas gracioso es que son cuatro personas las que dicen que miento o digo chorradas y son personas que no colaboran en este foro y solo saben que insultar y criticar a los demas.

Jamás he insultado, y al único al que he criticado es a ti, simplemente por decir las tonterías que dices, nada más. Hay personas que nos ofendemos cuando se falta a la verdad.


Por cierto, siempre quieres tener la última palabra. Te concederé el deseo, paso de intentar discutir, por enésima vez, con un personajillo de tal calaña.  ;)

nsL

 Yo aun no entiendo que os pasa en estos foros con zupervaca....
Yo no muero hasta la muerte -

zupervaca

 Realmente a los cuatro que dicen estas cosas de mi no les pasa nada, sencillamente se aburren y necesitan pasar el rato de alguna forma, buscan faltas de ortografia en los mensajes, intentan tirar una piedra de forma disimulada para causar polemica, dicen que quieres tener la ultima palabra para restarte credibilidad, creo que no son trolls son una nueva especie :D
Yo seguire haciendo mis cosistas y aportando lo que pueda al foro, sean chorradas o no.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.