Bladeren bron

Editor selections; Rework Collision and View;

tie372 11 jaren geleden
bovenliggende
commit
b90fdd4513

+ 2 - 2
data/class/brute.lua

@@ -7,7 +7,7 @@ Brute.code = 'brute'
 ----------------
 Brute.health = 235
 Brute.speed  = 150
-Brute.size = 20
+Brute.radius = 20
 
 
 ----------------
@@ -31,4 +31,4 @@ Brute.slots[3] = data.skill.adrenaline
 Brute.slots[4] = data.skill.rage
 Brute.slots[5] = data.skill.bloodlust
 
-return Brute
+return Brute

+ 9 - 13
data/prop/tree.lua

@@ -2,8 +2,12 @@ local Tree = {}
 Tree.name = 'Tree'
 Tree.code = 'tree'
 
+Tree.collision = {}
+Tree.collision.shape = 'circle'
+Tree.collision.solid = true
+
 Tree.activate = function(self, map)
-  self.scale = .5
+  if ovw.collision then ovw.collision:register(self) end
   self.image = map.graphics.tree
 end
 
@@ -20,19 +24,11 @@ Tree.draw = function(self)
   else
     love.graphics.setColor(255, 255, 255)
   end
-	love.graphics.draw(self.image, x, y, 0, self.scale, self.scale, self.image:getWidth() / 2, self.image:getHeight() / 2)
+  love.graphics.draw(self.image, x, y, 0, self.radius / 20, self.radius / 20, self.image:getWidth() / 2, self.image:getHeight() / 2)
 end
 
 Tree.editor = {}
-Tree.editor.boundingBox = function(self)
-  local w, h = self.image:getWidth(), self.image:getHeight()
-  return self.x - (self.scale * w / 2), self.y - (self.scale * h / 2), self.scale * w, self.scale * h
-end
-
-Tree.editor.move = function(self, x, y)
-  
-end
-
+Tree.editor.move = f.empty
 Tree.editor.scale = function(self, hx, hy, ew, eh, ox, oy, ow, oh)
   ew = ew * hx
   eh = eh * hy
@@ -44,8 +40,8 @@ Tree.editor.save = function(self)
     kind = 'tree',
     x = ]] .. self.x .. [[,
     y = ]] .. self.y .. [[,
-    scale = ]] .. self.scale .. [[
+    radius = ]] .. self.radius .. [[
   }]]
 end
 
-return Tree
+return Tree

+ 35 - 31
data/prop/wall.lua

@@ -2,8 +2,12 @@ local Wall = {}
 Wall.name = 'Wall'
 Wall.code = 'wall'
 
+Wall.collision = {}
+Wall.collision.shape = 'rectangle'
+Wall.collision.solid = true
+
 Wall.activate = function(self, map)
-  if ovw.collision then ovw.collision:addWall(self.x, self.y, self.w, self.h) end
+  if ovw.collision then ovw.collision:register(self) end
 
   self.top = love.graphics.newMesh({
     {0, 0, 0, 0},
@@ -14,7 +18,7 @@ Wall.activate = function(self, map)
 
   self.north = love.graphics.newMesh({
     {self.x, self.y, 0, 0, 0, 0, 0},
-    {self.x + self.w, self.y, 1, 0, 0, 0, 0},
+    {self.x + self.width, self.y, 1, 0, 0, 0, 0},
     {0, 0, 1, 1},
     {0, 0, 0, 1}
   }, map.graphics.grass)
@@ -22,14 +26,14 @@ Wall.activate = function(self, map)
   self.south = love.graphics.newMesh({
     {0, 0, 0, 0},
     {0, 0, 1, 0},
-    {self.x + self.w, self.y + self.h, 1, 1, 0, 0, 0},
-    {self.x, self.y + self.h, 0, 1, 0, 0, 0}
+    {self.x + self.width, self.y + self.height, 1, 1, 0, 0, 0},
+    {self.x, self.y + self.height, 0, 1, 0, 0, 0}
   }, map.graphics.grass)
 
   self.east = love.graphics.newMesh({
     {0, 0, 0, 0},
-    {self.x + self.w, self.y, 1, 0, 0, 0, 0},
-    {self.x + self.w, self.y + self.h, 1, 1, 0, 0, 0},
+    {self.x + self.width, self.y, 1, 0, 0, 0, 0},
+    {self.x + self.width, self.y + self.height, 1, 1, 0, 0, 0},
     {0, 0, 0, 1}
   }, map.graphics.grass)
 
@@ -37,7 +41,7 @@ Wall.activate = function(self, map)
     {self.x, self.y, 0, 0, 0, 0, 0},
     {0, 0, 1, 0},
     {0, 0, 1, 1},
-    {self.x, self.y + self.h, 0, 1, 0, 0, 0}
+    {self.x, self.y + self.height, 0, 1, 0, 0, 0}
   }, map.graphics.grass)
 
   self.depth = -5
@@ -53,9 +57,9 @@ Wall.draw = function(self)
   
   local v = ovw.view
   local ulx, uly = v:three(self.x, self.y, self.z)
-  local urx, ury = v:three(self.x + self.w, self.y, self.z)
-  local llx, lly = v:three(self.x, self.y + self.h, self.z)
-  local lrx, lry = v:three(self.x + self.w, self.y + self.h, self.z)
+  local urx, ury = v:three(self.x + self.width, self.y, self.z)
+  local llx, lly = v:three(self.x, self.y + self.height, self.z)
+  local lrx, lry = v:three(self.x + self.width, self.y + self.height, self.z)
 
   self.top:setVertex(1, ulx, uly, 0, 0)
   self.top:setVertex(2, urx, ury, 1, 0)
@@ -70,7 +74,7 @@ Wall.draw = function(self)
     love.graphics.draw(self.north, 0, 0)
   end
 
-  if self.y + self.h < y2 then
+  if self.y + self.height < y2 then
     self.south:setVertex(1, llx, lly, 0, 0)
     self.south:setVertex(2, lrx, lry, 1, 0)
     love.graphics.draw(self.south, 0, 0)
@@ -83,7 +87,7 @@ Wall.draw = function(self)
     love.graphics.draw(self.west, 0, 0)
   end
 
-  if self.x + self.w < x2 then
+  if self.x + self.width < x2 then
     self.east:setVertex(1, urx, ury, 0, 0)
     self.east:setVertex(4, lrx, lry, 0, 1)
     love.graphics.draw(self.east, 0, 0)
@@ -94,43 +98,43 @@ end
 
 Wall.editor = {}
 Wall.editor.boundingBox = function(self)
-  return self.x, self.y, self.w, self.h
+  return self.x, self.y, self.width, self.height
 end
 
 Wall.editor.move = function(self, x, y)
   self.north:setVertex(1, self.x, self.y, 0, 0, 0, 0, 0)
-  self.north:setVertex(2, self.x + self.w, self.y, 1, 0, 0, 0, 0)
+  self.north:setVertex(2, self.x + self.width, self.y, 1, 0, 0, 0, 0)
 
-  self.south:setVertex(3, self.x + self.w, self.y + self.h, 1, 1, 0, 0, 0)
-  self.south:setVertex(4, self.x, self.y + self.h, 0, 1, 0, 0, 0)
+  self.south:setVertex(3, self.x + self.width, self.y + self.height, 1, 1, 0, 0, 0)
+  self.south:setVertex(4, self.x, self.y + self.height, 0, 1, 0, 0, 0)
 
-  self.east:setVertex(2, self.x + self.w, self.y, 1, 0, 0, 0, 0)
-  self.east:setVertex(3, self.x + self.w, self.y + self.h, 1, 1, 0, 0, 0)
+  self.east:setVertex(2, self.x + self.width, self.y, 1, 0, 0, 0, 0)
+  self.east:setVertex(3, self.x + self.width, self.y + self.height, 1, 1, 0, 0, 0)
 
   self.west:setVertex(1, self.x, self.y, 0, 0, 0, 0, 0)
-  self.west:setVertex(4, self.x, self.y + self.h, 0, 1, 0, 0, 0)
+  self.west:setVertex(4, self.x, self.y + self.height, 0, 1, 0, 0, 0)
 end
 
 Wall.editor.scale = function(self, hx, hy, ew, eh, ox, oy, ow, oh)
   self.x, self.y = ox, oy
-  self.w, self.h = ow, oh
+  self.width, self.height = ow, oh
   
-  self.w = self.w + (ew * math.sign(hx))
-  self.h = self.h + (eh * math.sign(hy))
+  self.width = self.width + (ew * math.sign(hx))
+  self.height = self.height + (eh * math.sign(hy))
   if hx < 0 then self.x = self.x + ew end
   if hy < 0 then self.y = self.y + eh end
   
   self.north:setVertex(1, self.x, self.y, 0, 0, 0, 0)
-  self.north:setVertex(2, self.x + self.w, self.y, 1, 0, 0, 0, 0)
+  self.north:setVertex(2, self.x + self.width, self.y, 1, 0, 0, 0, 0)
 
-  self.south:setVertex(3, self.x + self.w, self.y + self.h, 1, 1, 0, 0, 0)
-  self.south:setVertex(4, self.x, self.y + self.h, 0, 1, 0, 0, 0)
+  self.south:setVertex(3, self.x + self.width, self.y + self.height, 1, 1, 0, 0, 0)
+  self.south:setVertex(4, self.x, self.y + self.height, 0, 1, 0, 0, 0)
 
-  self.east:setVertex(2, self.x + self.w, self.y, 1, 0, 0, 0, 0)
-  self.east:setVertex(3, self.x + self.w, self.y + self.h, 1, 1, 0, 0, 0)
+  self.east:setVertex(2, self.x + self.width, self.y, 1, 0, 0, 0, 0)
+  self.east:setVertex(3, self.x + self.width, self.y + self.height, 1, 1, 0, 0, 0)
 
   self.west:setVertex(1, self.x, self.y, 0, 0, 0, 0, 0)
-  self.west:setVertex(4, self.x, self.y + self.h, 0, 1, 0, 0, 0)
+  self.west:setVertex(4, self.x, self.y + self.height, 0, 1, 0, 0, 0)
 end
 
 Wall.editor.save = function(self)
@@ -138,10 +142,10 @@ Wall.editor.save = function(self)
     kind = 'wall',
     x = ]] .. self.x .. [[,
     y = ]] .. self.y .. [[,
-    w = ]] .. self.w .. [[,
-    h = ]] .. self.h .. [[,
+    w = ]] .. self.width .. [[,
+    h = ]] .. self.height .. [[,
     z = ]] .. self.z .. [[
   }]]
 end
 
-return Wall
+return Wall

+ 23 - 13
lib/collision.lua

@@ -1,5 +1,3 @@
-local hardon = require('lib/hardon')
-
 Collision = class()
 
 local cellSize = 128
@@ -22,8 +20,7 @@ function Collision:init()
       b:move(-dx, -dy)
       local p = self.playerShadows[self.players[b]] or ovw.players:get(self.players[b])
       p.x, p.y = p.x - dx, p.y - dy
-    else
-      
+    else      
       a:move(dx / 2, dy / 2)
       b:move(-dx / 2, -dy / 2)
     end
@@ -31,7 +28,6 @@ function Collision:init()
   
   self.players = {}
   self.playerShadows = {}
-  self.walls = {}
   
   ovw.event:on(evtClass, function(data)
     local shape = self.hc:addCircle(0, 0, gg.class[data.class].size)
@@ -47,12 +43,6 @@ function Collision:init()
   end)
 end
 
-function Collision:addWall(...)
-  local wall = self.hc:addRectangle(...)
-  self.hc:setPassive(wall)
-  self.walls[wall] = wall
-end
-
 function Collision:update()
   for i = 1, 16 do
     if self.players[i] then
@@ -71,12 +61,32 @@ function Collision:updateClone(id, obj)
   self.playerShadows[id] = nil
 end
 
+function Collision:register(obj)
+  if not obj.shape then
+    assert(obj.collision)
+    local shape
+    if obj.collision.shape == 'rectangle' then
+      shape = self.hc:addRectangle(obj.x, obj.y, obj.width, obj.height)
+    elseif obj.collision.shape == 'circle' then
+      shape = self.hc:addCircle(obj.x, obj.y, obj.radius)
+    end
+
+    if obj.collision.solid then
+      shape:setPassive()
+    end
+
+    obj.shape = shape
+    shape.owner = obj
+  end
+end
+
 function Collision:wallRaycast(x, y, dir, distance)
   local dx, dy = math.cos(dir), math.sin(dir)
   local shapes = {}
   local distances = {}
   
-  for _, shape in pairs(self.walls) do
+  for _, prop in pairs(ovw.map.propsBy.wall) do
+    local shape = prop.shape
     local hit, dis = shape:intersectsRay(x, y, dx, dy)
     if hit and dis <= distance and dis >= 0 then
       shapes[#shapes + 1] = shape
@@ -115,4 +125,4 @@ function Collision:playerRaycast(x, y, dir, options)
   if sort then table.sort(res, function(a, b) return a.distance < b.distance end) end
   
   return all and res or res[1]
-end
+end

+ 6 - 3
lib/editor.lua

@@ -1,14 +1,17 @@
+local hardon = require 'lib/hardon'
+
 Editor = class()
 
 function Editor:load()
   self.grid = EditorGrid()
   
   self.view = EditorView()
+	self.collision = EditorCollision()
   self.map = Map()
   self.event = Event()
   self.menu = EditorMenu()
   self.dragger = EditorDragger()
-  self.scaler = EditorScaler()
+  --self.scaler = EditorScaler()
   self.selector = EditorSelector()
   self.deletor = EditorDeletor()
   self.state = EditorState()
@@ -19,7 +22,7 @@ function Editor:load()
     self.view,
     self.menu,
     self.dragger,
-    self.scaler,
+    --self.scaler,
     self.deletor,
     self.selector,
     self.state,
@@ -57,4 +60,4 @@ end
 function Editor:mousereleased(x, y, button)
   table.each(self.components, f.egoexe('mousereleased', x, y, button))
   table.each(self.widgets, f.egoexe('mousereleased', x, y, button))
-end
+end

+ 32 - 0
lib/editor/editorcollision.lua

@@ -0,0 +1,32 @@
+local hardon = require 'lib/hardon'
+local cellSize = 128
+
+EditorCollision = class()
+
+function EditorCollision:init()
+  self.hc = hardon(cellSize)
+end
+
+function EditorCollision:update()
+	self.hc:update(tickRate)
+end
+
+function EditorCollision:register(obj)
+	if not obj.shape then
+		assert(obj.collision)
+		local shape
+		if obj.collision.shape == 'rectangle' then
+			shape = self.hc:addRectangle(obj.x, obj.y, obj.width, obj.height)
+		elseif obj.collision.shape == 'circle' then
+			shape = self.hc:addCircle(obj.x, obj.y, obj.radius)
+		end
+
+		if obj.collision.solid then
+			self.hc:setPassive(shape)
+		end
+
+		obj.shape = shape
+		shape.owner = obj
+	end
+end
+

+ 2 - 1
lib/editor/editordragger.lua

@@ -27,6 +27,7 @@ function EditorDragger:mousepressed(x, y, button)
     self.deselect = nil
     if love.keyboard.isDown('lshift') then return end
     if #ovw.selector.selection == 0 then
+			do return end
       local p = ovw.selector:pointTest(x, y)
       if p then ovw.selector:select(p) end
       self.deselect = p
@@ -45,4 +46,4 @@ function EditorDragger:mousereleased(x, y, button)
   if self.dragging then ovw.state:push() end
   self.dragging = false
   if self.deselect then ovw.selector:deselect(self.deselect) end
-end
+end

+ 2 - 1
lib/editor/editorgrid.lua

@@ -20,6 +20,7 @@ function EditorGrid:draw()
   for i = .5, ovw.map.height, self.size do
     g.line(0, i, ovw.map.width, i)
   end
+  g.setLineWidth(1)
 end
 
 function EditorGrid:keypressed(key)
@@ -30,4 +31,4 @@ end
 function EditorGrid:snap(x, y)
   if love.keyboard.isDown('lalt') then return x, y end
   return math.round(x / self.size) * self.size, math.round(y / self.size) * self.size
-end
+end

+ 119 - 31
lib/editor/editorselector.lua

@@ -1,4 +1,5 @@
 EditorSelector = class()
+EditorSelector.doubleClickSpeed = .5
 
 local function invoke(x, k, ...) return x.editor[k](x, ...) end
 
@@ -6,79 +7,166 @@ function EditorSelector:init()
   self.selection = {}
   self.active = false
   self.depth = -10000
+	self.lastClick = tick
+	self.dragging = false
+	self.dragStartX = nil
+	self.dragStartY = nil
   ovw.view:register(self)
 end
 
 function EditorSelector:update()
   self.active = love.keyboard.isDown('lshift')
+	if self.active and love.mouse.isDown('l', 'r') and math.distance(self.dragStartX, self.dragStartY, love.mouse.getPosition()) > 5 then
+		self.dragging = true
+	end
 end
 
 function EditorSelector:draw()
   love.graphics.setColor(0, 255, 255, 50)
   if self.active then
     table.each(ovw.map.props, function(prop)
-      love.graphics.rectangle('line', invoke(prop, 'boundingBox'))
+			prop.shape:draw('line')
     end)
   end
   
   love.graphics.setColor(0, 255, 255, 100)
-  for _, p in ipairs(self.selection) do
-    love.graphics.rectangle('fill', invoke(p, 'boundingBox'))
+  for _, prop in ipairs(self.selection) do
+		prop.shape:draw('fill')
   end
 end
 
+function EditorSelector:gui()
+	if self.active and self.dragging then
+		if love.keyboard.isDown('lctrl') then
+			love.graphics.setColor(0, 255, 255, 150)
+			love.graphics.line(self.dragStartX, self.dragStartY, love.mouse.getPosition())
+		else
+			love.graphics.setColor(0, 255, 255, 25)
+			local x, y = self.dragStartX + .5, self.dragStartY + .5
+			local w, h = love.mouse.getX() - self.dragStartX - 1, love.mouse.getY() - self.dragStartY - 1
+			love.graphics.rectangle('fill', x, y, w, h)
+			love.graphics.setColor(0, 255, 255, 150)
+			love.graphics.rectangle('line', x, y, w, h)
+		end
+	end
+end
+
 function EditorSelector:pointTest(x, y)
-  for i = 1, #ovw.map.props do
-    local p = ovw.map.props[i]
-    local x, y, w, h = invoke(p, 'boundingBox')
-    if math.inside(mouseX(), mouseY(), x, y, w, h) then
-      return p
-    end
-  end
+	local shapes = ovw.collision.hc:shapesAt(x + ovw.view.x, y + ovw.view.y)
+	return table.map(shapes, function(s) return s.owner end)
+end
+
+function EditorSelector:rectTest(x1, y1, x2, y2)
+	if x1 > x2 then x1, x2 = x2, x1 end
+	if y1 > y2 then y1, y2 = y2, y1 end
+	x1, y1 = ovw.view:transform(x1, y1)
+	x2, y2 = ovw.view:transform(x2, y2)
+	local selectRect = ovw.collision.hc:addRectangle(x1, y1, x2 - x1, y2 - y1)
+	
+	local res = {}
+	for shape in pairs(selectRect:neighbors()) do
+		if selectRect:collidesWith(shape) then
+			table.insert(res, shape.owner)
+		end
+	end
+
+	ovw.collision.hc:remove(selectRect)
+	
+	return res
+end
+
+function EditorSelector:lineTest(x1, y1, x2, y2)
+	x1, y1 = ovw.view:transform(x1, y1)
+	x2, y2 = ovw.view:transform(x2, y2)
+	local dis = math.distance(x1, y1, x2, y2)
+	
+	local res = {}
+	for shape in pairs(ovw.collision.hc:shapesInRange(math.min(x1, x2), math.min(y1, y2), math.max(x1, x2), math.max(y1, y2))) do
+		local intersects, d = shape:intersectsRay(x1, y1, x2 - x1, y2 - y1)
+		if intersects then
+			table.insert(res, shape.owner)
+		end
+	end
+
+	return res
 end
 
 function EditorSelector:mousepressed(x, y, button)
+	local function doubleClick()
+		return (tick - self.lastClick) * tickRate <= self.doubleClickSpeed
+	end
+
   if self.active then
     if button == 'l' then
-      local p = self:pointTest(x, y)
-      if p then self:toggleSelect(p) end
+			if doubleClick() then
+				self:selectAll()
+			else
+				self:select(unpack(self:pointTest(x, y)))
+			end
+			self.lastClick = tick
+			self.dragStartX = x
+			self.dragStartY = y
     elseif button == 'r' then
-      self:deselectAll()
+			if doubleClick() then
+				self:deselectAll()
+			else
+				self:deselect(unpack(self:pointTest(x, y)))
+			end
+			self.lastClick = tick
+			self.dragStartX = x
+			self.dragStartY = y
     end
   end
 end
 
-function EditorSelector:select(prop)
-  if not self.selection[prop] then self:toggleSelect(prop) end
+function EditorSelector:mousereleased(x, y, button)
+	if self.active and self.dragging then
+		local selector = love.keyboard.isDown('lctrl') and self.lineTest or self.rectTest
+		local targets = selector(self, self.dragStartX, self.dragStartY, x, y)
+		if button == 'l' then
+			self:select(unpack(targets))
+		elseif button == 'r' then
+			self:deselect(unpack(targets))
+		end
+		self.dragging = false
+	end
 end
 
-function EditorSelector:deselect(prop)
-  if self.selection[prop] then self:toggleSelect(prop) end
+function EditorSelector:select(prop, ...)
+	if not prop then return end
+
+	if not self.selection[prop] then
+		table.insert(self.selection, prop)
+		self.selection[prop] = #self.selection
+	end
+	
+	return self:select(...)
 end
 
-function EditorSelector:toggleSelect(prop)
-  if self.selection[prop] then
-    for i = self.selection[prop] + 1, #self.selection do
-      self.selection[self.selection[i]] = self.selection[self.selection[i]] - 1
-    end
-    table.remove(self.selection, self.selection[prop])
-    self.selection[prop] = nil
-  else
-    table.insert(self.selection, prop)
-    self.selection[prop] = #self.selection
-  end
+function EditorSelector:deselect(prop, ...)
+	if not prop then return end
+
+	if self.selection[prop] then
+		for i = self.selection[prop] + 1, #self.selection do
+			self.selection[self.selection[i]] = self.selection[self.selection[i]] - 1
+		end
+		table.remove(self.selection, self.selection[prop])
+		self.selection[prop] = nil
+	end
+	
+	return self:deselect(...)
 end
 
 function EditorSelector:selectAll()
-  table.each(ovw.map.props, f.cur(self.select, self))
+	self:select(unpack(ovw.map.props))
 end
 
 function EditorSelector:deselectAll()
-  table.clear(self.selection)
+	self:deselect(unpack(ovw.map.props))
 end
 
 function EditorSelector:each(fn)
   for i = 1, #self.selection do
     fn(self.selection[i])
   end
-end
+end

+ 5 - 1
lib/editor/editorview.lua

@@ -59,4 +59,8 @@ function EditorView:mousepressed(x, y, button)
   end
 end
 
-EditorView.contain = f.empty
+function EditorView:transform(x, y)
+	return x / self.scale + self.x, y / self.scale + self.y
+end
+
+EditorView.contain = f.empty

+ 70 - 68
lib/gooey/textbox.lua

@@ -3,93 +3,95 @@ TextBox = class()
 local g = love.graphics
 
 function TextBox:init()
-	self.x = 0
-	self.y = 0
-	self.w = 0
-	self.h = 0
-	self.bgColor = {0, 0, 0, 255}
-	self.borderColor = {0, 0, 0, 255}
+  self.x = 0
+  self.y = 0
+  self.w = 0
+  self.h = 0
+  self.bgColor = {0, 0, 0, 255}
+  self.borderColor = {0, 0, 0, 255}
 
-	self.font = nil
-	self.fontSize = 0
-	self.fontColor = {255, 255, 255, 255}
+  self.font = nil
+  self.fontSize = 0
+  self.fontColor = {255, 255, 255, 255}
 
-	self.hPadding = 0
-	self.vPadding = 0
+  self.hPadding = 0
+  self.vPadding = 0
 
-	self.text = ''
+  self.text = ''
 
-	self.focused = false
-	self.insertAt = 1
+  self.focused = false
+  self.insertAt = 1
 
-	self.onfocus = nil
-	self.onblur = nil
-	self.onchange = nil
+  self.onfocus = nil
+  self.onblur = nil
+  self.onchange = nil
+
+  self.onfocus = nil
 end
 
 function TextBox:focus()
-	if not self.focused then
-		self.focused = true
-		f.exe(self.onfocus, self)
-		love.keyboard.setKeyRepeat(true)
-	end
+  if not self.focused then
+    self.focused = true
+    f.exe(self.onfocus, self)
+    love.keyboard.setKeyRepeat(true)
+  end
 end
 
 function TextBox:blur()
-	if self.focused then
-		self.focused = false
-		f.exe(self.onblur, self)
-		love.keyboard.setKeyRepeat(false)
-	end
+  if self.focused then
+    self.focused = false
+    f.exe(self.onblur, self)
+    love.keyboard.setKeyRepeat(false)
+  end
 end
 
 function TextBox:keypressed(key)
-	if key == 'backspace' and self.focused and self.insertAt > 1 then
-		self.text = self.text:sub(1, self.insertAt - 2) .. self.text:sub(self.insertAt)
-		self.insertAt = self.insertAt - 1
-		f.exe(self.onchange, self)
-	elseif key == 'left' and self.insertAt > 1 then
-		self.insertAt = self.insertAt - 1
-	elseif key == 'right' and self.insertAt < #self.text + 1 then
-		self.insertAt = self.insertAt + 1
-	end
+  if key == 'backspace' and self.focused and self.insertAt > 1 then
+    self.text = self.text:sub(1, self.insertAt - 2) .. self.text:sub(self.insertAt)
+    self.insertAt = self.insertAt - 1
+    f.exe(self.onchange, self)
+  elseif key == 'left' and self.insertAt > 1 then
+    self.insertAt = self.insertAt - 1
+  elseif key == 'right' and self.insertAt < #self.text + 1 then
+    self.insertAt = self.insertAt + 1
+  end
 end
 
 function TextBox:textinput(char)
-	if self.focused then
-		self.text = self.text:sub(1, self.insertAt - 1) .. char .. self.text:sub(self.insertAt)
-		self.insertAt = self.insertAt + 1
-		f.exe(self.onchange, self)
-	end
+  if self.focused then
+    self.text = self.text:sub(1, self.insertAt - 1) .. char .. self.text:sub(self.insertAt)
+    self.insertAt = self.insertAt + 1
+    f.exe(self.onchange, self)
+  end
 end
 
 function TextBox:draw()
 
-	g.setColor(self.bgColor)
-	g.rectangle('fill', self.x, self.y, self.w, self.h)
-	g.setColor(self.borderColor)
-	g.rectangle('line', self.x + .5, self.y + .5, self.w - 1, self.h - 1)
-
-	g.setFontPixel(self.font, self.fontSize)
-	g.setColor(self.fontColor)
-
-	local str = self.text
-	if self.placeholder and #self.text == 0 then
-		local r, g, b, a = g.getColor()
-		a = a / 2
-		love.graphics.setColor(r, g, b, a)
-		str = self.placeholder
-	end
-	
-	local font = g.getFont()
-	local x = self.x + self.hPadding
-	local y = self.y + self.h / 2 - font:getHeight() / 2
-
-	g.print(str, x, y)
-
-	if self.focused then
-		local xx = self.x + self.hPadding + font:getWidth(self.text:sub(1, self.insertAt - 1)) + .5
-		g.setColor(self.fontColor)
-		g.line(xx, y, xx, y + font:getHeight())
-	end
+  g.setColor(self.bgColor)
+  g.rectangle('fill', self.x, self.y, self.w, self.h)
+  g.setColor(self.borderColor)
+  g.rectangle('line', self.x + .5, self.y + .5, self.w - 1, self.h - 1)
+
+  g.setFontPixel(self.font, self.fontSize)
+  g.setColor(self.fontColor)
+
+  local str = self.text
+  if self.placeholder and #self.text == 0 then
+    local r, g, b, a = g.getColor()
+    a = a / 2
+    love.graphics.setColor(r, g, b, a)
+    str = self.placeholder
+  end
+  
+  local font = g.getFont()
+  local x = self.x + self.hPadding
+  local y = self.y + self.h / 2 - font:getHeight() / 2
+
+  g.print(str, x, y)
+
+  if self.focused then
+    local xx = self.x + self.hPadding + font:getWidth(self.text:sub(1, self.insertAt - 1)) + .5
+    g.setColor(self.fontColor)
+    g.line(xx, y, xx, y + font:getHeight())
+  end
 end

+ 3 - 2
lib/hud.lua

@@ -15,6 +15,7 @@ function Hud:init()
   
   ovw.event:on(evtChat, function(data) self.chat:add(data) end)
   ovw.event:on(evtDead, function(data) self.feed:insert(data) end)
+	ovw.view:register(self)
 end
 
 function Hud:update()
@@ -24,7 +25,7 @@ function Hud:update()
   self.classSelect:update()
 end
 
-function Hud:draw()
+function Hud:gui()
   g.reset()
   
   if not myId then return self:connecting() end
@@ -70,4 +71,4 @@ function Hud:connecting()
   if tick > (6 / tickRate) + 10 then str = str .. ' oshit' end
   if tick > 10 / tickRate then str = str .. '\n' str = str .. string.rep('fuck', math.min(10, (tick - (10 / tickRate)) / 3)) end
   g.printf(str, 0, math.floor(love.window.getHeight() / 2 - love.graphics.height(.02)), love.window.getWidth(), 'center')
-end
+end

+ 4 - 1
lib/map.lua

@@ -20,6 +20,7 @@ function Map:init(name)
   local map = safeLoad(dir .. name .. '.lua')
   map.graphics = {}
   map.props = {}
+  map.propsBy = {}
   
   for _, file in ipairs(love.filesystem.getDirectoryItems(dir)) do
     if file:match('%.png$') then
@@ -76,6 +77,8 @@ end
 function Map:initProp(prop)
   setmetatable(prop, {__index = data.prop[prop.kind]})
   f.exe(prop.activate, prop, self)
+  self.propsBy[prop.kind] = self.propsBy[prop.kind] or {}
+  table.insert(self.propsBy[prop.kind], prop)
   if ovw.view then ovw.view:register(prop) end
   return prop
-end
+end

+ 3 - 2
lib/player.lua

@@ -20,7 +20,8 @@ function Player:create()
     maxSpeed = 0,
     maxHealth = 0,
     lifesteal = 0,
-    size = 0,
+		shape = 'cirlce',
+		radius = 0,
     depth = 0,
     recoil = 0,
     visible = 0,
@@ -150,4 +151,4 @@ end
 
 function Player:spawn()
   self:activate()
-end
+end

+ 1 - 0
lib/players.lua

@@ -58,6 +58,7 @@ function Players:activate(id)
   assert(id >= 1 and id <= 16)
   self.players[id].active = true
   if ovw.view then ovw.view:register(self.players[id]) end
+  if ovw.collision then ovw.collision:register(self.players[id]) end
   self:refresh()
 end
 

+ 7 - 3
lib/view.lua

@@ -31,6 +31,7 @@ end
 
 function View:register(x)
   table.insert(self.toDraw, x)
+  x.depth = x.depth or 0
 end
 
 function View:unregister(x)
@@ -77,9 +78,12 @@ function View:draw()
     return a.depth > b.depth
   end)
 
-  for k, v in ipairs(self.toDraw) do v:draw() end
+  for _, v in ipairs(self.toDraw) do f.exe(v.draw, v) end
+
   self:pop()
-  if ovw.hud then ovw.hud:draw() end
+
+  for _, v in ipairs(self.toDraw) do f.exe(v.gui, v) end
+  
   self:letterbox()
 end
 
@@ -110,4 +114,4 @@ function View:contain()
   if self.y < 0 then self.y = 0 end
   if self.x + self.w > ovw.map.width then self.x = ovw.map.width - self.w end
   if self.y + self.h > ovw.map.height then self.y = ovw.map.height - self.h end
-end
+end

+ 27 - 26
maps/jungleCarnage/props.lua

@@ -3,101 +3,102 @@ return {
     kind = 'wall',
     x = 128,
     y = 128 + 128,
-    w = 128,
-    h = 64,
+    width = 128,
+    height = 64,
     z = 64
   },
   {
     kind = 'wall',
     x = 128 + 128,
     y = 128,
-    w = 64,
-    h = 128,
+    width = 64,
+    height = 128,
     z = 64
   },
   {
     kind = 'wall',
     x = 1600 - (128 + 128 + 64),
     y = 1200 - (128 + 128),
-    w = 64,
-    h = 128,
+    width = 64,
+    height = 128,
     z = 64
   },
   {
     kind = 'wall',
     x = 1600 - (128 + 128),
     y = 1200 - (128 + 128 + 64),
-    w = 128,
-    h = 64,
+    width = 128,
+    height = 64,
     z = 64
   },
   {
     kind = 'wall',
     x = (1600 / 2) - 32,
     y = (1200 / 2) - 128,
-    w = 64,
-    h = 96,
+    width = 64,
+    height = 96,
     z = 64
   },
   {
     kind = 'wall',
     x = (1600 / 2) - 128,
     y = (1200 / 2) - 32,
-    w = 96,
-    h = 64,
+    width = 96,
+    height = 64,
     z = 64
   },
   {
     kind = 'wall',
     x = (1600 / 2) - 32,
     y = (1200 / 2) + 32,
-    w = 64,
-    h = 96,
+    width = 64,
+    height = 96,
     z = 64
   },
   {
     kind = 'wall',
     x = (1600 / 2) + 32,
     y = (1200 / 2) - 32,
-    w = 96,
-    h = 64,
+    width = 96,
+    height = 64,
     z = 64
   },
   {
     kind = 'wall',
     x = (1600 * .25) - 96,
     y = (1200 * .75) - 96,
-    w = 192,
-    h = 192,
+    width = 192,
+    height = 192,
     z = 64
   },
   {
     kind = 'wall',
     x = (1600 * .75) - 96,
     y = (1200 * .25) - 96,
-    w = 192,
-    h = 192,
+    width = 192,
+    height = 192,
     z = 64
   },
   {
     kind = 'wall',
     x = (1600 * .5) - 128,
     y =  256,
-    w = 256,
-    h = 64,
+    width = 256,
+    height = 64,
     z = 64
   },
   {
     kind = 'wall',
     x = (1600 * .5) - 128,
     y = 1200 - (256 + 64),
-    w = 256,
-    h = 64,
+    width = 256,
+    height = 64,
     z = 64
   },
   {
     kind = 'tree',
     x = 1600 * .5,
-    y = 1200 * .5
+    y = 1200 * .5,
+		radius = 10
   }
-}
+}