Inheritance problems

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
xordspar0
Prole
Posts: 10
Joined: Thu Nov 21, 2013 5:36 am

Inheritance problems

Post by xordspar0 »

I am trying to learn game development and LÖVE, so I'm making an extremely simple platformer. It might turn into a Jump n Bump clone or something.
Right now, I have want to have two sprites on the screen. One is a frog and one is a spider. They are each defined by an object. Because they are so similar, I want the spider to inherit most of the functions and variables from the frog. That's the way my code is supposed to be right now.
The problem is that even though I set a distinct image for the frog and the spider, they both are drawn as frogs. The spider object should be drawing a spider sprite on screen. I must lack some fundamental understanding of Lua or LÖVE, but there's always a chance I made a stupid mistake somewhere.
Inheritance problems.png
Inheritance problems.png (939 Bytes) Viewed 3824 times
Also, I define some variables (the ones that should be the same for all instances of the objects) outside of the constructor. Is this a good idea? If it is a good idea, am I doing it wrong?
Attachments
jnb.love
(66.33 KiB) Downloaded 160 times
User avatar
Ref
Party member
Posts: 702
Joined: Wed May 02, 2012 11:05 pm

Re: Inheritance problems

Post by Ref »

Little different approach you might want to consider.
Obviously you can improve on.
Just an idea.
Attachments
frog_spider.love
Crider creating module
(19.47 KiB) Downloaded 155 times
User avatar
Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

Re: Inheritance problems

Post by Inny »

The metatable chain is wrong. You want a Spider Instance to point to Spider that points to Frog, but instead you have a Spider Instance pointing right at Frog. The way you fix this is that the __index metafield points at the Spider class, where as the Spider class itself has to be an unconstructed instance of the Frog. Like so:

Code: Select all

Frog = {}
Frog.__index = Frog
function Frog.new() --[[ code here ]] end

Spider = {}
Spider.__index = Spider
setmetatable(Spider, Frog) -- This is the key line
function Spider.new() --[[ code here ]] end

local instance = Spider.new()
xordspar0
Prole
Posts: 10
Joined: Thu Nov 21, 2013 5:36 am

Re: Inheritance problems

Post by xordspar0 »

Ref: Yeah, I should definately have a generic class and that both Frog and Spider inherit from. I want them to each have unique behavior, though (I was planning on having the spider pace back and forth) so they do need to be separate.

Inny: Great, I get it now. Thanks!

One more thing. Is it a good idea to define some variables outside the constructor like this?

Code: Select all

Frog = {}
Frog.__index = Frog

-- constant for all frog instances
Frog.NUM_FRAMES = 8 -- number of frames in the animation
Frog.IMG = love.graphics.newImage("frog.png")
Frog.FRAMES = {}
for i = 0, (Frog.NUM_FRAMES - 1) do
	Frog.FRAMES[i] = love.graphics.newQuad(16*i, 0, 16, 16, 128, 16)
end

function Frog.new(x, y)
	local self = setmetatable({}, Frog)
	self.frame = 0 -- current frame
	self.facing = 1 -- 1 = right, -1 = left
	self.x = x
	self.y = y
	self.xvelocity = 0 -- measured in pixels per second
	self.yvelocity = 0
	self.yaccel = 1000 -- measured in pixels per second per second
	self.onGround = false
	
	return self
end
Maybe it would be less confusing if I just defined all of them in one place...
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: Inheritance problems

Post by micha »

If you define variable in the frog.new-function then each child-frog-object has this variable itself. If you define it outside, such that only the parent object "Frog" has it, then the children can use this variable, too but it is inherited.
If you create a child frog with

Code: Select all

child = Frog.new(0,0)
then it does not have the variable

Code: Select all

child.FRAMES
but, because of the metatable, whenever use write child.FRAMES, then Lua redirects the lookup to the parent (Frog.FRAMES). In terms of usage, there is no difference for you, but internally there is only one copy of FRAMES. So defining things outside is good for two purposes:
  • You save memory, because not each child has copies of these variables
  • When you change this property at the parent, then it is changed in all children. You might want to exchange the frog image to color all frogs in red. That would only require to change it at the parent frog.
I usually put all variable outside the constructor. The metatable then does the job for me. That also works for variables, that should be different for each instance. For example, if you put the x-coordinate outside and create a child. When you then perform this:

Code: Select all

child.x = child.x + 5*dt
Then first the right hand side is evaluated (which means the x-value of the parent is used). But the left hand side of the equations writes to the values of the child. That means that the child does not have an extra copy of x until child.x is written for the first time.

Also have a look at Chapter 16 in PiL.
xordspar0
Prole
Posts: 10
Joined: Thu Nov 21, 2013 5:36 am

Re: Inheritance problems

Post by xordspar0 »

Wow, thanks micha. That helps a lot. I have read that chapter of PiL, but reading about advanced concepts of Lua is very different from using them.
Everyone, thank you for your help! The LÖVE community is stunningly friendly and helpful!
Post Reply

Who is online

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