1. Hey! Guest! The 36th GMC Jam will take place between February 27th, 12:00 UTC - March 2nd, 12:00 UTC. Why not join in! Click here to find out more!
    Dismiss Notice

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,511
    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:
    89
    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