• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

GML Making a bullet with draw line? (or a trail/tracer) (Collision Line)

Dr_Nomz

Member
You know this sounds simple, but I have no idea where to begin. Basically I have this code:
Code:
var shot, count, spread, shot_offset;
count = 1; // how many per shot
spread = 15; // how much spread
shot_offset = 25; //How far from the character the bullet(s) are created.

if (canshoot < 0){
  canshoot = 0;
  shot = instance_create(x+lengthdir_x(shot_offset,angle_1),y+lengthdir_y(shot_offset,angle_1),obj_Bullet);
  shot.direction = angle_1 + (round(random(spread))) - spread*0.5;
  shot.image_angle = shot.direction;
  shot.speed = 40;
}
And it works great for creating a bullet object that jumps to the pixels specified, but I kinda want to make it look nicer, by adding a line that follows between those points. So if the bullet travels 50 pixels forward, it'll leave a trail 50 px behind it. (a line)

How do I do this?

Also it would be really great if that line touches something then it runs the code to destroy itself and damage the object if necessary.
 

Dr_Nomz

Member
Okay great, that works perfectly! :D Problem: the line is layered OVER the sprite, even though "draw_self" is at the top of the list. :/ How do I fix that?

ALSO how do I make the line be part of the collision? So that if it hits something, it runs the destroy/damage code.

Finally, how do I customize it? A pencil thin white line is boring, so how do I change it's thickness and color? And can I do anything else fancy with it?
 

Simon Gust

Member
1. draw_self should be below the draw_line code wise.
2. the bullet would already hit in a line if you use the right collision code, whether you have a line drawn there doesn't matter.
3. you have some other functions called draw_line_width_colour() to customize your line.

Rough collision with obj_enemy code
Code:
var x1 = x;
var y1 = y;
var x2 = x + lengthdir_x(speed, direction);
var y2 = y + lengthdir_y(speed, direction);
var inst = collision_line(x1, y1, x2, y2, obj_enemy, false, false);
if (inst != noone)
{

}
if an enemy is hit, it's id will be saved to "inst".
 
For the sprite layering issue you have to put draw_self() after the draw_line();

You can draw a "custom" line with the draw_line_width_colour() function and playing with blend modes:
Code:
draw_set_blend_mode(bm_add): or gpu_set_blendmode(bm_add);    // GMS1 -  GMS2
draw_line_width_colour(x1, y1, x2, y2, w, col1, col2);
draw_set_blend_mode(bm_normal):
draw_set_blend_mode(bm_add): or gpu_set_blendmode(bm_normal);  // GMS1 -  GMS2

draw_self();
For collisions, try experimenting with:
collision_line(x1, x2, y1, y2, obj, prec, notme);

Example:
Code:
with (collision_line(x1, x2, y1, y2, oWall, false, true)) {
      instance_destroy();
}
 

Dr_Nomz

Member
For the sprite layering issue you have to put draw_self() after the draw_line();

You can draw a "custom" line with the draw_line_width_colour() function and playing with blend modes:
Code:
draw_set_blend_mode(bm_add): or gpu_set_blendmode(bm_add);    // GMS1 -  GMS2
draw_line_width_colour(x1, y1, x2, y2, w, col1, col2);
draw_set_blend_mode(bm_normal):
draw_set_blend_mode(bm_add): or gpu_set_blendmode(bm_normal);  // GMS1 -  GMS2

draw_self();
Could you explain what this code does exactly? I don't follow.

Otherwise, I'll experiment with these suggestions when I have time later, thanks.

EDIT: Also since when does Game Maker layer things over top of eachother like that? Isn't the code at the top run first, followed by everything else? So why is "draw_self" not prioritized in the sprite layers if it's on top?
 
Your code will be compiled from the top to the bottom, so you have to call draw_line first, if you want the player to be above the line.
DrawSelf.png

draw_set_blend_mode(GMS1) or gpu_set_blendmode(GMS2) allow you to change how the colour of the pixel you're going to draw (Source Colour) and the colour of the pixel you're drawing to (Destination Colour) are being blended.
If you are familiar with photoshop, they are actually like the [normal, dissolve, multiply, color burn..] blending modes.

Code:
// Set additive blending
draw_set_blend_mode(bm_add):
// Draw the line with additive blending
draw_line_width_colour(x1, y1, x2, y2, w, col1, col2);
// Reset to default blend mode, now everything will be drawn with normal blending (default)
draw_set_blend_mode(bm_normal):

// Draw the player
draw_self();
BlendModes.png

If you are using GMS2, use gpu_set_blendmode() instead.

I suggest you to read these articles about blend modes:
https://www.yoyogames.com/blog/56/explaining-blend-modes-part-1
https://www.yoyogames.com/blog/57/explaining-blend-modes-part-2
 

Attachments

Dr_Nomz

Member
Wait, so the first thing to be drawn starts at the bottom, and everything after is drawn on top of it? That feels very backwards but okay. Thanks.

EDIT: Not sure anyone will even see this post at this point, but I might as well mention I'm editing this at 9/21/2019. It actually makes perfect sense because you type code moving down, so the first thing will be the background and everything else will be above it, otherwise you wouldn't see it as you're coding. Hope that made sense.
 
Last edited:

Dr_Nomz

Member
Wow it's been a long time since this was updated. Hi again, finally looking into this to get it working.

Code:
var x2 = x + lengthdir_x(speed, direction);
var y2 = y + lengthdir_y(speed, direction);
if collision_line(x,y,x2,y2,obj_Wall,false,false){
  instance_destroy(id);
}
//Draw:
draw_line(x,y,xprevious,yprevious)
draw_self();
That's what I'm using (tried the draw stuff above the collision stuff too) but every time the bullets hit the wall they leave their sprite behind instead of destroying themselves. What's going on?

I also tried a few different variations of the collision code, first copying the original exactly (it's in this thread) and then copying the x/y previous line in the collision check. (Which gave the exact same results, actually.)

It DOES predict where the line is going and stops the bullet, but it's sprite lingers. Any idea why and how I can fix that? EDIT: Actually turns out it's the object. It just stops moving before it hits the wall, not actually deleting the object itself.


EDIT2: Actually you know what, I figured out what was causing it. Having a collision with wall event that had nothing in it other than a title comment (///) and a commented out instance_destroy() line. (//) Not sure why though, that's really weird.
 
Last edited:
Top