Java-Gaming.org Hi !
Featured games (91)
games approved by the League of Dukes
Games in Showcase (804)
Games in Android Showcase (239)
games submitted by our members
Games in WIP (868)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  [solved][libGDX] Tile bounds = Entity bounds -> Cannot move in between  (Read 12388 times)
0 Members and 1 Guest are viewing this topic.
Offline Ivan Vinski

Senior Devvie


Medals: 5
Projects: 1
Exp: 3 years


Learning how to place those pixels nicely.


« Posted 2016-06-01 08:56:33 »

Hello JGO,

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.

Thanks in advance!

EDIT: I uploaded a video on the problem.
<a href="http://www.youtube.com/v/KPVn2v9Zivo?version=3&amp;hl=en_US&amp;start=" target="_blank">http://www.youtube.com/v/KPVn2v9Zivo?version=3&amp;hl=en_US&amp;start=</a>

Offline VaTTeRGeR
« Reply #1 - Posted 2016-06-01 09:52:07 »

Do you really want/need free movement in such confined space?

You can push the player in place on collision depending on desired movement direction but it's always a problem to make this reliable.
Offline Hydroque

JGO Coder


Medals: 25
Exp: 5 years


I'm always inspiring a good time.


« Reply #2 - Posted 2016-06-01 09:57:21 »

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.

You think I haven't been monitoring the chat? http://pastebin.java-gaming.org/c47d35366491fHere is a compilation <3
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Ivan Vinski

Senior Devvie


Medals: 5
Projects: 1
Exp: 3 years


Learning how to place those pixels nicely.


« Reply #3 - Posted 2016-06-01 10:07:39 »

Do you really want/need free movement in such confined space?

You can push the player in place on collision depending on desired movement direction but it's always a problem to make this reliable.
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):
1  
2  
3  
4  
5  
6  
7  
8  
    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.

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.
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.

Offline thedanisaur

JGO Knight


Medals: 59



« Reply #4 - Posted 2016-06-01 16:04:26 »

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.

Edit: clarification.

Every village needs an idiot Cool
Offline Hydroque

JGO Coder


Medals: 25
Exp: 5 years


I'm always inspiring a good time.


« Reply #5 - Posted 2016-06-01 17:39:54 »

Does bomberman do its collision

You think I haven't been monitoring the chat? http://pastebin.java-gaming.org/c47d35366491fHere is a compilation <3
Offline Ivan Vinski

Senior Devvie


Medals: 5
Projects: 1
Exp: 3 years


Learning how to place those pixels nicely.


« Reply #6 - Posted 2016-06-01 21:37:21 »

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.

Edit: clarification.
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.

Does bomberman do its collision
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.

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.

1. 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).
2. Create ObjectMap or whatever HashMap implementation you have which stores entity for key and entity for value.
3. When iterating over entities, poll all points of the entity.
4. If horizontal velocity is smaller than 0, only check points on the left side, otherwise only check points on the right side.
5. 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.
6. 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.

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:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
      if (horizontal.overlaps(obstacleBounds)) {
        float center = bounds.y + (bounds.height / 2f);
        float obstacleCenter = obstacleBounds.y + (obstacleBounds.height / 2f);
        float factor = center - obstacleCenter;
        if (factor < -5f) {
          velocity.y = -speed.value;
        } else if (factor > 5f) {
          velocity.y = speed.value;
        } else {
          velocity.y = 0f;
        }
        collidesHorizontally = true;
      }

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:
1  
      horizontal.set(newX, bounds.y, bounds.width, bounds.height);


EDIT #3:
Forgot to add cancellation code. This code is added before the loop.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
    if (!movement.vertical && movement.autoVertical && velocity.y != 0f) {
      BoundsComp obstacleBounds = prevLoopMap.entity.getComponent(BoundsComp.class);
      float center = bounds.y + (bounds.height / 2f);
      float obstacleCenter = obstacleBounds.y + (obstacleBounds.height / 2f);
      float newFactor = center - obstacleCenter;
      float absNewFactor = Math.abs(newFactor);
      if (absNewFactor > 54f && absNewFactor < 65f) {
        float offset = 0f;
        if (newFactor < 0f) {
          offset = -1f;
        } else if (newFactor > 0f) {
          offset = 1f;
        }
        bounds.y = ((bounds.y / world.getBlockHeight()) * world.getBlockHeight()) + offset;
        transform.y = bounds.y;
        velocity.y = 0f;
        movement.autoVertical = false;
      }
    }


The new method works with speed ranging from 100 to 200 and I haven't tested for faster speeds.

Offline Hydroque

JGO Coder


Medals: 25
Exp: 5 years


I'm always inspiring a good time.


« Reply #7 - Posted 2016-06-01 23:14:38 »

Or you could do a lower and upper check for the body because it appears only the head manipulates things

You think I haven't been monitoring the chat? http://pastebin.java-gaming.org/c47d35366491fHere is a compilation <3
Offline Ivan Vinski

Senior Devvie


Medals: 5
Projects: 1
Exp: 3 years


Learning how to place those pixels nicely.


« Reply #8 - Posted 2016-06-01 23:18:49 »

Or you could do a lower and upper check for the body because it appears only the head manipulates things
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!

Thanks for helping, guys!

Offline Riven
Administrator

« JGO Overlord »


Medals: 1371
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #9 - Posted 2016-06-02 18:26:48 »

If you use a circle or a rounded-rectangle as collision shape for your player, you'd squeeze right through any narrow entrance.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings!
Pages: [1]
  ignore  |  Print  
 
 

 
Riven (581 views)
2019-09-04 15:33:17

hadezbladez (5510 views)
2018-11-16 13:46:03

hadezbladez (2402 views)
2018-11-16 13:41:33

hadezbladez (5772 views)
2018-11-16 13:35:35

hadezbladez (1223 views)
2018-11-16 13:32:03

EgonOlsen (4661 views)
2018-06-10 19:43:48

EgonOlsen (5682 views)
2018-06-10 19:43:44

EgonOlsen (3198 views)
2018-06-10 19:43:20

DesertCoockie (4095 views)
2018-05-13 18:23:11

nelsongames (5115 views)
2018-04-24 18:15:36
A NON-ideal modular configuration for Eclipse with JavaFX
by philfrei
2019-12-19 19:35:12

Java Gaming Resources
by philfrei
2019-05-14 16:15:13

Deployment and Packaging
by philfrei
2019-05-08 15:15:36

Deployment and Packaging
by philfrei
2019-05-08 15:13:34

Deployment and Packaging
by philfrei
2019-02-17 20:25:53

Deployment and Packaging
by mudlee
2018-08-22 18:09:50

Java Gaming Resources
by gouessej
2018-08-22 08:19:41

Deployment and Packaging
by gouessej
2018-08-22 08:04:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!