Some Trigonometry and Positioning

N

Nabil Kabour

Guest
I have a homing missile in my game, with the origin a bit off center on the x axis (see image). The missile can point at any angle, and I want to be able to get the coordinates of the nose of the missile (the last pixel on the right). I'm currently attempting at doing this by first getting the distance between the origin and the nose:
Code:
var nose_offset = sprite_get_bbox_right(sprite_index) - sprite_get_xoffset(sprite_index);
and then using the lengthdir functions with the length being the nose_offset and the direction being the image_angle to get the x and y offsets for the angle that the missile is pointing at. The nose x and y coordinates are then as follows:
Code:
var nose_x = x + lengthdir_x(nose_offset, image_angle);
var nose_y = y + lengthdir_y(nose_offset, image_angle);
When I test this by drawing a line from the calculated nose coordinates to an arbitrary point at the same angle, The line does not start at the nose of the missile. What am I doing wrong, and what is the correct method of getting the nose coordinates?
 

Attachments

CloseRange

Member
Does the bounding box incompus the entire Sprite? If not show us the mask for it.

Other than that if you can assume the tip will always touch the very right edge of the Sprite change the Sprite nose variable to this:
Code:
Var nose_offset = sprite_width - sprite_xoffset
Try that and see if it works (btw adding the _get_ in the middle of these functions make them run slightly slower so only add that when you need to reference an external sprite)

If that doesn't work show us where the line draws from
 
N

Nabil Kabour

Guest
Does the bounding box incompus the entire Sprite? If not show us the mask for it.

Other than that if you can assume the tip will always touch the very right edge of the Sprite change the Sprite nose variable to this:
Code:
Var nose_offset = sprite_width - sprite_xoffset
Try that and see if it works (btw adding the _get_ in the middle of these functions make them run slightly slower so only add that when you need to reference an external sprite)

If that doesn't work show us where the line draws from
The bounding box is set to precise. I've attached an image to show exactly how it is. The reason I'm using the bounding box is so that the code would be universal to sprites that have empty space on the sides. Also sprite_get_bbox returns the relative position of the bounding box to the corner of the sprite, while the bbox variables returns the bounding box's positions in the room. I tried what you suggested and there's no difference. I've also attached an image that clearly shows the offset in the nose position and calculated position.
 

Attachments

Last edited by a moderator:

TheouAegis

Member
The rocket has spr_rocket assigned to it already by default, right? Just making sure it's reading the correct sprite. Although I'm not sure what -1 will do inside sprite_get_bbox_right(). lol

Post a picture of the missile with a direction between 40 and -40 degrees please. To me, it just looks like a rounding error when the missiles are rotated beyond 90 degrees.
 
N

Nabil Kabour

Guest
The rocket has spr_rocket assigned to it already by default, right? Just making sure it's reading the correct sprite. Although I'm not sure what -1 will do inside sprite_get_bbox_right(). lol

Post a picture of the missile with a direction between 40 and -40 degrees please. To me, it just looks like a rounding error when the missiles are rotated beyond 90 degrees.
No the missile doesn't have a sprite by default. It is assigned its sprite after creation (I use a script to create the missile and set all the parameters). This way I can use one object to create different missiles. I am doing the nose offset and position calculations each step, so that's not a problem. Yeah seems much better at angles close to 0. Hard to see, but I think the line could be at the right place when the angle is 0.

I don't understand what you mean by rounding error due to higher angles. Can you please explain. Shouldn't the calculation be uniform?
 

Attachments

TheouAegis

Member
Your nose_offset calculation only needs to be done ONCE -- after a sprite has been assigned. You're just wasting a lot of CPU time calling that function every step.

As for the offset, it's not uniform. First, you have the rotation aspect. At 0 degrees, let's say the line is drawn from the top of the origin toward 1 pixel down (because the line has a thickness of 1). When you rotate the sprite 180 degrees, it's still drawing the line down 1 pixel, but now the origin has been rotated 180, so the top of the line is now where the bottom of it should be, so now the line is 1 pixel lower than it was at 0 degrees. That's your main issue. The second issue is floating point rounding coupled with GM's automatic rounding. For example, 0.1 is not a valid number, but 0.125 and 0.0625 are, so GM will round off to one of those numbers in its calculations if 0.1 would have been the result of a calculation. Then before GM can draw the line, it has to convert it to pixels, which forces it to round off to some integer based on an internal rounding algorithm.

Most likely it's just the rotation aspect that's causing most of your issues. You could try using

var nose_y = y + lengthdir_y(nose_offset,image_angle) - n

where n is some condition that yields 1, like (image_angle div 180) or (abs(angle_difference(180,image_angle))<90). You'd probably have to do something for nose_x too, but not sure.
 
N

Nabil Kabour

Guest
Your nose_offset calculation only needs to be done ONCE -- after a sprite has been assigned. You're just wasting a lot of CPU time calling that function every step.

As for the offset, it's not uniform. First, you have the rotation aspect. At 0 degrees, let's say the line is drawn from the top of the origin toward 1 pixel down (because the line has a thickness of 1). When you rotate the sprite 180 degrees, it's still drawing the line down 1 pixel, but now the origin has been rotated 180, so the top of the line is now where the bottom of it should be, so now the line is 1 pixel lower than it was at 0 degrees. That's your main issue. The second issue is floating point rounding coupled with GM's automatic rounding. For example, 0.1 is not a valid number, but 0.125 and 0.0625 are, so GM will round off to one of those numbers in its calculations if 0.1 would have been the result of a calculation. Then before GM can draw the line, it has to convert it to pixels, which forces it to round off to some integer based on an internal rounding algorithm.

Most likely it's just the rotation aspect that's causing most of your issues. You could try using

var nose_y = y + lengthdir_y(nose_offset,image_angle) - n

where n is some condition that yields 1, like (image_angle div 180) or (abs(angle_difference(180,image_angle))<90). You'd probably have to do something for nose_x too, but not sure.
Ah, makes sense. Yeah adding that part to the y calculation makes a significant improvement. Yes, you are right, I have to do something for the x aswell. I tried doing
Code:
var nose_x = x - (abs(angle_difference(90,image_angle))<45) + (abs(angle_difference(270,image_angle))<45);
Where at angles within 45 degrees of 90 we shift one pixel to the left, and angles within 45 degrees of 270 we shift one pixel to the right. It's straightforward when drawn on paper (visualize how the line would be drawn at different angles). But it's not perfect, the line is off center at some angles. I'm not sure what I'm doing wrong.
 
N

Nabil Kabour

Guest
Use ||, not +
I tried that before I did + and now again, and there is still an offset at some angles. I created a room with a missile in the center that points towards a target that I can move around using the mouse, this makes it easier to see things more clearly. I also zoomed in on the missile so the offset can be more visible. Annoying issue with that though. The line remains 1 px thick while the missile sprite is zoomed in. I'll attach some images where there's an offset and where there's not. In the first 2 images there's no offset, while in the 3rd there is. When moving the target around the missile, it is clear when the line goes off position as snaps to an offset position.
 

Attachments

Last edited by a moderator:
N

Nabil Kabour

Guest
Use ||, not +
I'm also thinking is this even an issue in the real world. What I'm trying to do is like a sonar for the missiles in order to avoid obstacles. I guess it might make the missile crash in some very rare occasions. Still good to know how things are done on a technical level.
 
N

Nabil Kabour

Guest
Use ||, not +
Are the coordinates passed into the draw_line function points or the actual pixels themselves. In more general terms, are points coordinates on a grid, and the pixels being the squares?
 

TheouAegis

Member
Yes, coordinates are points on a grid, pixels are actual one by one squares. This is why there has always been issues but people not understanding why you need and even width sprite with the origin centered to perfectly mirror it. So rotating 180 degrees shifts the whole sprite down.
 
Top