shooting bullet based on an angle from a point - c++

what i am doing is scanning an area with a sprite of a straight line that i rotate 20 degrees back and forth
when i tap my action button i want to shoot a bullet in the direction of rotation of the sprite
i get the angle by doing a
sprite->getRotation();
and i have the point of my unit available, lets say it is (0,0)
i'm guessing i need to find a point on the line, but i don't know the math behind it.
is this even possible?

Given that you know the velocity of your bullet (pixels/second), let me assume you will call it v. That it takes s seconds to transverse your screen. And that x represents the position of your bullet at axis x (same to y variable), you can actualize both variables using this simple trigonometry:
x = 0; // initial position. You say that it start at (0,0)
y = 0;
for (int i = 0; i < s; i++) {
sleep(1); // look in unistd.h
x += v*cos(angle); // include math.h
y += v*sin(angle); // angle in radian, of course
// draw your sprite here, at (x, y)
}

Related

Drawing a sprite on the circumference of a circle based on the position of other objects

I'm making a sniper shooter arcade style game in Gamemaker Studio 2 and I want the position of targets outside of the viewport to be pointed to by chevrons that move along the circumference of the scope when it moves. I am using trig techniques to determine the coordinates but the chevron is jumping around and doesn't seem to be pointing to the target. I have the code broken into two: the code to determine the coordinates in the step event of the enemies class (the objects that will be pointed to) and a draw event in the same class. Additionally, when I try to rotate the chevron so it also points to the enemy, it doesn't draw at all.
Here's the coordinate algorithm and the code to draw the chevrons, respectively
//determine the angle the target makes with the player
delta_x = abs(ObjectPlayer.x - x); //x axis displacement
delta_y = abs(ObjectPlayer.y - y); //y axis displacement
angle = arctan2(delta_y,delta_x); //angle in radians
angle *= 180/pi //angle in radians
//Determine the direction based on the larger dimension and
largest_distance = max(x,y);
plusOrMinus = (largest_distance == x)?
sign(ObjectPlayer.x-x) : sign(ObjectPlayer.y-y);
//define the chevron coordinates
chevron_x = ObjectPlayer.x + plusOrMinus*(cos(angle) + 20);
chevron_y = ObjectPlayer.y + plusOrMinus*(sign(angle) + 20);
The drawing code
if(object_exists(ObjectEnemy)){
draw_text(ObjectPlayer.x, ObjectPlayer.y-10,string(angle));
draw_sprite(Spr_Chevron,-1,chevron_x,chevron_y);
//sSpr_Chevron.image_angle = angle;
}
Your current code is slightly more complex that it needs to be for this, if you want to draw chevrons pointing towards all enemies, you might as well do that on spot in Draw. And use degree-based functions if you're going to need degrees for drawing anyway
var px = ObjectPlayer.x;
var py = ObjectPlayer.y;
with (ObjectEnemy) {
var angle = point_direction(px, py, x, y);
var chevron_x = px + lengthdir_x(20, angle);
var chevron_y = py + lengthdir_y(20, angle);
draw_sprite_ext(Spr_Chevron, -1, chevron_x, chevron_y, 1, 1, angle, c_white, 1);
}
(also see: an almost-decade old blog post of mine about doing this while clamping to screen edges instead)
Specific problems with your existing code are:
Using a single-axis plusOrMinus with two axes
Adding 20 to sine/cosine instead of multiplying them by it
Trying to apply an angle to sSpr_Chevron (?) instead of using draw_sprite_ext to draw a rotated sprite.
Calculating largest_distance based on executing instance's X/Y instead of delta X/Y.

How to rotate an object so it faces another?

I am making a game in opengl, and i can't figure out how to make my enemy characters turn to face my player. I only need the enemy to rotate on the y axis towards the player. Then I want them to move towards him.I have tried a bunch of different methods but haven't been able to get anything to work.
There are a few things you need to decide on yourself at the beginning of the project to be used throughout the project, like the representation of positions and the orientation (as well as the setup of the screen/clip planes etc.) However, you haven't mentioned any of this. So you may have to adapt the code below to suit your game, but it should be easily adaptable and applicable.
For the following example, I'll assume that -y axis is the top of your screen.
#include <math.h> // atan2
// you need to way to represent position and directions
struct vector2{
float x;
float y;
} playerPosition, enemyPosition;
float playerRotation;
// setup the instances and values
void setup() {
// Set some default values for the positions
playerPosition.x = 100;
playerPosition.y = 100;
enemyPosition.x = 200;
enemyPosition.y = 300;
}
// called every frame
void update(float delta){
// get the direction vector between the player and the enemy. We can then use this to both calculate the rotation angle between the two as well as move the player towards the enemy.
vector2 dirToEnemy;
dirToEnemy.x = playerPosition.x - enemyPosition.x;
dirToEnemy.y = playerPosition.y - enemyPosition.y;
// move the player towards the enemy
playerPosition.x += dirToEnemy.x * delta * MOVEMENT_SPEED;
playerPosition.y += dirToEnemy.y * delta * MOVEMENT_SPEED;
// get the player angle on the y axis
playerRotation = atan2(-dirToEnemy.y, dirToEnemy.x);
}
void draw(){
// use the playerPosition and playerAngle to render the player
}
Using the above code, you should be able to move your player object around and set the angle of rotation (you need to watch out for radians/degrees of the returned and expected angle values).

C++ DirectX11 2d Game: Stopping enemy sprites moving over each other?

I am using IntersectsWith(this->boundingBox)) method to detect collisions between sprites and player. I want to somehow be able to use this method in detecting my enemy sprites that collide with each other, and when they do to make sure they don't move over one another.
All of the enemy sprites follow the player.
MainGame.cpp
Loops over each enemy in the vector and does the update loop:
for (auto &enemyMobsObj : this->enemyMobs)
{
enemyMobsObj->Update(tickTotal, tickDelta, timeTotal, timeDelta, windowBounds, this->ship, this->firstBoss,
this->enemyMobs, this->bullets, this->missiles, NULL, "NULL", "NULL");
}
Here is what I tried before to stop each sprite moving over each other:
EnemyMobOne::Update:
int nextEnemy;
for (int i = 0; i < enemyMobOne.size(); i++)
{
nextEnemy = i + 1;
if (nextEnemy < enemyMobOne.size())
{
//Deal with mobs collision
if (enemyMobOne[i].boundingBox.IntersectsWith(enemyMobOne[nextEnemy].boundingBox))
{
enemyMobOne[i].position.x = enemyMobOne[nextEnemy].position.x - enemyMobOne[i].boundingBox.Width;
}
}
}
However this makes each enemy sprite obviously stick to each other, which doesn't look right, it also makes them teleport.
Anyone know the correct code to stop them moving over each other? Thanks.
When you detect an intersection between two collision objects, you need to make a decision about how you're going to counteract the overlap (as I'm sure you figured out). However, how one does this is a bit trickier than simply "pushing" them to one side (as you've done in your code). What you likely want to do is to have a counter-force to the applied force, so to speak. Basically, you want to calculate the minimum translation, or the direction by which the least amount of movement would be required, to get at least ONE of the boxes to move OUT of the other one.
This is a bit more complicated than simply "put me on the right (or left, depending on how you set up your coordinates, I suppose) side of the other guy," which is more or less what your code does, now.
For a simple solution, just check if one of the colliders is closer to the left, right, top, or bottom of the other. To do this, you can simply take the collision intersection position and check the relative distance between that point and the minimum and maximum x and y coordinates relative to one of the colliders, then move the one or both of the sprites, accordingly.
Ex:
[Edit] After reviewing my previous answer for this, I realized you would need to calculate the overlap of the boxes, which would make it much easier to accomplish this all like so:
float minX = min(sprite0.boundingBox.maxX, sprite1.boundingBox.maxX);// Minimum of the boxes' right-side points (top right and bottom right) x coordinates
float minY = min(sprite0.boundingBox.maxY, sprite1.boundingBox.maxY);// Minimum of the boxes' top-side points (top left and top right) y coordinates
float maxX = max(sprite0.boundingBox.minX, sprite1.boundingBox.minX);// Maximum of the boxes' left-side points (top left and bottom left) x coordinates
float maxY = max(sprite0.boundingBox.minY, sprite1.boundingBox.minY);// Maximum of the boxes' bottom-side points (bottom left and bottom right) y coordinates
float distHoriz = minX - maxX;// The horizontal intersection distance
float distVert = minY - maxY;// The vertical instersection distance
// If the boxes are overlapping less on the horizontal axis than the vertical axis,
// move one of the sprites (in this case, sprite0) in the opposite direction of the
// x-axis overlap
if(abs(distHoriz) < abs(distVert))
{
sprite0.x -= distHoriz;
}
// Else, move one of the sprites (again, I just decided to use sprite0 here,
// arbitrarily) in the opposite direction of the y-axis overlap
else
{
sprite0.y -= distVert;
}
To further clarify (beyond the comments), what we're basically doing here is checking the distance between the overlapping lines. For example:
Box 0 x-axis xmin0|------------------|xmax0
Box 1 x-axis xmin1|----------------------|xmax1
|----|<-- Overlap (xmax0 - xmin1)
Notice that the minimum from the two bounding boxes that is used for the overlap is the maximum among the two minima (xmin0 and xmin1), and the maximum that is used for the overlap is the minimum among the two maxima (xmax0 and xmax1).
The y-axis calculation works exactly the same way. Once we have both axes, we simply check to see which one has a lower absolute value (which distance is shorter) and move along that distance to counteract the intersection.

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