rendering texture from other class in libgdx - libgdx

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!

Related

How to create an ImageButton with multiple Sprite/Texture layers in LibGDX?

I'm designing a game that requires generating a vast array of buttons, with different combinations of background colors and outlines. I already have a Sprite for the background and a Sprite for the outline and apply tints to each.
I've already tried to join both on a SpriteBatch but have had no luck converting it to a structure that ImageButton supports.
Thanks in advance.
You could make your own version of an ImageButton by extending the Actor class and implementing your own methods for drawing. The example below isn't tested but should give you and idea on how to make your own Custom button:
private class LayeredButton extends Actor{
private int width = 100;
private int height = 75;
private Texture backGround;
private Texture foreGround;
private Texture outline;
public LayeredButton(Texture bg, Texture fg, Texture ol){
setBounds(this.getX(),this.getY(),this.width,this.height);
backGround = bg;
foreGround = fg;
outline = ol;
addListener(new InputListener(){
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
// do something on click here
return true;
}
});
}
#Override
public void draw(Batch batch, float alpha){
// draw from back to front
batch.draw(backGround,this.getX(),this.getY());
batch.draw(foreGround,this.getX(),this.getY());
batch.draw(outline,this.getX(),this.getY());
}
#Override
public void act(float delta){
// do stuff to button
}
}

Libgdx ScaleToAction not resizing

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.

Couldn't load tmx

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.

libgdx-html5 : texture dispose generate a bufferunderflowexception

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

moving actors with the gesture listener Libgdx

Hello I've been stuck on an issue for a while trying to create a simple game using the Libgdx framework.
I have a stage with a background Image actor and a stick figure image actor that is placed in the center of the stage.
I cant seem to understand, after reading many posts on stackoverflow and the libgdx wiki on event handling, how events such as fling and pan are passed to the actor to simply move it my stickman around the screen.
I would greatly appreciate any help or explanations on how exactly this works.
I just don't know how to get the integer values from pan and the velocity values from fling into my actor's Vector2 position variable so that it can move around every time the render method is called.
Here is some of my code:
My GestureDetection Class:
public class GestureDetection implements GestureListener{
public GestureDetection(){
}
#Override
public boolean touchDown(float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean tap(float x, float y, int count, int button) {
System.out.println("tapped");
return false;
}
#Override
public boolean longPress(float x, float y) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean fling(float velocityX, float velocityY, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean panStop(float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean zoom(float initialDistance, float distance) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2,
Vector2 pointer1, Vector2 pointer2) {
// TODO Auto-generated method stub
return false;
}
}
My Game class
public class Game implements Screen{
StickFlick game;
SpriteBatch batch;
Texture gameBackground;
Stage stage;
GestureDetector gd;
InputMultiplexer im;
WalkingEnemy testEnemy;
public Game(StickFlick game){
this.game = game;
testEnemy = new WalkingEnemy("basic", 100, Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
//enemy1.update(delta);
System.out.println("");
stage.act(Gdx.graphics.getDeltaTime());
batch.begin();
stage.draw();
batch.end();
}
#Override
public void resize(int width, int height) {
stage = new Stage(width, height, true);
stage.clear();
gd = new GestureDetector(new GestureDetection());
im = new InputMultiplexer(gd, stage);
Gdx.input.setInputProcessor(im);
Texture gameBackground = new Texture("data/gameBackground.png");
Image backgroundImage = new Image(gameBackground);
backgroundImage.setWidth(Gdx.graphics.getWidth());
backgroundImage.setHeight(Gdx.graphics.getHeight());
stage.addActor(backgroundImage);
stage.addActor(testEnemy.getImage());
stage.addAction(Actions.sequence(Actions.alpha(0), Actions.fadeIn(1)));
}
#Override
public void show() {
batch = new SpriteBatch();
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
}
}
Ok, so at start you have to make some variables where you will keep X and Y coords of your stick man. Set some initial values to them, i.e. x should be half of screen width and y half of screen height to have your stick man at the center of the screen.
Then you have to use information you are getting in your GestureListener implementation to move your stick man, that is to change it's coordinates. Your current implementation does absolutely nothing - methods are empty, so when some gesture happens your code is not reacting to it.
So, you can i.e. inside of your pan method use deltaX and deltaY to change stick man coordinates for those values. Something like:
X+=deltaX;
y+=deltaY;
Or you can multiply deltaX and deltaY with some constant if you want faster or slower movement and/or multiply deltaY with -1 if movement is in opposite way from what you want it to be.
Or if you want to use fling use those variables that method provides - velocityX and velocityY - add them to you stick man x and y to move it.
So basically, you are always drawing stick man at x,y coords and from some method of GestureListener interface you implemented you should change stick man coords and make him move.