0

I'm still possibly a little green about object-pooling, and I want to make sure something like this is a sound design pattern before really embarking upon it. Take the following code (which uses the Starling framework in ActionScript 3):

[Embed(source = "/../assets/images/game/misc/red_door.png")]
private const RED_DOOR:Class;

private const RED_DOOR_TEXTURE:Texture = Texture.fromBitmap(new RED_DOOR());

private const m_vRedDoorPool:Vector.<Image> = new Vector.<Image>(50, true);
.
.
.
public function produceRedDoor():Image
{
    // get a Red Door image
}

public function retireRedDoor(pImage:Image):void
{
    // retire a Red Door Image
}

Except that there are four colors: red, green, blue, and yellow. So now we have a separate pool for each color, a separate produce function for each color, and a separate retire function for each color. Additionally there are several items in the game that follow this 4-color pattern, so for each of them, we have four pools, four produce functions, and four retire functions.

There are more colors involved in the images themselves than just their predominant one, so trying to throw all the doors, for instance, in a single pool, and then changing their color properties around isn't going to work. Also the nonexistence of the static keyword is due to its slowness in AS3.

Is this the right way to do things?


EDIT:

One individual piece of the puzzle is whether I should be trying to throw all of these pools into the same class, with brand new functions and everything for each and every pool. That is somewhat related to another question I asked recently. Even though the accepted answer of that question didn't necessarily address this particular scenario, getting more classes, variables, abstractions, etc. is going to create more overhead, and when you're trying to do something like object pooling, I'm not sure whether neatening up the class design like that is going to introduce "too much" overhead. This is only one individual part of what I'm asking though, as the question is ultimately much more general.

  • Is this a design or runtime question? If it is a design question then simply differentiating by color is a bad example because it is more efficient to modify a texture's color than to use different textures. – Dunk Nov 4 '13 at 14:19
  • I thought about that, but what if the textures are not monochromatic? What if a red door has red, black, brown, and a couple of shades of grey? Would there be a work-around like that in Starling? – Panzercrisis Nov 4 '13 at 17:35
  • :I don't use ActionScript or Starling so I don't know about the efficiency or capabilities. But in most frameworks there are ways that you can "tint" your textures towards a color of choice. – Dunk Nov 5 '13 at 15:57
1

If you have a {Red,Green,Blue,Yellow} Door pool and a {Red,Green,Blue,Yellow} Window pool, it would be worth choosing an appropriate abstraction: The variable things are the item type (door or window), and the color.

A Pool has a color, an item class, and a collection of images. It also has produce and retire methods. For example (switching to Java, because generics):

Pool<Door> redDoorPool = new Pool<Door>(Color.RED);
Image redDoor = redDoorPool.produce();

You could then create a ColorPool class which groups four Pools together:

class ColorPool<T> {
  public final red    = new Pool<T>(Color.RED);
  public final green  = new Pool<T>(Color.GREEN);
  public final blue   = new Pool<T>(Color.BLUE);
  public final yellow = new Pool<T>(Color.YELLOW);
}

Consider using the Composite Pattern here. Also, use accessors instead of public fields in actual code…

Then:

ColorPool<Door> doorPool = new ColorPool<Door>();
Image redDoor = doorPool.red.produce();

We have now successfully abstracted over all variable pieces in your pools, and neither type information, nor color information is part of the method name.

Note that generics are not strictly necessary for this design to work – I just used it here to make the relationships clear.

|improve this answer|||||
  • Thanks. I'm thinking about your answer. The main thing I'm curious about, as far as this answer goes, would be how much of an impact it might have on performance. – Panzercrisis Nov 4 '13 at 19:38
  • 1
    @Panzercrisis First, do a clean design and optimize for readability. If more performance is needed, then profile your code to find the real bottlenecks. Yes, OOP tends to have more indirection than under-designed code, but there can be other wins (better typing allows better optimization; smaller code is usually faster; optimize in one place, and all instances win; …). Note that my refactoring only costs one extra member access per invocation which could be optimized away, plus minimal memory overhead for the Pools. – amon Nov 4 '13 at 20:10
  • So basically as long as you've got a pool and you don't use particularly inefficient code in and around it, you'll still be able to come out ahead without having to really push things? (Sorry, like I said, I'm still a little green.) – Panzercrisis Nov 4 '13 at 22:59
  • 1
    @Panzercrisis The design in your question and the design in my answer are almost the same, except that mine is less work for the programmer and more elegant. On the performance scale, they are probably right next to each other, but the only way to know for sure is to benchmark them. Pooling and other forms of caching tend to drastically improve performance for some algorithms and usage patterns. For others, they are just useless indirection. But in general, I think you've understood it: Don't push things unless you have to. – amon Nov 4 '13 at 23:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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