Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am currently pursuing game development as a hobby, and have run into what seems to be a conflict in my mind regarding how to properly (using best practices) extend the Sprite class in LibGDX (or for the sake of this question, any Sprite class).

What I Would Like To Do

I would like to to create a class, Ship.java, with the constructor as follows:

// Note the lack of a Texture object in the constructor here
public Ship(float startingX, float startingY){

    super(new Texture(Gdx.files.internal("data/ship_texture.png")), 0, 0);

    this.startingX = startingX;
    this.startingY = startingY;

}

Why I Can't Do This

First, this implementation forces me to forfeit having a reference to the Texture that I am passing into the super constructor. This means that I cannot properly dispose() it later, which would lead to memory leaks later in the code.

The Problem

Since the constructor of the Sprite class forces you to specify a Texture, and I would want a Ship to always have the same Texture (thus would not want to specify it in the constructor of a Ship), I am limited to hacking together some factory method to construct the Ship.

My Current Solution

As specified above, I currently have a factory method that creates the Ship instead of using the constructor.

The Code

Below I have detailed the code I am currently using to get the Ship class instantiated. Please feel free to critique it:

// Private constructor because I do not want this method to be called ever
private Ship(Texture texture, int row, int column) {

    // Calls the super constructor (for the Sprite class)
    super(texture, row, column);
}

// Instead, this create method returns a new instance of Ship   
public static Ship create(int row, int column){

    // Create the new texture
    Texture texture = new Texture(Gdx.files.internal("data/ship.png"));

    // Set the LINEAR filter (might switch to NEAREST later)
    texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);

    // Return a new instance of the Ship
    return new Ship(texture, row, column);
}

Why I Don't Like This Solution

I feel as though this is a very "hacky" fix, as it defeats the purpose of a constructor, and although static factory methods are good practice, I don't think it should be necessary to implement a new factory method for each object I plan to draw on the Screen.


My Question

What is the best way to extend the Sprite class (thus keeping all the helper methods that it provides), and still define the Texture that will be displayed on the object within the constructor of the Ship?

Is the current approach I am using appropriate?

share|improve this question
1  
Not really an answer but I'd like to hear why you choose to extend the Sprite class in the first place? In our last game I had classes that had sprites, because I wanted each thing to be able draw itself - a base class called DrawableThing had a reference to a Texture or Sprite and a Draw method that took a SpriteBatch - but I didn't subclass directly from Sprite. Not criticizing your method, it honestly hadn't occurred to me. What are the pros/cons of your way vs my way? –  LoveMeSomeCode Mar 25 '13 at 20:44
    
After reviewing my circumstances, it actually does make more sense to simply include a Sprite in the class. Extending it would not really be necessary. The reason I chose to extend it was because I just wanted a Sprite that had maybe one more function, and didn't see the need for an entire new class. –  Squagem Mar 25 '13 at 21:13
    
Upon review, however, it makes sense that I could get this same functionality if I just added a Sprite into my class. This consideration makes my question sound silly, but hey, I learned something nonetheless! –  Squagem Mar 25 '13 at 21:14
    
it's this kind of stuff that can keep me up at night weighing the pros and cons of certain methods. what i love about indie gaming is that there's no wrong answer. if it works, it works. –  LoveMeSomeCode Mar 25 '13 at 21:24
    
This is precisely my problem. I always spend hours working on "best practices" instead of just getting something to work. –  Squagem Mar 25 '13 at 23:34
add comment

1 Answer 1

up vote 4 down vote accepted

In the game I'm developing I'm using a centralized AssetManager, which will hold the references and automatically dispose them. I just need to load the pack file and get the TextureAtlas from it. (or the texture if you are using single images instead of packs)

TextureAtlas atlas = game.assets.get("filename.pack", TextureAtlas.class);
jewelSprite = new JewelSprite(jewelType, atlas.findRegion("textureName")), game); 
// use `AtlasRegion` instead of `Texture`

Check the first link for a nice overview of the AssetManager. You don't need to pack the textures but it is recommended for performance.

share|improve this answer
    
Thank you for your prompt response. I will look into this immediately and get back to you! –  Squagem Mar 25 '13 at 15:26
    
Hmm, this seems to be a package geared towards making the loading of Textures easier and more streamlined, which does not help me here as I am not running into issues loading the Texture, but rather, when and how to load it. Did I maybe miss something in the link you provided that would relate more to my post? –  Squagem Mar 25 '13 at 15:44
    
@Squagem Well, using the manager to load the texture you won't need to create, or dispose it yourself, which I understood as being the problem. You just call manager.get("data/mytexture.png", Texture.class) to access it. If you sure you don't need a texture anymore just call `manager.unload("texture.png"). –  petervaz Mar 25 '13 at 15:49
    
Ahh yes, I see. Okay, this seems like it would be a solution. Yet again, however, this is quite a bit of overhead just to extend the Sprite class. The tutorial even specified, that if you only have a few Textures as I do, that using the AssetsManager was a bad idea. However, nonetheless, it solves my issue. I will leave the question unanswered for a while to hear some other potential approaches, but after a day or two you will receive your accept! (Assuming a more lightweight approach is not found) :) –  Squagem Mar 25 '13 at 16:04
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.