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

1 decade ago by saloon12yrd

Hi all,

I got my earlier issue with connecting doors to a switch sorted out. Now I have a more fundamental issue and no idea whatsoever how to resolve it.

It boils down to the question whether or not it is possible to configure entities such that they can slide over tiles on the collisionMap but still be walkable by other entities and the player?

Background info:
I want my doors to slide out of the way instead of just 'jumping' to a different position or disappear alltogether. While I got the movement code in place, naturally the doors will slide only thru space which is not occupied by tiles.

The problematic situation:
Consider a horizontal door. The player needs to be able to walk on it, so my doors have .collides = ig.Entity.COLLIDES.FIXED set. To the left and to the right of the door will be floor tiles, which renders the door immobile.

There is a bad workaround involving three tile thick floors / walls and the door moving in the middle tile range while emptying that out on the collisionMap but this is really limiting for level design - I.e. you still can't move a vertical door through the floor to block either the first or second floor AND keep the floor walkable without dents.

I'm really not sure how clear this is, let me know if you want screenshots :)

Regards,
Dominique

1 decade ago by saloon12yrd

Here's a screenshot that shows two varieties of the problem (horizontal and vertical).

click me, embedding doesn't seem to work

What you see:
The collisionMap and the entities - I left the tile maps out for better clarity. Doors are the cyan colored rectangles.

The idea:
The player will come from the upper floor from the left. He'll press the first switch, which will move the horizontal door to the left.

Then he can proceed to the middle floor where he presses the second switch. That switch moves the horizontal door back to the right and the vertical door downwards, opening the further passage. (think of this as an airlock)

Lastly the player can proceed to the left and down and press the third switch that will move the vertical door up again, opening passage out of the level.

Note that the doors move perfectly in this setup.

The issues:
In order to get the doors to move the floors have holes that you can see. When moving through the corridors as described the player entity will bounce into the first hole on the top floor. Note that the player entity won't fall through because it is broader than one tile and thus (by chance) will be held up by the vertical door.

However after pressing the second switch the hole in the top floor means that the player can actually jump on the upward moving vertical door and get back to the top floor through the hole in the top floor.

Hence, what I need is to close the gaps in the collisionMap BUT STILL have the doors to be able to move over those spaces while still being walkable.

Hope the screenshot clarifies it a bit.

Thanks for any hints on how to implement this,
Dominique

1 decade ago by Arantor

I think you should be able to do it by overriding the handleMovementTrace function in the door entity.

If the update code is already handling movement and you just have to not worry about collision between the door and world, overriding that entity's handleMovementTrace will solve the issue - because the player's own collision detection should cope with colliding with the door for you.

1 decade ago by saloon12yrd

Thx Arantor,

hmm yeah I thought about that and basically overrode the handleMovementTrace method with an empty one - no call to parent, nothing. The result is that the door doesn't move at all. No clue why.

1 decade ago by Arantor

Was the door's update handled by using pos.x/y or vel.x/y?

1 decade ago by saloon12yrd

Hi Arantor,

I guess the answer is vel.x/y, but see for yourself.

It works like this: The switch that triggers the door movement calls door.initMovement() which looks like this:

        initMovement: function(newPos) {
            this.gotoPos.x = newPos.x;
            this.gotoPos.y = newPos.y;
            this.sounds.open.play();
            
            if (this.pos.x > this.gotoPos.x) {
                //  move left
                this.vel.x = -1 * this.speed.x;
                this.vel.y = 0;

            } else if (this.pos.x < this.gotoPos.x) {
                // move right
                [...]
            } else if (this.pos.y > this.gotoPos.y) {
                // move up
                [...]
            } else if (this.pos.y < this.gotoPos.y) {
                // move down
                [...]
            }            
        },

The door.update() doesn't do much except checking whether the gotoPos was reached and then resets the vel.x/y:

        update: function() {
            this.parent();
            
            // need to round our position values, otherwise door can miss the gotoPos
            this.pos.x = Math.round(this.pos.x);
            this.pos.y = Math.round(this.pos.y);
            
            if (this.isMoving == true
                && this.pos.x == this.gotoPos.x 
                && this.pos.y == this.gotoPos.y) {
                
                this.isMoving   = false;
                this.vel.x      = 0;
                this.vel.y      = 0;
                
                if (this.pos.x == this.origPos.x && this.pos.y == this.origPos.y) {
                    this.isOpen = false;
                    
                } else {
                    this.isOpen = true;
                }
                                                
            } else if (this.vel.x != 0 || this.vel.y != 0) {
                this.isMoving   = true;
            }
        } 

Regards,
Dominique

1 decade ago by saloon12yrd

Oh bugger, I got it.
I updated the door.update() method to not call parent and do the necessary parts of the parent method on its own. Now it works. door.update() now looks like this:

        update: function() {
            this.last.x = this.pos.x;
            this.last.y = this.pos.y;
            
            // calculate new position, ignoring all possible collisions.
            // we need to round our position values, otherwise we can miss the gotoPos
            this.pos.x = Math.round(this.pos.x + this.vel.x * ig.system.tick);
            this.pos.y = Math.round(this.pos.y + this.vel.y * ig.system.tick);
            
            if (this.isMoving == true
                && this.pos.x == this.gotoPos.x 
                && this.pos.y == this.gotoPos.y) {
                
                this.isMoving   = false;
                this.vel.x      = 0;
                this.vel.y      = 0;
                
                if (this.pos.x == this.origPos.x && this.pos.y == this.origPos.y) {
                    this.isOpen = false;
                    
                } else {
                    this.isOpen = true;
                }
            } else if (this.vel.x != 0 || this.vel.y != 0) {
                this.isMoving   = true;
            }
            
            // update animation, if any
            if (this.currentAnim) {
                this.currentAnim.update();
            }
        }

@Arantor: thanks for pointing me in the right direction with your question (vel or pos?)!

Cheers,
Dominique
Page 1 of 1
« first « previous next › last »