GMS 2 Putting dents in a vehicle sprite

Discussion in 'Programming' started by A Random Creator, May 14, 2019.

  1. A Random Creator

    A Random Creator Member

    Joined:
    Jun 22, 2016
    Posts:
    90
    Hello! So my problem is pretty simple, however to my knowledge takes a really complicated solution..
    In my game I want the vehicles to be dented whenever they collide with a solid object, or get hit by a bullet or something. How I've done this is I made my sprite drawn through a primitive triangle strip and I simply "dent" one of the coordinates if it has been shot/crashed. The problem I'm having is I'm not sure how I should detect where the bullet hits the vehicle (or where the vehicle impacted) to place the dent.
    This is my code:
    Code:
    //Car create event
    Color = make_color_rgb(random(255),random(255),random(255))
    IndentVertexes = 20 //Number of corners that can be indent when the vehicle takes damage
    IndentValues = ds_grid_create(2,IndentVertexes)
    Code:
    //Car draw event
    var sprInd = 0
    var Col = Color
    repeat(2) {
    var tex = sprite_get_texture(sprite_index,sprInd);
    draw_primitive_begin_texture(pr_trianglestrip,tex);
    var mx = IndentVertexes;
    var xx = 0
    var yy = 0
    for(var i=1;i<=mx;i+=1) {
    if(yy > sprite_height) { yy = 0 xx += sprite_width/(mx/2-1) }
    //Local top right corner coords + xx + yy
    var Ox = -sprite_width/2+xx-ds_grid_get(IndentValues,0,i-1)
    var Oy = -sprite_height/2+yy-ds_grid_get(IndentValues,1,i-1)
    //In World rotated coords
    var Rx = x + (Ox  * dcos(-image_angle)) - (Oy * dsin(-image_angle))
    var Ry = y + (Ox  * dsin(-image_angle)) + (Oy * dcos(-image_angle))
    if(DEBUGGING) { draw_set_color(merge_color(c_red,c_lime,i/mx)) draw_circle(Rx,Ry,2,0) }
    draw_vertex_texture_color(Rx,Ry,xx/sprite_width,yy/sprite_height,Col,image_alpha)
    yy += sprite_height
    }
    draw_primitive_end()
    sprInd += 1
    Col = c_white
    }
    Code:
    //Bullet collision (this is in the step event of the bullet before moving the bullet)
    var Colis = collision_line(x,y,x+lengthdir_x(Spd,Angle),y+lengthdir_y(Spd,Angle),oPlayerSolids,0,1)
    if(Colis != noone) {
        if(Colis.object_index = oCar) {
            var Multi = 1
            if(point_direction(Colis.x,Colis.y,x,y) > 180) { Multi = 2 }
            var NearestPoint = round(((x-(Colis.x-Colis.sprite_width/2))/Colis.sprite_width)*(Colis.IndentVertexes/2))
            NearestPoint = min(max(0,NearestPoint),Colis.IndentVertexes/2-1)*Multi
            var Grid = Colis.IndentValues
            ds_grid_set(Grid,0,NearestPoint,-lengthdir_x(Spd,Angle)*0.2)
            ds_grid_set(Grid,1,NearestPoint,-lengthdir_y(Spd,Angle)*0.2)
            show_debug_message("Car hit, Nearest Vertex = "+string(NearestPoint))
        }
    instance_destroy()
    }
    There's probably better ways to do this than I am doing, if you know one please let me know! My primary concern however is figuring out how I can best dent the nearest vertex to where the vehicle has taken damage. Thank you in advance for any assistance!
     
  2. obscene

    obscene Member

    Joined:
    Jun 21, 2016
    Posts:
    2,428
    Seems like you're pretty close already.

    I would cycle through the grid and use point_distance to see if the impact point is within a range. Then do just as you done setting the grid values using lengthdir_x and lengthdir_y.

    Since you're not changing the sprite the collision function won't be accurate to the ever-changing shape of the vehicle so keep that in mind. How you'd do that accurately would be through a series of point_in_triangle calls (I think that's a function) using your vertices.
     
    A Random Creator likes this.
  3. A Random Creator

    A Random Creator Member

    Joined:
    Jun 22, 2016
    Posts:
    90
    I didn't think of that, thanks! I'll try that.
    Also for the collision I don't really mind if it's inaccurate, I plan on setting a maximum dent size so that the collision change won't be too noticeable, but I wasn't even taking collision in mind either so thanks for the tips!
     
  4. A Random Creator

    A Random Creator Member

    Joined:
    Jun 22, 2016
    Posts:
    90
    For anyone else who'd like to make this effect here's my final changes:

    Code:
    //Car Create
    Color = make_color_rgb(random(255),random(255),random(255))
    IndentVertexes = 32 //Number of corners that can be indent when the vehicle takes damage
    MaximumIndent = -2.5
    IndentValues = ds_grid_create(2,IndentVertexes) //Don't forget to destroy in clean event
    Code:
    //Car Draw
    var sprInd = 0
    var Col = Color
    repeat(2) { //Car has a color layer and a do not color layer
    var tex = sprite_get_texture(sprite_index,sprInd);
    draw_primitive_begin_texture(pr_trianglestrip,tex);
    var mx = IndentVertexes;
    var xx = 0
    var yy = 0
    for(var i=1;i<=mx;i+=1) {
    if(yy > sprite_height) { yy = 0 xx += sprite_width/(mx/2-1) }
    //Local top right corner coords + xx + yy
    var Ox = -sprite_width/2+xx-ds_grid_get(IndentValues,0,i-1)
    var Oy = -sprite_height/2+yy-ds_grid_get(IndentValues,1,i-1)
    //In World rotated coords
    var Rx = x + (Ox  * dcos(-image_angle)) - (Oy * dsin(-image_angle))
    var Ry = y + (Ox  * dsin(-image_angle)) + (Oy * dcos(-image_angle))
    if(DEBUGGING) {
    var Progress = abs(max(abs(ds_grid_get(IndentValues,0,i-1)),abs(ds_grid_get(IndentValues,1,i-1)))/MaximumIndent)
    draw_set_color(merge_color(c_lime,c_red,Progress)) draw_circle(Rx,Ry,2,0) }
    draw_vertex_texture_color(Rx,Ry,xx/sprite_width,yy/sprite_height,Col,image_alpha)
    yy += sprite_height
    }
    draw_primitive_end()
    sprInd += 1
    Col = c_white
    }
    
    if(keyboard_check_pressed(ord("K"))) {
        Color = make_color_rgb(random(255),random(255),random(255))
    }
    if(keyboard_check_pressed(ord("R"))) {
        ds_grid_set_region(IndentValues,0,0,1,IndentVertexes-1,0)
    }
    Code:
    //Bullet Collision (this can be altered to work for any denting)
    
    var Colis = collision_line(x,y,x+lengthdir_x(Spd,Angle),y+lengthdir_y(Spd,Angle),oPlayerSolids,0,1)
    if(Colis != noone) {
        Destroy = 1
        if(Colis.object_index = oCar) {
            with(Colis) {
            var oth = other.id
            var mx = IndentVertexes;
            var xx = 0
            var yy = 0
            var Nearest = -1;
            var NearestDist = -1;
            for(var i=1;i<=mx;i+=1) {
            if(yy > sprite_height) { yy = 0 xx += sprite_width/(mx/2-1) }
            //Local top right corner coords + xx + yy
            var Ox = -sprite_width/2+xx-ds_grid_get(IndentValues,0,i-1)
            var Oy = -sprite_height/2+yy-ds_grid_get(IndentValues,1,i-1)
            //In World rotated coords
            var Rx = x + (Ox  * dcos(-image_angle)) - (Oy * dsin(-image_angle))
            var Ry = y + (Ox  * dsin(-image_angle)) + (Oy * dcos(-image_angle))
            var dis = point_distance(oth.x,oth.y,Rx,Ry)
            if(dis < NearestDist || NearestDist = -1) { NearestDist = dis Nearest = i }
            yy += sprite_height
            }
            var GetGrid0 = ds_grid_get(IndentValues,0,Nearest-1);
            var GetGrid1 = ds_grid_get(IndentValues,1,Nearest-1);
            var Dirx = -lengthdir_x(oth.Spd,oth.Angle)*0.05;
            var Diry = -lengthdir_y(oth.Spd,oth.Angle)*0.05;
            ds_grid_set(IndentValues,0,Nearest-1,clamp(GetGrid0+Dirx,MaximumIndent,-MaximumIndent))
            ds_grid_set(IndentValues,1,Nearest-1,clamp(GetGrid1+Diry,MaximumIndent,-MaximumIndent))
            }
        }
    }
    Cheers! :p
     
    nikoscot, Japster and obscene like this.
  5. Japster

    Japster Member

    Joined:
    Aug 5, 2017
    Posts:
    51
    This sounds very cool, will be interesting to see this in action, and thanks for sharing the solution!
     
    A Random Creator likes this.

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