C
ContraMuffin
Guest
I don't know what type of issue this is, I can't even describe it properly. Some months ago I wrote a script that resolves the collisions of 2 objects. Over the next months I continued to work on my game, and the collision resolution script worked perfectly (except for a minor bug that I intend to fix later) every time I run the game. But just today I run the game and Game Maker throws me an error about an illegal variable use from that script. I have never had this problem, and I'm running the script from regular circumstances. I've tried to isolate the problem but all I could come up with is that the variables get deleted the moment they get set. I've tried closing and restarting Game Maker but the issue's still there. Since I have completely no idea what's going on, I'm willing to post any part of my code and any part of my project, including the entire project itself, if it helps me figure out what I'm doing wrong. Thanks in advance.
My collision script. The error gets thrown if 2 AABBs (rectangles) collide and if a circle collides with an AABB (2 different parts of the script), so I personally think it's something else that's interfering with this script. I used show_debug_message() and found out that radiusA, radiusB, contactA, contactB, norm, and normal (all of them are arrays to denote the x and y variables) were { {0, 0} } when I checked immediately after I set them.
My collision script. The error gets thrown if 2 AABBs (rectangles) collide and if a circle collides with an AABB (2 different parts of the script), so I personally think it's something else that's interfering with this script. I used show_debug_message() and found out that radiusA, radiusB, contactA, contactB, norm, and normal (all of them are arrays to denote the x and y variables) were { {0, 0} } when I checked immediately after I set them.
Code:
//resolves collisions
//collision(object, object);
if(argument0.index == argument1.index){
if(argument0.index == "AABB"){ //both are AABBs
if(argument0.inv_mass == 0 && argument1.inv_mass == 0){
exit;
}
collision_angle = abs(argument0.image_angle - argument1.image_angle) mod 90;
minimum_angle = min(collision_angle, 90 - collision_angle);
if(minimum_angle < 0.2){
objA = argument0;
objB = argument1;
if(objB.inv_mass == 0){
objA = argument1;
objB = argument0;
}
n[1] = -(objB.y - objA.y);
n[0] = objB.x - objA.x;
B_x = rotate_vector(n, -(degtorad(objA.image_angle)), 0);
B_y = rotate_vector(n, -(degtorad(objA.image_angle)), 1);
pen_x = (objA.sprite_width / 2) + (objB.sprite_width / 2) - abs(B_x);
pen_y = (objA.sprite_height / 2) + (objB.sprite_height / 2) - abs(B_y);
if(pen_y < pen_x){
pen = pen_y;
norm[1] = sign(B_y);
norm[0] = 0;
contact_vecA[1] = sign(B_y) * (objA.sprite_height / 2);
contact_vecA[0] = sign(B_x) * max(0, abs(B_x) - (objB.sprite_width / 2));
contact_vecB[1] = sign(B_y) * -(objB.sprite_height / 2);
contact_vecB[0] = sign(B_x) * -(max(0, abs(B_x) - (objA.sprite_width / 2)));
}
else{
pen = pen_x;
norm[1] = 0;
norm[0] = sign(B_x);
contact_vecA[1] = sign(B_y) * max(0, abs(B_y) - (objB.sprite_height / 2));
contact_vecA[0] = sign(B_x) * (objA.sprite_width / 2);
contact_vecB[1] = sign(B_y) * -(max(0, abs(B_y) - (objA.sprite_height / 2)));
contact_vecB[0] = sign(B_x) * -(objB.sprite_width / 2);
}
}
else{
//rotate into argument0
n[1] = -(argument1.y - argument0.y);
n[0] = argument1.x - argument0.x;
R1_x = rotate_vector(n, -(degtorad(argument0.image_angle)), 0);
R1_y = rotate_vector(n, -(degtorad(argument0.image_angle)), 1);
R1_rot = degtorad(argument1.image_angle - argument0.image_angle);
corner_count1 = 0;
pen1 = -1;
for(i = 0; i < 4; i++){
corner_x = R1_x + (cos(argument1.angle[i] + R1_rot) * argument1.distance);
corner_y = R1_y + (sin(argument1.angle[i] + R1_rot) * argument1.distance);
if(abs(corner_x) <= argument0.sprite_width / 2 && abs(corner_y) <= argument0.sprite_height / 2){
corner_count1++;
intersection = ((sign(R1_y) * (argument0.sprite_height / 2) - R1_y) * ((R1_x - corner_x) / (R1_y - corner_y))) + R1_x;
if(abs(intersection) > (argument0.sprite_width / 2)){
preside = 0;
prepen = (argument0.sprite_width / 2) - abs(corner_x);
}
else{
preside = 1;
prepen = (argument0.sprite_height / 2) - abs(corner_y);
}
if(prepen > pen1){
pen1 = prepen;
side1 = preside;
c1[1] = corner_y;
c1[0] = corner_x;
}
}
}
//rotate into argument1
n[1] = -(argument0.y - argument1.y);
n[0] = argument0.x - argument1.x;
R0_x = rotate_vector(n, -(degtorad(argument1.image_angle)), 0);
R0_y = rotate_vector(n, -(degtorad(argument1.image_angle)), 1);
R0_rot = degtorad(argument0.image_angle - argument1.image_angle);
corner_count0 = 0;
pen0 = -1;
for(i = 0; i < 4; i++){
corner_x = R0_x + (cos(argument0.angle[i] + R0_rot) * argument0.distance);
corner_y = R0_y + (sin(argument0.angle[i] + R0_rot) * argument0.distance);
if(abs(corner_x) <= argument1.sprite_width / 2 && abs(corner_y) <= argument1.sprite_height / 2){
corner_count0++;
intersection = ((sign(R0_y) * (argument1.sprite_height / 2) - R0_y) * ((R0_x - corner_x) / (R0_y - corner_y))) + R0_x;
if(abs(intersection) > (argument1.sprite_width / 2)){
preside = 0;
prepen = (argument1.sprite_width / 2) - abs(corner_x);
}
else{
preside = 1;
prepen = (argument1.sprite_height / 2) - abs(corner_y);
}
if(prepen > pen0){
pen0 = prepen;
side0 = preside;
c0[1] = corner_y;
c0[0] = corner_x;
}
}
}
if(sign(pen0) == -1){
if(sign(pen1) == -1){
exit;
}
else{
selection = 1;
}
}
else{
if(sign(pen1) == -1){
selection = 2;
}
else{
if(pen0 < pen1){
selection = 1;
}
else{
selection = 2;
}
}
}
if(selection == 1){
objA = argument0;
objB = argument1;
pen = pen1;
side = side1;
B_x = R1_x;
B_y = R1_y;
B_rot = R1_rot;
c[1] = c1[1];
c[0] = c1[0];
}
else{
objA = argument1;
objB = argument0;
pen = pen0;
side = side0;
B_x = R0_x;
B_y = R0_y;
B_rot = R0_rot;
c[1] = c0[1];
c[0] = c0[0];
}
if(side = 0){
norm[1] = 0;
norm[0] = sign(B_x);
contact_vecA[1] = c[1];
contact_vecA[0] = sign(B_x) * (objA.sprite_width / 2);
contact_vecB[1] = c[1] - B_y;
contact_vecB[0] = c[0] - B_x;
}
else{
norm[1] = sign(B_y);
norm[0] = 0;
contact_vecA[1] = sign(B_y) * (objA.sprite_height / 2);
contact_vecA[0] = c[0];
contact_vecB[1] = c[1] - B_y;
contact_vecB[0] = c[0] - B_x;
}
}
penetration = pen;
normal[1] = rotate_vector(norm, degtorad(objA.image_angle), 1);
normal[0] = rotate_vector(norm, degtorad(objA.image_angle), 0);
contactA[1] = rotate_vector(contact_vecA, degtorad(objA.image_angle), 1);
contactA[0] = rotate_vector(contact_vecA, degtorad(objA.image_angle), 0);
contactB[1] = rotate_vector(contact_vecB, degtorad(objA.image_angle), 1);
contactB[0] = rotate_vector(contact_vecB, degtorad(objA.image_angle), 0);
show_debug_message("yes");
show_debug_message(norm);
show_debug_message(normal);
show_debug_message(contactA);
show_debug_message(contactB);
}
else{ //both are circles
objA = argument0;
objB = argument1;
n[1] = -(objB.y - objA.y);
n[0] = objB.x - objA.x;
distance = pythag(n);
penetration = objA.radius + objB.radius - distance;
normal[1] = n[1] / distance;
normal[0] = n[0] / distance;
contactA[1] = sin(vectoangle(n)) * objA.radius;
contactA[0] = cos(vectoangle(n)) * objA.radius;
contactB[1] = -sin(vectoangle(n)) * objB.radius;
contactB[0] = -cos(vectoangle(n)) * objB.radius;
}
}
else{ //AABB and circle
objA = argument0;
objB = argument1;
if(objB.index == "AABB"){
objA = argument1;
objB = argument0;
}
n[1] = -(objB.y - objA.y);
n[0] = objB.x - objA.x;
B_x = rotate_vector(n, -(degtorad(objA.image_angle)), 0);
B_y = rotate_vector(n, -(degtorad(objA.image_angle)), 1);
if(abs(B_x) > objA.sprite_width / 2){
if(abs(B_y) > objA.sprite_height / 2){ //corner
contact_vecA[1] = sign(B_y) * (objA.sprite_height / 2);
contact_vecA[0] = sign(B_x) * (objA.sprite_width / 2);
contact_vecB[1] = sign(B_y) * ((objA.sprite_height / 2) - abs(B_y));
contact_vecB[0] = sign(B_x) * ((objA.sprite_width / 2) - abs(B_x));
distance = pythag(contact_vecB);
}
else{ //horizontal
contact_vecA[1] = B_y;
contact_vecA[0] = sign(B_x) * (objA.sprite_width / 2);
contact_vecB[1] = 0;
contact_vecB[0] = sign(B_x) * ((objA.sprite_width / 2) - abs(B_x));
distance = abs(contact_vecB[0]);
}
}
else{
if(abs(B_y) > objA.sprite_height / 2){ //vertical
contact_vecA[1] = sign(B_y) * (objA.sprite_height / 2);
contact_vecA[0] = B_x;
contact_vecB[1] = sign(B_y) * ((objA.sprite_height / 2) - abs(B_y));
contact_vecB[0] = 0;
distance = abs(contact_vecB[1]);
}
else{ //inside
if((objA.sprite_height / 2) - abs(B_y) < (objA.sprite_width / 2) - abs(B_x)){ //vertical
contact_vecA[1] = sign(B_y) * (objA.sprite_height / 2);
contact_vecA[0] = B_x;
contact_vecB[1] = sign(B_y) * -((objA.sprite_height / 2) - abs(B_y));
contact_vecB[0] = 0;
}
else{
contact_vecA[1] = B_y;
contact_vecA[0] = sign(B_x) * (objA.sprite_width / 2);
contact_vecB[1] = 0;
contact_vecB[0] = sign(B_x) * -((objA.sprite_width / 2) - abs(B_x));
}
distance = -(max(contact_vecB[0], contact_vecB[1]));
}
}
penetration = objB.radius - distance;
contactA[1] = rotate_vector(contact_vecA, degtorad(objA.image_angle), 1);
contactA[0] = rotate_vector(contact_vecA, degtorad(objA.image_angle), 0);
contactB[1] = sin(vectoangle(contact_vecB) + degtorad(objA.image_angle)) * objB.radius;
contactB[0] = cos(vectoangle(contact_vecB) + degtorad(objA.image_angle)) * objB.radius;
normal[1] = -(objB.y - (objA.y - contactA[1])) / distance;
normal[0] = (objB.x - (objA.x + contactA[0])) / distance;
}
//perpendicular radius
radiusA[1] = contactA[0];
radiusA[0] = -(contactA[1]);
radiusB[1] = contactB[0];
radiusB[0] = -(contactB[1]);
//relative linear velocity
rel_vel[1] = objB.velocity[1] - objA.velocity[1];
rel_vel[0] = objB.velocity[0] - objA.velocity[0];
//combined relative velocity
vel[1] = (objB.velocity[1] + (objB.rot_vel * radiusB[1])) - (objA.velocity[1] + (objA.rot_vel * radiusA[1]));
vel[0] = (objB.velocity[0] + (objB.rot_vel * radiusB[0])) - (objA.velocity[0] + (objA.rot_vel * radiusA[0]));
//calculate relative velocity in terms of collision normal
vel_norm = dot(vel, normal);
lin_vel_norm = dot(rel_vel, normal);
/*
//velocities separating
if(vel_norm < 0 && lin_vel_norm > 0){
show_debug_message("yes");
//exit;
}
*/
//calculate restitution
e = min(objA.e, objB.e);
show_debug_message(object_get_name(objA.object_index));
show_debug_message(object_get_name(objB.object_index));
show_debug_message(radiusA);
show_debug_message(radiusB);
show_debug_message(normal);
//calculate impulse scalar
j = -(1 + e) * vel_norm;
j /= (objA.inv_mass + objB.inv_mass) + (sqr(dot(radiusA, normal)) * objA.inv_inertia) + (sqr(dot(radiusB, normal)) * objB.inv_inertia);
//adjusted j
adj_j = j + (0.1 * penetration);
//apply impulse
impulse[1] = adj_j * normal[1];
impulse[0] = adj_j * normal[0];
objA.velocity[0] -= objA.inv_mass * impulse[0];
objA.velocity[1] -= objA.inv_mass * impulse[1];
objA.rot_vel -= objA.inv_inertia * dot(radiusA, impulse);
objB.velocity[0] += objB.inv_mass * impulse[0];
objB.velocity[1] += objB.inv_mass * impulse[1];
objB.rot_vel += objB.inv_inertia * dot(radiusB, impulse);
show_debug_message("vel" + string(vel));
//friction
tangent[1] = vel[1] - (dot(vel, normal) * normal[1]);
tangent[0] = vel[0] - (dot(vel, normal) * normal[0]);
t[1] = normal[0];
t[0] = -(normal[1]);
show_debug_message("tangent" + string(tangent));
//tangent_length = pythag(tangent);
/*
show_debug_message(tangent);
t[1] = 0;
t[0] = 0;
if(tangent_length != 0){
t[1] = tangent[1] / tangent_length;
t[0] = tangent[0] / tangent_length;
}
*/
show_debug_message("t" + string(t));
//calculate friction magnitude
jt = -dot(tangent, t);
show_debug_message(dot(radiusA, t));
jt /= (objA.inv_mass + objB.inv_mass) + (sqr(dot(contactA, t)) * objA.inv_inertia) + (sqr(dot(radiusB, t)) * objB.inv_inertia);
show_debug_message("jt" + string(jt));
show_debug_message("j" + string(j));
//calculate impulse of friction
mu = (objA.stat_fric + objB.stat_fric) / 2;
if(abs(jt) <= j * mu){
fric_impulse[1] = jt * t[1];
fric_impulse[0] = jt * t[0];
show_debug_message("stat");
}
else{
mu = (objA.dyn_fric + objB.dyn_fric) / 2;
fric_impulse[1] = -j * mu * t[1];
fric_impulse[0] = -j * mu * t[0];
show_debug_message("dyn");
}
//apply impulse of friction
objA.velocity[0] -= objA.inv_mass * fric_impulse[0];
objA.velocity[1] -= objA.inv_mass * fric_impulse[1];
objA.rot_vel -= objA.inv_inertia * dot(radiusA, fric_impulse);
objB.velocity[0] += objB.inv_mass * fric_impulse[0];
objB.velocity[1] += objB.inv_mass * fric_impulse[1];
objB.rot_vel += objB.inv_inertia * dot(radiusB, fric_impulse);
//positional correction
//0.05 is slop, 0.2 is percent
correction[1] = (penetration - 0.05) / (objA.inv_mass + objB.inv_mass) * 0.6 * normal[1];
correction[0] = (penetration - 0.05) / (objA.inv_mass + objB.inv_mass) * 0.6 * normal[0];
objA.x -= objA.inv_mass * correction[0];
objA.y += objA.inv_mass * correction[1];
objB.x += objB.inv_mass * correction[0];
objB.y -= objB.inv_mass * correction[1];