Jump to content
  • Advertisement
Sign in to follow this  
password

Direction and laser

This topic is 4346 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've done a whole lot of work now trying to get the right direction of the shot of a laser tower, will ask here before quitting for the day. I've done something like this to get the coordinates of where the laser shot should end, like way points:
SDL_Rect Lasereye::LaserCoordinates(Laser s) {
    SDL_Rect coordinate;
    
    // fix all coordinates here and remove this comment
    if (s.direction == 0 || s.direction == 1) {
        coordinate.x = x-17;
        coordinate.y = y+154;                
    } else if (s.direction == 2 || s.direction == 3) {
        coordinate.x = x-63;
        coordinate.y = y+140;                
    } else if (s.direction == 4 || s.direction == 5) {
        coordinate.x = x-83;
        coordinate.y = y+129;                
    } else if (s.direction == 6 || s.direction == 7) {
        coordinate.x = x-102;
        coordinate.y = y+110;                
    } else if (s.direction == 8 || s.direction == 9) {
        coordinate.x = x-118;
        coordinate.y = y+89;                
    } else if (s.direction == 10 || s.direction == 11) {
        coordinate.x = x-138;
        coordinate.y = y+11;
    } else if (s.direction == 12 || s.direction == 13) {
        coordinate.x = x-138;
        coordinate.y = y+11;
    } else if (s.direction == 14 || s.direction == 15) {
        coordinate.x = x-139;
        coordinate.y = y+4;
    } else if (s.direction == 16 || s.direction == 17) {
        coordinate.x = x-50;
        coordinate.y = y-4;
    } else if (s.direction == 18 || s.direction == 19) {
        coordinate.x = x-121;
        coordinate.y = y-54;
    } else if (s.direction == 20 || s.direction == 21) {
        coordinate.x = x-103;
        coordinate.y = y-84;
    } else if (s.direction == 22 || s.direction == 23) {
        coordinate.x = x-49;
        coordinate.y = y-124;
    } else if (s.direction == 24 || s.direction == 25) {
        coordinate.x = x+102;
        coordinate.y = y-104;
    } else if (s.direction == 26 || s.direction == 27) {
        coordinate.x = x+136;
        coordinate.y = y-62;
    } else if (s.direction == 28 || s.direction == 29) {
        coordinate.x = x+149;
        coordinate.y = y-39;
    } else if (s.direction == 30 || s.direction == 31) {
        coordinate.x = x+159;
        coordinate.y = y-10;
    } else if (s.direction == 32 || s.direction == 33) {
        coordinate.x = x+154;
        coordinate.y = y+38;
    } else if (s.direction == 34 || s.direction == 35) {
        coordinate.x = x+133;
        coordinate.y = y+91;
    } else if (s.direction == 36 || s.direction == 37) {
        coordinate.x = x+115;
        coordinate.y = y+113;
    } else if (s.direction == 38 || s.direction == 39) {
        coordinate.x = x+82;
        coordinate.y = y+138;
    } else if (s.direction == 40 || s.direction == 41) {
        coordinate.x = x+72;
        coordinate.y = y+142;
    } else if (s.direction == 42 || s.direction == 43 || s.direction == 44) {
        coordinate.x = x+8;
        coordinate.y = y+156;
    }
    
    return coordinate;  
}


and clipped everything out in photoshop and that was a pain to do. It works but some stuff is not 100%, maybe because I made a mistake or something, so I decided to do it the math way (if there is) and ask here about it instead. First I will explain what my problem is. I am making an enemy tower which constantly fire off laser shots with about 800 milliseconds interval. The range of the shot is 140px (something that doesn't really matter, but that's how it is , 140 is something I picked). Right now the function that shows the laser shots and all that stuff, looks lik e this:
void Lasereye::Shot() { 
    SDL_Rect coordinate; 
         
    // start new delay
    if (shootDelay==0) {
        shootDelay=800;
            
        lasertime = new Timer;
        lasertime->start();
        
        shot=true;
    }
    
    // if delay is done
    if (lasertime->get_ticks()>=shootDelay && shootDelay!=0) {
        shootDelay=0;
        delete lasertime;
    }
    
    // if shot is true
    if (shot) {
        Laser laser;
        
        // set coordinates
        laser.frame = 0;
        laser.startX = x;
        laser.startY = y;
        laser.x = laser.startX;
        laser.y = laser.startY;
        laser.direction = frame;
        
        shots.push_back(laser);
        shot=false;
    }
    
    // loop trough all shot structs in the vector
    for (int i=0;i<shots.size();i++) {
        coordinate = LaserCoordinates(shots);
        
        if (shots.x < coordinate.x)
            shots.x += 2;
        else if (shots.x > coordinate.x)
            shots.x -= 2;
            
        
        if (shots.y < coordinate.y)
            shots.y += 2;
        else if (shots.y > coordinate.y)
            shots.y -= 2;
        
        // change between frame 1 and 0
        if (shots.frame>=1)
            shots.frame=0;
        else
            shots.frame++;
        
        // show current laser struct
        BlitSurface(shots.x-camera.x, shots.y-camera.y, buffer, &shotRect[shots.frame]);
        
        // this line doesn't work because the y pos and x pos can vary now                 because of the angle
        if ((shots.x >= shots.x+range) || (shots.y >= shots.startY+range) || (shots.x <= shots.startX-range) || (shots.y <= shots.startY-range)) {
            shots.erase(shots.begin() + i);                
        }
    }           
}


Laser struct:
struct Laser {
    int direction;
    int frame;
    int startX;
    int startY;
    int x;
    int y;
};


Inherited Lasereye class:
class Lasereye : public Enemy {      
  public:
    Lasereye(int xPos, int yPos, string dir, int range);
    
    void Shot();
    
    SDL_Rect LaserCoordinates(Laser s);
  
  protected:
    bool shot;
    
    int range;
    int shootDelay;
    
    Timer *lasertime;
    
    vector<Laser> shots;
      
    SDL_Surface *buffer;
    SDL_Rect shotRect[1];
};


Here are some pics which explains what I mean. If you have any idea how to make a tower that fires the shots in the right direction, please explain how to do it. Most of the things are already done almost. Picture 1 Picture 2 I hope you understand what I want to do, doesn't have so much time right now so I explained it a little quick. Thankful for help..

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
What you are trying to do is theoretically impossible.

Share this post


Link to post
Share on other sites
If I understand you correctly, you are asking how to find the target point of the laser shot, given an angle at which the turret is turned, and a circle with radius 140. You may have to convert to radians first, but afaik, given an angle, in your case,

x = 140 * cos(angle)
y = 140 * sin(angle)

I think that you need to get the angle to be below 90 first, so you'll have to subtract 90 from the angle if it's too large, possibly multiple times. Depending on how often you subtract, the final x or y or both will have to be negative after you calculate them.

if 0 to 90 represents the upper right quadrant, with angle zero = horizontal (not sure if that is proper in math, but it shouldn't matter in this example), then

90-180 - x negative
180-270 - x and y negative
270-360 - y negative

Afterwards you still need to translate by position of turret, since these are relative to a turret at origin.

There may be a more elegant solution, but I think this should work.

Share this post


Link to post
Share on other sites
Something in that style is what i'm looking for. I kind of understand the most of it but there are so much things that is not clear yet. For example, isn't it necessary to include the xy position of the turret too in order to get it right. How are they included in the formula?

The first function I posted is the function that calculates the waypoint/coordinate the lasershot should follow, it varies depending on which frame the turret currently is on. The reason I check both 0 and 1, 1 and 2 in all if statements is because every sprite is shown two times, else it becomes too fast.

The first turret that is shown in frame 0 and 1 is almost turned down, a little bit to the left. I'm not really sure how i'm supposed to use the formulas. The angle 190 is something I thought sounded appropriate, don't really know.


if (s.direction == 0 || s.direction == 1) {
angle = 190;
coordinate.x = s.startX +- int(range * cos(angle));
coordinate.y = s.StartY +- int(range * sin(angle));
}





Not sure if it is + or - or neither, that's why it is +- for the moment (range = 140).

How would it look like if the coordinate the current laser should follow is like this (red dot on pic)? it would help a lot to know.
First coordinate

Maybe I can just add a loop which loops trough all 360 degrees that sounds like a fairly easy thing to do, is that possible? Not sure, but something in this style:


for (int i=0;i<360;i++) {
coordinate.x = 140 * cos(i);
coordinate.y = 140 * sin(i);
}





I'm really confused right now, like how i'm supposed to add the startX and startY positions in the formula etc.

Share this post


Link to post
Share on other sites
Quote:
Original post by lightbringer
I think that you need to get the angle to be below 90 first, so you'll have to subtract 90 from the angle if it's too large, possibly multiple times. Depending on how often you subtract, the final x or y or both will have to be negative after you calculate them.


No, you shouldn't have to do that.

[Edited by - Ezbez on July 2, 2006 7:43:53 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by password
Something in that style is what i'm looking for. I kind of understand the most of it but there are so much things that is not clear yet. For example, isn't it necessary to include the xy position of the turret too in order to get it right. How are they included in the formula?

1) start with the assumption that the turret is at the origin.
2) the point you are looking for should be given by the formulae shown above.
3) As Ezbez already pointed out, I made a mistake - the sin() and cos() functions will already give you the proper sign so you don't have to mess with that.
4) after you've calculated that, add the current turret coordinates.
5) the new point after all these steps is the point you are trying to fire at. (you don't really need to calculate this. rather, it would make more sense to keep everything relative to the turret, and only add the turret coordinates when drawing something on screen)

If you are still confused at this point, you need to google trigonometry and vector algebra.

Quote:
Original post by password
Maybe I can just add a loop which loops trough all 360 degrees that sounds like a fairly easy thing to do, is that possible?

There's no reason to do that. For travelling to that point, you just need to scale the vector. For instance, if the target point is at (-10, 5) (relative to the turret) and your animation takes five frames, you could each frame move the projectile by (-10, 5) * 0.2 = (-2, 1)

Share this post


Link to post
Share on other sites
Quote:
Original post by lightbringer
Quote:
Original post by password
Something in that style is what i'm looking for. I kind of understand the most of it but there are so much things that is not clear yet. For example, isn't it necessary to include the xy position of the turret too in order to get it right. How are they included in the formula?

1) start with the assumption that the turret is at the origin.
2) the point you are looking for should be given by the formulae shown above.
3) As Ezbez already pointed out, I made a mistake - the sin() and cos() functions will already give you the proper sign so you don't have to mess with that.
4) after you've calculated that, add the current turret coordinates.
5) the new point after all these steps is the point you are trying to fire at. (you don't really need to calculate this. rather, it would make more sense to keep everything relative to the turret, and only add the turret coordinates when drawing something on screen)

If you are still confused at this point, you need to google trigonometry and vector algebra.

Quote:
Original post by password
Maybe I can just add a loop which loops trough all 360 degrees that sounds like a fairly easy thing to do, is that possible?

There's no reason to do that. For travelling to that point, you just need to scale the vector. For instance, if the target point is at (-10, 5) (relative to the turret) and your animation takes five frames, you could each frame move the projectile by (-10, 5) * 0.2 = (-2, 1)


Thanks, I managed to find out how it worked while testing.
int(range * cos(angle)) is the x position
int(range * sin(angle)) is the y position

I hope this isn't somehow connected or made to work with the cartesian coordinate system only, because that is a little different from what SDL is using.

Share this post


Link to post
Share on other sites
Quote:
Original post by password
I hope this isn't somehow connected or made to work with the cartesian coordinate system only, because that is a little different from what SDL is using.



^ y
|
|
+---> x

is how it works, usually

+---> x
|
|
v y

Another typical arrangement, origin at the upper left. Does SDL look like this? If you run into trouble, you'll have to compute y = height - y as the last step before drawing.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!