Remember in Moai, you think of graphics resources in terms of Decks and Props. Decks are the actual definition of the resource – the vertex locations, texture data, etc. A Prop is a reference to a Deck and any information used to actually draw an instance of it – the actual location or any other transformation. In order for this to work though, you need to keep track of all your Decks in order to create new Props. I wrote up a class called ResourceManager to help with this.
ResourceManager = {} --cache of filename -> deck local cache = {}
Since we want this to be accessible anywhere, I’m treating this like a static class. That means I don’t need to use the CreateClass() function I introduced earlier – I just need to create a global scoped table and add some functions to it. Since there will only ever be one instance of this, I can create private variables by just declaring them local. Here, “ResourceManager” will be the name of the class, and we have a private table “cache”, which we will use as a dictionary with a string (filename) to Deck mapping.
Here is the function to actually get a Deck:
--returns a cached quad2d given a filename function ResourceManager.getDeck(filename, xmin, ymin, xmax, ymax) local key = filename if cache[key] then return cache[key] else local image = MOAIImage.new() image:load(filename) local texture = MOAITexture.new() --makes it smoother texture:setFilter(MOAITexture.GL_LINEAR_MIPMAP_LINEAR) texture:load(image) local deck = MOAIGfxQuad2D.new() deck:setTexture(texture) deck:setRect(xmin, ymin, xmax, ymax) cache[key] = deck return deck end end
Note that this function’s table is global and we use the “.” notation instead of “:”, since we don’t need to reference “self” to get at some instance’s data. This function getDeck() takes a filename, and the dimensions you want the deck to be. We can use the filename as the key, and then check if it has already been loaded. If so, we just return the previously created Deck. Otherwise, we need to create a new MOAIImage, use that to create a MOAITexture, and then pass that into the final MOAIGfxQuad2D (the basic rectangular Deck). Note that not all Deck classes actually have Deck in their name for some reason, though some of them do. You’ll have to check the Moai inheritance chart to see what the classes are. Also I found that scaling images can make them look pretty ugly by default, but if you specify for Moai to create a mipmap for them, it looks a lot better.
Since each MOAIGfxQuad2D deck actually defines the dimensions of it, you may need to create separate Decks even if you want to use the same image with different sizes. You can extend this design by adding that information to the key, and then caching each size separately. You can also create a separate texture cache so you don’t have to reload the same image multiple times.
Another resource you might need to get are fonts. Here is a function to get a font:
function ResourceManager.getFont(filename) if cache[filename] then return cache[filename] else local charcodes = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .,:;!?()&/-' local font = MOAIFont.new () font:loadFromTTF ( filename, charcodes, 7.5, 163 ) cache[filename] = font return font end end
I’m reusing the same cache because I don’t think font filenames and image filenames will overlap. This code creates a new font given a .ttf file, and returns it. Note that “loadFromTTF” takes some sizing information, which you need to make sure lines up with your world coordinate system, otherwise things will look ugly. The numbers I pass here roughly correspond to a world that is 480 units wide.
Lastly here is a convenient function to call if you need to create a simple Prop:
function ResourceManager.getProp(filename, x1, y1, x2, y2) local prop = MOAIProp2D.new() prop:setDeck(ResourceManager.getDeck(filename, x1, y1, x2, y2)) prop:setBlendMode(MOAIProp2D.GL_SRC_ALPHA, MOAIProp2D.GL_ONE_MINUS_SRC_ALPHA) return prop end
This just creates a new MOAIProp2D, grabs the actual Deck from the ResourceManager, and enables transparency.