Codea Craft and Documentation: Can we do better?

I’m thinking of starting an article series using Craft. I’d have kind of two angles. The first would be my usual learning by creating small programs that grow into larger programs. Some readers find those helpful in getting ideas of how to learn what the masses of code they are facing is all about.

The second notion would be to try to produce a sort of “linear” documentation of Craft, beginning at the beginning, and going as widely and as deeply as I can. Somewhere between a reference manual with examples, and a tutorial, I suppose.

Personally, I find the lack of any coherent narrative for Craft really irritating. There’s all this power. There are all these very complicated examples, many of which just do things without really explaining how they do them. Somewhere in those examples, maybe, there’s an example for what the reader might want to do, but it’s embedded in a program that does something else almost entirely.

I’m hoping to help create something better, perhaps both in terms of example code, and written documentation. I’m sure that I’ll need help finding examples, finding write ups, and so on. At this moment, I have no specific requests, but would appreciate questions and comments in this thread about whether this would be useful, what is needed, and most of all, how folks might help in small or large ways.

Thanks!

@RonJeffries Sounds good to me. I’d like to see something like that.

@ronjeffries - long time ago I started converting the reference section into pdf, with an appendix listing out the updates. All straight from the websites - my main reasoning was to add expanded examples to clarify command use etc. This was for my own use. Took up too much time so never completed it.

Do you think that would be a reasonable vehicle?

@RonJeffries it seems like you and me and a few others have come to the same conclusion about Craft—it’s got a ton of potential and a really opaque API.

My work with the Voxel Walker and the editor (and the texture pack fwiw) is motivated by the same awareness. It seems to me that we should have tons of cool Voxel worlds to walk around in by now. But we don’t. So I’m trying to make it easier for people to make cool things to walk around in.

That’s why I guess I’ve been focused on an example-by-example approach, and I think there’s possibly a salient perspective that’s come of it.

Basically, I think part of making Craft more accessible may be avoiding some of its systems altogether. Let me mention two examples, entity:add() and the touchHandler system.

entity:add() and the associated functions seem to be a somewhat confusing system for extending the abilities of Craft components, I think. In trying to simplify the camera setup in Voxel Walker, I’ve found that I don’t seem to need them. You can add properties and functions directly to entities, and thus extend their abilities without entity:add(). It might not be possible to jettison entity:add() with all the builtin examples, but at least with the Camera examples, you can achieve all the same functionality without it, and it results in code that’s much clearer to me.

The touchHandler system, too, I’ve come to regard suspiciously. It has some concerning pitfalls, not least of which that it seems to be completely incompatible with the default touched(touch) system. In short, as far as I can tell, using touchHandlers breaks touched(touch). It’s got some good features, to be sure, mainly that you can define how an object reacts to touches all inside its own code without having to route everything through that one touch function on the Main tab. But even so, it seems like it doesn’t add anything to Craft that can’t be done a simpler way, and it doesn’t play nice with the original Codea touch paradigm, which the vast majority of Codea projects rely on. And that makes a big hairy “gotcha” situation that newbie Craft users can get stuck in (like I did).

Now, I’m not anywhere near familiar enough with the API to definitively assert that no one should ever use entity:add() or touchHandlers, but I think this brings up a point that deserves some thought: in addition to being confusing, some of the Craft API may be better avoided when possible.

And if, for example, it would be better for people to ignore touchHandlers, it could actually be counter-productive to document it and create examples for it.

I don’t have a tidy conclusion to offer but I think the matter may deserve some discussion.

yes. the doc repo @John mentions might help. but i’m finding it daunting, as today’s slog of an article shows. i could learn faster by doing bigger things, but they’d be more cut paste, less real understanding.

but that article is so boring, maybe i need to learn a lot and only then write.

@Bri_G your pdf thing sounds good. maybe access to john’s repo is better, i’ll try to look at that. i suspect markdown format would be preferable to pdf, but don’t know what they have now.

it would help if all the craft example code in the docs could run. maybe there needs to be a place to plug it in, to save duplication …

at this point, i just don’t know, still floundering.

Might I suggest making the problem at hand the problem at hand?

What if the first aim of the articles was to make the very judgment call under discussion?

Like, the whole point could be playing with the systems presented to us, so as to gauge if they’re worth documenting in the first place?

I’m sorry, I don’t grasp the idea …

Maybe it’s not a good idea then lol!

Your articles are like explorations, at least that’s how they read to me: you have a goal, you try some things, you see how those things work, and you watch your own thought process and report on it.

I was just wondering if, before creating an exhaustive documentation of any given Craft way of doing things, there might be a step exploring the question “is this a good way to do things in the first place?”

Attached: the project I made as my first attempt to learn Craft, way way back when it first came out: “Li’l Learn Craft.”

I found the Learn Craft project of little help, so to better understand it I tried to make a clearer version of it.

It’s rudimentary, but possibly worthwhile to examine in the context of the question “what do we want examples to do?”

TouchHandler and OrbitViewer are definitely not that great. They were just made for the examples and come with some annoying baggage. It’s part of the issue with mixing declarative processing style code with OOP based design and is tricky to solve cleanly

@UberGoober Can you explain what the issue is with entity:add(component)?

All add() does is add a component to an entity and feed it events about the lifecycle of the entity. The built-in components use this system automatically. Adding a script to your entity (i.e. a class) will call update(dt) when the scene is updated. It’s pretty similar to Unity’s gameObject.addComponent<Type>()

The advantage being that you can mix and match multiple re-useable component types on the same entity to avoid having big monolithic classes. You can also use :has() and :get() to check if an entity has a component or :remove() to get rid of it. Shortcuts like entity.model and entity.material handle components for you (i.e. adding a renderer component for you)

@RonJeffries if you want me to explain how anything works, let me know

@John I want to be clear that I really like Craft. If I’m questioning the value of sweating over making certain documentation, I know it comes from my limitations as much as or more than anything else.

Like you just said, the declarative style and OOP don’t always fit together cleanly, and tbh one of the advantages of Codea, and often part of the fun, is that you can achieve fairly complex things really easily, and that’s explicitly because you don’t have to worry about OOP. So the more OOP-style Craft paradigms sometimes make me feel a kind of torn loyalty.

The entity:add() system seems really elegant and powerful and clear when described, and in practice I just don’t seem to be able to get my head around it. This mostly comes up around trying to understand cameras.

I made this little “rig” system that I’ve been using for cameras because, while working on the Voxel Editor, I kept trying to manually place the ‘player’ at a certain place, and I couldn’t seem to do it. There seemed to be multiple entities involved, and then the camera and the viewers each have some kind of associated entity, maybe, I think, I’m never totally sure, and I didn’t seem to be able to get anywhere by setting a simple “position” value on any of them.

So I just tried to make it simpler for myself. If you look at the code in my most recent Voxel Walker zip (also attached here), it should be pretty easy to see what I’ve done, because for the most part I’ve just snipped up your existing code and organized it all a very slightly different way. My overall goal, though, was to have the whole setup simple enough that if I wanted to place or rotate something I always knew exactly how to do it.

@UberGoober the rig concept you’ve got looks pretty interesting, it looks like you’ve focused on the idea of procedural setup functions, that apply a specific configuration to an entity

If I were to do a component based version of the same thing I would make it look something like this:

scene = craft.scene()

-- Get the default scene camera and apply a first person rig
-- This automatically gets/or adds a camera and registers for touches
scene.camera:add(CameraRig.FirstPerson)

The entity:add() method returns the thing you created so you don’t have to call get after

The code would be almost exactly the same as yours, but use a class instead of functions, i.e.

CameraRig = class()
-- shared camera rig functions, etc...

...

CameraRig.FirstPerson = class(CameraRig)

function CameraRig.FirstPerson:init(entity)
  assert(entity.hasCameraRig == false, "Entity already has a rig!")
  entity.hasCameraRig = true

  entity.camera = entity:get(craft.camera) or entity:add(craft.camera, 45, 0.1, 1000, false)

  -- etc...
end

function CameraRig.FirstPerson:update(dt)
  -- any additional stuff that needs to be updated each frame
end

...

CameraRig.FirstPerson = FirstPersonCameraRig

I’m realising now, that there should probably be component:added() and component:removed() methods that would be called automatically when the component is added and removed. There is already a component:destroyed() which is called when the entity is destroyed. This would let you automatically clean up your component like you have with the clearRig(camEntity) method.

I do like how you’ve used custom properties on entities to store extra information, which is a perfectly valid way of using them.

@John that seems like a good way to go about things, though the OOP pattern constrains rigs to being one-per-entity.

In the Player above, I found myself creating a rig for attaching a rigidbody to an entity, which has nothing to do with cameras, and in fact to compose the Player, I’m actually piling a few rigs on top of each other, in a way that could conceptually be chained together like this:


playerBody = cameraHybrid(scene)
      .joystickRig(params)
      .rigidCapsuleRig(params)
      .joystickPlayerRig(params)

It seems to me that the main thing lost in my version of the rig pattern is the ability to remove a component from an entity, but when I think on it, I can’t recall anything I’ve come across in the examples or in my own usage where I absolutely needed the ability to remove a component.

Yeah, I hadn’t considered your other rigs, but I feel like there is a way to combine these. Adding new methods to the entity also looks pretty interesting. Like your joystickPlayerRig jump function. My version only restricted it to one camera rig, since I don’t see how you would need more than one thing controlling the camera at once

Codea 4 should be interesting since having a Library folder that works with require should make it pretty easy to add lots of extensions, even to the point where you could just have:

require 'uber/rigs'

...

myEntity.rigs:firstPersonCamera():joystick():rigidCapsule():joystickPlayer()

or something to that effect

interesting stuff above, @UberGoober and @John. I think, for now, I’ve just decided that a tutorial is a good idea and I’m going to try it until it isn’t a good idea, or until I get tired of doing it. So …

  1. I’ll try writing some basic tutorial stuff for Craft. If I show my exploration at all, it’ll be as sidebars. The articles will focus on “do this, here’s what’s going on” with code that I’ve already made do whatever it is.
  2. I plan to use the OrbitViewer because it exists. Somewhere down the road, I’ll explore what it is and how it works.
  3. The camera rigs sound quite interesting, and I can imagine pulling that idea into the series at some point. Right now, I haven’t explored the rigs enough to have a feeling, and freely grant that I don’t quite get the general idea of what a “rig” means to you, @UberGoober.
  4. I appreciate the offer of help, @John. Are questions here the best way to ask? If not, let me know. In particular, where might I have found out about :has and :get? Is there code I should/could read as background info?
  5. Agreed on the value of added and removed methods.
  6. I heartily approve of the use of classes in this, and would urge greater consistency in doing that, and in the details of the resulting classes.

Anyway I think I’ll get down to writing the first tutorial bit and see what happens.

Thanks, folks! Let’s see if we can build up some momentum and get some more good things happening.

@RonJeffries I think I can explain rigs simply.

Craft’s camera:add() is conceptually straightforward: to add features and controls to craft.camera, you don’t subclass it, you write a separate “helper” class, give it all the functions and properties it needs, and then “add” it to the camera.

All rigs do is take an entity and add the camera, the properties, and the functions directly to it. No custom object necessary, you’re just “rigging up” a normal entity object. That’s it.

You can literally cut-and-paste the code from a helper class into a rig; the attached example project shows rigs that do just that with the OrbitViewer and the FirstPersonViewer.

I’ll have to read it, I guess. My question was more “what are rigs, in general, in your mind? what do they mean to you, how are they different from other ways, what do they bring to the table for you?”

Here’s today’s article, a cut at a tutorial style.

@UberGoober do you know what the sensitivity, depth buffer clearing and color clearing are about? I see that you have setters and getters for them …

This is a very early impression and I mean it to be helpful not irritating. :smile:

The rigs, especially the orbitviewer one seem very flat. I’d hope that there would be more depth to the tree of capability, which might be easier to obtain if the rigs used classes directly rather than just functions.

Does that make sense?

I think I may disagree with @John on the idea of tapping new custom properties into the existing entities. I have at least these concerns with it:

  1. There is a danger that one will clobber an existing system property;
  2. There is a danger that Joe’s properties will clobber Jane’s;
  3. Reading the code, it is nearly impossible to determine which properties are standard and which are local to some particular rig or other code.

I think it would be better if Codea were to:

  1. Expose a standard place for added properties, like `entity.properties;
  2. Provide an interface that’s better than `e.properties.propX = mumble, so that people still can’t accidentally hit each other’s properties.

Failing that, it would be wise if folks adding properties to an entity were at least to give their properties names like uberPropX rather than just propX. But a good general rule, it seems to me, is not to extend system objects and classes.