Thanks for all your feedback. John, I tried to use the body.info again with Codea 1.4.1 and now it works for me. But I possibly found a bug in Codea which might be interesting to fix. Or I have a bug in my code and I would be glad to get a hint. I stripped down the code to only contain the problem.
I create three types of objects: Balls, Catchers and Walls. The Balls and Catchers use the .info to store the class. In the collide function it checks, if a Ball and a Catcher collide and then print “Catched.”.
But when a Ball touches the wall, which has an emtpy .info (nil), then Codea completely crashes. But I check for nil in the collide function.
Just start the code and wait until the balls fall down. I’m sure this could be solved by having the wall done as class and a filled info, but I think it should not crash in the way it is done now, thats why i post it.
Ball = class()
function Ball:init(radius, col, x, y)
-- you can accept and set parameters here
self.what = "Ball"
self.col = col
self.body = physics.body(CIRCLE, radius)
self.body.info = self
self.body.type = DYNAMIC
self.body.x = x
self.body.y = y
self.body.interpolate = true
self.body.mass = radius / 100
self.body.restitution = 0.4
self.body.sleepingAllowed = false
self.body.bullet = true
--self.body.friction = 1
end
function Ball:draw()
-- Codea does not automatically call this method
pushMatrix()
translate(self.body.x, self.body.y)
rotate(self.body.angle)
r = self.body.radius * 2
stroke(0, 0, 0, 255)
fill(self.col)
ellipse(0, 0, r)
fill(0,0,0,255)
ellipse(r / 4, r / 4, r / 10)
popMatrix()
end
function Ball:touched(touch)
-- Codea does not automatically call this method
end
Catcher = class()
function Catcher:init(w, h, col, x, y)
-- you can accept and set parameters here
self.what = "Catcher"
self.col = col
self.w = w
self.h = h
self.x = x
self.y = y
self.body = physics.body(POLYGON, vec2(-w/2, -h/2), vec2(-w/2, h/2), vec2(w/2, h/2), vec2(w/2, -h/2))
self.body.info = self
self.body.x = x
self.body.y = y
self.body.type = STATIC
--self.body.fixedRotation = true
self.body.restitution = 0
self.body.sleepingAllowed = false
self.body.interpolate = true
self.body.gravityScale = 0
self.body.mass = 1
self.body.bullet = true
--racket.friction=0
end
function Catcher:draw()
-- Codea does not automatically call this method
-- Reset position
--self.body.x = self.x
--self.body.y = self.y
stroke(0,0,0,255)
fill(self.col)
pushMatrix()
translate(self.body.x, self.body.y)
rotate(self.body.angle)
rect(-self.w/2, -self.h/2, self.w, self.h)
popMatrix()
end
function Catcher:touched(touch)
-- Codea does not automatically call this method
end
--# Main
-- Use this function to perform your initial setup
function setup()
supportedOrientations(LANDSCAPE_LEFT)
--backingMode(RETAINED)
backingMode(STANDARD)
displayMode(STANDARD)
--displayMode(FULLSCREEN)
parameter("CreationDelta", 2, 10, 5)
balls = {}
catchers = {}
lastCreatedTime = 0
watch("lastCreatedTime")
watch("ElapsedTime")
goal = Catcher(200, 25, color(30, 150, 30, 128), WIDTH/2, HEIGHT * 1/32)
goal.body.angle = 2
table.insert(catchers, goal)
wall2 = physics.body(EDGE,vec2(0,0),vec2(WIDTH,0))
wall2.type = STATIC
wall2.info = nil
end
function collide(contact)
if contact.bodyA == nil or contact.bodyB == nil then
return nil end
local infoA = contact.bodyA.info
local infoB = contact.bodyB.info
-- check for collision
if infoA and infoB and contact.state == BEGAN then
print(string.format("%s : %s", contact.bodyA.info.what, contact.bodyB.info.what))
if contact.bodyA.info.what == "Ball" then
if contact.bodyB.info.what == "Catcher" then
print("Catched.")
end
elseif contact.bodyB.info.what == "Ball" then
if contact.bodyA.info.what == "Catcher" then
print("Catched.")
end
end
end
end
-- This function gets called once every frame
function draw()
--tint(255, 255, 255, 5)
background(255, 255, 255, 255)
stroke(0, 0, 0, 255)
strokeWidth(2)
if ElapsedTime > (lastCreatedTime + CreationDelta) then
lastCreatedTime = ElapsedTime
s=50
-- Balls should not be able to stack, so create a small random x - translation.
rnd = math.random() - 0.5
newBall = Ball(s, color(math.random(0,255), math.random(0,255), math.random(0,255), 128), WIDTH / 2 + rnd, HEIGHT - 25)
table.insert(balls, newBall)
currentBall = newBall
end
for i = 0, table.maxn(balls) do
if balls[i] == nil then
else
balls[i]:draw()
end
end
for i = 0, table.maxn(catchers) do
if catchers[i] == nil then
else
catchers[i]:draw()
end
end
end