There’s this thing called a Mimic …

A Mimic is a monster that looks like a treasure chest. But when it opens, well, TEETH!

I’ve spent a fortune, namely $7, for some Mimic art. I think the Dung program needs Mimics. Here are some random thoughts about them:

  • Use one of the Mimic frames for all Chests, so that you can’t easily tell them apart.
  • Maybe they start as Decor and spawn a Mimic when moved on.
  • Mimics should be hard to beat.
  • Mimics should provide something of value when beaten.
  • Maybe the key to the next level?
  • Mimics don’t show up in the music or Monster attribute sheet unless they are active. (Decor idea solves this.)

From an implementation viewpoint, I think a Mimic can be built as a standard monster. They do have more animation frames available than other monsters, but that should be OK. The sprites I got are divided into idle, walking, attacking, and so on, so perhaps we’ll have some kind of monster attitude that comes out of this.

I guess I have to start by bringing in the sprites. That’s a pain. I’ll document the process here, because I like to have places to find out how I did it, and some few readers are actually using Codea and running the program, so they might find the info useful.

Getting the Sprites

I begin in the Files app, open the mimic folder and drill down to the small size PNG ones, which are the ones I want:

files app

There are 10 frames each for walk, idle, hurt, hide, death, and attack. There are also individual multi-sprite sheets for those headings.

One odd thing is that the sizes of the frames are not all the same. In particular the attack ones get quite large.

attack_007 is 184x178, while hide_000 is only 96x127. That’s going to require a little more work, but there’s the AdjustedSprite object that knows a scale, so it should just come down to some cut and try. We only use those in Tiles and Attribute sheets, but one way or another it shouldn’t be terribly hard to cope.

I don’t think we can just let them get bigger than a tile, unless we ensure that the monsters are drawn after the whole tile space, but again, that can be dealt with if we need to.

The “decision” to be made is whether to bring over just the spritesheets with multiple sprites, or all of them. 60 tiles or 6. The sheets look to be a bit tricky to split apart but we have that technology.

I’ll move just the sheets to Codea’s Dropbox.assets, and I think I might do some work in a separate project to get a sense of these new sprites.

Select the sheets:

select

Tap Move to get to the move-to screen:

moveto

Select Codea / Dropbox.assets and tap Copy

codea

And voila! Codea can see the assets … except that it can’t.

Turns out those sheets are Photoshop files. Can I export them somehow?

Yes! Import the PSD file into Procreate. Share to Files as PNG. Now I think I have one. Let’s see:

it is there

After a bit of reading and retraining, I think I know enough to import the walk sprites for the Mimic. We have a method in GameRunner:

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_vial", "red_vial", "green_vial",
    "blue_flask", "red_flask", "green_flask",
    "blue_jar", "red_jar", "green_jar",
    "blue_vase", "red_vase", "green_vase",
    "copper_bag","gold_bag","","","","","",
    "silver_bag"}
    assert(#names==23, "bad count for bottles and jars")
    Sprites:add(names, sheet, 1,0, 0,1)
end

I’ll add another element:

    sheet = asset.mimic_spritesheet_walk)
    names = {"mw01","mw02","mw03","mw04","mw05","mw06","mw07","mw08","mw09","mw10"}
    assert(#names==10, "bad count for mimic walk")
    Sprites:add(names,sheet, 0,0,0,0)

Now I should have those sprites. Let’s see if we can define a monster that uses them.

The monster table entry is this:

    m = {name="Mimic", level=1, health={10,10}, speed={10,10}, strength=10,
        attackVerbs={"bites", "chomps", "gnaws"},
        dead="mw10", hit="mw02",moving={"mw01", "mw01", "mw03", "mw04", "mw05", "mw06", "mw07", "mw08", "mw09", "mw10"}
    }
    table.insert(MT,m)

Monsters aren’t prepared to use slices, so we change draw to refer to Sprites:sprite(), which returns assets untouched and looks up slice names when given a string.

function Monster:drawMonster()
    if not self.tile.currentlyVisible then return end
    pushMatrix()
    pushStyle()
    spriteMode(CENTER)
    noTint()
    local center = self.tile:graphicCenter()
    translate(center.x,center.y)
    self:flipTowardPlayer()
    if self:isDead() then
        tint(0,128,0,175)
        sprite(Sprites:sprite(self.dead)) -- <---
    elseif self.showDamage then
        self:selectDamageTint()
        sprite(Sprites:sprite(self.hit)) -- <---
    else
        sprite(Sprites:sprite(self.moving[self.movingIndex])) -- <---
    end
    popStyle()
    popMatrix()
end

This gives me a more or less working Mimic:

mimic movie

The Mimic is too large, of course. We should scale all the sprites to fit into a tile, at least for now.

function Monster:drawMonster()
    if not self.tile.currentlyVisible then return end
    pushMatrix()
    pushStyle()
    spriteMode(CENTER)
    noTint()
    local center = self.tile:graphicCenter()
    translate(center.x,center.y)
    self:flipTowardPlayer()
    if self:isDead() then
        tint(0,128,0,175)
        sprite(Sprites:sprite(self.dead), 0,0, 64,64)
    elseif self.showDamage then
        self:selectDamageTint()
        sprite(Sprites:sprite(self.hit), 0,0, 64,64)
    else
        sprite(Sprites:sprite(self.moving[self.movingIndex]), 0,0, 64,64)
    end
    popStyle()
    popMatrix()
end

mimic size

That’s better. I think we can count the initial Mimic as done. They spawn as regular active monsters, but that’s OK for a first cut. We can see we’ll want to import all the sprites, but that seems to be in hand.

Let’s wrap and sum up.

Wrapping Up

This has been a morning of hackery. I refreshed my mind on how the Sprite slicing worked. I had to slightly mash it here:

function SS:sliceFromImage(img,sliceNumber)
    local sliceWidth = img.width/self.numberX
    local sliceHeight = img.height
    local sliceStartX = (sliceNumber-1)*sliceWidth + self.xSkipLow + 1
    local sliceStartY = self.ySkipLow + 1
    local sliceW = sliceWidth - self.xSkipLow - self.xSkipHigh
    local sliceH = sliceHeight - self.ySkipLow - self.ySkipHigh
    self.slices[sliceNumber] = img:copy(sliceStartX//1, sliceStartY//1, sliceW//1, sliceH//1)
end

The Mimic’s sheet x dimension is not divisible by 10. So I was sending floats into the img:copy. That was not appreciated.

Then it was fairly easy to get some sprites, and certainly slipping the Sprites:sprite call into Monster was easy enough. Then I had to force the size because even the smallest Mimic art is larger than my tiles. Doing that causes other monsters to go out of scale. That’s surprising although not necessarily unacceptable.

What I think is the case is that we’re going to have to do some more scaling work. In a “real” game, we’d have standard sizes for all our art. In a game like this one, where the art has been scavenged from all over, some work will need to be done to get everything to a reasonable scale.

I might be able to do that in Procreate, smushing the sheets down there and only then exporting. Or I can rely on Codea’s ability to scale things, and give everything a built-in scale that gets applied. I’ll have to think about it.

I think for now what I’d like to do is set the Mimic never to be used, and take the scaling back off the monster drawing. We’ll consider this a Spike for Mimic and work from here next time.

I hope to see you then!


D2.zip