Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
piXelicidio committed Mar 21, 2018
2 parents 98af607 + 0120ec7 commit ae8f9c3
Show file tree
Hide file tree
Showing 60 changed files with 3,347 additions and 97 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@ luac.out
*.hex

# Folders starting with 'i_'
i_*/
i_*/
*.love
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This is not a translation, is a remake from scratch using opensource engine Löv

Last screenshots:

![](https://raw.githubusercontent.com/piXelicidio/locas-ants/develop/screenshots/gridCellsOnly.gif)
![](https://raw.githubusercontent.com/piXelicidio/locas-ants/develop/screenshots/nicePath.gif)

(Btw, I'm learning Git/Github so beware of weird things with this my first Open Source"?" project)

Expand Down
91 changes: 62 additions & 29 deletions code/ant.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,22 @@ local map = {} --circular reference to Map module. Set

-- Sorry of the Delphi-like class styles :P
local TAnt = {}
local imgAntWalk = {}


-- PUBLIC class fields
function TAnt.setMap ( ourMap )
map = ourMap
end

-- a global init before any ant is created.
function TAnt.init()
imgAntWalk[0] = apiG.newImage('images//antWalk_01.png')
imgAntWalk[1] = apiG.newImage('images//antWalk_02.png')
imgAntWalk[2] = apiG.newImage('images//antWalk_02.png')
imgAntWalk[3] = apiG.newImage('images//antWalk_03.png')
end


-- Sim has to set this refernce to the grid
TAnt.grid = nil
Expand Down Expand Up @@ -43,25 +52,21 @@ function TAnt.create()
ant.direction = { 1.0, 0.0 } --direction heading movement unitary vector
ant.oldPosition = {0, 0}
ant.radius = 2
ant.speed = 0.1
ant.speed = 0.1
ant.traveled = 0 -- traveled distance
ant.friction = 1
ant.acceleration = 0.04 + math.random()*0.05
ant.erratic = cfg.antErratic --crazyness
ant.maxSpeed = cfg.antMaxSpeed
ant.tasks = {'food','cave'} --TODO: no need for Array of task, they can only have to targets, use two variables and swap
ant.maxSpeed = cfg.antMaxSpeed
ant.lookingForTask = 1
ant.comingFromTask = 0
--ant.lookingFor = 'food'
ant.comingFrom = ''
--ant.lastTimeSeenFood = -1
--ant.lastTimeSeenCave = -1
ant.comingFromTask = 0
ant.comingFrom = ''
ant.lastTimeSeen = {food = -1, cave = -1} --we can access t['food'] = n
ant.maxTimeSeen = -1
--ant.comingFromAtTime = 0
ant.maxTimeSeen = -1
ant.lastTimeUpdatedPath = -1
ant.lookingFor = 'food'
ant.nextTask = 'cave'
ant.cargo = { material = '', count = 0 }
ant.cargo = { material = '', count = 0, capacity = 1 }
ant.oldestPositionRemembered = {0,0} --vector 2D arr
ant.betterPathCount = 0
ant.color = cfg.colorAnts
Expand Down Expand Up @@ -98,6 +103,15 @@ function TAnt.create()
ant.oldestPositionRemembered = fPastPositions[1]
end

function ant.taskFound( cell )
--swap
ant.lookingFor, ant.nextTask = ant.nextTask, ant.lookingFor
local dv = vec.makeScale( ant.direction, -1) --go oposite
ant.direction = dv
ant.speed = 0
ant.disablePheromonesWrite( cfg.antPositionMemorySize )
end

function ant.updatePaused()
if cfg.simFrameNumber >= ant.pauseUntil then ant.unPause() end
end
Expand Down Expand Up @@ -163,27 +177,34 @@ function TAnt.create()

function ant.objectAvoidance()
local ahead = vec.makeScale( ant.direction, cfg.antSightDistance )
if not map.gridCanPass(vec.makeSum( ant.position, ahead )) --[[TAnt.map.anyCollisionWith( vec.makeSum( ant.position, ahead ) )]] then
local adir = { ant.direction[1], ant.direction[2] }
if not map.gridCanPass(vec.makeSum( ant.position, ahead )) then
-- if something blocking ahead, where to turn? left or right?
--print('something in my way')
local vLeft = vec.makeFrom( ant.direction )
local vRight = vec.makeFrom( ant.direction )
vec.rotate( vLeft, -cfg.antObjectAvoidance_FOV )
vec.rotate( vRight, cfg.antObjectAvoidance_FOV )
local goLeft = vec.makeScale( vLeft, cfg.antSightDistance/2 )
local goRight = vec.makeScale( vRight, cfg.antSightDistance/2 )
vec.add( goLeft, ant.position )
vec.add( goRight, ant.position )
local freeLeft = not map.gridCanPass( goLeft )
local freeRight = not map.gridCanPass( goRight )

if freeLeft and not freeRight then
--goleft
vec.setFrom( ant.direction, vLeft )
elseif not freeLeft then
--goright
vec.setFrom( ant.direction, vRight )
end --else keep going
local blocked = false
vec.rotate( vLeft, -cfg.antObjectAvoidance_FOV )
vec.rotate( vRight, cfg.antObjectAvoidance_FOV )
local goLeft = vec.makeScale( vLeft, cfg.antSightDistance/2 )
local goRight = vec.makeScale( vRight, cfg.antSightDistance/2 )
vec.add( goLeft, ant.position )
vec.add( goRight, ant.position )
local freeLeft = map.gridCanPass( goLeft )
local freeRight = map.gridCanPass( goRight )

if freeLeft and not freeRight then
--goleft
vec.setFrom( ant.direction, vLeft )
elseif freeRight and not freeLeft then
--goright
vec.setFrom( ant.direction, vRight )
elseif not freeLeft and not freeRight then
--I'm blocked try more wide, one more time
blocked = true
end

end
end

Expand All @@ -210,14 +231,26 @@ function TAnt.create()
--test pause
end

function ant.dirToRad()
if ant.direction[2]>0 then
return math.acos( ant.direction[1] )
else
return math.pi*2 - math.acos( ant.direction[1] )
end
end

function ant.drawNormal()
apiG.setColor(ant.color)

apiG.line(ant.position[1] - ant.direction[1]*2, ant.position[2] - ant.direction[2]*2, ant.position[1] + ant.direction[1]*2, ant.position[2] + ant.direction[2]*2 )
-- apiG.line(ant.position[1] - ant.direction[1]*2, ant.position[2] - ant.direction[2]*2, ant.position[1] + ant.direction[1]*2, ant.position[2] + ant.direction[2]*2 )
--sprites draw
local imgIdx = math.floor(ant.traveled % 4 )
apiG.draw(imgAntWalk[ imgIdx ], ant.position[1] , ant.position[2], ant.dirToRad(), cfg.imgScale, cfg.imgScale, 16, 16)


if ant.cargo.count~=0 then
apiG.setColor(cfg.colorFood)
if not cfg.debugGrid then apiG.circle("line", ant.position[1] + ant.direction[1]*2, ant.position[2] + ant.direction[2]*2, 0.5) end
if not cfg.debugGrid then apiG.circle("line", ant.position[1] + ant.direction[1]*2.1, ant.position[2] + ant.direction[2]*2.1, 0.5) end
end
-- debug
end
Expand Down
68 changes: 66 additions & 2 deletions code/cell.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ local apiG = love.graphics

local TCell = {}

TCell.cavesStorage = {}

local imgCave = {}
local imgFood = {}
local imgGrass = {}

local grass = {} --singleton class instance

--- cell base classs
function TCell.newCell()
local cell={}
Expand All @@ -15,24 +23,80 @@ function TCell.newCell()
return cell
end

function TCell.init()
imgCave = apiG.newImage('images//cave.png')
imgFood[3] = apiG.newImage('images//food04.png')
imgFood[2] = apiG.newImage('images//food03.png')
imgFood[1] = apiG.newImage('images//food02.png')
imgFood[0] = apiG.newImage('images//food01.png')
imgGrass = apiG.newImage('images//grass01.png')

-- singletons
grass = TCell.newCell()
grass.type = 'grass'
grass.pass = true
grass.img = imgGrass
grass.friction = 0.8
end

--- child class food
function TCell.newFood()
local food=TCell.newCell()
--public proeprties
food.type = 'food'
food.pass = true
food.color = cfg.colorFood
food.color = cfg.colorFood
food.storage = 1000
food.infinite = true
food.img = imgFood[3]

--methods
function food.affectAnt( ant )
if ant.lookingFor == food.type then
if (ant.cargo.count < ant.cargo.capacity ) and ( food.storage > 0 ) then
local take = ant.cargo.capacity - ant.cargo.count
if take >= food.storage then
ant.cargo.count = ant.cargo.count + food.storage
food.storage = 0
else
ant.cargo.count = ant.cargo.count + take
if not food.infinite then food.storage = food.storage - take end
end
end
ant.maxTimeSeen = 0
ant.taskFound(food)
end
end

return food
end

--- child class cave
--- child class cave - singleton?
function TCell.newCave()
local cave=TCell.newCell()
cave.type = 'cave'
cave.pass = true
cave.color = cfg.colorCave
cave.img = imgCave
--methods
function cave.affectAnt( ant )
if ant.lookingFor == cave.type then
ant.cargo.count = 0
ant.maxTimeSeen = 0
ant.taskFound(cave)
end
end
return cave
end

--- child class grass - singleton
function TCell.newGrass()
function grass.affectAnt( ant )
ant.friction = grass.friction
end
return grass
end


return TCell

26 changes: 18 additions & 8 deletions code/map.lua
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@ map.maxXg = math.floor(map.maxX / map.gridSize) + gridBorder
map.minYg = math.floor(map.minY / map.gridSize) - gridBorder
map.maxYg = math.floor(map.maxY / map.gridSize) + gridBorder

local imgGround = apiG.newImage('images//ground01.png')
local imgBlock = apiG.newImage('images//block01.png')

function map.init()
-- initializing all Grid data structure, avoiding future validations and mem allocation
TCell.init()
for i = map.minXg, map.maxXg do
map.grid[i]={}
for j = map.minYg, map.maxYg do
Expand All @@ -61,6 +65,8 @@ function map.initCell(xg, yg)
where = {0,0}, --the non-normalized vector direction of last position remembered.
}
end
if math.random()<0.002 then map.grid[xg][yg].cell = TCell.newGrass() end
if math.random()<0.001 then map.grid[xg][yg].pass = false end
end

function map.setCell_food(xg, yg)
Expand Down Expand Up @@ -210,6 +216,7 @@ function map.resolve_BlockingCollision_andMove( ant )
vec.setFrom( ant.direction, dir)
ant.position[1] = ant.position[1] + dir[1] * ant.speed
ant.position[2] = ant.position[2] + dir[2] * ant.speed
ant.traveled = ant.traveled + ant.speed

if numTries > 1 then
--there was al least one collision
Expand Down Expand Up @@ -291,25 +298,28 @@ local cellPheromInfo = function(cell, i, j)
end

function map.draw()
apiG.setColor( map.limitsColor )
apiG.rectangle("line", map.minX, map.minY, map.maxX-map.minX, map.maxY-map.minY )

--
--
for i = map.minXg, map.maxXg do
for j = map.minYg, map.maxYg do
if map.grid[i][j].pass then
apiG.setColor(255,255,255);
apiG.draw(imgGround, i*cfg.mapGridSize, j*cfg.mapGridSize, 0, cfg.imgScale, cfg.imgScale );
local cell = map.grid[i][j].cell
if cell then
apiG.setColor( cell.color )
apiG.rectangle('fill',i*cfg.mapGridSize, j*cfg.mapGridSize, cfg.mapGridSize , cfg.mapGridSize )
--apiG.setColor( cell.color )
apiG.draw(cell.img, i*cfg.mapGridSize, j*cfg.mapGridSize, 0, cfg.imgScale, cfg.imgScale )
end
else
apiG.setColor( cfg.colorObstacle )
apiG.rectangle('fill',i*cfg.mapGridSize, j*cfg.mapGridSize, cfg.mapGridSize , cfg.mapGridSize )
-- apiG.setColor( cfg.colorObstacle )
-- apiG.rectangle('fill',i*cfg.mapGridSize, j*cfg.mapGridSize, cfg.mapGridSize , cfg.mapGridSize )
apiG.setColor(255,255,255);
apiG.draw(imgBlock, i*cfg.mapGridSize, j*cfg.mapGridSize, 0, cfg.imgScale, cfg.imgScale );
end
end
end
--debuging grid
apiG.setColor( map.limitsColor )
apiG.rectangle("line", map.minX, map.minY, map.maxX-map.minX, map.maxY-map.minY )

if cfg.debugGrid then
map.gridForEachCell( cellcount )
Expand Down
14 changes: 9 additions & 5 deletions code/simconfig.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,29 @@

local simconfig = {

numAnts = 2550,
numAnts = 4500,
antMaxSpeed = 1.2,
antComAlgorithm = 1, -- 0 = Nothing; 1 = Pheromones inspiration
antComEveryFrame = false, -- comunicate every frame? or use values of antComNeedFrameStep below
antComNeedFrameStep = {3,13}, -- {a,b} ant would need for comunication with other ants every amount of frames form a to b. Greater values more speed less path quality.
antSightDistance = 30, -- Only bellow this distance the ant can identify and locate|avoid things, bettr if > than antComRadius
antPositionMemorySize = 15, -- How many past position they can remember
antPositionMemorySize = 10, -- How many past position they can remember
antErratic = 0.2,
antInterests = {'food','cave'},
antObjectAvoidance = true,
antObjectAvoidance_FOV = 3.14/6, -- Field of view, for avoiding collision, number is half of angle in radians

debugGrid = false,
debugPheromones = false,
debugHideAnts = false,
debugCounters = {0,0,0,0,0,0},

-- our map dimensions, it can grow on any direction not only on positive integers
mapMinX = -350,
mapMinY = -250,
mapMaxX = 550,
mapMaxY = 350,
mapGridSize = 20,
mapGridSize = 16,
mapGridComScan = {
--this are the neibor cells we are going to scan looking for near ants to do communications... normal is 8 'N'eibor cells in square formation around 'C'enter cell.
-- mapGridComScan[2..9]=neibors
Expand All @@ -43,9 +44,12 @@ local simconfig = {
{ 1, 1},
},

colorAnts = {20,10,0},
zoomMaxScale = 4,
imgScale = 1/4,

colorAnts = {255,255,255},
colorObstacle = {200,200,200},
colorFood = {240, 240, 230},
colorFood = {250, 240, 100},
colorCave = {40,40,40},
colorBk = {180,180,180},
colorBkLimits = {120, 120, 120},
Expand Down
Loading

0 comments on commit ae8f9c3

Please sign in to comment.