Using classes with a timer

I am trying to use a class to draw a ball that animates on the screen. This would be simple by doing for example Ball:draw() , but I also have a timer

counter = counter + 1
    if counter > limit then
        if limit < 181 and limit > 80 then
            limit = limit - 10
        elseif limit < 81 and limit > 40 then
            limit = limit - 5
        elseif limit < 41 and limit > 30 then
            limit = limit - 1 
        elseif limit < 30 then
            limit = limit - 0.1
        end
        counter = 0
        Ball:draw()
    end

and using it as I am, it doesn’t work because it is only being called once and needs to be called every frame. How can I get this to work?

this code needs to go in your main draw function, then it will get run every frame

@Ignatz It is there, but because counter must be greater than limit, when counter is then set to 0, Ball:draw() is never drawn.

I don’t understand the problem, isn’t the timer there to decide when the ball is drawn? If so, isn’t it working properly?

If you want the ball drawn every frame, take it outside the if statement

@Ignatz when Ball:draw() is called, it calls an animation that lasts a couple of seconds. So, when Ball:draw() is called where it is, it is only called for one frame because counter = 0 sets counter to less than limit. So the timer works for the first ball if I set a Boolean e.g. Go = false in setup. Then I declare go = true instead of Ball:draw() and outside of the statement,

If go == true then
Ball:draw()
End

This works, but only for the first one because you can’t keep resetting the Boolean because multiple balls will eventually be drawn on the screen and that would only allow for one. If you still don’t understand, I can pm you my whole code (it’s not very long).

Yep, I suggest you post all your code, just put it here in the forum, one of us will fix it


--# Main
-- radial gradient
displayMode(FULLSCREEN)
function setup()
    c1 = color(255, 255, 255, 0)
    c2 = color(0,0,255)
    c3 = color(255, 0, 0, 255)
    yellow = color(255, 250, 0, 255)
    green = color(0, 255, 0, 255)
    g = radial(250,c1,green)
    y = radial(250,c1,yellow)
    blue = radial(250, c1, c2)
    r = radial(250,c1,c3)
    balls={}
    counter = 250
    limit = 180
    thrust = 20
    gravity = 0
    b1 = Ball(WIDTH/2,-100,50,20,0,c2)
    go = false
end

function draw()
    background(255, 255, 255, 255)
        
    counter = counter + 1
    if counter > limit then
        if limit < 181 and limit > 80 then
            limit = limit - 10
        elseif limit < 81 and limit > 40 then
            limit = limit - 5
        elseif limit < 41 and limit > 30 then
            limit = limit - 1 
        elseif limit < 30 then
            limit = limit - 0.1
        end
        counter = 0
        go = true
    end
end



--# Ball
Ball = class()

function Ball:init(x,y,d,t,g,c)
    -- you can accept and set parameters here
    self.x = x
    self.y = y
    self.diameter = d
    self.thrust = t
    self.gravity = g
    self.color = c
end

function Ball:draw()
    -- Codea does not automatically call this method
    fill(self.color)
    ellipse(self.x,self.y,self.diameter)
    self.y = self.y + self.thrust - self.gravity
    self.thrust = self.thrust * 0.98
    self.gravity = self.gravity + 0.05 
end

function Ball:touched(touch)
    -- Codea does not automatically call this method
end

@Staples - you can do this most simply by setting a variable that tells Codea whether the ball is being animated at the moment. So when the counter hits the limit, you set

animating=true

then you have this statement in draw(), but outside the if statement, so it runs every time that draw() runs

if animating then Ball:draw() end

This will keep drawing the ball until animating is turned off.

So your Ball:draw() function needs to set animating=false, when the animation finishes.

@Staples I added the 3~'s to format your code.

@Staples - I couldn’t see how Ball:draw() was running a two second animation, it just seems to adjust position and draw the ball.

Can you clarify what you want to draw when the counter is below the limit, and how it changes when it hits the limit?

Every time counter is larger than limit, I want a ball to pop up and for now, fall down. The code is a little different to how it was originally because I was trying to get it to work. As of right now, they are not deleting when they fall back down, but I think I can handle that. The counter is the main problem.

@Ignatz doesn’t this only work for one ball. I want a new ball to come onto the screen every time counter is greater than limit. This will eventually lead to multiple balls on the screen.

@Staples - then you need a table containing balls, and each time the counter hits the limit, you add a ball to the table

table.insert(ballsTable,Ball())

then after doing the if tests (still inside draw), you draw all the balls currently on the screen.

But the Balls:draw function needs to tell the main draw function when it is done, so the ball can be deleted from the table. Suppose Balls:draw returns true when it is done, then you can put this in your main draw function, both to draw, and delete if necessary, each ball

for i,b in ballsTable() do
    if b:draw() then ballsTable[i]=nil end --delete ball if Balls:draw returns true
end

NB untested

@Ignatz I think that will work, but where do I actually draw the balls I.e. Where do I put Ball:draw(), b1:draw, or b:draw?

@Staples - if you don’t know how to use classes, I suggest you do that before going any further

I explain them here

http://coolcodea.wordpress.com/2013/03/22/7-classes-in-codea/

http://coolcodea.wordpress.com/2013/03/23/8-classes-in-codea-2/

@Ignatz sorry this is taking so long! I’ve read your classes tutorials, but I’m still struggling with this. Here is my code, the ball is only being drawn once.


--# Main
-- radial gradient
displayMode(FULLSCREEN)
function setup()
    c1 = color(255, 255, 255, 0)
    c2 = color(0,0,255)
    c3 = color(255, 0, 0, 255)
    yellow = color(255, 250, 0, 255)
    green = color(0, 255, 0, 255)
    balls={}
    counter = 250
    limit = 180
    thrust = 20
    gravity = 0
    b1 = Ball(WIDTH/2,100,50,20,0,c2)
    go = false
end

function draw()
    background(255, 255, 255, 255)
        
    counter = counter + 1
    if counter > limit then
        if limit < 181 and limit > 80 then
            limit = limit - 10
        elseif limit < 81 and limit > 40 then
            limit = limit - 5
        elseif limit < 41 and limit > 30 then
            limit = limit - 1 
        elseif limit < 30 then
            limit = limit - 0.1
        end
        counter = 0
        create()
    end
    for i,b in pairs(balls) do
        b:draw()
        if b.y < 0 then table.remove(balls,i)end
    end
end

function create()
    table.insert(balls,b1)
end

--# Ball
Ball = class()

function Ball:init(x,y,d,t,g,c)
    -- you can accept and set parameters here
    self.x = x
    self.y = y
    self.diameter = d
    self.thrust = t
    self.gravity = g
    self.color = c
end

function Ball:draw()
    -- Codea does not automatically call this method
    fill(self.color)
    ellipse(self.x,self.y,self.diameter)
    self.y = self.y + self.thrust - self.gravity
    self.thrust = self.thrust * 0.98
    self.gravity = self.gravity + 0.05 
end

function Ball:touched(touch)
    -- Codea does not automatically call this method
end

@Staples - get rid of the line with b1 and use this

function create()
    table.insert(balls,Ball(WIDTH/2,100,50,20,0,c2))
end

@Ignatz finally! Thanks so much I couldn’t figure that out! Works great.