# Thread: Trouble Understanding a bug in my collision detection system...

1. ## Trouble Understanding a bug in my collision detection system...

I'm working on a basic collision system for my HTML5 game. Unfortunately I'm running into a problem in the algorithm. This is what the collision system does:

- Detects if collision boxes are intersecting. If not, false. If true, a
"collision solver" function is fired. This is where my problem starts:

1. - Get the normalized sides
2. - Calculate the absolute change in X and Y
3. - But when it's time to place the player on either the right, left, top, or bottom sides of the collidee box, my character appears on one of the corners.

If I let the player hit either the left or right edge, the system works perfectly. The problem occurs when the player hits either the top or bottom edges.

What I think is happening

If I remove the if statements that check left and right edges, the top and bottom collision detetion works perfectly. Which leads me to believe that the issue is related to the order of execution in the algorithm. (If, else, if, else). In fact, if you look at the function code I'm providing, you'll notice left and right come first. What puzzles me is that even if I put the top and bottom if statements first, the same problem occurs.

Hopefully this all makes sense to somebody. Thanks in advance. Any questions, I'll check back on the thread.

Code:
```collisionsolver: function (collidee)
{
// Calculate Absolute change in X and Y
this.normalizedX = (collidee.colliderMidX - this.colliderMidX) / (collidee.width /2);
this.normalizedY = (collidee.colliderMidY - this.colliderMidY) / (collidee.height /2);

this.absNX = Math.abs(this.normalizedX) / (collidee.width/2);
this.absNY = Math.abs(this.normalizedY) / (collidee.height/2);
var test = (this.absNX - this.absNY);

if(Math.abs(test) < .1)
{
// Hit Right Side?
if(this.normalizedX < 0)
{
this.x = collidee.colliderRight;
console.log('right!');
}
// Left Side
else
{
this.x = collidee.colliderLeft - this.width;
console.log('left!');
}
if(this.normalizedY < 0)
{
this.y = collidee.colliderBottom;
console.log('bottom!');
}
else
{
console.log('top');
this.y = collidee.colliderTop - this.height;
}
}
},```

2. Banned
Join Date
May 2014
Posts
1,126
Your math for this just seems weird... also not sure why you're saving "normalize"... I'm not even sure how that would work out to actually provide box collisions.

From what I'm seeing for variables:

Code:
```var
xRange = (collidee.width + this.width) / 2,
yRange = (collidee.height + this.height) / 2,
xDistance = (collidee.colliderMixX - this.colliderMidX),
yDistance = (collidee.colliderMixY - this.colliderMidY);

if (abs(xDistance) < xRange) {
if (xDistance < 0) {
this.x = collidee.colliderLeft - this.width;
console.log('left!');
} else {
this.x = collidee.colliderRight;
console.log('right!');
}
}

if (abs(yDistance) < yRange) {
if (yDistance < 0) {
this.y = collidee.colliderTop - this.height;
console.log('top!');
} else {
this.y = collidee.colliderBottom;
console.log('bottom!');
}
}```
Should do what you are trying for. Of course, this misses that you should only REALLY have a collision if BOTH conditions are true.

Code:
```var
xRange = (collidee.width + this.width) / 2,
yRange = (collidee.height + this.height) / 2,
xDistance = (collidee.colliderMixX - this.colliderMidX),
yDistance = (collidee.colliderMixY - this.colliderMidY),
xCollide = abs(xDistance) < xRange,
yCollide = abs(yDistance) < yRange;

if (xCollide && yCollide) {
if (xCollide) {
if (xDistance < 0) {
this.x = collidee.colliderLeft - this.width;
console.log('left!');
} else {
this.x = collidee.colliderRight;
console.log('right!');
}
}
if (yCollide) {
if (yDistance < 0) {
this.y = collidee.colliderTop - this.height;
console.log('top!');
} else {
this.y = collidee.colliderBottom;
console.log('bottom!');
}
}
}```
Though really this whole mid-point nonsense is just making things harder than need be. Box collisons are simple, don't make them hard. Assuming you have .x, .y, .width and .height on all elements involved...

Code:
```var
// you can skip these four vars if you already have these calculated
thisEx = this.x + collidee.width,
thisEy = this.y + collidee.height,
colEx = collidee.x + collidee.width,
colEy = collidee.y + collidee.height,
xCollide = (
(this.x >= collidee.x) && (this.x <= colEx)
) ? -1 : (
(thisEx <= colEx) &&(thisEx >= collidee.x) ? 1 : 0
);
yCollide = (
(this.y >= collidee.y) && (this.y <= colEy)
) ? -1 : (
(thisEy <= colEy) &&(thisEy >= collidee.y) ? 1 : 0
);

if (xCollide && yCollide) {

if (xCollide < 0) {
this.x = collidee.colliderLeft - this.width;
console.log('left!');
} else if (xCollide > 0) {
this.x = collidee.colliderRight;
console.log('right!');
}

if (yCollide < 0) {
this.y = collidee.colliderTop - this.height;
console.log('top!');
} else if (yCollide > 0) {
this.y = collidee.colliderBottom;
console.log('bottom!');
}

}```
But that's likely the low level 8088 coder in me trying to avoid divide, multiply, and any other math. Of course if this were ASM, or a compiled language like Pascal or C, I'd be using !=0 instead of >0 on the second 'if' since at the low level it's easier to check for z instead of ns.

-- edit -- wait, are you trying to calculate internal or external collision here? If internal, that's called a 'bounding' check, not 'collision' (even if it IS a collision)
Last edited by deathshadow; 07-22-2014 at 08:32 PM.

3. Registered User
Join Date
Jul 2014
Posts
9
Your math for this just seems weird... also not sure why you're saving "normalize"... I'm not even sure how that would work out to actually provide box collisions.

From what I'm seeing for variables:

Code:
```var
xRange = (collidee.width + this.width) / 2,
yRange = (collidee.height + this.height) / 2,
xDistance = (collidee.colliderMixX - this.colliderMidX),
yDistance = (collidee.colliderMixY - this.colliderMidY);

if (abs(xDistance) < xRange) {
if (xDistance < 0) {
this.x = collidee.colliderLeft - this.width;
console.log('left!');
} else {
this.x = collidee.colliderRight;
console.log('right!');
}
}

if (abs(yDistance) < yRange) {
if (yDistance < 0) {
this.y = collidee.colliderTop - this.height;
console.log('top!');
} else {
this.y = collidee.colliderBottom;
console.log('bottom!');
}
}```
Should do what you are trying for. Of course, this misses that you should only REALLY have a collision if BOTH conditions are true.

Code:
```var
xRange = (collidee.width + this.width) / 2,
yRange = (collidee.height + this.height) / 2,
xDistance = (collidee.colliderMixX - this.colliderMidX),
yDistance = (collidee.colliderMixY - this.colliderMidY),
xCollide = abs(xDistance) < xRange,
yCollide = abs(yDistance) < yRange;

if (xCollide && yCollide) {
if (xCollide) {
if (xDistance < 0) {
this.x = collidee.colliderLeft - this.width;
console.log('left!');
} else {
this.x = collidee.colliderRight;
console.log('right!');
}
}
if (yCollide) {
if (yDistance < 0) {
this.y = collidee.colliderTop - this.height;
console.log('top!');
} else {
this.y = collidee.colliderBottom;
console.log('bottom!');
}
}
}```
Though really this whole mid-point nonsense is just making things harder than need be. Box collisons are simple, don't make them hard. Assuming you have .x, .y, .width and .height on all elements involved...

Code:
```var
// you can skip these four vars if you already have these calculated
thisEx = this.x + collidee.width,
thisEy = this.y + collidee.height,
colEx = collidee.x + collidee.width,
colEy = collidee.y + collidee.height,
xCollide = (
(this.x >= collidee.x) && (this.x <= colEx)
) ? -1 : (
(thisEx <= colEx) &&(thisEx >= collidee.x) ? 1 : 0
);
yCollide = (
(this.y >= collidee.y) && (this.y <= colEy)
) ? -1 : (
(thisEy <= colEy) &&(thisEy >= collidee.y) ? 1 : 0
);

if (xCollide && yCollide) {

if (xCollide < 0) {
this.x = collidee.colliderLeft - this.width;
console.log('left!');
} else if (xCollide > 0) {
this.x = collidee.colliderRight;
console.log('right!');
}

if (yCollide < 0) {
this.y = collidee.colliderTop - this.height;
console.log('top!');
} else if (yCollide > 0) {
this.y = collidee.colliderBottom;
console.log('bottom!');
}

}```
But that's likely the low level 8088 coder in me trying to avoid divide, multiply, and any other math. Of course if this were ASM, or a compiled language like Pascal or C, I'd be using !=0 instead of >0 on the second 'if' since at the low level it's easier to check for z instead of ns.

-- edit -- wait, are you trying to calculate internal or external collision here? If internal, that's called a 'bounding' check, not 'collision' (even if it IS a collision)
Thanks, I will try it.

There are currently 1 users browsing this thread. (0 members and 1 guests)

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•

"

"

## X vBulletin 4.2.2 Debug Information

• Page Generation 0.11916 seconds
• Memory Usage 2,876KB
• Queries Executed 13 (?)
Template Usage (34):
• (7)bbcode_code
• (1)bbcode_quote
• (1)footer
• (1)forumjump
• (1)forumrules
• (1)gobutton
• (3)memberaction_dropdown
• (1)navbar
• (1)navbar_moderation
• (1)navbar_noticebit
• (1)navbar_tabs
• (2)option
• (3)postbit
• (3)postbit_onlinestatus
• (3)postbit_wrapper
• (1)spacer_close
• (1)spacer_open
• (1)tagbit_wrapper

Phrase Groups Available (6):
• global
• inlinemod
• postbit
• posting
• reputationlevel
Included Files (26):
• ./global.php
• ./includes/class_bootstrap.php
• ./includes/init.php
• ./includes/class_core.php
• ./includes/config.php
• ./includes/functions.php
• ./includes/class_friendly_url.php
• ./includes/class_hook.php
• ./includes/class_bootstrap_framework.php
• ./vb/vb.php
• ./vb/phrase.php
• ./includes/functions_calendar.php
• ./includes/functions_bigthree.php
• ./includes/class_postbit.php
• ./includes/class_bbcode.php
• ./includes/functions_reputation.php
• ./includes/functions_notice.php
• ./packages/vbattach/attach.php
• ./vb/types.php
• ./vb/cache.php
• ./vb/cache/db.php
• ./vb/cache/observer/db.php
• ./vb/cache/observer.php

Hooks Called (70):
• init_startup
• friendlyurl_resolve_class
• init_startup_session_setup_start
• database_pre_fetch_array
• database_post_fetch_array
• init_startup_session_setup_complete
• global_bootstrap_init_start
• global_bootstrap_init_complete
• cache_permissions
• fetch_foruminfo
• global_state_check
• global_bootstrap_complete
• global_start
• style_fetch
• global_setup_complete
• strip_bbcode
• friendlyurl_clean_fragment
• friendlyurl_geturl
• forumjump
• cache_templates
• cache_templates_process
• template_register_var
• template_render_output
• fetch_template_start
• fetch_template_complete
• parse_templates
• notices_check_start
• notices_noticebit
• process_templates_complete
• friendlyurl_redirect_canonical
• bbcode_fetch_tags
• bbcode_create
• postbit_factory
• postbit_display_start
• postbit_imicons
• bbcode_parse_start
• bbcode_parse_complete_precache
• bbcode_parse_complete
• postbit_display_complete
• memberaction_dropdown
• tag_fetchbit_complete
• forumrules
• navbits
• navbits_complete