Jump to content


Photo

LASER BEAM! Well I hope any way.


  • Please log in to reply
20 replies to this topic

#1 sunnysideunder

sunnysideunder

    GMC Member

  • GMC Member
  • 50 posts
  • Version:GM8

Posted 27 March 2016 - 01:03 AM

So I'm seeing a handful of tutorial of creating laser beams. Most follow a mouse and are single pixel. I am looking to create beams 6- 10 px wide. It's for a shmup and needs to lead from my ship to the top of my view and must move with the ship. I'm not looking for an insane Dodonpachi beam but, I am looking for any enemy that collides with the beam gets damaged per step. What would be the best way to go about this? 


  • 0

#2 johnboy

johnboy

    GMC Member

  • GMC Member
  • 496 posts
  • Version:GM:Studio

Posted 27 March 2016 - 01:42 AM

I can think of two ways to do this:

 

1)Use draw_sprite_pos (?)  or sprite rotation so that a sprite can be moved around - collisions could then be handled physically, and the draw_sprite_pos allows you to place it at whatever width you want.

2) Use the inbuilt draw function draw_line_width (?) to create the "beam" , and then use collision_line to check for objects that are affected, as I don't think drawing the beam with this function gives it a physical presence to check for collisions.

 

Either of those two is a fairly basic place for you to begin with. You might then look at surfaces and shaders for enhancing the visual effect - but I can't really clue you up on that side of things. I do think option 2 is the most intensive choice performance wise: collision_line isn't too bad, but draw_line etc is fairly hefty for something so simple.

 

EDIT: I'm writing this without GMS in front of me, so apologies if the commands aren't quite right


Edited by johnboy, 27 March 2016 - 01:44 AM.

  • 1

#3 Bojack29

Bojack29

    GMC Member

  • GMC Member
  • 1649 posts
  • Version:GM:Studio

Posted 27 March 2016 - 04:07 AM

Heres a post I dug up from last year

Okay so everything went relatively smoothly. All done.

There are some key things that need to be illustrated so I will lay them out here. First and foremost, you need an object beam and two sprites. One sprite representing the head of the beam and another sprite consisting of the full beam. The beam stem itself can animate as well.

Make sure the sprite's origin is centered and at the bottom for the stem (VERY important)

Here is the code for obj_beam (Make sure obj_beam's sprite is the head of the beam, he is going to draw his stem)

CREATE

///Settings

int_xoffset = sprite_get_xoffset(spr_beamStem);

int_yoffset = sprite_get_yoffset(spr_beamStem);

int_width = sprite_get_width(spr_beamStem);

int_height = sprite_get_height(spr_beamStem);

int_beamImageIndex = 0;

int_imageNumber = sprite_get_number(spr_beamStem) - 1;
DRAW
///Draw self

x = obj_ship.x;

if (collision_line(x, 0, obj_ship.x, obj_ship.y, obj_enemy, false, true)){
    var yy = obj_ship.y;
    while(!place_meeting(x, yy, obj_enemy)){
        yy --;
    }     
    y = yy;
}else{
    y = 0;
}

int_beamImageIndex ++;

if (int_beamImageIndex > int_imageNumber){
    int_beamImageIndex = 0;
}

if (obj_ship.y - y <= int_height){
    int_yoffset = obj_ship.y - y;
}else{
    int_yoffset = sprite_get_yoffset(spr_beamStem);
}
    
draw_sprite_part(spr_beamStem, int_beamImageIndex, 0, 0, int_width, obj_ship.y - y, obj_ship.x - int_xoffset, obj_ship.y - int_yoffset);
    
draw_self();

Edited by Bojack29, 27 March 2016 - 04:35 AM.

  • 1

#4 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 18181 posts
  • Version:GM:Studio

Posted 27 March 2016 - 05:42 AM

http://gmc.yoyogames...howtopic=295555

 

Everything is pretty much covered here...

 

long story short, collision_line_first or range_finder (or combine them) on gmlscripts.com


  • 1

gmcbanner.pnggmcbanner_tools.png

ICU Live Tutoring Through Slack or Skype | My Tools Page follow.png

I FRANTICALLY MADE MY 18000 POST TOPIC BEFORE MIKE ANNOUNCED A DELAY...
Now I'm squirming not to hit that reply button


#5 sunnysideunder

sunnysideunder

    GMC Member

  • GMC Member
  • 50 posts
  • Version:GM8

Posted 27 March 2016 - 09:35 AM

 

 

Heres a post I dug up from last year

Quote

Okay so everything went relatively smoothly. All done.

There are some key things that need to be illustrated so I will lay them out here. First and foremost, you need an object beam and two sprites. One sprite representing the head of the beam and another sprite consisting of the full beam. The beam stem itself can animate as well.

Make sure the sprite's origin is centered and at the bottom for the stem (VERY important)

Here is the code for obj_beam (Make sure obj_beam's sprite is the head of the beam, he is going to draw his stem)

CREATE

///Settings

int_xoffset = sprite_get_xoffset(spr_beamStem);

int_yoffset = sprite_get_yoffset(spr_beamStem);

int_width = sprite_get_width(spr_beamStem);

int_height = sprite_get_height(spr_beamStem);

int_beamImageIndex = 0;

int_imageNumber = sprite_get_number(spr_beamStem) - 1;DRAW
///Draw self

x = obj_ship.x;

if (collision_line(x, 0, obj_ship.x, obj_ship.y, obj_enemy, false, true)){
var yy = obj_ship.y;
while(!place_meeting(x, yy, obj_enemy)){
yy --;
}
y = yy;
}else{
y = 0;
}

int_beamImageIndex ++;

if (int_beamImageIndex > int_imageNumber){
int_beamImageIndex = 0;
}

if (obj_ship.y - y <= int_height){
int_yoffset = obj_ship.y - y;
}else{
int_yoffset = sprite_get_yoffset(spr_beamStem);
}

draw_sprite_part(spr_beamStem, int_beamImageIndex, 0, 0, int_width, obj_ship.y - y, obj_ship.x - int_xoffset, obj_ship.y - int_yoffset);

draw_self();
 

So I gave this a shot and it I crash and crash hard. I don't even get an error message I just freeze up. This is unfortunate, because the code looked so promising and made the most sense to me. 

 

 

http://gmc.yoyogames...howtopic=295555

 

Everything is pretty much covered here...

 

long story short, collision_line_first or range_finder (or combine them) on gmlscripts.com

I actually saw this post when I was googling about and it turned me off when I saw the the first sentence said something about 1px wide. I just read into it more and see I was wrong to do so. However, this code blows my mind. I am really lost. I got it to work somewhat... I am drawing the beam but, it is moving in the wrong direction and very slow. Also, there is an alarm [0] in the player step event that I think is supposed to correlate with the alarm[0] in the obj_laser. So that is throwing me off too. *Choke* Help? Sorry for my noob ways. Really appreciate the help!


  • 0

#6 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Elder
  • 18181 posts
  • Version:GM:Studio

Posted 27 March 2016 - 11:43 AM

basic concept is changing the image_xscale until it contacts the enemy.  image_angle specified the direction of the beam. origin x needs to be 0 and y centered. and the image needs to have precision collision ON

 

the weird code does that. checking at full lenght, if collision, retry at half length, if still collision retry at half that length... if no collision then grow bu half the length... until it touches again or the number of tries is reached.

 

the alarm stuff is just to keep the instance up for a period of time, 10 draw in the example so you have a chance to see it. it's not needed...

 

 

you can achieve the same result with range_finder. you call range finder. it gives you the distance. you create a laser instance and change the image_xscale to match the distance in pixels + 1 extra pixel... the distance_calculated / the sprite width

 

the instance can have an alarm so it stays up a bit and it can have a collision event to perform damage. though the initial laser collision check is done with collision line the final collision is the width of the sprite's height


Edited by icuurd12b42, 27 March 2016 - 11:44 AM.

  • 1

gmcbanner.pnggmcbanner_tools.png

ICU Live Tutoring Through Slack or Skype | My Tools Page follow.png

I FRANTICALLY MADE MY 18000 POST TOPIC BEFORE MIKE ANNOUNCED A DELAY...
Now I'm squirming not to hit that reply button


#7 Bojack29

Bojack29

    GMC Member

  • GMC Member
  • 1649 posts
  • Version:GM:Studio

Posted 27 March 2016 - 01:58 PM

Thats unusual. I built the obj_beam for a fellow a long time ago as an experiment and it worked marvelously. Tell me, is there an appropriate mask for the head of your beam? I tell you this object works perfectly, something else is at play within your game. Its a beam for a top down plane game that scrolls vertically.

Please don't give up, I'll help you figure it out. The object is vercital and allows for any size beam at any length and width. It even animates the beam if you have multiple subimages for the stem.

please post some relative code so I can see what's going on.

As an added note I do believe the beam head sprite had his origin fixed at x = center and y = 0. That's how the beam head understood collisions.

Edited by Bojack29, 27 March 2016 - 02:00 PM.

  • 1

#8 sunnysideunder

sunnysideunder

    GMC Member

  • GMC Member
  • 50 posts
  • Version:GM8

Posted 27 March 2016 - 06:58 PM

 

 

Thats unusual. I built the obj_beam for a fellow a long time ago as an experiment and it worked marvelously. Tell me, is there an appropriate mask for the head of your beam? I tell you this object works perfectly, something else is at play within your game. Its a beam for a top down plane game that scrolls vertically.

Please don't give up, I'll help you figure it out. The object is vercital and allows for any size beam at any length and width. It even animates the beam if you have multiple subimages for the stem.

please post some relative code so I can see what's going on.

As an added note I do believe the beam head sprite had his origin fixed at x = center and y = 0. That's how the beam head understood collisions. 

 

Alrighty, so I have made some ground! I duplicated my ship sprite to fit edit the spr_beam for a good fit and forgot to fix the modified masking. That is fixed now. I have created a 14px wide spr_beam that is 540 px high. The spr_beam_tip has precise collision with an origin centered on x and y of 0. My spr_beam (this is my stem) has precise collision with the origin centered on x and with a y of 5. My obj_beam has the spr_beam_tip as the attached sprite. 

 

So in my create event for my ob_beam.

 

///Settings

 
int_xoffset = sprite_get_xoffset(spr_beam);
 
int_yoffset = sprite_get_yoffset(spr_beam);
 
int_width = sprite_get_width(spr_beam);
 
int_height = sprite_get_height(spr_beam);
 
int_beamImageIndex = 0;
 
int_imageNumber = sprite_get_number(spr_beam) - 1;

 

Draw of obj_beam.

 

///Draw self

 
x = obj_ship.x;
 
if (collision_line(x, 0, obj_ship.x, obj_ship.y, obj_enemy_parent, false, true)){
    var yy = obj_ship.y;
    while(!place_meeting(x, yy, obj_enemy_parent)){
        yy --;
    }     
    y = yy;
}else{
    y = 0;
}
 
int_beamImageIndex ++;
 
if (int_beamImageIndex > int_imageNumber){
    int_beamImageIndex = 0;
}
 
if (obj_ship.y - y <= int_height){
    int_yoffset = obj_ship.y - y;
}else{
    int_yoffset = sprite_get_yoffset(spr_beam);
}
    
draw_sprite_part(spr_beam, int_beamImageIndex, 0, 0, int_width, obj_ship.y - y, obj_ship.x - int_xoffset, obj_ship.y - int_yoffset);
    
draw_self();

 

Step event of my ship. Which is going to be changed, I'm just trying to make it work for now. 

 

//BEAM

if (keyboard_check_pressed(ord('U')))
{
      instance_create( x, y, obj_beam);
}
 

 

So now my I am now drawing the beam! However, if there is no enemy in front of the ship the beam goes down not up. If there is a ship in front of the enemy it works perfect. Now I don't know if these attributes would do anything but, my view scrolls across my room at y = -1 and my enemies are placed above the view then activate once in the room. Maybe if I can get the beam to stop at view_yview it will work? I'm not sure how I would work that in the code. 

 

EDIT

 

Alright so I re-read my post and caught myself. Not sure why I had the origin of spr_beam at a y of 5. Changed it to 540 and it works perfectly! So it wasn't a code thing after all it was my sprites... However if i could get a solution to the beam stopping a view_yview that would be awesome too! I really appreciate everything. 


Edited by sunnysideunder, 27 March 2016 - 07:19 PM.

  • 0

#9 Bojack29

Bojack29

    GMC Member

  • GMC Member
  • 1649 posts
  • Version:GM:Studio

Posted 27 March 2016 - 09:31 PM

Hm. Well need some reworking here. You could switch that 0 argument out for view_yview[0]. Here's the relevant code.

//Changed the y argument
if (collision_line(x, view_yview[0], obj_ship.x, obj_ship.y, obj_enemy_parent, false, true)){
    var yy = obj_ship.y;
    while(!place_meeting(x, yy, obj_enemy_parent)){
        yy --;
    }     
    y = yy;
}else{
    y = view_yview[0];//Change here too
}

  • 1

#10 sunnysideunder

sunnysideunder

    GMC Member

  • GMC Member
  • 50 posts
  • Version:GM8

Posted 27 March 2016 - 11:14 PM

Hahahaha this is great! I have been having so much fun beaming stuff down I have totally forgot about making a game. So I decent way to execute the beam in my player step event. Let me know what you think. 

 

//Beam

if (keyboard_check(ord('U')))
{
    global.beam = true;
 
if global.beam = true && !instance_exists(obj_beam)
{
    instance_create(x, y, obj_beam);
}
 
if !(keyboard_check(ord('U')))
{
    global.beam = false;
}

 

Then in my beam step event if global.beam = false I have it destroy itself. Thoughts?


  • 0

#11 Bojack29

Bojack29

    GMC Member

  • GMC Member
  • 1649 posts
  • Version:GM:Studio

Posted 27 March 2016 - 11:31 PM

There are more simple ways to do this

if (keyboard_check_pressed(ord('U')){
     instance_create(x, y, obj_beam);
}

if (keyboard_check_released(ord('U')){
     with(obj_beam){
          instance_destroy();
     }
}

  • 1

#12 sunnysideunder

sunnysideunder

    GMC Member

  • GMC Member
  • 50 posts
  • Version:GM8

Posted 27 March 2016 - 11:34 PM

Ah, yes! I keep forgetting about the 'with' statements. This is much cleaner. Thanks Bojack29 I owe you big!


  • 0

#13 Bojack29

Bojack29

    GMC Member

  • GMC Member
  • 1649 posts
  • Version:GM:Studio

Posted 27 March 2016 - 11:39 PM

;) glad it worked. Just mention me in the credits and I hope to see the release.
  • 0

#14 sunnysideunder

sunnysideunder

    GMC Member

  • GMC Member
  • 50 posts
  • Version:GM8

Posted 28 March 2016 - 01:06 AM

Oh, noes! I've just found a bug. So some of my ai backs out of the room going up and when the enemies have a negative y-speed I'm not making a collision with the enemies. No damage or animation. 

 

I already wrote your username down just in the event of a release!  :lol:


  • 0

#15 Bojack29

Bojack29

    GMC Member

  • GMC Member
  • 1649 posts
  • Version:GM:Studio

Posted 28 March 2016 - 01:18 AM

Your head beam object should be doing all of the collision code. Assuming your beams origin is x center and y 0, the beam should be checking for a collision with position_meeting(x, y - 1, par_enemy)
  • 0

#16 sunnysideunder

sunnysideunder

    GMC Member

  • GMC Member
  • 50 posts
  • Version:GM8

Posted 28 March 2016 - 07:17 AM

I just double checked my beam_tip object and the sprite is correct. I changed it to y of 1 just to see and same results. Any of my enemies that have a vspeed of less than -1 are not forming a collision. I have them set that way because of my scrolling view. Now maybe I'm thinking wrong but, if I'm checking for a collision at y-1 per step and my enemies traveling away at less than that, like -2, are my enemies out running the collision?


  • 0

#17 Bojack29

Bojack29

    GMC Member

  • GMC Member
  • 1649 posts
  • Version:GM:Studio

Posted 28 March 2016 - 08:40 AM

Here is the collision.
var t, xx, yy;

x = obj_ship.x;
 
if (collision_line(x, view_yview[0], obj_ship.x, obj_ship.y, obj_enemy_parent, false, true)){
    yy = obj_ship.y;
    while(!place_meeting(x, yy, obj_enemy_parent)){
        yy --;
    }     
    y = yy;
}else{
    y = view_yview[0];
}

t = instance_position(x, y - 1, obj_enemy_parent);

if (t > -4){
     with(t){
          hp -= 10;
          if (hp < 0){
               instance_destroy();
          }
     }
}
This will drain 10 hp from any unit for every frame it is attacked by the beam

Edited by Bojack29, 29 March 2016 - 04:47 AM.

  • 0

#18 sunnysideunder

sunnysideunder

    GMC Member

  • GMC Member
  • 50 posts
  • Version:GM8

Posted 29 March 2016 - 12:02 AM

Yes that works even when they are traveling a vspeed of -1 or less. I'm still not getting the collisions though. I have my collisions happening in a collision event. Should it be there? It's just hp and image values right now. 

 

EDIT 

Also, where would be the best place to code in something like if the player is destroyed, destroy the beam?


Edited by sunnysideunder, 29 March 2016 - 12:15 AM.

  • 0

#19 Bojack29

Bojack29

    GMC Member

  • GMC Member
  • 1649 posts
  • Version:GM:Studio

Posted 29 March 2016 - 12:33 AM

Do your collisions against the enemy in the same event where your beam heads step event it. I am suspicious that you're enemy is moving before your collision event has a chance to fire off. Simply change the code where I have that message box.

As for your health, something like this should suffice.
if (hp < 0){
     with(obj_ beam){
          instance_destroy();
     }
     instance_destroy();
}

  • 0

#20 sunnysideunder

sunnysideunder

    GMC Member

  • GMC Member
  • 50 posts
  • Version:GM8

Posted 29 March 2016 - 01:49 AM

The health code works perfect! I'm lost on the collision part though. Where exactly do you want me to put it? I have this right now.

 

Collision event with enemy parent

 

/// Hit the enemy

    instance_create(x,y, obj_flare);
    other.hp -= 2;

  • 0

#21 Bojack29

Bojack29

    GMC Member

  • GMC Member
  • 1649 posts
  • Version:GM:Studio

Posted 29 March 2016 - 04:48 AM

Here is the collision.
var t, xx, yy;

x = obj_ship.x;
 
if (collision_line(x, view_yview[0], obj_ship.x, obj_ship.y, obj_enemy_parent, false, true)){
    yy = obj_ship.y;
    while(!place_meeting(x, yy, obj_enemy_parent)){
        yy --;
    }     
    y = yy;
}else{
    y = view_yview[0];
}

t = instance_position(x, y - 1, obj_enemy_parent);

if (t > -4){
     with(t){
          hp -= 10;
          if (hp < 0){
               instance_destroy();
          }
     }
}
This will drain 10 hp from any unit for every frame it is attacked by the beam
  • 0