To expand on what Nikki is saying, the problem is that you're trying to refer to an obstacle but there's no code that says what the 'obstacle' name means. Let's review what's happening is different parts of the program! I hope this helps with understanding how programming in Lua and LÖVE works (though you probably already understand some things here already). "..." represents parts I skipped over.
Code: Select all
-- main.lua
Class = require 'class'
...
require 'Player'
require 'Obstacle'
In main.lua we're telling Lua to run the contents of class.lua, Player.lua and Obstacle.lua. We're also saying that 'Class' is a global that refers to what the class module returns. We don't need to know how the class module works - we only need to know that we can call 'Class' to create something that represents a class, which is what we're doing in some other files. All good so far.
Code: Select all
-- Obstacle.lua
Obstacle = Class{}
In Obstacle.lua we're creating a global object called 'Obstacle' that represents a unique "class". Then we define some functions that we attach to the Obstacle class. (We may call these functions "methods" as it's the appropriate term used in object oriented programming for this situation).
We're doing very similar things in Player.lua: we create a global 'Player' and define some methods.
Code: Select all
-- main.lua
function love.load()
...
player = Player()
obstacle1 = Obstacle()
obstacle2 = Obstacle()
end
Back to main.lua. We're now defining the function love.load which is a function that the LÖVE framework knows about and will automatically execute at an appropriate time (before love.update etc. are called).
When LÖVE calls love.load we're creating some globals, namely 'player', 'obstacle1' and 'obstacle2' (and some other things that I skipped over). Those are
instances of the classes we were defining in Obstacle.lua and Player.lua. Again, we don't need to know how exactly classes or instances work internally (which is defined in class.lua) more than that we call Obstacle() to create instances of the Obstacle class and that the methods we defined earlier can operate on these instances (for example, Obstacle:collision() can operate on Obstacle instances).
What we probably want to do here after creating the instances is make an array that contains references to all the obstacles so that the player can check collisions against all of them:
Code: Select all
obstacle1 = Obstacle()
obstacle2 = Obstacle()
obstacles = {}
table.insert(obstacles, obstacle1)
table.insert(obstacles, obstacle2)
If we jump to where the error was, in player:update(), instead of trying to reference the non-existent 'obstacle' (with a lower-case O) we can loop over all the obstacles, which we can now easily do after having created the global 'obstacles' array!
Code: Select all
function Player:update(dt)
...
--obstacle collisions
for index, obstacle in ipairs(obstacles) do
if self.x == obstacle.x then
...
end
...
end
...
end
Note that 'self' refers to the instance of the Player class (which is actually an invisible first argument to the called method). Let's quickly look at that too:
Code: Select all
-- main.lua
function love.update(dt)
...
player:update(dt)
...
end
What's happening here is that we call the 'update' method on the Player class, with the 'player' instance representing 'self' inside Player:update().
In summary, the error happened because we don't define any local or global value called 'obstacle'. (We do define the global 'Obstacle' but that's irrelevant here.) The error could have been fixed by replacing 'obstacle' with 'obstacle1' or 'obstacle2', but since the player probably care about all obstacles we created a globally accessible array containing a reference to all obstacles we created. There are other problems too, and more things that can be done, but I'll leave those for you to find.