Dungeon 129
Second shot down. Slices looking good. What shall we do today?
Got my second C-19 shot today, 25 minutes in and out, including the 15 minute wait to see if I went into shock. I guess I didn’t. Half hour drive to and from the place. Now back to days like all the other days for the past year or so. Fortunately, as an introvert, I don’t much mind it.
What shall we do today? I guess we should push forward a bit with the Slices and SpriteSheet stuff. I think my general plan will be to have a new standard way of calling the sprite
internal function, namely to refer the input value to the Slices object, which will translate it or return it as is.
To make a test bed for that, let’s do this:
- Import some potion bottle slices, or something like that;
- Set the strength and speed power-ups to use those new images.
That should be pretty simple, as things go. (Famous last words, second only to “hold my beer”.)
Let’s remind ourselves where we are. It has been literally hours since I worked on this, and I like to leave all my thinking in the program and these articles, to save room in my head for other matters. Or wind.
We have this class:
Sprites = class()
function Sprites:init()
self.sprites = {}
end
function Sprites:add(names, sheet, xSkipLow, xSkipHigh, ySkipLow, ySkipHigh)
local ss = SpriteSheet(sheet, #names, xSkipLow, xSkipHigh, ySkipLow, ySkipHigh)
for i,name in ipairs(names) do
if name ~= "" then
self.sprites[name] = ss:slice(i)
end
end
end
function Sprites:sprite(name)
return self.sprites[name]
end
At this point, we would need a place to instantiate Sprites and use it. Let’s swap things around, so that we can just call it with the class name.
If we’re going to do that, then this test:
_:test("Sprites lookup", function()
local testss = SS(sheet, 12, 1,0, 0,1)
local names = {"crossed", "green_staff", "feather_staff",
"purple_staff", "snake_staff", "cudgel_staff", "skull_staff",
"bird_staff", "jewel_staff", "knob_staff", "crystal_staff", "twist_staff"}
_:expect(#names).is(12)
local sp = Sprites()
sp:add(names, sheet, 1,0, 0,1)
local eq = areImagesEqual(sp:sprite("green_staff"), testss:slice(2))
_:expect(eq).is(true)
end)
Needs to be:
_:test("Sprites lookup", function()
local testss = SS(sheet, 12, 1,0, 0,1)
local names = {"crossed", "green_staff", "feather_staff",
"purple_staff", "snake_staff", "cudgel_staff", "skull_staff",
"bird_staff", "jewel_staff", "knob_staff", "crystal_staff", "twist_staff"}
_:expect(#names).is(12)
Sprites:add(names, sheet, 1,0, 0,1)
local eq = areImagesEqual(Sprites:sprite("green_staff"), testss:slice(2))
_:expect(eq).is(true)
end)
And the implementation:
Sprites = class()
local sprites = {}
function Sprites:init()
assert(false, "No need to make an instance")
end
function Sprites:add(names, sheet, xSkipLow, xSkipHigh, ySkipLow, ySkipHigh)
local ss = SpriteSheet(sheet, #names, xSkipLow, xSkipHigh, ySkipLow, ySkipHigh)
for i,name in ipairs(names) do
if name ~= "" then
sprites[name] = ss:slice(i)
end
end
end
function Sprites:sprite(name)
return sprites[name]
end
I expect the tests to run. Curiously enough, they do.
We do need to initialize some slices. Let’s do that as part of GameRunner init.
function GameRunner:init()
self.tileSize = 64
self.tileCountX = 85 -- if these change, zoomed-out scale
self.tileCountY = 64 -- may also need to be changed.
self.cofloater = Floater(self, 50,25,4)
self.musicPlayer = MonsterPlayer(self)
self:initializeSprites()
self.dungeonLevel = 0
self.requestNewLevel = false
self.playerRoom = 1
end
I’ll copy the init from the test, and add some more from other images that I’ll move over.
function GameRunner:initializeSprites()
local names
local sheet
sheet = asset.gear_staffs_2
names = {"crossed", "green_staff", "feather_staff",
"purple_staff", "snake_staff", "cudgel_staff", "skull_staff",
"bird_staff", "jewel_staff", "knob_staff", "crystal_staff", "twist_staff"}
Sprites:add(names, sheet, 1,0, 0,1)
sheet = asset.items_health
names = { "blue_pack", "red_pack", "green_pack",
"blue_bottle", "red_bottle", "green_bottle",
"blue_flask", "red_flask", "green_flask",
"blue_jar", "red_jar", "green_jar",
"", "", "",
"copper_bag","gold_bag","","","","","",
"silver_bag"}
assert(#names==23, "bad count for bottles and jars")
Sprites:add(names, sheet, 1,0, 0,1)
end
Now Sprites
should know those names. Let’s look at the Loots and fix them up.
local LootIcons = {Strength=asset.builtin.Planet_Cute.Gem_Blue, Health=asset.builtin.Planet_Cute.Heart, Speed=asset.builtin.Planet_Cute.Star}
I’ll start by making them all items from the health asset, so I don’t have to build the trick stuff in yet.
local LootIcons = {Strength="blue_pack", Health="red_flask", Speed="green_jar"}
Now to fix the draw
:
function Loot:draw()
pushStyle()
spriteMode(CENTER)
local g = self.tile:graphicCenter()
sprite(Sprites:sprite(self.icon),g.x,g.y+10)
popStyle()
end
That works as advertised:
I think I’ll leave the attribute sheet icons alone, though we might as well remove them, as they are not very meaningful.
Now I want to change the sprite
method to return an asset (a userdata, or anything other than a string) directly, and only look up strings.
Let’s write a test for it.
_:test("assets pass through", function()
local testss = SS(sheet, 12, 1,0, 0,1)
local names = {"crossed", "green_staff", "feather_staff",
"purple_staff", "snake_staff", "cudgel_staff", "skull_staff",
"bird_staff", "jewel_staff", "knob_staff", "crystal_staff", "twist_staff"}
Sprites:add(names, sheet, 1,0, 0,1)
local a = Sprites:sprite(asset.air006)
_:expect(a).is(asset.air006)
end)
As expected, test fails:
5: assets pass through -- Actual: nil, Expected: Asset Key: air006.png (path: "/private/var/mobile/Containers/Data/Application/483B2209-7216-46A0-8C24-5253968FCBE5/Documents/D2.codea/air006.png")
Implementing:
function Sprites:sprite(name)
if type(name) == "string" then
return sprites[name]
else
return name
end
end
We’re good to go. Test runs, game runs. Enough for the morning.
Commit: new SpriteSheet icons for Loots, more assets moved.
Summary
This went nicely. The little Sprites object is easy to use in game play, and not too much of a pain to set up i initialization. You just provide a sheet, some names, and a couple of offsets if the artist left lines in their sheet. Snip snip, slice slice, and Bob’s your uncle.
Tomorrow, if I’m not reacting too badly, to the Pfizer, we’ll do something else. See you then!