Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411412 Posts in 69360 Topics- by 58415 Members - Latest Member: sophi_26

April 15, 2024, 11:23:09 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Platforming Collisions
Pages: [1]
Print
Author Topic: Platforming Collisions  (Read 1397 times)
YetiSeekingYeti
Level 0
**



View Profile
« on: April 11, 2014, 03:08:01 AM »

Alright, I've been struggling with this for at least a week, time to swallow my pride and ask for help from you clever, clever forum people  Shrug

I'm trying to make a platform game in Game Maker Studio, and I don't want to use any of the built-in things (behaviours, drag-and-drop commands, solid flags, etc.) as things are going to get a lot more complicated than they allow.

For now though, I can't even get my collision detection to work.

It seems like the player object gets stuck less-than-a-pixel into walls and floors sometimes. Not all the time, only sometimes, and I really can't tell what causes it, I've changed and re-written this code a bunch of times to try to avoid this, but to no avail.

I've attached my collision detection script, which is called during the end-step of any movable objects (just the player object for now).

The only variables changed by any other code I've written are the player's velX and velY values.

Any help would be seriously appreciated, I'm just banging my head on the keys at this point.

I've also uploaded the source code, if anybody wants to run the thing (and has GM Studio).

Edit: Haha, ugh, just noticed the horrible spelling in my comments. Take it as a symptom of my frustration.

Code:

/*
* THIS IS GOING TO BE COMPLICATED
* use my own x/y/bounds etc values
* read velX and velY from the movable object
*/


//only change velX and velY in the movement scripts, the rest is handeled here.

//get the working bounds
workingLeft = workingX - colWidth/2;
workingRight = workingX + colWidth/2
workingTop = workingY - colHeight/2;
workingBottom = workingY + colHeight/2;

//don't let the player move into walls
if(wallRight && velX > 0){
    velX = 0;
}
else if(wallLeft && velX < 0){
    velX = 0;
}
if(wallBelow && velY > 0){
    velY = 0;
}
else if(wallAbove && velY < 0){
    velY = 0;
}

//if the player is moving at all (make this more efficent later)
if(velX != 0 || velY != 0){
    //collisions need to be checked along the diagonal line of movement
    
    //SO: get the movement as mag and norms
    mag = sqrt(sqr(velX)+sqr(velY));
    normX = velX/mag;
    normY = velY/mag;
    
    //NOTE: solid objects only have PER PIXEL AABB ACCURACY to their collisions.
    
    //check ahead to find if the obstacle is in our path
    maxMag = mag;
    maxX = velX;
    maxY = velY;
    
    //note: don't check at current position (i=0),
    //don't want none of that moving slowly backwards through walls crap
    collided = false;
    
    for(i = 1; i < mag; i++){
        if(collision_rectangle(workingLeft+normX*i, workingTop+normY*i, workingRight+normX*i, workingBottom+normY*i,
            ob_parent_Solid, true, true)){
            //at this value of i, the obstacle IS HIT
            collided = true;
            //therefor, take i-1 dists as MAX NATURAL MOVEMENT DISTANCES
            maxX = normX*(i-1);
            maxY = normY*(i-1);
            break;
        }
    }
    
    //we might not have to worry about collisions at all
    if(!collided){
        //just move by velX & velY
        workingX += velX;
        workingY += velY;
    }
    
    //but if we DO have to worry about collisions
    if(collided){
        //I know that I can DEFINITELY move the ob by maxX & maxY
        //but after that movement, at least 1 of the axes will be within a pixel of a collision
        
        //so: round these distances UP and then move
        if(velX > 0){
            workingX += ceil(maxX);
        }
        else if(velX < 0){
            workingX += floor(maxX);
        }
        if(velY > 0){
            workingY += ceil(maxY);
        }
        else if(velY < 0){
            workingY += floor(maxY);
        }
        
        //now I should be RIGHT AT the collision. Perfect.
        //just leave things at this for now
     }
    
}

//recheck the walls around the player
if(collision_line(workingLeft-1, workingTop, workingLeft-1, workingBottom, ob_parent_Solid, true, true)){
    wallLeft = true
}
else{
    wallLeft = false;
}
if(collision_line(workingRight+1, workingTop, workingRight+1, workingBottom, ob_parent_Solid, true, true)){
    wallRight = true
}
else{
    wallRight = false;
}
if(collision_line(workingLeft, workingTop-1, workingRight, workingTop-1, ob_parent_Solid, true, true)){
    wallAbove = true
}
else{
    wallAbove = false;
}
if(collision_line(workingLeft, workingBottom+1, workingRight, workingBottom+1, ob_parent_Solid, true, true)){
    wallBelow = true
}
else{
    wallBelow = false;
}

//finally match x&y to working x&y
x = round(workingX);
y = round(workingY);

Logged
jgrams
Level 3
***



View Profile
« Reply #1 on: April 11, 2014, 09:34:07 AM »

It seems like the player object gets stuck less-than-a-pixel into walls and floors sometimes.

My first guess would be that it's because you're rounding up in the `if(collided)` section. Have you tried it without that?

Overall it strikes me as an odd way to do things: looping along the current direction in increments of one-pixel lengths (which doesn't necessarily move it by a whole pixel in either axis), and then rounding not that length, but the actual pixel amounts which you're moving it by...

--Josh
Logged
YetiSeekingYeti
Level 0
**



View Profile
« Reply #2 on: April 11, 2014, 12:05:46 PM »

It seems like the player object gets stuck less-than-a-pixel into walls and floors sometimes.

My first guess would be that it's because you're rounding up in the `if(collided)` section. Have you tried it without that?

Overall it strikes me as an odd way to do things: looping along the current direction in increments of one-pixel lengths (which doesn't necessarily move it by a whole pixel in either axis), and then rounding not that length, but the actual pixel amounts which you're moving it by...

--Josh

Thanks Josh. It definitely seems a lot harder than it should be, so you're probably right. I don't know how I can have less-than-a-pixel-per-tick speed differences without all this faffing around, though.

I've tried removing the rounding in that bit, and rounding it different ways in a bunch of previous attempts, no luck.

I'm going to look around online to see if I can find any helpful writings on the topic, I'll hopefully have made at least some headway by tomorrow. Hopefully.
Logged
ink.inc
Guest
« Reply #3 on: April 11, 2014, 12:33:36 PM »

take a look at the grandma engine

http://forums.tigsource.com/index.php?topic=5790.0
Logged
jgrams
Level 3
***



View Profile
« Reply #4 on: April 11, 2014, 01:47:05 PM »


Hey, that looks nice! Though apparently not ported to Studio...?


I've tried removing the rounding in that bit, and rounding it different ways in a bunch of previous attempts, no luck.

OK, I went and downloaded the trial of GM Studio, and... if I drop all the `if(!collided)` and `if(collided)` fiddling and just do

Code:
workingX += maxX;
workingY += maxY;

it seems to work fine for me. Am I missing something?
Logged
YetiSeekingYeti
Level 0
**



View Profile
« Reply #5 on: April 11, 2014, 08:17:30 PM »


OK, I went and downloaded the trial of GM Studio, and... if I drop all the `if(!collided)` and `if(collided)` fiddling and just do

Code:
workingX += maxX;
workingY += maxY;

it seems to work fine for me. Am I missing something?

I'm screaming at my own ineptitude right now - that really does fix the clipping problems. I've clearly been staring at this one script for way too long. Thanks for going through the effort of getting the trial and everything! I still need to edit the player's speed after a collision and things, but Tears of Joy

@John Sandoval That engine feels really really nice. I might ask the creator if I can port it to Studio and use it myself, thanks for pointing it out.
Logged
YetiSeekingYeti
Level 0
**



View Profile
« Reply #6 on: April 13, 2014, 12:46:16 PM »

Just wanted to jump on and say I finally-bloody-finally got this working.

I'll post the code in a few days, once it's less horribly messy and not stained with bitter tears of frustration, for anyone lurking around dealing with the same problem.

Thanks for the replies and all that Gentleman

EDIT: My computer kind of completely died the day after I got this solved (seriously!) and I won't be able to keep working on the game for a week or two. If anyone really wants to see how I got collisions working, and doesn't mind waiting, let me know. Assuming nobody particularly cares, I'm just going to let this thread die.
« Last Edit: April 17, 2014, 05:42:19 AM by YetiSeekingYeti » Logged
One-bit Punch
Level 0
***



View Profile WWW
« Reply #7 on: April 20, 2014, 05:14:28 PM »

For those who are curious about using Grandma Engine with Studio check out this link http://gmc.yoyogames.com/index.php?showtopic=556430. Might need slight tweaking for each game's purpose, but I did try it long ago and it works. Its mainly replacing the original execute_string function to find rooms with a custom loop.

Just wanted to jump on and say I finally-bloody-finally got this working.

Congrats!!  Beer!
Logged

mokesmoe
Level 10
*****



View Profile WWW
« Reply #8 on: April 20, 2014, 07:45:45 PM »

The room switching isn't an integral part of the engine and is easily removed.
Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic