Spacewar! 07 - Maybe there should be a way to drive these babies.
Today Tozier and I think we’ll try to figure out how to do controls for Spacewar. At first we thought maybe no but decided the game would be boring. We need to learn how touching the screen works in Codea.
My recollection from reading and experimenting is that each time you touch, or drag a finger, or lift a finger, there is a touched
event, which has various fields, state, x, y, and so on. It seems like you get a touched
event for every finger on the screen, every time through the draw loop. Unless your finger isn’t moving, in which case you don’t get an event.
That’s recollection. We needed to verify that and start to learn what’s true. We wrote this little program:
-- Controls
function setup()
Touches = {}
end
function draw()
background(40, 40, 50)
t = "Touches:"
for k,v in pairs(Touches) do
t = t .. "\n" .. k .. ": " .. v
end
text(t, WIDTH/2, HEIGHT/2)
end
function touched(touch)
if touch.state == ENDED then
Touches[touch.id] = nil
else
Touches[touch.id] = "yes"
end
end
This results in a text line on the screen for each finger you put down:
MOVIE HERE
I thought it’d be fun to enhance this program to draw a circle where each finger goes down. Tozier demurs. He suggests that we should draw a circle and display something only if the touch is inside the circle. I am nothing if not reasonable, as all attest, so that’s what we’ll do.
Here’s what we came up with:
-- Controls
function setup()
Touches = {}
Center = vec2(WIDTH*.25, HEIGHT/2)
Radius = 100
end
function draw()
background(40, 40, 50)
ellipseMode(RADIUS)
blendMode(ADDITIVE)
pushStyle()
fill(255, 0, 0, 255)
ellipse(Center.x, Center.y, Radius)
popStyle()
t = "Touches:"
for id, touch in pairs(Touches) do
inside = "no"
if insideCircle(touch.x, touch.y) then inside = "yes" end
t = t .. "\n" .. id .. ": " .. inside
ellipse(touch.x, touch.y, 30)
end
text(t, WIDTH/2, HEIGHT/2)
end
function touched(touch)
if touch.state == ENDED then
Touches[touch.id] = nil
else
Touches[touch.id] = touch
end
end
function insideCircle(x,y)
return Center:dist(vec2(x,y)) <= Radius
end
MOVIE HERE
Wow, so how did that happen? A lot went on.
First we drew a big red circle (but not as big as in the movie). Then we built the Touches table you see above. We had it keyed by touch.id and containing a string as in the previous model. But then we couldn’t see x and y, so we indexed the table by the touch (the parameter to the touched
function instead, and drew a little grey circle where the touch was. The universe exploded.
We got a grey smear, as if the circles weren’t erasing, and the text got longer and longer until finally everything seemed to stop. It looked to me as if we had stopped erasing the background, which lets things build up like that. But no.
We finally realized that on each touch, we got a different touch “object”, with a matching ID based on some magic inside Codea. So we had to go back to indexing by id, and storing the touch. That required us to move the code around as you see it now.
Normally, I write these things as I go. For some reason I’ve not been doing that so far. I’m kind of glad because we’d really look stupid up until now. Anyway …
Then Tozier noticed that the message “yes” came out before the little finger circle actually got inside the big red circle. We learned by the well-known RTFM method that the normal mode for ellipses is to draw width (and optionally height), not radius. So we put in the ellipseMode
call and got the big circle you see, and now the word changes when your finger (circle center) is actually inside.
Tozier is attracted to shiny objects and saw the word blendMode
, so we set the mode to ADDITIVE, which makes the finger circle color have a transparent look when it’s over the red circle.
It occurs to me to wonder about all this “playing around”. Should we be more serious, more heads-down, more directly addressing the Real User Story, which is something about having buttons on the screen? Well, there’s maybe an hour’s work here, and now we know a lot of things we didn’t know about how touches work in Codea. So back off, OK?
Summing up …
This is a good place to pause, it being 11 o’clock, but we’ll sum up what we’ve learned and plan a bit for tomorrow.
Q: there will be control objects, owning a region. Will the control tell the ship turn left or whatever, or will the ship ask the control, do you think I should turn left? (Is there another possible way?)
Q: does each control receive all touches or are they somehow filtered “above”? The latter would be more efficient but might cause us to have to create a place to stand.
Q: touched occurs naturally only in Main and must be passed on. To whom?