Making a bullet fire in the direction a sprite is facing - c++

How exactly would this be achieved? Here is the code I have so far which just rotates the ship based on where the mouse is, as well as the bullet:
xPos = ship.getPosition().x, yPos = ship.getPosition().y, mousex = sf::Mouse::getPosition(window).x, mousey = sf::Mouse::getPosition(window).y;
if (mousex > 800) mousex = 800; if (mousey > 600) mousey = 600; if (mousex < 0) mousex = 0; if (mousey < 0) mousey = 0;
double angle = atan2(mousey - yPos, mousex - xPos) * (180/3.14159);
ship.setRotation(90+angle);
bullet.setRotation(-90+angle);
So, how would I match the bullet's velocity to be the same as the direction the ship is facing? So that if I fire a bullet it should fire exactly where the ship is looking towards.
What I've tried so far is creating a distance vector from the bullet to the mouse position, and moving the bullet by that distance vector, but of course that would instantly move the bullet to the mouse's position in just 1 frame. It needs to be like a normal velocity that still goes towards the mouse position.

So, as you correctly described what you need is a normalized delta in the direction of the angle.
Either you use the properties of the unity circle and calculate it like
velocity_x = cos(angle)*speed;
velocity_y = sin(angle)*speed;
or you use the approach that you started and do
diff_x = mousex - xPos;
diff_y = mousey - yPos;
magnitude = sqrt(diff_x*diff_x + diff_y*diff_y);
velocity_x = diff_x/magnitude * speed;
velocity_y = diff_y/magnitude * speed;

Related

SDL joystick shooting angle c++

I'm having some issues with my shooting mechanics in my c++ 2D platform game using the SDL joystick. When I direct the joystick in any direction the bullet seem to go in the right direction-ish. When I do not direct the joystick in any dirction but press the shoot button I want the bullet to go in a horizontal line in the direction the player is facing( either 0 or -180), but right now the angle seems to be -108ish.
This is the code I use to get the angle of the joystick relative to the players position.
controller_y = SDL_JoystickGetAxis(j, 1); // get controller y axis
controller_x = SDL_JoystickGetAxis(j, 0); // get controller x axis
int deltax = xpos - controller_x; // diference in x pos
int deltay = ypos - controller_y; // diference in Y pos
angle = atan2(-deltay, -deltax) * 180 / PI;
and in my update function I update the bullets position like this:
box.x += speed *(cos(angle*PI / 180)) * delta;
box.y += speed *(sin(angle*PI / 180)) * delta;
When I do not move the joystick in any direction the x and y value of the Joystick is usually lower 500 and bigger than -500. So my question is how I can get the bullet to go in the angle -180 if my player is facing left and I do not move the joystick and the angle 0 if my player is facing right when I do not move the joystick if that makes sense.

Rotation Angle of Sprite towards Mouse is only calculated but Sprite does not rotate. But, it works well in Debugger

I am a beginner in C++ and know SFML. I have read a lot of articles about Sprite rotation towards Mouse and have been able to calculate proper angle of rotation of Sprite using this code:
void Player::changeAngle(double Mx, double My) { // This is for making Player point towards Mouse
double dX = x - Mx; // x and y are global Varibales declared outside
double dY = y - My;
double magnitude = sqrt((dX*dX) + (dY*dY));
double normalizedX = dX / magnitude;
double normalizedY = dY / magnitude;
// This part is for Making Player move to Mouse
Xvelocity = normalizedX * speed; // Xvelocity, Yvelocity and speed are global variables
Yvelocity = normalizedY * speed;
// Rotate towards the Mouse
double angle = ( atan2(dY, dX) ) * 180 / M_PI;
entity.setRotation(angle); // entity is a sf::RectangleShape
}
And, this bit actually worked and the Sprite was rotating properly only before a few days. Now the Sprite is just frozen on the screen, nothing happens. I had not made any changes in that code but I had added a View from the main.cpp.
So here is how I call changeAngle() from the main.cpp :
case Event::MouseMoved : {
Vector2f worldPos = window.mapPixelToCoords(Mouse::getPosition(window), view);
double x = worldPos.x;
double y = worldPos.y;
player.changeAngle(x, y);
break;
}
I tried running the debugger and stepped through the code. I found that the angle is properly calculated and my mouse coordinates are also right. And, to my surprise, the sprite was Rotating now !
I could not understand why, but every time its in debugging mode, the Sprite will rotate. But, it won't rotate while running normally.
Can anyone tell me why and how to fix it so it rotates every time ? Tell me if there is any problem with my code.
Thanks !

Issue with angle limiting

I am creating a game using SFML 2.2 and Box2D. The game is similar to Peggle in that you have a cannon attached to the top of the screen. I have the movement of the cannon mostly working but I would like to limit the rotation so it cannot rotate and point straight up (off screen). I have implemented the code below and it works to an extent. The cannon can move fine within the bounds, but if it hits one of the two edges it becomes stuck there. If I press the opposite direction, instead of rotating back around it quickly jumps to the opposite edge, causing the cannon to be either all the way to the right or all the way to the left.
In my game, when the cannon is pointing straight down the angle is 0/360 degrees, all the way left is 90 degrees and all the way right is 270 degrees.
//******************************/
// Aiming Controls
//******************************/
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Left))
{
float sin = sinf(-m_fRotationSpeed*elapsedTime);
float cos = cosf(-m_fRotationSpeed*elapsedTime);
sf::Vector2f newDirection;
newDirection.x = (cos*m_vAimDirection.x) - (sin * m_vAimDirection.y);
newDirection.y = (sin*m_vAimDirection.x) + (cos*m_vAimDirection.y);
//Update sprite rotation
// Find angle of rotation by acos(v1dotv2)
float rotationAngle = acosf(1 * m_vAimDirection.y);
// Check to make sure we get the right direction!
if (m_vAimDirection.x < 0)
rotationAngle = (b2_pi*2.0f) - rotationAngle;
// convert to degrees
rotationAngle *= 180.0f / b2_pi;
// HERE IS WHERE I CHECK THE BOUNDS
if (rotationAngle > 88.0f && rotationAngle < 272.0f)
rotationAngle = 88.0f;
else
m_vAimDirection = newDirection;
//apply new rotation
m_sCannon.setRotation(rotationAngle);
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::Right))
{
float sin = sinf(m_fRotationSpeed*elapsedTime);
float cos = cosf(m_fRotationSpeed*elapsedTime);
sf::Vector2f newDirection;
newDirection.x = (cos*m_vAimDirection.x) - (sin * m_vAimDirection.y);
newDirection.y = (sin*m_vAimDirection.x) + (cos*m_vAimDirection.y);
//Update sprite rotation
// Find angle of rotation by acos(v1dotv2)
float rotationAngle = acosf(1 * m_vAimDirection.y);
// Check to make sure we get the right direction!
if (m_vAimDirection.x < 0)
rotationAngle = (b2_pi*2.0f) - rotationAngle;
// convert to degrees
rotationAngle *= 180.0f / b2_pi;
// HERE IS WHERE I CHECK THE BOUNDS
if (rotationAngle < 272.0f && rotationAngle > 88.0f)
rotationAngle = 272.0f;
else
m_vAimDirection = newDirection;
//apply new rotation
m_sCannon.setRotation(rotationAngle);
}

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

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;

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);
}