I'm developping games with LIBGDX on ANDROID. Today, i've tried to generate one of my project in a HTML5 version. I put the content of the WAR folder on my server. All is fine except 2 things. I'll present you here just one of these 2 issues.
The problem : when a texture has to be disposed (by the call of its method dispose()), i get a BufferUnderflowException. It happens everytime.
Here is the sample code which is automatically generated when you create a new project :
public class TexDispose implements ApplicationListener
{
private OrthographicCamera camera;
private SpriteBatch batch;
private Texture texture;
#Override
public void create() {
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera = new OrthographicCamera(1, h/w);
batch = new SpriteBatch();
texture = new Texture(Gdx.files.internal("data/libgdx.png"));
Gdx.input.setInputProcessor(this);
}
#Override
public void dispose() {
batch.dispose();
texture.dispose(); // HERE IS THE ERROR
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.end();
}
#Override
public void resize(int width, int height) {
}
}
Has one of you already met this issue..? If yes, how can i avoid that (except by not disposing anything lol) ?
Thank you ! ;)
Related
i am making a game in libgdx. I have a super class Monster with child classes of that monster (warrior,mage,..). I would like to render this Monster class (actually his child) in playScreen class. Each class has its own animaton and textures, damage/health values. How do i do that? In which class do i define position for rendering, animation of that monster? in child classes, super class or in playScreen? My current code is here:
public class Monster {
public Animation monster;
public TextureAtlas atlas;
public int health;
public int damage;
public Monster(){
atlas = new TextureAtlas(Gdx.files.internal("mons1.txt"));
monster = new Animation(1/15f, atlas.getRegions());
}
Child class:
public class Mage extends Monster {
public Mage(int health,int damage, Animation animation){
super(health, damage, animation);
}
PlayScreen class:
public class PlayScreen implements Screen, InputProcessor {
private SpriteBatch batch;
public TextureAtlas atlas;
TextureRegion region;
private int height;
private Viewport viewport;
private Camera camera;
private int width;
private float elapsedTime = 0;
private Handler h;
private Stage stage;
private InputProcessor processor;
public PlayScreen(Handler h){
this.h = h;
batch = h.batch;
camera = h.camera;
viewport = h.viewport;
height = h.height;
width = h.width;
region = new TextureRegion();
stage = new Stage(viewport,batch);
stateTime = 0f;
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.end();
}
Create base class that will have methods for all entities in your world.
For example let's give in name Entity. It will have only fields and methods that base for all monsters, creatures, player also, etc.
class Entity {
protected int x; // use getters/setters to get/change these fields
protected int y;
protected int width;
protected int height;
protected Texture texture;
public Entity(Texture texture, int x, int y, int width, int height) {
this.texture = texture;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
void draw(SpriteBatch batch) {
batch.draw(texture, x, y, width, height);
}
}
Now you can create base entity that will simple draw one texture always.
How to animate it? Create inheritor.
class AnimatedEntity extends Entity{
protected float stateTimer = 0f; // use getters/setters to get/change these fields
protected Animation animation;
public AnimatedEntity(Animation animation, int x, int y, int width, int height) {
super(animation.getKeyFrames(0), x, y, width, height); // calls parent constructor
this.animation = animation;
}
#Override
void draw(SpriteBatch batch) {
texture = animation.getKeyFrame(stateTimer); // texture from parent visible here
super(batch); // calls draw method from Entity
}
}
Now you can extend Monster from AnimatedEntity class. To add attack method for example. Hope you got it. I mean principe.
How to draw all my entities?
Outside constructor :
ArrayList<Entity> entities;
In constructor :
entities = new ArrayList<>();
AnimatedEntity mage = new AnimatedEntity(someAnimation, x, y, width, height);
entities.add(mage);
In render(..) :
for (e in entities) {
e.draw(batch);
}
You could make a render method in the monster and/or child class. It depends if all monsters are going to be rendered the same way, either way it is useful to make an empty render method in the monster class nonetheless (so we do not have to cast classes in future).
public class Monster {
public Animation monster;
public TextureAtlas atlas;
public int health;
public int damage;
public Monster(){
atlas = new TextureAtlas(Gdx.files.internal("mons1.txt"));
monster = new Animation(1/15f, atlas.getRegions());
}
public void render(SpriteBatch batch) {
// here you will use your animation and textureAtlas to render
}
You then call the render method in your main render in PlayScreen, make sure to put the batch as parameter.
If you have one monster you wish to render differently, you could override the monster's render method like this:
public class Mage extends Monster {
public Mage(int health,int damage, Animation animation){
super(health, damage, animation);
}
#Override
public void render(SpriteBatch batch) {
// your mage specific render
// calling super.render(batch) will call its superclass' render
}
I hope you know how to use your animation to actually render it now, otherwise here is a useful link. Good luck!
I am trying to make a sprite move, rotate and resize by using MoveToAction, RotateToAction and ScaleToAction. The first two works fine, but I have a problem with ScaleToAction.
I add the action to the Actor just like I do with the two that works. I think the problem might be in the #Override? When I run the code the sprite moves and rotates but no scaling is done.
I tried to use sprite.setscale as suggested in the answer below, but still no luck. I add the code from the class here:
public class Prizes extends Actor {
private LearnToRead game;
private TextureAtlas atlas;
private TextureRegion prizepic;
private Sprite sprite;
private RotateToAction rta;
private ScaleToAction sta;
private MoveToAction mta;
public Prizes(LearnToRead game) {
this.game = game;
atlas = new TextureAtlas("prizes.pack");
prizepic = atlas.findRegion("haxhatt");
sprite = new Sprite(prizepic);
sprite.setPosition(450 - sprite.getWidth() / 2, 450 * Gdx.graphics.getHeight() / Gdx.graphics.getWidth() - sprite.getHeight() / 2);
//setBounds(sprite.getX(), sprite.getY(), sprite.getWidth(), sprite.getHeight());
setTouchable(Touchable.enabled);
rta = new RotateToAction();
sta = new ScaleToAction();
mta = new MoveToAction();
rta.setRotation(180f);
sta.setScale(2f);
mta.setPosition(0, 0);
mta.setDuration(5f);
rta.setDuration(5f);
sta.setDuration(5f);
Prizes.this.addAction(rta);
Prizes.this.addAction(sta);
Prizes.this.addAction(mta);
}
#Override
public void draw(Batch batch, float parentAlpha) {
sprite.draw(batch);
}
#Override
public void act(float delta) {
super.act(delta);
}
#Override
protected void positionChanged() {
sprite.setPosition(getX(), getY());
}
#Override
protected void rotationChanged() {
sprite.setRotation(getRotation());
}
#Override
protected void sizeChanged() {
sprite.setScale(getScaleX(), getScaleY());
}
}
If also tried to remove sprite and just use the TextureRegion, but didn't get it to work. The texture is drawn, but not moving. I post that code as well, but I do confess that I am quite uncertain about this code:
public class Prizes extends Actor {
private LearnToRead game;
private TextureAtlas atlas;
private TextureRegion prizepic;
private RotateToAction rta;
private ScaleToAction sta;
private MoveToAction mta;
public Prizes(LearnToRead game) {
this.game = game;
atlas = new TextureAtlas("prizes.pack");
prizepic = atlas.findRegion("haxhatt");
Prizes.this.setBounds(450 - Prizes.this.getX(), Prizes.this.getY(), Prizes.this.getWidth(), Prizes.this.getHeight());
setTouchable(Touchable.enabled);
rta = new RotateToAction();
sta = new ScaleToAction();
mta = new MoveToAction();
rta.setRotation(180f);
sta.setScale(2f);
mta.setPosition(0, 0);
mta.setDuration(5f);
rta.setDuration(5f);
sta.setDuration(5f);
Prizes.this.addAction(rta);
Prizes.this.addAction(sta);
Prizes.this.addAction(mta);
}
#Override
public void draw(Batch batch, float parentAlpha) {
game.batch.begin();
game.batch.draw(prizepic, Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2);
game.batch.end();
}
#Override
public void act(float delta) {
super.act(delta);
}
#Override
protected void positionChanged() {
Prizes.this.setPosition(getX(), getY());
}
#Override
protected void rotationChanged() {
Prizes.this.setRotation(getRotation());
}
#Override
protected void sizeChanged() {
Prizes.this.setScale(getScaleX(), getScaleY());
}
}
Maybe someone has a good idea about what I am doing wrong?
Use sprite.setScale instead of sprite.scale. The difference is that you are setting it a specific value instead of multiplying the current scale by some value.
But it is redundant to use Sprite with Actor because both classes store position, rotation, scale, and color. It makes more sense to use a TextureRegion with Actor. Or you can use the Image class, which already handles this for you.
Edit:
I see the other part of the issue. You are overriding sizeChanged, but it's the scale, not the size, that you are changing with a ScaleToAction. Actor doesn't have a callback for the scale changing. You could override the setScale methods to apply your change to the Sprite, but like I said above, it doesn't make sense to be using a Sprite for this. You should reference a TextureRegion, and draw it with all the appropriate parameters in the draw() method.
I want to include a TiledMap inside my LibGdx Project.
I did coding like this.
public static final AssetDescriptor<TiledMap> tMap = new AssetDescriptor<TiledMap>("tmap.tmx",
TiledMap.class);
Inside MyGdxGame class,called a loader also:
assetManager = new AssetManager();
//tmx loading
assetManager.setLoader(TiledMap.class, new TmxMapLoader(new InternalFileHandleResolver()));//loader for tiledmap
assetManager.load("tmap.tmx", TiledMap.class);
assetManager.finishLoading();
Inside gameScreen Class:
private TiledMap tiledMap;
private OrthogonalTiledMapRenderer orthogonalTiledMapRenderer;
public void show() {
tiledMap = assetManager.get(Assets.tMap);
orthogonalTiledMapRenderer = new OrthogonalTiledMapRenderer(tiledMap,batch);
orthogonalTiledMapRenderer.setView(game.camera);
}
public void render(float delta) {
batch.setProjectionMatrix(game.camera.projection);
batch.setTransformMatrix(game.camera.view);
orthogonalTiledMapRenderer.render();
}
But TiledMap image is not showing up while running the project.It does not show any error while running.
Also how to manage camera with tilemaps?
I'm using in this way
AssetManager manager = new AssetManager();
manager.setLoader(TiledMap.class, new TmxMapLoader(new InternalFileHandleResolver()));
manager.load("maps/tile.tmx", TiledMap.class);
When all asset are loaded.
TiledMap tiledMap=manager.get("maps/tile.tmx");
OrthogonalTiledMapRenderer renderer=new OrthogonalTiledMapRenderer(tiledMap);
render in this way :
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
game.camera.position.set(...); //set position according to your requirement
game.camera.update();
orthogonalTiledMapRenderer.setView(game.camera);
orthogonalTiledMapRenderer.render();
orthogonalTiledMapRenderer.getBatch(); // for batch related work
}
May be it would be helpful.
Thanks.
I'm using libgdx in my 2D platformer game project for college task. For now I'm confused with loading tiledmap in libgdx. I have a big tmx map with size of 11400x1500 pixels and 30x30 tile size. Also an image with same pixel size which I load it in image layer. I try to load it but libgdx shows nothing.
My question is how to load single big tmx map or should I divide the map into several segment/section? Because I've tried other small tmx (3000x1500). If the tmx is divided then how to load them as one stage?
public class Layarloh implements Screen{
private JumatUtama game;
private TiledMap map;
private TmxMapLoader mapLoader;
private OrthographicCamera kamera;
private OrthogonalTiledMapRenderer mapRenderer;
private Viewport viewport;
public Layarloh(JumatUtama utama) {
float l=Gdx.graphics.getWidth(),t=Gdx.graphics.getHeight();
this.game = utama;
loadstage();
kamera = new OrthographicCamera();
kamera.setToOrtho(false,l,t);
kamera.update();
viewport = new FitViewport(l/3,t/3,kamera);
}
public void loadstage(){
mapLoader = new TmxMapLoader();
map = mapLoader.load("stage/s11.tmx");
mapRenderer = new OrthogonalTiledMapRenderer(map);
}
public void stik(float dt){
if (Gdx.input.isKeyPressed(Input.Keys.ANY_KEY))
kamera.position.x +=100*dt;
}
#Override
public void render(float delta) {
stik(delta);
kamera.position.set(550,550,0);
kamera.update();
mapRenderer.setView(kamera);
mapRenderer.render();
}
#Override
public void resize(int width, int height) {
kamera.viewportWidth = viewport.getScreenWidth();
kamera.viewportHeight = viewport.getScreenHeight();
kamera.update();
}
Unitscale does nothing, the code above works on smaller size of tmx map.
EDIT
Code above isn't working, and the below is working, notice the maploader is loading different tmx file, above code trying to load 11400x1500 pixel with 30x30 tile size, while code below trying to load 3800x1500 with 30x30 tile size, but I try to use the code below to load bigger tmx, its not working,
public class Layarloh implements Screen{
private JumatUtama game;
private TiledMap map;
private TmxMapLoader mapLoader;
private OrthographicCamera kamera;
private OrthogonalTiledMapRenderer mapRenderer;
public Layarloh(JumatUtama utama) {
float l=Gdx.graphics.getWidth(),t=Gdx.graphics.getHeight();
this.game = utama;
loadstage();
kamera = new OrthographicCamera();
kamera.setToOrtho(false,l,t);
kamera.position.set(550,550,0);
kamera.update();
}
public void loadstage(){
mapLoader = new TmxMapLoader();
map = mapLoader.load("stage/segmen1.tmx");
mapRenderer = new OrthogonalTiledMapRenderer(map);
}
public void stik(float dt){
if (Gdx.input.isKeyPressed(Input.Keys.ANY_KEY))
kamera.position.x +=100*dt;
}
#Override
public void render(float delta) {
stik(delta);
kamera.update();
mapRenderer.setView(kamera);
mapRenderer.render();
}
Try this code and this should fix it.
#Override
public void render(float delta) {
kamera.position.set(x, y, z);
kamera.update();
mapRenderer.setView(kamera);
mapRenderer.render();
}
#Override
public void resize(int width, int height) {
kamera.viewportWidth = width;
kamera.viewportHeight = height;
kamera.update();
}
EDIT
In the original code, OP was missing kamera.update() statement. And also the resize method. That is something which causes trouble when displaying the tiled map properly as you need to update the camera at every iteration of render.
I'm new to LibGDX and I am trying to get my screen resolution sizes set up first before I get into the actual game itself. Before I added extendViewport I had an orthographic Camera and an Image that displayed. But when I got rid of the orthographic camera and added the Viewport the image disappeared. Here is the code i have for the the screen.
public class GameScreen implements Screen {
SlingshotSteve game;
private ExtendViewport viewport;
PerspectiveCamera camera;
public void Menu(SlingshotSteve game){
this.game = game;
}
SpriteBatch batch;
TextureRegion backgroundTexture;
Texture texture;
GameScreen(final SlingshotSteve gam) {
this.game = gam;
batch = new SpriteBatch();
Texture texture = new Texture(Gdx.files.internal("background.jpg"));
backgroundTexture = new TextureRegion(texture, 0, 0, 500, 500);
Music mp3Sound = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));
mp3Sound.setLooping(true);
mp3Sound.play();
}
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(backgroundTexture, 0, 0, SlingshotSteve.WIDTH, SlingshotSteve.HEIGHT);
batch.end();
}
#Override
public void resize(int width, int height) {
viewport.update(width, height);
}
#Override
public void dispose() {
batch.dispose();
texture.dispose();
}
#Override
public void show() {
camera = new PerspectiveCamera();
viewport = new ExtendViewport(800, 480, camera);
}
}
The other question I have is that this screen is the main game screen where Level 1 is going to occur. Since I added a main menu I had to switch from the "Application Listener" to the "Implement Screen". Is this correct, or do I have to go back to the Application Listener to get the Create() method? I'm not completely sure what everything means so If someone could please explain this to me that would be great!