Compare commits
2 Commits
main
...
coordinate
| Author | SHA1 | Date | |
|---|---|---|---|
| 17a07bc95a | |||
| e46316cff8 |
@@ -4,10 +4,10 @@ Lua game inspired by an old arcade game(Qix/Gals Panic) using LOVE2D for Linux.
|
|||||||
|
|
||||||
## TO-DO
|
## TO-DO
|
||||||
|
|
||||||
- Stop player from creating crossed lines
|
|
||||||
|
|
||||||
- Fix creation of the lines / polygon / points
|
- Fix creation of the lines / polygon / points
|
||||||
|
|
||||||
- Add more pictures (manga?)
|
- Add more pictures (manga?)
|
||||||
|
|
||||||
- Fix balls sometimes attaching to the lines
|
- Fix balls sometimes attaching to the lines
|
||||||
|
|
||||||
|
- Add spiders moving around in the board, player collision kills
|
||||||
|
|||||||
5
main.lua
5
main.lua
@@ -65,6 +65,11 @@ function love.keypressed(key)
|
|||||||
push:switchFullscreen()
|
push:switchFullscreen()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if key == 'r' then
|
||||||
|
gStateStack:clear()
|
||||||
|
gStateStack:push(StartState())
|
||||||
|
end
|
||||||
|
|
||||||
love.keyboard.keysPressed[key] = true
|
love.keyboard.keysPressed[key] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
12
src/Ball.lua
12
src/Ball.lua
@@ -22,13 +22,15 @@ function Ball:reset()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Ball:update(dt,level)
|
function Ball:update(dt,level)
|
||||||
local tempX = self.x + self.dx * dt
|
local tempX = math.floor((self.x + self.dx * dt) + 0.5)
|
||||||
local tempY = self.y + self.dy * dt
|
local tempY = math.floor((self.y + self.dy * dt) + 0.5)
|
||||||
|
|
||||||
local trailSeg = level:pointOnEdge(tempX,tempY,level.player.trailSegments)
|
local trailSeg = level:pointOnEdge(tempX,tempY,level.player.trailSegments)
|
||||||
if trailSeg then
|
if trailSeg then
|
||||||
self.hitPlayer = true
|
self.hitPlayer = true
|
||||||
|
-- print("ball hits player")
|
||||||
gSounds['hit']:play()
|
gSounds['hit']:play()
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local i, segment = level:getTouchingSegment(tempX,tempY)
|
local i, segment = level:getTouchingSegment(tempX,tempY)
|
||||||
@@ -49,8 +51,9 @@ function Ball:update(dt,level)
|
|||||||
gSounds['blip']:play()
|
gSounds['blip']:play()
|
||||||
end
|
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
|
self.remove = true
|
||||||
|
print("ball outside or touching segment")
|
||||||
end
|
end
|
||||||
|
|
||||||
self.x = self.x + self.dx * dt
|
self.x = self.x + self.dx * dt
|
||||||
@@ -60,8 +63,9 @@ function Ball:update(dt,level)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Ball:render()
|
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.circle('fill', self.x, self.y, self.width/2)
|
||||||
|
love.graphics.setColor(1,1,1,1)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Ball:getCollisionDirection(segment,x,y)
|
function Ball:getCollisionDirection(segment,x,y)
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ function Clock:render()
|
|||||||
love.graphics.setColor(self.color[1], self.color[2], self.color[3],
|
love.graphics.setColor(self.color[1], self.color[2], self.color[3],
|
||||||
self.color[4])
|
self.color[4])
|
||||||
end
|
end
|
||||||
love.graphics.setFont(gFonts['medium'])
|
love.graphics.setFont(gFonts['small'])
|
||||||
love.graphics.printf('Time: ' .. self.currentTime, 0, 5, VIRTUAL_WIDTH,
|
love.graphics.printf('Time: ' .. self.currentTime, 0, LEVEL_RENDER_OFFSET_TOP/2, VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET,
|
||||||
'right')
|
'right')
|
||||||
love.graphics.setFont(gFonts['small'])
|
love.graphics.setFont(gFonts['small'])
|
||||||
love.graphics.setColor(1, 1, 1, 1)
|
love.graphics.setColor(1, 1, 1, 1)
|
||||||
|
|||||||
482
src/Level.lua
482
src/Level.lua
@@ -5,64 +5,98 @@ function Level:init(def, stage)
|
|||||||
self.stage = stage
|
self.stage = stage
|
||||||
self.points = {}
|
self.points = {}
|
||||||
self.player = {}
|
self.player = {}
|
||||||
self.segments = self:createLevelFromDef(def, stage)
|
self.segments = self:createLevelFromDef(def)
|
||||||
self.polygon = self:createPolygon()
|
self.polygon = self:createPolygon()
|
||||||
self.mesh = poly2mesh(self.points)
|
self.mesh = poly2mesh(self.points)
|
||||||
|
self.balls = self:createBallsFromDef(def)
|
||||||
|
self.clock = Clock(def.timeLimit, "down")
|
||||||
end
|
end
|
||||||
|
|
||||||
function Level:update(dt)
|
function Level:update(dt)
|
||||||
self.mesh = poly2mesh(self.points)
|
self.mesh = poly2mesh(self.points)
|
||||||
|
self:updateBalls(dt)
|
||||||
|
self.clock:update(dt)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Level:render()
|
function Level:render()
|
||||||
self:renderBackground()
|
self:renderBackground()
|
||||||
self:renderOuterSegments()
|
self:renderOuterSegments()
|
||||||
|
self:renderBalls()
|
||||||
|
self.clock:render()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Level:renderOuterSegments()
|
function Level:renderOuterSegments()
|
||||||
for k, segment in pairs(self.segments) do segment:render() end
|
for k, segment in pairs(self.segments) do
|
||||||
end
|
segment:render()
|
||||||
|
|
||||||
function Level:renderBackground()
|
|
||||||
love.graphics.draw(gImages[(self.stage % #gImages)], LEVEL_RENDER_OFFSET,
|
|
||||||
LEVEL_RENDER_OFFSET_TOP)
|
|
||||||
if self.mesh:type() == "Mesh" then
|
|
||||||
love.graphics.draw(self.mesh, 0, 0)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Level:createLevelFromDef(def, stage)
|
function Level:renderBackground()
|
||||||
|
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 = {}
|
local level = {}
|
||||||
for i, seg in pairs(def[1].segments) do
|
for i, seg in pairs(def.segments) do
|
||||||
table.insert(level, Segment(seg.p1, seg.p2, seg.width, seg.face) )
|
table.insert(level, Segment(seg.p1, seg.p2, seg.width, seg.face))
|
||||||
end
|
end
|
||||||
return level
|
return level
|
||||||
end
|
end
|
||||||
|
|
||||||
function Level:createLevel()
|
function Level:createLevel()
|
||||||
local level = {
|
local level = {
|
||||||
[1] = Segment({LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP}, {
|
[1] = Segment(
|
||||||
VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP
|
{LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},
|
||||||
}, .5, 'down'),
|
{
|
||||||
[2] = Segment({
|
VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET,
|
||||||
VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP
|
LEVEL_RENDER_OFFSET_TOP
|
||||||
}, {
|
},
|
||||||
VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET,
|
.5,
|
||||||
VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET
|
"down"
|
||||||
}, .5, 'left'),
|
),
|
||||||
[3] = Segment({
|
[2] = Segment(
|
||||||
VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET,
|
{
|
||||||
VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET
|
VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET,
|
||||||
}, {LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET}, .5, 'up'),
|
LEVEL_RENDER_OFFSET_TOP
|
||||||
[4] = Segment({
|
},
|
||||||
LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET
|
{
|
||||||
}, {LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP}, .5, 'right')
|
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 = {
|
-- local level = {
|
||||||
-- [1] = Segment({LEVEL_RENDER_OFFSET,LEVEL_RENDER_OFFSET_TOP},{VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},.5),
|
-- [1] = Segment({LEVEL_RENDER_OFFSET,LEVEL_RENDER_OFFSET_TOP},{VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},.5),
|
||||||
-- [2] = Segment({VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},{VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},.5),
|
-- [2] = Segment({VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP},{VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},.5),
|
||||||
-- [3] = Segment({VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},{VIRTUAL_WIDTH / 2 + 10, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},.5),
|
-- [3] = Segment({VIRTUAL_WIDTH - LEVEL_RENDER_OFFSET, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},{VIRTUAL_WIDTH / 2 + 10, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},.5),
|
||||||
-- [4] = Segment({VIRTUAL_WIDTH / 2 + 10, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},{VIRTUAL_WIDTH / 2 + 10, VIRTUAL_HEIGHT / 2},.5),
|
-- [4] = Segment({VIRTUAL_WIDTH / 2 + 10, VIRTUAL_HEIGHT - LEVEL_RENDER_OFFSET},{VIRTUAL_WIDTH / 2 + 10, VIRTUAL_HEIGHT / 2},.5),
|
||||||
-- [5] = Segment({VIRTUAL_WIDTH / 2 + 10, VIRTUAL_HEIGHT / 2},{LEVEL_RENDER_OFFSET,VIRTUAL_HEIGHT / 2},.5),
|
-- [5] = Segment({VIRTUAL_WIDTH / 2 + 10, VIRTUAL_HEIGHT / 2},{LEVEL_RENDER_OFFSET,VIRTUAL_HEIGHT / 2},.5),
|
||||||
-- [6] = Segment({LEVEL_RENDER_OFFSET,VIRTUAL_HEIGHT / 2},{LEVEL_RENDER_OFFSET,LEVEL_RENDER_OFFSET_TOP},.5)
|
-- [6] = Segment({LEVEL_RENDER_OFFSET,VIRTUAL_HEIGHT / 2},{LEVEL_RENDER_OFFSET,LEVEL_RENDER_OFFSET_TOP},.5)
|
||||||
-- }
|
-- }
|
||||||
@@ -74,8 +108,10 @@ function Level:insideBounds2(x, y)
|
|||||||
return shape:testPoint(x, y)
|
return shape:testPoint(x, y)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Level:insideBounds(x, y, segments)
|
function Level:insideBounds4(x, y, segments)
|
||||||
if not segments then segments = self.segments end
|
if not segments then
|
||||||
|
segments = self.segments
|
||||||
|
end
|
||||||
|
|
||||||
local up, down, left, right = false
|
local up, down, left, right = false
|
||||||
local upSeg, downSeg, leftSeg, rightSeg = nil
|
local upSeg, downSeg, leftSeg, rightSeg = nil
|
||||||
@@ -84,40 +120,40 @@ function Level:insideBounds(x, y, segments)
|
|||||||
for i, segment in pairs(segments) do
|
for i, segment in pairs(segments) do
|
||||||
-- check raycast on y axis
|
-- check raycast on y axis
|
||||||
if segment.vertical then
|
if segment.vertical then
|
||||||
if y <= math.max(segment.firstPointY, segment.secondPointY) and y >=
|
if
|
||||||
math.min(segment.firstPointY, segment.secondPointY) then
|
y <= math.max(segment.firstPointY, segment.secondPointY) and
|
||||||
|
y >= math.min(segment.firstPointY, segment.secondPointY)
|
||||||
|
then
|
||||||
if x <= segment.firstPointX then
|
if x <= segment.firstPointX then
|
||||||
if not rightSeg then
|
if not rightSeg then
|
||||||
rightSeg = segment
|
rightSeg = segment
|
||||||
elseif math.abs(segment.firstPointX - x) <
|
elseif math.abs(segment.firstPointX - x) < math.abs(rightSeg.firstPointX - x) then
|
||||||
math.abs(rightSeg.firstPointX - x) then
|
|
||||||
rightSeg = segment
|
rightSeg = segment
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if not leftSeg then
|
if not leftSeg then
|
||||||
leftSeg = segment
|
leftSeg = segment
|
||||||
elseif math.abs(segment.firstPointX - x) <
|
elseif math.abs(segment.firstPointX - x) < math.abs(leftSeg.firstPointX - x) then
|
||||||
math.abs(leftSeg.firstPointX - x) then
|
|
||||||
leftSeg = segment
|
leftSeg = segment
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if segment.horizontal then
|
if segment.horizontal then
|
||||||
if x <= math.max(segment.firstPointX, segment.secondPointX) and x >=
|
if
|
||||||
math.min(segment.firstPointX, segment.secondPointX) then
|
x <= math.max(segment.firstPointX, segment.secondPointX) and
|
||||||
|
x >= math.min(segment.firstPointX, segment.secondPointX)
|
||||||
|
then
|
||||||
if y <= segment.firstPointY then
|
if y <= segment.firstPointY then
|
||||||
if not downSeg then
|
if not downSeg then
|
||||||
downSeg = segment
|
downSeg = segment
|
||||||
elseif math.abs(segment.firstPointY - y) <
|
elseif math.abs(segment.firstPointY - y) < math.abs(downSeg.firstPointY - y) then
|
||||||
math.abs(downSeg.firstPointY - y) then
|
|
||||||
downSeg = segment
|
downSeg = segment
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if not upSeg then
|
if not upSeg then
|
||||||
upSeg = segment
|
upSeg = segment
|
||||||
elseif math.abs(segment.firstPointY - y) <
|
elseif math.abs(segment.firstPointY - y) < math.abs(upSeg.firstPointY - y) then
|
||||||
math.abs(upSeg.firstPointY - y) then
|
|
||||||
upSeg = segment
|
upSeg = segment
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -125,11 +161,15 @@ function Level:insideBounds(x, y, segments)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not rightSeg or not leftSeg or not upSeg or not downSeg then
|
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
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
if rightSeg.face ~= 'left' or leftSeg.face ~= 'right' or upSeg.face ~=
|
|
||||||
'down' or downSeg.face ~= 'up' then return false end
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -140,18 +180,51 @@ function Level:insideBounds3(x, y)
|
|||||||
local j = #self.polygon
|
local j = #self.polygon
|
||||||
local polygon = self.polygon
|
local polygon = self.polygon
|
||||||
for i = 1, #polygon do
|
for i = 1, #polygon do
|
||||||
if (polygon[i].y < y and polygon[j].y >= y or polygon[j].y < y and
|
if (polygon[i].y < y and polygon[j].y >= y or polygon[j].y < y and polygon[i].y >= y) then
|
||||||
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
|
||||||
if (polygon[i].x + (y - polygon[i].y) /
|
oddNodes = not oddNodes
|
||||||
(polygon[j].y - polygon[i].y) * (polygon[j].x - polygon[i].x) <
|
end
|
||||||
x) then oddNodes = not oddNodes end
|
|
||||||
end
|
end
|
||||||
j = i
|
j = i
|
||||||
end
|
end
|
||||||
return oddNodes
|
return oddNodes
|
||||||
end
|
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()
|
function Level:createPolygon()
|
||||||
|
if #self.segments > 5 then
|
||||||
|
print("Level:createPolygon")
|
||||||
|
print_r(self.segments)
|
||||||
|
end
|
||||||
local polygon = {}
|
local polygon = {}
|
||||||
local polygonPoints = {}
|
local polygonPoints = {}
|
||||||
local pointlist = {}
|
local pointlist = {}
|
||||||
@@ -159,16 +232,16 @@ function Level:createPolygon()
|
|||||||
for i, segment in ipairs(self.segments) do
|
for i, segment in ipairs(self.segments) do
|
||||||
polygon[i] = {}
|
polygon[i] = {}
|
||||||
polygon[i + 1] = {}
|
polygon[i + 1] = {}
|
||||||
polygon[i].x, polygon[i].y, polygon[i + 1].x, polygon[i + 1].y =
|
polygon[i].x, polygon[i].y, polygon[i + 1].x, polygon[i + 1].y = segment:segmentToPoints()
|
||||||
segment:segmentToPoints()
|
|
||||||
polygonPoints[j] = polygon[i].x
|
polygonPoints[j] = polygon[i].x
|
||||||
polygonPoints[j + 1] = polygon[i].y
|
polygonPoints[j + 1] = polygon[i].y
|
||||||
polygonPoints[j + 2] = polygon[i + 1].x
|
polygonPoints[j + 2] = polygon[i + 1].x
|
||||||
polygonPoints[j + 3] = polygon[i + 1].y
|
polygonPoints[j + 3] = polygon[i + 1].y
|
||||||
|
|
||||||
table.insert(pointlist, polygon[i].x)
|
if polygon[i + 1].x ~= polygon[i].x or polygon[i + 1].y ~= polygon[i].y then
|
||||||
table.insert(pointlist, polygon[i].y)
|
table.insert(pointlist, polygon[i].x)
|
||||||
|
table.insert(pointlist, polygon[i].y)
|
||||||
|
end
|
||||||
j = j + 4
|
j = j + 4
|
||||||
i = i + 1
|
i = i + 1
|
||||||
end
|
end
|
||||||
@@ -178,25 +251,30 @@ function Level:createPolygon()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Level:pointOnEdge(x, y, segments)
|
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
|
local margin = 2
|
||||||
for i, segment in pairs(segments) do
|
for i, segment in pairs(segments) do
|
||||||
if segment.vertical then -- vertical line
|
if segment.vertical then -- vertical line
|
||||||
if x >= segment.firstPointX - margin and x <= segment.firstPointX +
|
if
|
||||||
margin and y <=
|
x >= segment.firstPointX - margin and x <= segment.firstPointX + margin and
|
||||||
math.max(segment.firstPointY, segment.secondPointY) and y >=
|
y <= math.max(segment.firstPointY, segment.secondPointY) and
|
||||||
math.min(segment.firstPointY, segment.secondPointY) then
|
y >= math.min(segment.firstPointY, segment.secondPointY)
|
||||||
|
then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
elseif segment.horizontal then -- horizontal line
|
elseif segment.horizontal then -- horizontal line
|
||||||
if y >= segment.firstPointY - margin and y <= segment.firstPointY +
|
if
|
||||||
margin and x <=
|
y >= segment.firstPointY - margin and y <= segment.firstPointY + margin and
|
||||||
math.max(segment.firstPointX, segment.secondPointX) and x >=
|
x <= math.max(segment.firstPointX, segment.secondPointX) and
|
||||||
math.min(segment.firstPointX, segment.secondPointX) then
|
x >= math.min(segment.firstPointX, segment.secondPointX)
|
||||||
|
then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
-- print("ball pointOnEdge is false")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -204,17 +282,19 @@ function Level:getTouchingSegment(x, y)
|
|||||||
local margin = 2
|
local margin = 2
|
||||||
for i, segment in pairs(self.segments) do
|
for i, segment in pairs(self.segments) do
|
||||||
if segment.vertical then -- vertical line
|
if segment.vertical then -- vertical line
|
||||||
if x >= segment.firstPointX - margin and x <= segment.firstPointX +
|
if
|
||||||
margin and y <=
|
x >= segment.firstPointX - margin and x <= segment.firstPointX + margin and
|
||||||
math.max(segment.firstPointY, segment.secondPointY) and y >=
|
y <= math.max(segment.firstPointY, segment.secondPointY) and
|
||||||
math.min(segment.firstPointY, segment.secondPointY) then
|
y >= math.min(segment.firstPointY, segment.secondPointY)
|
||||||
|
then
|
||||||
return i, segment
|
return i, segment
|
||||||
end
|
end
|
||||||
elseif segment.horizontal then -- horizontal line
|
elseif segment.horizontal then -- horizontal line
|
||||||
if y >= segment.firstPointY - margin and y <= segment.firstPointY +
|
if
|
||||||
margin and x <=
|
y >= segment.firstPointY - margin and y <= segment.firstPointY + margin and
|
||||||
math.max(segment.firstPointX, segment.secondPointX) and x >=
|
x <= math.max(segment.firstPointX, segment.secondPointX) and
|
||||||
math.min(segment.firstPointX, segment.secondPointX) then
|
x >= math.min(segment.firstPointX, segment.secondPointX)
|
||||||
|
then
|
||||||
return i, segment
|
return i, segment
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -223,15 +303,12 @@ function Level:getTouchingSegment(x, y)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Level:cutLevel()
|
function Level:cutLevel()
|
||||||
|
|
||||||
local newSegs = self.player.trailSegments
|
local newSegs = self.player.trailSegments
|
||||||
local startSegi, startSeg = self.player.trailStartSegment[1],
|
local startSegi, startSeg = self.player.trailStartSegment[1], self.player.trailStartSegment[2]
|
||||||
self.player.trailStartSegment[2]
|
local endSegi, endSeg = self.player.trailFinishSegment[1], self.player.trailFinishSegment[2]
|
||||||
local endSegi, endSeg = self.player.trailFinishSegment[1],
|
|
||||||
self.player.trailFinishSegment[2]
|
|
||||||
local first = 0
|
local first = 0
|
||||||
local last = 0
|
local last = 0
|
||||||
local firstFace = ''
|
local firstFace = ""
|
||||||
|
|
||||||
-- check if it is same start and finish segment
|
-- check if it is same start and finish segment
|
||||||
if startSegi == endSegi then
|
if startSegi == endSegi then
|
||||||
@@ -259,15 +336,16 @@ function Level:cutLevel()
|
|||||||
while k <= #self.segments do
|
while k <= #self.segments do
|
||||||
-- print(" segment to be inserted "..tostring(k))
|
-- print(" segment to be inserted "..tostring(k))
|
||||||
if k == startSegi and not insertedNewSegs then
|
if k == startSegi and not insertedNewSegs then
|
||||||
|
-- print_r(new)
|
||||||
|
-- print("-- finished inserting new segments and parts")
|
||||||
-- print("Reached the segment being cut")
|
-- print("Reached the segment being cut")
|
||||||
-- print_r(self.segments[k])
|
-- print_r(self.segments[k])
|
||||||
-- print("split the segment")
|
-- print("split the segment")
|
||||||
part1, temp, part2 = self.segments[k]:splitInThreeWithSegments(
|
part1, temp, part2 = self.segments[k]:splitInThreeWithSegments(newSegs[1], newSegs[#newSegs])
|
||||||
newSegs[1], newSegs[#newSegs])
|
|
||||||
-- print("part1")
|
-- print("part1")
|
||||||
part1:debug()
|
-- part1:debug()
|
||||||
-- print("part2")
|
-- print("part2")
|
||||||
part2:debug()
|
-- part2:debug()
|
||||||
|
|
||||||
-- print("insert first part")
|
-- print("insert first part")
|
||||||
new[j] = part1
|
new[j] = part1
|
||||||
@@ -285,8 +363,6 @@ function Level:cutLevel()
|
|||||||
insertedNewSegments = true
|
insertedNewSegments = true
|
||||||
new[j] = part2
|
new[j] = part2
|
||||||
j = j + 1
|
j = j + 1
|
||||||
-- print_r(new)
|
|
||||||
-- print("-- finished inserting new segments and parts")
|
|
||||||
else
|
else
|
||||||
new[j] = self.segments[k]:copy()
|
new[j] = self.segments[k]:copy()
|
||||||
j = j + 1
|
j = j + 1
|
||||||
@@ -318,20 +394,21 @@ function Level:cutLevel()
|
|||||||
-- print("-----start Loop for "..tostring(k).."-----")
|
-- print("-----start Loop for "..tostring(k).."-----")
|
||||||
if k == startSegi and not insertedNewSegments then
|
if k == startSegi and not insertedNewSegments then
|
||||||
board2StartSegi = k
|
board2StartSegi = k
|
||||||
-- print("-- this segment is the start segment and not inserted new segments yet")
|
-- print("-- this segment is the start segment and not inserted new segments yet")
|
||||||
-- print("newsegs[1] is joined perpendicular to k segment:")
|
-- print("newsegs[1] is joined perpendicular to k segment:")
|
||||||
newSegs[1]:debug()
|
newSegs[1]:debug()
|
||||||
newSegs[1]:joinPerpendicular(self.segments[k])
|
newSegs[1]:joinPerpendicular(self.segments[k])
|
||||||
newSegs[1]:debug()
|
newSegs[1]:debug()
|
||||||
-- print("newSegs[1] is joined -- finished")
|
-- print("newSegs[1] is joined -- finished")
|
||||||
local startPart1, startPart2 =
|
local startPart1, startPart2 = self.segments[k]:splitInTwoWithSegment(newSegs[1])
|
||||||
self.segments[k]:splitInTwoWithSegment(newSegs[1])
|
|
||||||
-- print("-- Segment k split into 2 segments by newsegs[1]: ")
|
-- print("-- Segment k split into 2 segments by newsegs[1]: ")
|
||||||
startPart1:debug()
|
startPart1:debug()
|
||||||
startPart2:debug()
|
startPart2:debug()
|
||||||
|
|
||||||
if self.segments[last]:endEqualsStartOf(self.segments[k]) or
|
if
|
||||||
self.segments[last]:startEqualsStartOf(self.segments[k]) then -- last one is linked to the start of this one
|
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
|
-- keep first part of segment
|
||||||
-- print("-- keep first part of the k segment")
|
-- print("-- keep first part of the k segment")
|
||||||
self.segments[k] = startPart1
|
self.segments[k] = startPart1
|
||||||
@@ -348,7 +425,7 @@ function Level:cutLevel()
|
|||||||
-- print("-- before checking for inserted new segments - Board1")
|
-- print("-- before checking for inserted new segments - Board1")
|
||||||
-- print_r(board1)
|
-- print_r(board1)
|
||||||
if not insertedNewSegments then
|
if not insertedNewSegments then
|
||||||
k = endSegi -- skip to last segment to cut and insert it as well
|
k = endSegi -- skip to last segment to cut and insert it as well
|
||||||
last = k - 1
|
last = k - 1
|
||||||
board2EndSegi = k
|
board2EndSegi = k
|
||||||
newSegs[#newSegs]:joinPerpendicular(self.segments[k])
|
newSegs[#newSegs]:joinPerpendicular(self.segments[k])
|
||||||
@@ -360,18 +437,19 @@ function Level:cutLevel()
|
|||||||
end
|
end
|
||||||
-- print_r(board1)
|
-- print_r(board1)
|
||||||
|
|
||||||
local endPart1, endPart2 =
|
local endPart1, endPart2 = self.segments[k]:splitInTwoWithSegment(newSegs[#newSegs])
|
||||||
self.segments[k]:splitInTwoWithSegment(newSegs[#newSegs])
|
|
||||||
-- print("-- proceed to insert the second split segment")
|
-- print("-- proceed to insert the second split segment")
|
||||||
if self.segments[last]:endEqualsEndOf(self.segments[k]) or
|
if
|
||||||
self.segments[last]:startEqualsEndOf(self.segments[k]) then -- next one is linked to the start of this one
|
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
|
self.segments[k] = endPart1
|
||||||
savedEnd = endPart2
|
savedEnd = endPart2
|
||||||
-- print("-- keep first part of the k segment")
|
|
||||||
else
|
else
|
||||||
|
-- print("-- keep second part of the k segment")
|
||||||
self.segments[k] = endPart2
|
self.segments[k] = endPart2
|
||||||
savedEnd = endPart1
|
savedEnd = endPart1
|
||||||
-- print("-- keep second part of the k segment")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
board1[j] = self.segments[k]:copy()
|
board1[j] = self.segments[k]:copy()
|
||||||
@@ -381,20 +459,21 @@ function Level:cutLevel()
|
|||||||
end
|
end
|
||||||
elseif k == endSegi and not insertedNewSegments then
|
elseif k == endSegi and not insertedNewSegments then
|
||||||
board2StartSegi = k
|
board2StartSegi = k
|
||||||
-- print("-- this segment is the end segment and not inserted new segments yet")
|
-- print("-- this segment is the end segment and not inserted new segments yet")
|
||||||
-- print("newsegs[#newSegs] is joined perpendicular to k segment:")
|
-- print("newsegs[#newSegs] is joined perpendicular to k segment:")
|
||||||
newSegs[#newSegs]:debug()
|
newSegs[#newSegs]:debug()
|
||||||
newSegs[#newSegs]:joinPerpendicular(self.segments[k])
|
newSegs[#newSegs]:joinPerpendicular(self.segments[k])
|
||||||
newSegs[#newSegs]:debug()
|
newSegs[#newSegs]:debug()
|
||||||
-- print("newSegs[#newSegs] is joined -- finished")
|
-- print("newSegs[#newSegs] is joined -- finished")
|
||||||
local endPart1, endPart2 =
|
local endPart1, endPart2 = self.segments[k]:splitInTwoWithSegment(newSegs[#newSegs])
|
||||||
self.segments[k]:splitInTwoWithSegment(newSegs[#newSegs])
|
|
||||||
-- print("-- Segment k split into 2 segments by newsegs[#newSegs]: ")
|
-- print("-- Segment k split into 2 segments by newsegs[#newSegs]: ")
|
||||||
endPart1:debug()
|
endPart1:debug()
|
||||||
endPart2:debug()
|
endPart2:debug()
|
||||||
|
|
||||||
if self.segments[last]:endEqualsStartOf(self.segments[k]) or
|
if
|
||||||
self.segments[last]:startEqualsStartOf(self.segments[k]) then -- last one is linked to the start of this one
|
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
|
-- keep first part of segment
|
||||||
self.segments[k] = endPart1
|
self.segments[k] = endPart1
|
||||||
savedEnd = endPart2
|
savedEnd = endPart2
|
||||||
@@ -407,7 +486,7 @@ function Level:cutLevel()
|
|||||||
j = j + 1
|
j = j + 1
|
||||||
|
|
||||||
if not insertedNewSegments then
|
if not insertedNewSegments then
|
||||||
k = startSegi -- skip to last segment to cut and insert it as well
|
k = startSegi -- skip to last segment to cut and insert it as well
|
||||||
last = k - 1
|
last = k - 1
|
||||||
board2EndSegi = k
|
board2EndSegi = k
|
||||||
newSegs[1]:joinPerpendicular(self.segments[k])
|
newSegs[1]:joinPerpendicular(self.segments[k])
|
||||||
@@ -422,14 +501,15 @@ function Level:cutLevel()
|
|||||||
end
|
end
|
||||||
-- print_r(board1)
|
-- print_r(board1)
|
||||||
|
|
||||||
local startPart1, startPart2 =
|
local startPart1, startPart2 = self.segments[k]:splitInTwoWithSegment(newSegs[1])
|
||||||
self.segments[k]:splitInTwoWithSegment(newSegs[1])
|
|
||||||
-- print("-- Segment k split into 2 segments by newsegs[1]: ")
|
-- print("-- Segment k split into 2 segments by newsegs[1]: ")
|
||||||
startPart1:debug()
|
startPart1:debug()
|
||||||
startPart2:debug()
|
startPart2:debug()
|
||||||
|
|
||||||
if self.segments[last]:endEqualsEndOf(self.segments[k]) or
|
if
|
||||||
self.segments[last]:startEqualsEndOf(self.segments[k]) then -- next one is linked to the start of this one
|
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
|
self.segments[k] = startPart1
|
||||||
savedstart = startPart2
|
savedstart = startPart2
|
||||||
else
|
else
|
||||||
@@ -442,7 +522,6 @@ function Level:cutLevel()
|
|||||||
-- print_r(board1)
|
-- print_r(board1)
|
||||||
insertedNewSegments = true
|
insertedNewSegments = true
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif k ~= startSegi and k ~= endSegi then
|
elseif k ~= startSegi and k ~= endSegi then
|
||||||
board1[j] = self.segments[k]:copy()
|
board1[j] = self.segments[k]:copy()
|
||||||
j = j + 1
|
j = j + 1
|
||||||
@@ -461,6 +540,7 @@ function Level:cutLevel()
|
|||||||
-- print('---- Create Second board from '..tostring(board2StartSegi)..' to '..tostring(board2EndSegi))
|
-- print('---- Create Second board from '..tostring(board2StartSegi)..' to '..tostring(board2EndSegi))
|
||||||
j = 1
|
j = 1
|
||||||
if board2StartSegi < board2EndSegi then
|
if board2StartSegi < board2EndSegi then
|
||||||
|
-- print_r(board2)
|
||||||
board2[j] = savedStart
|
board2[j] = savedStart
|
||||||
j = j + 1
|
j = j + 1
|
||||||
-- print_r(board2)
|
-- print_r(board2)
|
||||||
@@ -485,9 +565,9 @@ function Level:cutLevel()
|
|||||||
board2[j] = newseg:copy()
|
board2[j] = newseg:copy()
|
||||||
j = j + 1
|
j = j + 1
|
||||||
end
|
end
|
||||||
-- print_r(board2)
|
|
||||||
|
|
||||||
else
|
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')
|
-- print('-- inserted first segment, proceed with skipped segments in first board, end < start')
|
||||||
board2[j] = savedEnd
|
board2[j] = savedEnd
|
||||||
j = j + 1
|
j = j + 1
|
||||||
@@ -515,8 +595,6 @@ function Level:cutLevel()
|
|||||||
j = j + 1
|
j = j + 1
|
||||||
i = i - 1
|
i = i - 1
|
||||||
end
|
end
|
||||||
-- print('-- inserted new segments, final board2 before ordering')
|
|
||||||
-- print_r(board2)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- print("order segments in cutlevel board2")
|
-- print("order segments in cutlevel board2")
|
||||||
@@ -525,17 +603,16 @@ function Level:cutLevel()
|
|||||||
-- print("PREPARE BOARD 2 -- FINAL")
|
-- print("PREPARE BOARD 2 -- FINAL")
|
||||||
-- print_r(board2)
|
-- print_r(board2)
|
||||||
|
|
||||||
if self:containsBalls(board1) == 0 then
|
local b1balls = self:containsBalls(board1)
|
||||||
self.segments = board2
|
local b2balls = self:containsBalls(board2)
|
||||||
elseif self:containsBalls(board2) == 0 then
|
if b1balls > b2balls then
|
||||||
self.segments = board1
|
self.segments = board1
|
||||||
else
|
else
|
||||||
self.segments = self:getPerimeter(board1) >
|
self.segments = board2
|
||||||
self:getPerimeter(board2) and board1 or board2
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self:createPolygon()
|
self.polygon = self:createPolygon()
|
||||||
self.mesh = poly2mesh(self.points)
|
self.mesh = poly2mesh(self.points)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -563,8 +640,7 @@ function Level:orderSegments(segs)
|
|||||||
|
|
||||||
-- -- print("new[i] end equals start of ")
|
-- -- print("new[i] end equals start of ")
|
||||||
-- s:debug()
|
-- s:debug()
|
||||||
if new[i].vertical == s.vertical and new[i].horizontal ==
|
if new[i].vertical == s.vertical and new[i].horizontal == s.horizontal then
|
||||||
s.horizontal then
|
|
||||||
-- -- print("join contiguous "..tostring(i).. 'with'..tostring(j))
|
-- -- print("join contiguous "..tostring(i).. 'with'..tostring(j))
|
||||||
new[i]:joinContiguous(s)
|
new[i]:joinContiguous(s)
|
||||||
table.remove(segs, j)
|
table.remove(segs, j)
|
||||||
@@ -584,8 +660,7 @@ function Level:orderSegments(segs)
|
|||||||
-- -- print("new[i] end equals end of ")
|
-- -- print("new[i] end equals end of ")
|
||||||
-- s:debug()
|
-- s:debug()
|
||||||
s:switchDirection()
|
s:switchDirection()
|
||||||
if new[i].vertical == s.vertical and new[i].horizontal ==
|
if new[i].vertical == s.vertical and new[i].horizontal == s.horizontal then
|
||||||
s.horizontal then
|
|
||||||
-- -- print("join contiguous "..tostring(i).. 'with'..tostring(j))
|
-- -- print("join contiguous "..tostring(i).. 'with'..tostring(j))
|
||||||
new[i]:joinContiguous(s)
|
new[i]:joinContiguous(s)
|
||||||
table.remove(segs, j)
|
table.remove(segs, j)
|
||||||
@@ -608,14 +683,10 @@ function Level:orderSegments(segs)
|
|||||||
-- -- print("search didnt yield any segment")
|
-- -- print("search didnt yield any segment")
|
||||||
local margin = 2
|
local margin = 2
|
||||||
while not found and margin < 5 do
|
while not found and margin < 5 do
|
||||||
fi, fs = self:findNearestSegment(new[i].secondPointX,
|
fi, fs = self:findNearestSegment(new[i].secondPointX, new[i].secondPointY, segs, margin)
|
||||||
new[i].secondPointY, segs,
|
|
||||||
margin)
|
|
||||||
|
|
||||||
if not fs then
|
if not fs then
|
||||||
fi, fs = self:findNearestSegment(new[i].firstPointX,
|
fi, fs = self:findNearestSegment(new[i].firstPointX, new[i].firstPointY, segs, margin)
|
||||||
new[i].firstPointY, segs,
|
|
||||||
margin)
|
|
||||||
|
|
||||||
if not fs then
|
if not fs then
|
||||||
margin = margin + 1
|
margin = margin + 1
|
||||||
@@ -662,60 +733,60 @@ function Level:calculateSegmentFaces(segments, firstFace)
|
|||||||
for k, s in ipairs(segments) do
|
for k, s in ipairs(segments) do
|
||||||
s.face = face
|
s.face = face
|
||||||
if k + 1 <= #segments then
|
if k + 1 <= #segments then
|
||||||
if face == 'up' then
|
if face == "up" then
|
||||||
if s.direction == 'right' then
|
if s.direction == "right" then
|
||||||
if segments[k + 1].direction == 'up' then
|
if segments[k + 1].direction == "up" then
|
||||||
face = 'left'
|
face = "left"
|
||||||
else
|
else
|
||||||
face = 'right'
|
face = "right"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if segments[k + 1].direction == 'up' then
|
if segments[k + 1].direction == "up" then
|
||||||
face = 'right'
|
face = "right"
|
||||||
else
|
else
|
||||||
face = 'left'
|
face = "left"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif face == 'down' then
|
elseif face == "down" then
|
||||||
if s.direction == 'right' then
|
if s.direction == "right" then
|
||||||
if segments[k + 1].direction == 'up' then
|
if segments[k + 1].direction == "up" then
|
||||||
face = 'right'
|
face = "right"
|
||||||
else
|
else
|
||||||
face = 'left'
|
face = "left"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if segments[k + 1].direction == 'up' then
|
if segments[k + 1].direction == "up" then
|
||||||
face = 'left'
|
face = "left"
|
||||||
else
|
else
|
||||||
face = 'right'
|
face = "right"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif face == 'right' then
|
elseif face == "right" then
|
||||||
if s.direction == 'up' then
|
if s.direction == "up" then
|
||||||
if segments[k + 1].direction == 'right' then
|
if segments[k + 1].direction == "right" then
|
||||||
face = 'down'
|
face = "down"
|
||||||
else
|
else
|
||||||
face = 'up'
|
face = "up"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if segments[k + 1].direction == 'right' then
|
if segments[k + 1].direction == "right" then
|
||||||
face = 'up'
|
face = "up"
|
||||||
else
|
else
|
||||||
face = 'down'
|
face = "down"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif face == 'left' then
|
elseif face == "left" then
|
||||||
if s.direction == 'up' then
|
if s.direction == "up" then
|
||||||
if segments[k + 1].direction == 'right' then
|
if segments[k + 1].direction == "right" then
|
||||||
face = 'up'
|
face = "up"
|
||||||
else
|
else
|
||||||
face = 'down'
|
face = "down"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if segments[k + 1].direction == 'right' then
|
if segments[k + 1].direction == "right" then
|
||||||
face = 'down'
|
face = "down"
|
||||||
else
|
else
|
||||||
face = 'up'
|
face = "up"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -725,28 +796,38 @@ end
|
|||||||
|
|
||||||
function Level:getPerimeter(segments)
|
function Level:getPerimeter(segments)
|
||||||
local p = 0
|
local p = 0
|
||||||
if not segments then segments = self.segments end
|
if not segments then
|
||||||
for k, s in pairs(segments) do p = p + s:length() end
|
segments = self.segments
|
||||||
|
end
|
||||||
|
for k, s in pairs(segments) do
|
||||||
|
p = p + s:length()
|
||||||
|
end
|
||||||
return p
|
return p
|
||||||
end
|
end
|
||||||
|
|
||||||
function Level:findNearestSegment(x, y, segments, margin)
|
function Level:findNearestSegment(x, y, segments, margin)
|
||||||
if not segments then segments = self.segments end
|
if not segments then
|
||||||
if not margin then margin = 2 end
|
segments = self.segments
|
||||||
|
end
|
||||||
|
if not margin then
|
||||||
|
margin = 2
|
||||||
|
end
|
||||||
-- find a touching segment within margins
|
-- find a touching segment within margins
|
||||||
for i, segment in pairs(segments) do
|
for i, segment in pairs(segments) do
|
||||||
if segment.vertical then -- vertical line
|
if segment.vertical then -- vertical line
|
||||||
if x >= segment.firstPointX - margin and x <= segment.firstPointX +
|
if
|
||||||
margin and y <=
|
x >= segment.firstPointX - margin and x <= segment.firstPointX + margin and
|
||||||
math.max(segment.firstPointY, segment.secondPointY) and y >=
|
y <= math.max(segment.firstPointY, segment.secondPointY) and
|
||||||
math.min(segment.firstPointY, segment.secondPointY) then
|
y >= math.min(segment.firstPointY, segment.secondPointY)
|
||||||
|
then
|
||||||
return i, segment
|
return i, segment
|
||||||
end
|
end
|
||||||
elseif segment.horizontal then -- horizontal line
|
elseif segment.horizontal then -- horizontal line
|
||||||
if y >= segment.firstPointY - margin and y <= segment.firstPointY +
|
if
|
||||||
margin and x <=
|
y >= segment.firstPointY - margin and y <= segment.firstPointY + margin and
|
||||||
math.max(segment.firstPointX, segment.secondPointX) and x >=
|
x <= math.max(segment.firstPointX, segment.secondPointX) and
|
||||||
math.min(segment.firstPointX, segment.secondPointX) then
|
x >= math.min(segment.firstPointX, segment.secondPointX)
|
||||||
|
then
|
||||||
return i, segment
|
return i, segment
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -755,15 +836,62 @@ function Level:findNearestSegment(x, y, segments, margin)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Level:containsBalls(segments)
|
function Level:containsBalls(segments)
|
||||||
-- returns numbere of balls inside the bounds passed in or self.segments
|
-- returns number of balls inside the bounds passed in or self.segments
|
||||||
if not segments then segments = self.segments end
|
if not segments then
|
||||||
|
segments = self.segments
|
||||||
|
end
|
||||||
local counter = 0
|
local counter = 0
|
||||||
|
|
||||||
for k, b in pairs(self.balls) do
|
for k, b in pairs(self.balls) do
|
||||||
if self:insideBounds(b.x + 4, b.y + 4, segments) or
|
if self:insideBounds(b.x + 4, b.y + 4, segments) or self:pointOnEdge(b.x + 4, b.y + 4, seegments) then
|
||||||
self:pointOnEdge(b.x + 4, b.y + 4, seegments) then
|
|
||||||
counter = counter + 1
|
counter = counter + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return counter
|
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
|
end
|
||||||
|
|||||||
@@ -98,7 +98,6 @@ function Player:onEdge()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Player:onWalking()
|
function Player:onWalking()
|
||||||
-- if position of player collides with its own trail, stop motion
|
|
||||||
if #self.trail > 1 then
|
if #self.trail > 1 then
|
||||||
table.remove(self.trail)
|
table.remove(self.trail)
|
||||||
table.remove(self.trailSegments)
|
table.remove(self.trailSegments)
|
||||||
|
|||||||
@@ -171,14 +171,14 @@ end
|
|||||||
|
|
||||||
function Segment:joinPerpendicular(s)
|
function Segment:joinPerpendicular(s)
|
||||||
-- changes the self, not the parameter
|
-- changes the self, not the parameter
|
||||||
if s.vertical then
|
if s.vertical and self.horizontal then
|
||||||
local sx = s.firstPointX
|
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
|
self.firstPointX = sx
|
||||||
else
|
else
|
||||||
self.secondPointX = sx
|
self.secondPointX = sx
|
||||||
end
|
end
|
||||||
else
|
elseif s.horizontal and self.vertical then
|
||||||
local sy = s.firstPointY
|
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
|
self.firstPointY = sy
|
||||||
|
|||||||
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
|
-- convert a list of points forming a polygon {x1, y1, x2, y2, ...} into a mesh
|
||||||
|
|
||||||
function poly2mesh(points)
|
function poly2mesh(points)
|
||||||
-- remove duplicates???
|
-- print("util - poly2mesh: ")
|
||||||
|
-- print_r(points)
|
||||||
if #points > 2 then
|
if #points > 2 then
|
||||||
local polypts = love.math.triangulate(points)
|
local polypts = love.math.triangulate(points)
|
||||||
local tlist
|
local tlist
|
||||||
@@ -119,3 +120,155 @@ function poly2mesh(points)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
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
|
||||||
@@ -75,5 +75,207 @@ LEVELS_DEF = {
|
|||||||
face = 'right'
|
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)
|
function EntityWalkEdgeState:update(dt)
|
||||||
|
|
||||||
local dy = self.entity.walkingSpeed * dt
|
local dy = math.floor(self.entity.walkingSpeed * dt + 0.5)
|
||||||
local dx = self.entity.walkingSpeed * dt
|
local dx = math.floor(self.entity.walkingSpeed * dt + 0.5)
|
||||||
|
|
||||||
if self.entity.direction == 'left' then
|
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
|
if self.entity.level:pointOnEdge(self.entity.x - dx + TILE_SIZE / 2, self.entity.y + TILE_SIZE / 2) then
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
-- require('mobdebug').start()
|
-- require('mobdebug').start()
|
||||||
|
|
||||||
PlayState = Class{__includes = BaseState}
|
PlayState = Class {__includes = BaseState}
|
||||||
|
|
||||||
function PlayState:init()
|
function PlayState:init()
|
||||||
self.name = 'PlayState'
|
self.name = "PlayState"
|
||||||
self.stage = 1
|
self.stage = 1
|
||||||
self.level = Level(LEVELS_DEF, self.stage)
|
self.level = Level(LEVELS_DEF[1], self.stage)
|
||||||
self.player = Player ( ENTITY_DEFS['player'] , self.level)
|
self.player = Player(ENTITY_DEFS["player"], self.level)
|
||||||
self.level.player = self.player
|
self.level.player = self.player
|
||||||
self.balls = {}
|
self.balls = self.level.balls
|
||||||
self:createBalls()
|
self.clock = self.level.clock
|
||||||
self.level.balls = self.balls
|
|
||||||
self.clock = Clock(30,"down")
|
|
||||||
|
|
||||||
gSounds['music']:setLooping(true)
|
|
||||||
gSounds['music']:play()
|
|
||||||
|
|
||||||
|
gSounds["music"]:setPitch(1)
|
||||||
|
gSounds["music"]:setLooping(true)
|
||||||
|
gSounds["music"]:play()
|
||||||
end
|
end
|
||||||
|
|
||||||
function PlayState:enter()
|
function PlayState:enter()
|
||||||
@@ -24,107 +22,106 @@ end
|
|||||||
function PlayState:update(dt)
|
function PlayState:update(dt)
|
||||||
self.level:update(dt)
|
self.level:update(dt)
|
||||||
self.player:update(dt)
|
self.player:update(dt)
|
||||||
self.clock:update(dt)
|
|
||||||
self:updateBalls(dt, self.level)
|
|
||||||
self:checkEndLevel(self.level)
|
self:checkEndLevel(self.level)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PlayState:render()
|
function PlayState:render()
|
||||||
love.graphics.clear(0, 0, 0, 255/255)
|
love.graphics.clear(0, 0, 0, 255 / 255)
|
||||||
love.graphics.setColor(40/255, 45/255, 52/255,255/255)
|
love.graphics.setColor(56 / 255, 56 / 255, 56 / 255, 1)
|
||||||
|
|
||||||
love.graphics.setFont(gFonts['small'])
|
love.graphics.setFont(gFonts["small"])
|
||||||
love.graphics.printf('Score '..tostring(self.player.score),
|
love.graphics.printf("Score " .. tostring(self.player.score), LEVEL_RENDER_OFFSET, LEVEL_RENDER_OFFSET_TOP/2, VIRTUAL_WIDTH, "left")
|
||||||
0, 5, VIRTUAL_WIDTH, 'left')
|
|
||||||
|
|
||||||
love.graphics.setFont(gFonts['medium'])
|
love.graphics.setFont(gFonts["medium"])
|
||||||
love.graphics.printf('Stage '..tostring(self.stage),
|
love.graphics.printf("Stage " .. tostring(self.stage), 0, 5, VIRTUAL_WIDTH, "center")
|
||||||
0, 5, VIRTUAL_WIDTH, 'center')
|
|
||||||
|
|
||||||
self.clock:render()
|
|
||||||
self.level:render()
|
self.level:render()
|
||||||
self.player:render()
|
self.player:render()
|
||||||
self:renderBalls(dt)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function PlayState:createBalls()
|
function PlayState:checkEndLevel(level)
|
||||||
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
|
|
||||||
))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function PlayState:updateBalls(dt, level)
|
|
||||||
for k,ball in pairs(self.balls) do
|
|
||||||
ball:update(dt,level)
|
|
||||||
end
|
|
||||||
-- remove balls outside bounds
|
|
||||||
for k,ball in pairs(self.balls) do
|
|
||||||
if ball.remove then
|
|
||||||
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
|
|
||||||
self:gameOver()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function PlayState:checkEndLevel (level)
|
|
||||||
if #self.balls <= 0 then
|
if #self.balls <= 0 then
|
||||||
-- game over - reset level
|
-- game over - reset level
|
||||||
|
print("game over due to 0 balls")
|
||||||
self:gameOver()
|
self:gameOver()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- check perimeter of level, if low enough, create new level move on to the next stage
|
-- check perimeter of level, if low enough, create new level move on to the next stage
|
||||||
if level:getPerimeter() < 500 then
|
if level:getPerimeter() < 500 then
|
||||||
|
print("next stage due to perimeter goal reached")
|
||||||
self:nextStage()
|
self:nextStage()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- check if clock finished counting limit time
|
-- check if clock finished counting limit time
|
||||||
if self.clock.direction == 'up' and self.clock.currentTime * 1 > self.clock.timeLimit then
|
if self.clock.direction == "up" and self.clock.currentTime * 1 > self.clock.timeLimit then
|
||||||
|
print("game over due to time limit reached")
|
||||||
self:gameOver()
|
self:gameOver()
|
||||||
elseif self.clock.direction == 'down' and self.clock.currentTime * 1 <= 0 then
|
elseif self.clock.direction == "down" and self.clock.currentTime * 1 <= 0 then
|
||||||
|
print("game over due to time limit reached")
|
||||||
self:gameOver()
|
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
|
end
|
||||||
end
|
|
||||||
|
|
||||||
function PlayState:renderBalls(dt)
|
-- remove balls outside bounds
|
||||||
for k,ball in pairs(self.balls) do
|
for k, ball in pairs(self.balls) do
|
||||||
ball:render()
|
if ball.remove then
|
||||||
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function PlayState:gameOver()
|
function PlayState:gameOver()
|
||||||
gStateStack:pop()
|
gStateStack:pop()
|
||||||
gSounds['music']:stop()
|
gSounds["music"]:stop()
|
||||||
gStateStack:push(GameOverState(self.player.score),function() end)
|
gStateStack:push(
|
||||||
|
GameOverState(self.player.score),
|
||||||
|
function()
|
||||||
|
end
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function PlayState:nextStage()
|
function PlayState:nextStage()
|
||||||
gStateStack:push(FadeOutState({
|
gStateStack:push(
|
||||||
r = 255/255, g = 255/255, b = 255/255}, 1,function()
|
FadeOutState(
|
||||||
self.stage = self.stage + 1
|
{
|
||||||
self.level = Level(LEVELS_DEF,self.stage)
|
r = 255 / 255,
|
||||||
self.clock = Clock(self.clock.timeLimit + 3 * #self.balls,"down")
|
g = 255 / 255,
|
||||||
self.player:reset()
|
b = 255 / 255
|
||||||
self.player.score = self.player.score + self.player.multiplier * #self.balls
|
},
|
||||||
self.player.multiplier = self.player.multiplier + #self.balls
|
1,
|
||||||
self.balls = {}
|
function()
|
||||||
self:createBalls()
|
self.stage = self.stage + 1
|
||||||
self.level.player = self.player
|
local nextDef = self.stage % (#LEVELS_DEF + 1)
|
||||||
self.player.level = self.level
|
if nextDef == 0 then nextDef = 1 end
|
||||||
self.level.balls = self.balls
|
self.level = Level(LEVELS_DEF[nextDef], self.stage)
|
||||||
gSounds['music']:stop()
|
self.balls = self.level.balls
|
||||||
gSounds['heal']:play()
|
self.clock = self.level.clock
|
||||||
gStateStack:push(FadeOutState({r = 1/255, g = 1/255, b = 1/255}, 1,function()
|
self.player:reset()
|
||||||
gSounds['music']:play()
|
self.player.score = self.player.score + self.player.multiplier * #self.balls
|
||||||
end))
|
self.player.multiplier = self.player.multiplier + #self.balls
|
||||||
end))
|
self.level.player = self.player
|
||||||
end
|
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