| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- local Wall = {}
- Wall.name = 'Wall'
- Wall.code = 'wall'
- Wall.collision = {}
- Wall.collision.shape = 'rectangle'
- Wall.collision.tag = 'wall'
- local function perim(x, y, l, t, w, h)
- local r, b = l + w, t + h
- x, y = math.clamp(x, l, r), math.clamp(y, t, b)
- local dl, dr, dt, db = math.abs(x - l), math.abs(x - r), math.abs(y - t), math.abs(y - b)
- local m = math.min(dl, dr, dt, db)
- if m == dt then return x, t end
- if m == db then return x, b end
- if m == dl then return l, y end
- return r, y
- end
- function Wall:activate(map)
- if not Wall.texture then
- local x, y, w, h = map.textures.wall:getViewport()
- Wall.texture = love.graphics.newCanvas(w, h)
- Wall.texture:renderTo(function()
- love.graphics.setColor(255, 255, 255)
- love.graphics.draw(map.atlas, map.textures.wall)
- end)
- Wall.texture:setWrap('repeat', 'repeat')
- end
- ctx.event:emit('collision.attach', {object = self})
- self.top = love.graphics.newMesh({
- {0, 0, 0, 0},
- {0, 0, 1, 0},
- {0, 0, 1, 1},
- {0, 0, 0, 1}
- }, self.texture)
- self.north = love.graphics.newMesh({
- {self.x, self.y, 0, 0, 0, 0, 0},
- {self.x + self.width, self.y, 1, 0, 0, 0, 0},
- {0, 0, 1, 1},
- {0, 0, 0, 1}
- }, self.texture)
- self.south = love.graphics.newMesh({
- {0, 0, 0, 0},
- {0, 0, 1, 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}
- }, self.texture)
- self.east = love.graphics.newMesh({
- {0, 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}
- }, self.texture)
- self.west = love.graphics.newMesh({
- {self.x, self.y, 0, 0, 0, 0, 0},
- {0, 0, 1, 0},
- {0, 0, 1, 1},
- {self.x, self.y + self.height, 0, 1, 0, 0, 0}
- }, self.texture)
- self.meshX = self.x
- self.meshY = self.y
- self.depth = -5
- if ctx.view then ctx.view:register(self) end
- end
- function Wall:deactivate()
- ctx.event:emit('collision.detach', {object = self})
- if ctx.view then ctx.view:unregister(self) end
- end
- function Wall:update()
- if ctx.view then
- if not self:inView() then return end
- local x1, y1 = ctx.view.x + ctx.view.width / 2, ctx.view.y + ctx.view.height / 2
- local x2, y2 = perim(x1, y1, self.x, self.y, self.width, self.height)
- self.depth = math.clamp(math.distance(x1, y1, x2, y2) * ctx.view.scale - 1000 - self.z, -4096, -16)
- end
- if self.meshX ~= self.x or self.meshY ~= y then
- self:updateMesh()
- end
- end
- function Wall:draw()
- if not self:inView() then return end
- local v = ctx.view
- local ulx, uly = v:three(self.x, self.y, 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)
- local w, h = self.width / self.texture:getWidth(), self.height / self.texture:getHeight()
- self.top:setVertex(1, ulx, uly, 0, 0)
- self.top:setVertex(2, urx, ury, w, 0)
- self.top:setVertex(3, lrx, lry, w, h)
- self.top:setVertex(4, llx, lly, 0, h)
- love.graphics.setColor(255, 255, 255)
- local y2 = ctx.view.y + (ctx.view.height / 2)
- if self.y > y2 then
- self.north:setVertex(3, urx, ury, w, h)
- self.north:setVertex(4, ulx, uly, 0, h)
- love.graphics.draw(self.north, 0, 0)
- end
- if self.y + self.height < y2 then
- self.south:setVertex(1, llx, lly, 0, 0)
- self.south:setVertex(2, lrx, lry, w, 0)
- love.graphics.draw(self.south, 0, 0)
- end
- local x2 = ctx.view.x + (ctx.view.width / 2)
- if self.x > x2 then
- self.west:setVertex(2, ulx, uly, w, 0)
- self.west:setVertex(3, llx, lly, w, h)
- love.graphics.draw(self.west, 0, 0)
- end
- if self.x + self.width < x2 then
- self.east:setVertex(1, urx, ury, 0, 0)
- self.east:setVertex(4, lrx, lry, 0, h)
- love.graphics.draw(self.east, 0, 0)
- end
- love.graphics.draw(self.top, 0, 0)
- end
- function Wall:inView()
- local x, y, w, h = self.x, self.y, self.width, self.height
- local v = ctx.view
- return x + w >= v.x and x <= v.x + v.width and y + h >= v.y and y <= v.y + v.height
- end
- function Wall:updateMesh()
- local w, h = self.width / self.texture:getWidth(), self.height / self.texture:getHeight()
- self.north:setVertex(1, self.x, self.y, 0, 0, 0, 0, 0)
- self.north:setVertex(2, self.x + self.width, self.y, w, 0, 0, 0, 0)
- self.south:setVertex(3, self.x + self.width, self.y + self.height, w, h, 0, 0, 0)
- self.south:setVertex(4, self.x, self.y + self.height, 0, h, 0, 0, 0)
- self.east:setVertex(2, self.x + self.width, self.y, w, 0, 0, 0, 0)
- self.east:setVertex(3, self.x + self.width, self.y + self.height, w, h, 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.height, 0, h, 0, 0, 0)
- self.meshX = self.x
- self.meshY = self.y
- end
- function Wall:__tostring()
- return [[{
- kind = 'wall',
- x = ]] .. self.x .. [[,
- y = ]] .. self.y .. [[,
- w = ]] .. self.width .. [[,
- h = ]] .. self.height .. [[,
- z = ]] .. self.z .. [[
- }]]
- end
- return Wall
|