123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- -- title: cylshooter
- -- author: pixelbath
- -- desc: short description
- -- site: website link
- -- license: MIT License (change this to your license of choice)
- -- version: 0.1
- -- script: lua
- -- The idea:
- -- like Resogun, a cylindrical shooter
- -- 1. render map
- -- 2. fix column-by-column, raycast style
- -- 3. how to draw background?
- -- 1. render bg map offscreen
- -- 2. memcpy to onscreen
- -- 3. render fg map offscreen
- -- 4. memcpy/pix the fg to the screen?
- local t=0
- local player = {
- x=140, y=70,
- vx=0, vy=0,
- speed=1.5,
- }
- function player:update()
- self.vx = 0
- self.vy = 0
- if btn(0) then
- self.vy=-self.speed
- end
- if btn(1) then
- self.vy=self.speed
- end
- if btn(2) then
- self.vx=-self.speed
- end
- if btn(3) then
- self.vx=self.speed
- end
- -- slow down diagonal movements
- if self.vx * self.vy ~= 0 then
- self.vx = self.vx * 0.707
- self.vy = self.vy * 0.707
- end
- self.x = self.x + self.vx
- self.y = self.y + self.vy
- end
- 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 Shot.speed:set(value)
- return function()
- Shot.speed = value
- end
- end
- 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 Shot.velocity:set(speed, direction)
- return function()
- Shot.speed = speed
- Shot.direction = direction
- end
- end
- 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()
- 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>
|