libgdx making a touch event - java

I'm currently following this book to create my libgdx game..
So far, i have these classes to create my game :
AbstractGameScreen.java - that Implements libgdx's Screen
AbstractGameObject.java - that extends libgdx's Actor
GamePlay.java - which is my game screen
GameController.java - where i init my game objects
GameRenderer.java - when i render all my objects
Assets.java - a class that organizes my game assets
Ring.java - an object in my game
And here is my code..
AbstractGameScreen
public abstract class AbstractGameScreen implements Screen {
protected Game game;
public AbstractGameScreen(Game game){
this.game = game;
}
public abstract void render(float deltaTime);
public abstract void resize(int width, int height);
public abstract void show();
public abstract void hide();
public abstract void pause();
public void resume(String bg, String ring){
Assets.instance.init(new AssetManager(), bg, ring); // kosongin, jadinya default
}
public void dispose(){
Assets.instance.dispose();
}
}
AbstractGameObject
public abstract class AbstractGameObject extends Actor{ //implements EventListener{ //extends Sprite{
public Vector2 position;
public Vector2 dimension;
public Vector2 origin;
public Vector2 scale;
public float rotation;
public AbstractGameObject(){
position = new Vector2();
dimension = new Vector2(1, 1);
origin = new Vector2();
scale = new Vector2(1, 1);
rotation = 0;
}
public void update (float deltaTime){
}
public abstract void render(SpriteBatch batch);
}
GamePlay
public class GamePlay extends AbstractGameScreen implements InputProcessor{
private GameController gameController;
private GameRenderer gameRenderer;
private String dummyBg, dummyRing;
private boolean paused;
// for touch purposes
private static final int appWidth = Constants.VIEWPORT_GUI_WIDTH_INT;
private static final int appHeight = Constants.VIEWPORT_GUI_HEIGHT_INT;
public GamePlay(Game game) {
super(game);
// still dummy.. nantinya ngambil dari database nya
this.dummyBg = "bg-default";
this.dummyRing = "ring-default";
Gdx.input.setInputProcessor(this);
}
#Override
public void render(float deltaTime) {
if(!paused){
gameController.update(deltaTime);
}
//Gdx.gl.glClearColor(0x64 / 255.0f, 0x95 / 255.0f,0xed / 255.0f, 0xff / 255.0f);
//Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// render game nya
gameRenderer.render();
}
#Override
public void resize(int width, int height) {
gameRenderer.resize(width, height);
}
#Override
public void show() {
Assets.instance.init(new AssetManager(), "bg-default", "ring-default");
Gdx.app.log("GamePlay", "After show() method");
gameController = new GameController(game);
gameRenderer = new GameRenderer(gameController);
Gdx.input.setCatchBackKey(true);
}
#Override
public void hide() {
gameRenderer.dispose();
Gdx.input.setCatchBackKey(false);
}
#Override
public void dispose(){
gameRenderer.dispose();
Assets.instance.dispose();
}
#Override
public void pause() {
paused = true;
}
#Override
public void resume() {
super.resume(this.dummyBg, this.dummyRing);
//Assets.instance.init(new AssetManager(), this.dummyBg, this.dummyRing);
paused = false;
}
#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) {
return true;
}
// for touch purposes
private float getCursorToModelX(int screenX, int cursorX) {
return (((float)cursorX) * appWidth) / ((float)screenX);
}
private float getCursorToModelY(int screenY, int cursorY) {
return ((float)(screenY - cursorY)) * appHeight / ((float)screenY) ;
}
#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;
}
}
GameController
public class GameController extends InputAdapter{
// game objects
public Array<Tiang> tiangs;
public Array<Ring> rings;
//private Game game;
// game decorations
public Background background; public Sprite[] testSprite;
private Game game;
public GameController(Game game){
this.game = game;
init();
}
private void init(){
// preparing variables
rings = new Array<Ring>();
tiangs = new Array<Tiang>();
initObjects();
initDecorations();
initGui();
}
private void initObjects(){
AbstractGameObject obj = null;
obj = new Ring(1, "default");
obj.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
//super.clicked(event, x, y);
Gdx.app.log("tag", "test clisk");
}
});
rings.add((Ring)obj);
}
private void initDecorations(){
}
private void initGui(){
}
private void handleInput(float deltatime){
}
public void update(float deltaTime){
//if(Gdx.input.isTouched()){
// Gdx.app.log("update", "screen touched");
//}
}
}
GameRenderer
public class GameRenderer implements Disposable{
private OrthographicCamera camera;
private GameController controller;
private SpriteBatch batch;
public GameRenderer(GameController controller){
this.controller = controller;
init();
}
private void init(){
batch = new SpriteBatch();
camera = new OrthographicCamera(Constants.VIEWPORT_WIDTH, Constants.VIEWPORT_HEIGHT); //diambil dari class "Constants" (di package util)
camera.position.set(0, 0, 0);
camera.update();
}
public void resize(int width, int height){
camera.viewportWidth = (Constants.VIEWPORT_HEIGHT / height) * width;
camera.update();
}
public void render(){
renderGui();
renderDecorations();
renderObjects();
}
private void renderGui(){
}
private void renderDecorations(){
}
private void renderObjects(){
batch.setProjectionMatrix(camera.combined);
batch.begin();
for(Ring rings : controller.rings){
rings.render(batch);
}
batch.end();
}
#Override
public void dispose() {
}
}
Assets
public class Assets implements Disposable, AssetErrorListener{
public static final String TAG = Assets.class.getName();
public static final Assets instance = new Assets();
private AssetManager assetManager;
// inner class objects
public AssetTiang tiang;
public AssetBackgroud bg;
public AssetTombol tombol;
public AssetTombolBg tombolBg;
public AssetRing ring;
//singleton pattern, buat mencegah instansiasi dari class yang lain
private Assets(){}
//public void init(AssetManager assetManager){
public void init(AssetManager assetManager, String jenisBg, String jenisRing){
this.assetManager = assetManager;
assetManager.setErrorListener(this);
//load texture atlas yang udah dibikin pake TexturePacker nya (liat ebook page 167)
assetManager.load(Constants.TEXTURE_ATLAS_OBJECTS, TextureAtlas.class);
assetManager.load(Constants.TEXTURE_ATLAS_DECORATION, TextureAtlas.class);
assetManager.load(Constants.TEXTURE_ATLAS_GUI, TextureAtlas.class);
// inner class objects
tiang = new AssetTiang(atlasObject);
bg = new AssetBackgroud(atlasDecoration, jenisBg);
tombol = new AssetTombol(atlasGui);
tombolBg = new AssetTombolBg(atlasDecoration);
ring = new AssetRing(atlasObject, jenisRing);
}
#Override
public void error(AssetDescriptor asset, Throwable throwable) {
// TODO Auto-generated method stub
}
#Override
public void dispose(){
assetManager.dispose();
}
public class AssetRing{
public final AtlasRegion ring;
// jenis ring dimasukin disini, karena jenis ring bisa diganti-ganti sesuai yang dipilih
public AssetRing(TextureAtlas atlas, String jenisRing){
if(!jenisRing.equals("")){
ring = atlas.findRegion(jenisRing);
}
else{
ring = atlas.findRegion("ring-default");
}
}
}
}
And finally, Ring (Object)
public class Ring extends AbstractGameObject{
private TextureRegion ringOverLay;
private float length;
// jenis ring nya
public String jenis;
public Ring(float length, String jenis){
init();
setLength(length);
setJenis(jenis);
}
// getters
public float getLength(){
return this.length;
}
public String getJenis(){
return this.jenis;
}
public Vector2 getPosition(){
return position;
}
// setters
public void setLength(float length){
this.length = length;
dimension.set(5.0f, 1.0f);
}
public void setJenis(String jenis){
this.jenis = jenis;
}
public void setPosition(float x, float y){
position.set(x, y);
}
private void init(){
ringOverLay = Assets.instance.ring.ring; // Assets.instance.namaobjek.atlasregion
origin.x = dimension.x/2; // -dimension.x/2;
origin.y = dimension.y/2;
position.x = -5.0f;
position.y = -2.5f;
}
#Override
public void render(SpriteBatch batch) {
TextureRegion reg = null;
reg = ringOverLay;
batch.draw(reg.getTexture(), position.x, position.y, origin.x, origin.y, dimension.x, dimension.y, scale.x, scale.y, rotation, reg.getRegionX(), reg.getRegionY(), reg.getRegionWidth(), reg.getRegionHeight(), false, false);
}
}
So what's the problem? Okay, the problem is i cannot make the Ring (game object) become clickable.. the Ring is extending AbstractGameObject (which is Actor), and, in the GameController i've add a ClickListener to the Ring object, but the object still unclickable..
Please, anyone tell me what's my mistake?

You're using your Actor (in your case, the Ring) incorrectly: Actors are part of Scene2d, and as such must follow precise rules to work correctly.
To answer your question more specifically, Ring needs to be added to a Stage which itself is an InputProcessor. The Stage is responsible to distribute the input events (such as touch events) to the its Actors. Without defining a Stage your Actors will not respond to any input events.
Read up on Scene2d from the link above. This video tutorial is also helpful.

Related

Accessing to inner class in java

I'm a beginner in libGdx and I'm making a simple game.
I wrote a nested class. As you can see here:
public class classes{
public class GameObject{
//declaring section
private Texture texture;
private Texture[] spawnAnimation;
private Texture[] deathAnimation;
private Texture[] damageAnimation;
private Texture[] moveAnimation;
private Texture[] fightAnimation;
private Texture[] talkAnimation;
private SpriteBatch batch = new SpriteBatch();
private float width, height;
private float x, y;
private Sound spawnSound, touchSound, deathSound, objSound, moveSound, fightSound;
public GameObject(Texture txtr, float width, float height, float x, float y) {
this.texture = txtr;
this.width = width;
this.height = height;
this.x = x;
this.y = y;
}
//this method checks wether our game object is over an other object
public boolean isOver(GameObject obj){
if(((this.x >= obj.x) && (this.x <= (obj.x + obj.width))) && ((this.y >= obj.y) && (this.y <= (obj.y + obj.height))))
return true;
return false;
}
//this method sets the object bounds
public void setBounds(float width, float height, float x, float y){
this.width = width;
this.height = height;
this.x = x;
this.y = y;
}
//this method draws the object
public void draw(){
batch.draw(this.texture, this.width, this.height, this.x, this.y);
}
//animation setting section
public void setSpawnAnimation(Texture[] texture){
this.spawnAnimation = texture;
}
public void setDeathAnimation(Texture[] texture){
this.deathAnimation = texture;
}
public void setDamageAnimation(Texture[] texture){
this.damageAnimation = texture;
}
public void setMoveAnimation(Texture[] texture){
this.moveAnimation = texture;
}
public void setFightAnimation(Texture[] texture){
this.fightAnimation = texture;
}
public void setTalkAnimation(Texture[] texture){
this.talkAnimation = texture;
}
//sounds setting section
public void setSpawnSound(Sound sound){
this.spawnSound = sound;
}
public void setTouchSound(Sound sound){
this.touchSound = sound;
}
public void setDeathSound(Sound sound){
this.deathSound = sound;
}
public void setObjSound(Sound sound){
this.objSound = sound;
}
public void setMoveSound(Sound sound){
this.moveSound = sound;
}
public void setFightSound(Sound sound){
this.fightSound = sound;
}
//animation and behavior section
public void spawn(){
batch.begin();
for(int i=0;i<=this.spawnAnimation.length;i++){
this.texture = this.spawnAnimation[i];
this.draw();
try
{
Thread.sleep(0, 1);
}
catch (InterruptedException e)
{}
}
batch.end();
}
public void die(Texture[] deathTexture){
}
}
}
I went to the other file, in the other class, and I tried to set the object texture
public class MyGdxGame implements ApplicationListener{
Texture texture;
SpriteBatch batch;
classes.GameObject gun;
#Override
public void create()
{
batch = new SpriteBatch();
gun = new classes.GameObject(new Texture(Gdx.files.internal("gun.png")), 0, 0, 300, 300);
}
#Override
public void render()
{
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.end();
}
#Override
public void dispose()
{
}
#Override
public void resize(int width, int height)
{
}
#Override
public void pause()
{
}
#Override
public void resume()
{
}
}
once I try to access it. I face this error: aan instance for an enclosing class is required
note: I'm making this game for android. using AIDE ide which offers developing apps and games directly on your phone.
Inner classes that are declared without the keyword static are tethered to the outer class they exist in.
To fix
public static class GameObject{
Why would you want an inner class without static? Here's an example
public class Game {
private Data gameData;
class MyListener {
public void receiveNewData(Data newData) {
//update gameData with the new data
}
}
}
If MyListener was static, it would not be able to access Game's gameData

libGDX sprite sheet 2d animation

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);
}

Why are my actors not being drawn with the correct bounds in LibGDX?

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);
}

libgdx world to screen pos and factors

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;
}
}

How to draw a Sprite in Libgdx/Android?

im working on a libgdx Game where you avoid Asteroids with a spaceship. When i launch my project i only see a white Screen :( Here u can see a big part of my code to understand what iam trying to do.
Main Class:
package com.me.mygdxgame;
import screen.MenuScreen;
import screen.ScreenManager;
public class MyGdxGame implements ApplicationListener {
SpriteBatch batch;
public static int WIDTH = 800 , HEIGHT = 480; // resolution
#Override
public void create() {
batch = new SpriteBatch();
ScreenManager.setScreen(new MenuScreen());
}
#Override
public void dispose() {
if(ScreenManager.getCurrentScreen() != null){
ScreenManager.getCurrentScreen().dispose();
}
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if(ScreenManager.getCurrentScreen() != null){
ScreenManager.getCurrentScreen().update();
}
if(ScreenManager.getCurrentScreen() != null){
ScreenManager.getCurrentScreen().render(batch);
}
}
Screen class:
package screen;
public abstract class Screen {
public abstract void create();
public abstract void render(SpriteBatch batch);
public abstract void update();
public abstract void resize(int width, int height);
public abstract void dispose(int width, int height);
public abstract void dispose();
public abstract void pause();
public abstract void resume();
}
ScreenManager:
public class ScreenManager {
private static Screen currentScreen;
public static void setScreen(Screen screen){
if(currentScreen != null){
currentScreen.dispose();
currentScreen = screen;
currentScreen.create();
}
}
public static Screen getCurrentScreen() {
return currentScreen;
}
}
MenuScreen:
public class MenuScreen extends Screen {
private OrthoCamera cam;
private Spaceship spaceship;
#Override
public void create() {
// TODO Auto-generated method stub
cam = new OrthoCamera();
spaceship = new Spaceship();
}
#Override
public void render(SpriteBatch batch) {
// TODO Auto-generated method stub
batch.setProjectionMatrix(cam.combined);
batch.begin();
spaceship.render(batch);
batch.end();
}
#Override
public void update() {
// TODO Auto-generated method stub
cam.update();
spaceship.update();
}
Spaceship Class:
public class Spaceship extends Entity {
Texture texture;
Sprite sprite;
public Spaceship() {
texture = new Texture("spritesheet.png");
texture.setFilter(TextureFilter.Linear, TextureFilter.Linear );
TextureRegion region = new TextureRegion(texture, 0, 312, 258, 144);
sprite = new Sprite(region);
sprite.setSize(sprite.getWidth(), sprite.getHeight());
sprite.setOrigin(sprite.getWidth() / 2, sprite.getHeight() / 2);
sprite.setPosition(-sprite.getWidth() / 2, -sprite.getHeight() / 2);
}
public void update() {
if (Gdx.input.isTouched()) {
pos.x = Gdx.input.getX() - MyGdxGame.WIDTH / 2;
pos.y = -Gdx.input.getY() + MyGdxGame.HEIGHT / 2;
}
}
#Override
public void render(SpriteBatch batch) {
sprite.draw(batch);
}
The problem should be in your ScreenManager. The method setScreen is incapable of initializing a screen if there is no previous screen:
public static void setScreen(Screen screen){
if(currentScreen != null){
currentScreen.dispose();
currentScreen = screen;
currentScreen.create();
}
}
Should be:
public static void setScreen(Screen screen) {
if (currentScreen != null){
currentScreen.dispose();
}
currentScreen = screen;
currentScreen.create();
}

Categories

Resources