Touch function within classes

I’m pretty lost when it comes to how the touch function works when it comes to classes and was wondering if anyone could help me solve this problem. My code (the touch function code isn’t mine) is below and whenever more than one ball is on the screen, they both move. Also, when one is removed from the table, they are all then removed. I would greatly appreciate any help.



--# Main
displayMode(FULLSCREEN)
function setup()
    c1 = color(255, 255, 255, 0)
    c2 = color(0,0,255)
    c3 = color(255, 0, 0, 255)
    balls={}
    counter = 250
    limit = 50
    thrust = 0
    gravity = 0
end

function draw()
    background(255, 255, 255, 255)
    rectMode(CENTER)
    fill(0)
    rect(WIDTH-100,HEIGHT-100,200,200)
    counter = counter + 1
    if counter > limit then
        if limit <= 240 and limit > 150 then
            limit = limit-50
        end
        counter = 0
        create()
    end
    for i,b in pairs(balls) do
        b:draw()
        if b.y < -100 then
            table.remove(balls,i)
        end
        end
end



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

function touched(touch)
    for i,b in pairs(balls) do
    b:touched(touch)
    end
end


--# Ball
Ball = class()

function Ball:init(x,y,d,t,g,c,vx,vy)
    -- 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
    self.velx = vx
    self.vely = vy
    self.velocity = {}
    self.newVelocity = vec2(0,0)
    self.touchcircle = false
    self.n = 0
    self.touches = {}
end

function Ball:draw()
    -- Codea does not automatically call this method
    fill(self.color)
    ellipseMode(RADIUS)
    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 
    self.y = self.y + self.vely
    self.x = self.x + self.velx 
    self.velx = self.velx * 0.98
    self.vely = self.vely * 0.98
    if self.x > WIDTH-self.diameter then
        self.velx = 0
        self.x = WIDTH-self.diameter
    elseif self.x < self.diameter then
        self.velx = 0
        self.x = self.diameter
    end
    if self.y > HEIGHT-self.diameter/2 then
        self.vely = 0
        self.y = HEIGHT-self.diameter/2
    end
    if self.x < WIDTH and self.x > WIDTH-200 and self.y < HEIGHT and self.y > HEIGHT-200 then
    table.remove(balls,b)
    end
end

function Ball:touched(touch)
    -- Codea does not automatically call this
    if touch.state == MOVING then
        self.newVelocity = vec2(touch.deltaX, touch.deltaY)
        table.insert(self.velocity, 1, self.newVelocity)
    end

    if touch.state == ENDED then
        for i = 1, 10 do
            if self.velocity[i] then
                self.n = self.n + 1.5
                self.vely = self.vely + self.velocity[i].y
                self.velx = self.velx + self.velocity[i].x
            end 
        end
        if self.n > 0 then
            self.velx = self.velx/self.n
            self.vely = self.vely/self.n
        end
    end
end



This should solve the problem with all of the balls being removed from the table:

--# Main
displayMode(FULLSCREEN)
function setup()
    c1 = color(255, 255, 255, 0)
    c2 = color(0,0,255)
    c3 = color(255, 0, 0, 255)
    balls={}
    counter = 250
    limit = 50
    thrust = 0
    gravity = 0
end

function draw()
    background(255, 255, 255, 255)
    rectMode(CENTER)
    fill(0)
    rect(WIDTH-100,HEIGHT-100,200,200)
    counter = counter + 1
    if counter > limit then
        if limit <= 240 and limit > 150 then
            limit = limit-50
        end
        counter = 0
        create()
    end
    for i,b in pairs(balls) do
        b:draw()
        if b.y < -100 then
            table.remove(balls,i)
        end
        if b.x < WIDTH and b.x > WIDTH-200 and b.y < HEIGHT and b.y > HEIGHT-200 then
            table.remove(balls,i)
        end
    end    
end



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

function touched(touch)
    for i,b in pairs(balls) do
    b:touched(touch)
    end
end


--# Ball
Ball = class()

function Ball:init(x,y,d,t,g,c,vx,vy)
    -- 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
    self.velx = vx
    self.vely = vy
    self.velocity = {}
    self.newVelocity = vec2(0,0)
    self.touchcircle = false
    self.n = 0
    self.touches = {}
end

function Ball:draw()
    -- Codea does not automatically call this method
    fill(self.color)
    ellipseMode(RADIUS)
    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 
    self.y = self.y + self.vely
    self.x = self.x + self.velx 
    self.velx = self.velx * 0.98
    self.vely = self.vely * 0.98
    if self.x > WIDTH-self.diameter then
        self.velx = 0
        self.x = WIDTH-self.diameter
    elseif self.x < self.diameter then
        self.velx = 0
        self.x = self.diameter
    end
    if self.y > HEIGHT-self.diameter/2 then
        self.vely = 0
        self.y = HEIGHT-self.diameter/2
    end
end

function Ball:touched(touch)
    -- Codea does not automatically call this
    if touch.state == MOVING then
        self.newVelocity = vec2(touch.deltaX, touch.deltaY)
        table.insert(self.velocity, 1, self.newVelocity)
    end

    if touch.state == ENDED then
        for i = 1, 10 do
            if self.velocity[i] then
                self.n = self.n + 1.5
                self.vely = self.vely + self.velocity[i].y
                self.velx = self.velx + self.velocity[i].x
            end 
        end
        if self.n > 0 then
            self.velx = self.velx/self.n
            self.vely = self.vely/self.n
        end
    end
end

As for making only one ball move with the swipe, I don't know how to do. How are you going to know which ball to control?

@Saturn031000 I tried something like this

function Ball:init()
touchcircle = false
end

function Ball:touched(t)
If t.state == BEGAN and t.x < self.x + self.diameter and t.x > self.x + self.diameter and t.y < self.y + self.diameter and t.y > self.x - self.diameter then
touchcircle = true
end

And added “and touchcircle == true” to the moving and ended parts. It registered the Boolean as true to each ball, but they stopped being able to move. By the way the self.diameter is actually the radius.

@Staples This isn’t a fix for your code, but here’s an example that shows 2 balls that you can drag individually. Once you lift your finger, that ball is removed from the table and another random ball is added. This might help you understand how to keep touches seperate.


displayMode(FULLSCREEN)

function setup()
    tab={}
    table.insert(tab,ball(math.random(WIDTH),math.random(HEIGHT),50))   
    table.insert(tab,ball(math.random(WIDTH),math.random(HEIGHT),50))                  
end

function draw()
    background(40, 40, 50)
    for a,b in pairs(tab) do
        b:draw()
        if b.remove then
            table.remove(tab,a)
        end
    end    
end

function touched(t)
    for a,b in pairs(tab) do
        b:touched(t)
    end
end

ball=class()

function ball:init(x,y,s)
    self.x=x
    self.y=y
    self.size=s   
    self.id=0
    self.remove=false
end

function ball:draw()
    fill(255)
    ellipse(self.x,self.y,self.size*2)    
end

function ball:touched(t)
    if t.state==BEGAN then
        v1=vec2(t.x,t.y) 
        d=v1:dist(vec2(self.x,self.y))
        if d<self.size and self.id==0 then
            self.id=t.id
        end       
    end
    if t.state==MOVING and t.id==self.id then
        self.x=t.x
        self.y=t.y
    end
    if t.state==ENDED and t.id==self.id then
        self.id=0   
        self.remove=true
        table.insert(tab,ball(math.random(WIDTH),math.random(HEIGHT),50))                  
    end
end

@Staples Here’s your code with the touches fixed. It was too easy getting the balls in the black corner, so I made it smaller.


--# Main
displayMode(FULLSCREEN)
function setup()
    c1 = color(255, 255, 255, 0)
    c2 = color(0,0,255)
    c3 = color(255, 0, 0, 255)
    balls={}
    counter = 250
    limit = 50
    thrust = 0
    gravity = 0
end

function draw()
    background(255, 255, 255, 255)
    rectMode(CENTER)
    fill(0)
    rect(WIDTH-50,HEIGHT-50,100,100)
    counter = counter + 1
    if counter > limit then
        if limit <= 240 and limit > 150 then
            limit = limit-50
        end
        counter = 0
        create()
    end
    for i,b in pairs(balls) do
        b:draw()
        if b.remove then
            table.remove(balls,i)
        end
    end
end

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

function touched(touch)
    for i,b in pairs(balls) do
        b:touched(touch)
    end
end

--# Ball
Ball = class()

function Ball:init(x,y,d,t,g,c,vx,vy)
    self.x = x
    self.y = y
    self.diameter = d
    self.thrust = t
    self.gravity = g
    self.color = c
    self.velx = vx
    self.vely = vy
    self.velocity=0
    self.newVelocity = vec2(0,0)
    self.n = 0
    self.id=0
    self.remove=false
end

function Ball:draw()
    fill(self.color)
    ellipseMode(RADIUS)
    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 
    self.y = self.y + self.vely
    self.x = self.x + self.velx 
    self.velx = self.velx * 0.98
    self.vely = self.vely * 0.98
    if self.x > WIDTH-self.diameter then
        self.velx = 0
        self.x = WIDTH-self.diameter
    elseif self.x < self.diameter then
        self.velx = 0
        self.x = self.diameter
    end
    if self.y > HEIGHT-self.diameter/2 then
        self.vely = 0
        self.y = HEIGHT-self.diameter/2
    end
    if self.x > WIDTH-60 and self.y > HEIGHT-60 then
        self.remove=true
    end
end

function Ball:touched(touch)
    if touch.state==BEGAN and self.id==0 then
        v1=vec2(touch.x,touch.y)
        d=v1:dist(vec2(self.x,self.y))
        if d<self.diameter then
            self.id=touch.id
        end
    end
    if touch.state == MOVING and touch.id==self.id then
        self.newVelocity = vec2(touch.deltaX, touch.deltaY)
    end
    if touch.state == ENDED and touch.id==self.id then
        self.n = self.n + 1.5
        self.vely = self.vely + self.newVelocity.y
        self.velx = self.velx + self.newVelocity.x
        self.id=0
    end
end

@dave1707 sorry for the delayed response. I fixed my code with the help of your first code. For some reason, my iPad won’t let me copy your second code, but I’m sure it’s great in action. I’ll test it out later. Thanks!