1
\$\begingroup\$

Engine: Gamemaker Studio

I'm learning to code in GML and I am having difficulty in having my bullets be created in the desired position, the front of the object firing them. Here's how it presently looks. I made the "player object" transparent to see the bullets traveling "under" it for demonstration purpose.

enter image description here

Here's the code of the bullet creation: enter image description here

\$\endgroup\$
  • \$\begingroup\$ I may answer to your question, but first: what is the origin of both your bullet and "player object" sprite? Is it centered for both? \$\endgroup\$ – liggiorgio Jun 13 '16 at 9:49
  • \$\begingroup\$ BTW, randimize() need call only once, when game starts. \$\endgroup\$ – Dmi7ry Jun 13 '16 at 15:06
3
\$\begingroup\$

By "tip of rotating object", you meant the front? If that so.

You could do it easily if you have the rotation angle. Just add an offset to the bullet's spawn location/position. Speaking generally it would be something like:

x += offset * cos(angleInRadians);
y += offset * sin(angleInRadians);

This should be the basic idea. On your game, you probably want offset to be half the player's height (assuming your bullet is spawning from the middle of the player). And angleInRadians is of course the angle of your bullet (which i suppose is the player's angle + 90 degrees) in radians.

Oh, and when doing this step do it without the randomized angle. Because with the randomized angle, it means that your bullet are going to be translated not exactly in front of the player.


TL;DR: Move the bullet some step ahead without the randomized angle at the start.

\$\endgroup\$
2
\$\begingroup\$

Thanks everyone for the replies, it's very appreciated. Origins are in center of objects for the record. For reasons that don't really exist, I ended up using the solution given focusing on the angle of my object in radians, played with the numbers a bit and got a solution of code that looks like this:

enter image description here

I do plan to attempt the solution from Liggiorgio as well just for the sake of learning.

\$\endgroup\$
  • \$\begingroup\$ Instead of converting radians on your own, why don't you use the degtorad() built-in function? \$\endgroup\$ – liggiorgio Jun 14 '16 at 10:14
  • \$\begingroup\$ BTW you need to convert into radians when using goniometric functions, whilst the lengthdir_*() functions still use angles in degrees. \$\endgroup\$ – liggiorgio Jun 14 '16 at 10:17
  • \$\begingroup\$ I didn't do it that way out of a lack of awareness of that method ;P I only started learning this programming in the recent few days. \$\endgroup\$ – Bob Robertson Jun 15 '16 at 13:50
  • \$\begingroup\$ It's never late to learn something new :) \$\endgroup\$ – liggiorgio Jun 16 '16 at 7:02
2
\$\begingroup\$

Probably VERY late response, but you can do this:

instance_create( x+lengthdir_x(sprite_get_width( sprite_index)/2,image_angle),
                 y+lengthdir_y(sprite_get_height(sprite_index)/2,image_angle),
                 obj_bullet);

and the bullet will spawn at the tip of the object, no matter what image_angle it has.

\$\endgroup\$
1
\$\begingroup\$

Your issue can be easily solved. But first, I'd like to premise there's a tiny optimization you can do in your game.

Enhance

Since the direction variable is pointing leftwards when its value is 0, those sprites which are supposed to rotate (by changing the image_angle of the instance) of the same angle as direction may be loaded in GM:S facing the left side.

Sprite transformation: just rotate it!

This way, if you set the sprite_index of your "player object" to such a sprite, in the Step Event you can simply write:

image_angle = direction;

instead of:

image_angle = direction + 90;

The same applies for your bullet sprite: make it so that it's facing to the left.

Make it work

Now, let's make the player object fire the bullets properly. From now on, I'm assuming your sprites both have their respective origin at the center of the sprite itself. In the Space Press Event of your obj_player_press, change the source code as follow:

/// Fire bullet
var angle = random_range(-20,20);
var inst = instance_create(x,y,obj_bullet);
inst.image_angle = image_angle;
inst.direction = direction;
//inst.speed = some_value;

This way, your bullet object will be created at the same position where your "player object" is placed. The difference with your code is the usage of the local variable inst to change the value of the bullet variables instead of using the with statement. In this case, there's no need to use the with statement, as you're referring to one instance in particular only, and it's much cleaner, clearer, and faster referring to the instance by using its id on the go, instead of using the with statement, which will tell GM:S to look up for the instance whose id is the one taken as argument. The with statement is more effective when using object_indexes, whilst working with ids can be easier.

The final touch

We want the bullet to be created at the tip of our rotating object. We can achieve this by using the built-in functions lengthdir_x and lengthdir_y. What they do is computing the offset distances along the x and y axes for us. Let's edit our code as follows:

/// Fire bullet
var angle = random_range(-20,20);
var len = 32;
var inst = instance_create(x+lengthdir_x(len,direction),y+lengthdir_y(len,direction),obj_bullet);
inst.image_angle = image_angle;
inst.direction = direction;
//inst.speed = some_value;

They are as useful as easy to use. Check this out, and see your bullets being shot from the tip of your player object!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.