Autor
Tema: [SFML] Rebote de colisión (Leído 7,720 veces)
DeMoNcRaZy
Desconectado
Mensajes: 420
$~*|_
Buenas, Tengo un problema al intentar colisionar dos figuras en sfml, la cosa es que colisiona pero en vez de chocar y estarse quieto sin poder avanzar se coloca en la otra parte de la otra figura y así consecutivamente.
Aquí un vídeo previo del error: El vídeo es capturado por mi, dura 30 seg. Para mostrar el error. VIDEO sf:: FloatRect rect = rec.getGlobalBounds ( ) ;
sf:: FloatRect rect2 = rec2.getGlobalBounds ( ) ;
if ( rect.intersects ( rect2) ) {
if ( rec.getPosition ( ) .x < 400 ) {
std:: cout << rec.getPosition ( ) .x << std:: endl ;
rec.setPosition ( 350 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .x > 400 ) {
rec.setPosition ( 450 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .y < 400 ) {
rec.setPosition ( rec.getPosition ( ) .x , 350 ) ;
}
if ( rec.getPosition ( ) .y > 400 ) {
rec.setPosition ( rec.getPosition ( ) .x , 450 ) ;
}
}
rec -> es el rectángulo que manejo con el keyboard.
rec2 -> es el rectángulo que está situado fijamente en el centro de la ventana.
Si supiesen a que debe deberse dicho error agradecería alguna respuesta.
Gracias.
Saludos!
En línea
Esta página web no está disponible - Google Chrome
ivancea96
Desconectado
Mensajes: 3.412
ASMático
A que se debe es algo obvio, pusiste los setPosition(). Para empezar, y dado que tienes la rect2, en vez de poner 400, 350 y 450, deberías poner los campos de la variable rect2. No es que haya un error, simplemente el concepto es incorrecto.
En línea
DeMoNcRaZy
Desconectado
Mensajes: 420
$~*|_
Intenté hacer lo que me indicaste pero no daba resultado al igual también intenté esto:
if ( rec.getPosition ( ) .x < 400 ) {
std:: cout << rec.getPosition ( ) .x << std:: endl ;
rec.setPosition ( rec.getPosition ( ) .x , rec.getPosition ( ) .y ) ;
}
Que no pueda avanzar más si colisiona sin ser posicionado, pero al igual sigue con el mismo error.
Gracias por la respuesta.
Saludos!
En línea
Esta página web no está disponible - Google Chrome
ivancea96
Desconectado
Mensajes: 3.412
ASMático
rec.setPosition ( rec.getPosition ( ) .x , rec.getPosition ( ) .y ) ;
Mira atentamente esa línea.
A parte:
Ese ejemplo que pones en el vídeo no explica nada si no indicas cuales son las coordenadas de los objetos. ¿Qué es 400?
Lo que indiqué era cambiar esos valores por valores de las variables. Poner un 400 para quien ve ese código es como poner un 7568. No dice nada. Cambia cada valor por el campo de la variable que ha de ser. No va a corregir el problema ni mucho menos, pero haré cl programa más legible y más fácil de corregir (y más fácil de rehacer en caso de que quieras cambiar la posición del cuadrado ese)
En línea
DeMoNcRaZy
Desconectado
Mensajes: 420
$~*|_
Así está repartido:
sf:: RenderWindow window( sf:: VideoMode ( 800 , 600 ) , "Colision" ) ;
//Rectangualo
sf:: RectangleShape rec( sf:: Vector2f ( 50 , 50 ) ) ;
rec.setFillColor ( sf:: Color :: Cyan ) ;
//Otro rectangulo
sf:: RectangleShape rec2( sf:: Vector2f ( 50 , 50 ) ) ;
rec2.setFillColor ( sf:: Color :: Magenta ) ;
rec2.setPosition ( 400 , 300 ) ;
En el centro de la ventana (800x600).
Código completo:
#include <SFML/Graphics.hpp>
#include <iostream>
int main( ) {
//Creamos la ventana
sf:: RenderWindow window( sf:: VideoMode ( 800 , 600 ) , "Colision" ) ;
//Rectangualo
sf:: RectangleShape rec( sf:: Vector2f ( 50 , 50 ) ) ;
rec.setFillColor ( sf:: Color :: Cyan ) ;
//Otro rectangulo
sf:: RectangleShape rec2( sf:: Vector2f ( 50 , 50 ) ) ;
rec2.setFillColor ( sf:: Color :: Magenta ) ;
rec2.setPosition ( 400 , 300 ) ;
window.setFramerateLimit ( 200 ) ;
//Si la ventana está abierta
while ( window.isOpen ( ) ) {
//Creamos un evento
sf:: Event ventana;
//Llamamos a los eventos
while ( window.pollEvent ( ventana) ) {
//Cerramos la ventana cuando se solicite
if ( ventana.type == sf:: Event :: Closed ) {
window.close ( ) ;
}
}
//Movimiento rectangulo
if ( sf:: Keyboard :: isKeyPressed ( sf:: Keyboard :: Up ) ) {
rec.move ( 0 , - 1 ) ;
}
if ( sf:: Keyboard :: isKeyPressed ( sf:: Keyboard :: Down ) ) {
rec.move ( 0 , 1 ) ;
}
if ( sf:: Keyboard :: isKeyPressed ( sf:: Keyboard :: Left ) ) {
rec.move ( - 1 , 0 ) ;
}
if ( sf:: Keyboard :: isKeyPressed ( sf:: Keyboard :: Right ) ) {
rec.move ( 1 , 0 ) ;
}
//Colisiones
if ( rec.getPosition ( ) .x < 0 ) {
rec.setPosition ( 0 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .x > 750 ) {
rec.setPosition ( 750 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .y < 0 ) {
rec.setPosition ( rec.getPosition ( ) .x , 0 ) ;
}
if ( rec.getPosition ( ) .y > 550 ) {
rec.setPosition ( rec.getPosition ( ) .x , 550 ) ;
}
sf:: FloatRect rect = rec.getGlobalBounds ( ) ;
sf:: FloatRect rect2 = rec2.getGlobalBounds ( ) ;
if ( rect.intersects ( rect2) ) {
if ( rec.getPosition ( ) .x < 400 ) {
std:: cout << rec.getPosition ( ) .x << std:: endl ;
rec.setPosition ( 350 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .x > 400 ) {
rec.setPosition ( 450 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .y < 400 ) {
rec.setPosition ( rec.getPosition ( ) .x , 350 ) ;
}
if ( rec.getPosition ( ) .y > 400 ) {
rec.setPosition ( rec.getPosition ( ) .x , 450 ) ;
}
}
//Limpiamos ventana
window.clear ( ) ;
//Dibujamos el rectangulo
window.draw ( rec) ;
window.draw ( rec2) ;
//Actualizamos ventana
window.display ( ) ;
}
}
Saludos!
En línea
Esta página web no está disponible - Google Chrome
ivancea96
Desconectado
Mensajes: 3.412
ASMático
Pues cambia el .x<400 por rec2.left, y así con cada uno. Los valores, en variables, especialmente en este tipo de programa.
En línea
DeMoNcRaZy
Desconectado
Mensajes: 420
$~*|_
He probado tu forma pero no funcionaba y al igual con tu idea intente hacer algo similar haber si funcionaba al principio parecía que iba a funcionar pero al final no.
Probé con algo así:
sf:: FloatRect rect = rec.getGlobalBounds ( ) ;
sf:: FloatRect rect2 = rec2.getGlobalBounds ( ) ;
if ( rect.intersects ( rect2) ) {
if ( rec.getPosition ( ) .x < rect2.left ) {
rec.setPosition ( rec2.getPosition ( ) .x - 50 , rec2.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .x > rect2.left ) {
rec.setPosition ( rec2.getPosition ( ) .x + 50 , rec2.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .y < rect2.left ) {
rec.setPosition ( rec2.getPosition ( ) .x , rec2.getPosition ( ) .y - 50 ) ;
}
if ( rec.getPosition ( ) .y > rect2.left ) {
rec.setPosition ( rec2.getPosition ( ) .x , rec2.getPosition ( ) .y + 50 ) ;
}
}
Puse rect2.left ya que tenia que declararla y no valía rec2.left Disculpa que te esté dando trabajo, te agradezco la mano que intentas echarme. He estado buscando información y tal y encontré alguna otra forma también posible de hacerlo:
#include <SFML/Graphics.hpp>
#include <iostream>
void comprobarIntersecta( ) ;
int main( ) {
//Creamos la ventana
sf:: RenderWindow window( sf:: VideoMode ( 800 , 600 ) , "Colision" ) ;
//Rectangualo
sf:: RectangleShape rec( sf:: Vector2f ( 50 , 50 ) ) ;
rec.setFillColor ( sf:: Color :: Cyan ) ;
//Otro rectangulo
sf:: RectangleShape rec2( sf:: Vector2f ( 50 , 50 ) ) ;
rec2.setFillColor ( sf:: Color :: Magenta ) ;
rec2.setPosition ( 400 , 300 ) ;
window.setFramerateLimit ( 200 ) ;
//Si la ventana está abierta
while ( window.isOpen ( ) ) {
//Creamos un evento
sf:: Event ventana;
//Llamamos a los eventos
while ( window.pollEvent ( ventana) ) {
//Cerramos la ventana cuando se solicite
if ( ventana.type == sf:: Event :: Closed ) {
window.close ( ) ;
}
}
//Colisiones ventana bordes
if ( rec.getPosition ( ) .x < 0 ) {
rec.setPosition ( 0 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .x > 750 ) {
rec.setPosition ( 750 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .y < 0 ) {
rec.setPosition ( rec.getPosition ( ) .x , 0 ) ;
}
if ( rec.getPosition ( ) .y > 550 ) {
rec.setPosition ( rec.getPosition ( ) .x , 550 ) ;
}
sf:: FloatRect rect = rec.getGlobalBounds ( ) ;
sf:: FloatRect rect2 = rec2.getGlobalBounds ( ) ;
bool chocar [ 4 ] = { false ,false ,false ,false } ; //Norte, sur, este y oeste
if ( rect.intersects ( rect2) ) {
comprobarIntersecta( ) ;
}
if ( sf:: Keyboard :: isKeyPressed ( sf:: Keyboard :: Up ) ) {
if ( ! chocar[ 0 ] )
rec.move ( 0 , - 1 ) ;
}
else if ( sf:: Keyboard :: isKeyPressed ( sf:: Keyboard :: Down ) ) {
if ( ! chocar[ 1 ] )
rec.move ( 0 , 1 ) ;
}
else if ( sf:: Keyboard :: isKeyPressed ( sf:: Keyboard :: Left ) ) {
if ( ! chocar[ 2 ] )
rec.move ( - 1 , 0 ) ;
}
else if ( sf:: Keyboard :: isKeyPressed ( sf:: Keyboard :: Right ) ) {
if ( ! chocar[ 3 ] )
rec.move ( 1 , 0 ) ;
}
//Limpiamos ventana
window.clear ( ) ;
//Dibujamos el rectangulo
window.draw ( rec) ;
window.draw ( rec2) ;
//Actualizamos ventana
window.display ( ) ;
}
}
void comprobarIntersecta( ) {
sf:: RectangleShape rec( sf:: Vector2f ( 50 , 50 ) ) ;
rec.setFillColor ( sf:: Color :: Cyan ) ;
if ( rec.getPosition ( ) .x < 400 ) {
chocar[ 0 ] = true ;
}
}
Pero de igual modo supuestamente hay que modificar el bool por true cuando colisione o tal así.
Gracias.
Saludos!
En línea
Esta página web no está disponible - Google Chrome
ivancea96
Desconectado
Mensajes: 3.412
ASMático
Repasa el algoritmo. Piensa en qué pasa en cada momento, y en qué es incorrecto.
if ( rec.getPosition ( ) .x < rect2.left )
if ( rec.getPosition ( ) .x > rect2.left )
¿Qué ocurre si x==rect.left? En vez de > pon >=, o <= en vez de <, como veas.
Si repasas el algoritmo y sacas valores por pantalla, haciendo las operaciones acabarás viendo por qué ocurre lo que ocurre. Sinó, puedes hacerlo en papel con valores pequeños (1-5) para encontrar el error, o mejor aun, para encontrar la forma correcta.
Mirarlo en internet no te va a ayudar a entenderlo, y menos copiando código sin más.
En línea
DeMoNcRaZy
Desconectado
Mensajes: 420
$~*|_
Probé como me dijiste y por una parte responde bien entre sí...
De nuevo un corto vídeo del funcionamiento.
Solo funciona si voy de izquierda a derecha. <-->
VIDEO #include <SFML/Graphics.hpp>
#include <iostream>
int main( ) {
//Creamos la ventana
sf:: RenderWindow window( sf:: VideoMode ( 800 , 600 ) , "Colision" ) ;
//Rectangualo
sf:: RectangleShape rec( sf:: Vector2f ( 50 , 50 ) ) ;
rec.setFillColor ( sf:: Color :: Cyan ) ;
//Otro rectangulo
sf:: RectangleShape rec2( sf:: Vector2f ( 50 , 50 ) ) ;
rec2.setFillColor ( sf:: Color :: Magenta ) ;
rec2.setPosition ( 400 , 300 ) ;
window.setFramerateLimit ( 200 ) ;
//Si la ventana está abierta
while ( window.isOpen ( ) ) {
//Creamos un evento
sf:: Event ventana;
//Llamamos a los eventos
while ( window.pollEvent ( ventana) ) {
//Cerramos la ventana cuando se solicite
if ( ventana.type == sf:: Event :: Closed ) {
window.close ( ) ;
}
}
//Movimiento rectangulo
if ( sf:: Keyboard :: isKeyPressed ( sf:: Keyboard :: Up ) ) {
rec.move ( 0 , - 1 ) ;
}
if ( sf:: Keyboard :: isKeyPressed ( sf:: Keyboard :: Down ) ) {
rec.move ( 0 , 1 ) ;
}
if ( sf:: Keyboard :: isKeyPressed ( sf:: Keyboard :: Left ) ) {
rec.move ( - 1 , 0 ) ;
}
if ( sf:: Keyboard :: isKeyPressed ( sf:: Keyboard :: Right ) ) {
rec.move ( 1 , 0 ) ;
}
//Colisiones
if ( rec.getPosition ( ) .x < 0 ) {
rec.setPosition ( 0 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .x > 750 ) {
rec.setPosition ( 750 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .y < 0 ) {
rec.setPosition ( rec.getPosition ( ) .x , 0 ) ;
}
if ( rec.getPosition ( ) .y > 550 ) {
rec.setPosition ( rec.getPosition ( ) .x , 550 ) ;
}
sf:: FloatRect rect = rec.getGlobalBounds ( ) ;
sf:: FloatRect rect2 = rec2.getGlobalBounds ( ) ;
if ( rect.intersects ( rect2) ) {
if ( rec.getPosition ( ) .x == rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x - 50 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .x == rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x + 50 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .y == rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x , rec.getPosition ( ) .y - 50 ) ;
}
if ( rec.getPosition ( ) .y == rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x , rec.getPosition ( ) .y + 50 ) ;
}
}
//Limpiamos ventana
window.clear ( ) ;
//Dibujamos el rectangulo
window.draw ( rec) ;
window.draw ( rec2) ;
//Actualizamos ventana
window.display ( ) ;
}
}
Parte que modifiqué:
if ( rect.intersects ( rect2) ) {
if ( rec.getPosition ( ) .x == rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x - 50 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .x == rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x + 50 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .y == rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x , rec.getPosition ( ) .y - 50 ) ;
}
if ( rec.getPosition ( ) .y == rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x , rec.getPosition ( ) .y + 50 ) ;
}
}
Gracias.
Saludos!
En línea
Esta página web no está disponible - Google Chrome
DeMoNcRaZy
Desconectado
Mensajes: 420
$~*|_
#ACTUALIZACIÓN Acabo de probar otra forma que da resultado por una parte, pero por la otra no.
Si voy de izquierda a derecha colisiona y no puede avanzar "bien", si voy de derecha a izquierda colisiona y no puede avanzar "bien", eso si quitamos la colisión de "y". Y si añado la colisión de "y" se desplaza el rectángulo a los lados como se ve al principio del siguiente vídeo:
VIDEO Código al que hago referencia en el vídeo:
sf:: FloatRect rect = rec.getGlobalBounds ( ) ;
sf:: FloatRect rect2 = rec2.getGlobalBounds ( ) ;
if ( rect.intersects ( rect2) ) {
if ( rec.getPosition ( ) .x <= rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x - 1 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .x >= rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x + 1 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .y <= rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x , rec.getPosition ( ) .y - 1 ) ;
}
if ( rec.getPosition ( ) .y >= rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x , rec.getPosition ( ) .y + 1 ) ;
}
}
Por una parte parece que funciona:
if ( rec.getPosition ( ) .x <= rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x - 1 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .x >= rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x + 1 , rec.getPosition ( ) .y ) ;
}
Ya que colisionan y no pueden avanzar bien, eso si están solo estas funciones.
Si añado las demás funciones que hace referencia a "y" ya al colisionar se desplaza solo.
f( rec.getPosition ( ) .x <= rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x - 1 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .x >= rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x + 1 , rec.getPosition ( ) .y ) ;
}
if ( rec.getPosition ( ) .y <= rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x , rec.getPosition ( ) .y - 1 ) ;
}
if ( rec.getPosition ( ) .y >= rect2.left ) {
rec.setPosition ( rec.getPosition ( ) .x , rec.getPosition ( ) .y + 1 ) ;
}
Saludos!
En línea
Esta página web no está disponible - Google Chrome
Mensajes similares
Asunto
Iniciado por
Respuestas
Vistas
Último mensaje
Colision de 2 image [Solucionado]
Programación Visual Basic
skapunky
8
7,782
4 Septiembre 2008, 14:52 pm
por cobein
Comprobar colisión de 2 cuadrados en SDL
Programación C/C++
Stereo
7
4,641
24 Febrero 2013, 15:32 pm
por Anastacio
¿ Como hago para que un radiobutton rebote en un button ?
.NET (C#, VB.NET, ASP)
arts
2
2,632
18 Junio 2013, 04:18 am
por XresH
Colisión entre objetos JS
Desarrollo Web
SrTrp
6
5,116
14 Julio 2017, 02:29 am
por SrTrp
Rebote de ubicacion por whatsapp??
Dispositivos Móviles (PDA's, Smartphones, Tablets)
luislial
0
1,968
29 Abril 2018, 19:07 pm
por luislial