My first game

This is my HD remake of bit invaders next version will have a Scoring system and other enemies

ENEMY_SPAWN_EASY = 0
ENEMY_SPAWN_HARD = 1

EnemyHorde = class()

function EnemyHorde:init()
    -- you can accept and set parameters here
    self.frame = 0
    self.units = {} -- enemy units
    self.heroBullets = {} -- hero's bullets
    self.explosions = {}
    self.enemySize = 50
    self.killCount = 0
    self.spawnPattern = ENEMY_SPAWN_EASY 
end

function EnemyHorde:draw()
    self.frame = (self.frame+1)%128

    pushStyle()

    if self.spawnPattern == ENEMY_SPAWN_EASY then
        fill(123, 25, 100, 255)
    else
        fill(16, 221, 4, 255)
    end

    stroke(62, 33, 37, 255)
    strokeWidth(4)

    -- Spawn random enemy every 100 frames
    if self.frame%50 == 0 then
        spawn = vec2( math.random(WIDTH), HEIGHT + self.enemySize )
        table.insert( self.units, spawn )
    end

    for i,v in ipairs(self.units) do
        -- Move unit down
        v.y = v.y - 5    

        -- If hard, move in sine wave
        if self.spawnPattern == ENEMY_SPAWN_HARD then
            -- Compute movement vector
            sideMove = vec2( math.sin(v.y * 0.02) * 60, 0 )
            v = v + sideMove
        end

        -- Cull unit
        culled = false
        if (v.y + self.enemySize) < 0 then
            table.remove(self.units, i)
            culled = true -- no continue statement
        end 

        -- Check if hit by a bullet
        if culled == false then
            for j,b in ipairs(self.heroBullets) do
                if v:dist(b) < self.enemySize/2 then
                    table.remove(self.units, i)
                    table.remove(self.heroBullets, j)
                    
                    -- Explode!
                    table.insert(self.explosions, Explosion(v))

                    -- Update killCount
                    self.killCount = self.killCount + 1
                end
            end
        end

        -- Draw unit
        sprite("Tyrian Remastered:Blimp Boss", v.x, v.y, self.enemySize, self.enemySize)
        
    end

    -- Draw explosions
    for i,e in ipairs(self.explosions) do
        e:draw()

        if e:isDone() then
            table.remove(self.explosions,i)
        end
    end

    popStyle()
end
Explosion = class()

function Explosion:init(pos)
    self.position = pos
    self.opacity = 255
    self.time = 0
    self.lines = {}

    sound("explode",1285)

    for i = 1,10 do
        dir = vec2(0,1)
        dir = dir:rotate( math.rad(math.random(360)) )
        table.insert( self.lines, dir*math.random(2,7) )
    end
end

function Explosion:isDone()
    return self.opacity <= 0
end

function Explosion:draw()
    self.time = self.time + 1.939
    
    pushStyle()
    lineCapMode(ROUND)
    strokeWidth(6)
    smooth()
    stroke(255, 146, 0, 255)

    p = self.position
    for i,v in ipairs(self.lines) do
        vt = p + v * self.time
        line(p.x, p.y, vt.x, vt.y) 
    end

    self.opacity = 255 * (1 - (self.time/30));

    popStyle()
end
Invader = class()

function Invader:init()
    self.position = vec2(0,0)
    self.bullets = {}
    self.frame = 0
end

function Invader:spawnBullet()
    sound("shoot",77)
    table.insert( self.bullets, vec2( self.position.x, self.position.y + 30 ) )
end

function Invader:drawBullets()
    -- Spawn bullets
    if self.frame%30 == 0 then
        self:spawnBullet()
    end

    -- Move, draw, cull bullets
    for i,v in ipairs(self.bullets) do
        v.y = v.y + 3

        rect(v.x, v.y, 2.5, 45)

        if v.y > (HEIGHT + 10) then
            table.remove(self.bullets,i)
        end 
    end
end

function Invader:draw()
    self.frame = (self.frame + 1)%128

    pushMatrix()
    pushStyle()
    
    -- Set up basic graphical style
    lineCapMode(ROUND)
    strokeWidth(8)
    stroke(222, 12, 12, 255)
    smooth()
    noFill()

    -- Transform to pos
    translate(self.position.x, self.position.y)

    -- Draw our triangle invader
    -- 60 pixels high, 40 pixels wide
   fill(47, 34, 34, 255)
     line( 0, 30, 20, -30 )
    line( 0, 30,-20, -30 )
    line( -20, -30, 20, -30 )
    sprite("Tyrian Remastered:Boss D")

    popMatrix()

    self:drawBullets()

    popStyle()
end

function Invader:touched(touch)
    -- Codea currently does not automatically call this method
end
hero = nil
enemies = nil
bgLines = nil
explosion = nil

GAME_PLAYING = 0
GAME_DEAD = 1
state = GAME_PLAYING

-- Use this function to perform your initial setup
function setup()
    state = GAME_PLAYING

    iparameter("BackgroundSpawnRate",0,3,2)

    hero = Invader()
    hero.position = vec2(WIDTH/2, 150)

    enemies = EnemyHorde()
    enemies.heroBullets = hero.bullets

    bgLines = StreamingLines()
end

function touchingAtPos()
    if CurrentTouch.state == BEGAN or 
       CurrentTouch.state == MOVING then
        return vec2( CurrentTouch.x, CurrentTouch.y )
    end 

    return nil
end

-- This function gets called once every frame
function draw()
    background(12, 0, 255, 255)

    bgLines.spawnRate = BackgroundSpawnRate

    bgLines:update()
    bgLines:draw()

    if state == GAME_PLAYING then 
        -- Process touch
        touch = touchingAtPos()
        if touch then
            if touch.x < (hero.position.x - 10) then
                hero.position.x = hero.position.x - 3
            elseif touch.x > (hero.position.x + 10) then
                hero.position.x = hero.position.x + 3
            end
        end

        if enemies.killCount == 5 then
            enemies.spawnPattern = ENEMY_SPAWN_HARD
        end

        enemies:draw()

        hero:draw()

        -- Check if hero is hit
        for i,v in ipairs(enemies.units) do
            if v:dist(hero.position) < 60 then
                state = GAME_DEAD
                explosion = Explosion(hero.position)
            end
        end
    elseif state == GAME_DEAD then
        if explosion then
            explosion:draw()
            if explosion:isDone() then
                explosion = nil
            end
        end
    end
end
-- This class draws the lines streaming past in the background
-- of the game. We spawn and delete them in the self.lines table

----------------------------------------------
-- Single line
----------------------------------------------
StreamLine = class()
function StreamLine:init(pos, vel)
    self.position = pos
    self.velocity = vel
end

function StreamLine:update()
    self.position.y = self.position.y - self.velocity
end

function StreamLine:draw()
    p = self.position
    line(p.x,p.y,p.x,p.y + self.velocity)
end

function StreamLine:shouldCull()
    -- Check if off the bottom of the screen
    if (self.position.y + self.velocity) < 0 then
        return true
    end 

    return false
end

----------------------------------------------
-- All lines
----------------------------------------------
StreamingLines = class()

function StreamingLines:init()
    self.minSpeed = 5
    self.speed = 30
    self.spawnRate = 2
    self.lines = {}
end

function StreamingLines:updateAndCull()
    toCull = {}
    for i,v in ipairs(self.lines) do
        if v:shouldCull() then
            -- table.insert( toCull, i )
            table.remove( self.lines, i )
        else
            v:update()
        end
    end

    -- print("Removing ", #toCull)
    --for i = #toCull,1,-1 do
    --    table.remove( self.lines, i )
    --end
end

function StreamingLines:update()
    -- Create spawnRate lines per update
    for i = 1,self.spawnRate do
        -- Generate random spawn location
        vel = math.random(self.minSpeed, self.speed)
        spawn = vec2( math.random(WIDTH), HEIGHT + vel )

        table.insert(self.lines, StreamLine(spawn, vel))
    end

    -- Update and cull offscreen lines
    self:updateAndCull()
end

function StreamingLines:draw()
    --print("Num lines = ", #self.lines)

    pushStyle()

    noSmooth()
    stroke(252, 205, 6, 173)
    strokeWidth(2)
    lineCapMode(SQUARE)
 
    for i,v in ipairs(self.lines) do
        v:draw()
    end

    popStyle()
end

@Michael, I edited your posts to use code sections. You can use them in comments by putting your code between three tilde characters. That is:


~~~
Your code here
~~~

Very sharp

I’m getting better at the cut/paste from forum. It seems if you click a fairly large word and rub around a bit, it will eventually highlight the whole block.

Just select One word - keep the Finger down and go to an area where no text is —> everything highlited! :wink:

@MICHAEL - You can put it on my compitition here.

.Codea extension spoiled me :frowning:
Copy and pasting though.

Nevermind