SFML community forums
Help => General => Topic started by: ravenheart on September 28, 2008, 03:24:54 pm
-
well i have a problem (again):
in my pong clone the ball should bounce when it touches the top or bottom of the window, i tried it like this:
thers a class ball with a vector2f dir for the direction the ball goes , and a float speed for the velocity;
moreover i got a function bounce_y when the ball should bounce from top or bottom:
class ball
{
vector2f dir;
float speed;
...
}
void ball::bounce_y()
{
if(dir.y == 1)
dir.y = -1;
else
dir.y = 1;
}
i try to find out wether the ball should bounce like that:
if( Ball.GetPosition().y <= 0 || Ball.GetPosition().y +10 >= WINDOW_HEIGHT)
Ball.bounce_y();
after that i move the ball:
Ball.Move(Ball.speed * Ball.dir * App.GetFrameTime());
mostly it works fine but sometimes in my game my ball is hanging, it doesnt bounce when it should
could that be because there are no negative y-values in GetPosition?
well i cannot find any other mistake; if there are problems with understanding my question i could post the whole code;
at moment only the y-direction is important
-
What do you think is special about when dir.y == 1 that's making you test against that?
Edit: Also, I hope you are normalizing dir or you're going to get some weird movement calculations.
-
sry quasius, ill tell u a bit more:
my vector dir can be (-1|-1) (1|-1) (-1|1) or (1|1)
i do not have to normalize the vector because only 45° appear
i think my problem is following:
let´s take the top of my window: the ball reaches a negative y-coord and then there is the order: bounce() which changes the y-value of dir , and now it seems that the ball does not reach a positive y-coord in the next frame and the ball bounces so long until it reaches a positive y-coord again
i hope my thoughts are not too far from truth, if u have a solution for this , pls tell me
thanks your raven
-
Can you post your code for your Ball.Move method.
Also, your bounce_y method can be simplified somewhat:
void ball::bounce_y()
{
dir.y = -dir.y;
}
-
sry quasius, ill tell u a bit more:
my vector dir can be (-1|-1) (1|-1) (-1|1) or (1|1)
i do not have to normalize the vector because only 45° appear
i think my problem is following:
let´s take the top of my window: the ball reaches a negative y-coord and then there is the order: bounce() which changes the y-value of dir , and now it seems that the ball does not reach a positive y-coord in the next frame and the ball bounces so long until it reaches a positive y-coord again
i hope my thoughts are not too far from truth, if u have a solution for this , pls tell me
thanks your raven
That sounds like it could be a problem. If that's the case, you need to test something else before calling bounce. (Use &&)
-
is there any possibilty that a certain function cannot be called in 2 following frames, i think about a bool bounce
when the ball bounced its 1
if bounce == 1, the function cannot be called
and bounce = 0 again
does it sound like a good plan?
_____________________________________________________________
i hate collisions
-
sry forgot to post my ball movement:
if( Ball.GetPosition().y <= 0 || Ball.GetPosition().y +10 >= WINDOW_HEIGHT)
Ball.bounce_y();
if(Uhr.GetElapsedTime() > 5.0)
{
Ball.increase_speed();
Uhr.Reset();
}
Ball.Move(Ball.speed * Ball.dir * App.GetFrameTime());
-
is there any possibilty that a certain function cannot be called in 2 following frames, i think about a bool bounce
when the ball bounced its 1
if bounce == 1, the function cannot be called
and bounce = 0 again
does it sound like a good plan?
_____________________________________________________________
i hate collisions
Something like that would work, but before you start making new variables and making your code more complicated, look at what you already have. Is there something in the data you already have (position, speed, dir, etc.) that would tell you if you've already bounced and shouldn't do it again?
-
i think its easier when i let u see the code:
#include <SFML/Graphics.hpp>
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace sf;
using namespace std;
////////////////////////////////////////////////////////////
/// Entry point of application
////////////////////////////////////////////////////////////
class ball: public Shape
{
public:
Vector2f dir;
float speed;
int width;
int height;
ball();
void increase_speed();
void bounce_y();
void bounce_x();
};
ball::ball()
{
AddPoint(0,0);
AddPoint(10,0);
AddPoint(10,10);
AddPoint(0,10);
width = height = 10;
dir.x = dir.y = -1;
speed = 50;
}
void ball::increase_speed()
{
speed = speed +50;
}
void ball::bounce_y()
{
dir.y = -dir.y;
}
void ball::bounce_x()
{
dir.x = -dir.x;
}
class bat : public sf::Shape
{
public:
bat();
bool exist;
int width;
int height;
};
bat::bat()
{
AddPoint(0, 0, sf::Color(255, 0, 0), sf::Color(0, 128, 128));
AddPoint(50, 0, sf::Color(255, 85, 85), sf::Color(0, 128, 128));
AddPoint(50, 50, sf::Color(255, 170, 170), sf::Color(0, 128, 128));
AddPoint(0, 50, sf::Color(255, 170, 170), sf::Color(0, 128, 128));
SetColor(Color(255, 255, 255, 255));
Scale(1, 3);
SetPosition(0,0);
width = 50;
height = 150;
exist = 1;
}
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
int main()
{
// Create main window
RenderWindow App;
App.Create(sf::VideoMode(WINDOW_WIDTH,WINDOW_HEIGHT,32), "SFML Window", Style::Fullscreen);
// Cursor is not being shown
ShowCursor(0);
// create bats
bat left;
bat right;
right.SetPosition(WINDOW_WIDTH - right.width,0);
// INput
bool left_up ;
bool left_down ;
bool right_up ;
bool right_down;
// Ball
ball Ball;
Ball.SetPosition((WINDOW_WIDTH - Ball.width)/2, (WINDOW_HEIGHT - Ball.height)/2);
// goals
int goal1;
int goal2;
goal1 = goal2 = 0;
// Uhr
Clock Uhr;
// im spiel
bool gameover;
bool goal;
gameover = goal = 0;
// TExte
String Text;
Text.SetFont(sf::Font::GetDefaultFont());
Text.SetSize(20);
Text.SetPosition(350,0);
std::ostringstream out;
out << setprecision(2) <<fixed;
std::string str;
while (App.IsOpened())
{
// Process events
Event Event;
while (App.GetEvent(Event))
{
// Close window : exit
if (Event.Type == Event.Closed)
App.Close();
// keybord-events
if ((Event.Type == Event.KeyPressed) && (Event.Key.Code == Key::Escape))
{
App.Close();
}
if ((Event.Type == Event.KeyPressed) && (Event.Key.Code == Key::F1))
{
right.SetPosition(WINDOW_WIDTH - right.width,0);
left.SetPosition(0,0);
Ball.SetPosition((WINDOW_WIDTH - Ball.width)/2, (WINDOW_HEIGHT - Ball.height)/2);
Ball.speed = 50;
goal = 0;
goal1 = goal2 = 0;
gameover = 0;
}
}
out << goal1 << " : " << goal2;
str = out.str();
out.seekp(0);
Text.SetText(str);
App.Draw(Text);
// handle bat-movements
const Input& Input = App.GetInput();
left_up = Input.IsKeyDown(Key::W);
left_down = Input.IsKeyDown(Key::S);
right_up = Input.IsKeyDown(Key::Up);
right_down = Input.IsKeyDown(Key::Down);
if( right_down)
{
right.Move(0, 400* App.GetFrameTime());
}
if(right_up)
{
right.Move(0, - 400 * App.GetFrameTime());
}
if(left_down)
{
left.Move(0, 400* App.GetFrameTime());
}
if(left_up)
{
left.Move(0, -400* App.GetFrameTime());
}
if(Uhr.GetElapsedTime() > 5.0)
{
Ball.increase_speed();
Uhr.Reset();
}
// tor
if( Ball.GetPosition().x < 0 && gameover == 0)
{
goal2 = goal2 +1;
goal = 1;
}
if( Ball.GetPosition().x > WINDOW_WIDTH && gameover == 0)
{
goal1 = goal1+1;
goal = 1;
}
if( goal1 >4 || goal2 >4)
gameover =1 ;
if(!gameover)
{
if(goal)
{
Ball.SetPosition((WINDOW_WIDTH - Ball.width)/2, (WINDOW_HEIGHT - Ball.height)/2);
Ball.speed = 50;
goal = 0;
}
// check bounce
if( Ball.GetPosition().y <= 0 || Ball.GetPosition().y +10 >= WINDOW_HEIGHT)
Ball.bounce_y();
if((Ball.GetPosition().x <= left.width) && Ball.GetPosition().y +10 >= left.GetPosition().y && Ball.GetPosition().y <= left.GetPosition().y + left.height)
Ball.bounce_x();
if((Ball.GetPosition().x +10 >= WINDOW_WIDTH - right.width) && Ball.GetPosition().y +10 >= right.GetPosition().y && Ball.GetPosition().y <= right.GetPosition().y + right.height)
Ball.bounce_x();
}
out << goal1 << " : " << goal2;
str = out.str();
out.seekp(0);
Text.SetText(str);
App.Draw(Text);
// move Ball
Ball.Move(Ball.speed * Ball.dir * App.GetFrameTime());
// Draw
App.Draw(left);
App.Draw(right);
App.Draw(Ball);
// Finally, display the rendered frame on screen
App.Display();
}
return 0;
}
-
Try checking to see if the ball will be off the screen coordinates on its next move, rather than once it has moved.
Vector2f checkPosition(Ball.speed * Ball.dir * App.GetFrameTime());
if( checkPosition.y <= 0 || checkPosition.y +10 >= WINDOW_HEIGHT)
Ball.bounce_y();
Ball.Move(Ball.speed * Ball.dir * App.GetFrameTime());
-
yes in my last version i did it like that, but i didnt know how to manage collision with x-ccords then
-
my problem is:
when i test if the balls x-position would be smaller than 50 in the next movement , the loop will test it every frame, so i would need a second condition, something like
if ( Ball.GetPosition().x + speed*dir*App.GetFrameTime() <= 50 && Ball.GetPosition().x + speed*dir*App.GetFrameTime() >= 45 )
bounce_x();
so there is a 5 pixel big zone where it may bounce;
but i want that the ball does exactly what it is supposed to do
# has anyone done a similiar project and could post me the code?
-
Hi dude, did you get this solved in the end? If not, I can check it out tomorrow.