Can anyone help me with entities?

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Matkins
Citizen
Posts: 53
Joined: Mon Mar 23, 2009 5:12 pm

Can anyone help me with entities?

Post by Matkins »

What i need is probably easy, but i'm not that experienced with lua yet and can't seem to figure it out. I want to be able to spawn any number of entities (they're going to be apples), wether each is red or green should be random, and I need to be able to destroy them individually. I've gathered that I will probably need to create a class for this, but I've looked around at classes in lua and have gotten utterly confused. One of the main things that I can't seem to grasp is how to draw an undetermined number of entities. I originally just tried using a table for this but quickly ran into problems with indexing the correct ones when drawing or destroying.

By the way, I've been looking through Envy and the Wrath game to figure out how its done in there, so far I don't get it. Is anyone able to break this down nice and simple for me? Thanks.
User avatar
mikembley
Citizen
Posts: 72
Joined: Wed Dec 17, 2008 5:30 pm
Location: Blackburn, UK
Contact:

Re: Can anyone help me with entities?

Post by mikembley »

As someone who is progressively learning LUA and messing with LÖVE constantly i feel as though i am able to teach others of what ive learned so far

You are looking to create entities that you can modify on the fly

The way i would do it (and it may not be the best way) would be to create a table to throw all of your entities into so then you have sort of a database or an array which is essentially what tables are.

Example time..

You create a table

Code: Select all

apples = { } --BASICALLY THIS LINE INITIALIZES A VARIABLE (apples) WITH AN EMPTY TABLE
a table can have numerous pieces of data in them, so lets start adding to the table

Code: Select all

apples = {} --INITIALIZED EMPTY TABLE IN VARIABLE apples

--Now you can access tables by using indexes take a look at the next line
apples[0] = { color="red", size="small", eaten=false }
So now what we have done is added data to the apples table, in the form of color, size and if it is eaten or not (true/false)
These are variables within the table which we can now access when the need arises. I will explain how to access them after i have explained a bit more about the structure of tables

Table indexes are pretty much unique and it would probably be best to do them incrementally.
For instance:

Code: Select all

apples = {}
apples[0] = { color="red", size="small", eaten=false }
apples[1] = { color="green", size="small", eaten=false }
apples[2] = { color="green", size="big", eaten=false }
apples[3] = { color="red", size="small, eaten=true }
So, As can see we keep changing the index between [ ] and it increases each time for a new entity ( apple[x] where x is the next incremented index )
Now that we have data in the apples table, We should probably start thinking about how to access these apples individually and also how to loop and display or modify them.

Say now, we wanted to find out what apple number 3's color is (bearing in mind table indexes start at 0, So apple number 3 would technically be number 2, because we counted the 0 as 1 ) we would access the apples table like so

Code: Select all

apples = {}
apples[0] = { color="red", size="small", eaten=false }
apples[1] = { color="green", size="small", eaten=false }
apples[2] = { color="green", size="big", eaten=false }
apples[3] = { color="red", size="small, eaten=true }

myapple = apples[2].color --apples is the table name, [2] is the index of the apples table, and .color is the variable inside the table, what we have done here is
                                       --allowed myapple to take the data from the .color variable
Now that you have accessed the color of apple number 3 and copied it into a variable you can now display or use that data wherever you like.

Lets move onto modifying a table.

Say we want to modify apple number 4's eaten status

Code: Select all

apples = {}
apples[0] = { color="red", size="small", eaten=false }
apples[1] = { color="green", size="small", eaten=false }
apples[2] = { color="green", size="big", eaten=false }
apples[3] = { color="red", size="small, eaten=true }

--All we need to do is use the same table index to replace the variable inside it like so:
apples[3] .eaten = false  --apples is the table, [3] is the index, and .eaten is the variable inside the table index

--Now the table structure will look like:
apples[0] = { color="red", size="small", eaten=false }
apples[1] = { color="green", size="small", eaten=false }
apples[2] = { color="green", size="big", eaten=false }
apples[3] = { color="red", size="small, eaten=false }
This is as simple as tables gets

As for being able to manage a table in terms of having a large quantity of apples. You would start to use loops

An example loop:

Code: Select all

apples = {}
apples[0] = { color="red", size="small", eaten=false }
apples[1] = { color="green", size="small", eaten=false }
apples[2] = { color="green", size="big", eaten=false }
apples[3] = { color="red", size="small, eaten=true }

--Do the Loop
for i=0, #apples do --THIS LINE MEANS START i AT 0 AND #apples COUNTS HOW MANY INDEXES THERE ARE, BUT THE LOOP DOES THE INCREMENTING
       --MAKE A LOOP HANDLE SO WE DO NOT HAVE TO KEEP TYPING apples[i].color ETC.. MUCH EASIER TO ACCESS VARIABLE LIKE apple.color, apple.size
       apple = apples[i]
       --HERE WE DISPLAY THE APPLES VARIABLES BY DRAWING THEM
       love.graphics.draw("Apple " .. i .. " is " .. apple.color .. " and is " .. apple.size .. " and it is " .. tostring(apple.eaten) .. " that is has been eaten.", 20, 20+20*i)
end

The last piece of code would produce something like so on-screen:

Apple 0 is red and is small and it is false that it has been eaten
Apple 1 is green and is small and it is false that it has been eaten
Apple 2 is green and is big and it is false that it has been eaten
Apple 3 is red and is small and it is true that it has been eaten

You mentioned that you would like to do an undetermined amount of entities
Take a look at the next piece of code based on the knowledge that you have seen above:

Code: Select all

apples = {} -- Initialize a blank table
appleamount = math.random(0, 200) --Generate a number between 0, 200 and put it into variable appleamount

for i=0, appleamount do
       if math.random(0, 2 ) == 1 then      --If a random number is 1 then the color variable will be red otherwise it will be green
             color = "red"
       else
             color = "green"
       end

       apples[i] = { color=color } --This inserts the random color into the apples table
end
Now depending on what result comes from math.random(0, 200) you could have a table with anywhere between 0 and 200 indexes and also a random outcome of red / green apples each time

You would normally do the table generating once, in the load() function, and not the draw() or update() functions, because this would obviously keep resetting your table values with different results each time the code is parsed

As an example of what the table would contain would look like this due to randomness.

apples[0] = { color="red" }
apples[1] = { color="green" }
apples[2] = { color="red" }
apples[3] = { color="red" }
apples[4] = { color="green" }
apples[5] = { color="red" }
apples[6] = { color="green" }
....
Skip a few for typings sake..
....
apples[28] = { color="red" }
apples[29] = { color="red" }
apples[30] = { color="green" }
apples[31] = { color="red" }

I hope this gives you an insight on how tables work, but again this is partly some of my methodology and how i sometimes do things, even though it might not be the most efficient or best way, Its what i've come to know as being DIY for me

If theres anything that you want me to clarify or be more clear on, then just ask :)

PHew....Im done! :P

p.s - If you need a working example, I could provide one too if needs be :)
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: Can anyone help me with entities?

Post by bartbes »

@mikembley:
I haven't read your complete post, but I noticed some mistakes:
Table indexes start at 1, not at 0, that's true for arrays, not for lua tables.
Your way is.. messy, at least, it's better to use table.insert, table.remove and pairs.

@Matkins:
Sorry, but I can't give you code examples of what I said above right now, I don't have the time.
User avatar
qubodup
Inner party member
Posts: 775
Joined: Sat Jun 21, 2008 9:21 pm
Location: Berlin, Germany
Contact:

Re: Can anyone help me with entities?

Post by qubodup »

Here's my reply: Apples.
lg.newImage("cat.png") -- made possible by lg = love.graphics
-- Don't force fullscreen (it frustrates those who want to try your game real quick) -- Develop for 1280x720 (so people can make HD videos)
User avatar
mikembley
Citizen
Posts: 72
Joined: Wed Dec 17, 2008 5:30 pm
Location: Blackburn, UK
Contact:

Re: Can anyone help me with entities?

Post by mikembley »

I knew i would get slammed for the table indexes :P Its just im used to using PHP and i can never remember :P

But the main part of the stuff above is to show an example whether or not it looks good, I just find it easier to show people how tables are pretty much like arrays and then they can move on to table.insert, remove, pairs and do it the clean way.
Matkins
Citizen
Posts: 53
Joined: Mon Mar 23, 2009 5:12 pm

Re: Can anyone help me with entities?

Post by Matkins »

Thanks for your efforts mikembly, but i'm not sure if tables are going to work for me. Because I would idealy like to remove the destroyed apples from the table, so the table wont end up being astronomical if run for a long time. But say I have a table of 10 apples and i remove apple 7; then apple 8 becomes 7, 9 becomes 8 and 10 becomes 9. And that totally screws up my program, i end up trying to destroy one apple and seeing a different one vanish, and eventually i end up with errors. Can anyone tell me the best way to do something like this? Or at least point me in the right direction? Thanks.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Can anyone help me with entities?

Post by Robin »

You can always just nil them: apples[7] = nil
Of course, you can't use general for loops anymore. In the example above, using general for loops will mean that apples[8], apples[9] and apples[10] will be ignored. Then you need to set apples.n = 10 and use "for i=1,apples.n do" instead of "for i,apple in ipairs(apples) do", but I wouldn't recommend that: using table.remove is much cleaner. How will that screw up your program? Do you keep references to apple indexes or something?
Help us help you: attach a .love.
Matkins
Citizen
Posts: 53
Joined: Mon Mar 23, 2009 5:12 pm

Re: Can anyone help me with entities?

Post by Matkins »

Robin wrote:You can always just nil them: apples[7] = nil
Of course, you can't use general for loops anymore. In the example above, using general for loops will mean that apples[8], apples[9] and apples[10] will be ignored. Then you need to set apples.n = 10 and use "for i=1,apples.n do" instead of "for i,apple in ipairs(apples) do", but I wouldn't recommend that: using table.remove is much cleaner. How will that screw up your program? Do you keep references to apple indexes or something?
The reason why it screwed up my program:
I want the apples to be destroyed when they collide with a particular object. The only way I could think of doing this is like this:

Code: Select all

function spawnApple()
	apple[1+#apple] = {body = love.physics.newBody(world, spawnPos, -50, 10), color = ""}
	apple_shape[#apple]	= love.physics.newCircleShape(apple[#apple].body, 15)
	apple_shape[#apple]:setData(#apple)
	apple[#apple].body:setMassFromShapes()
end

function collision(sd1, sd2, co)
	if(sd1 == "Object")then
		apple[sd2].body:destroy()
		apple_shape[sd2]:destroy()
		table.remove(apple, sd2)
		table.remove(apple_shape, sd2)
	elseif(sd2 == "Object")then
		apple[sd1]:destroy()
		apple_shape[sd1]:destroy()
		table.remove(apple, sd1)
		table.remove(apple_shape, sd1)
	end
end
So as you can see, I am using the index of each apple as it's shapeData in order to determine which apple has collided with the object. And i'm sure it's clear to you why this doesn't work, it's clear to me also but i can't figure out how to do it right.
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: Can anyone help me with entities?

Post by bartbes »

You can assign unique values, and use those unique values to determine which apple has the collision. (by a loop) Maybe there's some cleaner/faster way, but that works.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Can anyone help me with entities?

Post by Robin »

For example, using tables as keys:

Code: Select all

apples[{}] = { color="green", size="small", eaten=false }
an empty table always creates a new, unique object. Even if you remove some of the appels, the key stays the same for each apple.
Help us help you: attach a .love.
Post Reply

Who is online

Users browsing this forum: No registered users and 14 guests