C++ bouncing ball goes out of screen - c++

I tried making a simple bouncing ball with constant velocity, that is supposed to bounce of the screen edges.
I have succeeded in making the ball move forward and down, but it does not stop and instead keeps moving and goes out of the screen.
Also, I just started c++ graphics yesterday and the program is quite primitive and thus I'd appreciate it if the answer could be simple.
(All Header files are included)
void main()
{
int gdriver = DETECT, gmode, xmax, ymax, Vx=10, Vy=10, Cx=150, Cy=150, t=1;
initgraph(&gdriver, &gmode, "");
xmax = getmaxx();
ymax = getmaxy();
setfillstyle(SOLID_FILL, YELLOW);
a:
while((Cx!=xmax-5 && Cx!=0) || (Cy!=ymax-5 && Cy!=0))
{
Cx += (Vx * t);
Cy += (Vy * t);
clrscr();
pieslice(Cx,Cy,0,360,10);
delay(100);
}
if (Cx==xmax-5 || Cx==0)
{
Vx = - Vx;
}
else if (Cy==ymax-5 || Cy==0)
{
Vy = - Vy;
}
goto a;
}

while(Cx!=xmax-5 || Cx!=0 || Cy!=ymax-5 || Cy!=0)
This is always true!
Whatever the value of Cx, it is always either "not xmax-5" or "not zero" (well, unless xmax-5 itself is zero, which it is probably isn't).
Similarly, your Cy conditions always hold.
So, the ball always moves.
Instead:
while ((Cx!=xmax-5 && Cx!=0) || (Cy!=ymax-5 && Cy!=0))
Now you still have the problem that the horizontal and vertical movement is checked at once, which only works if the ball hits an exact corner. But I'll leave you to work that one out on your own.

Related

C++ Multiple Possible Value Control Flow

Currently using C++20, GCC 11.1.0
I'm coding for simple movement in a game loop.
Following the abstract pseudocode below, how would I be able to translate this into code? I was thinking of using either goto to just skip right into the scope that uses the values, or std::optional to check whether the values exist or not.
The reason I'm trying to do this instead of just adding the bottom if statement into the A...D if statements is because the bottom if statement could become very large, and may add redundancy. Or should I just refactor the if statement into a separate function?
if (direction is left && ...)
{
int xVelocity {left_calculation...};
}
else if (direction is right && ...)
{
int xVelocity {right_calculation...};
}
else if (direction is up && ...)
{
int yVelocity {up_calculation...};
}
else if (direction is down && ...)
{
int yVelocity {down_calculation...};
}
if (x has a value or y has a value)
{
// Do something with those values...
}
You can represent optionality via std::option:
std::optional xVelocityOpt =
direction == left ? std::make_optional(left_calculation)
: direction == right ? std::make_optional(right_calculation)
: {};
std::optional yVelocityOpt =
direction == up ? std::make_optional(up_calculation)
: direction == down ? std::make_optional(down_calculation)
: {};
if (xVelocityOpt || yVelocityOpt)
{
// you can use the actual values as
// *xVelocityOpt and *yVelocityOpt
// ...
}
... but I'd also consider using simple int velocities and represent empty as 0 (if what you mean by the variables are delta v in physics).
If instead of x,y you use delta_x,delta_y for relative value change then your problem solves itself. Then your if is just:
int delta_x = 0;
int delta_y = 0;
...
if( delta_x | delta_y )
on_xy_changed(old_x + delta_x, old_y + delta_y);

OpenGL checking screen boundaries

I am working on a project for my openGL class that is supposed to emulate a Yo-Yo, I am making progress but I have seem to hit a roadblock when it comes to checking the bounds of the screen. I am trying to get it so that once the ball reaches the bottom of the screen it starts to go up and vice verse, and help would be much appreciated!
I have three static floats declared above that are to be incremented by the function, I am trying to check the deltay in order to limit the ball's movement.
Below is my function that translates the ball, the ball moves but will continue to move past the boundaries I have set
void moveYoYo()
{
glClear(GL_COLOR_BUFFER_BIT);
//going up
if(flag == 1)
{
deltay -= .05;
if(deltay <= -.002)
{
flag = 0;
}
}
//going down
if(flag == 0)
{
deltay += .05;
if(deltay >= .002)
{
flag = 1;
}
}
glPushMatrix();
glTranslatef(deltax,deltay,deltaz);
display();
glPopMatrix();
glFlush();
glutSwapBuffers();
}
If you want that ball to bounce between the bottom and the top of the screen, the lower bound where it changes the direction should be <= -0.002 and the upper bound >= 1.002 if you want to use those strange numbers. Anyway much better would be to use less random numbers, like f.e.:
if (flag == 1) {
// Going down
deltay -= 0.05f;
if (deltay == 0)
flag = 0;
} else if (flag == 0) {
// Going up
deltay += 0.05f;
if (deltay == 1)
flag = 1;
}
Also if the flag in only used as 0 or 1 why not use a bool?

SFML 2.1 how to make one sprite face another sprite

I am trying to make a shooter game, and while trying to code the enemies
to face towards the player, I tried to use trigonometry to find the necessary rotation, but the code didn't work, and the enemy rotated erratically. This is the code:
void face(sf::Sprite& target, sf::Sprite& subject){
int adjacent = subject.getPosition().x - target.getPosition().x;
int opposite = target.getPosition().y - subject.getPosition().y;
if (opposite == 0){
opposite++;
}
if (adjacent == 0){
adjacent++;
}
//if (adjacent < 0){
//adjacent += 180;
//}
float result=atan(/*opposite / adjacent*/adjacent/opposite)*180/PI;
subject.setRotation(result);
}
Any advice would be appreciated!
You must use float with adjacent and opposite. And change result with this:
float angle = atan(adjacent / opposite) * 180 / PI;
if (opposite > 0)
angle += 180;

Create a simple 2D AI C++

I would like to receive some insight as to how I can make an AI, that can walk smoothly around the map(between window size). Like, if the AI reached that defined spot, then it will walk to another spot.
Here is what I have tried,
First, I get a random float number from 0.0f to 608.0f because my window size is 640,640.
void AIntelligence::GenRandom()
{
MapX = static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 608.0f));
MapY = MapX;
}
Then,I pass in the current position of my sprite to this function
void AIntelligence::RandomMove(float PosX, float PosY)
{
this->PosX = PosX;
this->PosY = PosY;
if (PosX == MapX || PosY == MapY) //If the current is the same as the generated random, then
{ generate it again.
GenRandom();
}
else
{
if (PosX < MapX || PosY < MapY) //If not then I see if the position less than the
{ generated and translate it.
this->PosX += 8.0f;
this->PosY += 8.0f;
}
else if (PosX > MapX || PosY > MapY)
{
this->PosX -= 8.0f;
this->PosY -= 8.0f;
}
else
this->PosX += 0.0f;
this->PosY += 0.0f;
}
}
In my message loop, here is how I call the method
while (GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
Inputs->GetInput(); //Not related
Moving->RandomMove(PosX,PosY);
D3DXVECTOR2 SpritePos = D3DXVECTOR2(Moving->getPosX(), Moving->getPosY());
PosX = Moving->getPosX();
PosY = Moving->getPosY();
Graphic->ClearBegin(); //Begin the direct3d scene
Sprite->Begin(D3DXSPRITE_ALPHABLEND);
float Radian = D3DXToRadian(Rotation);
D3DXMatrixTransformation2D(&Mat, NULL, 0.0f, &SpriteScaling, &SpriteCenter, Radian, &SpritePos); // This is where the transformation is set.
Sprite->SetTransform(&Mat);
Sprite->Draw(Texture, NULL, NULL, NULL, D3DCOLOR_XRGB(255, 255, 255));
Sprite->End();
Graphic->EndPresent();
}
The sprite did move but only moving downward right. And once it reached the same certain spot, it will only stay and vibrate there.... Sorry if my explanation is not clear enough or did not provide enough information needed.
Here are a few things that should help you:
1) In RandomMove, your last else doesn't have braces, since you're performing two operations, you should wrap both of them in braces like you did elsewhere
2) float comparison is tricky. It's very unlikely that your PosX == MapX || PosY == MapY will ever trigger. A better idea would be to calculate the distance between your current position and the random position and then execute the code if the distance is less than an epsilon (small value). Here is a pretty detailed post about float comparison (link)
3) GenRandom always assigns the same value to MapX and MapY. You should try to execute two random calls instead (and probably use a const float to define your max value or make it configurable instead of hardcoding that width
4) Your RandomMove method is a bit misleading. It's not performing random movement, it's going towards MapX and MapY. You should separate the calls to GenRandom from your movement code.
5) Your movement code is meant to work only in diagonals since you always increment or decrement your position in both axes at the same time, in the same direction.
Here is a suggestion (not tested) of what your code could look like:
void AIntelligence::GenRandom(const float in_MaxValueX, const float in_MaxValueY)
{
MapX = in_MaxValueX * (float)rand() / (float)RAND_MAX;
MapY = in_MaxValueY * (float)rand() / (float)RAND_MAX;
}
bool AIntelligence::MoveTowards(const float in_PosX, const float in_PosY)
{
// how far are we from our objective
const float distX = in_PosX - PosX; // by calculating the distance from the target position, it makes our speed calculations easier later on
const float distY = in_PosY - PosY;
// tolerance in pixels
const float tolerance = 1.0f;
const float absDistX = abs(distX);
const float absDistY = abs(distY);
if(absDistX <= tolerance && absDistY <= tolerance) // destination reached
return true;
else
{
// here, normally, you would use a desired speed AND a delta time (your message loop is not really good for that though) to compute how much movement you can execute in a given frame
const float movement = min(10.f, absDistX + absDistY); // by using min, we're making sure not to overshoot our destination
// compute how this movement is spread on each axis
const float movementX = movement * distX / (absDistX + absDistY);
const float movementY = movement * distY / (absDistX + absDistY);
PosX += movementX;
PosY += movementY;
}
return false;
}
// in your loop
if(Moving->MoveTowards(MapX, MapY))
{
Moving->GenRandom(608.f, 608.f); // you should definitely not hardcode these values
}
Feel free to comment if there's parts you don't quite understand

moving a sprite causes jerky movement

I've got some jerky movement of my sprite.
Basically, when the user touches a point on the screen, the sprite should move to that point. This is working mostly fine... it's even taking into account a delta - because frame rate may not be consistant.
However, I notice that the y movement usually finishes before the x movement (even when the distances to travel are the same), so it appears like the sprite is moving in an 'L' shape rather than a smooth diagonal line.
Vertical and horizontal velocity (vx, vy) are both set to 300. Any ideas what's wrong? How can I go about getting my sprite to move in a smooth diagonal line?
- (void)update:(ccTime)dt
{
int x = self.position.x;
int y = self.position.y;
//if ball is to the left of target point
if (x<targetx)
{
//if movement of the ball won't take it to it's target position
if (x+(vx *dt) < targetx)
{
x += vx * dt;
}
else {
x = targetx;
}
} else if (x>targetx) //same with x being too far to the right
{
if (x-(vx *dt) > targetx)
{
x -= vx * dt;
}
else {
x = targetx;
}
}
if (y<targety)
{
if (y+(vy*dt)<targety)
{
y += vy * dt;
}
else {
y = targety;
}
} else if (y>targety)
{
if (y-(vy*dt)>targety)
{
y -= vy * dt;
}
else {
y = targety;
}
}
self.position = ccp(x,y);
}
You want to move to (targetx, targety) from any (x,y) and arrive at both coordinates at the same time (to avoid the "dogleg"). So, suppose the x velocity is vx and you get there in t seconds. That means vx = (targetx - x)/t. t must be the same for the y coordinate if you want smooth movement to the same point at the same time, so that means t = (targetx - x)/vx and vy must actually be (targety - y)*vx/(targetx - x).
In other words, you can't set vx and vy separately and get the result you want.