Collision using Tiled and LibGDX not working - java

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

Related

Getting NullPointerException for no reason [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 3 years ago.
Improve this question
I am getting a NullPointerException for no reason. Please don't redirect me to another post. I have looked at all of them. I am making a game with LibGDX.
Here is the Error
Exception in thread "LWJGL Application" java.lang.NullPointerException
at net.hasanbilal.pr.entities.Entity.getWeight(Entity.java:88)
at net.hasanbilal.pr.entities.Entity.update(Entity.java:25)
at net.hasanbilal.pr.entities.Porter.update(Porter.java:34)
at net.hasanbilal.pr.world.GMap.update(GMap.java:28)
at net.hasanbilal.pr.world.TiledGMap.update(TiledGMap.java:40)
at net.hasanbilal.pr.PrisonRevelations.render(PrisonRevelations.java:59)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:215)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:120)
I will be showing each class that the error points too.
This is the Entity Class.
package net.hasanbilal.pr.entities;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import net.hasanbilal.pr.world.GMap;
public abstract class Entity {
protected Vector2 pos;
protected EntityType t;
protected float velocityY = 0;
protected GMap m;
protected boolean grounded = false;
public void create (EntitySnapshot snapshot, EntityType type, GMap map) {
this.pos = new Vector2(snapshot.getX(),snapshot.getY());
this.t = t;
this.m = m;
}
public void update (float delta, float g) {
float newY = pos.y;
this.velocityY += g * delta * getWeight();
newY += this.velocityY * delta;
if (m.doesRectCollideWithMap(pos.x, newY, getWidth(), getHeight())) {
if (velocityY < 0) {
this.pos.y = (float) Math.floor(pos.y);
grounded = true;
}
this.velocityY = 0;
} else {
this.pos.y = newY;
grounded = false;
}
}
public abstract void render (SpriteBatch b);
protected void moveX(float amount) {
float newX = this.pos.x + amount;
if (!m.doesRectCollideWithMap(newX, pos.y, getWidth(), getHeight()))
this.pos.x = newX;
}
public EntitySnapshot getSaveSnapshot(){
return new EntitySnapshot(t.getId(), pos.x, pos.y);
}
public Vector2 getPos() {
return pos;
}
public float getX() {
return pos.x;
}
public float getY() {
return pos.y;
}
public EntityType getT() {
return t;
}
public float getVelocityY() {
return velocityY;
}
public boolean isGrounded() {
return grounded;
}
public int getWidth() {
return t.getWidth();
}
public int getHeight() {
return t.getHeight();
}
public float getWeight() {
return t.getWeight();
}
}
This is the Porter Class.
package net.hasanbilal.pr.entities;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import net.hasanbilal.pr.world.GMap;
public class Porter extends Entity {
private static final int SPEED = 80;
private static final int JUMP_VELOCITY = 5;
Texture img;
public void create (EntitySnapshot snapshot, EntityType type, GMap map) {
super.create(snapshot, type, map);
img = new Texture("porter.png");
}
#Override
public void render(SpriteBatch b) {
b.draw(img, pos.x, pos.y, getWidth(), getHeight());
}
public void update(float delta, float g) {
if (Gdx.input.isKeyPressed(Keys.SPACE) && grounded)
this.velocityY += JUMP_VELOCITY * getWeight();
else if (Gdx.input.isKeyPressed(Keys.SPACE) && !grounded && this.velocityY > 0)
this.velocityY += JUMP_VELOCITY * getWeight() * delta;
super.update(delta, g);
if (Gdx.input.isKeyPressed(Keys.LEFT))
moveX(-SPEED * delta);
if (Gdx.input.isKeyPressed(Keys.RIGHT))
moveX(SPEED * delta);
}
}
This is the GMap
package net.hasanbilal.pr.world;
import java.util.ArrayList;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import net.hasanbilal.pr.entities.Entity;
import net.hasanbilal.pr.entities.EntityLoader;
import net.hasanbilal.pr.entities.Porter;
public abstract class GMap {
protected ArrayList<Entity> entities;
public GMap() {
entities = new ArrayList<Entity>();
entities.addAll(EntityLoader.loadEntities("basic", this, entities));
}
public void render (OrthographicCamera c, SpriteBatch b) {
for (Entity entity : entities) {
entity.render(b);
}
}
public void update (float deltaTime) {
for (Entity entity : entities) {
entity.update(deltaTime, -9.8f);
}
}
public void dispose () {
EntityLoader.saveEntities("basic", entities);
}
/**
* Gets a tile by location
* #param layer
* #param x
* #param y
* #return
*/
public TileType getByLocation(int layer, float x, float y) {
return this.getByCoordinate(layer, (int) (x / TileType.TILE_SIZE), (int) (y / TileType.TILE_SIZE));
}
/**
* Gets Tile by coordinate
* #param layer
* #param col
* #param row
* #return
*/
public abstract TileType getByCoordinate(int layer, int col, int row);
public boolean doesRectCollideWithMap(float x, float y, int width, int height) {
if (x<0 || y < 0 || x + width > getPixelWidth() || y + height > getPixelHeight())
return true;
for (int row = (int) (y / TileType.TILE_SIZE); row < Math.ceil((y + height) / TileType.TILE_SIZE); row++) {
for (int col = (int) (x / TileType.TILE_SIZE); col < Math.ceil((x + width) / TileType.TILE_SIZE); col++) {
for (int layer = 0; layer < getLayers(); layer++) {
TileType type = getByCoordinate(layer, col, row);
if (type != null && type.isCollidable())
return true;
}
}
}
return false;
}
public abstract int getWidth();
public abstract int getHeight();
public abstract int getLayers();
public int getPixelWidth() {
return this.getWidth() * TileType.TILE_SIZE;
}
public int getPixelHeight() {
return this.getHeight() * TileType.TILE_SIZE;
}
}
This is the class for the TiledGMap
package net.hasanbilal.pr.world;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TiledMapTile;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import net.hasanbilal.pr.entities.Entity;
import net.hasanbilal.pr.entities.Porter;
public class TiledGMap extends GMap {
TiledMap lvl1;
OrthogonalTiledMapRenderer otmr;
public TiledGMap() {
lvl1 = new TmxMapLoader().load("level1.tmx");
otmr = new OrthogonalTiledMapRenderer(lvl1);
}
#Override
public void render(OrthographicCamera c, SpriteBatch b) {
otmr.setView(c);
otmr.render();
b.setProjectionMatrix(c.combined);
b.begin();
super.render(c, b);
b.end();
}
#Override
public void update(float deltaTime) {
super.update(deltaTime);
}
#Override
public void dispose() {
lvl1.dispose();
}
#Override
public TileType getByCoordinate(int layer, int col, int row) {
Cell cell = ((TiledMapTileLayer) lvl1.getLayers().get(layer)).getCell(col, row);
if (cell !=null) {
TiledMapTile t = cell.getTile();
if (t != null) {
int id = t.getId();
return TileType.getTileTypeById(id);
}
}
return null;
}
#Override
public int getWidth() {
return ((TiledMapTileLayer) lvl1.getLayers().get(0)).getWidth();
}
#Override
public int getHeight() {
return ((TiledMapTileLayer) lvl1.getLayers().get(0)).getHeight();
}
#Override
public int getLayers() {
return lvl1.getLayers().getCount();
}
}
This is the Prison Revelations class
package net.hasanbilal.pr;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector3;
import net.hasanbilal.pr.world.GMap;
import net.hasanbilal.pr.world.TileType;
import net.hasanbilal.pr.world.TiledGMap;
public class PrisonRevelations extends ApplicationAdapter {
OrthographicCamera c;
SpriteBatch b;
GMap gm;
#Override
public void create () {
b = new SpriteBatch();
c = new OrthographicCamera();
c.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
c.update();
gm = new TiledGMap();
}
#Override
public void render () {
Gdx.gl.glClearColor(255, 255, 255, 1);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if (Gdx.input.isTouched()) {
c.translate(-Gdx.input.getDeltaX(), Gdx.input.getDeltaY());
c.update();
}
if (Gdx.input.justTouched()) {
Vector3 pos = c.unproject(new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0));
TileType t = gm.getByLocation(1, pos.x, pos.y);
if (t != null) {
System.out.println("You clicked on tile with id" + t.getId() + " " + t.getName()+ " " + t.isCollidable() + " " + t.getDamage());
}
}
c.update();
gm.update(Gdx.graphics.getDeltaTime());
gm.render(c, b);
}
#Override
public void dispose () {
b.dispose();
gm.dispose();
}
}
Please help. Im gonna die. This is due soon.
Looks like you made a mistake with parameters names on your create, change to this:
public void create (EntitySnapshot snapshot, EntityType type, GMap map) {
this.pos = new Vector2(snapshot.getX(),snapshot.getY());
this.t = type;
this.m = map;
}

Projectiles in my ArrayList are not changed individually upon collision, how can I fix this?

I am trying to make a game. I want the projectiles (balls) that I shoot to each have their own individual collisions with objects and the margins of the game screen, but right now when one ball collides with the game screen margins, every balls' velocity.x or velocity.y is multiplied by -1 to simulate collision rather than just the individual ball that hit's velocity being modified. (When one ball hits, all balls' velocities are affected). The projectiles are stored in an ArrayList in the GameWorld class and are all given an identical velocity when they are shot. You pick a direction to shoot in, then balls are shot every 0.3s in that direction until all balls are shot.
Here is the code from my Projectiles class:
package com.trimble.gameobjects;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Vector2;
import com.trimble.gameworld.GameWorld;
public class Projectile {
private Vector2 velocity, acceleration;
private Vector2 position;
private final float RADIUS = 3f;
private boolean active, shot;
private GameWorld world;
private float theta;
public Projectile(float x, GameWorld world) {
this.world = world;
this.position = new Vector2();
this.position.x = x;
this.position.y = world.getGameRect().y - 3;
// hitbox = new Circle(position, 3f);
this.velocity = new Vector2();
this.acceleration = new Vector2(0, 0.5f);
this.active = false;
this.shot = false;
}
public void update(float delta) {
if (active) {
position.add(velocity.cpy().scl(delta));
velocity.add(acceleration.cpy().scl(delta));
// left
if (this.position.x <= 3) {
Gdx.app.log("hit", " left");
this.position.x = 3;
this.velocity.x *= -1;
}
// right
else if (this.position.x >= world.getGameRect().width - 3) {
Gdx.app.log("hit", " right");
this.position.x = world.getGameRect().width - 3;
this.velocity.x *= -1;
}
// top
if (this.position.y < world.getGameRect().y + world.getGameRect().height + 3) {
Gdx.app.log("hit", " top");
this.position.y = world.getGameRect().y + world.getGameRect().height + 3;
this.velocity.y *= -1;
}
// bottom
else if (this.position.y > world.getGameRect().y - 3 && velocity.y > 0) {
Gdx.app.log("hit", " bottom");
if (!this.world.hasTouched()) {
this.world.getBaseCircle().setPositionX(position.x);
this.world.setTouched(true);
}
zeroVelocity();
this.active = false;
this.position = world.getBaseCirclePos();
this.world.addInactive();
}
}
}
public Vector2 getVelocity() {
return velocity;
}
public float getVelocityX() {
return velocity.x;
}
public float getVelocityY() {
return velocity.y;
}
public void setVelocity(Vector2 velocity) {
this.velocity = velocity;
}
public void setVelocityX(float x) {
this.velocity.x = x;
}
public void setVelocityY(float y) {
this.velocity.y = y;
}
public float getTheta() {
return theta;
}
public void setTheta(float theta) {
this.theta = theta;
}
public void zeroVelocity() {
this.velocity.x = 0;
this.velocity.y = 0;
}
public Vector2 getPosition() {
return position;
}
public void setPositionY(float y) {
this.position.y = y;
}
public void setPositionX(float x) {
this.position.x = x;
}
public void setPosition(Vector2 position) {
this.position = position;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public float getR() {
return RADIUS;
}
public boolean wasShot() {
return shot;
}
public void setShot(boolean shot) {
this.shot = shot;
}
}
Here is the code in GameWorld which is called when the player shoots:
public void transitionHasShot() {
if (currentState == GameState.READY) {
currentState = GameState.HASSHOT;
velocity.y = (float) (-165 * Math.sin(theta));
velocity.x = (float) (165 * Math.cos(theta));
baseCircle.setActive(false);
for (Projectile p : projectiles) {
p.setVelocity(velocity);
}
projectiles.get(0).setActive(true);
}
}
Let me know if you need any more info.
I solved the problem by changing the code in transitionHasShot():
change
for (Projectile p : projectiles) {
p.setVelocity(velocity);
}
to:
for (Projectile p : projectiles) {
p.setVelocity(velocity.cpy());
}

LibGDX Flip 2D Sprite Animation

I have an animation that I want to play flipped if the user presses the 'A' key on their keyboard. The animation is facing right in the file and is played normally until I try to flip the texture.
This is what happens when I try to flip the texture when the player's direction has changed:
As you can see, the animation plays fine in the beginning but when I change the player's direction it alternates between the flipped frame and the unflipped frame.
This is my player class:
package unit22.game;
import java.util.ArrayList;
import unit22.core.Utils;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
public class Player {
private PlayerState state = PlayerState.STANDING;
private Direction direction = Direction.RIGHT;
private int x = 0, y = 0, width = 0, height = 0;
private PlayerInputProcessor inputProcessor;
private String name;
private ArrayList<Action> actions;
private Animation standingAnim;
private Animation movingAnim;
private float stateTime;
private SpriteBatch spriteBatch;
private Action currentAction;
private Animation currentAnimation;
public Player(String name, int x, int y, int width, int height) {
this.name = name;
setBounds(x, y, width, height);
if(getX() > 400) setDirection(Direction.LEFT);
this.actions = new ArrayList<Action>();
standingAnim = new Animation(0.06f, Utils.loadTextureAtlas("standing", "textures/characters/animations/" + name + "/").getRegions());
//movingAnim = new Animation(0.06f, Utils.loadTextureAtlas("moving", "textures/characters/animations/" + name + "/").getRegions());
stateTime = 0f;
spriteBatch = new SpriteBatch();
}
public void update() {
stateTime += Gdx.graphics.getDeltaTime();
switch(state) {
case STANDING:
if(currentAnimation != standingAnim)
currentAnimation = standingAnim;
break;
case MOVING:
if(currentAnimation != movingAnim)
currentAnimation = movingAnim;
break;
case ACTING:
Animation anim = new Animation(0.06f, Utils.loadTextureAtlas(currentAction.getName(), "textures/characters/animations/" + getName() + "/").getRegions());
if(currentAnimation != anim)
currentAnimation = anim;
break;
}
}
public void render() {
TextureRegion currentFrame = currentAnimation.getKeyFrame(stateTime, true);
if(getDirection() == Direction.LEFT) {
currentFrame.flip(true, false);
}
System.out.println("Direction: " + direction + ", Flipped: " + currentFrame.isFlipX());
spriteBatch.begin();
spriteBatch.draw(currentFrame, x, y, width, height);
spriteBatch.end();
}
public ArrayList<Action> getActions() {
return actions;
}
public void addAction(Action action) {
this.actions.add(action);
}
public void setActions(ArrayList<Action> actions) {
this.actions = actions;
}
public void setInputProcessor(PlayerInputProcessor inputProcessor) {
this.inputProcessor = inputProcessor;
}
public PlayerInputProcessor getInputProcessor() {
return inputProcessor;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Direction getDirection() {
return direction;
}
public PlayerState getState() {
return state;
}
public void setDirection(Direction direction) {
this.direction = direction;
}
public void setState(PlayerState state) {
this.state = state;
}
public int[] getBounds() {
return new int[] {x, y, width, height};
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public void setBounds(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
}
In my render method I am checking whether the player's direction is left and if it is then to flip the current animation frame.
This is how I am handling my input:
package unit22.screens;
import unit22.core.Game;
import unit22.core.Screen;
import unit22.game.Direction;
import unit22.game.Player;
import unit22.game.PlayerInputProcessor;
import com.badlogic.gdx.Gdx;
public class Playing extends Screen {
Player player;
public Playing(Game game, String name) {
super(game, name);
}
#Override
public void init() {
player = new Player("misaka", 100, 100, 188, 380);
player.setInputProcessor(new PlayerInputProcessor(player) {
#Override
public boolean keyTyped(char character) {
if(getPlayer().getX() <= 14) getPlayer().setX(15);
if(getPlayer().getX() + getPlayer().getWidth() >= 1024 - getPlayer().getWidth()) getPlayer().setX(1024 - getPlayer().getWidth() - 15);
if(character == 'a' || character == 'A') {
getPlayer().setX((int)(getPlayer().getX() - (900 * Gdx.graphics.getDeltaTime())));
if(getPlayer().getDirection() == Direction.RIGHT) {
getPlayer().setDirection(Direction.LEFT);
}
}
if(character == 'd' || character == 'D') {
getPlayer().setX((int)(getPlayer().getX() + (900 * Gdx.graphics.getDeltaTime())));
if(getPlayer().getDirection() == Direction.LEFT) {
getPlayer().setDirection(Direction.RIGHT);
}
}
return super.keyTyped(character);
}
});
getInputHandle().addProcessor(player.getInputProcessor());
}
#Override
public void render(float delta) {
super.render(delta);
player.update();
player.render();
}
}
I've been trying to figure this problem out for a couple of hours now and haven't made any progress. Any idea why this would be happening?
The problem is here:
if(getDirection() == Direction.LEFT) {
currentFrame.flip(true, false);
}
The flip method permanently flips the original TextureRegion that the Animation class is referencing. So you either need to make sure you flip it back each time after flipping and drawing it, or do this, which I think is simpler:
Never flip it but instead use a negative width when drawing it with SpriteBatch, like this:
boolean flip = (getDirection() == Direction.LEFT);
spriteBatch.draw(currentFrame, flip ? x+width : x, y, flip ? -width : width, height);
If somebody is still wondering, negating scaleX or scaleY works like a charm and does not hurt performance (like TextureRegion.flip does for example).
Example:
draw(region, x, y, originX, originY, width, float height,
(flip ? -1 : 1) * scaleX, float scaleY, float rotation);
I know that question is old but I think it is better solution
currentFrame = walkAnimation.getKeyFrame(stateTime, true);
if(!currentFrame.isFlipX())
currentFrame.flip(true, false);
batch.draw(currentFrame, 0,0,0,0);
I flip my animation sequence use the code below(in kotlin):
if (this.position <= 0f)
{
this.speed = - this.speed
this.position = 0.0f
this.runAnimation.keyFrames.forEach {
it.flip(true, false)
}
}else if(this.position >= SCREEN_WIDTH / SCALE - width)
{
this.speed = - this.speed
this.position = SCREEN_WIDTH / SCALE - width
this.runAnimation.keyFrames.forEach {
it.flip(true, false)
}
}
this.game.batch.begin()
this.game.batch.draw(currentFrame, this.position, 40f)
this.game.batch.end()
Every time you flip the sequence, make sure loop every frame and flip every one:
this.runAnimation.keyFrames.forEach { it.flip(true, false) }
and remember that, the frames are flipped forever, so if you want to return back, you should flip again(flip = true)!

trying to make my (very simple) libgdx game more object-oriented. added GameObject class - game doesn't launch anymore

what the title says.
first of all, here are my 3 classes:
MyGdxGame:
package com.mygdx.game;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
public class MyGdxGame extends ApplicationAdapter {
SpriteBatch batch;
Sprite sp;
Texture img;
int width;
int height;
Player p;
#Override
public void create () {
batch = new SpriteBatch();
img = new Texture("dildo.png");
sp = new Sprite(img);
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
p = new Player(img);
Gdx.input.setInputProcessor(p);
}
#Override
public void render () {
//sp.flip(true, false);
p.update();
Gdx.gl.glClearColor(255,255,255,255);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
//batch.draw(img, 0, height/6, -img.getWidth(), img.getHeight());
p.draw(batch);
//sp.draw(batch);
batch.end();
}
}
Player:
package com.mygdx.game;
import com.badlogic.gdx.Gdx;
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.math.Vector2;
import com.badlogic.gdx.utils.TimeUtils;
public class Player extends GameObject implements InputProcessor {
private Sprite sp;
private Texture te;
private float xPos;
private float yPos;
private float xSpeed;
private float ySpeed;
private float accelerationX;
private float g;
Vector2 position;
private float accelerationJump = 9f;
private boolean allowJump = true;
private boolean isDragged = false;
public Player(Texture sprite) {
xPos = 0;
yPos = (super.getHeight()/6);
xSpeed = 5.5f;
ySpeed = 0;
te = sprite;
sp.setX(xPos);
sp.setY(yPos);
g = 0.2f;
accelerationX=0.02f;
}
public void update() {
ySpeed -= g;
if(isDragged) {
xSpeed += accelerationX;
moveBy(xSpeed,0);
isDragged = false;
}
if (getxPos() > super.getWidth()) {
setxPos(0);
} else {
moveBy(xSpeed, ySpeed);
}
if (getyPos() < super.getHeight() / 6) {
moveTo(sp.getX(), getHeight() / 6);
}
if (onGround()) {
allowJump = true;
ySpeed = 0;
}
}
public void jump() {
ySpeed += accelerationJump;
}
public boolean onGround() {
return (sp.getY() == super.getHeight()/6);
}
#Override
public boolean keyDown(int keycode) {
return false;
}
#Override
public boolean keyUp(int keycode) {
return false;
}
#Override
public boolean keyTyped(char character) {
return false;
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
return true;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
if (allowJump && isDragged == false) {
allowJump = false;
jump();
}
return false;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
if(isDragged==false) {
isDragged = true;
}
return false;
}
#Override
public boolean mouseMoved(int screenX, int screenY) {
return false;
}
#Override
public boolean scrolled(int amount) {
return false;
}
}
GameObject:
package com.mygdx.game;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
public abstract class GameObject {
private Sprite sp;
private int width;
private int height;
private float xPos;
private float yPos;
private float xSpeed;
private float ySpeed;
public GameObject(int width, int height) {
this.width = width;
this.height = height;
}
public GameObject() {
}
public void moveTo(float xPos2, float yPos2) {
setxPos(xPos2);
setyPos(yPos2);
}
public void moveBy(float dx, float dy) {
sp.setY(sp.getY() + dy);
sp.setX(sp.getX() + dx);
}
public float getxPos() {
return xPos;
}
public float getyPos() {
return yPos;
}
public void setxPos(float xPos2) {
sp.setX(xPos2);
}
public void setyPos(float yPos) {
sp.setY(yPos);
}
public float getxSpeed() {
return xSpeed;
}
public float getySpeed() {
return ySpeed;
}
public void setxSpeed(float xSpeed2) {
xSpeed = xSpeed2;
}
public void setySpeed(float ySpeed2) {
ySpeed = ySpeed2;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height
}
public void draw(SpriteBatch batch) {
sp.draw(batch);
}
}
basically, the game as it is now is just a sprite moving from left to right of the screen - when you tap, it jumps, when you drag the screen it dashes forward. i want to now start adding things like power-ups and platforms so i thought it would be a good idea to create a GameObject class. but now when i run it the screen goes black and the application just crashes, i have a feeling it has something to do with the way i'm initialising my Texture? any ideas?
any help is highly appreciated, many thanks in advance :)
edit: in GameObject constructor width and height are the width and height of the screen
if you have your image in asset folder of android project, test img = new Texture (Gdx.files.internal ("dildo.png"));
example:
AdroidProyect->Asset->YourFile.png
and in player i think
1-
public Player(Texture sprite) {
xPos = 0;
yPos = (super.getHeight()/6);
xSpeed = 5.5f;
ySpeed = 0;
te = sprite;
//add and refactor your code if it works
sp = new Sprite(sprite);
sp.setX(xPos);
sp.setY(yPos);
g = 0.2f;
accelerationX=0.02f;
}
or 2-
I do not want to do, but in your MyGdxGame, your
you say,
..//
img = new Texture ("dildo.png");
         sp = new Sprite (img);
         p = new Player (img);
..//
but after you pass the player a texture, because no sprite or as I said before initializing the player, you could also change the constructor of the player.
public Player(Sprite sprite){t
..//
this.sp = sprite;
ADD NEW:
Musta Been to look at your code and no offense, you have a code a little crazy :)
visibility of variables is somewhat confusing because what you want but do not test well and looks over the access modifiers, aver if they match what you want to do.
my English is also a little crazy too.
in your class MyGdxGame;
..//
#Override
public void create () {
batch = new SpriteBatch();
img = new Texture(Gdx.files.internal("dildo.png"));
sp = new Sprite(img);
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
p = new Player(sp);
Gdx.input.setInputProcessor(p);
}
..//
class GameObject Change;
public abstract class GameObject {
protected Sprite sp;
protected int width;
protected int height;
protected float xPos;
protected float yPos;
protected float xSpeed;
protected float ySpeed;
player class.
public class Player extends GameObject implements InputProcessor {
//private Sprite sp; remove
private Texture te;
//private float xPos; remove
//private float yPos; remove
//private float xSpeed; remove
//private float ySpeed; remove
private float accelerationX;
private float g;
Vector2 position;
private float accelerationJump = 9f;
private boolean allowJump = true;
private boolean isDragged = false;
public Player(Sprite sprite) {
..//
sp = sprite;

Libgdx show score and add 1 to score every second

I want to increment the score by 1 point every second but I am struggling to get it to work properly.
e.g.
(pseudo code):
int score = 0f // on create
updateEverySecond() {
score += 1;
displayScore()
}
I would also like to know how to display the score at the top of my screen and centred.
My Full Source Code:
package com.ryanwarren.dodge.game;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
public class libgdxGame extends ApplicationAdapter {
SpriteBatch batch;
Texture player;
Vector2 position;
float time = 0f;
#Override
public void create () {
batch = new SpriteBatch();
player = new Texture(Gdx.files.internal("player.png"));
position = new Vector2((Gdx.graphics.getWidth()/2 - (player.getWidth()/2)),50);
}
#Override
public void dispose() {
}
#Override
public void render () {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if(Gdx.input.isKeyPressed(Keys.W)) {
position.y += 1f;
}
if((Gdx.input.isKeyPressed(Keys.A)) && (position.x > 0)) {
position.x -= 2f;
}
if(Gdx.input.isKeyPressed(Keys.S)) {
position.y -= 1f;
}
if((Gdx.input.isKeyPressed(Keys.D)) && (position.x < Gdx.graphics.getWidth() - player.getWidth())) {
position.x += 2f;
}
if(Gdx.input.isTouched()) {
System.out.println("application clicked");
}
if((Gdx.input.getAccelerometerX() >= 0) && (position.x > 0)) {
position.x -= 2f;
}
else if((Gdx.input.getAccelerometerX() < 0) && (position.x < Gdx.graphics.getWidth() - player.getWidth())) {
position.x += 2f;
}
System.out.println("Rotation: " + Gdx.input.getAccelerometerX());
batch.begin();
batch.draw(player, position.x, position.y);
batch.end();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
float timeState=0f;
public void render(){
// ............
timeState+=Gdx.graphics.getDeltaTime();
if(timeState>=1f){
// 1 second just passed
timeState=0f; // reset our timer
updateEverySecond(); // call the function that you want
}

Categories

Resources