I’m trying to wrap my head around classes, but getting kind of thrown off.
I’m setting up a class that creates a physics.body circle and giving it an ellipse shape in the class draw function, then trying to draw it in the main function but it isn’t showing up and is giving an error. Anyone see what I’m doing wrong? I’m new to using classes, so this is probably a super simple question.
Here is the code I’m messing with:
-- Classes
-- Use this function to perform your initial setup
function setup()
physics.continuous=true
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(0,0,0,255)
Player:draw()
end
Player = class()
function Player:init(x,y)
self = physics.body(CIRCLE,32)
self.linearvelocity= vec2(math.random(-256,256), math.random(-256,256))
self.x=WIDTH/2
self.y=HEIGHT/2
self.restitution=1
end
function Player:draw()
fill(0,255,0,255)
ellipse(self.x,self.y,64)
end
Thanks but still getting an error in the ellipse part of the class. Is it because I’m using “self” which tells Codea that there will be more than one instance of Player, but only creating one?
I messed with classes before for creating multiples of the object created in the class, using “self” to define things, but I created a table and did for I=1,#Player then, and created multiple instances of it and it worked, but just creating one from a class doesn’t seem to work.
-- Classes
-- Use this function to perform your initial setup
function setup()
physics.continuous=true
ply = Player(WIDTH/2,HEIGHT/2)
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(0,0,0,255)
ply:draw()
end
Edit: your player class should look like this, as you cannot assign ‘self’ as a variable. ‘self’ is what the class consists of so in the case of the following:
Player = class()
function Player:init(x,y)
self.pb = physics.body(CIRCLE,32)
self.pb.linearvelocity= vec2(math.random(-256,256), math.random(-256,256))
self.pb.x=WIDTH/2
self.pb.y=HEIGHT/2
self.pb.restitution=1
end
function Player:draw()
fill(0,255,0,255)
ellipse(self.pb.x,self.pb.y,64)
end
this wont work. The physics body lives its own life: put it somewhere, then check where it is to draw it. self.x and self.x wont update by themselves. Check what i have to do to get it working in http://codea.io/talk/discussion/6224/gaz-simulation.
here is come code. the. ball:update() must be called at each draw for instance.
Ball = class()
local rand = math.random
function Ball:init(x,y,r)
self.x = x
self.y = y
self.r = r or 10
self:initAssets()
-- physics body
self.body = physics.body(CIRCLE, self.r)
self.body.x = self.x
self.body.y = self.y
self.body.sleepingAllowed = false
self.body.gravityScale = 0
self.body.linearVelocity = vec2(rand(400)-200,rand(400)-200)
self.body.linearDamping = 0
self.body.fixedRotation = true
self.body.friction = 0
self.body.restitution = 1
self.body.info = self
self.body.bullet = true
-- events
World:on("update",self.update,self)
World:on("delete",self.delete,self)
self:update()
self:updateColor()
end
local ms
function Ball:initAssets()
if not ms then
ms = mesh()
local img = image(10,10)
setContext(img)
ellipseMode(CORNERS)
fill(255)
noStroke()
ellipse(0,0,10,10)
setContext()
ms.texture = img
World:on("draw",function() noSmooth() ms:draw() end)
end
self.w = 2*self.r
self.h = 2*self.r
self.iRect = ms:addRect(self.x,self.y,self.w,self.h)
end
function Ball:update()
local pos = self.body.position
self.x, self.y = pos.x, pos.y
ms:setRect(self.iRect, self.x,self.y,self.w,self.h)
end
function Ball:delete()
self.body:destroy()
World:off(self)
end
function Ball:updateColor()
-- lets change color
local x = self.body.linearVelocity:len()/300*255
local r,g,b, a = x, 64, 255-x, 255
self.color = color(r,g,b,a)
ms:setRectColor(self.iRect, self.color)
end
function Ball:collide(c,obj)
self:updateColor()
end
@Jmv38 your code has unnecessary steps. Bodies do have an x and y value that automatically updates. The position value wraps these in a vec2. You can use either position or x/y, but you don’t have to use both. @Luatee 's code works fine.
EDIT I’m probably being unfair to @Jmv38 here, I didn’t notice that @Luatee had edited the post, so maybe when Jmv38 said “that won’t work” he was referring to the pre-edit version, before the body was assigned to self.pb.
Thanks @Luatee that works how I was hoping it would. Not sure why the self.pb.linearvelocity line isn’t effecting the ball though.
So the “pb” in self.pb can be any variable like self.body, self.b, self.whatever, as long as you are consistent with it? And you must use a variable like “pb” after self?
Can you use that same variable (pb) in multiple classes? Or the variable has to be different for each class?
Last question… I’m confused as to why we have to define the position again in function setup() with ply = Player(WIDTH/2,HEIGHT/2) when it is already defined in the class.
@Crumble yes that is the case, it’s just a variable name with self. before, as you have to link it to the class somehow. ‘self’ behaves (but is not) the same as a table.
Classes use that sort of structure for ‘self’ and it’s very dynamic. ‘self’ is local to each class, so you can have self.body representing different objects in different classes, the same way local variables work in functions. Lua works with scopes of variables, so a local outside a function won’t affect a local inside a function even if they have the same name.
@Crumble you don’t have to define x and y if they aren’t used, but it shows what they are used for. You can replace self.pb.x = WIDTH/2 with self.pb.x = x and same for y.