Thanks, this helps a lot!
I've now got a basic npc system working. It first creates a list of tiles where it is allowed to spawn npc's. I've marked areas in the level as so called "party zones". And my festive npc will be spawning in these areas. This allows me to create hotspots where a bunch of npc's group together.
Code: Select all
function spawnnpcs(numberofnpcs,partyzones)
npclist = {}
npclist.__index = npclist
npc.size = {32, 48} --Same size as player
--Create all npc anims (same as player's anims)
npc.anims = {}
npc.anims[0] = {"idleup",1,npc.size,{0,0},{1}}
npc.anims[1] = {"idleright",1,npc.size,{0,0},{5}}
npc.anims[2] = {"idledown",1,npc.size,{0,0},{9}}
npc.anims[3] = {"idleleft",1,npc.size,{0,0},{13}}
npc.anims[4] = {"walkup",4,npc.size,{0,0},{1,2,3,4}}
npc.anims[5] = {"walkright",4,npc.size,{0,0},{5,6,7,8}}
npc.anims[6] = {"walkdown",4,npc.size,{0,0},{9,10,11,12}}
npc.anims[7] = {"walkleft",4,npc.size,{0,0},{13,14,15,16}}
--Spawn all npc's for the level
for n=1,numberofnpcs do
local npcspawnloc = partyzones[(love.math.random(1,#partyzones))]
--print("Creating npc at "..npcspawnloc[1]..", "..npcspawnloc[2])
npclist[#npclist+1] = npc:initialize(npcspawnloc[1]*tileSize, npcspawnloc[2]*tileSize) --Add reference of npc to list
addNpc("npc"..(#npclist+1), npcspawnloc[1]*tileSize, npcspawnloc[2]*tileSize, npc.size[1], npc.size[2]) --Add npc to npc bump world
end
print("Added "..#npclist.." npc's to the world.")
end
As you can see, it also defines a default animation list for npc's in general, and then spawns all npc's at once. It also adds a reference to each npc to a separate table.
Should the npc's all be stored in a separate table, like I am doing now? Or is it better to store the npc's along with their functions inside bump's world? Because I will need to use bump to find out which objects are currently on screen, and then collect the data belonging to that npc from the other table. I'm not entirely sure how to do this back and forth, and it seems cumbersome.
Next, here is the code that defines the npc 'class':
Code: Select all
function npc:initialize(x, y)
self.x, self.y = x, y
local rgender = love.math.random(0,1)
if (rgender == 0) then self.gender = "male" else self.gender = "female" end
self.race = love.math.random(1,5)
self.name = getNpcName(self.gender,self.race)
self.interests = love.math.random(1,24)
self.action = "idle"
self.direction = "down"
self.tile = {math.floor((self.x+(mapX/tileSize)+(self.size[1]/2)+(tileSize/2))/tileSize),math.floor((self.y+(mapY/tileSize)+self.size[2]+(tileSize/2))/tileSize)}
--print("Added "..self.name..", who is a "..self.race.." "..self.gender..".")
return self.name
end
The initialize code defines all the attributes of the npc, such as their gender, their name (randomly selected from a huge list, based on their gender) and their race (determines what sprite to use for their body). I'll be adding a lot more to this list as the game develops.
Lastly, npcadd will add the npc to a separate bump world, called npcworld. I don't want the player to collide with the over 50 npc's that populate the level. I don't want the npc's to cause a blockade, so I made a separate collision world for them. They won't be bumping with the level I think, depending on how I code their movement.
Code: Select all
function addNpc(npcname, npcx, npcy, npcsizex, npcsizey)
npcworld:add(npcname, npcx+(npcsizex/4), (npcy+npcsizey-tileSize/2), 16,8) -- x,y,w,h
end
But I have another question. Is it a good idea to have a separate collision world for the npc's? Because I don't want the player to collide with the npc's, and I don't want the npc's to collide with the player, nor with each other. However, I will be doing some line of sight checks and touch events based on the npc's. But I am not sure how to go about doing this. For example, when an npc touches a door, I want the door to open, and when they no longer touch it, the door should close. I have not made the door object yet, but I am trying to figure out how to best do this. I suppose I could add the doors to the npcworld, but the player will be opening and closing doors too.... so do I add the doors to both? Or should everything just be inside one collision world?