'OOP' how to generate a table of anon enemies on "game" object's initilization?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
wheelsofsteel
Prole
Posts: 2
Joined: Tue May 09, 2017 5:26 pm

'OOP' how to generate a table of anon enemies on "game" object's initilization?

Post by wheelsofsteel »

Trying to concisely sum up what I wanted to ask in the title was a bit difficult.

Some background, I normally use JavaScript and this crazy, new and exciting world without arrays and stuff is a harsh adjustment!

Basically, what I like to do in JS is init an instance of my game class (if we can say 'class' with JS) and on it's initialization I create an array on anonymous enemies or objects etc to use later. In lua, I have no idea how to go about doing this.

For example:

Code: Select all

Game = {}

function Game:new()    
	newObj = {
		y = love.graphics.getHeight() - 200,
		objects = self:generateWorld()
	}                                  
 	self.__index = self                     
 	return setmetatable(newObj, self)        
end

function Game:generateWorld(arr)
	return {Enemy:new(400, 400, 200, 600)}  --ideally would loop this with as many enemies as I want
end

function Game:draw()
	love.graphics.setColor(200, 100, 255)
    self.objects[i]:draw()
end

Enemy = {}

function Enemy:new(x, y, w, h)
	newObj = {
		x = x,
		y = y,
		w = w,
		h = h
	}
	self.__index = self                      
 	return setmetatable(newObj, self)  
 end

 function Enemy:draw()
 	rect('fill', self.x, self.y, self.w, self.h)
 end
Here's what I have done previously in JS:

Code: Select all

//game 'class'
var Game = function() {
    this.enemies = this.generateEnemies([]);
    }
    
    Game.prototype.generateEnemies = function(enemies) {

    for (var i = 0; i < ROWS; i++) {
        var newRow = [];
        for (var y = 0; y < COLS; y++) {
            var randNo = random(0,2);
            var type;
            if(randNo > 1) {
                type = invader
            } else {
                type = invader2
            }
            newRow.push(new Enemy(y * 40 + 40, 40 + i * 35, type));
        }
        enemies.push(newRow);
    }
    return enemies;
}
How do you guys go about doing this in Love2d and lua? :o
User avatar
raidho36
Party member
Posts: 2063
Joined: Mon Jun 17, 2013 12:00 pm

Re: 'OOP' how to generate a table of anon enemies on "game" object's initilization?

Post by raidho36 »

Here's a boilerplate code I use for my "classes" - from my math library - and some example method at the end. They're not actually classes but I use duck typing so it doesn't matter.

Code: Select all

local Vec2 = setmetatable ( { }, { __call = function ( class, ... ) return class.new ( ... ) end } )
Vec2.__index = Vec2

function Vec2.new ( x, y )
	local self = setmetatable ( { }, Vec2 )
	self.x = x or 0
	self.y = y or 0
	return self
end

function Vec2:add ( v )
	self.x = self.x + v.x
	self.y = self.y + v.y
	return self
end
But I think your problems come from lack of understanding. You should read Lua manual concerning metatables. TL;DR:

The __index methametod is invoked when you access a key that doesn't exist in the table itself. Since it's a common practice to use simply fetch data from another table, you can set it as that table, instead of a function that would fetch from that table. Using the above code as example, Vec2 is a "class" body. I set it's __index field to itself, but Vec2 itself doesn't use it - it's not in its metatable. Then you create Vec2 instance by assigning "class" to a new table as its metatable. Now that new table has metatable attached to it, and its __index metatable is pointing to Vec2. Then you populate the table with instance variables. If you now access that table's "add" funciton, which is not in the class instance, it will be redirected to Vec2, where it exists. You can also use this to implement "default" values or class "constants". Note that if you attempt to write into class fields of an instance, new data will go into instance while the class will remain unaffected. That new instance data will preclude class data until you erase it. Conversely, overwriting anything in class modifies related behavior of all isntances.

You'll notice that the first line uses __call metamethod. It's invoked when you call a table as function, and it passes that table as first argument into the function, with the rest following after. I took advantage of it and made it call the "new" method, so that calling "Vec2 ( )" produces new vector, as opposed to having to call "Vec2.new ( )".

Now regarding dot notation and colon notation, those are simply two different ways of calling and declaring a function, result is identical. Dot notation produces ordinary function, and calls the function ordinarily. Colon notation implicitly declares first argument to be "self", and when called, passes callee table as first argument. You can call functions produced with colon notation using dot notation, but you'll have to manually supply the "self" argument. You can also call functions produced with dot notation using colon notation, but then the callee table will go as first argument automatically.
User avatar
rmcode
Party member
Posts: 454
Joined: Tue Jul 15, 2014 12:04 pm
Location: Germany
Contact:

Re: 'OOP' how to generate a table of anon enemies on "game" object's initilization?

Post by rmcode »

I'm a fan of the closure-based approach because it allows you to have private functions and variables too:

Code: Select all

local foo = {}

-- Constructor
function foo.new()
    local self = {}
    
    local a = 1 -- private attribute
    self.b = 2 -- public attribute

    function self:update()
        print( a, self.b )
    end

    -- Public method -> Getter for private a
    function self:getA()
        return a
    end

    return self
end

return foo

Code: Select all

local Foo = require( 'foo' )

local arr = {
    Foo.new(),
    Foo.new(),
    Foo.new(),
    Foo.new()
}

function love.update()
    for i = 1, #arr do
        arr[i]:update()
    end
end
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 5 guests