Autor Tema: Ejercicio java juego bola rebota contra barra mueve usuario precursor pong atari  (Leído 3373 veces)

manuromero73

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 40
    • Ver Perfil
Hola me gustaría recabar ayuda con el ejercicio siguiente en Java.

Arcade retro basics

Debe iniciar un programa con una ventana gráfica que ocupe aproximadamente la mitad de la pantalla del usuario, centrada sobre la misma. La ventana tendrá un panel izquierdo con borde marcado donde tendrá lugar la animación gráfica, que ocupará aproximadamente 4/5 partes de la ventana gráfica. Y un panel derecho con cinco botones: "Iniciar", "Acelerar", "Frenar", "Detener/Continuar" y "Resetear" que será 1/5 parte aproximadamente de la ventana gráfica.

Inicialmente deben aparecer dos elementos gráficos sobre el tablero: uno circular ("la bola") centrado sobre el borde superior del panel de animación o tablero. Otro rectangular ("la barra") centrado sobre el borde inferior del panel de animación o tablero. El comportamiento debe ser el siguiente:

1. Si se pulsa "Iniciar", la bola deberá moverse hacia abajo en una dirección aleatoria con una velocidad inicial predeterminada y avanzar. Si alcanza una pared lateral o la superior, debe rebotar. Si alcanza la parte inferior y choca con la barra, debe rebotar. En cambio si alcanza la parte inferior y no choca con la barra debe detenerse el movimiento y aparecer el mensaje "Game over". Inicialmente la bola va hacia abajo y rebota hacia abajo, con lo cual no podrá volver a la pared superior si antes no ha rebotado en la barra.

2. La barra deberá moverse hacia izquierda o derecha cuando el usuario pulse las teclas del cursor "flecha derecha" (la barra se mueve hacia la derecha mientras pueda. Cuando alcanza la pared, ya no se puede mover más.) o "flecha izquierda" (idem pero hacia la izquierda). De esta manera, el jugador tiene que intentar que la bola rebote en la barra para seguir jugando. Si no lo logra, llega al game over y termina el juego (aunque podrá iniciar otro juego pulsando en iniciar).

3. Si se pulsa "Acelerar" la bola incrementa su velocidad. Sucesivas pulsaciones generarán nuevos incrementos de velocidad hasta el valor tope que se determine.

4. Si se pulsa "Frenar" el comportamiento es análogo al de acelerar, pero en este caso disminuyendo la velocidad hasta el valor límite que se determine.

5. Si se pulsa "Detener/Continuar" la bola quedará quieta (detener) o reanudará su movimiento si estaba quieta (continuar)

6. Si se pulsa "Resetear" se vuelve al estado inicial (bola y barra centradas sobre el panel de animación y a la espera de que se pulse un botón).

Las pulsaciones sin sentido no generarán ninguna respuesta. Por ejemplo si la bola no ha iniciado su movimiento o si está en pausa, al pulsar en acelerar no habrá ninguna respuesta puesto que no se puede acelerar. Si se pulsa detener/continuar antes de "Iniciar" no habrá respuesta, etc.

Deberá realizar un diseño orientado a objetos con las clases que estime oportunas respetando siempre:

a) Que exista orientación a objetos (distintas clases con distintas responsabilidades)
b) Funcionalidad: un elemento circular que se mueve por la pantalla y rebota en los bordes.

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 989
    • Ver Perfil
Hola.
De momento olvida la bola y céntrate en intentar representar la barra y su movimiento.

Quisiera hacer yo un intento, pero no se cuándo podré, no tengo tiempo ni para cag..., digo.., pensar... ::)
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

YoanPupo

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 16
    • Ver Perfil

Empezando con diseñar un componente subclase de JPanel que permita visualizar la bola y la barra

debes sobreescribir el metodo paintComponent(java.awt.Graphics gc)  para tomar el control del renderizado

Crea una clase que servirá de superclase de bola y de barra (ObjetoGrafico por ejemplo) que mantendria como variables posicion (Un point2D o dos float) que mantendran la posicion de el objeto, tamaño con la longitud en x y en y,posicion anterior ,que mantendrá la ultima posicion ocupada,un boolean , que es true si el ultimo movimiento fue en x o false si fue en y,(tiene que ver con las colisiones), y vectorVelocidad, un Point2D o dos float que representa la velocidad actual del objeto.

Ademas del constructor y los get/set, necesitaras un metodo que actualice el objeto, lo mueva a su nueva posicion y otro metodo para determinar si este colisiona con otro objeto pasado como parametro(retorna boolean) la clase Rectangle2D te servirá para probar colisiones
ademas un metodo colision con que se anulará en subclase para definir el comportamiento ante una colision
y un metodo para dibujar el objeto, que recibiria como parametro un Graphics sobre el que dibujar
ademas una clase que gestione los objetos(Universo)que mantendria una lista de objetos graficos,y un metodo para actualizarlos, que itere sobre los objetos que contiene y luego probaria las colisiones, algo asi
     for(ObjetoGrafico obj : ElUniverso){
             obj.actualizar();
              for (ObjetoGrafico otro : ElUniverso){
                     if(obj.colisionaCon(otro)){
                            obj.hayColision(otro);


                      }
}
              }
el metodo actualizar seria asi
public void actualizar(){
    if(ultimoEnX){
posicionAnterior=posicion.clone();
posicion.y+=vectorVelocidad.y;
ultimoEnX =true;
}else{
  posicion.y+=vectorVelocidad.y;
ultimoEnX=false;


}
este metodo mueve el objeto alternativamente en x y en la siguiente llamada en yx ya veras para que
el metodo hay colision esta en blanco en esta clase
el metodo de dibujo husaria el metodo fillRect(int x,int y,int width,int height) para dibujar un rectangulo con la posicion y tamqño del objeto
Una subclase Bola representaria la pelota,el vectorVelocidad se crearia con valores aleatorios, y el metodo hayColision seria asi
public void hayColision(ObjetoGrafico otro){
posicion=ultimaPosicion;
if(ultimoEnX){
vectorVelocidad.x=-vectorVelocidad.x;
}else{
vectorVelocidad.y=-vectorVelocidad.y;
}
}
el efecto conseguido es que al ocurrir una colision se retorna el objeto a la posicion anterior,y se comprueba el ultimo movimiento, si fue en x el valor x de velocidad se invierte, en caso contrario se invierte y, esto consigue el efecto de rebote.
el metodo de dibujo simplemente usaria el metodo fillOval(int x,int y,int width,int height)de Graphics para dibujar la bola
empieza intentando eso,coloca un objeto bola encerrado entre cuatro ObjetoGrafico y ve si se comporta como quieres, ahora no tengo a mano una PC, luego puedo darte codigo mas completo

YoanPupo

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 16
    • Ver Perfil
Aun necesitas ayuda?

manuromero73

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 40
    • Ver Perfil
HOla, sí, sigo interesado en poder resolver esto pero no tengo nivel de programacion suficiente en cuanto a codigo y también en cuanto a conceptos como tomar el control del renderizado o vectorVelocidad creo que hay partes matematicas que no son faciles

YoanPupo

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 16
    • Ver Perfil
Los vectores son el medio para representar coordenadas x;y, o x;y;z para 3d, son la base del funcionamiento de los juegos

Para renderizar en swing solo creas una clase qie herede de JComponent y anulas el metodo paint(Graphics gc)

Dentro de este usas el objeto Graphics para dibujar, este tiene metodos para dibujar lineas, rectangulos ,elipses, poligonos, curvas, imagenes, y controlar el color
Primero dibujas un rectangulo con el color de getBackground() para borrar la imagen anterior y luego dibujas lo que quieras

Para crear el bucle que actualice constantemente la pantall a puedes usar la clase java.swing.Timer, este se construye con un delay o retardo entre actualizaciones , y un objeto ActionListener(una subclase realmente ya que es una interfaz) ,cuando se inicia ejecuta el codigo  delActionListener una y otra vez.
Adjunto un zip con el codigo completo, no es identico a como querias, pero es muy modificable, la "raqueta" se mueve con el mouse, y cada tantos rebotes se agrega otra bola, señalo que las clases del paquete gameSystem son muy genericas y pueden reutilizarse en otros minijuegos

YoanPupo

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 16
    • Ver Perfil
Te sirvió?, dime si no entiendes algo

manuromero73

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 40
    • Ver Perfil
Hola, me da un error de compilación en public class GameBoard en el metodo

Código: [Seleccionar]
    public void slow() {
        for (GameObject o : getWorld().getContent()) {
            if (o instanceof Ball ball) {
                float ballSpeed = ball.getSpeedVector().lenght();

                if (ballSpeed > MIN_SPEED) {
                    ball.getSpeedVector().mult(0.8f);
                }
            }
        }
    }

En la línea if (o instanceof Ball ball) marca el error --------  ')' expected

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 989
    • Ver Perfil
Hola, me da un error de compilación en public class GameBoard en el metodo

En la línea if (o instanceof Ball ball) marca el error --------  ')' expected

Prueba a quitar el segundo ball, en minúscula. Ahí solo debería interesar el nombre de la clase, que es Ball (mayúscula)

Citar
if (o instanceof Ball ball)
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

YoanPupo

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 16
    • Ver Perfil
Cambia el if quitando el ball
Y agrega en el bloque if esta linea

Ball ball=(Ball)o;

el error probablemente sea por tu version del JDK o por la configuracion del IDE, porque esta funcionalidad con instanceof es relativamente reciente

YoanPupo

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 16
    • Ver Perfil
Probablemente se repita en otros instanceof( hay varios en el codigo de gestion de colisiones) solo repite el proceso de mover la varizble del if a una linea con casting dentro del bloque
« Última modificación: 01 de Marzo 2024, 17:16 por YoanPupo »

manuromero73

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 40
    • Ver Perfil
Hola gracias ya he logrado que compile y la ejecucion del juego modificando

            if (o instanceof Ball ball) {

por

            if (o instanceof Ball) {
                Ball ball=(Ball)o;


o lo mismo en otra parte donde aparece en lugar de una o, una a.

Es bastante parecido con lo que queria hacer aunque aqui van apareciendo varias bolas conforme se avanza en el juego, no hay una sola bola. El boton + seria similar a acelerar, el boton - seria similar a frenar. Aunque el boton - parece que responde bien sin embargo hay ocasiones en que por mucho que pulso el boton + no acelera.

Por otro lado el mando de la barra de rebote no esta en las teclas del cursor, sino en el ratón. Y una cosa con la que me he encontrado es que a veces aunque yo intente mover la barra para colocarla en determinada posicion, no puedo moverla porque se queda como si estuviera bloqueada en un sitio y no responde y cuando voy a colocarla para lograr el rebote de la bola ya la bola ha tocado el fondo y no se puede continuar la partida.


YoanPupo

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 16
    • Ver Perfil
Las bolas extra no son un error, el codigo agrega mas cuando se supera cierto record, si quieres eliminar este comportamiento elimina o comenta la llamada a addBall que esta en el metodo update() de la clase GameBoard
La barra es controlada por el movimiento del cursor MIENTRAS ESTÉ EN EL AREA DE JUEGO, el evento que mueve la barra esta asociado al componente GameBoard, asi que la barra se detendra si el cursor sale del area de juego, ejemplo hacia la barra de titulo o la zona de los botones
La clase GameBoard tiene un metodo setBarPosition(float y) que permite establecer donde esta la barra en la horizontal, en la clase principal Phong se le asigna la posicion del cursor cursor, si quieres pasarlo al teclado no es dificil
La razon del control por mouse es que en lo personal el teclado se hacia injugable, era casi imposible atravekar a tiempo el campo antes que la bola, ademas, el juego se me hacia monotono porque el rebote era siempre igual, asi que al rebotar con la barra a la bola se le agrega la velocidad que tiene la barra al momento del choque ( algo que ademas aumenta el realismo), tambien fue porque querias el resto de controles con botones, y si estabas jugando y , por ejemplo, apretabas "frenar" el foco( o sea, quien escucha al teclado) pasaria a ese boton, y no podrias mover la barra
 Aun asi, si quieres puedo indicarte que cambiar para jugar con el teclado
  Asegurate de estudiar el codigo, encontraras que puedes hacerle varios cambios

manuromero73

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 40
    • Ver Perfil
Uno de los problemas que he encontrado es que en ocasiones la bola va cayendo despacio y muy horizontal, casi imperceptiblemente, y en este caso hay que esperar un buen tiempo hasta que llega a la parte inferior para poder rebotar o caer. En estos casos aunque pulso el botón + para tratar de acelerar la velocidad del movimiento la bola no acelera, o al menos no se percibe que acelere.
Tambien ocurre que si la bola esta cayendo rapido y pulso el - para ralentizarla, puedo hacer que se mueva muy muy despacio. Sin embargo si tras hacer esto pulso + para acelerar ya no se incrementa la velocidad sino que sigue cayendo igual de lenta que iba, no responde si intento acelerarla.

YoanPupo

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 16
    • Ver Perfil
Ya encontré el problema, un pequeño error logico en el uso de Vector2D.ORIGIN_POINT
El error venia del constructor de la clase GameObject y del metodo lenght() de Vector2D
Solo reemplaza las clases GameObject y GameBoard por estas y listo
Como mejoria te sugiero pasar el control del juego(inicio, pausa  ,acelerar, frenar) al teclado y eliminar los botones

 

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".