GMS 2 Putting dents in a vehicle sprite

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

Tags:
1. A Random CreatorMember

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. obsceneMember

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 CreatorMember

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 CreatorMember

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! nikoscot, Japster and obscene like this.
5. JapsterMember

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.