# GM:S 1.4 Bullet Shooting Relative to Object - Simple but Not (GML)

Discussion in 'Programming' started by Benjamin Crump, Jul 15, 2016.

1. ### Benjamin CrumpGuest

Hey all,

This is my first time posting on here. I've been through the asteroids tutorial and am now playing around with some different variations to help solidify the knowledge. I've taken the basic asteroids tutorial and I'm trying to make a modification to the firing of the bullet. The tutorial teaches you how to fire 1 bullet from the center of the player object (the ship), but I'm trying to make a modification to fire 2 bullets (1 from Y+10 and 1 from Y-10) simultaneously and in the correct direction (image angle of the player object). Code below:

bullet_direction = image_angle

bullet1 = instance_create(x,y+10,obj_bullet);
bullet2 = instance_create(x,y-10,obj_bullet);

bullet1.direction = bullet_direction
bullet2.direction = bullet_direction

bullet1.speed=10
bullet2.speed=10

The player object successfully fires 2 bullets from the correct position when facing right (position 0) and facing left (180). When facing up or down, however, the bullets are no longer separated but are firing on top of each other (the gap between the bullets begins to close as soon as you begin turning the ship from 0 or 180. I've tried doing it through DnD and through anything I can find of GML (lots of using Google and the help file). Could anyone please help me understand why this code isn't forcing the bullets to fire with the degrees of separation in each and every direction as opposed to just left and right? Thanks in advance!

2. ### joakimFFMember

Joined:
Jun 20, 2016
Posts:
119
This should do what you want

//create event

xx = x;
yy = y-10;

Len = point_distance(0, 0, xx, yy);
Angle = point_direction(0, 0, xx, yy);

xx2 = x;
yy2 = y+10;

Len2 = point_distance(0, 0, xx2, yy2);
Angle2 = point_direction(0, 0, xx2, yy2);

//create bullet event

instance_create(x + hspeed + lengthdir_x(Len, Angle + image_angle),y + vspeed + lengthdir_y(Len, Angle + image_angle),obj_bullet);
instance_create(x + hspeed + lengthdir_x(Len2, Angle2 + image_angle),y + vspeed + lengthdir_y(Len2, Angle2 + image_angle),obj_bullet);

3. ### TehCupcakesMember

Joined:
Jun 21, 2016
Posts:
63
What joakimFF posted should pretty much work, but they didn't explain what the code is doing and I think adding Angle + image_angle might not be the effect you want.

The problem is that the Y axis is relative to the room, not relative to your object.

Code:
```bullet1 = instance_create(x+dsin(image_angle)*10, y+dcos(image_angle)*10,obj_bullet);
bullet2 = instance_create(x-dsin(image_angle)*10, y-dcos(image_angle)*10,obj_bullet);

bullet1.direction = image_angle;
bullet2.direction = image_angle;

bullet1.speed = 10;
bullet2.speed = 10;
```
This will allow you to create the bullets with the same direction and speed that you have been, but their place of creation will always be at the sides of the ship regardless of angle. dcos() and dsin() allow you to determine the x factor and y factor to multiply by based on the angle to adjust the position. If math isn't your strong suite, open up a calculator and try plugging in angles in then doing sin and cos. You'll notice that you always get a number between -1 and 1. So for examle, when your player is facing fully right (angle 0), cos will give you 1, so you get bullets at y+10 and y-10. Whereas at angle 90, cos is 0 so the bullets originate from the player's y, but x+10 and x-10.

Papa Doge and Waffle like this.
4. ### flyingsaucerinvasionMember

Joined:
Jun 20, 2016
Posts:
2,250
To add a slightly different take on above solutions.

This requires you to define the position of each gun relative to the ship's origin. You want to define the position as if the ship were NOT rotated, and the origin is at coordinates (0,0). I'm assuming here that zero image_angle is pointing to the right.

So say I want two guns.
Code:
```num_guns = 2;
gun_array[0,0] = 5; //x coordinate of first gun
gun_array[0,1] = -10 // y coordinate of first gun
gun_array[1,0] = 5; //x coordinate of second gun
gun_array[1,1] = 10 // y coordinate of second gun
```
now that I have the positions for my guns defined, I can calculate their position in the room by taking into account the ship's position and orientation. Then once I have the gun's position in the room, I can create a bullet at that location.
Code:
```var _c = dcos(image_angle);
var _s = dsin(image_angle);
for (var i = 0; i < num_guns; i++)
{
var _gun_x = x + _c * gun_array[i,0] + _s * gun_array[i,1];
var _gun_y = y + _c * gun_array[i,1] - _s * gun_array[i,0];
with instance_create(_gun_x,_gun_y,obj_bullet) { direction = other.image_angle; }
}
```

Crossoni likes this.
5. ### YalGMC MemerGMC Elder

Joined:
Jun 20, 2016
Posts:
4,214
To add context to @flyingsaucerinvasion's code, it's basically using the 2D rotation matrix (see below) to compute the position after rotation using the position before rotation. The sign of the y terms are reversed because GM's y axis is reversed (positive downwards instead of positive upwards).

6. ### Benjamin CrumpGuest

Thank you guys for the responses! I'm going to spend some time deciphering the answers to make sure I understand what you're doing, and then I'll implement. Again, thanks everybody!