Codea Craft 16 - A movement spike
It’s Sunday. My long-suffering wife is prepping for the upcoming election. On my own, I decided to spike motion for my game creature.
Assume a long rant here about how hard my wife, Deputy Clerk of our township, works in preparation for elections. We have a presidential primary next Tuesday. All the machines have to be set up and checked, ballots prepared, etc etc. I don’t know half of what the poor woman does, but she’s been working 7 days a week for a couple of weeks now.
Among the tragic outcomes of this is that we didn’t get our traditional breakfast with Sunday Morning today. The good news is that I hit the grocery store and the cat won’t starve.
So I came to BAR1 and after wasting some time decided I’d do a motion spike on the “Game”. Last time, I stopped with a Creature, represented by a block Orc, standing on a small plane or plain, depending how you want to think of it. Today, I’d make it move.
I briefly reviewed the Braitenberg vehicles code and then did something much simpler. It may still be necessary to set up the partial function idea I used there, but for now it wasn’t needed.
You must not be a very good pair to work with, because instead of writing this article contemporaneously, I just went ahead and coded motion, and it went pretty well. Oh, I got a lot of messages trying to execute nil
and the like, but all the problems were trivial. And I made the Orc move diagonally from the center toward one corner, then reverse and go toward the other corner, repeat until done. It looks like this:
The code changes were all in the Creature object:
Creature = class()
local CreatureMaxTime = 300
function Creature:init(entity, x, z, behaviors)
self.entity = entity
self.behaviors = behaviors or {self.walk}
entity.x = x
entity.z = z
entity.y = 2 -- just above the ground
entity.model = craft.model("Blocky Characters:Orc")
entity.scale = vec3(1,1,1)/8
end
function Creature:update(dt)
dt = dt or DeltaTime
for _,b in pairs(self.behaviors) do
b(self)
end
end
function Creature:walk()
local speed = 60
self.time = self.time or CreatureMaxTime
self.mul = self.mul or 1
self.time = self.time - 1
if ( self.time <= 0 ) then
self.mul = -self.mul
self.time = 2*CreatureMaxTime
end
self.entity.x = self.entity.x + self.mul*1/speed
self.entity.z = self.entity.z + self.mul*1/speed
end
I added a behaviors
collection, initialized by default with self.walk
which is the function Creature.walk. That function, as you can see, just counts down from self.time
to zero, and when it gets to zero, it changes the sign of mul
, which results in the Orc going the other direction. It also sets the time to 2*CreatureMaxTime
, so that after starting in the center and going one way, it goes all the way back and forth after that.
The update
function sets dt (oops that should be local, and it’s a YAGNI violation since it’s not used), then loops through the behaviors
list calling each one, passing self
to it because it’s a method.
That’s all it took to make the little guy move. No changes on other tabs.
This is a really decent spike: it provides a simple behavior that can be elaborated as we go forward. I expect that we’ll have special functions to build behavior lists, as we have in the Braitenberg example, but we’ll deal with that when the time comes.
Not bad for a quick morning’s fun. Now to take the cat food home.
See you next time!
-
Brighton Agile Roundtable, the round table we sit at at the Brighton MI Barnes & Noble. ↩