I'm trying to create simple 2d game in Java with libGDX.
I stuck on creating 2d animation from sprite sheet in PNG file.
I have AbstractScreen class which holds 'things' for every screen.
GameScreen class for drawing my game and Player class with animation code.
Player class is from https://github.com/libgdx/libgdx/wiki/2D-Animation example.
Firstly i created AbstractScreen and MainMenuScreen (based on AbstractScreen). It's works but now i'm trying to create GameScreen with my animated player. Something is wrong because i haven't any error and player is not visible on app screen. How to properly implement sprite sheet animation for skeleton of my app?
My game screen:
class GameScreen extends AbstractScreen {
Player player;
public GameScreen(NinjaGame game) {
super(game);
init();
}
#Override
protected void init() {
initPlayer();
}
private void initPlayer() {
player = new Player();
player.setDebug(true);
stage.addActor(player);
}
#Override
public void render(float delta) {
super.render(delta);
update();
spriteBatch.begin();
stage.draw();
spriteBatch.end();
}
private void update() {
stage.act();
}
}
My AbstractScreen class:
public abstract class AbstractScreen implements Screen {
protected NinjaGame game;
protected Stage stage;
private OrthographicCamera camera;
protected SpriteBatch spriteBatch;
public AbstractScreen(NinjaGame game) {
this.game = game;
createCamera();
/* Stage for actors */
stage = new Stage(new StretchViewport(NinjaGame.SCREEN_WIDTH, NinjaGame.SCREEN_HEIGHT, camera));
/* Batch for sprites */
spriteBatch = new SpriteBatch();
/* Stage takes user inputs */
Gdx.input.setInputProcessor(stage);
init();
}
protected abstract void init();
private void createCamera() {
/* Orthographic means like in CAD drawings */
camera = new OrthographicCamera();
camera.setToOrtho(false, NinjaGame.SCREEN_WIDTH, NinjaGame.SCREEN_HEIGHT);
camera.update();
}
/** Clean screen on black color between render frames */
private void clearScreen() {
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
}
#Override
public void render(float delta) {
clearScreen();
camera.update();
spriteBatch.setProjectionMatrix(camera.combined);
}
}
My player class:
public class Player extends Actor {
private static final int FRAME_COLS = 10, FRAME_ROWS = 1;
Animation<TextureRegion> walkAnimation;
Texture walkSheet;
private final static int STARTING_X = 50;
private final static int STARTING_Y = 50;
public Player(){
createIdleAnimation();
this.setPosition(STARTING_X, STARTING_Y);
}
private void createIdleAnimation() {
walkSheet = new Texture(Gdx.files.internal("sheets/ninja-idle-sheet.png"));
TextureRegion[][] tmp = TextureRegion.split(walkSheet,
walkSheet.getWidth() / FRAME_COLS,
walkSheet.getHeight() / FRAME_ROWS);
TextureRegion[] walkFrames = new TextureRegion[FRAME_COLS * FRAME_ROWS];
int index = 0;
for (int i = 0; i < FRAME_ROWS; i++) {
for (int j = 0; j < FRAME_COLS; j++) {
walkFrames[index++] = tmp[i][j];
}
}
walkAnimation = new Animation<TextureRegion>(0.025f, walkFrames);
}
#Override
public void act(float delta) {
super.act(delta);
}
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
}
}
UPDATE 1
NinjaGame class
public class NinjaGame extends Game{
public final static int SCREEN_WIDTH = 800;
public final static int SCREEN_HEIGHT = 480;
public final static String GAME_NAME = "ninja vs zombie";
private boolean paused;
#Override
public void create() {
this.setScreen(new GameScreen(this));
}
}
Make small modification in your Player class so that it draw player Animation frame. You need to overloaded draw method of Actor and draw texture of Player.
public class Player extends Actor {
private static final int FRAME_COLS = 10, FRAME_ROWS = 1;
Animation<TextureRegion> walkAnimation;
Texture walkSheet;
private final static int STARTING_X = 50;
private final static int STARTING_Y = 50;
TextureRegion reg;
float stateTime;
public Player(){
createIdleAnimation();
this.setPosition(STARTING_X, STARTING_Y);
}
private void createIdleAnimation() {
walkSheet = new Texture(Gdx.files.internal("sheets/ninja-idle-sheet.png"));
TextureRegion[][] tmp = TextureRegion.split(walkSheet,
walkSheet.getWidth() / FRAME_COLS,
walkSheet.getHeight() / FRAME_ROWS);
TextureRegion[] walkFrames = new TextureRegion[FRAME_COLS * FRAME_ROWS];
int index = 0;
for (int i = 0; i < FRAME_ROWS; i++) {
for (int j = 0; j < FRAME_COLS; j++) {
walkFrames[index++] = tmp[i][j];
}
}
walkAnimation = new Animation<TextureRegion>(0.025f, walkFrames);
stateTime = 0f;
reg=walkAnimation.getKeyFrame(0);
}
#Override
public void act(float delta) {
super.act(delta);
stateTime += delta;
reg = walkAnimation.getKeyFrame(stateTime,true);
}
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
batch.draw(reg,getX(),getY(),getWidth()/2,getHeight()/2,getWidth(),getHeight(),getScaleX(),getScaleY(),getRotation());
}
}
EDIT
You need to resize viewport of stage according to your device screen width and height so override resize method and also no need to call begin and end of spritebatch. you're using stage that having own SpriteBatch
class GameScreen extends AbstractScreen {
Player player;
public GameScreen(NinjaGame game) {
super(game);
init();
}
#Override
protected void init() {
initPlayer();
}
private void initPlayer() {
player = new Player();
player.setDebug(true);
stage.addActor(player);
}
#Override
public void render(float delta) {
super.render(delta);
update();
stage.draw();
}
private void update() {
stage.act();
}
#Override
public void resize(int width, int height){
stage.getViewport().update(width,height);
}
}
EDIT 2
private void initPlayer() {
player = new Player();
player.setSize(100,150);
player.setDebug(true);
stage.addActor(player);
}
Related
I currently have the class for my main character "Student", it has no behaviors except the left and right movements. I managed to make it so all the frames of my spritesheet will render, so I need help in drawing the first 3 frames (which are the walk cycle) when I press LEFT / RIGHT keys.
Here's the spritesheet: http://imgur.com/a/HHdm9
Edit: AND 2nd and 3rd rows when pressing UP and Down Keys.
Student Class
public class Student {
private Texture player;
private Animation<TextureRegion> playerAnimation;
private int pX;
private int pY;
private SpriteBatch batch;
private int HP;
public Student(float speed, int x, int y){
player = new Texture("student.png");
TextureRegion[][] tmp= TextureRegion.split(player,450/3,450/3);
TextureRegion[] character = new TextureRegion[9];
int index = 0;
for(int i=0; i <3; i++){
for(int j=0; j < 3; j++){
character[index++] = tmp[i][j];}
}
playerAnimation = new Animation<TextureRegion>(speed,character);
pX=x;
pY=y;
}
public SpriteBatch getBatch() {
return batch;
}
public void setBatch(SpriteBatch batch) {
this.batch = batch;
}
public void goLeft(){
pX-=5;
if(pX < -10){
pX = -10;
}
}
public void goRight(){
pX+=5;
}
public void renderStudent(float stateTime){
TextureRegion currentFrame = playerAnimation.getKeyFrame(stateTime,true);
batch.draw(currentFrame, (float) pX, (float) pY, 0, 0, currentFrame.getRegionWidth(),
currentFrame.getRegionHeight(),1.5f,1.5f,0);
}
public void dispose(){
player.dispose();
}
}
Main Class
public class HaxMain extends ApplicationAdapter {
SpriteBatch batch;
Texture bg;
float stateTime;
private Student student1;
private Guard mguard, fguard;
private Admin madmin, fadmin;
#Override
public void create () {
batch = new SpriteBatch();
bg = new Texture("Level1.png");
student1 = new Student(.5f, 100, 0);
student1.setBatch(batch);
}
#Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stateTime += Gdx.graphics.getDeltaTime();
if(Gdx.input.isKeyPressed(Input.Keys.LEFT)){
student1.goLeft();
//Code to render image to the left
}else if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)){
//Code to render image to the right
student1.goRight();
}
batch.begin(); /*default code*/
batch.draw(bg, 0, 0);
student1.renderStudent(stateTime);
batch.end();
}
#Override
public void dispose () {
batch.dispose();
bg.dispose();
student1.dispose();
}
}
You need to create Animation only for Running and use that animation to show your player is running left or right. You can flip TextureRegion according to direction of your player like this :
TextureRegion[] character;
boolean isRight;
public Student(float speed, int x, int y){
player = new Texture("student.png");
TextureRegion[][] tmp= TextureRegion.split(player,450/3,450/3);
character = new TextureRegion[9];
int index = 0;
for(int i=0; i <3; i++){
for(int j=0; j < 3; j++){
character[index++] = tmp[i][j];}
}
TextureRegion runningFrames[]=new TextureRegion[3];
for (int i=0;i<runningFrames.length;i++)
runningFrames[i]= character[i];
playerAnimation = new Animation<TextureRegion>(speed, runningFrames);
playerAnimation.setPlayMode(Animation.PlayMode.LOOP);
pX=x;
pY=y;
}
public void goLeft(){
pX-=5;
if(pX < -10){
pX = -10;
}
if(isRight){
isRight=false;
for (TextureRegion textureRegion:playerAnimation.getKeyFrames())
if(textureRegion.isFlipX()) textureRegion.flip(true,false);
}
}
public void goRight(){
pX+=5;
if(!isRight){
isRight=true;
for (TextureRegion textureRegion: playerAnimation.getKeyFrames())
if(!textureRegion.isFlipX()) textureRegion.flip(true,false);
}
}
Create another animation of other action and draw frame of animation using flag.
I'm trying to make a little game with the java game engine called libGDX. I already got the player but he can't jump and I dont know why.
This is my GameScreen class:
public class GameScreen extends ScreenManager{
//For the view of the game and the rendering
private SpriteBatch batch;
private OrthographicCamera cam;
//DEBUG
private Box2DDebugRenderer b2dr;
//World, Player and so on
private GameWorld world;
private Player player;
private Ground ground;
public static float w, h;
public GameScreen(Game game) {
super(game);
//vars
w = Gdx.graphics.getWidth();
h = Gdx.graphics.getHeight();
//view and rendering
batch = new SpriteBatch();
cam = new OrthographicCamera();
cam.setToOrtho(false, w/2, h/2);
//debug
b2dr = new Box2DDebugRenderer();
//world, bodies ...
player = new Player(world);
ground = new Ground(world);
}
#Override
public void pause() {
}
#Override
public void show() {
}
#Override
public void render(float delta) {
//clearing the screen
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//updating
update(Gdx.graphics.getDeltaTime());
//render
batch.setProjectionMatrix(cam.combined);
//debug
b2dr.render(world.getWorld(), cam.combined);
}
#Override
public void resize(int width, int height) {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
#Override
public void onKlick(float delta) {
}
public void update(float delta){
world.update(delta);
player.keyInput();
System.out.println(player.getBody().getPosition().x);
System.out.println(player.getBody().getPosition().y);
}
}
and this is my Player class:
public class Player {
public static Body body;
public static BodyDef def;
private FixtureDef fd;
//set form
private PolygonShape shape;
private GameScreen gs;
public Player(GameWorld world){
def = new BodyDef();
def.fixedRotation = true;
def.position.set(gs.w / 4, gs.h / 4);
def.type = BodyType.DynamicBody;
body = world.getWorld().createBody(def);
shape = new PolygonShape();
shape.setAsBox(32 / 2, 32 / 2);
fd = new FixtureDef();
fd.shape = shape;
fd.density = 30;
body.createFixture(fd);
shape.dispose();
}
public static Body getBody() {
return body;
}
public static BodyDef getDef() {
return def;
}
public static void keyInput(){
if(Gdx.input.isKeyPressed(Input.Keys.UP)){
body.applyForceToCenter(0, 900, false);
System.out.println("PRESSED");
}
}
}
this finally is my GameWorld class:
public class GameWorld {
public static World world;
public GameWorld(){
world = new World(new Vector2(0f, -10f), false);
}
public void update(float delta){
world.step(1 / 60f, 5, 2);
System.out.println("WorldUPDATE");
}
public static World getWorld() {
return world;
}
}
I don't know why the body can't jump please help me if you can (: Thank you in advance.
Force pushes the body each timestep, while gravity pushes it back down again. There is a function applyLinearImpulse() which pushes it like once with all its "force" before gravity interferention.
When you are using applyForceToCenter() body should be pushed up, but its very slow process compared to impulse.
I have been having a hell of a time trying to get this stage thing figured out. I basically want to draw a background image that fills the entire stage. The image is 1920x1080. The problem is that the image is being drawn at half the width and half of the height that it should be. The application is set to fullscreen and the inside corner of the image is at the center of the screen. I have tested the dimensions of the camera, the viewport, and the stage. All are correct. What am I doing wrong? By the way, I am using a custom game state manager to handle different screens so I apologize for the seemingly needless extra code.
Application.java
public class Application extends ApplicationAdapter {
public static boolean DEBUG = false;
public static final String TITLE = "Hexatan";
public static final int V_WIDTH = 720, V_HEIGHT = 480;
public static final float SCALE = 2.0f;
private GameStateManager gsm;
private OrthographicCamera camera;
private FitViewport vp;
private SpriteBatch batch;
private Stage stage;
private float w, h;
#Override
public void create() {
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
batch = new SpriteBatch();
camera = new OrthographicCamera();
camera.setToOrtho(true, w / SCALE, h / SCALE);
vp = new FitViewport(w, h, camera);
stage = new Stage(vp, batch);
gsm = new GameStateManager(this);
}
#Override
public void render() {
gsm.update(Gdx.graphics.getDeltaTime());
gsm.render();
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
gsm.dispose();
batch.dispose();
}
#Override
public void resize(int width, int height) {
gsm.resize((int)(width / SCALE), (int)(height / SCALE));
}
public SpriteBatch getBatch() {
return this.batch;
}
public OrthographicCamera getCamera(){
return this.camera;
}
public Stage getStage(){
return this.stage;
}
}
GameStateManager.java
public class GameStateManager {
private final Application app;
private Stack<GameState> states;
public enum State {
SPLASH, MAINMENU, GAME
}
public GameStateManager(final Application app){
this.app = app;
this.states = new Stack<GameState>();
this.setState(State.GAME);
}
public Application getApp(){
return app;
}
public void update(float delta){
states.peek().update(delta);
}
public void render(){
states.peek().render();
}
public void dispose(){
for(GameState gs : states){
gs.dispose();
}
states.clear();
}
public void resize(int w, int h){
states.peek().resize(w, h);
}
public void setState(State state){
if(states.size() >= 1) {
states.pop().dispose();
}
states.push(getState(state));
}
public GameState getState(State state){
return new GameLoop(this);
}
}
GameState.java
public abstract class GameState {
protected GameStateManager gsm;
protected Application app;
protected SpriteBatch batch;
protected OrthographicCamera camera;
public GameState(GameStateManager gsm){
this.gsm = gsm;
this.app = gsm.getApp();
batch = app.getBatch();
camera = app.getCamera();
}
public void resize(int w, int h){
camera.setToOrtho(true, w, h);
camera.update();
}
public abstract void update(float delta);
public abstract void render();
public abstract void dispose();
}
GameLoop.java
public class GameLoop extends GameState {
private boolean DEV_MODE = true;
private int WIDTH, HEIGHT;
private float mouseX, mouseY;
private Stage stage;
private Game game;
private Application app;
Texture hexture, water, island, robber, highlight, scoreboard;
BitmapFont font = new BitmapFont(Gdx.files.internal("core/assets/Playbill.fnt"));
BitmapFont devFont = new BitmapFont(Gdx.files.internal("core/assets/Arial.fnt"));
public GameLoop(GameStateManager gsm){
super(gsm);
app = gsm.getApp();
WIDTH = Gdx.graphics.getWidth();
HEIGHT = Gdx.graphics.getHeight();
stage = app.getStage();
System.out.println(stage.getCamera().position.x);
Gdx.input.setInputProcessor(stage);
water = new Texture(Gdx.files.internal("core/assets/img/water.png"));
island = new Texture(Gdx.files.internal("core/assets/img/island.png"));
highlight = new Texture(Gdx.files.internal("core/assets/img/highlightVertex.png"));
scoreboard = new Texture(Gdx.files.internal("core/assets/img/scoreboard.png"));
Image waterImg = new Image(new TextureRegionDrawable(new TextureRegion(water)));
waterImg.setWidth(WIDTH);
waterImg.setHeight(HEIGHT);
stage.addActor(waterImg);
}
#Override
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
app.getStage().act(Gdx.graphics.getDeltaTime());
app.getStage().draw();
}
#Override
public void update(float delta) {
}
#Override
public void dispose() {
}
#Override
public void resize(int w, int h){
camera.setToOrtho(true, w, h);
app.getStage().getViewport().update(w, h, true);
}
I want to draw a texture on a body, which is a box.
How do I convert the coordinates of the body to screen coordinates?
I know that the other way around is with camera.unproject(pos), is it similar to this?
I see a lot of people using constants such as WORLD_TO_SCREEN = 32, but I currently don't have that in my game. Is that a problem, and how can I implement it now? Because it seems like people that are using these factors can convert world to screen positions easily. I currently have a camera and an ExtendViewport
camera = new OrthographicCamera(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
viewport = new ExtendViewport(VIEWPORT_WIDTH, VIEWPORT_HEIGHT, camera);
camera.position.set(VIEWPORT_WIDTH/2, VIEWPORT_HEIGHT/2, 0f);
Viewport width and height are set to this
public static final int VIEWPORT_WIDTH = 20;
public static final int VIEWPORT_HEIGHT = 22;
I don't really know what I'm doing, I read documentation and read some tutorials, but if someone could give some explanation about these variables and the world_to_screen factor that would really help me out.
I also set APP_WIDTH=1280, APP_HEIGHT = 720
Do viewport width and height mean that for box2d my screen is 20 meters wide and 22 meters high?
(asking it again because I added a lot the question and I would really like to know these things)
[EDIT]
So I'm trying to draw a ground picture on the ground body
float x = stage.getGround().getX();
float y = stage.getGround().getY();
float w = stage.getGround().getWidth();
float h = stage.getGround().getHeight();
stage.act(delta);
stage.draw();
stage.updateCamera();
Texture texture = new Texture(Gdx.files.internal("ground.png"));
Sprite sprite = new Sprite(texture);
sprite.setSize(w, h);
sprite.setPosition(x-sprite.getWidth()/2, y-sprite.getHeight()/2);
But I don't see it anywhere
[EDIT 2]
Stage Class
public class Mission1Stage extends Stage{
public static final int VIEWPORT_WIDTH = 20;
public static final int VIEWPORT_HEIGHT = 22;
private World world;
private Ground ground;
private LeftWall leftWall;
private Rocket rocket;
private static final float TIME_STEP = 1 / 300f;
private float accumulator = 0f;
private OrthographicCamera camera;
private Box2DDebugRenderer renderer;
private Viewport viewport;
private SpriteBatch spriteBatch = new SpriteBatch();
private Vector3 touchPoint;
private ShapeRenderer shapeRenderer;
private Button boostButton;
private Skin boostSkin;
private Button boostLeftButton;
private Skin boostLeftSkin;
private Button boostRightButton;
private Skin boostRightSkin;
private Button resetButton;
private Skin resetSkin;
private Game game;
private boolean isTouched = false;
public Mission1Stage(Game game) {
setUpWorld();
renderer = new Box2DDebugRenderer();
shapeRenderer = new ShapeRenderer();
setupCamera();
setUpButtons();
addActor(new Background(ground));
}
private void setUpWorld() {
world = WorldUtils.createWorld();
setUpGround();
setUpRocket();
}
private void setUpGround() {
ground = new Ground(WorldUtils.createGround(world));
addActor(ground);
}
private void setUpLeftWall() {
leftWall = new LeftWall(WorldUtils.createLeftWall(world));
}
private void setUpRocket() {
rocket = new Rocket(WorldUtils.createRocket(world));
addActor(rocket);
}
private void setupCamera() {
camera = new OrthographicCamera(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
viewport = new ExtendViewport(VIEWPORT_WIDTH, VIEWPORT_HEIGHT, camera);
camera.position.set(VIEWPORT_WIDTH/2, VIEWPORT_HEIGHT/2, 0f);
camera.update();
}
private void setUpButtons() {
boostSkin = new Skin(Gdx.files.internal("skin/flat-earth-ui.json"));
boostButton = new Button(boostSkin);
boostButton.setSize(80,80);
boostButton.setPosition(Gdx.graphics.getWidth()-boostButton.getWidth()*2,0);
boostButton.setTransform(true);
boostButton.scaleBy(0.5f);
Gdx.input.setInputProcessor(this);
addActor(boostButton);
boostLeftSkin = new Skin(Gdx.files.internal("skin/flat-earth-ui.json"));
boostLeftButton = new Button(boostLeftSkin);
boostLeftButton.setSize(100, 100);
boostLeftButton.setPosition(0, 0);
addActor(boostLeftButton);
boostRightSkin = new Skin(Gdx.files.internal("skin/flat-earth-ui.json"));
boostRightButton = new Button(boostRightSkin);
boostRightButton.setSize(100, 100);
boostRightButton.setPosition(boostLeftButton.getWidth(), 0);
addActor(boostRightButton);
resetSkin = new Skin(Gdx.files.internal("skin/flat-earth-ui.json"));
resetButton = new Button(resetSkin);
resetButton.setSize(100, 100);
resetButton.setPosition(Gdx.graphics.getWidth()-100, Gdx.graphics.getHeight()-100);
addActor(resetButton);
}
#Override
public void act(float delta) {
super.act(delta);
handleInput();
accumulator += delta;
while(accumulator >= delta) {
world.step(TIME_STEP, 6, 2);
accumulator -= TIME_STEP;
}
}
#Override
public void draw() {
super.draw();
renderer.render(world, camera.combined);
float x = getGround().getBody().getPosition().x;
float y = getGround().getBody().getPosition().y;
float w = getGround().getWidth() * 2;
float h = getGround().getHeight() * 2;
spriteBatch.setProjectionMatrix(getCamera().combined);
Texture texture = new Texture(Gdx.files.internal("ground.png"));
Sprite sprite = new Sprite(texture);
sprite.setSize(w, h);
sprite.setPosition(x-sprite.getWidth()/2, y-sprite.getHeight()/2);
spriteBatch.begin();
sprite.draw(spriteBatch);
spriteBatch.end();
}
public void handleInput() {
if(boostButton.isPressed()) {
rocket.boost();
}
if(boostLeftButton.isPressed()) {
rocket.turnLeft();
}
if(boostRightButton.isPressed()) {
rocket.turnRight();
}
if(resetButton.isPressed()) {
}
}
public boolean resetScreen() {
if(resetButton.isPressed()) return true;
return false;
}
public void updateCamera() {
}
public Ground getGround() {
return ground;
}
public void resize(int width, int height) {
viewport.update(width, height);
camera.position.x = VIEWPORT_WIDTH / 2;
camera.position.y = VIEWPORT_HEIGHT /2;
}
private void translateScreenToWorldCoordinates(int x, int y) {
getCamera().unproject(touchPoint.set(x, y, 0));getCamera();
}
}
Screen class
public class Mission1Screen implements Screen{
private Game game;
private Mission1Stage stage;
private SpriteBatch spriteBatch = new SpriteBatch();
private Skin boostSkin;
private Button boostButton;
public Mission1Screen(Game game) {
this.game = game;
stage = new Mission1Stage(game);
}
#Override
public void show() {
}
#Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if(stage.resetScreen()) {
game.setScreen(new Mission1Screen(game));
}
stage.act(delta);
stage.draw();
stage.updateCamera();
}
#Override
public void resize(int width, int height) {
stage.resize(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
}
[EDIT 3]
public class Main extends Game {
#Override
public void create () {
this.setScreen(new Mission1Screen(this));
}
#Override
public void render () {
super.render();
}
#Override
public void dispose () {
}
}
We mostly use Pixel to meter conversion because box2d best works in meters (0-10) but you can avoid this conversion by using small worldwidth and height of your viewport. I mostly prefer 48 and 80 as viewport width and height.
You can use unproject(vector3) method of camera that translate a point given in screen coordinates to world space. I am using this method in touchdown because I get screen coordinate as parameter then I need to convert it into camera world space so that I can generate object at a particular position in world.
public class MyGdxTest extends Game implements InputProcessor {
private SpriteBatch batch;
private ExtendViewport extendViewport;
private OrthographicCamera cam;
private float w=20;
private float h=22;
private World world;
private Box2DDebugRenderer debugRenderer;
private Array<Body> array;
private Vector3 vector3;
#Override
public void create() {
cam=new OrthographicCamera();
extendViewport=new ExtendViewport(w,h,cam);
batch =new SpriteBatch();
Gdx.input.setInputProcessor(this);
world=new World(new Vector2(0,-9.8f),true);
array=new Array<Body>();
debugRenderer=new Box2DDebugRenderer();
vector3=new Vector3();
BodyDef bodyDef=new BodyDef();
bodyDef.type= BodyDef.BodyType.StaticBody;
bodyDef.position.set(0,0);
Body body=world.createBody(bodyDef);
ChainShape chainShape=new ChainShape();
chainShape.createChain(new float[]{1,1,55,1});
FixtureDef fixtureDef=new FixtureDef();
fixtureDef.shape=chainShape;
fixtureDef.restitution=.5f;
body.createFixture(fixtureDef);
chainShape.dispose();
}
#Override
public void render() {
super.render();
Gdx.gl.glClearColor(0,1,1,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
world.step(1/60f,6,2);
batch.setProjectionMatrix(cam.combined);
batch.begin();
world.getBodies(array);
for (Body body:array){
if(body.getUserData()!=null) {
Sprite sprite = (Sprite) body.getUserData();
sprite.setPosition(body.getPosition().x-sprite.getWidth()/2, body.getPosition().y-sprite.getHeight()/2);
sprite.setRotation(body.getAngle()*MathUtils.radDeg);
sprite.draw(batch);
}
}
batch.end();
debugRenderer.render(world,cam.combined);
}
#Override
public void resize(int width, int height) {
super.resize(width,height);
extendViewport.update(width,height);
cam.position.x = w /2;
cam.position.y = h/2;
cam.update();
}
private void createPhysicsObject(float x,float y){
float sizeX=2,sizeY=2;
BodyDef bodyDef=new BodyDef();
bodyDef.position.set(x,y);
bodyDef.type= BodyDef.BodyType.DynamicBody;
Body body=world.createBody(bodyDef);
PolygonShape polygonShape=new PolygonShape();
polygonShape.setAsBox(sizeX,sizeY);
FixtureDef fixtureDef=new FixtureDef();
fixtureDef.shape=polygonShape;
fixtureDef.restitution=.2f;
fixtureDef.density=2;
body.createFixture(fixtureDef);
body.setFixedRotation(false);
polygonShape.dispose();
Sprite sprite=new Sprite(new Texture("badlogic.jpg"));
sprite.setSize(2*sizeX,2*sizeY);
sprite.setPosition(x-sprite.getWidth()/2,y-sprite.getHeight()/2);
sprite.setOrigin(sizeX,sizeY);
body.setUserData(sprite);
}
#Override
public void dispose() {
batch.dispose();
debugRenderer.dispose();
world.dispose();
}
#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) {
vector3.set(screenX,screenY,0);
Vector3 position=cam.unproject(vector3);
createPhysicsObject(vector3.x,vector3.y);
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(int amount) {
return false;
}
}
Player Class
public class Player extends Sprite implements InputProcessor {
public Vector2 velocity = new Vector2();
private float speed = 500;
public Rectangle rectangle;
public Player(Sprite sprite){
super(sprite);
this.rectangle = sprite.getBoundingRectangle();
}
public void draw(SpriteBatch spriteBatch){
update(Gdx.graphics.getDeltaTime());
super.draw(spriteBatch);
}
public void update(float delta) {
rectangle = new Rectangle(getX() + velocity.x * delta,0,rectangle.getWidth(),rectangle.getWidth());
setX(getX() + velocity.x * delta);
}
}
PlayScreen Class
public class PlayScreen implements Screen {
private Player player;
private OrthographicCamera camera;
private OrthogonalTiledMapRenderer renderer;
private TiledMap map;
private Rectangle rightRectangle, leftRectangle, playerRectangle;
//private ShapeRenderer shapeRenderer;
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderer.render();
renderer.getSpriteBatch().begin();
player.draw(renderer.getSpriteBatch());
renderer.getSpriteBatch().end();
//shapeRenderer.begin(ShapeType.Filled);
//shapeRenderer.setColor(0, 1, 0, 1);
//shapeRenderer.rect(
// player.getX() + player.velocity.x * delta, 0,
// player.rectangle.getWidth(), player.rectangle.getHeight());
//shapeRenderer.end();
}
#Override
public void resize(int width, int height) {
camera.viewportWidth = width;
camera.viewportHeight = height;
camera.update();
}
#Override
public void show() {
camera = new OrthographicCamera();
map = new TiledMap();
renderer = new OrthogonalTiledMapRenderer(map);
//shapeRenderer = new ShapeRenderer();
player = new Player(new Sprite(new Texture("img/player.png")));
rightRectangle = new Rectangle(1280,0,0,720);
leftRectangle = new Rectangle(0,0,0,720);
boolean wallLeft = leftRectangle.overlaps(player.rectangle);
boolean wallRight = rightRectangle.overlaps(player.rectangle);
if(wallLeft){
System.out.println("wallLeft Overlap");
player.velocity.x = 0;
}
else if(wallRight){
System.out.println("wallRight Overlap");
player.velocity.x = 0;
}
player.setPosition(
Gdx.graphics.getWidth()/2f - player.getWidth()/2f,
Gdx.graphics.getHeight()/2f - player.getHeight()/2f
- Gdx.graphics.getHeight()/5f);
}
}
Doesn't seem to be colliding correctly. The rightRectangle and leftRectangle are my screen side bounds. When I use the shapeRenderer, it produces the ShapeRendered rectangle and it will follow my player around. However, I believe that my player.rectangle is not moving at all for some reason, resulting in it not colliding with my side bounds. Any help would be greatly appreciated!
rightRectangle = new Rectangle(1280,0,0,720);
leftRectangle = new Rectangle(0,0,0,720);
A Rectangle is defined as Rectangle(x, y, width, height). It looks like you are trying to define it incorrectly as Rectangle(x1, y1, x2, y2). In the above, you have created two rectangles of 0 width.