Simon Gust
Member
I’ve been wanting to create a collision system for objects moving on a grid that works the same like CardinalCoder’s object based collision.
Turns out to be extremely complicated to get this to work.
The reason is probably the addition of several quality-of-life aspects.
- sub-pixel perfection
- no overshooting
- support for every rectangular bounding box size.
As of now, I have a solution allthough the sub-pixel perfection isn’t working by default
because the bbox_ variables are integers.
This prototype is not tested very much and it isn’t very optimized.
I am searching for ideas and improvements.
I still need to find an alternative to the bbox variables.
CardinalCoder's method looks inviting, will look into that.
Before you ask questions:
Yes, I’ve seen Ariak’s grid collisions, I just find it hard to implement and manage.
And coding collisions myself gives a far greater feeling of accomplishment.
Here is a basic implementation so you don’t have to code it yourself
CREATE
STEP
And here is the collision code (no scripts)
A draw event is required too
The sprites you would have to make yourself.
I used a grid cell size of 16 x 16
My sprite was something like 28 x 44.
Shoutouts to
@CardinalCoder64 and @Ariak
Turns out to be extremely complicated to get this to work.
The reason is probably the addition of several quality-of-life aspects.
- sub-pixel perfection
- no overshooting
- support for every rectangular bounding box size.
As of now, I have a solution allthough the sub-pixel perfection isn’t working by default
because the bbox_ variables are integers.
This prototype is not tested very much and it isn’t very optimized.
I am searching for ideas and improvements.
I still need to find an alternative to the bbox variables.
CardinalCoder's method looks inviting, will look into that.
Before you ask questions:
Yes, I’ve seen Ariak’s grid collisions, I just find it hard to implement and manage.
And coding collisions myself gives a far greater feeling of accomplishment.
Here is a basic implementation so you don’t have to code it yourself
CREATE
Code:
x = 64;
y = 64;
hspd = 0;
vspd = 0;
wdt = 32;
hgt = 32;
grid = 0;
for (var i = wdt-1; i >= 0; i--) {
for (var j = hgt-1; j >= 0; j--) {
grid[i, j] = 1;
}}
for (var i = 1; i < wdt-1; i++) {
for (var j = 1; j < hgt-1; j++) {
if (random(5)) grid[i, j] = 0;
}}
for (var i = 1; i < 10; i++) {
for (var j = 1; j < 10; j++) {
grid[i, j] = 0;
}}
enum cell {size = 16}
Code:
var spd = 6.00; // normal speed
if (keyboard_check(vk_shift))
{
spd = 25.00; // overshoot speed
}
else
if (keyboard_check(vk_control))
{
spd = 3.48723; // sub-pixel speed
}
hspd = spd * (keyboard_check(ord("D")) - keyboard_check(ord("A")));
vspd = spd * (keyboard_check(ord("S")) - keyboard_check(ord("W")));
Code:
/// collision
/// scr_grid_collision(x+hspd, y+vspd) // potential script
// save fraction of position for later
var xfrac = frac(x);
var yfrac = frac(y);
// floor position
x = floor(x + 0.0001);
y = floor(y + 0.0001);
// save potential new position
var x_new = x + hspd; //argument0; // potential argument
var y_new = y + vspd; //argument1; // potential argument
// remember speed
var xspd = hspd;
var yspd = vspd;
// set bounding boxes
var lft = bbox_left;
var top = bbox_top;
var rgt = bbox_right;
var bot = bbox_bottom;
var flag = true;
// start looping down the height of the player
var y1 = top;
var y2 = bot + cell.size;
for (var j = y1; j <= y2; j += cell.size)
{
// define deadzone
var yy = min(j, bot);
var grid_y = yy div cell.size;
// horizontal collision
if (xspd < 0) // left
{
// start looping down the path of the player
var x1 = lft + xspd;
var x2 = lft;
for (var xx = x1; xx <= x2; xx += cell.size)
{
// define deadzone
var grid_x = xx div cell.size;
// check for collision
var tile = (grid[grid_x, grid_y]);
if (tile == 1)
{
// set new potential position
x_new = max(x_new, (grid_x * cell.size) + (x - lft) + cell.size);
hspd = 0;
flag = false;
}
}
}
else
if (xspd > 0) // right
{
// start looping down the path of the player
var x1 = rgt;
var x2 = rgt + xspd + 1;
for (var xx = x2; xx >= x1; xx -= cell.size)
{
// define deadzone
var grid_x = xx div cell.size;
// check for collision
var tile = (grid[grid_x, grid_y]);
if (tile == 1)
{
// set new potential position
x_new = min(x_new, (grid_x * cell.size) + (x - rgt) - 1);
hspd = 0;
flag = false;
}
}
}
}
// move player
x = x_new;
if (flag)
x += xfrac;
// update bounding boxes
var lft = bbox_left;
var top = bbox_top;
var rgt = bbox_right;
var bot = bbox_bottom;
var flag = true;
// start looping down the width of the player
var x1 = lft;
var x2 = rgt + cell.size;
for (var i = x1; i <= x2; i += cell.size)
{
// define deadzone
var xx = min(i, rgt);
var grid_x = xx div cell.size;
// vertical collision
if (yspd < 0) // up
{
// start looping down the path of the player
var y1 = top + yspd;
var y2 = top;
for (var yy = y1; yy < y2; yy += cell.size)
{
// define deadzone
var grid_y = yy div cell.size;
// check for collision
var tile = (grid[grid_x, grid_y]);
if (tile == 1)
{
// set new potential position
y_new = max(y_new, (grid_y * cell.size) + (y - top) + cell.size);
vspd = 0;
flag = false;
}
}
}
else
if (yspd > 0) // down
{
// start looping down the path of the player
var y1 = bot;
var y2 = bot + yspd + 1;
for (var yy = y2; yy >= y1; yy -= cell.size)
{
// define deadzone
var grid_y = yy div cell.size;
// check for collision
var tile = (grid[grid_x, grid_y]);
if (tile == 1)
{
// set new potential position
y_new = min(y_new, (grid_y * cell.size) + (y - bot) - 1);
vspd = 0;
flag = false;
}
}
}
}
// move player
y = y_new;
if (flag)
y += yfrac;
A draw event is required too
Code:
// draw player
draw_self();
// draw grid
for (var i = 0; i < wdt; i++) {
var xx = i * cell.size;
for (var j = 0; j < hgt; j++) {
var yy = j * cell.size;
if (grid[i, j] == 1) {
draw_sprite(spr_grid, 0, xx, yy);
}
}}
I used a grid cell size of 16 x 16
My sprite was something like 28 x 44.
Shoutouts to
@CardinalCoder64 and @Ariak
Last edited: