Java - Bola en movimiento

 
Vista:

Bola en movimiento

Publicado por Octavio (2 intervenciones) el 20/06/2010 13:18:00
En estos tiempos estoy intentando aprender programación gráfica en Java, y hallé el código de cómo mover una bola en una ventana con el teclado. Lo cambié ligeramente, para que la bola no vaya más rápidamente en diagonal que en las demás direcciones, pero me percaté de un fallo. Mientras es presionada la tecla de la derecha, si es presionada la izquierda, la bola hace caso de la tecla izquierda mientras es pulsada; pero si es presionada la tecla de la izquierda y después la de la derecha, entonces continúa su avances hacia la izquierda. Y lo análogo ocurría si la bola iba hacia arriba o hacia abajo. Intentando determinar el problema en el código, lo arreglé; pero cuando soltaba la tecla derecha y presiono la tecla izquierda rápidamente, la bola se para unos instantes, y después sí obedece la instrucción, lo cual me parece inaceptable. El código siguiente que mantiene el defecto inicial indicado es el siguiente:

package Bola;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Bola extends JComponent {

private final static int ANCHO = 512, ALTO = 384, DIAMETRO = 20;
private float x, y, vx, vy;
private boolean arriba, abajo, izquierda, derecha;
public Bola(){
setPreferredSize(new Dimension(ANCHO, ALTO));
x = 10;
y = 20;

addKeyListener(new KeyAdapter(){

public void keyPressed(KeyEvent e){
actualiza(e.getKeyCode(), true);
}

public void keyReleased(KeyEvent e){
actualiza(e.getKeyCode(), false);
}

private void actualiza(int tecla, boolean presionada){
switch(tecla){
case KeyEvent.VK_UP:
arriba = presionada;
break;

case KeyEvent.VK_DOWN:
abajo = presionada;
break;

case KeyEvent.VK_LEFT:
if(derecha==true){izquierda = presionada;}
else {izquierda = presionada;}
break;

case KeyEvent.VK_RIGHT:
derecha = presionada;
break;
}
}
});

setFocusable(true);
}

private float clamp(float valor, float min, float max){
if(valor > max){return max;}
if(valor < min){return min;}
return valor;
}

private void fisica(float dt){
vx = 0;
vy = 0;

if(arriba){
if(derecha){
vy=-212;
vx= 212;
}

else if(izquierda){
vy=-212;
vx=-212;
}
else{
vy = -300;
}
}

else if(abajo){
if(izquierda){
vy= 212;
vx=-212;
}
else if(derecha){
vy= 212;
vx= 212;
}
else{
vy = 300;
}
}

else if(izquierda){
vx =-300;
}

else if(derecha){
vx= 300;
}

x = clamp(x + vx * dt, 0, ANCHO - DIAMETRO);
y = clamp(y + vy * dt, 0, ALTO - DIAMETRO);
}

public void paint(Graphics g){
g.setColor(Color.WHITE);
g.fillRect(0, 0, ANCHO, ALTO);
g.setColor(Color.RED);
g.fillOval(Math.round(x), Math.round(y), DIAMETRO, DIAMETRO);
}

private void dibuja() throws Exception {
SwingUtilities.invokeAndWait(new Runnable(){
public void run(){
paintImmediately(0, 0, ANCHO, ALTO);
}
});
}

public void cicloPrincipalJuego() throws Exception {
long tiempoViejo = System.nanoTime(), tiempoNuevo;
float dt;
while (true){
tiempoNuevo = System.nanoTime();
dt = (tiempoNuevo - tiempoViejo) / 1000000000f;
tiempoViejo = tiempoNuevo;
fisica(dt);
dibuja();
}
}

public static void main(String[] args) throws Exception {
JFrame jf = new JFrame("Bola");
jf.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
jf.setResizable(false);
Bola bola = new Bola();
jf.getContentPane().add(bola);
jf.pack();
jf.setVisible(true);
bola.cicloPrincipalJuego();
}
}

Siendo la parte que interesa considerar por este problema la del constructor. Dejándolo así no se para la bola unos instantes, al cambiar la dirección horizontal de la bola. Pero sustituyendo la parte del "switch":

case KeyEvent.VK_LEFT:
if(derecha==true){izquierda = presionada;}
else {izquierda = presionada;}
break;

Por:

case KeyEvent.VK_LEFT:
if(derecha==true){izquierda = false;}
else {izquierda = presionada;}
break;

El problema inicial es solucionado en lo que respecta al movimiento horizontal, no así con el vertical, pero aparece el problema siguiente mencionado, aunque simplemente he sustituido la variable booleana "presionada", por un valor booleano constante. Esto me parece absurdo e inaceptable, y si alguien me puede decir cómo solucionarlo se lo agradecería mucho. Quería aprender a escribir videojuegos y otros programas gráficos en Java; pero si esto no puede ser solucionado, dejaré Java y me pasaré a C++.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil

RE:Bola en movimiento

Publicado por Javier Mariscal (94 intervenciones) el 21/06/2010 04:51:48
Hola amigo espero que te ayude a resolver tu problem
Bueno por lo que veo la causa de ese problema que mencionas esta en el case
al presionar la tecla LEFT:

case KeyEvent.VK_LEFT:
if(derecha==true){
izquierda = presionada;
} else {
izquierda = presionada;
}
break;
//Haber analicemos el codigo :
Si tu presionas la tecla a la derecha la variable "derecha" sera "true", pero
si despues presionar la tecla a la izquiera pregunta si la variable "derecha=true" si eso se cumple la variable "izquiera=true" por lo que tendrias derecha he izquieda en true, creo que eso causaria problemas mencionado.l

Justo encontre el codigo que mencionas en una pagina ahi esta lo que te digo.
http://www.simplej.com/?q=node/42
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Bola en movimiento

Publicado por Octavio (2 intervenciones) el 21/06/2010 21:16:24
Cuando escribí:

case KeyEvent.VK_LEFT:
if(derecha==true){
izquierda = presionada;
}
else {
izquierda = presionada;
}
break;

Lo hice para que sea evidente que no es razonable, que poniendo "false" en lugar de la aparición primera de la variable "presionada", la bola se detenga unos instantes al cambiar su avance hacia la derecha por el de la izquierda. Sino habría puesto directamente:

case KeyEvent.VK_LEFT:
izquierda = presionada;
break;

Que hace lo mismo, y que es lo que venía en el código inicial, aunque yo sustituyo las variables con nombre ingleses por otras con nombres en español. Para solucionar el problema inicial escribí finalmente:

case KeyEvent.VK_LEFT:
if(derecha==true){
izquierda = false;
}
else {
izquierda = presionada;
}
break;

Pero entonces la bola se detenía inicialmente al cambiar su movimiento de derecha a izquierda, y poniendo "presionada" en lugar de "false" no, pero no arreglaba el problema del principio.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar