|
@@ -18,13 +18,10 @@
|
|
|
-- 3. render fg map offscreen
|
|
|
-- 4. memcpy/pix the fg to the screen?
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-local world = {}
|
|
|
-local entities = {}
|
|
|
+local t=0
|
|
|
|
|
|
local player = {
|
|
|
- x=0, y=0,
|
|
|
+ x=140, y=70,
|
|
|
vx=0, vy=0,
|
|
|
speed=1.5,
|
|
|
}
|
|
@@ -55,34 +52,259 @@ function player:update()
|
|
|
self.y = self.y + self.vy
|
|
|
end
|
|
|
|
|
|
-function player:draw()
|
|
|
- rect(self.x, self.y, 8, 8, 4)
|
|
|
+local Random = {
|
|
|
+ angle = {
|
|
|
+ between = function(min, max)
|
|
|
+ return min + math.random() * (max - min)
|
|
|
+ end
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+local Shot = {
|
|
|
+ x = 20,
|
|
|
+ y = 20,
|
|
|
+ speed = {},
|
|
|
+ direction = {},
|
|
|
+ position = {},
|
|
|
+ velocity = {},
|
|
|
+ bullets = {},
|
|
|
+}
|
|
|
+
|
|
|
+function Shot:new()
|
|
|
+ local shot = setmetatable({}, { __index = Shot })
|
|
|
+ shot.bullets = {}
|
|
|
+ return shot
|
|
|
end
|
|
|
|
|
|
-function world:add_entity(en)
|
|
|
- table.insert(entities, en)
|
|
|
+function Shot.speed:set(value)
|
|
|
+ return function()
|
|
|
+ Shot.speed = value
|
|
|
+ end
|
|
|
end
|
|
|
|
|
|
-function world:update()
|
|
|
- for key,val in ipairs(entities) do
|
|
|
- entities[key]:update()
|
|
|
+function Shot.position:set(distance, bearing)
|
|
|
+ return function()
|
|
|
+ Shot.x = math.cos(math.rad(bearing)) * distance
|
|
|
+ Shot.y = math.sin(math.rad(bearing)) * distance
|
|
|
end
|
|
|
end
|
|
|
|
|
|
-function world:draw()
|
|
|
- for key,val in ipairs(entities) do
|
|
|
- entities[key]:draw()
|
|
|
+function Shot.velocity:set(speed, direction)
|
|
|
+ return function()
|
|
|
+ Shot.speed = speed
|
|
|
+ Shot.direction = direction
|
|
|
end
|
|
|
end
|
|
|
|
|
|
-world:add_entity(player)
|
|
|
+function Shot.direction:add(degrees)
|
|
|
+ return function()
|
|
|
+ Shot.direction = Shot.direction + degrees
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+-- Pattern manager
|
|
|
+local PatternManager = {
|
|
|
+ activePatterns = {},
|
|
|
+ windowWidth = 800, -- Default window size
|
|
|
+ windowHeight = 600 -- Default window size
|
|
|
+}
|
|
|
+
|
|
|
+function PatternManager:new(windowWidth, windowHeight)
|
|
|
+ local manager = setmetatable({}, { __index = PatternManager })
|
|
|
+ manager.activePatterns = {}
|
|
|
+ manager.windowWidth = windowWidth or 800
|
|
|
+ manager.windowHeight = windowHeight or 600
|
|
|
+ return manager
|
|
|
+end
|
|
|
+
|
|
|
+
|
|
|
+-- Initialize the pattern manager with window dimensions
|
|
|
+patternManager = PatternManager:new(240,136)
|
|
|
+
|
|
|
+
|
|
|
|
|
|
function TIC()
|
|
|
cls()
|
|
|
- world:update()
|
|
|
- world:draw()
|
|
|
+ if t==0 then
|
|
|
+ -- Start both patterns
|
|
|
+ patternManager:startPattern("firstShot")
|
|
|
+ patternManager:startPattern("secondShot")
|
|
|
+ end
|
|
|
+
|
|
|
+ -- player:update()
|
|
|
+ patternManager:update()
|
|
|
+ patternManager:draw()
|
|
|
+
|
|
|
+ t = t + 1
|
|
|
+end
|
|
|
+
|
|
|
+
|
|
|
+-- Pattern system functions
|
|
|
+local function aim()
|
|
|
+ return function()
|
|
|
+ local dx = player.x - Shot.x
|
|
|
+ local dy = player.y - Shot.y
|
|
|
+ Shot.direction = math.deg(math.atan2(dy, dx))
|
|
|
+ end
|
|
|
end
|
|
|
|
|
|
+local function line(count, options)
|
|
|
+ return function()
|
|
|
+ local speedChange = options.shotSpeedChange or 0
|
|
|
+ local currentSpeed = Shot.speed
|
|
|
+
|
|
|
+ for i = 1, count do
|
|
|
+ currentSpeed = currentSpeed + (speedChange * (count - 1))
|
|
|
+ table.insert(Shot.bullets, {
|
|
|
+ x = Shot.x,
|
|
|
+ y = Shot.y,
|
|
|
+ speed = currentSpeed,
|
|
|
+ direction = Shot.direction,
|
|
|
+ vanishTime = nil
|
|
|
+ })
|
|
|
+ end
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+local function wait(frames)
|
|
|
+ return function()
|
|
|
+ for i = 1, frames do
|
|
|
+ coroutine.yield()
|
|
|
+ end
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+local function fire(actions)
|
|
|
+ return function()
|
|
|
+ local bullet = {
|
|
|
+ x = Shot.x,
|
|
|
+ y = Shot.y,
|
|
|
+ speed = Shot.speed,
|
|
|
+ direction = Shot.direction,
|
|
|
+ vanishTime = nil
|
|
|
+ }
|
|
|
+
|
|
|
+ -- for _, action in ipairs(actions) do
|
|
|
+ -- if type(action) == "function" then
|
|
|
+ -- action(bullet)
|
|
|
+ -- end
|
|
|
+ -- end
|
|
|
+
|
|
|
+ table.insert(Shot.bullets, bullet)
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+local function vanish()
|
|
|
+ return function(bullet)
|
|
|
+ bullet.vanishTime = 0
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+local function loop(actions)
|
|
|
+ return function()
|
|
|
+ while true do
|
|
|
+ for _, action in ipairs(actions) do
|
|
|
+ if type(action) == "function" then
|
|
|
+ action()
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+-- Pattern definitions
|
|
|
+local patterns = {
|
|
|
+ firstShot = {
|
|
|
+ Shot.speed:set(2),
|
|
|
+ loop({
|
|
|
+ -- Shot.position:set(150, Random.angle.between(0, 360)),
|
|
|
+ aim(),
|
|
|
+ line(8, { shotSpeedChange = 0.5 }),
|
|
|
+ wait(100)
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ secondShot = {
|
|
|
+ Shot.velocity:set(1, 90),
|
|
|
+ loop({
|
|
|
+ fire({
|
|
|
+ wait(60),
|
|
|
+ vanish()
|
|
|
+ }),
|
|
|
+ Shot.direction:add(12),
|
|
|
+ wait(1)
|
|
|
+ })
|
|
|
+ },
|
|
|
+}
|
|
|
+
|
|
|
+function PatternManager:startPattern(patternName)
|
|
|
+ local pattern = patterns[patternName]
|
|
|
+ if not pattern then
|
|
|
+ error("Pattern " .. patternName .. " not found")
|
|
|
+ end
|
|
|
+
|
|
|
+ local co = coroutine.create(function()
|
|
|
+ for _, action in ipairs(pattern) do
|
|
|
+ if type(action) == "function" then
|
|
|
+ action()
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end)
|
|
|
+
|
|
|
+ table.insert(self.activePatterns, {
|
|
|
+ coroutine = co,
|
|
|
+ name = patternName
|
|
|
+ })
|
|
|
+end
|
|
|
+
|
|
|
+function PatternManager:update()
|
|
|
+ -- Update all active patterns
|
|
|
+ for i = #self.activePatterns, 1, -1 do
|
|
|
+ local pattern = self.activePatterns[i]
|
|
|
+ if coroutine.status(pattern.coroutine) ~= "dead" then
|
|
|
+ local success, err = coroutine.resume(pattern.coroutine)
|
|
|
+ if not success then
|
|
|
+ error("Error in pattern " .. pattern.name .. ": " .. err)
|
|
|
+ end
|
|
|
+ else
|
|
|
+ table.remove(self.activePatterns, i)
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ -- Update bullet positions
|
|
|
+ for i = #Shot.bullets, 1, -1 do
|
|
|
+ local bullet = Shot.bullets[i]
|
|
|
+ if bullet.vanishTime then
|
|
|
+ bullet.vanishTime = bullet.vanishTime + 1
|
|
|
+ if bullet.vanishTime >= 30 then
|
|
|
+ table.remove(Shot.bullets, i)
|
|
|
+ end
|
|
|
+ else
|
|
|
+ bullet.x = bullet.x + math.cos(math.rad(bullet.direction)) * bullet.speed
|
|
|
+ bullet.y = bullet.y + math.sin(math.rad(bullet.direction)) * bullet.speed
|
|
|
+
|
|
|
+ -- Remove bullets that are off screen
|
|
|
+ if bullet.x < -50 or bullet.x > self.windowWidth + 50 or
|
|
|
+ bullet.y < -50 or bullet.y > self.windowHeight + 50 then
|
|
|
+ table.remove(Shot.bullets, i)
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function PatternManager:draw()
|
|
|
+ -- Draw all bullets
|
|
|
+ for _, bullet in ipairs(Shot.bullets) do
|
|
|
+ circ(bullet.x, bullet.y, 2, 6)
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
-- <PALETTE>
|
|
|
-- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57
|
|
|
-- </PALETTE>
|