I’m creating bomberman-type game so the walls are like a grid. Entity size is 64x128 and bounds are 64x63. Tile size is 128x64 and bounds are 128x64. So, I can pass through the top and bottom since the width of the entity bounds is smaller than the width of the tile bounds. But, I can only pass left and right when I’m either on top or bottom of the map since it assures that the entity is in line with the tile. Sometimes I’m lucky and can pass through one of the middle blocks since I magically align the entity with the tile. The problem I face is the fact entity bounds height is only 1 pixel smaller than the height of tile bounds. What are some solutions to this? I don’t want to have tile based movement. I’m aiming for free movement.
Note: I cannot make entity bounds smaller since the legs would pass through the top of the block. I’m simulating 3d in 2d and each tile is actually only a part of the block, so the entity is drawn on top of the base part of the block, but the top part of the block is drawn over the entity.
Do you iterate through all objects in the game for collision detection or are you using some fancy means? If you are iterating, just hit test using the bounds of the player, and before frame update, set them back where they were trying to move from if it is an invalid move (or move as much as they can.)
This is best done with 2 sets of 2 spacial positions to check against.
If they could make this work in 1983 with NES Bomberman, then I wish to have free movement in 2016.
I thought about making that edge sliding so it slides you in the tile aligned position if you’re blocked, but not exactly sure how to actually calculate where relative to a tile are you. I’m doing something like (entity.x + entity.width / 2f) % block.width and (entity.y + entity.height / 2f) % block.height, but it doesn’t tell me where from the tile it is, only positive numbers so I don’t know where to push him. I did something like that before on a topic on these forums, but it is just too messy code and I’m looking for elegant solution that is not that confusing.
This is what could solve the problem (pseudocode):
if (moving right && blocked) {
float relativeY = calculates somehow position relative to tile;
if (relativeY > 0f) {
velocity.y = speed; // up
} else if (relativeY < 0f) {
velocity.y = -speed; // down
}
}
But also then, it should stop once it hits the alignment.
This is very confusing and I hope there is elegant solution.
You must have misread the question.
I have collision detection that is iterating over all entities (soon I might implement some broad phase method), then I filter them with bitwise operators and then check if the bounds are being hit and if they are, I set them back. The collision detection works nicely, but the problem is with the movement through those narrow spaces between the tiles.
How far can you move in one update? If it’s more than one pixel (the width of the hallway) you are always going to have problems without some sort of assistance.
Sliding is a good idea.
What you need to do is calculate the center point of the blocking object and the player, then subtract one from the other. This will give you a positive/negative value with which to choose the direction to offset the player.
The only way this works right is if you offset by the level of tolerance exactly (in this case 1 pixel). So you’ll have to work around this to get the correct feel you’re looking for.
Well, in the video, velocity is 50 pixels and it is multiplied by delta time which means it moves 50 pixels per frame update I guess. What I realized is, entering those areas is easy if I press both horizontal and vertical control which means I need to simulate that. I realized, as I was going through my day as usual, that I could have two collision points on each side (left and right) and if on one side only one is colliding, I would know exactly where to push the player, or actually whether the vertical velocity needs to be positive or negative. I will take your reply in consideration.
I’m using entity component system framework called Ashley which means bomberman doesn’t actually perform collision detection. There is class I created called MovementSystem (that extends IteratingSystem) which is doing the work.
EDIT: Yes. The solution is having collision points.
[s]I have tested that method with speeds ranging from 100 to 200 and concluded that it works smoothly when speed is in range from 100 to 150, after that it starts to jiggle multiple times (up and down) until it hits that alignment that allows him to pass through. That is actually good, since there is no need in my bomberman game to move faster. Each power up for speed will increase the speed by 10 until it hits 150.
I would share the code, but there is a lot of refactoring to be done first. The (fully documented) source code will be available anyway once I release the game, so I will just explain what I’m doing for people who might stumble upon the same problem in the future.
Create collision points on both sides (left and right) at the top and bottom, that are a bit outside the bounds (5 pixels, in my case), that have boolean variable which states whether or not they have been activated (have collided in the last frame).
Create ObjectMap or whatever HashMap implementation you have which stores entity for key and entity for value.
When iterating over entities, poll all points of the entity.
If horizontal velocity is smaller than 0, only check points on the left side, otherwise only check points on the right side.
If only one point on the particular side is colliding, do the following:
a) If top point is colliding, move the player downwards.
b) If bottom point is colliding, move the player upwards.
You should map entities and have a boolean that states whether or not the they were added in the current loop.
At the end (outside the for loop), if entities haven’t been mapped in the current loop, poll points that are colliding and if none of the points are colliding, cancel the velocity. Also, if the player is no longer moving into the wall, also cancel the velocity. However, figure out a way to actually know if the player is trying to move up and down so you don’t cancel the actual input the player is triggering. Note: Remember to set the flags for collision points if they are colliding or not.
This isn’t the most efficient method yet, as I said, it needs to be refactored. I’m not exactly sure how it will be once I change stuff, but the source code will be available and if I remember, I will edit this post once the game is released and include the code snippet.
[/s]
And here’s a cookie for providing really useful information which I might find useful if I ever need it in future.
EDIT #2: I have merged two solutions provided by thedanisaur and Hydroque into one and it works even nicer than the previous one. I had hard time cancelling velocity and now it is very easy. Code snippet:
Note: When changing and cancelling velocity, make sure you take into account whether or not the user has actually pressed the control to move vertically.
I split detection into two, horizontal and vertical so sliding is allowed and horizontal is a local variable representing a rectangle inside MovementSystem and is used like this:
I’m not exactly sure if that would work. Body bounds are automatically stopped before it enters and those collision points are actually always either inside or outside some entity.
However, I’m a bit sleepy and will consider this once I get to refactoring the code and refining this method tomorrow. Here’s a delicious cookie for you, too!