Calculating ball deflection angle when colliding with paddle in brick slayer game - c++

Here is my code:
void Draw()
{
int x = 59;
int y = 500;
int temp = x;
int colour;
for (int i = 0; i < 9; ++i)
{
for (int j = 0; j < 10; ++j)
{
if (i % 2 == 0)
colour = 2;
else
colour = 3;
DrawRectangle(x, y, 65, 25, colors[colour]);
x += 67;
}
x = temp;
y -= 39;
}
DrawRectangle(tempx, 0, 85, 12, colors[5]);
DrawCircle(templx, temply, 10, colors[7]);
}
// This function will be called automatically by this frequency: 1000.0 / FPS
void Animate()
{
templx +=5;
temply +=5;
/*if(templx>350)
templx-=300;
if(temply>350)
temply-=300;*/
glutPostRedisplay(); // Once again call the Draw member function
}
// This function is called whenever the arrow keys on the keyboard are pressed...
//
I am using OpenGL for this project. The function Draw() is used to print the bricks, slider, and the ball. The Animate() function is called automatically by the frequency given in the code. As it can be seen, I have incremented the values of templx and temply, but the ball goes out of screen as it crosses its limit. I have to deflect the ball if it collides with the paddle or the wall. What can I do to achieve this? All the conditions that I have used by now do not work properly.

So basically you would like to have a ball that is bouncing from the edges of your window. (For this answer I will ignore the slider, finding collision with the slider is very similar to finding collision with the walls).
templx and temply pair is position of your ball. I don't know what is the 3rd argument of DrawCircle function so I will assume that it is the radius. Let wwidth and wheight be width and height of a game window. Note that this magic constant 5 is, in fact, a velocity of the ball. Now ball is moving from upper left corner to lower right corner of your window. If you change 5 to -5 it will move from lower right corner to upper left corner.
Let's introduce two more variables vx and vy - velocity on x axis and velocity on y axis. The initial values will be 5 and 5. Now notice that when ball hits the right edge of the window it doesn't change its vertical velocity, it is still moving up/down but it changes its horizontal velocity from left->right to right->left. So if the vx was 5, after hitting the right edge of the window we should change it to -5.
The next problem is how to find out if we hit the edge of the window or not.
Note that the right-most point on the ball has the position templx + radius and the left-most point on the ball has the position templx - radius etc. Now to find out if we hit the wall or not we should just compare this values with window dimensions.
// check if we hit right or left edge
if (templx + radius >= wwidth || templx - radius <= 0) {
vx = -vx;
}
// check if we hit top or bottom edge
if (temply + radius >= wheight || temply - radius <= 0) {
vy = -vy;
}
// update position according to velocity
templx += vx;
temply += vy;

Related

How to make a 3D model follow the mouse movements?

I'm writing a simple version of the game Duck Hunt in C++, using OpenGL. I managed to render the 3D model of a rifle in the center of the screen, and what I want is to rotate it on his y and z axes depending on the mouse movements, so that the rifle is always pointing to the mouse pointer. I have tried to compute the rotation angles using the arctan equation, in order to have the right proportion between the mouse movements and the distance of the pointer from the rifle, but the result is not really good as the sensibility of the rotation seems to be too low. Here there is my current implementation:
void passiveMotion(int x, int y) {
switch (gamePhase) {
case gameStarted:
if(x > 540 && x < 1000)
gunYrot = ((-(atan(abs(y-720) / (double)(x-540)))) * 180 / M_PI);
else if(x > 80 && x < 540)
gunYrot = (((atan(-abs(y - 720) / (double)(x - 540)))) * 180 / M_PI - 180);
if (y > 320 && y < 355) gunZrot = y;
break;
default: break;
}
}
The game screen is this:
Any clues about what could be the best approach to move the rifle?
Bonus question: at the moment, the bullet is shot from the point in which the rifle is rendered (so it starts from its center); how could I dinamically compute the coordinates of where the gun barrel ends to make it the starting point of the bullet?
Thank you for any help with this.

My square tetrimino keeps rotating oddly, but my other tetrimonos rotate fine?

So in my tetris game, I'm working on rotation. I've found an algorithim that works for every piece but the square piece (ironically, the only one that doesn't even need to rotate). I know I could just check to see if the piece isn't a square then rotate it if it isn't, but that's just cheap. So here's the code:
pieceShape.setTexture(imgr.GetImage("square.png"));
for(int i = 0; i < 4; i++){
sf::RectangleShape rect;
if(i < 2)
rect.setPosition(pieceShape.getPosition().x, i * 10);
else
rect.setPosition(pieceShape.getPosition().x + 10, (i - 2) * 10);
rect.setSize(sf::Vector2f(10, 10));
rect.setFillColor(sf::Color::Blue);
pieceRectangles_.push_back(rect);
}
originCount = 10;
Here, I'm creating all four blocks that make up a square piece. 10 is the width of each box (4 boxes per square) in pixels. For all other pieces, I set originCount to 5 so the origin falls in the middle of the first box created. The originCount comes into play in the RotateRight/Left functions:
void GamePiece::RotateRight(){
int newx, newy;
sf::Vector2f origin(pieceRectangles_[0].getPosition().x + originCount, pieceRectangles_[0].getPosition().y + originCount);
for(int i = 0; i < 4; i++){
newx = (pieceRectangles_[i].getPosition().y + origin.x - origin.y);
newy = (origin.x + origin.y - pieceRectangles_[i].getPosition().x - 10);
pieceRectangles_[i].setPosition(newx, newy);
}
}
In theory, the origin has now been set to the middle of the square's sprite, and the boxes should rotate about that point (i.e. appear to not even move). But the boxes shoot to the left 10 pixels on the first click, go up maybe 2 pixels on click two, etc. I'm clearly missing something, but what?
You calculate origin incorrectly. After the first rotation the coordinates of pieceRectangles_[0] will be (0, 10), so next time origin will be calculated as (10, 20), which is not what you want.

Make a circle push others away?

My problem is probably quite simple for you guys, I'm just new with programming so yeah.
I want to have a circle on the center of the screen, then I want that when a player gets close to it, he'll be pushed away in relation to the direction he came from,
Here's a little drawing I made to be abit more clear
The red circles are the player coming from different directions,
the green circle is the obstacle.
The arrows show what direction the player should be pushed to
the player moves only in the x,y axis
Thank you very much for your time
Transform player coordinates (red circle centres) from Descartes-like screen system to polar with origo of centre obstacle (green circle).
Choosing complex numbers for that purpose could be a solution: complex(x,y) == polar(r,th). Radii of objects are given and a tolerancy radius ('close') also.
Iterate through player coordinates and compare their magnitude (distance of red circle centres from origo). When distance is larger than sum of their radius + tolerancy then they are not considered close. Otherwise magnitudes are adjusted. Back transforming output coordinates into screen gives the result.
void PushAway( std::vector< std::complex< double > > & player_coords )
{
const double r_o = 3.0; // obstacle radius
const double r_p = 1.0; // player radius
const double r_t = 0.1; // 'close'
const double push = 10.0; // pushing amount
for( uint idx = 0; idx < player_coords.size(); ++idx )
{
std::complex< double > & pc = player_coords[idx];
double magn = std::abs( pc );
// too close ?
if( magn < r_o + r_t + r_p )
{
// push away in appropriate direction
pc = std::polar( push + magn, std::arg( pc ) );
}
}
}

algorithm for drawing a sort of nozzle(line),whose is direction determined by the mouse?

i am using The old Turbo C++ and am a beginner.
This is the code of a ongoing project that i am planning.
the circle moves withe WSAD keys
But the problem is that i want the nozzle(a line from the center) of that circle to follow the movement of the mouse,but i cant figure out the mathematical part to restrict the length of that nozzle to, say 30 pixels. the line goes on touching the pointer's location.
I tried to use the Distance formula and the line equation to get with an expression which has both the slope and the length of the line. But the problem here is that there is an square root in the denominator, and i think that is causing the problem
Most of the code here is unnecessary for the following problem, so please ignore
here is the relevant code
originx=getmaxx()/2;
originy=getmaxy()/2;
while(doga==0) //main game loop
{ if(kbhit())
op=getch();
if(limiter>10) //limiter is used to restrict the motion of the circle for a limited // time
{ op=0;limiter=0;} // otherwise the cirlce moves in that direction unless another //key is pressed
//movement of the circle
if(op==72)
{ originy--; limiter++;}
if(op==80)
{originy++; limiter++;}
if(op==75)
{ originx--; limiter++ ;}
if(op==77)
{ originx++; limiter++; }
circle(originx,originy,5);
mouseposi(x,y,cl);
printf(" %d %d",x,y);
printf("\b\b\b\b\b\b\b\b");
m=sloper(originx,originy,x,y);
line(originx,originy,80/sqrt(1+m*m),m*80/sqrt(1+m*m)); //THIS LINE IS WHERE THE PROBLEM IS
delay(30);
cleardevice();
if(op==49) //for exiting
doga=2;
}
}
Let (x,y) be the point you're after, (ox, oy) be your origin, and (mx, my) be the mouse location.
The vector from the origin to the mouse is (dx, dy) = (mx - ox, my - oy).
The distance between the mouse and the origin is the same as the norm of that vector:
distance = sqrt(dx * dx + dy * dy);
Normalizing (scaling) the vector to get a new vector of length 1 ("unit length") we get
nx = dx / distance;
ny = dy / distance;
And finally we can scale those coordinates by the desired length (remembering to add back the origin)
x = ox + length * nx;
y = oy + length * ny;

How do I make projectiles?

I am totally stumped on this one. I'm using C++ and SFML 1.6 for a game I'm developing, and I have no bloody idea. How do I make projectiles (like bullets)? I just don't understand it. It could be my lack of sleep but I don't know.
So my question is how do I create a Sprite that moves in a definite direction based on where the mouse is? (Think of a top down shooter with mouse aiming)
Easiest solution:
If the mouse is at Mx,My and the ship is at Sx,Sy then calculate the direction from the ship to the mouse:
Dx=Sx-Mx
Dy=Sy-My
Now normalise D (this means scale it so that it's length is one):
DLen=sqrt(Dx*Dx + Dy*Dy)
Dx/=DLen;
Dy/=DLen;
Now Dx is the distance you want to move the bullet on the x axis in order to get bullet speed of 1.
Thus each frame you move the bullet like so (position of bullet: Bx,By Speed of bullet: Bs [in pixels per millisec] Frame time Ft[in millisec])
Bx=Bx+Dx*Bs*Ft
By=By+Dy*Bs*Ft
This give you a bullet that moves towards the mouse position at a speed independent of the direction of the mouse or framerate of the game.
EDIT: As #MSalters says you need to check for the DLen==0 case when the mouse is directly above the ship to avoid division by zero errors on the normalise
One way to do it is to make the bullet face the mouse and then move it across the x and y axis by using trigonometry to find the hypotinuse from the angle. I don't think i explained this very well, so here the code to make a sprite move from its rotation:
void sMove(sf::Sprite& input,float toMove, int rotation){
bool negY = false;
bool negX = false;
int newRot = rotation;
if (rotation <= 90){
negY = true;
}
else if (rotation <= 180){
//newRot -= 90;
negY = true;
}
else if (rotation <= 360){
newRot -= 270;
negY = true;
negX = true;
}
float y = toMove*cos(newRot*PI/180);
float x = toMove*sin(newRot*PI/180);
if (negY){
y = y*-1;
}
if (negX){
x = x*-1
}
input.move(x, y);
}