Source: http://javaparanulos.blogspot.com.es/2012_11_01_archive.html
Timestamp: 2017-02-22 08:21:01+00:00

Document:
JavaBlog: noviembre 2012
Animación de Imágenes en Java
En esta entrada del blog,
voy a enseñarte cómo hacer imágenes con animación en Java. Para
ello, lo primero que vamos a necesitar son...lo has adivinado:
imágenes. Pueden ser fotos, o pueden ser dibujos sencillos, pero eso
sí, tienen que mostrar movimientos consecutivos; por ejemplo, un
pájaro subiendo y bajando las alas, o una cara abriendo y cerrando
Si sabes utilizar
Photoshop, Gimp o cualquier otro programa por el estilo, enhorabuena,
dale rienda suelta a tu imaginación para crear las imágenes que
desees (y ya puestos, compártelas con nosotros).
Si por el contrario, eres
como yo, que a lo más que llegas es a dibujar un círculo con Paint,
pues nada, le pones dos circulitos más pequeños dentro para simular
ojos abiertos y dos líneas para simular ojos cerrados y ya tienes
una carita que parpadea. Ahora guardas los dos dibujos como .png y
También puedes añadirle
una imagen de fondo que ocupe toda la pantalla: una foto en formato
.jpg, otro dibujo o un fondo liso, lo que quieras.
Lo que vamos a hacer con
estas imágenes es, primero, crear un ArrayList para contenerlas, y
después, asignarles a cada una una duración determinada en
milisegundos. Por último, vamos a mostrarlas en pantalla en un bucle
para conseguir ese efecto de animación.
Para ello vamos a crear
una clase, Animación (qué sorpresa de nombre, ¿eh?) que contendrá
los métodos necesarios. Despues haremos otra para probarla, y
originales como somos la llamaremos AnimaciónTest.
PruebaDeAnimación tampoco está mal, pero es que es más largo. Dentro de esta clase AnimaciónTest vamos a utilizar un objeto de la clase PantallaCompleta, que creamos en una entrada anterior y que utilizamos, nunca lo adivinarías, para visualizar el resultado en una pantalla completa . Aquí puedes ver el código de esa clase.
Para que luego no te líes
con el código, te voy a explicar el significado de algunas variables
que verás en él:
frames, que en
inglés viene siendo fotogramas, es el nombre del ArrayList
actualFrame es el
número de índice de un elemento de frames
tiempoAnimación es
el tiempo que dura toda la animación tiempoTotal es la
suma de los milisegundos de duración que hemos asignado a cada
Clase Animación.java
public class Animación{
private int actualFrame;
private long tiempoAnimación;
private long tiempoTotal;
public Animación(){
frames = new ArrayList();
tiempoTotal = 0;
public synchronized void addFrame(Image image, long duración){
tiempoTotal += duración;
frames.add(new AnimFrame(image, tiempoTotal));
public synchronized void start(){
tiempoAnimación = 0;
actualFrame = 0;
public synchronized void update(long tiempoTranscurrido){
if(frames.size()&gt;1){
tiempoAnimación += tiempoTranscurrido;
if(tiempoAnimación &gt;= tiempoTotal){
tiempoAnimación = tiempoAnimación % tiempoTotal;
while(tiempoAnimación &gt; getFrame(actualFrame).endTime){
actualFrame++;
public synchronized Image getImage(){
if (frames.size() ==0){
return getFrame(actualFrame).image;
private AnimFrame getFrame(int i){
private class AnimFrame{
public AnimFrame(Image image, long endTime){
Clase AnimaciónTest.java
public class AnimaciónTest {
DisplayMode displayMode= new DisplayMode(1024, 768, 32,
DisplayMode.REFRESH_RATE_UNKNOWN);
AnimaciónTest test = new AnimaciónTest();
test.run(displayMode);
private static final long DEMO_TIME = 10000;
private PantallaCompleta pc;
private Image bgImage;
private Animación animación;
public void loadImages() {
// cargamos las imágenes
bgImage = loadImage("images/background.jpg");
Image cara1 = loadImage("images/cara1.png");
Image cara2 = loadImage("images/cara2.png");
Image cara3 = loadImage("images/cara3.png");
// creamos la animación
animación = new Animación();
animación.addFrame(cara1, 250);
animación.addFrame(cara2, 150);
animación.addFrame(cara1, 150);
animación.addFrame(cara3, 200);
private Image loadImage(String fileName) {
public void run(DisplayMode displayMode) {
pc = new PantallaCompleta();
pc.setFullScreen(displayMode, new JFrame());
pc.restoreScreen();
public void animationLoop() {
long tiempoActual = tiempoInicio;
while (tiempoActual - tiempoInicio &lt; DEMO_TIME) {
long tiempoTranscurrido =
System.currentTimeMillis() - tiempoActual;
tiempoActual += tiempoTranscurrido;
// actualizamos la animación
animación.update(tiempoTranscurrido);
// se dibuja en pantalla
Graphics g =
pc.getFullScreenWindow().getGraphics();
// una pequeña pausa
catch (InterruptedException ex) { }
// se dibuja el fondo
// se dibuja la imagen y la centramos más o menos
g.drawImage(animación.getImage(), 300, 200, null);
Yo he utilizado una imagen de fondo y tres dibujos de una cara, pero tú puedes usar el número de imágenes que quieras. Fíjate que cada imagen se puede añadir más de una vez, en distinto orden y con distinto tiempo asignado, para crear distintas animaciones. Tú puedes jugar con ello hasta encontrar la que te gusta.
En otro momento te enseñaré a añadirle otros efectos y a utilizar la clase BufferStrategy para evitar que la imagen parpadee.
¡Si tienes alguna duda, ya sabes dónde estoy!
Thread Pools en Java
En otras entradas he
explicado que son los hilos o threads, cómo crearlos y cómo
funcionan. En esta entrada voy a tratar el tema de las thread
pools, literalmente “piscinas
de hilos”. ¿Por qué se llaman así? Bueno...ni idea. Pero ya que
le han dado ese nombre, voy a utilizarlo en mi metáfora para
explicarte en que consisten.
una thread pool como un grupo de nadadores vagueando al borde de una
piscina. De vez en cuando llega un entrenador con la orden de que uno
de los nadadores tiene que recorrer la piscina de arriba abajo. A
veces todos los nadadores reciben esas órdenes, un entrenador por
cada nadador. En ocasiones hay más entrenadores que nadadores, y
los últimos en llegar tienen que esperar a que vayan regresando los
nadadores para ir dándoles de nuevo la orden de recorrer la piscina.
Y otras veces sólo algunos nadadores están nadando mientras los
otros están jugando a las cartas, esperando a que llegue algún
entrenador. Ahora
sustituye “entrenador” por “tarea” y “nadador” por “hilo”
y ya tienes una thread pool. “Vale”,
te preguntarás, “¿y por qué hacer una thread pool? ¿No es mejor
ir creando los hilos según los necesitemos?”. Pues eso va a
depender del programa en cuestión. Ten en cuenta que cada hilo que
creas ocupa lugar en la memoria. Si tienes un programa que sólo va a
tener tres o cuatro tareas distintas, pues bueno, creas tres o cuatro
hilos. Pero, ¿y si es un programa con cientos o miles de tareas?.
Cientos de hilos ocuparán bastante memoria. Y lo que es peor: tú
tendrás que escribir el código para crear todos esos hilos.Créeme,
es buena práctica separar en ese caso las tareas de los hilos en tu
código. Y tú trabajarás menos.
está la cuestión de la eficiencia. Ya sé lo que estás pensando:
“¿No es más eficiente tener un hilo para cada tarea, en lugar de
tener tareas esperando que haya un hilo libre?” Volvamos a nuestro
ejemplo de la piscina.
que en la piscina hay cien nadadores y que todos reciben la orden de
nadar a la vez. ¿Has tratado alguna vez de nadar en una piscina
abarrotada? ¿Crees que alguno de los nadadores conseguiría un
récord de velocidad? Pues tu programa lo mismo. El sistema en el que
se ejecute tendrá que repartir sus recursos entre todos los hilos a
la vez. Hagamos
ahora que los nadadores sean sólo diez, con las mismas cien tareas.
Es cierto que hay algunas tareas que tendrán que esperar a que los
nadadores vayan regresando para realizarse, pero como los nadadores
pueden ir y volver mucho más rápido, las primeras tareas serán
“visto y no visto” y el tiempo de espera de las últimas será
similar al producido si todas tuviesen un hilo propio. Y eso si todas
las órdenes se reciben a la vez, porque si los entrenadores van
llegando de forma separada, el tiempo de espera de los últimos no
será mayor que el de los primeros.
ya sabemos lo que es una thread pool, ¿pero cómo se utiliza?. Ah,
aquí entran en juego los “Ejecutores”. No, no es una película
de Schawzenegger. Los ejecutores en java son simplemente los que se
encargan de manejar la ejecución de las tareas.
tiene una clase, Executors, con métodos estáticos para la creación
de thread pools, y tres interfaces:
que simplemente ejecuta las tareas
ExecutorService,
subinterfaz de la anterior que añade nuevos métodos para controlar
ScheduledExecutorService,
subinterfaz de ExecutorService que soporta la ejecución de tareas
ellas forman parte del paquete java.util.concurrent.
A continuación, te voy a mostrar un ejemplo sencillísimo de thread pool. Vamos a crear dos clases, una que implementa la interfaz Runnable, porque los ejecutores trabajan con objetos "runnable" o "callable", y otra que contiene el método principal y donde crearemos una thread pool de 10 hilos.
Tarea.java
public class Tarea implements Runnable{
public Tarea(String name){
this.name = name;//le asignamos un nombre a cada tarea.
sleepTime = 1000;
System.out.printf("El hilo de la tarea "+this.name+" va a dormir durante %d milisegundos.\n",sleepTime);
Thread.sleep(sleepTime);//hacemos que cada hilo duerma durante 1 segundo
}catch(InterruptedException exception){
System.out.println("Este hilo ya ha dormido bastante");
EjemploThreadPool.java
public class EjemploThreadPool{
System.out.println("Comienza la ejecución");
ExecutorService ex = Executors.newFixedThreadPool(10);
Tarea t;
for(int i = 0;i&lt;200; i++){
t = new Tarea(""+i);
ex.execute(t);
¿Qué es lo que hace este programa? No gran cosa. Se limita a escribir en la consola que el hilo que está ejecutando cada tarea, a las que hemos asignado un número, va a dormir durante 1 segundo. Pero, ¿y lo que has aprendido?
Fíjate que al método execute es al que hay que darle un objeto runnable, y que el método shutdown se asegura de cerrar al finalizar las tareas. Ambos métodos pertenecen a la interfaz ExecutorService. Para crear la trhead pool hemos empleado el método newFixedThreadPool(), al que se le da un número específico de hilos. Pero existen más, como el newCachedThreadPool(), ambos de la clase Executors.
Para ampliar conocimientos, te recomiendo el tutorial sobre concurrencia de Oracle, y el libro "Java Threads", de S. Oaks y H. Wong, publicado por O´Reilly.
Y como siempre, si tienes alguna duda o comentario, ya sabes donde estamos.
Cómo crear una pantalla completa para juegos en Java
Supongamos que has estado aprendiendo Java durante algún tiempo; ya sabes todo lo que hay que saber sobre clases, objetos, métodos, polimorfismo, threads...Pero ahora quieres hacer algo realmente espectacular, como un juego (no para presumir, por supuesto, sólo para ampliar conocimientos). Y no un juego cualquiera, no una pequeña applet ni un juego embebido en una frame, sino un juego a pantalla completa, sin menús, ni barras horizontales o laterales que distraigan al jugador. Pero, ¿por dónde empezar?
Bueno, evidentemente, excede los límites de cualquier entrada de un blog el explicarte cómo hacer un juego en Java, pero lo que sí puedo hacer es mostrarte cómo crear una pantalla a tamaño completo para él. Antes de nada, vamos a aclarar algunos conceptos que necesitas saber (si ya los sabes, pues te vas directamente al código y listo).
Al diseñar un juego, hay que tener en cuenta que se tiene que poder ver en distintos ordenadores, de los que no vas a saber la resolución de los monitores ni la capacidad de la tarjeta de vídeo.¿Qué es la resolución? La pantalla de un monitor está dividida en pequeños puntitos llamados píxeles. El número de píxeles horizontales y verticales es la resolución de esa pantalla. Por ejemplo, un monitor con 800 píxeles horizontales y 600 píxeles verticales tiene una resolución de 800x600. Ten en cuenta que los píxeles se empiezan a contar desde 0, es decir 0 es el primer píxel y 799 el último.
Si tú pones una resolución en la pantalla de tu juego, pero el monitor tiene otra, la imagen no será tan nítida. Lo ideal es que el jugador pueda elegir la resolución según su monitor. Las resoluciones más utilizadas hoy en día son 800x600, 1024x768 y 1280x1024. En el código que verás después, hemos puesto una resolución fija, para no hacerlo muy extenso, pero tú puedes poner la de tu propio monitor si no es la misma.
Otro detalle en el que hay que fijarse, es en el Display Mode, o capacidad de bits de un monitor, que determina el número de colores que ese monitor puede mostrar. En nuestro ejemplo vamos a dejarlo en 32, que son 2 elevado a 32 colores (¿tienes una calculadora científica a mano? ¿no? bueno, son muchos colores) Si tu monitor es un poco más antiguo o prefieres aumentar la rapidez, puedes usar 16 bit, que son (esta me la sé) 65.536 colores.
Por último tenemos el Refresh Rate, que viene siendo la rapidez con la que la pantalla se está "repintando" una y otra vez. Lo que a ti te parece una imagen fija, en realidad no lo es, porque la luz de los píxeles se desvanece y el monitor está continuamente "encendiéndolos" de nuevo.
Ahora que ya hemos aclarado estos aspectos, para que sepas lo que son cuando los veas en el código, te voy a explicar lo que vamos a hacer. Vamos a crear una ventana, como las típicas de Windows, pero sin ninguna decoración, es decir, sin menús ni barras, ni botoncito de ningún tipo. En un juego normal, por supuesto, tienes la opción de salir cuando quieras, pero aquí, para favorecer la claridad del código y de lo que quiero enseñarte, vamos a dejar que esa pantalla se mantenga unos segundos y luego se desvanezca, que no es cuestión de que te quedes para siempre con ella. Si deseas que tenerla durante más o menos segundos, sólo tienes que cambiar el valor que yo le he puesto.
Hay algunos sistemas que no dejan que cambies el display que tienen por defecto, por lo que tendremos que asegurarnos primero de que ése no es el caso. Así que vamos a hacer dos clases, la primera será la que tenga el constructor de la pantalla, y la segunda será la que tenga el método main, donde probaremos a ver si funciona. Con ellas crearemos una pantalla completa con un color de fondo naranja y una frase en negro, que se mantendrá durante 10 segundos.
PantallaCompleta.java
public class PantallaCompleta{
private GraphicsDevice gd;//tarjeta gráfica
public PantallaCompleta(){
//hay que usar los medios del propio sistema
gd = env.getDefaultScreenDevice();
public void setFullScreen(DisplayMode dm, JFrame ventana){
ventana.setUndecorated(true);
ventana.setResizable(false);
gd.setFullScreenWindow(ventana);
//comprobamos que el sistema soporta el cambio
if(dm != null &amp;&amp; gd.isDisplayChangeSupported()){
gd.setDisplayMode(dm);
}catch(IllegalArgumentException e){}
public Window getFullScreenWindow(){
return gd.getFullScreenWindow();
//restauramos los valores previos
public void restoreScreen(){
Window w = gd.getFullScreenWindow();
TestPantallaCompleta.java
public class TestPantallaCompleta extends JFrame{
//Pon aquí los valores que prefieras
DisplayMode dm = new DisplayMode(1024,768,32,DisplayMode.REFRESH_RATE_UNKNOWN);
TestPantallaCompleta test = new TestPantallaCompleta();
test.run(dm);
public void run (DisplayMode dm){
setBackground(Color.ORANGE);
setFont(new Font("Dialog", Font.PLAIN,48));
PantallaCompleta pc = new PantallaCompleta();
pc.setFullScreen(dm, this);
//ponemos el tiempo que queremos que dure
}catch(InterruptedException ex){}
}finally{//pase lo que pase, se restaura a sus antiguos valores
if (g instanceof Graphics2D){
//difuminamos los bordes del texto
g2.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
//el texto va a aparecer 300px a la derecha y 400px hacia abajo
g.drawString("Aquí va a ir mi juego",300,400);
Eso de "antialiasing" que ves al final del código, no es que no dejes a los jugadores tener un alias, sino que sirve para que el texto aparezca como escalonado, como escrito en cuadraditos.
A continuación te dejo una captura de pantalla para que veas cómo queda con los valores que yo le he asignado.
Si quieres más información sobre cómo crear juegos en Java, te recomiendo el libro Developing Games in Java, de David Brackeen, Bret Barker y Lawrence Vanhelsuwe, editorial New Riders Publishing. El código que te muestro aquí es una versión del que aparece en este libro. No sé si hay traducción en castellano, pero como creo que es muy interesante es seguro que en otras entradas os muestre otros ejemplos sacados de él.
Además he encontrado unos tutoriales en vídeo en Youtube, que su autor no lo dice, pero yo juraría que están basados en este libro. Están en inglés, pero aunque no lo entiendas, puede que el código que muestra te sea útil. Podéis encontralos en esta página.
Drag and Drop: cómo funciona
¡Después de unos cuantos meses de ausencia, por fin he vuelto! No, no me he ido de vacaciones (que más quisiera), sino que el imponderable deber de tener que trabajar para vivir se interpuso entre este blog y yo. ¡Y mira que os pongo anuncios para que clickéis y me libréis de ese problema! Pero, nada, no os dáis por enterados. ;-)
Hablando ahora ya en serio, esta entrada esta dedicada al Drag and Drop. Para los que no sepáis lo que es, os diré que no se trata del nombre de un grupo pop, sino de ese efecto de arrastrar elementos de un lugar a otro, como cuando arrastramos ficheros de una carpeta al escritorio del ordenador.
En principio, todos los componentes de Swing soportan el Drag and Drop, pero algunos tienen instalada la forma de ejecutarlo por defecto y otros no. Para los primeros, basta con invocar el método setDragEnabled(true) y listo. Para los segundos, hay que escribir el código necesario para adaptarlo a tus necesidades.
Los componentes que tienen un mecanismo de arrastre por defecto son:
En cuanto al mecanismo para "dejar caer" los datos que queremos transferir, en estos componentes no hay que hacer nada más:
mietras que estos otros necesitan un poco más de código para funcionar:
Para los componentes que no tienen un método de trasnferencia de datos por defecto, deberemos usar la clase TransferHandler.
A continuación voy a poneros un par de ejemplos, simplificados hasta el extremo, para que veáis el funcionamiento del Drag and Drop en Java. En el primero crearemos dos selectores de color y arrastraremos el color seleccionado en el primero hasta el segundo. Fijaos que no podemos arrastrar desde los cuadraditos pequeños, sino desde la vista previa. Este primer ejemplo es una adaptación del que podéis encontrar en la siguiente página.
public class DobleColor {
JFrame frame = new JFrame("Doble Selector de Color ");
JColorChooser izquierda = new JColorChooser();
izquierda.setDragEnabled(true);
frame.add(izquierda, BorderLayout.WEST);
JColorChooser derecha = new JColorChooser();
derecha.setDragEnabled(true);
frame.add(derecha, BorderLayout.EAST);
Podéis ver aquí cómo quedaría, tras haber arrastrado el color seleccionado desde el primero hasta el segundo.
En el siguiente ejemplo, vamos a arrastrar un texto desde una etiqueta o JLabel a un campo de texto o JTextField. Para ello utilizaremos los método setTransferHandler y getTransferHandler, además de crear un evento al presionar con el ratón, para que funcione el gesto de arrastrar.
public class SimpleDnDs extends JFrame{
//Vamos a crear componentes
SimpleDnDs dnd = new SimpleDnDs();
public SimpleDnDs(){ //constructor de SimpleDnDs
JFrame frame = new JFrame("Drag and Drop");
textField = new JTextField(40);
label = new JLabel("Este es el texto a arrastrar");
//especificamos qué tipo de dato vamos a transferir
label.setTransferHandler(new TransferHandler("text"));
MouseListener ml = new MouseAdapter(){
//creamos el método para transferir
//datos al presionar con el ratón
JComponent jc = (JComponent)e.getSource();
TransferHandler th = jc.getTransferHandler();
th.exportAsDrag(jc, e, TransferHandler.COPY);
label.addMouseListener(ml);
panel.add(textField);
frame.add(panel); //añadimos el panel al marco
frame.setSize(600,600); //le ponemos las medidas que queramos
Una vez ejecutado el programa, podréis arrastrar el texto desde la etiqueta al campo de texto. Es por supuesto muy sencillito, sólo para que veáis cómo funciona, y podáis crear vuestros propios programas, jugando con distintos componentes y tipos de datos a transferir.
Para ello, recomiendo a los que sepáis inglés que echéis un ojo al tutorial de Oracle sobre Drag and Drop. Y como siempre, si tenéis dudas o comentarios, ya sabéis cómo. Además, si queréis saber cuándo publico las siguientes entradas sin tener que estar pendientes del blog, os recomiendo que os suscribáis.
Cómo crear una pantalla completa para juegos en Ja...
Plantilla Sencillo. Las imágenes de las plantillas son obra de kelvinjay. Con la tecnología de Blogger.

References: resolución 
 resolución 
 resolución 
 resolución 
 resolución 
 resolución