Compare commits
7 Commits
bglap
...
coordinate
| Author | SHA1 | Date | |
|---|---|---|---|
| 17a07bc95a | |||
| e46316cff8 | |||
| 0aeb0139d3 | |||
| 391e2ab1b7 | |||
| 3af5bbe928 | |||
| e0ac6abaef | |||
| 56ffd396bc |
@@ -4,12 +4,10 @@ Lua game inspired by an old arcade game(Qix/Gals Panic) using LOVE2D for Linux.
|
||||
|
||||
## TO-DO
|
||||
|
||||
- Stop player from creating crossed lines
|
||||
|
||||
- Fix creation of the lines / polygon / points
|
||||
|
||||
- Add more pictures (manga?)
|
||||
|
||||
- Fix Mesh
|
||||
|
||||
- Fix balls sometimes attaching to the lines
|
||||
|
||||
- Add spiders moving around in the board, player collision kills
|
||||
|
||||
10
main.lua
10
main.lua
@@ -37,6 +37,7 @@ if os.getenv("LOCAL_LUA_DEBUGGER_VSCODE") == "1" then
|
||||
function love.load()
|
||||
love.window.setTitle('SpiderCut')
|
||||
love.graphics.setDefaultFilter('nearest', 'nearest')
|
||||
love.graphics.setLineJoin( "bevel" )
|
||||
math.randomseed(os.time())
|
||||
|
||||
push:setupScreen(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, WINDOW_WIDTH, WINDOW_HEIGHT, {
|
||||
@@ -60,6 +61,15 @@ function love.keypressed(key)
|
||||
love.event.quit()
|
||||
end
|
||||
|
||||
if key == 'f' then
|
||||
push:switchFullscreen()
|
||||
end
|
||||
|
||||
if key == 'r' then
|
||||
gStateStack:clear()
|
||||
gStateStack:push(StartState())
|
||||
end
|
||||
|
||||
love.keyboard.keysPressed[key] = true
|
||||
end
|
||||
|
||||
|
||||
12
src/Ball.lua
12
src/Ball.lua
@@ -22,13 +22,15 @@ function Ball:reset()
|
||||
end
|
||||
|
||||
function Ball:update(dt,level)
|
||||
local tempX = self.x + self.dx * dt
|
||||
local tempY = self.y + self.dy * dt
|
||||
local tempX = math.floor((self.x + self.dx * dt) + 0.5)
|
||||
local tempY = math.floor((self.y + self.dy * dt) + 0.5)
|
||||
|
||||
local trailSeg = level:pointOnEdge(tempX,tempY,level.player.trailSegments)
|
||||
if trailSeg then
|
||||
self.hitPlayer = true
|
||||
-- print("ball hits player")
|
||||
gSounds['hit']:play()
|
||||
return
|
||||
end
|
||||
|
||||
local i, segment = level:getTouchingSegment(tempX,tempY)
|
||||
@@ -49,8 +51,9 @@ function Ball:update(dt,level)
|
||||
gSounds['blip']:play()
|
||||
end
|
||||
|
||||
if not (level:insideBounds(tempX,tempY) or level:pointOnEdge(tempX,tempY)) then
|
||||
if not level:insideBounds(tempX,tempY) and not level:pointOnEdge(tempX,tempY) then
|
||||
self.remove = true
|
||||
print("ball outside or touching segment")
|
||||
end
|
||||
|
||||
self.x = self.x + self.dx * dt
|
||||
@@ -60,8 +63,9 @@ function Ball:update(dt,level)
|
||||
end
|
||||
|
||||
function Ball:render()
|
||||
love.graphics.setColor(255/255,1/255,1/255,255/255)
|
||||
love.graphics.setColor(1,0.1,0.1,1)
|
||||
love.graphics.circle('fill', self.x, self.y, self.width/2)
|
||||
love.graphics.setColor(1,1,1,1)
|
||||
end
|
||||
|
||||
function Ball:getCollisionDirection(segment,x,y)
|
||||
|
||||
36
src/Clock.lua
Normal file
36
src/Clock.lua
Normal file
@@ -0,0 +1,36 @@
|
||||
Clock = Class {}
|
||||
|
||||
function Clock:init(timelimit, direction)
|
||||
self.timeLimit = timelimit
|
||||
self.direction = direction
|
||||
self.color = {56 / 255, 56 / 255, 56 / 255, 1}
|
||||
self.currentTime = "0"
|
||||
self.timer = 0
|
||||
self.startTime = self:getOsTime()
|
||||
end
|
||||
|
||||
function Clock:update(dt)
|
||||
local passed = math.floor((self:getOsTime() - self.startTime) * 10 + 0.5)
|
||||
if self.direction == 'down' then
|
||||
self.currentTime = tostring(self.timeLimit - passed)
|
||||
else
|
||||
self.currentTime = tostring(passed)
|
||||
end
|
||||
end
|
||||
|
||||
function Clock:render()
|
||||
if self.currentTime * 1 <= 10 then
|
||||
local a = math.abs(math.cos(love.timer.getTime() * .85 % 2 * math.pi))
|
||||
love.graphics.setColor(.8, .12, .12, a)
|
||||
else
|
||||
love.graphics.setColor(self.color[1], self.color[2], self.color[3],
|
||||
self.color[4])
|
||||
end
|
||||
love.graphics.setFont(gFonts['small'])
|
||||
love.graphics.printf('Time: ' .. self.currentTime, 0, LEVEL_RENDER_OFFSET_TOP/2, VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET,
|
||||
'right')
|
||||
love.graphics.setFont(gFonts['small'])
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
function Clock:getOsTime() return os.clock() end
|
||||
@@ -10,6 +10,7 @@ Timer = require 'lib/knife.timer'
|
||||
require 'src/Animation'
|
||||
require 'src/constants'
|
||||
require 'src/StateMachine'
|
||||
require 'src/Clock'
|
||||
require 'src/Util'
|
||||
|
||||
require 'src/Level'
|
||||
|
||||
469
src/Level.lua
469
src/Level.lua
@@ -1,61 +1,96 @@
|
||||
-- require('mobdebug').start()
|
||||
Level = Class {}
|
||||
|
||||
function Level:init(stage)
|
||||
function Level:init(def, stage)
|
||||
self.stage = stage
|
||||
self.points = {}
|
||||
self.player = {}
|
||||
self.segments = self:createLevel()
|
||||
self.segments = self:createLevelFromDef(def)
|
||||
self.polygon = self:createPolygon()
|
||||
self.mesh = poly2mesh(self.points)
|
||||
|
||||
self.balls = self:createBallsFromDef(def)
|
||||
self.clock = Clock(def.timeLimit, "down")
|
||||
end
|
||||
|
||||
function Level:update(dt)
|
||||
-- print_r(self.points)
|
||||
-- print(tostring(#self.points))
|
||||
-- if self.mesh == nil and #self.points > 2 then
|
||||
-- self.mesh = poly2mesh(self.points)
|
||||
-- end
|
||||
self.mesh = poly2mesh(self.points)
|
||||
-- print_r(self.mesh:getVertices())
|
||||
self:updateBalls(dt)
|
||||
self.clock:update(dt)
|
||||
end
|
||||
|
||||
function Level:render()
|
||||
self:renderBackground()
|
||||
self:renderOuterSegments()
|
||||
self:renderBalls()
|
||||
self.clock:render()
|
||||
end
|
||||
|
||||
function Level:renderOuterSegments()
|
||||
for k, segment in pairs(self.segments) do segment:render() end
|
||||
for k, segment in pairs(self.segments) do
|
||||
segment:render()
|
||||
end
|
||||
end
|
||||
|
||||
function Level:renderBackground()
|
||||
love.graphics.draw(gImages[(self.stage % #gImages)], LEVEL_RENDER_OFFSET,
|
||||
LEVEL_RENDER_OFFSET_TOP)
|
||||
local nextImg = self.stage % (#gImages + 1)
|
||||
if nextImg == 0 then
|
||||
nextImg = 1
|
||||
end
|
||||
love.graphics.draw(gImages[nextImg], LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP)
|
||||
if self.mesh:type() == "Mesh" then
|
||||
love.graphics.draw(self.mesh, 0, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function Level:createLevelFromDef(def)
|
||||
local level = {}
|
||||
for i, seg in pairs(def.segments) do
|
||||
table.insert(level, Segment(seg.p1, seg.p2, seg.width, seg.face))
|
||||
end
|
||||
return level
|
||||
end
|
||||
|
||||
function Level:createLevel()
|
||||
local level = {
|
||||
[1] = Segment({LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP}, {
|
||||
VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP
|
||||
}, .5, 'down'),
|
||||
[2] = Segment({
|
||||
VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP
|
||||
}, {
|
||||
VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET,
|
||||
VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET
|
||||
}, .5, 'left'),
|
||||
[3] = Segment({
|
||||
VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET,
|
||||
VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET
|
||||
}, {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET}, .5, 'up'),
|
||||
[4] = Segment({
|
||||
LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET
|
||||
}, {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP}, .5, 'right')
|
||||
[1] = Segment(
|
||||
{LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
{
|
||||
VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET,
|
||||
LEVEL_RENDER_OFFSET_TOP
|
||||
},
|
||||
.5,
|
||||
"down"
|
||||
),
|
||||
[2] = Segment(
|
||||
{
|
||||
VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET,
|
||||
LEVEL_RENDER_OFFSET_TOP
|
||||
},
|
||||
{
|
||||
VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET,
|
||||
VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET
|
||||
},
|
||||
.5,
|
||||
"left"
|
||||
),
|
||||
[3] = Segment(
|
||||
{
|
||||
VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET,
|
||||
VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET
|
||||
},
|
||||
{LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
.5,
|
||||
"up"
|
||||
),
|
||||
[4] = Segment(
|
||||
{
|
||||
LEVEL_RENDER_OFFSET,
|
||||
VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET
|
||||
},
|
||||
{LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
.5,
|
||||
"right"
|
||||
)
|
||||
}
|
||||
-- local level = {
|
||||
-- [1] = Segment({LEVEL_RENDER_OFFSET,LEVEL_RENDER_OFFSET_TOP},{VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},.5),
|
||||
@@ -73,8 +108,10 @@ function Level:insideBounds2(x, y)
|
||||
return shape:testPoint(x, y)
|
||||
end
|
||||
|
||||
function Level:insideBounds(x, y, segments)
|
||||
if not segments then segments = self.segments end
|
||||
function Level:insideBounds4(x, y, segments)
|
||||
if not segments then
|
||||
segments = self.segments
|
||||
end
|
||||
|
||||
local up, down, left, right = false
|
||||
local upSeg, downSeg, leftSeg, rightSeg = nil
|
||||
@@ -83,40 +120,40 @@ function Level:insideBounds(x, y, segments)
|
||||
for i, segment in pairs(segments) do
|
||||
-- check raycast on y axis
|
||||
if segment.vertical then
|
||||
if y <= math.max(segment.firstPointY, segment.secondPointY) and y >=
|
||||
math.min(segment.firstPointY, segment.secondPointY) then
|
||||
if
|
||||
y <= math.max(segment.firstPointY, segment.secondPointY) and
|
||||
y >= math.min(segment.firstPointY, segment.secondPointY)
|
||||
then
|
||||
if x <= segment.firstPointX then
|
||||
if not rightSeg then
|
||||
rightSeg = segment
|
||||
elseif math.abs(segment.firstPointX - x) <
|
||||
math.abs(rightSeg.firstPointX - x) then
|
||||
elseif math.abs(segment.firstPointX - x) < math.abs(rightSeg.firstPointX - x) then
|
||||
rightSeg = segment
|
||||
end
|
||||
else
|
||||
if not leftSeg then
|
||||
leftSeg = segment
|
||||
elseif math.abs(segment.firstPointX - x) <
|
||||
math.abs(leftSeg.firstPointX - x) then
|
||||
elseif math.abs(segment.firstPointX - x) < math.abs(leftSeg.firstPointX - x) then
|
||||
leftSeg = segment
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if segment.horizontal then
|
||||
if x <= math.max(segment.firstPointX, segment.secondPointX) and x >=
|
||||
math.min(segment.firstPointX, segment.secondPointX) then
|
||||
if
|
||||
x <= math.max(segment.firstPointX, segment.secondPointX) and
|
||||
x >= math.min(segment.firstPointX, segment.secondPointX)
|
||||
then
|
||||
if y <= segment.firstPointY then
|
||||
if not downSeg then
|
||||
downSeg = segment
|
||||
elseif math.abs(segment.firstPointY - y) <
|
||||
math.abs(downSeg.firstPointY - y) then
|
||||
elseif math.abs(segment.firstPointY - y) < math.abs(downSeg.firstPointY - y) then
|
||||
downSeg = segment
|
||||
end
|
||||
else
|
||||
if not upSeg then
|
||||
upSeg = segment
|
||||
elseif math.abs(segment.firstPointY - y) <
|
||||
math.abs(upSeg.firstPointY - y) then
|
||||
elseif math.abs(segment.firstPointY - y) < math.abs(upSeg.firstPointY - y) then
|
||||
upSeg = segment
|
||||
end
|
||||
end
|
||||
@@ -124,11 +161,15 @@ function Level:insideBounds(x, y, segments)
|
||||
end
|
||||
end
|
||||
if not rightSeg or not leftSeg or not upSeg or not downSeg then
|
||||
print("ball outside - seg check")
|
||||
return false
|
||||
end
|
||||
|
||||
if rightSeg.face ~= "left" or leftSeg.face ~= "right" or upSeg.face ~= "down" or downSeg.face ~= "up" then
|
||||
print("ball outside - face check")
|
||||
return false
|
||||
end
|
||||
|
||||
if rightSeg.face ~= 'left' or leftSeg.face ~= 'right' or upSeg.face ~=
|
||||
'down' or downSeg.face ~= 'up' then return false end
|
||||
return true
|
||||
end
|
||||
|
||||
@@ -139,18 +180,51 @@ function Level:insideBounds3(x, y)
|
||||
local j = #self.polygon
|
||||
local polygon = self.polygon
|
||||
for i = 1, #polygon do
|
||||
if (polygon[i].y < y and polygon[j].y >= y or polygon[j].y < y and
|
||||
polygon[i].y >= y) then
|
||||
if (polygon[i].x + (y - polygon[i].y) /
|
||||
(polygon[j].y - polygon[i].y) * (polygon[j].x - polygon[i].x) <
|
||||
x) then oddNodes = not oddNodes end
|
||||
if (polygon[i].y < y and polygon[j].y >= y or polygon[j].y < y and polygon[i].y >= y) then
|
||||
if (polygon[i].x + (y - polygon[i].y) / (polygon[j].y - polygon[i].y) * (polygon[j].x - polygon[i].x) < x) then
|
||||
oddNodes = not oddNodes
|
||||
end
|
||||
end
|
||||
j = i
|
||||
end
|
||||
return oddNodes
|
||||
end
|
||||
|
||||
function Level:insideBounds(x, y, segments)
|
||||
if not segments then
|
||||
segments = self.segments
|
||||
end
|
||||
-- prepare shape
|
||||
local polygon = self:getPolygonFromSegments(segments)
|
||||
|
||||
return PointWithinShape(polygon, x, y)
|
||||
end
|
||||
|
||||
function Level:getPolygonFromSegments(segments)
|
||||
local polygon = {}
|
||||
local polygonPoints = {}
|
||||
local pointlist = {}
|
||||
local j = 1
|
||||
for i, segment in ipairs(segments) do
|
||||
polygon[i] = {}
|
||||
polygon[i + 1] = {}
|
||||
polygon[i].x, polygon[i].y, polygon[i + 1].x, polygon[i + 1].y = segment:segmentToPoints()
|
||||
polygonPoints[j] = polygon[i].x
|
||||
polygonPoints[j + 1] = polygon[i].y
|
||||
polygonPoints[j + 2] = polygon[i + 1].x
|
||||
polygonPoints[j + 3] = polygon[i + 1].y
|
||||
|
||||
j = j + 4
|
||||
i = i + 1
|
||||
end
|
||||
return polygon
|
||||
end
|
||||
|
||||
function Level:createPolygon()
|
||||
if #self.segments > 5 then
|
||||
print("Level:createPolygon")
|
||||
print_r(self.segments)
|
||||
end
|
||||
local polygon = {}
|
||||
local polygonPoints = {}
|
||||
local pointlist = {}
|
||||
@@ -158,16 +232,16 @@ function Level:createPolygon()
|
||||
for i, segment in ipairs(self.segments) do
|
||||
polygon[i] = {}
|
||||
polygon[i + 1] = {}
|
||||
polygon[i].x, polygon[i].y, polygon[i + 1].x, polygon[i + 1].y =
|
||||
segment:segmentToPoints()
|
||||
polygon[i].x, polygon[i].y, polygon[i + 1].x, polygon[i + 1].y = segment:segmentToPoints()
|
||||
polygonPoints[j] = polygon[i].x
|
||||
polygonPoints[j + 1] = polygon[i].y
|
||||
polygonPoints[j + 2] = polygon[i + 1].x
|
||||
polygonPoints[j + 3] = polygon[i + 1].y
|
||||
|
||||
table.insert(pointlist, polygon[i].x)
|
||||
table.insert(pointlist, polygon[i].y)
|
||||
|
||||
if polygon[i + 1].x ~= polygon[i].x or polygon[i + 1].y ~= polygon[i].y then
|
||||
table.insert(pointlist, polygon[i].x)
|
||||
table.insert(pointlist, polygon[i].y)
|
||||
end
|
||||
j = j + 4
|
||||
i = i + 1
|
||||
end
|
||||
@@ -177,25 +251,30 @@ function Level:createPolygon()
|
||||
end
|
||||
|
||||
function Level:pointOnEdge(x, y, segments)
|
||||
if not segments then segments = self.segments end
|
||||
if not segments then
|
||||
segments = self.segments
|
||||
end
|
||||
local margin = 2
|
||||
for i, segment in pairs(segments) do
|
||||
if segment.vertical then -- vertical line
|
||||
if x >= segment.firstPointX - margin and x <= segment.firstPointX +
|
||||
margin and y <=
|
||||
math.max(segment.firstPointY, segment.secondPointY) and y >=
|
||||
math.min(segment.firstPointY, segment.secondPointY) then
|
||||
if
|
||||
x >= segment.firstPointX - margin and x <= segment.firstPointX + margin and
|
||||
y <= math.max(segment.firstPointY, segment.secondPointY) and
|
||||
y >= math.min(segment.firstPointY, segment.secondPointY)
|
||||
then
|
||||
return true
|
||||
end
|
||||
elseif segment.horizontal then -- horizontal line
|
||||
if y >= segment.firstPointY - margin and y <= segment.firstPointY +
|
||||
margin and x <=
|
||||
math.max(segment.firstPointX, segment.secondPointX) and x >=
|
||||
math.min(segment.firstPointX, segment.secondPointX) then
|
||||
if
|
||||
y >= segment.firstPointY - margin and y <= segment.firstPointY + margin and
|
||||
x <= math.max(segment.firstPointX, segment.secondPointX) and
|
||||
x >= math.min(segment.firstPointX, segment.secondPointX)
|
||||
then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
-- print("ball pointOnEdge is false")
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -203,17 +282,19 @@ function Level:getTouchingSegment(x, y)
|
||||
local margin = 2
|
||||
for i, segment in pairs(self.segments) do
|
||||
if segment.vertical then -- vertical line
|
||||
if x >= segment.firstPointX - margin and x <= segment.firstPointX +
|
||||
margin and y <=
|
||||
math.max(segment.firstPointY, segment.secondPointY) and y >=
|
||||
math.min(segment.firstPointY, segment.secondPointY) then
|
||||
if
|
||||
x >= segment.firstPointX - margin and x <= segment.firstPointX + margin and
|
||||
y <= math.max(segment.firstPointY, segment.secondPointY) and
|
||||
y >= math.min(segment.firstPointY, segment.secondPointY)
|
||||
then
|
||||
return i, segment
|
||||
end
|
||||
elseif segment.horizontal then -- horizontal line
|
||||
if y >= segment.firstPointY - margin and y <= segment.firstPointY +
|
||||
margin and x <=
|
||||
math.max(segment.firstPointX, segment.secondPointX) and x >=
|
||||
math.min(segment.firstPointX, segment.secondPointX) then
|
||||
if
|
||||
y >= segment.firstPointY - margin and y <= segment.firstPointY + margin and
|
||||
x <= math.max(segment.firstPointX, segment.secondPointX) and
|
||||
x >= math.min(segment.firstPointX, segment.secondPointX)
|
||||
then
|
||||
return i, segment
|
||||
end
|
||||
end
|
||||
@@ -222,15 +303,12 @@ function Level:getTouchingSegment(x, y)
|
||||
end
|
||||
|
||||
function Level:cutLevel()
|
||||
|
||||
local newSegs = self.player.trailSegments
|
||||
local startSegi, startSeg = self.player.trailStartSegment[1],
|
||||
self.player.trailStartSegment[2]
|
||||
local endSegi, endSeg = self.player.trailFinishSegment[1],
|
||||
self.player.trailFinishSegment[2]
|
||||
local startSegi, startSeg = self.player.trailStartSegment[1], self.player.trailStartSegment[2]
|
||||
local endSegi, endSeg = self.player.trailFinishSegment[1], self.player.trailFinishSegment[2]
|
||||
local first = 0
|
||||
local last = 0
|
||||
local firstFace = ''
|
||||
local firstFace = ""
|
||||
|
||||
-- check if it is same start and finish segment
|
||||
if startSegi == endSegi then
|
||||
@@ -258,15 +336,16 @@ function Level:cutLevel()
|
||||
while k <= #self.segments do
|
||||
-- print(" segment to be inserted "..tostring(k))
|
||||
if k == startSegi and not insertedNewSegs then
|
||||
-- print_r(new)
|
||||
-- print("-- finished inserting new segments and parts")
|
||||
-- print("Reached the segment being cut")
|
||||
-- print_r(self.segments[k])
|
||||
-- print("split the segment")
|
||||
part1, temp, part2 = self.segments[k]:splitInThreeWithSegments(
|
||||
newSegs[1], newSegs[#newSegs])
|
||||
part1, temp, part2 = self.segments[k]:splitInThreeWithSegments(newSegs[1], newSegs[#newSegs])
|
||||
-- print("part1")
|
||||
part1:debug()
|
||||
-- part1:debug()
|
||||
-- print("part2")
|
||||
part2:debug()
|
||||
-- part2:debug()
|
||||
|
||||
-- print("insert first part")
|
||||
new[j] = part1
|
||||
@@ -284,8 +363,6 @@ function Level:cutLevel()
|
||||
insertedNewSegments = true
|
||||
new[j] = part2
|
||||
j = j + 1
|
||||
-- print_r(new)
|
||||
-- print("-- finished inserting new segments and parts")
|
||||
else
|
||||
new[j] = self.segments[k]:copy()
|
||||
j = j + 1
|
||||
@@ -323,14 +400,15 @@ function Level:cutLevel()
|
||||
newSegs[1]:joinPerpendicular(self.segments[k])
|
||||
newSegs[1]:debug()
|
||||
-- print("newSegs[1] is joined -- finished")
|
||||
local startPart1, startPart2 =
|
||||
self.segments[k]:splitInTwoWithSegment(newSegs[1])
|
||||
local startPart1, startPart2 = self.segments[k]:splitInTwoWithSegment(newSegs[1])
|
||||
-- print("-- Segment k split into 2 segments by newsegs[1]: ")
|
||||
startPart1:debug()
|
||||
startPart2:debug()
|
||||
|
||||
if self.segments[last]:endEqualsStartOf(self.segments[k]) or
|
||||
self.segments[last]:startEqualsStartOf(self.segments[k]) then -- last one is linked to the start of this one
|
||||
if
|
||||
self.segments[last]:endEqualsStartOf(self.segments[k]) or
|
||||
self.segments[last]:startEqualsStartOf(self.segments[k])
|
||||
then -- last one is linked to the start of this one
|
||||
-- keep first part of segment
|
||||
-- print("-- keep first part of the k segment")
|
||||
self.segments[k] = startPart1
|
||||
@@ -359,18 +437,19 @@ function Level:cutLevel()
|
||||
end
|
||||
-- print_r(board1)
|
||||
|
||||
local endPart1, endPart2 =
|
||||
self.segments[k]:splitInTwoWithSegment(newSegs[#newSegs])
|
||||
local endPart1, endPart2 = self.segments[k]:splitInTwoWithSegment(newSegs[#newSegs])
|
||||
-- print("-- proceed to insert the second split segment")
|
||||
if self.segments[last]:endEqualsEndOf(self.segments[k]) or
|
||||
self.segments[last]:startEqualsEndOf(self.segments[k]) then -- next one is linked to the start of this one
|
||||
if
|
||||
self.segments[last]:endEqualsEndOf(self.segments[k]) or
|
||||
self.segments[last]:startEqualsEndOf(self.segments[k])
|
||||
then -- next one is linked to the start of this one
|
||||
-- print("-- keep first part of the k segment")
|
||||
self.segments[k] = endPart1
|
||||
savedEnd = endPart2
|
||||
-- print("-- keep first part of the k segment")
|
||||
else
|
||||
-- print("-- keep second part of the k segment")
|
||||
self.segments[k] = endPart2
|
||||
savedEnd = endPart1
|
||||
-- print("-- keep second part of the k segment")
|
||||
end
|
||||
|
||||
board1[j] = self.segments[k]:copy()
|
||||
@@ -386,14 +465,15 @@ function Level:cutLevel()
|
||||
newSegs[#newSegs]:joinPerpendicular(self.segments[k])
|
||||
newSegs[#newSegs]:debug()
|
||||
-- print("newSegs[#newSegs] is joined -- finished")
|
||||
local endPart1, endPart2 =
|
||||
self.segments[k]:splitInTwoWithSegment(newSegs[#newSegs])
|
||||
local endPart1, endPart2 = self.segments[k]:splitInTwoWithSegment(newSegs[#newSegs])
|
||||
-- print("-- Segment k split into 2 segments by newsegs[#newSegs]: ")
|
||||
endPart1:debug()
|
||||
endPart2:debug()
|
||||
|
||||
if self.segments[last]:endEqualsStartOf(self.segments[k]) or
|
||||
self.segments[last]:startEqualsStartOf(self.segments[k]) then -- last one is linked to the start of this one
|
||||
if
|
||||
self.segments[last]:endEqualsStartOf(self.segments[k]) or
|
||||
self.segments[last]:startEqualsStartOf(self.segments[k])
|
||||
then -- last one is linked to the start of this one
|
||||
-- keep first part of segment
|
||||
self.segments[k] = endPart1
|
||||
savedEnd = endPart2
|
||||
@@ -421,14 +501,15 @@ function Level:cutLevel()
|
||||
end
|
||||
-- print_r(board1)
|
||||
|
||||
local startPart1, startPart2 =
|
||||
self.segments[k]:splitInTwoWithSegment(newSegs[1])
|
||||
local startPart1, startPart2 = self.segments[k]:splitInTwoWithSegment(newSegs[1])
|
||||
-- print("-- Segment k split into 2 segments by newsegs[1]: ")
|
||||
startPart1:debug()
|
||||
startPart2:debug()
|
||||
|
||||
if self.segments[last]:endEqualsEndOf(self.segments[k]) or
|
||||
self.segments[last]:startEqualsEndOf(self.segments[k]) then -- next one is linked to the start of this one
|
||||
if
|
||||
self.segments[last]:endEqualsEndOf(self.segments[k]) or
|
||||
self.segments[last]:startEqualsEndOf(self.segments[k])
|
||||
then -- next one is linked to the start of this one
|
||||
self.segments[k] = startPart1
|
||||
savedstart = startPart2
|
||||
else
|
||||
@@ -441,7 +522,6 @@ function Level:cutLevel()
|
||||
-- print_r(board1)
|
||||
insertedNewSegments = true
|
||||
end
|
||||
|
||||
elseif k ~= startSegi and k ~= endSegi then
|
||||
board1[j] = self.segments[k]:copy()
|
||||
j = j + 1
|
||||
@@ -460,6 +540,7 @@ function Level:cutLevel()
|
||||
-- print('---- Create Second board from '..tostring(board2StartSegi)..' to '..tostring(board2EndSegi))
|
||||
j = 1
|
||||
if board2StartSegi < board2EndSegi then
|
||||
-- print_r(board2)
|
||||
board2[j] = savedStart
|
||||
j = j + 1
|
||||
-- print_r(board2)
|
||||
@@ -484,9 +565,9 @@ function Level:cutLevel()
|
||||
board2[j] = newseg:copy()
|
||||
j = j + 1
|
||||
end
|
||||
-- print_r(board2)
|
||||
|
||||
else
|
||||
-- print('-- inserted new segments, final board2 before ordering')
|
||||
-- print_r(board2)
|
||||
-- print('-- inserted first segment, proceed with skipped segments in first board, end < start')
|
||||
board2[j] = savedEnd
|
||||
j = j + 1
|
||||
@@ -514,8 +595,6 @@ function Level:cutLevel()
|
||||
j = j + 1
|
||||
i = i - 1
|
||||
end
|
||||
-- print('-- inserted new segments, final board2 before ordering')
|
||||
-- print_r(board2)
|
||||
end
|
||||
|
||||
-- print("order segments in cutlevel board2")
|
||||
@@ -524,17 +603,16 @@ function Level:cutLevel()
|
||||
-- print("PREPARE BOARD 2 -- FINAL")
|
||||
-- print_r(board2)
|
||||
|
||||
if self:containsBalls(board1) == 0 then
|
||||
self.segments = board2
|
||||
elseif self:containsBalls(board2) == 0 then
|
||||
local b1balls = self:containsBalls(board1)
|
||||
local b2balls = self:containsBalls(board2)
|
||||
if b1balls > b2balls then
|
||||
self.segments = board1
|
||||
else
|
||||
self.segments = self:getPerimeter(board1) >
|
||||
self:getPerimeter(board2) and board1 or board2
|
||||
self.segments = board2
|
||||
end
|
||||
end
|
||||
|
||||
self:createPolygon()
|
||||
self.polygon = self:createPolygon()
|
||||
self.mesh = poly2mesh(self.points)
|
||||
end
|
||||
|
||||
@@ -562,8 +640,7 @@ function Level:orderSegments(segs)
|
||||
|
||||
-- -- print("new[i] end equals start of ")
|
||||
-- s:debug()
|
||||
if new[i].vertical == s.vertical and new[i].horizontal ==
|
||||
s.horizontal then
|
||||
if new[i].vertical == s.vertical and new[i].horizontal == s.horizontal then
|
||||
-- -- print("join contiguous "..tostring(i).. 'with'..tostring(j))
|
||||
new[i]:joinContiguous(s)
|
||||
table.remove(segs, j)
|
||||
@@ -583,8 +660,7 @@ function Level:orderSegments(segs)
|
||||
-- -- print("new[i] end equals end of ")
|
||||
-- s:debug()
|
||||
s:switchDirection()
|
||||
if new[i].vertical == s.vertical and new[i].horizontal ==
|
||||
s.horizontal then
|
||||
if new[i].vertical == s.vertical and new[i].horizontal == s.horizontal then
|
||||
-- -- print("join contiguous "..tostring(i).. 'with'..tostring(j))
|
||||
new[i]:joinContiguous(s)
|
||||
table.remove(segs, j)
|
||||
@@ -607,14 +683,10 @@ function Level:orderSegments(segs)
|
||||
-- -- print("search didnt yield any segment")
|
||||
local margin = 2
|
||||
while not found and margin < 5 do
|
||||
fi, fs = self:findNearestSegment(new[i].secondPointX,
|
||||
new[i].secondPointY, segs,
|
||||
margin)
|
||||
fi, fs = self:findNearestSegment(new[i].secondPointX, new[i].secondPointY, segs, margin)
|
||||
|
||||
if not fs then
|
||||
fi, fs = self:findNearestSegment(new[i].firstPointX,
|
||||
new[i].firstPointY, segs,
|
||||
margin)
|
||||
fi, fs = self:findNearestSegment(new[i].firstPointX, new[i].firstPointY, segs, margin)
|
||||
|
||||
if not fs then
|
||||
margin = margin + 1
|
||||
@@ -661,60 +733,60 @@ function Level:calculateSegmentFaces(segments, firstFace)
|
||||
for k, s in ipairs(segments) do
|
||||
s.face = face
|
||||
if k + 1 <= #segments then
|
||||
if face == 'up' then
|
||||
if s.direction == 'right' then
|
||||
if segments[k + 1].direction == 'up' then
|
||||
face = 'left'
|
||||
if face == "up" then
|
||||
if s.direction == "right" then
|
||||
if segments[k + 1].direction == "up" then
|
||||
face = "left"
|
||||
else
|
||||
face = 'right'
|
||||
face = "right"
|
||||
end
|
||||
else
|
||||
if segments[k + 1].direction == 'up' then
|
||||
face = 'right'
|
||||
if segments[k + 1].direction == "up" then
|
||||
face = "right"
|
||||
else
|
||||
face = 'left'
|
||||
face = "left"
|
||||
end
|
||||
end
|
||||
elseif face == 'down' then
|
||||
if s.direction == 'right' then
|
||||
if segments[k + 1].direction == 'up' then
|
||||
face = 'right'
|
||||
elseif face == "down" then
|
||||
if s.direction == "right" then
|
||||
if segments[k + 1].direction == "up" then
|
||||
face = "right"
|
||||
else
|
||||
face = 'left'
|
||||
face = "left"
|
||||
end
|
||||
else
|
||||
if segments[k + 1].direction == 'up' then
|
||||
face = 'left'
|
||||
if segments[k + 1].direction == "up" then
|
||||
face = "left"
|
||||
else
|
||||
face = 'right'
|
||||
face = "right"
|
||||
end
|
||||
end
|
||||
elseif face == 'right' then
|
||||
if s.direction == 'up' then
|
||||
if segments[k + 1].direction == 'right' then
|
||||
face = 'down'
|
||||
elseif face == "right" then
|
||||
if s.direction == "up" then
|
||||
if segments[k + 1].direction == "right" then
|
||||
face = "down"
|
||||
else
|
||||
face = 'up'
|
||||
face = "up"
|
||||
end
|
||||
else
|
||||
if segments[k + 1].direction == 'right' then
|
||||
face = 'up'
|
||||
if segments[k + 1].direction == "right" then
|
||||
face = "up"
|
||||
else
|
||||
face = 'down'
|
||||
face = "down"
|
||||
end
|
||||
end
|
||||
elseif face == 'left' then
|
||||
if s.direction == 'up' then
|
||||
if segments[k + 1].direction == 'right' then
|
||||
face = 'up'
|
||||
elseif face == "left" then
|
||||
if s.direction == "up" then
|
||||
if segments[k + 1].direction == "right" then
|
||||
face = "up"
|
||||
else
|
||||
face = 'down'
|
||||
face = "down"
|
||||
end
|
||||
else
|
||||
if segments[k + 1].direction == 'right' then
|
||||
face = 'down'
|
||||
if segments[k + 1].direction == "right" then
|
||||
face = "down"
|
||||
else
|
||||
face = 'up'
|
||||
face = "up"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -724,28 +796,38 @@ end
|
||||
|
||||
function Level:getPerimeter(segments)
|
||||
local p = 0
|
||||
if not segments then segments = self.segments end
|
||||
for k, s in pairs(segments) do p = p + s:length() end
|
||||
if not segments then
|
||||
segments = self.segments
|
||||
end
|
||||
for k, s in pairs(segments) do
|
||||
p = p + s:length()
|
||||
end
|
||||
return p
|
||||
end
|
||||
|
||||
function Level:findNearestSegment(x, y, segments, margin)
|
||||
if not segments then segments = self.segments end
|
||||
if not margin then margin = 2 end
|
||||
if not segments then
|
||||
segments = self.segments
|
||||
end
|
||||
if not margin then
|
||||
margin = 2
|
||||
end
|
||||
-- find a touching segment within margins
|
||||
for i, segment in pairs(segments) do
|
||||
if segment.vertical then -- vertical line
|
||||
if x >= segment.firstPointX - margin and x <= segment.firstPointX +
|
||||
margin and y <=
|
||||
math.max(segment.firstPointY, segment.secondPointY) and y >=
|
||||
math.min(segment.firstPointY, segment.secondPointY) then
|
||||
if
|
||||
x >= segment.firstPointX - margin and x <= segment.firstPointX + margin and
|
||||
y <= math.max(segment.firstPointY, segment.secondPointY) and
|
||||
y >= math.min(segment.firstPointY, segment.secondPointY)
|
||||
then
|
||||
return i, segment
|
||||
end
|
||||
elseif segment.horizontal then -- horizontal line
|
||||
if y >= segment.firstPointY - margin and y <= segment.firstPointY +
|
||||
margin and x <=
|
||||
math.max(segment.firstPointX, segment.secondPointX) and x >=
|
||||
math.min(segment.firstPointX, segment.secondPointX) then
|
||||
if
|
||||
y >= segment.firstPointY - margin and y <= segment.firstPointY + margin and
|
||||
x <= math.max(segment.firstPointX, segment.secondPointX) and
|
||||
x >= math.min(segment.firstPointX, segment.secondPointX)
|
||||
then
|
||||
return i, segment
|
||||
end
|
||||
end
|
||||
@@ -754,15 +836,62 @@ function Level:findNearestSegment(x, y, segments, margin)
|
||||
end
|
||||
|
||||
function Level:containsBalls(segments)
|
||||
-- returns numbere of balls inside the bounds passed in or self.segments
|
||||
if not segments then segments = self.segments end
|
||||
-- returns number of balls inside the bounds passed in or self.segments
|
||||
if not segments then
|
||||
segments = self.segments
|
||||
end
|
||||
local counter = 0
|
||||
|
||||
for k, b in pairs(self.balls) do
|
||||
if self:insideBounds(b.x + 4, b.y + 4, segments) or
|
||||
self:pointOnEdge(b.x + 4, b.y + 4, seegments) then
|
||||
if self:insideBounds(b.x + 4, b.y + 4, segments) or self:pointOnEdge(b.x + 4, b.y + 4, seegments) then
|
||||
counter = counter + 1
|
||||
end
|
||||
end
|
||||
return counter
|
||||
-- return #self.balls
|
||||
end
|
||||
|
||||
function Level:createBalls(n)
|
||||
local balls = {}
|
||||
|
||||
for i = 1, n do
|
||||
table.insert(
|
||||
balls,
|
||||
Ball(
|
||||
math.random(LEVEL_RENDER_OFFSET + 5, VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET - 5), --X
|
||||
math.random(LEVEL_RENDER_OFFSET_TOP + 5, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET - 5), --Y
|
||||
math.random(20, 90),
|
||||
math.random(20, 90) -- speed
|
||||
)
|
||||
)
|
||||
end
|
||||
return balls
|
||||
end
|
||||
function Level:createBallsFromDef(def)
|
||||
local balls = {}
|
||||
|
||||
for i = 1, def.balls do
|
||||
table.insert(
|
||||
balls,
|
||||
Ball(
|
||||
math.random(LEVEL_RENDER_OFFSET + 5, VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET - 5), --X
|
||||
math.random(LEVEL_RENDER_OFFSET_TOP + 5, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET - 5), --Y
|
||||
math.random(def.ballSpeed - 10, def.ballSpeed + 10),
|
||||
math.random(def.ballSpeed - 10, def.ballSpeed + 10) -- speed
|
||||
)
|
||||
)
|
||||
end
|
||||
return balls
|
||||
end
|
||||
|
||||
function Level:updateBalls(dt)
|
||||
for k, ball in pairs(self.balls) do
|
||||
ball:update(dt, self)
|
||||
end
|
||||
end
|
||||
|
||||
function Level:renderBalls()
|
||||
for k, ball in pairs(self.balls) do
|
||||
ball:render()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -39,6 +39,7 @@ function Player:init(def, level )
|
||||
end
|
||||
|
||||
function Player:isMoveAllowed(point)
|
||||
point = {point[1] + self.width/2, point[2] + self.width/2}
|
||||
for i,segment in pairs (self.trailSegments) do
|
||||
if segment:pointInSegment(point) then
|
||||
return false
|
||||
@@ -97,7 +98,6 @@ function Player:onEdge()
|
||||
end
|
||||
|
||||
function Player:onWalking()
|
||||
-- if position of player collides with its own trail, stop motion
|
||||
if #self.trail > 1 then
|
||||
table.remove(self.trail)
|
||||
table.remove(self.trailSegments)
|
||||
|
||||
123
src/Segment.lua
123
src/Segment.lua
@@ -1,10 +1,9 @@
|
||||
-- require('mobdebug').start()
|
||||
|
||||
Segment = Class{}
|
||||
Segment = Class {}
|
||||
|
||||
local symbols = {['up'] = 207, ['down'] = 209, ['right'] = 199, ['left'] = 182}
|
||||
|
||||
function Segment:init(firstPoint, secondPoint,lineWidth, face, color)
|
||||
function Segment:init(firstPoint, secondPoint, lineWidth, face, color)
|
||||
self.firstPointX = firstPoint[1]
|
||||
self.firstPointY = firstPoint[2]
|
||||
self.secondPointX = secondPoint[1]
|
||||
@@ -14,15 +13,16 @@ function Segment:init(firstPoint, secondPoint,lineWidth, face, color)
|
||||
self.horizontal = self.firstPointY == self.secondPointY
|
||||
self.face = face or ''
|
||||
self.direction = self:calculateDirection()
|
||||
self.color = color or {r=255,g=255,b=255}
|
||||
self.color = color or {r = 255, g = 255, b = 255}
|
||||
end
|
||||
|
||||
function Segment:render()
|
||||
love.graphics.setColor(self.color.r,self.color.g, self.color.b,255)
|
||||
love.graphics.setColor(self.color.r, self.color.g, self.color.b, 1)
|
||||
love.graphics.setLineWidth(self.lineWidth)
|
||||
love.graphics.line(self.firstPointX,self.firstPointY,self.secondPointX, self.secondPointY)
|
||||
love.graphics.line(self.firstPointX, self.firstPointY, self.secondPointX,
|
||||
self.secondPointY)
|
||||
|
||||
love.graphics.setColor(255,255, 255, 255)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
|
||||
-- debug
|
||||
-- love.graphics.setFont(gFonts['small'])
|
||||
@@ -31,14 +31,18 @@ function Segment:render()
|
||||
end
|
||||
|
||||
function Segment:segmentToPoints()
|
||||
return self.firstPointX, self.firstPointY, self.secondPointX, self.secondPointY
|
||||
return self.firstPointX, self.firstPointY, self.secondPointX,
|
||||
self.secondPointY
|
||||
end
|
||||
|
||||
function Segment:length()
|
||||
return math.sqrt( (self.secondPointX - self.firstPointX) * (self.secondPointX - self.firstPointX) + (self.secondPointY - self.firstPointY) * (self.secondPointY - self.firstPointY) )
|
||||
return math.sqrt((self.secondPointX - self.firstPointX) *
|
||||
(self.secondPointX - self.firstPointX) +
|
||||
(self.secondPointY - self.firstPointY) *
|
||||
(self.secondPointY - self.firstPointY))
|
||||
end
|
||||
|
||||
function Segment:sideOfSegment(x,y)
|
||||
function Segment:sideOfSegment(x, y)
|
||||
if y < self.firstPointY and y < self.secondPointY then -- above
|
||||
return 'up'
|
||||
end
|
||||
@@ -55,9 +59,7 @@ function Segment:sideOfSegment(x,y)
|
||||
end
|
||||
|
||||
function Segment:debug(msg)
|
||||
if not msg then
|
||||
msg = ''
|
||||
end
|
||||
if not msg then msg = '' end
|
||||
-- print("Segment:debug ".. msg .." ...............")
|
||||
-- print("FirstPoint: "..tostring(self.firstPointX)..','..tostring(self.firstPointY))
|
||||
-- print("SecondPoint: "..tostring(self.secondPointX)..','..tostring(self.secondPointY))
|
||||
@@ -72,35 +74,35 @@ function Segment:copy()
|
||||
copy.secondPointY = self.secondPointY
|
||||
copy.lineWidth = self.lineWidth
|
||||
copy.face = self.face
|
||||
return Segment({copy.firstPointX,copy.firstPointY},{copy.secondPointX,copy.secondPointY},copy.lineWidth, copy.face)
|
||||
return Segment({copy.firstPointX, copy.firstPointY},
|
||||
{copy.secondPointX, copy.secondPointY}, copy.lineWidth,
|
||||
copy.face)
|
||||
end
|
||||
|
||||
function Segment:endEqualsStartOf(s)
|
||||
-- segments are linked at the end of this one
|
||||
if self.secondPointX == s.firstPointX and
|
||||
self.secondPointY == s.firstPointY then
|
||||
if self.secondPointX == s.firstPointX and self.secondPointY == s.firstPointY then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
function Segment:endEqualsEndOf(s)
|
||||
-- segments are linked at the end of this one
|
||||
if self.secondPointX == s.secondPointX and self.secondPointY == s.secondPointY then
|
||||
return true
|
||||
end
|
||||
if self.secondPointX == s.secondPointX and self.secondPointY ==
|
||||
s.secondPointY then return true end
|
||||
return false
|
||||
end
|
||||
|
||||
function Segment:startEqualsEndOf(s)
|
||||
-- segments are linked at the beginning of this one
|
||||
if self.firstPointX == s.secondPointX and self.firstPointY == s.secondPointY then
|
||||
if self.firstPointX == s.secondPointX and self.firstPointY == s.secondPointY then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
function Segment:startEqualsStartOf(s)
|
||||
-- segments are linked at the beginning of this one
|
||||
if self.firstPointX == s.firstPointX and self.firstPointY == s.PointY then
|
||||
if self.firstPointX == s.firstPointX and self.firstPointY == s.PointY then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
@@ -129,27 +131,17 @@ function Segment:splitInTwoWithPoint(point) -- number
|
||||
local s1, s2 = {}
|
||||
if point > 0 then
|
||||
if self.vertical then
|
||||
s1 = Segment(
|
||||
{self.firstPointX, self.firstPointY},
|
||||
{self.secondPointX, point},
|
||||
self.lineWidth, self.face
|
||||
)
|
||||
s2 = Segment(
|
||||
{self.firstPointX, point},
|
||||
{self.secondPointX,self.secondPointY},
|
||||
self.lineWidth, self.face
|
||||
)
|
||||
s1 = Segment({self.firstPointX, self.firstPointY},
|
||||
{self.secondPointX, point}, self.lineWidth, self.face)
|
||||
s2 = Segment({self.firstPointX, point},
|
||||
{self.secondPointX, self.secondPointY}, self.lineWidth,
|
||||
self.face)
|
||||
else
|
||||
s1 = Segment(
|
||||
{self.firstPointX, self.firstPointY},
|
||||
{point, self.secondPointY},
|
||||
self.lineWidth, self.face
|
||||
)
|
||||
s2 = Segment(
|
||||
{point, self.firstPointY},
|
||||
{self.secondPointX,self.secondPointY},
|
||||
self.lineWidth, self.face
|
||||
)
|
||||
s1 = Segment({self.firstPointX, self.firstPointY},
|
||||
{point, self.secondPointY}, self.lineWidth, self.face)
|
||||
s2 = Segment({point, self.firstPointY},
|
||||
{self.secondPointX, self.secondPointY}, self.lineWidth,
|
||||
self.face)
|
||||
end
|
||||
else
|
||||
return nil, nil
|
||||
@@ -179,18 +171,16 @@ end
|
||||
|
||||
function Segment:joinPerpendicular(s)
|
||||
-- changes the self, not the parameter
|
||||
if s.vertical then
|
||||
if s.vertical and self.horizontal then
|
||||
local sx = s.firstPointX
|
||||
if math.abs(self.firstPointX - sx) <
|
||||
math.abs(self.secondPointX - sx) then
|
||||
if math.abs(self.firstPointX - sx) < math.abs(self.secondPointX - sx) then
|
||||
self.firstPointX = sx
|
||||
else
|
||||
self.secondPointX = sx
|
||||
end
|
||||
else
|
||||
elseif s.horizontal and self.vertical then
|
||||
local sy = s.firstPointY
|
||||
if math.abs(self.firstPointY - sy) <
|
||||
math.abs(self.secondPointY - sy) then
|
||||
if math.abs(self.firstPointY - sy) < math.abs(self.secondPointY - sy) then
|
||||
self.firstPointY = sy
|
||||
else
|
||||
self.secondPointY = sy
|
||||
@@ -259,14 +249,14 @@ function Segment:compare(s)
|
||||
return self.firstPointY - s.firstPointY
|
||||
end
|
||||
else
|
||||
return (self.firstPointX + self.firstPointY +
|
||||
self.secondPointX + self.secondPointY) - (
|
||||
s.firstPointX + s.firstPointY + s.secondPointX
|
||||
+s.secondPointY)
|
||||
return (self.firstPointX + self.firstPointY + self.secondPointX +
|
||||
self.secondPointY) -
|
||||
(s.firstPointX + s.firstPointY + s.secondPointX +
|
||||
s.secondPointY)
|
||||
end
|
||||
end
|
||||
|
||||
function Segment:splitInThreeWithSegments(s1,s2)
|
||||
function Segment:splitInThreeWithSegments(s1, s2)
|
||||
local p1, p2, p3, t = {}
|
||||
if self.direction == 'down' or self.direction == 'right' then
|
||||
if s1:compare(s2) < 0 then
|
||||
@@ -286,23 +276,32 @@ function Segment:splitInThreeWithSegments(s1,s2)
|
||||
end
|
||||
end
|
||||
|
||||
return p1,p2,p3
|
||||
return p1, p2, p3
|
||||
end
|
||||
|
||||
function Segment:insert(list)
|
||||
|
||||
end
|
||||
function Segment:insert(list) end
|
||||
|
||||
function Segment:pointInSegment(point)
|
||||
-- remove "+ 8" and replace by sprite.width / 2
|
||||
if self.direction == 'up' or self.direction == 'down' then
|
||||
if point[1] <= self.firstPointX + 1 and
|
||||
point[1] >= self.firstPointX - 1 then
|
||||
return true
|
||||
if point[1] <= self.firstPointX + 1 and point[1] >= self.firstPointX - 1 then
|
||||
if self.direction == 'down' then
|
||||
if point[2] >= self.firstPointY and point[2] <=
|
||||
self.secondPointY then return true end
|
||||
else
|
||||
if point[2] >= self.secondPointY and point[2] <=
|
||||
self.firstPointY then return true end
|
||||
end
|
||||
end
|
||||
else
|
||||
if point[2] <= self.firstPointY + 1 and
|
||||
point[2] >= self.firstPointY - 1 then
|
||||
return true
|
||||
if point[2] <= self.firstPointY + 1 and point[2] >= self.firstPointY - 1 then
|
||||
if self.direction == 'right' then
|
||||
if point[1] >= self.firstPointX and point[1] <=
|
||||
self.secondPointX then return true end
|
||||
else
|
||||
if point[1] >= self.secondPointX and point[1] <=
|
||||
self.firstPointX then return true end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
155
src/Util.lua
155
src/Util.lua
@@ -74,7 +74,8 @@ end
|
||||
-- convert a list of points forming a polygon {x1, y1, x2, y2, ...} into a mesh
|
||||
|
||||
function poly2mesh(points)
|
||||
-- remove duplicates???
|
||||
-- print("util - poly2mesh: ")
|
||||
-- print_r(points)
|
||||
if #points > 2 then
|
||||
local polypts = love.math.triangulate(points)
|
||||
local tlist
|
||||
@@ -119,3 +120,155 @@ function poly2mesh(points)
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
-- point in shape calculation
|
||||
function PointWithinShape(shape, tx, ty)
|
||||
if #shape == 0 then
|
||||
return false
|
||||
elseif #shape == 1 then
|
||||
return shape[1].x == tx and shape[1].y == ty
|
||||
elseif #shape == 2 then
|
||||
return PointWithinLine(shape, tx, ty)
|
||||
else
|
||||
return CrossingsMultiplyTest(shape, tx, ty)
|
||||
end
|
||||
end
|
||||
|
||||
function BoundingBox(box, tx, ty)
|
||||
return (box[2].x >= tx and box[2].y >= ty)
|
||||
and (box[1].x <= tx and box[1].y <= ty)
|
||||
or (box[1].x >= tx and box[2].y >= ty)
|
||||
and (box[2].x <= tx and box[1].y <= ty)
|
||||
end
|
||||
|
||||
function colinear(line, x, y, e)
|
||||
e = e or 0.1
|
||||
m = (line[2].y - line[1].y) / (line[2].x - line[1].x)
|
||||
local function f(x) return line[1].y + m*(x - line[1].x) end
|
||||
return math.abs(y - f(x)) <= e
|
||||
end
|
||||
|
||||
function PointWithinLine(line, tx, ty, e)
|
||||
e = e or 0.66
|
||||
if BoundingBox(line, tx, ty) then
|
||||
return colinear(line, tx, ty, e)
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
-- The following function is based off code from
|
||||
-- [ http://erich.realtimerendering.com/ptinpoly/ ]
|
||||
--
|
||||
--[[
|
||||
======= Crossings Multiply algorithm ===================================
|
||||
* This version is usually somewhat faster than the original published in
|
||||
* Graphics Gems IV; by turning the division for testing the X axis crossing
|
||||
* into a tricky multiplication test this part of the test became faster,
|
||||
* which had the additional effect of making the test for "both to left or
|
||||
* both to right" a bit slower for triangles than simply computing the
|
||||
* intersection each time. The main increase is in triangle testing speed,
|
||||
* which was about 15% faster; all other polygon complexities were pretty much
|
||||
* the same as before. On machines where division is very expensive (not the
|
||||
* case on the HP 9000 series on which I tested) this test should be much
|
||||
* faster overall than the old code. Your mileage may (in fact, will) vary,
|
||||
* depending on the machine and the test data, but in general I believe this
|
||||
* code is both shorter and faster. This test was inspired by unpublished
|
||||
* Graphics Gems submitted by Joseph Samosky and Mark Haigh-Hutchinson.
|
||||
* Related work by Samosky is in:
|
||||
*
|
||||
* Samosky, Joseph, "SectionView: A system for interactively specifying and
|
||||
* visualizing sections through three-dimensional medical image data",
|
||||
* M.S. Thesis, Department of Electrical Engineering and Computer Science,
|
||||
* Massachusetts Institute of Technology, 1993.
|
||||
*
|
||||
--]]
|
||||
|
||||
--[[ Shoot a test ray along +X axis. The strategy is to compare vertex Y values
|
||||
* to the testing point's Y and quickly discard edges which are entirely to one
|
||||
* side of the test ray. Note that CONVEX and WINDING code can be added as
|
||||
* for the CrossingsTest() code; it is left out here for clarity.
|
||||
*
|
||||
* Input 2D polygon _pgon_ with _numverts_ number of vertices and test point
|
||||
* _point_, returns 1 if inside, 0 if outside.
|
||||
--]]
|
||||
function CrossingsMultiplyTest(pgon, tx, ty)
|
||||
local i, yflag0, yflag1, inside_flag
|
||||
local vtx0, vtx1
|
||||
|
||||
local numverts = #pgon
|
||||
|
||||
vtx0 = pgon[numverts]
|
||||
vtx1 = pgon[1]
|
||||
|
||||
-- get test bit for above/below X axis
|
||||
yflag0 = ( vtx0.y >= ty )
|
||||
inside_flag = false
|
||||
|
||||
for i=2,numverts+1 do
|
||||
yflag1 = ( vtx1.y >= ty )
|
||||
|
||||
--[[ Check if endpoints straddle (are on opposite sides) of X axis
|
||||
* (i.e. the Y's differ); if so, +X ray could intersect this edge.
|
||||
* The old test also checked whether the endpoints are both to the
|
||||
* right or to the left of the test point. However, given the faster
|
||||
* intersection point computation used below, this test was found to
|
||||
* be a break-even proposition for most polygons and a loser for
|
||||
* triangles (where 50% or more of the edges which survive this test
|
||||
* will cross quadrants and so have to have the X intersection computed
|
||||
* anyway). I credit Joseph Samosky with inspiring me to try dropping
|
||||
* the "both left or both right" part of my code.
|
||||
--]]
|
||||
if ( yflag0 ~= yflag1 ) then
|
||||
--[[ Check intersection of pgon segment with +X ray.
|
||||
* Note if >= point's X; if so, the ray hits it.
|
||||
* The division operation is avoided for the ">=" test by checking
|
||||
* the sign of the first vertex wrto the test point; idea inspired
|
||||
* by Joseph Samosky's and Mark Haigh-Hutchinson's different
|
||||
* polygon inclusion tests.
|
||||
--]]
|
||||
if ( ((vtx1.y - ty) * (vtx0.x - vtx1.x) >= (vtx1.x - tx) * (vtx0.y - vtx1.y)) == yflag1 ) then
|
||||
inside_flag = not inside_flag
|
||||
end
|
||||
end
|
||||
|
||||
-- Move to the next pair of vertices, retaining info as possible.
|
||||
yflag0 = yflag1
|
||||
vtx0 = vtx1
|
||||
vtx1 = pgon[i]
|
||||
end
|
||||
|
||||
return inside_flag
|
||||
end
|
||||
|
||||
function GetIntersect( points )
|
||||
local g1 = points[1].x
|
||||
local h1 = points[1].y
|
||||
|
||||
local g2 = points[2].x
|
||||
local h2 = points[2].y
|
||||
|
||||
local i1 = points[3].x
|
||||
local j1 = points[3].y
|
||||
|
||||
local i2 = points[4].x
|
||||
local j2 = points[4].y
|
||||
|
||||
local xk = 0
|
||||
local yk = 0
|
||||
|
||||
if checkIntersect({x=g1, y=h1}, {x=g2, y=h2}, {x=i1, y=j1}, {x=i2, y=j2}) then
|
||||
local a = h2-h1
|
||||
local b = (g2-g1)
|
||||
local v = ((h2-h1)*g1) - ((g2-g1)*h1)
|
||||
|
||||
local d = i2-i1
|
||||
local c = (j2-j1)
|
||||
local w = ((j2-j1)*i1) - ((i2-i1)*j1)
|
||||
|
||||
xk = (1/((a*d)-(b*c))) * ((d*v)-(b*w))
|
||||
yk = (-1/((a*d)-(b*c))) * ((a*w)-(c*v))
|
||||
end
|
||||
return xk, yk
|
||||
end
|
||||
@@ -10,3 +10,5 @@ LEVEL_RENDER_OFFSET_TOP = 30
|
||||
LEVEL_RENDER_OFFSET = 10
|
||||
|
||||
TILE_SIZE = 16
|
||||
|
||||
LINE_WIDTH = .5
|
||||
@@ -25,9 +25,9 @@ function Entity:changeState(name)
|
||||
-- printChangeState to "..name)
|
||||
end
|
||||
|
||||
-- function Entity:isMoveAllowed(point)
|
||||
-- return point.x, point.y
|
||||
-- end
|
||||
function Entity:isMoveAllowed(point)
|
||||
return true
|
||||
end
|
||||
|
||||
function Entity:changeAnimation(name)
|
||||
self.currentAnimation = self.animations[name]
|
||||
|
||||
@@ -45,3 +45,237 @@ ENTITY_DEFS = {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LEVELS_DEF = {
|
||||
[1] = {
|
||||
segments =
|
||||
{
|
||||
{
|
||||
p1 = {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
p2 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
width = LINE_WIDTH,
|
||||
face = 'down'
|
||||
},
|
||||
{
|
||||
p1 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
p2 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
width = LINE_WIDTH,
|
||||
face = 'left'
|
||||
},
|
||||
{
|
||||
p1 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
p2 = {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
width = LINE_WIDTH,
|
||||
face = 'up'
|
||||
},
|
||||
{
|
||||
p1 = {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
p2 = {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
width= LINE_WIDTH,
|
||||
face = 'right'
|
||||
},
|
||||
},
|
||||
spiders = 0,
|
||||
timeLimit = 300,
|
||||
balls = 1,
|
||||
ballSpeed = 20,
|
||||
},
|
||||
[2] = {
|
||||
segments =
|
||||
{
|
||||
{
|
||||
p1 = {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
p2 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
width = LINE_WIDTH,
|
||||
face = 'down'
|
||||
},
|
||||
{
|
||||
p1 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
p2 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
width = LINE_WIDTH,
|
||||
face = 'left'
|
||||
},
|
||||
{
|
||||
p1 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
p2 = {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
width = LINE_WIDTH,
|
||||
face = 'up'
|
||||
},
|
||||
{
|
||||
p1 = {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
p2 = {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
width= LINE_WIDTH,
|
||||
face = 'right'
|
||||
},
|
||||
},
|
||||
spiders = 0,
|
||||
timeLimit = 35,
|
||||
balls = 2,
|
||||
ballSpeed = 40,
|
||||
},
|
||||
[3] = {
|
||||
segments =
|
||||
{
|
||||
{
|
||||
p1 = {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
p2 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
width = LINE_WIDTH,
|
||||
face = 'down'
|
||||
},
|
||||
{
|
||||
p1 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
p2 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
width = LINE_WIDTH,
|
||||
face = 'left'
|
||||
},
|
||||
{
|
||||
p1 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
p2 = {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
width = LINE_WIDTH,
|
||||
face = 'up'
|
||||
},
|
||||
{
|
||||
p1 = {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
p2 = {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
width= LINE_WIDTH,
|
||||
face = 'right'
|
||||
},
|
||||
},
|
||||
spiders = 0,
|
||||
timeLimit = 45,
|
||||
balls = 3,
|
||||
ballSpeed = 45,
|
||||
},
|
||||
[4] = {
|
||||
segments =
|
||||
{
|
||||
{
|
||||
p1 = {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
p2 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
width = LINE_WIDTH,
|
||||
face = 'down'
|
||||
},
|
||||
{
|
||||
p1 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
p2 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
width = LINE_WIDTH,
|
||||
face = 'left'
|
||||
},
|
||||
{
|
||||
p1 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
p2 = {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
width = LINE_WIDTH,
|
||||
face = 'up'
|
||||
},
|
||||
{
|
||||
p1 = {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
p2 = {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
width= LINE_WIDTH,
|
||||
face = 'right'
|
||||
},
|
||||
},
|
||||
spiders = 1,
|
||||
timeLimit = 60,
|
||||
balls = 3,
|
||||
ballSpeed = 45,
|
||||
},
|
||||
[5] = {
|
||||
segments =
|
||||
{
|
||||
{
|
||||
p1 = {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
p2 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
width = LINE_WIDTH,
|
||||
face = 'down'
|
||||
},
|
||||
{
|
||||
p1 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
p2 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
width = LINE_WIDTH,
|
||||
face = 'left'
|
||||
},
|
||||
{
|
||||
p1 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
p2 = {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
width = LINE_WIDTH,
|
||||
face = 'up'
|
||||
},
|
||||
{
|
||||
p1 = {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
p2 = {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
width= LINE_WIDTH,
|
||||
face = 'right'
|
||||
},
|
||||
},
|
||||
spiders = 1,
|
||||
timeLimit = 65,
|
||||
balls = 4,
|
||||
ballSpeed = 50,
|
||||
},
|
||||
[6] = {
|
||||
segments =
|
||||
{
|
||||
{
|
||||
p1 = {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
p2 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
width = LINE_WIDTH,
|
||||
face = 'down'
|
||||
},
|
||||
{
|
||||
p1 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
p2 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
width = LINE_WIDTH,
|
||||
face = 'left'
|
||||
},
|
||||
{
|
||||
p1 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
p2 = {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
width = LINE_WIDTH,
|
||||
face = 'up'
|
||||
},
|
||||
{
|
||||
p1 = {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
p2 = {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
width= LINE_WIDTH,
|
||||
face = 'right'
|
||||
},
|
||||
},
|
||||
spiders = 2,
|
||||
timeLimit = 75,
|
||||
balls = 4,
|
||||
ballSpeed = 50,
|
||||
},
|
||||
[7] = {
|
||||
segments =
|
||||
{
|
||||
{
|
||||
p1 = {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
p2 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
width = LINE_WIDTH,
|
||||
face = 'down'
|
||||
},
|
||||
{
|
||||
p1 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
p2 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
width = LINE_WIDTH,
|
||||
face = 'left'
|
||||
},
|
||||
{
|
||||
p1 = {VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
p2 = {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
width = LINE_WIDTH,
|
||||
face = 'up'
|
||||
},
|
||||
{
|
||||
p1 = {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},
|
||||
p2 = {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||
width= LINE_WIDTH,
|
||||
face = 'right'
|
||||
},
|
||||
},
|
||||
spiders = 2,
|
||||
timeLimit = 90,
|
||||
balls = 5,
|
||||
ballSpeed = 60,
|
||||
},
|
||||
}
|
||||
@@ -10,8 +10,8 @@ end
|
||||
|
||||
function EntityWalkEdgeState:update(dt)
|
||||
|
||||
local dy = self.entity.walkingSpeed * dt
|
||||
local dx = self.entity.walkingSpeed * dt
|
||||
local dy = math.floor(self.entity.walkingSpeed * dt + 0.5)
|
||||
local dx = math.floor(self.entity.walkingSpeed * dt + 0.5)
|
||||
|
||||
if self.entity.direction == 'left' then
|
||||
if self.entity.level:pointOnEdge(self.entity.x - dx + TILE_SIZE / 2, self.entity.y + TILE_SIZE / 2) then
|
||||
|
||||
@@ -9,9 +9,11 @@ function EntityWalkState:init(entity)
|
||||
end
|
||||
|
||||
function EntityWalkState:update(dt)
|
||||
-- print("EntityWalkState - Current Position:" .. tostring(self.entity.x) .. "," .. tostring(self.entity.y))
|
||||
if self.entity.direction == 'up' then
|
||||
if self.entity:isMoveAllowed({self.entity.x, self.entity.y - self.entity.walkingSpeed * dt}) then
|
||||
self.entity.y = self.entity.y - self.entity.walkingSpeed * dt
|
||||
local move = {math.floor(self.entity.x + 0.5), math.floor(self.entity.y - self.entity.walkingSpeed * dt + 0.5)}
|
||||
if self.entity:isMoveAllowed(move) then
|
||||
self.entity.y = move[2]
|
||||
if self.entity.y + TILE_SIZE / 2 < LEVEL_RENDER_OFFSET_TOP - 2 then
|
||||
self.entity.y = self.entity.y + self.entity.walkingSpeed * dt
|
||||
Event.dispatch('back-to-wall')
|
||||
@@ -19,8 +21,9 @@ function EntityWalkState:update(dt)
|
||||
end
|
||||
end
|
||||
elseif self.entity.direction == 'down' then
|
||||
if self.entity:isMoveAllowed({self.entity.x, self.entity.y + self.entity.walkingSpeed * dt}) then
|
||||
self.entity.y = self.entity.y + self.entity.walkingSpeed * dt
|
||||
local move = {math.floor(self.entity.x + 0.5), math.floor(self.entity.y + self.entity.walkingSpeed * dt + 0.5)}
|
||||
if self.entity:isMoveAllowed(move) then
|
||||
self.entity.y = move[2]
|
||||
if self.entity.y + TILE_SIZE / 2 > VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET + 2 then
|
||||
self.entity.y = self.entity.y - self.entity.walkingSpeed * dt
|
||||
Event.dispatch('back-to-wall')
|
||||
@@ -28,8 +31,9 @@ function EntityWalkState:update(dt)
|
||||
end
|
||||
end
|
||||
elseif self.entity.direction == 'right' then
|
||||
if self.entity:isMoveAllowed({self.entity.x + self.entity.walkingSpeed * dt, self.entity.y}) then
|
||||
self.entity.x = self.entity.x + self.entity.walkingSpeed * dt
|
||||
local move = {math.floor(self.entity.x + self.entity.walkingSpeed * dt + 0.5), math.floor(self.entity.y + 0.5)}
|
||||
if self.entity:isMoveAllowed(move) then
|
||||
self.entity.x = move[1]
|
||||
if self.entity.x + TILE_SIZE / 2 > VIRTUAL_WIDTH - TILE_SIZE / 2 + 2 or self.entity.previousdirection == 'left' then
|
||||
self.entity.x = self.entity.x - self.entity.walkingSpeed * dt
|
||||
Event.dispatch('back-to-wall')
|
||||
@@ -37,8 +41,9 @@ function EntityWalkState:update(dt)
|
||||
end
|
||||
end
|
||||
elseif self.entity.direction == 'left' then
|
||||
if self.entity:isMoveAllowed({self.entity.x - self.entity.walkingSpeed * dt, self.entity.y}) then
|
||||
self.entity.x = self.entity.x - self.entity.walkingSpeed * dt
|
||||
local move = {math.floor(self.entity.x - self.entity.walkingSpeed * dt + 0.5),math.floor(self.entity.y + 0.5)}
|
||||
if self.entity:isMoveAllowed(move) then
|
||||
self.entity.x = move[1]
|
||||
if self.entity.x < 0 or self.entity.previousdirection == 'right' then
|
||||
self.entity.x = self.entity.x + self.entity.walkingSpeed * dt
|
||||
Event.dispatch('back-to-wall')
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
-- require('mobdebug').start()
|
||||
|
||||
PlayState = Class{__includes = BaseState}
|
||||
PlayState = Class {__includes = BaseState}
|
||||
|
||||
function PlayState:init()
|
||||
self.name = 'PlayState'
|
||||
self.name = "PlayState"
|
||||
self.stage = 1
|
||||
self.level = Level(self.stage)
|
||||
self.player = Player ( ENTITY_DEFS['player'] , self.level)
|
||||
self.level = Level(LEVELS_DEF[1], self.stage)
|
||||
self.player = Player(ENTITY_DEFS["player"], self.level)
|
||||
self.level.player = self.player
|
||||
self.balls = {}
|
||||
self:createBalls()
|
||||
self.level.balls = self.balls
|
||||
|
||||
gSounds['music']:setLooping(true)
|
||||
gSounds['music']:play()
|
||||
self.balls = self.level.balls
|
||||
self.clock = self.level.clock
|
||||
|
||||
gSounds["music"]:setPitch(1)
|
||||
gSounds["music"]:setLooping(true)
|
||||
gSounds["music"]:play()
|
||||
end
|
||||
|
||||
function PlayState:enter()
|
||||
@@ -23,106 +22,106 @@ end
|
||||
function PlayState:update(dt)
|
||||
self.level:update(dt)
|
||||
self.player:update(dt)
|
||||
self:updateBalls(dt, self.level)
|
||||
self:checkEndLevel(self.level)
|
||||
end
|
||||
|
||||
function PlayState:render()
|
||||
love.graphics.clear(0, 0, 0, 255/255)
|
||||
love.graphics.setColor(40/255, 45/255, 52/255,255/255)
|
||||
love.graphics.clear(0, 0, 0, 255 / 255)
|
||||
love.graphics.setColor(56 / 255, 56 / 255, 56 / 255, 1)
|
||||
|
||||
love.graphics.setFont(gFonts['small'])
|
||||
love.graphics.printf('Score '..tostring(self.player.score),
|
||||
0, 5, VIRTUAL_WIDTH, 'left')
|
||||
love.graphics.setFont(gFonts["small"])
|
||||
love.graphics.printf("Score " .. tostring(self.player.score), LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP/2, VIRTUAL_WIDTH, "left")
|
||||
|
||||
love.graphics.setFont(gFonts['medium'])
|
||||
love.graphics.printf('Stage '..tostring(self.stage),
|
||||
0, 5, VIRTUAL_WIDTH, 'center')
|
||||
love.graphics.setFont(gFonts["medium"])
|
||||
love.graphics.printf("Stage " .. tostring(self.stage), 0, 5, VIRTUAL_WIDTH, "center")
|
||||
|
||||
self.level:render()
|
||||
self.player:render()
|
||||
self:renderBalls(dt)
|
||||
end
|
||||
|
||||
function PlayState:createBalls()
|
||||
self.balls = {}
|
||||
|
||||
for i = 1, self.stage do
|
||||
table.insert(self.balls,Ball(
|
||||
math.random(LEVEL_RENDER_OFFSET + 5, VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET - 5), --X
|
||||
math.random(LEVEL_RENDER_OFFSET_TOP + 5, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET - 5), --Y
|
||||
math.random(20,90),math.random(20,90) -- speed
|
||||
))
|
||||
function PlayState:checkEndLevel(level)
|
||||
if #self.balls <= 0 then
|
||||
-- game over - reset level
|
||||
print("game over due to 0 balls")
|
||||
self:gameOver()
|
||||
end
|
||||
end
|
||||
|
||||
function PlayState:updateBalls(dt, level)
|
||||
for k,ball in pairs(self.balls) do
|
||||
ball:update(dt,level)
|
||||
-- check perimeter of level, if low enough, create new level move on to the next stage
|
||||
if level:getPerimeter() < 500 then
|
||||
print("next stage due to perimeter goal reached")
|
||||
self:nextStage()
|
||||
end
|
||||
|
||||
-- check if clock finished counting limit time
|
||||
if self.clock.direction == "up" and self.clock.currentTime * 1 > self.clock.timeLimit then
|
||||
print("game over due to time limit reached")
|
||||
self:gameOver()
|
||||
elseif self.clock.direction == "down" and self.clock.currentTime * 1 <= 0 then
|
||||
print("game over due to time limit reached")
|
||||
self:gameOver()
|
||||
elseif self.clock.direction == "up" and self.clock.currentTime * 1 > self.clock.timeLimit - 10 then
|
||||
gSounds["music"]:setPitch(1.25)
|
||||
elseif self.clock.direction == "down" and self.clock.currentTime * 1 <= 10 then
|
||||
gSounds["music"]:setPitch(1.25)
|
||||
end
|
||||
|
||||
-- remove balls outside bounds
|
||||
for k,ball in pairs(self.balls) do
|
||||
for k, ball in pairs(self.balls) do
|
||||
if ball.remove then
|
||||
table.remove(self.balls,k)
|
||||
table.remove(self.balls, k)
|
||||
self.player.score = self.player.score - 1
|
||||
elseif ball.hitPlayer then
|
||||
-- check if any ball hit the player trail segments
|
||||
print("game over due to player hit by ball")
|
||||
self:gameOver()
|
||||
end
|
||||
end
|
||||
|
||||
if #self.balls <= 0 then
|
||||
-- game over - reset level
|
||||
self:gameOver()
|
||||
end
|
||||
|
||||
-- check perimeter of level, if low enough, create new level move on to the next stage
|
||||
if level:getPerimeter() < 500 then
|
||||
self:nextStage()
|
||||
end
|
||||
end
|
||||
|
||||
function PlayState:checkEndLevel (level)
|
||||
if #self.balls <= 0 then
|
||||
-- game over - reset level
|
||||
self:gameOver()
|
||||
end
|
||||
|
||||
-- check perimeter of level, if low enough, create new level move on to the next stage
|
||||
if level:getPerimeter() < 500 then
|
||||
self:nextStage()
|
||||
end
|
||||
end
|
||||
|
||||
function PlayState:renderBalls(dt)
|
||||
for k,ball in pairs(self.balls) do
|
||||
ball:render()
|
||||
end
|
||||
end
|
||||
|
||||
function PlayState:gameOver()
|
||||
gStateStack:pop()
|
||||
gSounds['music']:stop()
|
||||
gStateStack:push(GameOverState(self.player.score),function() end)
|
||||
gSounds["music"]:stop()
|
||||
gStateStack:push(
|
||||
GameOverState(self.player.score),
|
||||
function()
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
function PlayState:nextStage()
|
||||
gStateStack:push(FadeOutState({
|
||||
r = 255/255, g = 255/255, b = 255/255}, 1,function()
|
||||
self.stage = self.stage + 1
|
||||
self.level = Level(self.stage)
|
||||
self.player:reset()
|
||||
self.player.score = self.player.score + self.player.multiplier * #self.balls
|
||||
self.player.multiplier = self.player.multiplier + #self.balls
|
||||
self.balls = {}
|
||||
self:createBalls()
|
||||
self.level.player = self.player
|
||||
self.player.level = self.level
|
||||
self.level.balls = self.balls
|
||||
gSounds['music']:stop()
|
||||
gSounds['heal']:play()
|
||||
gStateStack:push(FadeOutState({r = 1/255, g = 1/255, b = 1/255}, 1,function()
|
||||
gSounds['music']:play()
|
||||
end))
|
||||
end))
|
||||
gStateStack:push(
|
||||
FadeOutState(
|
||||
{
|
||||
r = 255 / 255,
|
||||
g = 255 / 255,
|
||||
b = 255 / 255
|
||||
},
|
||||
1,
|
||||
function()
|
||||
self.stage = self.stage + 1
|
||||
local nextDef = self.stage % (#LEVELS_DEF + 1)
|
||||
if nextDef == 0 then nextDef = 1 end
|
||||
self.level = Level(LEVELS_DEF[nextDef], self.stage)
|
||||
self.balls = self.level.balls
|
||||
self.clock = self.level.clock
|
||||
self.player:reset()
|
||||
self.player.score = self.player.score + self.player.multiplier * #self.balls
|
||||
self.player.multiplier = self.player.multiplier + #self.balls
|
||||
self.level.player = self.player
|
||||
self.player.level = self.level
|
||||
gSounds["music"]:stop()
|
||||
gSounds["heal"]:play()
|
||||
gStateStack:push(
|
||||
FadeOutState(
|
||||
{r = 1 / 255, g = 1 / 255, b = 1 / 255},
|
||||
1,
|
||||
function()
|
||||
gSounds["music"]:setPitch(1)
|
||||
gSounds["music"]:play()
|
||||
end
|
||||
)
|
||||
)
|
||||
end
|
||||
)
|
||||
)
|
||||
end
|
||||
Reference in New Issue
Block a user