I feel I’ve got my feet firmly on the grass, dirt, and bedrock, and I can see what I’m doing. Time to become confused again.
The code, as shown yesterday, could still use a bit of cleaning. But I feel that I have a few basic concepts coming under control. I don’t know all the ins and outs, but I feel I have a good understanding of the things in the “game” so far.
I was thinking this morning about how I’d begin to write an introduction to Codea, and felt I could do it. Maybe I’ll start that real soon now: it might be useful to someone. But the point is, I’m starting to get a conceptual grasp that I didn’t have before. And if you’ve been following along, perhaps you are as well.
A separate lesson that these articles might offer is a sense that its OK to be confused by a big framework like this, and a few ideas on how to begin to slice things apart to learn about them.
Be that as it may, I feel that I’ve cracked the basic problem of having a small runnable version of the “product” that I can evolve fairly quickly.
Of course we’ve only begun to scratch the surface. Here are a few of the things our game will need:
- Terrain - Craft has a powerful terrain capability with the ability to stream a huge terrain space, with cubes out to coordinates of two billion. (I’m told that it slows down out there.) There’ll be a bunch to learn there.
- Player - We’ve just got a camera view right now. We’ll need some kind of entity to serve as a player. The Codea sample uses a capsule with physical properties to detect running into walls and such.
- Inventory - Whatever the game is, it will surely include an inventory of cubes and other game items.
- UI - We’ll probably need some kind of joypad to drive our player around, so that screen touches mostly affect the world, placing blocks, digging, making blocks do whatever they do.
- Behavior - Blocks will have behavior. Some standard interface will be required in order to make them do things. There are samples in the Craft examples.
- NPCs - We may want to implement non-player characters, some kind of creatures that exist in the world and interact with our player.
- AR - Craft can do augmented reality things. We could have our player play on the floor, perhaps, or build a castle on the table. Could be amusing.
But wait, there’s more. Here are some Codea and Craft topics that will probably turn up:
- Camera - We have probably seen 60% of what we need with the camera, but there is zooming to think about.
- Ray-casting - We’ll need to cast rays (or spheres) to figure out what the user is touching when she touches the screen.
- Models and Assets - There are some nice block resources to copy, and more available on the Internet, but we will need to learn more about how to use those assets, and if this were a real game, we’d need to learn how to create our own. This is mostly, if not entirely, done in other tools outside Codea.
- Chunks - This has something to do with the overall size of the world, which is some number of chunks of a specified or default size.
- Voxel Details - There are many details, such as fill style (replace, union, clear, etc), update; iterate a callback; block data; and more. We’ll probably encounter these as we go.
- Voxel Volume - At this moment I have no idea what that is, but it’s in there.
- Noise - Noise generators to be used in the creation of content. I suppose these are used to create random terrain or the like. Again, no real idea.
Suffice to say, there’s far more still inside the box than we’ve learned about. But we can likely learn as we go. We need to learn enough, from the examples or our own experiments, to build up a sense of where to look, but the details can probably wait.
All that’s for another day. We’re on our way. Now let’s look at our code and see what it’s asking for:
-- GameCamera -- RJ 20200226 -- RJ 20200227 move camera rotation inside; cleanup GameCamera = class() function GameCamera:init(entity) self.entity = entity self.camera = entity:get(craft.camera) Camera = self.camera self.rx = 0 self.ry = 0 self.rz = 0 self.distance = 20 self.target = vec3(8,0,8) self.camera.ortho = false self.camera.orthoSize = 5 self.camera.fieldOfView = 60 end function GameCamera:update(dt) if CurrentTouch.state == MOVING then self.rx = self.rx - CurrentTouch.deltaY * 0.25 -- note XY inversion self.ry = self.ry - CurrentTouch.deltaX * 0.25 end local rotation = quat.eulerAngles(self.rx, self.ry, self.rz) self.entity.rotation = rotation self.entity.position = -self.entity.forward * self.distance + self.target end
This is pretty simple and needs almost nothing. There’s that creation of a global
Camera. That’s a vestige of the past and should go. Done, code committed.
This code isn’t really fielding touch events at all, which is good enough for now. In due time that will have tochange. For now … not bad.
-- blocks -- RJ 20200222 -- ERJ 20200226 fixed dirt grass function blocks() scene.voxels.blocks:addAssetPack("Blocks") local dirt = scene.voxels.blocks:new("Dirt Grass") dirt.setTexture(ALL, "Blocks:Dirt Grass") dirt.setTexture(UP, "Blocks:Grass Top") dirt.setTexture(DOWN, "Blocks:Dirt") local bedrock = scene.voxels.blocks:new("Bedrock") bedrock.setTexture(ALL, "Blocks:Greystone") local allBlocks = scene.voxels.blocks:all() return allBlocks end
This is entirely ad hoc, of course. Just created a couple of blocks and painted them. We’ll need to expand this to create a variety of blocks, some very simple, like our
bedrock, and some with complicated behavior, like the fence we looked at in a previous article. All that will come in due time, and there are examples to explore.
-- Game-1 -- RJ 20200222 initial plan, make a floor -- RJ 20200226 camera object works w/o touch -- RJ 20200227 cleanup function setup() scene = craft.scene() -- Setup camera and lighting scene.sun.rotation = quat.eulerAngles(25, 125, 0) -- Set the scenes ambient lighting scene.ambientColor = color(127, 127, 127, 255) allBlocks = blocks() -- Setup voxel terrain local m = 1 -- 5 scene.voxels:resize(vec3(5,1,5)) scene.voxels.coordinates = vec3(-16*m,0,-16*m) scene.voxels:fill("Dirt Grass") scene.voxels:box(0,2,0,16*m,2,16*m) scene.voxels:fill("Bedrock") scene.voxels:box(0,0,0, 16*m,0,16*m) setupCamera(scene) end function setupCamera(scene) scene.camera:add(GameCamera) end function update(dt) scene:update(dt) end function draw() update(DeltaTime) scene:draw() end
Not much to see here, but it’s a bit messy and not consistent. We can break out the setup a bit, applying “Composed Function” pattern or the “Single Level of Abstraction Principle” (SLAP).
Color and lighting could be broken out (and we’ll want to learn more of course).
scene is global and shouldn’t be.
So we could and should do a bit of cleanup before moving on. But that’ll be for next time. This morning is used up, writing this, signing up for deliver:Agile, and various other activities.
See you next time!