I have implemented a Player class which handles collision between the player and the objects in game. When I run it, he falls through the floor. I have followed a tutorial step by step but it is not working.
Below I have added the Player class and GameScreen class.
I have tried making rectangles around my Player to interact with, but it wasnt a fix.
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.maps.MapObjects;
import com.badlogic.gdx.maps.objects.RectangleMapObject;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.viewport.Viewport;
import inf112.skeleton.app.AGame;
import inf112.skeleton.app.entities.Player;
import inf112.skeleton.app.scenes.Hud;
public class GameScreen implements Screen {
public AGame game;
public TiledMap map;
private OrthogonalTiledMapRenderer mapRenderer;
private OrthographicCamera camera;
public Player player;
private BitmapFont font;
public Viewport gameport;
private Hud hud;
public GameScreen (AGame game) {
this.game = game;
hud = new Hud(game.batch);
}
@Override
public void show() {
font = new BitmapFont();
font.setColor(Color.RED);
font.setColor(Color.RED);
map = new TmxMapLoader().load("assets/data/GameBoard2.tmx");
camera = new OrthographicCamera();
camera.setToOrtho(false, 10, 10);
mapRenderer = new OrthogonalTiledMapRenderer(map, (float)0.015625);
mapRenderer.setView(camera);
player = new Player((TiledMapTileLayer) map.getLayers().get("Player"));
player.setPosition(11 * player.getCollisionLayer().getTileWidth(), (player.getCollisionLayer().getHeight() - 14) * player.getCollisionLayer().getTileHeight());
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
mapRenderer.setView(camera);
mapRenderer.render();
mapRenderer.getBatch().begin();
player.draw((SpriteBatch) mapRenderer.getBatch());
mapRenderer.getBatch().end();
game.batch.setProjectionMatrix(hud.stage.getCamera().combined);
hud.stage.draw();
}
@Override
public void resize(int width, int height) {
camera.viewportHeight = height;
camera.viewportWidth = width;
}
@Override
public void pause() {
// TODO Auto-generated method stub
}
@Override
public void resume() {
// TODO Auto-generated method stub
}
@Override
public void hide() {
// TODO Auto-generated method stub
}
@Override
public void dispose() {
font.dispose();
mapRenderer.dispose();
map.dispose();
game.dispose();
}
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
public class Player extends Sprite implements InputProcessor {
private String blockedKey = "blocked";
private Vector2 velocity = new Vector2();
private float speed = 60 * 2, gravity = 60 * 1.8f, increment;
private boolean canJump;
private TiledMapTileLayer collisionLayer;
public Player(TiledMapTileLayer collisionLayer) {
this.collisionLayer = collisionLayer;
//setScale((float)0.1);
}
public void draw(SpriteBatch spriteBatch) {
update(Gdx.graphics.getDeltaTime());
super.draw(spriteBatch);
}
public void update(float delta) {
// apply gravity
velocity.y -= gravity * delta;
// clamp velocity
if(velocity.y > speed)
velocity.y = speed;
else if(velocity.y < -speed)
velocity.y = -speed;
// save old position
float oldX = getX(), oldY = getY();
boolean collisionX = false, collisionY = false;
// move on x
setX(getX() + velocity.x * delta);
// calculate the increment for step in #collidesLeft() and #collidesRight()
increment = collisionLayer.getTileWidth();
increment = getWidth() < increment ? getWidth() / 2 : increment / 2;
if(velocity.x < 0) // going left
collisionX = collidesLeft();
else if(velocity.x > 0) // going right
collisionX = collidesRight();
// react to x collision
if(collisionX) {
setX(oldX);
velocity.x = 0;
}
// move on y
setY(getY() + velocity.y * delta * 5f);
// calculate the increment for step in #collidesBottom() and #collidesTop()
increment = collisionLayer.getTileHeight();
increment = getHeight() < increment ? getHeight() / 2 : increment / 2;
if(velocity.y < 0) // going down
canJump = collisionY = collidesBottom();
else if(velocity.y > 0) // going up
collisionY = collidesTop();
// react to y collision
if(collisionY) {
setY(oldY);
velocity.y = 0;
}
// update animation
}
private boolean isCellBlocked(float x, float y) {
TiledMapTileLayer.Cell cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()));
return cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey(blockedKey);
}
public boolean collidesRight() {
for(float step = 0; step <= getHeight(); step += increment)
if(isCellBlocked(getX() + getWidth(), getY() + step))
return true;
return false;
}
public boolean collidesLeft() {
for(float step = 0; step <= getHeight(); step += increment)
if(isCellBlocked(getX(), getY() + step))
return true;
return false;
}
public boolean collidesTop() {
for(float step = 0; step <= getWidth(); step += increment)
if(isCellBlocked(getX() + step, getY() + getHeight()))
return true;
return false;
}
public boolean collidesBottom() {
for(float step = 0; step <= getWidth(); step += increment)
if(isCellBlocked(getX() + step, getY()))
return true;
return false;
}
public Vector2 getVelocity() {
return velocity;
}
public void setVelocity(Vector2 velocity) {
this.velocity = velocity;
}
public float getSpeed() {
return speed;
}
public void setSpeed(float speed) {
this.speed = speed;
}
public float getGravity() {
return gravity;
}
public void setGravity(float gravity) {
this.gravity = gravity;
}
public TiledMapTileLayer getCollisionLayer() {
return collisionLayer;
}
public void setCollisionLayer(TiledMapTileLayer collisionLayer) {
this.collisionLayer = collisionLayer;
}
@Override
public boolean keyDown(int keycode) {
switch(keycode) {
case Input.Keys.W:
if(canJump) {
velocity.y = speed / 1.8f;
canJump = false;
}
break;
case Input.Keys.A:
velocity.x = -speed;
break;
case Input.Keys.D:
velocity.x = speed;
}
return true;
}
@Override
public boolean keyUp(int keycode) {
switch(keycode) {
case Input.Keys.A:
case Input.Keys.D:
velocity.x = 0;
}
return true;
}
@Override
public boolean keyTyped(char character) {
return false;
}
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
return false;
}
@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
return false;
}
@Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
return false;
}
@Override
public boolean mouseMoved(int screenX, int screenY) {
return false;
}
@Override
public boolean scrolled(float amountX, float amountY) {
return false;
}
The position of a libGDX Sprite
is bottom left so you need to make a distinction between position as far as your render is concerned, and as far as collision is concerned. So if you add a half tile width to the x position when checking for the collision that would match what you see, being the base of the sprite.
Imagine a tilewidth of 4f
and a position of 7f
. As you look the sprite is rendered mainly on the third tile, but the collision is tested against the second one.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.