GMS 2 2D Hitscan

Discussion in 'Tutorials' started by Ratsha, Jan 17, 2019.

  1. Ratsha

    Ratsha Member

    Joined:
    Jun 22, 2016
    Posts:
    59
    GM Version: GMS2
    Target Platform: ALL
    Download: N/A
    Links: N/A

    Summary:
    How to implement hitscan in 2D games using collision_line().

    Tutorial:

    Code below for the hitscan code in Left Clicked Event.
    This includes a fix (gun_direction) that accounts for the gun's slightly offset in the Sprite.
    Code:
    var gun_x = x + lengthdir_x(gunDistance, image_angle + gunAngle);
    var gun_y = y + lengthdir_y(gunDistance, image_angle + gunAngle);
    var gun_direction = point_direction(gun_x, gun_y, mouse_x, mouse_y);
    var aimed_x = gun_x + lengthdir_x(500, gun_direction);
    var aimed_y = gun_y + lengthdir_y(500, gun_direction);
    instance_create_layer(gun_x, gun_y, "Instances", oMuzzleFlash);
    
    var target = collision_line(gun_x, gun_y, aimed_x, aimed_y, oTarget, true, true);
    if (target == noone) {
        effect_create_above(ef_smoke, aimed_x, aimed_y, 0, c_white);
    } else {
        var contact_x = aimed_x;
        var contact_y = aimed_y;
        var percent_start = 0;
        var percent_end = 1;
        var distance_x = aimed_x - gun_x;
        var distance_y = aimed_y - gun_y;
        var iterations = ceil(log2(point_distance(gun_x, gun_y, aimed_x, aimed_y)))
        repeat (iterations) {
            var middle_way =  (percent_end - percent_start) * 0.5 + percent_start;
            var end_x = distance_x * middle_way + gun_x;
            var end_y = distance_y * middle_way + gun_y;
            var start_x = distance_x * percent_start + gun_x;
            var start_y = distance_y * percent_start + gun_y;
            var found = collision_line(start_x, start_y, end_x, end_y, oTarget, true, true);
            if (found == noone) {
                percent_start = middle_way;
            } else {
                target = found;
                contact_x = end_x;
                contact_y = end_y;
                percent_end = middle_way;
            }
        }
        if (target.object_index == oWall) {
            effect_create_above(ef_smoke, contact_x, contact_y, 0, c_white);
        } else if (target.object_index == oEnemy) {
            // hp reduction
            effect_create_above(ef_smoke, contact_x, contact_y, 0, c_red);
        }
    }
     
    Last edited: Jan 18, 2019
    trg601 and Edwin like this.
  2. maybethatsyou

    maybethatsyou Member

    Joined:
    Aug 3, 2019
    Posts:
    7
    Free Godot have RayCast and this code in Godot have 3 lines...
     
  3. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,404
    ... and it takes other workarounds to implement place_meeting/position_meeting/instance_place/instance_position there. What was the point of the comment again?
     
  4. Lonewolff

    Lonewolff Member

    Joined:
    Jan 8, 2018
    Posts:
    1,207
    Great. :)

    This is a GameMaker forum though. You seem to be lost.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice