Anuncios Google

Duda sobre movimiento y eventos de ratón en juego Java

Verán, estava creando un juego java, en el cual un personaje (imagen) se mueve sobre un tablero creado con la clase Graphics. Hasta ahi todo bien, el problema es que gera un movimiento fluido al dejar mantenida la tecla de avanzar, y mi intencion era que avanzase un cuadradito cada vez que se pulsase el botón sin importar si se deja pulsado o no.

Despues, proximamente, tenía intencion de hacer que el personaje se moviese seleccionandolo (boolean) y mas tarde haciendeo clik derecho con el ratón para que apareciese un cuadro emergente con distintas opciones (mover, atacar, defender, etz). Les escrivo a continuacion el codigo del movimiento para que vean como lo he echo:

 

public void act() {
		super.act();
		x+=vx;
		y+=vy;
		if (x < 0 ) 
		  x = 0;
		if (x > Stage.PLAY_WIDTH - getWidth())
		  x = Stage.PLAY_WIDTH - getWidth();
		if (y < 0 )
		  y = 0;
		if ( y > Stage.PLAY_HEIGHT-getHeight())
		  y = Stage.PLAY_HEIGHT - getHeight();
	}
 
	public int getVx() { return vx; }
	public void setVx(int i) {vx = i;	}
 	public int getVy() { return vy; }
  public void setVy(int i) {vy = i;	}
 
 
  protected void updateSpeed() {
  	vx=0;vy=0;
  	if (down && MOV_RESTANTES>0){
            vy = PLAYER_SPEED;
            MOV_RESTANTES--;
            ABAJO=true;
            ARRIBA=false;
            IZQUIERDA=false;
            DERECHA=false;
        }
  	if (up && MOV_RESTANTES>0){
            vy = -PLAYER_SPEED;
            MOV_RESTANTES--;
            ARRIBA=true;
            ABAJO=false;
            IZQUIERDA=false;
            DERECHA=false;
        }
  	if (left && MOV_RESTANTES>0){
            vx = -PLAYER_SPEED;
            MOV_RESTANTES--;
            IZQUIERDA=true;
            ARRIBA=false;
            ABAJO=false;
            DERECHA=false;
        }
  	if (right && MOV_RESTANTES>0 ){
            vx = PLAYER_SPEED;
            MOV_RESTANTES--;
            DERECHA=true;
            IZQUIERDA=false;
            ARRIBA=false;
            ABAJO=false;
        }
  }
 
 
  public void keyReleased(KeyEvent e) {
   	switch (e.getKeyCode()) {
  		case KeyEvent.VK_DOWN : down = false;break;
		  case KeyEvent.VK_UP : up = false; break;
		  case KeyEvent.VK_LEFT : left = false; break; 
		  case KeyEvent.VK_RIGHT : right = false;break;
   	}
   	updateSpeed();
  }
 
  public void keyPressed(KeyEvent e) {
  	switch (e.getKeyCode()) {
		  case KeyEvent.VK_UP : up = true; break;
		  case KeyEvent.VK_LEFT : left = true; break;
		  case KeyEvent.VK_RIGHT : right = true; break;
		  case KeyEvent.VK_DOWN : down = true;break;
		  case KeyEvent.VK_SPACE : fire(); break;
  	}
  	updateSpeed();
  }<hr />

Editado: Movido a Tecnicas de programacion y otros lenguajes, postear en el lugar incorrecto incumple las Normas de la Comunidad, antes de volver a postear por favor revíselas.| AORV


  • ABEL


Anuncios Google

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de abelreyes

Hola de nuevo a


Hola de nuevo a todos;
Despues de solucionar el primer problema, con el movimiento del jugador, me he topado con otro, el movimiento que deven tener los enemigos.
Veran, la clase que controla a los enemigos (Monster.java), vendría siendo exactamente igual que la clase Player.java, con la diferencia de que esta primera no contiene los KeyEvent(); .
En la clase principal del juego (Juego.java), es donde esta el codigo que controla el numero y la posicion de los personajes que se crean durante la ejecucción. He aqui ese fragmento de codigo:

	public void initWorld() {
    player = new Player(this);
    player.setX(20);
    player.setY(40);
 
    actors = new ArrayList();
    monsters = new ArrayList();
    for (int i = 0; i < 5; i++){
      Monster m = new Monster(this);
      m.setX(i*80);
      m.setY( i*100 );
      m.setVx(00);
      actors.add(m);
      monsters.add(m);
      //Movimiento enemigos
      if(player.x-m.x<=0){
         m.setVx(-1);
         Monster.down=true;
         Monster.up=false;
         Monster.left=false;
         Monster.right=false;
      }
      else if(player.x-m.x>=0){
         m.setVx(1);
         Monster.up=true;
         Monster.down=false;
         Monster.left=false;
         Monster.right=false;
      }
      if(player.y-m.y<=0){
         m.setVy(-1);
         Monster.left=true;
         Monster.up=false;
         Monster.down=false;
         Monster.right=false;
      }
      else if(player.y-m.y>=0){
         m.setVy(1);
         Monster.right=true;
         Monster.up=false;
         Monster.left=false;
         Monster.down=false;
      }
    }

Las ultimas lineas las he añadido recientemente, para intentar que los monstruos se dirigan hacia el jugador (Mas tarde ya lo condicionare más, cada cosa en su momento)
Despues, exsiste un metodo llamado "updateWorld()", en el cual, en un principio, se actualizava el movimiento del jugador, el cual ahora he dejado así:
	public void updateWorld() {
		int i = 0;
                int e = 0;
		while (i < actors.size()) {
			Actor m = (Actor)actors.get(i);
			if (m.isMarkedForRemoval()) {
				actors.remove(i);
			} else {
				m.act();
				i++;
			}
		}
                while (e < monsters.size()) {
			Monster a = (Monster)monsters.get(e);
			if (a.isMarkedForRemoval()) {
				monsters.remove(e);
			} else {
				a.act();
				e++;
			}
		}
		player.act();
 
	}

Prove añadiendo, bajo "player.act();" "monster.act();", pero marcava un error.

Finalmente, al ejecutar el codigo con estos cambios, los monstruos, se dirigen hacia la direccion en la que estas, ya sea vertical o horizontal, pero no cambia de dirección durante la ejecucion...

No estoy muy seguro de como devo hacerlo,...

Muchas gracias a todos ! :)


  • ABEL

Imagen de abelreyes

Aprovechando que tengo el

Aprovechando que tengo el tema abierto, como ago para añadir una JProgressBar en el juego?

Obviamente, usar:

JProgressBar barra=new JProgressBar();
 
barra.setVisible(true);

[...] No me ha servido de nada.

He mirado el codigo que genera NetBeans cuando añades una Barra de progreso desde la paleta y no lo he entendido.

¿Me echas una mano?

Gracias :)


  • ABEL

Imagen de Loopin

No he usado nunca

No he usado nunca JProgressBar, pero supongo que con la API no tendras ningun problema.

Saludos y ya me cuentas.

Imagen de Loopin

Bueno, por partes: Para

Bueno, por partes:

Para evitar que el cuadradito se mueva indefinidamente yo haria lo siguiente en el metodo KeyPressed:

if(!pulsado){

---codigo correspondiente---

}

pulsado=true;

Y lo siguiente en el KeyReleased:

---codigo correspondiente---

pulsado=false;

En cuanto a hacer click secundario sobre un personaje y hacer aparecer un cuadro emergente, pues supongo que la clase Personaje debera heredar de JComponent para poder implementar escuchadores de eventos. Y dependiendo del evento, crear una ventana emergente, y seleccionar opciones y tal. 

 

Espero que te sirva. 

Un saludo.


Imagen de abelreyes

Perdona, pero el codigo no

Perdona, pero el codigo no funciona...
Lo unico que hace añadir un if() en el metodo keypresed es que no se puedan pulsar dos teclas a la vez, pero sigue siendo un movimiento continuo.
Alguna otra idea? Muchas gracias :)


  • ABEL

Imagen de Loopin

public void

public void keyReleased(KeyEvent e) {
    if(!pulsado){
   	switch (e.getKeyCode()) {
  		case KeyEvent.VK_DOWN : down = false;break;
		  case KeyEvent.VK_UP : up = false; break;
		  case KeyEvent.VK_LEFT : left = false; break; 
		  case KeyEvent.VK_RIGHT : right = false;break;
   	}
   	updateSpeed();
     }
     pulsado=true;
  }
 
  public void keyPressed(KeyEvent e) {
  	switch (e.getKeyCode()) {
		  case KeyEvent.VK_UP : up = true; break;
		  case KeyEvent.VK_LEFT : left = true; break;
		  case KeyEvent.VK_RIGHT : right = true; break;
		  case KeyEvent.VK_DOWN : down = true;break;
		  case KeyEvent.VK_SPACE : fire(); break;
  	}
  	updateSpeed();
        pulsado=false;
  }

¿Seguro que no funciona? Si la variable pulsado esta a true, no entrara en el if por muchos eventos de teclado que generes manteniendo pulsada una tecla. Al levantarla, le das paso a que si entre. El booleano debe ser un atributo de la clase.

Un saludo.


Imagen de abelreyes

Perdona pero,... ¿Has


Perdona pero,... ¿Has colocado el if() en el keyRealsed ?
No devería ir en keyPresed ?
He provado el codigo que me has mandado, y poniendo el if() en keyPresed y nada, el movimiento sigue siendo continuo, no lo entiendo...
No se que mas hacer. Aunque mas tarde, cuando aga la parte de popUpMenu tendré que cambiar el codigo.

Muchas gracias por toda tu colaboracion :)
¡Cuidate!


  • ABEL

Imagen de Loopin

Uff tio, perdoname es

Uff tio, perdoname es correcto lo que dices, se me ha traspapelado el keyPressed con el Released. Te pongo un ejemplo en un main, incluso con keyTyped (con keyPressed es identico):

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
 
import javax.swing.JFrame;
 
 
public class Prueba{
 
	static boolean pulsado;
	public static void main(String[] args) {
		JFrame ventana=new JFrame();
		ventana.setVisible(true);
		ventana.addKeyListener(new KeyListener() {
 
			public void keyTyped(KeyEvent e) {
				if(!pulsado)
					System.out.print("a");
				pulsado=true;
			}
 
			public void keyPressed(KeyEvent e) {
 
 
			}
 
			public void keyReleased(KeyEvent e) {
				pulsado=false;
			}
		});
	}
 
}


Imagen de abelreyes

Nada de nada... Ahora el

Nada de nada... Ahora el movimiento del personaje es algo distitno. No te permite moverte en diagonal, como lo hacia en un principio, pero sigue siendo un movimiento continuo. He provado tambien ha cambiar el Presed por Typed como añades en el ejemplo, pero nada, es más, ni se mueve.

Muchas gracias por toda tu colaboracion ! :)


  • ABEL

Imagen de joserc87

Creo que se cual puede ser el problema.

La variable pulsado es innecesaria. Pulsado, equivaldría a (up || down || right || left). En tu código estás diciendo que si hay una tecla pulsada, no compruebes si hay otra, por lo que si pulsas arriba e inmediatamente después la derecha, esta última la va a obviar, moviéndose hacia arriba.

La forma más rápida de solucionarlo tal y como lo estais haciendo vosotros sería:

public void keyReleased(KeyEvent e) {
	boolean actualizar=false;
	switch (e.getKeyCode()) {
		case KeyEvent.VK_DOWN	: if (down)actualizar=true; down = false;break;
		case KeyEvent.VK_UP	: if (up)actualizar=true; up = false; break;
		case KeyEvent.VK_LEFT	: if (left)actualizar=true; left = false; break; 
		case KeyEvent.VK_RIGHT	: if (right)actualizar=true; right = false;break;
   	}
	if (actualizar)
   		updateSpeed();
     }
  }
 
  public void keyPressed(KeyEvent e) {
	boolean actualizar=false;
  	switch (e.getKeyCode()) {
		case KeyEvent.VK_UP	: if (!up)actualizar=true; up = true; break;
		case KeyEvent.VK_LEFT	: if (!left)actualizar=true; left = true; break;
		case KeyEvent.VK_RIGHT	: if (!right)actualizar=true; right = true; break;
		case KeyEvent.VK_DOWN	: if (!down)actualizar=true; down = true;break;
		case KeyEvent.VK_SPACE	: fire(); break;
  	}
	if (actualizar)
  		updateSpeed();
  }

Aunque la forma correcta sería que los keyPressed y keyReleased no alterasen el estado del juego diréctamente, sino que solo cambiasen las variables up, left, right down y DISPARAR y el act, al principio, se llamase a update speed. De hecho, yo creo que quitando en tu código original el updateSpeed que hay en los keyPressed/relased y poniéndolo al principio de act, funcionaría perfectamente :D.

Como moraleja, siempre es bueno separar las cosas (las entradas/salidas de la modificación de las variables internas y de la representación), de forma que primero mires todas las entradas (ya sean de teclado o de ratón), después modifiques el estado interno del modelo y finalmente lo representes, siempre en ese orden.

Saludos y espero que te sirva :)


Be pointer my friend...

Dennis Ritchie. Padre de C y cocreador de UNIX.

R.I.P.

 

Imagen de abelreyes

uu' Me ha costado bastante


uu' Me ha costado bastante entender la explicacion (Tengo poca practica en java, tengo que aclarar conceptos aun).
He provado el codigo, y ahora estamos como al principio, movimiento libre por todo el mapa :S
Me esta dando muchos dolores de cabeza este codigo...

Muchas gracias a todos, de verdad, que soys muy grandes :)

Saludos (Y)


  • ABEL

Imagen de joserc87

Que raro

Estaba convencido de que ese código funcionaría. Tendría que probarlo para encontrar el error.

¿Has probado a poner el update en el método act en lugar de en la actualización de botones? Así, se actualizarían todas las variables up/down/etc todas juntas y en cada iteración actualizarías la velocidad según las teclas que estén pulsadas en ese momento, no según el número de pulsaciones. Me explico:

- Si colocas el update en keyPressed o keyReleased, llamas a la función tantas veces como pulses o levantes el botón.

- Si lo colocas en act, solo se llamará una vez, por lo que te quitarás todos los dolores de cabeza.

Prueba a ver que tal y nos cuentas

Saludos!

 


Be pointer my friend...

Dennis Ritchie. Padre de C y cocreador de UNIX.

R.I.P.

 

Imagen de abelreyes

Finalmente, arto de provar,


Finalmente, arto de provar, incluso lo que me dijiste, puse el siguiente codigo:

public class Player extends Actor {
	protected static final int PLAYER_SPEED = 5;
	protected static int vx;
	protected static int vy;
	private boolean up,down,left,right;
        protected static boolean ABAJO=false;
        protected static boolean ARRIBA=true;
        protected static boolean IZQUIERDA=false;
        protected static boolean DERECHA=false;
        protected static int MOV_RESTANTES=300;
        protected static boolean BALA_ACTIVA=false;
        protected static boolean pulsado=false;
        public static int VIDA=100;
        private int shields;
        public static final int MAX_SHIELDS = 100;
        protected static boolean ACTIVADO=true;
 
	public Player(Stage stage) {
		super(stage);
		setSpriteNames( new String[] {"cruz.png"});
                shields = MAX_SHIELDS;
 
	}
 
	public void act() {
		super.act();
		x+=vx;
		y+=vy;
		if (x < 0 ) 
		  x = 0;
		if (x > Stage.PLAY_WIDTH - getWidth())
		  x = Stage.PLAY_WIDTH - getWidth();
		if (y < 0 )
		  y = 0;
		if ( y > Stage.PLAY_HEIGHT-getHeight())
		  y = Stage.PLAY_HEIGHT - getHeight();
 
	}
 
	public int getVx() { return vx; }
	public void setVx(int i) {vx = i;	}
 	public int getVy() { return vy; }
  public void setVy(int i) {vy = i;	}
 
 
  protected void updateSpeed() {
  	vx=0;vy=0;
  	if (down && MOV_RESTANTES>0 && VIDA>0 && !ACTIVADO){
            vy = PLAYER_SPEED;
            MOV_RESTANTES--;
            ABAJO=true;
            ARRIBA=false;
            IZQUIERDA=false;
            DERECHA=false;
        }
  	if (up && MOV_RESTANTES>0 && VIDA>0 && !ACTIVADO){
            vy = -PLAYER_SPEED;
            MOV_RESTANTES--;
            ARRIBA=true;
            ABAJO=false;
            IZQUIERDA=false;
            DERECHA=false;
        }
  	if (left && MOV_RESTANTES>0 && VIDA>0 && !ACTIVADO){
            vx = -PLAYER_SPEED;
            MOV_RESTANTES--;
            IZQUIERDA=true;
            ARRIBA=false;
            ABAJO=false;
            DERECHA=false;
        }
  	if (right && MOV_RESTANTES>0 && VIDA>0 && !ACTIVADO){
            vx = PLAYER_SPEED;
            MOV_RESTANTES--;
            DERECHA=true;
            IZQUIERDA=false;
            ARRIBA=false;
            ABAJO=false;
        }
  }
 
 
public void keyReleased(KeyEvent e) {
	switch (e.getKeyCode()) {
		case KeyEvent.VK_DOWN	: ACTIVADO=false; down = false;break;
		case KeyEvent.VK_UP	: ACTIVADO=false; up = false; break;
		case KeyEvent.VK_LEFT	: ACTIVADO=false; left = false; break; 
		case KeyEvent.VK_RIGHT	: ACTIVADO=false; right = false;break;
   	}
     }
 
 
  public void keyPressed(KeyEvent e) {
  	switch (e.getKeyCode()) {
		case KeyEvent.VK_UP	: ACTIVADO=true; up = true; break;
		case KeyEvent.VK_LEFT	: ACTIVADO=true; left = true; break;
		case KeyEvent.VK_RIGHT	: ACTIVADO=true; right = true; break;
		case KeyEvent.VK_DOWN	: ACTIVADO=true; down = true;break;
		case KeyEvent.VK_SPACE	: fire(); break;
                case KeyEvent.VK_A      : ataqueEspada(); break;
                case KeyEvent.VK_ENTER      : MOV_RESTANTES=300; break;
  	}
        updateSpeed();
  }

Pero no parece seguir ninguna norma al moverse, hace lo que quiere.
A veces se mueve, a veces no. Cuando disparas, puedes moverte en una direccion, pero no cambiarla.
Si no pulsas espacio para disparar, no puedes moverte.

Gracias !


  • ABEL

Imagen de joserc87

Vale.

Perdón, pero es que había malentendido tu problema. He vuelto a leer lo del principio y ya se que es lo que quieres hacer. Si no he entendido mal quieres que al pulsar un botón se mueva tu jugador, pero solo cuando se pulsa el botón, si lo dejas pulsado no quieres que se mueva, no?

Si es eso, la solución es bastante simple. Simplemente haces que al terminar la función act se "levanten" las teclas haciendo que up=down=left=right=false;. Imaginemos que el usuario pulsa el botón derecho. Entonces:

- Se genera un keyPressed y right=true;

- Cuando se ejecute act, se actualizará la velocidad, y se cambiará la posición (hacia la derecha, ya que right==true).

- Al final de act, se ponen todas a false.

- La siguiente vez que se ejecute act, right==false, por lo que no se hará nada.

- Cuando se levante el botón y se vuelva a pulsar, volverá a ser true.

Un par de aclaraciones:

- El metodo keyReleased no te sirve para nada realmente.

- El updateSpeed te lo he puesto en act, porque es mejor que esté ahí, creeme.

- Los disparos no te conviene que los realices en keyPressed. Yo pondría variables como con la dirección y generaría los disparos en act.

- Te he quitado el ACTIVADO de los ifs, porque ya no hace falta.

- Si en updateSpeed, en if (up) por ejemplo pones DERECHA o IZQUIERDA=false, no podrás hacer diagonales. if(up) e if(down) solo deberían modificar ARRIBA y ABAJO, y right y left DERECHA e IZQUIERDA.

Bueno, aquí está el código:

public class Player extends Actor {
	protected static final int PLAYER_SPEED = 5;
	protected static int vx;
	protected static int vy;
	private boolean up,down,left,right;
        protected static boolean ABAJO=false;
        protected static boolean ARRIBA=true;
        protected static boolean IZQUIERDA=false;
        protected static boolean DERECHA=false;
        protected static int MOV_RESTANTES=300;
        protected static boolean BALA_ACTIVA=false;
        protected static boolean pulsado=false;
        public static int VIDA=100;
        private int shields;
        public static final int MAX_SHIELDS = 100;
        protected static boolean ACTIVADO=true;
 
	public Player(Stage stage) {
		super(stage);
		setSpriteNames( new String[] {"cruz.png"});
                shields = MAX_SHIELDS;
 
	}
 
	public void act() {
		super.act();
		// Por norma general, las actualizaciones del modelo se hacen todas en el mismo sitio.
		// Si actualizas la velocidad en métodos como keyPressed, tendrás muchos dolores de cabeza
		updateSpeed ();
		x+=vx;
		y+=vy;
		if (x < 0 ) 
		  x = 0;
		if (x > Stage.PLAY_WIDTH - getWidth())
		  x = Stage.PLAY_WIDTH - getWidth();
		if (y < 0 )
		  y = 0;
		if ( y > Stage.PLAY_HEIGHT-getHeight())
		  y = Stage.PLAY_HEIGHT - getHeight();
 
 		// Para finalizar, hacemos que todos los botones no estén pulsados
		// para que en el siguiente ciclo no se vuelva a mover
		// evitando el movimiento continuo
		up=down=left=right=false;
	}
 
	public int getVx() { return vx; }
	public void setVx(int i) {vx = i;	}
 	public int getVy() { return vy; }
  public void setVy(int i) {vy = i;	}
 
 
  protected void updateSpeed() {
  	vx=0;vy=0;
  	if (down && MOV_RESTANTES>0 && VIDA>0){
            vy = PLAYER_SPEED;
            MOV_RESTANTES--;
            ABAJO=true;
            ARRIBA=false;
        }
  	if (up && MOV_RESTANTES>0 && VIDA>0){
            vy = -PLAYER_SPEED;
            MOV_RESTANTES--;
            ARRIBA=true;
            ABAJO=false;
        }
  	if (left && MOV_RESTANTES>0 && VIDA>0){
            vx = -PLAYER_SPEED;
            MOV_RESTANTES--;
            IZQUIERDA=true;
            DERECHA=false;
        }
  	if (right && MOV_RESTANTES>0 && VIDA>0){
            vx = PLAYER_SPEED;
            MOV_RESTANTES--;
            DERECHA=true;
            IZQUIERDA=false;
        }
  }
 
 
public void keyReleased(KeyEvent e) {
	switch (e.getKeyCode()) {
		case KeyEvent.VK_DOWN	: down = false;break;
		case KeyEvent.VK_UP	: up = false; break;
		case KeyEvent.VK_LEFT	: left = false; break; 
		case KeyEvent.VK_RIGHT	: right = false;break;
   	}
     }
 
 
  public void keyPressed(KeyEvent e) {
  	switch (e.getKeyCode()) {
		case KeyEvent.VK_UP	: up = true; break;
		case KeyEvent.VK_LEFT	: left = true; break;
		case KeyEvent.VK_RIGHT	: right = true; break;
		case KeyEvent.VK_DOWN	: down = true;break;
		case KeyEvent.VK_SPACE	: fire(); break;
                case KeyEvent.VK_A	: ataqueEspada(); break;
                case KeyEvent.VK_ENTER	: MOV_RESTANTES=300; break;
  	}
	// He quitado de aqui el updateSpeed, ya que aquí no pinta nada.
  }

No se si funcionará (espero que sí), pero lo que me interesa es que cojas la idea, para que si en cuentras algún fallo, lo puedas arreglar.

Saludos!


Be pointer my friend...

Dennis Ritchie. Padre de C y cocreador de UNIX.

R.I.P.

 

Imagen de abelreyes

Buaa ! Muchas gracias, de


Buaa ! Muchas gracias, de verdad.
Al fin funciona... Lo unico que ahora siempre dispara en diagonal, no se porque, ya investigare.

Muchas gracias por tu colaboracion :)
Saludos !


  • ABEL

Imagen de Loopin

Pues que raro, habra que

Pues que raro, habra que buscarse alguna otra manera de hacerlo, ahora mismo no se me ocurre nada :S

Imagen de abelreyes

Muchas gracias, lo provare en

Muchas gracias, lo provare en cuanto pueda.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.