GameMaker: Lightning between points

Poorly animated and still previews of lightning

This intermediate example demonstrates creation of a nice-looking lightning effect in GameMaker.

A 8-parameter, well-commented 50-line script gives a lot of freedom in relation to drawing lightning effects between points, controlling "density", "width", and actual drawing behaviour. It is also optimized to skip drawing if lightning is not going to overlap view area.

And it looks pretty cool, overall.

Download GMK

Code follows,

/// draw_lightning(x1, y1, x2, y2, xmin, xmax, ymin, ymax)
//                  0   1   2   3     4     5     6     7
/** Draws a lightning between points.
 * @x1 : source X
 * @y1 : source Y
 * @x2 : destination X
 * @y2 : destination Y
 * @xmin : minimum distance step (>0)
 * @xmax : maximum distance step (>xmin)
 * @ymin : minimum "side" step (lightning "width")
 * @ymax : maximum "side" step (lightning "width")
 * @return number of segments drawn.
var i, r, c, l, dx, dy, sx, sy, px, py, cx, cy, alpha;
// avoid drawing outside view:
if (max(argument0, argument2) < view_xview[view_current] - 10) return 0
if (max(argument1, argument3) < view_yview[view_current] - 10) return 0
if (min(argument0, argument2) > view_xview[view_current] + view_wview[view_current] + 10) return 0
if (min(argument1, argument3) > view_yview[view_current] + view_hview[view_current] + 10) return 0
// find distance between points (used for loop)
l = point_distance(argument0, argument1, argument2, argument3)
if (l == 0) return 0
// main direction:
i = point_direction(argument0, argument1, argument2, argument3)
dx = lengthdir_x(1, i); dy = lengthdir_y(1, i)
// side direction:
i += 90
sx = lengthdir_x(1, i); sy = lengthdir_y(1, i)
// first point coordinates:
px = argument0; py = argument1
c = 0
i = random_range(argument4, argument5)
alpha = draw_get_alpha()
repeat (5000) { // edit for line segment limit
    r = choose(-1, +1) * (argument6 + (argument7 - argument6)
        * lengthdir_y(random(1), i / l * 180)) // this part makes lightning "wider" near middle
    // current point coordinates:
    if (i < l) {
        cx = argument0 + dx * i + sx * r
        cy = argument1 + dy * i + sy * r
    } else { cx = argument2; cy = argument3 } // end point
    // line drawing code here:
    // can be just a single draw_line or something fancy like this:
    draw_set_alpha(alpha * 0.3)
    draw_line_width(px, py, cx, cy, 3.7)
    draw_set_alpha(alpha * 0.7)
    draw_line_width(px, py, cx, cy, 1.3)
    // exit condition:
    if (i >= l) break
    // update previous point coordinates:
    px = cx; py = cy
    // increments:
    c += 1
    i += random_range(argument4, argument5)
return c

ВК 3369

Related posts:

17 thoughts on “GameMaker: Lightning between points

  1. Neat script! Gotta say though, the naming conventions leave something to be desired. There’s a reason naming is one of the hardest things in programming :)

    • Admittedly, this script is pretty old – it tells through it’s variable declarations on top of the script (because GM<=8.0 did not support `var name=value` syntax) and general absence of trailing semicolons on lines.

      I’d love to say that I’ve also since moved away from giving 1-2 letter names to local variables, but, alas – auto-completion and syntax highlighting for those only made it’s entry recently, and old habits don’t go easily.

      I’ll get around to reorganizing this a bit and making an interactive demo one of these days.

      • Did you manage to rewrite it? I failed miserably at it and i would love to see how its supposed to be

        • Not yet, there’s a lot happening right now. It still works fine, it’s just that the code looks bad.

          Adding caching would require vertex buffers and a couple other things.

  2. It works so well, thank you very much !

    I have a concern however : this script seems very heavy on CPU when you multiply its use (for my game, I use it a hundred times at once… ^^). Any clue on how make it lighter?

    Thank you again for this blog!

    • If you use it a lot, you’ll need to rewrite the script to work a bit more efficiently – in a good case to use vertex buffers, or at least primitives. I don’t have time to make a new version of this script right now, but you can ask for help on Discord if you get stuck.

      • Thanks for your answer anyway. Your blog is such a valuable ressource, I hope you’ll get more time in the future.

    • Hey, your result looks so nice and some friends and I were wondering how you implemented the effect.
      I know it is an old post, but could you tell us something about that? Thanks!

      • Well, the complete source code is included in the post itself..?

        A short version would be that it’s two lines (for cheap “glow”) with “wiggle” increasing closer to the midpoint.

  3. thanks a lot it is amazing i run it in GM studio after i change execute_string on string function

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.