The main issue that I see in your code is a confusion between the various types of variable. These are:
- Global variables
- Local variables
- Instance variables
(These also apply to functions.)
Local and global variables are straightforward: a variable has a scope wherein it is defined and has meaning. Outside that scope, it is inaccessible. Unless otherwise stated, a variable has global scope in that it has meaning for the entire program. But a variable that is declared using
local has scope only for the block in which it is defined.
(Where this can get slightly confusing is with reuse of variable names. So there can be variables with the same name but with different scopes. The rule is that the most recent declaration wins and all others are hidden.)
In your code you didn’t actually have any local variables so we’ll skip over that and pass to instance variables. When working with objects you can define variables that are bound to a particular instance of that object. In your code you have one object,
Paddle, and one instance of that object,
paddle might have some attributes that are set for it (such as its position, size, colour) that could be different for a different instance of that object. If you had two paddles they could have different sizes. These are stored as instance variables and are prefixed with the word
self. So in your code,
self.posx is an example. Thus if you create two paddles, you can safely assign different positions to each.
However, in your code then not all things that should be instance variables are so. In particular,
pos is a global variable. This means that if you had more than one paddle, all would be trying to use the same
pos variable to store their position. This would cause chaos: each would be updating the same variable instead of their own position variables. So
pos needs to be
A similar story holds for functions. The
checkGrav function should really be an instance function because it modifies instance variables. What it does to one paddle will be different to what it does to another paddle. The way to do this is to make it a method by defining it as
Paddle:checkGrav and calling it as
self:checkGrav (from within
paddle:checkGrav from the main program). What this does is to ensure that within that function call, the variable
self refers to the instance of the object that is calling it. This means that
self.pos now refers to the position of the paddle that is invoking the
Here’s my version of your code with the above put in place. As you see, I could pass in vectors with no problem so I don’t know what was causing the difficulties there. I also reduced the number of
ifs in the
checkGrav routine since you were doing the same thing on the inner
if (the check for
-(-20*Gravity.x) = 20*Gravity.x). The first
if in that routine could skip the check but this would be an optimisation step: I don’t know if doing the
if makes it faster than always updating
self.pos and correcting for endpoints afterwards.
pColor = color(67, 132, 128, 255)
paddle = Paddle(vec2(WIDTH/2,5),vec2(80,15),pColor)
-- This function gets called once every frame
background(0, 0, 0, 255)
rect(WIDTH/2,HEIGHT - 20, 80,15)
Paddle = class()
-- Josh Knox
-- This is a paddle class that moves based on gravity.
-- I would like to hear any suggestions as to the 'elegence' of the code.
-- I wanted to pass in posx and posy as position (vec2) but kept getting an nil error?
-- And self.pos.x doesn't seem to work
-- Anyone know why or how to pass in vector properly?
self.pos = pos
self.size = size
self.pColor = pColor
-- I really don't like having some of the varables self.blah or others not.
-- It just feels like there are alot of 'if's in this function...any ideas?
-- This function checks boundaries first to avoid 'bouncing' on the edges
if self.pos.x >= 0 and self.pos.x <= WIDTH - self.size.x then
self.pos.x = self.pos.x + (20 * Gravity.x)
if self.pos.x < 0 then
self.pos.x = 0
if self.pos.x > WIDTH - self.size.x then
self.pos.x = WIDTH - self.size.x
-- Codea does not automatically call this method