Skip to content
Snippets Groups Projects
Commit 9f22a1f5 authored by dg's avatar dg
Browse files

smarter move

git-svn-id: http://svn.net-core.org/repos/t-engine4@89 51575b47-30f0-44d4-a5cc-537603b46e54
parent fca5cf90
No related branches found
No related tags found
No related merge requests found
......@@ -30,9 +30,6 @@ function _M:move(map, x, y, force)
if y < 0 then y = 0 end
if y >= map.h then y = map.h - 1 end
self.x, self.y = x, y
-- if self.levelid then
-- game.level.c_level:moveActor(self.levelid, x, y)
-- end
map(x, y, Map.ACTOR, self)
game.level:idleProcessActor(self)
......
......@@ -74,6 +74,11 @@ end
--- This is the "main game loop", do something here
function _M:tick()
-- Run the level distancer
if self.level.distancer_co then
local ok, err = coroutine.resume(self.level.distancer_co)
if not ok and err then error(err) end
end
end
--- Called by the engine when the user tries to close the window
......
......@@ -34,11 +34,5 @@ function _M:tick()
end
end
end
-- Run the level distancer
if self.level.distancer_co then
local ok, err = coroutine.resume(self.level.distancer_co)
if not ok and err then error(err) end
end
end
end
......@@ -8,7 +8,6 @@ module(..., package.seeall, class.make)
function _M:init(level, map)
self.level = level
self.map = map
-- self.c_level = core.map.newLevel(500)
self.e_array = {}
self.entities = {}
-- This stores the distance for each actors to each other actors
......@@ -24,7 +23,6 @@ end
function _M:addEntity(e)
if self.entities[e.uid] then error("Entity "..e.uid.." already present on the level") end
self.entities[e.uid] = e
-- e.levelid = self.c_level:addActor(e.uid, e.x, e.y)
table.insert(self.e_array, e)
end
......@@ -38,7 +36,6 @@ function _M:removeEntity(e)
break
end
end
-- self.c_level:removeActor(e.levelid)
-- Tells it to delete itself if needed
if e.deleteFromMap then e:deleteFromMap(self.map) end
end
......@@ -55,7 +52,6 @@ function _M:save()
distancer_co = true,
-- dont save the distances table either it will be recomputed on the fly
e_distances = true,
c_level = true,
})
end
function _M:loaded()
......@@ -64,7 +60,6 @@ function _M:loaded()
local nes = {}
for uid, e in pairs(self.entities) do
nes[e.uid] = e
-- self.c_level:addActor(e.uid, e.x, e.y)
end
self.entities = nes
......@@ -84,9 +79,7 @@ function _M:createDistancer()
while true do
local e = table.remove(self.e_toprocess)
if e then
-- print("distancer for", e.uid)
self:computeDistances(e)
-- print("distancer ran for", i, e.uid)
end
coroutine.yield()
end
......@@ -99,40 +92,26 @@ local dist_sort = function(a, b) return a.dist < b.dist end
--- Compute distances to all other actors
function _M:computeDistances(e)
self.e_distances[e.uid] = {}
for i = e.x - e.sight, e.x + e.sight do
for j = e.y - e.sight, e.y + e.sight do
local dst = self.map(i, j, Map.ACTOR)
if dst and dst ~= e then
-- check los
local l = line.new(e.x, e.y, dst.x, dst.y)
local lx, ly = l()
while lx and ly do
if self.map:checkEntity(lx, ly, Map.TERRAIN, "block_sight") then break end
lx, ly = l()
end
core.fov.calc_circle(e.x, e.y, e.sight, function(self, lx, ly)
if self.map:checkEntity(lx, ly, Map.TERRAIN, "block_sight") then return true end
-- At the end ?
if not lx then
table.insert(self.e_distances[e.uid], {uid=dst.uid, dist=core.fov.distance(e.x, e.y, dst.x, dst.y)})
-- if e.uid ~= 9 then print("found LOS", e.uid, dst.uid) end
end
local dst = self.map(lx, ly, Map.ACTOR)
if dst then
table.insert(self.e_distances[e.uid], {uid=dst.uid, dist=core.fov.distance(e.x, e.y, dst.x, dst.y)})
end
end
end
end, function()end, self)
table.sort(self.e_distances[e.uid], dist_sort)
-- if e.uid ~= 9 then print("processed", e.uid) end
end
--- Get distances to all other actors
-- This eithers computes directly if not available or use data from the distancer coroutine
function _M:getDistances(e)
-- if not self.e_distances[e.uid] then self:computeDistances(e) end
function _M:getDistances(e, force)
if force and not self.e_distances[e.uid] then self:computeDistances(e) end
return self.e_distances[e.uid]
end
--- Insert an actor to process
function _M:idleProcessActor(act)
-- print("to process", act.uid)
table.insert(self.e_toprocess, 1, act)
-- print("add distancer for", act.uid)
end
......@@ -17,7 +17,7 @@ OBJECT = 1000
--- The order of display for grid seen
displayOrder = { ACTOR, OBJECT, TERRAIN }
--- The order of display for grids remembered
rememberDisplayOrder = { TERRAIN }
rememberDisplayOrder = { ACTOR, TERRAIN }
--- Sets the viewport size
-- Static
......
......@@ -4,11 +4,7 @@
newAI("move_simple", function(self)
if self.ai_target.actor then
local act = self.ai_target.actor
local l = line.new(self.x, self.y, act.x, act.y)
local lx, ly = l()
if lx and ly then
self:move(lx, ly)
end
return self:moveDirection(act.x, act.y)
elseif self.ai_target.x and self.ai_target.y then
local l = line.new(self.x, self.y, self.ai_target.x, self.ai_target.y)
local lx, ly = l()
......@@ -32,12 +28,16 @@ newAI("target_simple", function(self)
end
for i = 1, #arr do
act = __uids[arr[i].uid]
-- find the closest ennemy
if act and self:reactionToward(act) < 0 then
self.ai_target.actor = act
break
return true
end
end
-- No target ? Ask for more
game.level:idleProcessActor(self)
end)
newAI("target_player", function(self)
......
require "engine.class"
local Map = require "engine.Map"
--- Handles actors artificial intelligence (or dumbness ... ;)
module(..., package.seeall, class.make)
......@@ -33,8 +34,48 @@ function _M:init(t)
setmetatable(self.ai_target, {__mode='v'})
end
function _M:aiFindTarget()
self.ai_target.actor = game.player
local coords = {
[1] = { 4, 2, 7, 3 },
[2] = { 1, 3, 4, 6 },
[3] = { 2, 6, 1, 9 },
[4] = { 7, 1, 8, 2 },
[5] = {},
[6] = { 9, 3, 8, 2 },
[7] = { 4, 8, 1, 9 },
[8] = { 7, 9, 4, 6 },
[9] = { 8, 6, 7, 3 },
}
--- Move one step to the given target if possible
-- This tries the most direct route, if not available it checks sides and always tries to get closer
function _M:moveDirection(x, y)
local l = line.new(self.x, self.y, x, y)
local lx, ly = l()
if lx and ly then
-- if we are blocked, try some other way
if game.level.map:checkEntity(lx, ly, Map.TERRAIN, "block_move") then
local dirx = lx - self.x
local diry = ly - self.y
local dir = coord_to_dir[dirx][diry]
local list = coords[dir]
local l = {}
-- Find posiblities
for i = 1, #list do
local dx, dy = self.x + dir_to_coord[list[i]][1], self.y + dir_to_coord[list[i]][2]
if not game.level.map:checkEntity(dx, dy, Map.TERRAIN, "block_move") then
l[#l+1] = {dx,dy, (dx-x)^2 + (dy-y)^2}
end
end
-- Move to closest
if #l > 0 then
table.sort(l, function(a,b) return a[3]<b[3] end)
return self:move(l[1][1], l[1][2])
end
else
return self:move(lx, ly)
end
end
end
--- Main entry point for AIs
......
......@@ -187,6 +187,23 @@ dir_to_coord = {
[8] = { 0,-1},
[9] = { 1,-1},
}
coord_to_dir = {
[-1] = {
[-1] = 7,
[ 0] = 4,
[ 1] = 1,
},
[ 0] = {
[-1] = 8,
[ 0] = 5,
[ 1] = 2,
},
[ 1] = {
[-1] = 9,
[ 0] = 6,
[ 1] = 3,
},
}
util = {}
function util.boundWrap(i, min, max)
......
......@@ -73,6 +73,7 @@ function _M:newGame()
self.zone = Zone.new("ancient_ruins")
self.player = Player.new{
name=self.player_name, max_life=10000, display='@', color_r=230, color_g=230, color_b=230,
move_others=true,
}
self:changeLevel(1)
end
......@@ -164,6 +165,27 @@ function _M:display()
self.target.target.x, self.target.target.y = tmx, tmy
end
self.old_tmx, self.old_tmy = tmx, tmy
local act = self.level.map(tmx, tmy, engine.Map.ACTOR)
if act then
local s = core.display.newSurface(16,16)
s:alpha(125)
s:erase(0,255,255)
core.fov.calc_circle(act.x, act.y, act.sight, function(self, lx, ly)
if self.level.map:checkEntity(lx, ly, engine.Map.TERRAIN, "block_sight") then return true end
s:toScreen(self.level.map.display_x + (lx - game.level.map.mx) * self.level.map.tile_w, self.level.map.display_y + (ly - game.level.map.my) * self.level.map.tile_h)
local dst = self.level.map(lx, ly, engine.Map.ACTOR)
if dst then
-- table.insert(self.e_distances[e.uid], {uid=dst.uid, dist=core.fov.distance(e.x, e.y, dst.x, dst.y)})
-- print("found LOS", act.uid, dst.uid)
end
end, function()end, self)
end
end
engine.GameTurnBased.display(self)
......
......@@ -18,7 +18,7 @@ function _M:bumpInto(target)
-- TODO: implement !
elseif target.player and self.can_talk then
-- TODO: implement! requet the player to talk
else
elseif self.move_others then
-- Displace
game.level.map:remove(self.x, self.y, Map.ACTOR)
game.level.map:remove(target.x, target.y, Map.ACTOR)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment