Part 2: Players, NPCs and Navigation

posted in trill41 for project ABx
Published August 28, 2018
Advertisement

Player

Replaced the ball with a real character model. At the moment I have just a few character models with two animations (run and idle): Video

The character was made with MakeHuman and the animations are from Mixamo. The workflow is straight forward and (more or less) painless:

  1. In MakeHuman export the character as .mhx2.
  2. Import in Blender. The MakeHuman Blender Plugin has a MHX2 importer.
  3. If needed apply transformation, but if you use MHX2 i think this is not needed.
  4. Export from Blender as .fbx.
  5. Upload the FBX file to Mixamo.
  6. Select the animation.
  7. Download the FBX file.
  8. Import in Blender.
  9. Export the character with the Urho3D-Blender plugin. I would recommend to export a Prefab so you can load the whole thing with materials etc. at once.

NPCs

RPGs (and other games) usually have NPCs - non playing characters, well they are playing but they are computer controlled.

This game should be largely scriptable. There are different game formats and maps and each should just differ in the script that is executed.

A game script could look like this:


function onStart()
  -- self is the this pointer
  -- Spawn an NPC and set the position.
  local smith = self:AddNpc("/scripts/creatures/npcs/smith.lua")
  if (smith ~= nil) then
    local x = -6.71275
    local z = 12.5906
    local y = self:GetTerrainHeight(x, z)
    smith:SetPosition(x, y, z)
    -- Here we just use the Y-axis, internally it uses Quaternions
    smith:SetRotation(180)
  end  
  local merchant = self:AddNpc("/scripts/creatures/npcs/merchant.lua")
  if (merchant ~= nil) then
    local x = 4.92965
    local z = 12.2049
    local y = self:GetTerrainHeight(x, z)
    merchant:SetPosition(x, y, z)
    merchant:SetRotation(180)
  end  
end

function onStop()
end

function onAddObject(object)
  print("Object added: " .. object:GetName())
end

function onRemoveObject(object)
  print("Object removed: " .. object:GetName())
end

function onPlayerJoin(player)
  player:AddEffect(empty, 1000, 0)
  print("Player joined: " .. player:GetName())
end

function onPlayerLeave(player)
  player:RemoveEffect(1000)
  print("Player left: " .. player:GetName())
end

-- Game Update
function onUpdate(timeElapsed)
--  print(timeElapsed)
end

As with other scripting APIs, there are events that are called by the program (from C++), and there are objects that have methods accessible by the script.

An NPC script is as simple:


-- Object stats/properties
name = "Smith"
level = 20
modelIndex = 5     -- Smith body model
sex = 2            -- Male
creatureState = 1  -- Idle
prof1Index = 1     -- Warrior
prof2Index = 0     -- None

function onInit()
  return true
end

function onUpdate(timeElapsed)
  -- Do something intelligent!
end

-- self was selected by creature
function onSelected(creature)
  print(creature:GetName() .. " selected me, the " .. self:GetName() .. " :D")
end

-- creature collides with self
function onCollide(creature)
  -- Testing Octree query
  local objects = self:QueryObjects(2.0)
  print(type(objects))
  for i, v in ipairs(objects) do
    print(i, v, v:GetName()) 
  end
end

abnpc.thumb.png.4f399bd4d448bd45ca1f962b27b04549.png

Navigation

Navigation is a difficult topic. Fortunately there is Recast & Detour, a library to find paths with a navigation mesh. Currently it can to go to a static position and follow a moving object. Technically it's the same, but it doesn't recalculate the path when the object is not moving. However, I've read somewhere that Detour can calculate incomplete paths which would be useful for following objects, but I didn't figure that out yet.

Video

Detour uses navigation meshes created with Recast. The image bellow shows the generated navigation mesh based on the heightfield of this map.

recast.thumb.png.47e0dd3e430a6f3e5fcf937fd5932174.png

As mentioned earlier, the heightfield is just a bitmap where brighter colors are higher altitudes than darker colors. A mesh is created with a custom command line program from this bitmap, which Recast uses to generate the navigation mesh.

heightfield.png.b52f22273e13e8a74ee4948830896129.png

To be continued...

Previous Entry Introduction
2 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement

Latest Entries

Advertisement