Impact

This forum is read only and just serves as an archive. If you have any questions, please post them on github.com/phoboslab/impact

10 years ago by LazerFriends

I have a crate entities in my platformer game, and they are stackable. Is there a way for crate on the bottom of a stack to detect if there is a crate on top of it?

(In the game I would like the player to be unable to pick up a crate if there is another one on top of it.)

Link to the game: http://bsmallbeck.com/impact/

Thanks!

10 years ago by Joncom

In the crate update call, why not loop through all other crates, and check if their position is roughly the same on the x-axis and roughly one-crate-high upward on the y-axis?

10 years ago by Spiderhund

I know this is a somewhat old thread but I'll post this for you anyways.

You don't have to check if the X axis is "roughly" the same, you can calulate if one crate is above another if you have a width and a height assigned to the crate entities.

The way you should go about this is firstly have a property on the crates called "canPickup" or something, this will be a boolean obviously. Now in the update() function you want to loop through all other crates (get an array of all of them by using getEntitiesByType()).

Pro-tip: Looping through an array backwards is faster than looping forwards in Javascript. This is done like so "for(var i = crates.length;i--;)".

Now for every crate you have to do alittle bit of math to figure out if it's "on top" (Don't worry, it's not bad at all). We will do this one axis at a time and we will start with the X axis.

Simply take the X axis of your current crate (the one where the update() function is currently executing) and the X axis of the "other" crate (the one selected in the loop) and subtract them. Make sure the number you get is not negative and then compare it to the width of the crates. If the number is smaller than the width it means the crate is "on top" on the X axis. The formula / code for this looks like this:
var diffX = Math.abs(this.pos.x - other.pos.x);
if(diffX < this.width){
    //On top on the X axis.
}

The Math.abs() function makes sure the number is not negative.

Now lets handle the Y axis, this one is even easier.
We simply check if the Y axis + the height of the crate of the "other" crate is smaller than the Y axis of "this" crate. Like so:
if((other.pos.y + other.height) < this.pos.y){
    //On top on the Y axis.
}

That's it. Now based on this we will set our "canPickup" property to either true or false. I've included a full example of the update() function below.

var otherCrates = ig.game.getEntitiesByType(EntCrate);
for(var i = otherCrates.length;i--;){
    //Skip this iteration if the crate from the array is "this" crate.
    if(otherCrates[i] === this)
        continue;

    var diffX = Math.abs(this.pos.x - otherCrates[i].pos.x);

    //Notice the exclamation mark here, it means if the two statements are true, false will be returned and if the two statements are false, true will be returned.
    this.canPickup = !(diffX < this.width && (otherCrates[i].pos.y + otherCrates[i].height) < this.pos.y);

    //Terminate the loop if we have already determined that a crate is on top.
    if(this.canPickup)
        break;
}

I hope this helps you out in case you didn't fix the problem already.

10 years ago by Joncom

You don't have to check if the X axis is "roughly" the same, you can calulate if one crate is above another if you have a width and a height assigned to the crate entities.
You just said that checking if X is roughly the same is not necessary, and then proceeded to provide code that does exactly that.

diffX < this.width is checking if the X axis position is within this.width distance. In other words "is close enough" or "roughly the same".

Pro-tip: Looping through an array backwards is faster than looping forwards in Javascript. This is done like so "for(var i = crates.length;i--;)".
Looping through something backwards is generally poor advice, unless you have a good reason for doing so. Performance, generally speaking, is a poor reason. This is JavaScript. Emphasis here has never been speed. Code should be easy to read and understand. And even then, it's usually plenty fast enough.

I wouldn't recommend following odd practices for the sole purpose of saving a few milliseconds that likely don't matter. If your application has performance issues, you probably have bigger issues than "looping in the wrong direction" anyway.

10 years ago by Spiderhund

You just said that checking if X is roughly the same is not necessary, and then proceeded to provide code that does exactly that.

Right, when I read your advice about checking if it's roughly the same I understood it as "Check if this x is equal to other x plus / minus some margin". Whatever the case I never meant anything by the statement I made above, just wanted to help out.

Looping through something backwards is generally poor advice, unless you have a good reason for doing so.

My reason for doing so is speed. If I have a particle system spawning hundreds of particles I'm glad to save a few milliseconds here and there so I'll be using every performance trick I can. It's kinda the same in this situration, each crate is looping through every other crate (Including itself although that iteration is skipped and thus doesn't make as big of an impact). I don't know how many crates he's going to use but if he has 20 in a level that's 400 iterations per frame, even when a crate is below another crate it still keeps checking.
In my personal opinion looping backwards doesn't make the code any less readable (I find it easy to identify if a loop is going backwards or if it's going forwards). The only place I wouldn't loop backwards is in my draw() call.

Anyways I don't mean to start an argument or anything, just providing you with my reasoning for giving such advice. I also realize I could have come across as being arrogant in my previous post, that was not my intention.
Page 1 of 1
« first « previous next › last »