Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Spots [Update v0.6]

edited August 2016 in Code Sharing Posts: 160

Hello everyone!
I've created a little game I call "Spots". It's a game where you are a spot and you consume smaller spots to grow and avoid larger spots to survive! (Just like agar.io) I wanted to make it a little different from agar.io though, to make it feel unique. To do that i'll be updating this game a lot. Right now there aren't that many differences though. If you find an error, please tell me the error and what you did to cause it. If you have a suggestion, please let me know and if I like it, I will add it.

Here is the code:

--# Main

supportedOrientations(CurrentOrientation)
displayMode(FULLSCREEN)
-- Use this function to perform your initial setup
function setup()
    Menu.Begin = Button({text="Begin",colour=color(255),colourSharpness=100, size=70, pos=vec2(WIDTH/2,HEIGHT/3), callback=function()
        screen = Playing
        Menu.fadedIn = false
        Menu.alpha = 0
        tween.reset(Menu.tID)
    end})
    spots = {}
    menuImg = deadScreen()
    screen.setup()
    spotSpawningTimer = 20

    maximumSpots = 30

    fps = {}
    for k=1,10 do
        table.insert(fps,1/60)
    end
    parameter.watch(afps)
end

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

    if #spots <= maximumSpots then
        spotSpawningTimer = spotSpawningTimer - 1
        if spotSpawningTimer < 0 then
            spotSpawningTimer = spotSpawningTimer + 20
            spots[#spots+1] = Spot()
        end
    end

    for i=#spots, 1, -1 do
        local v = spots[i]
        local remove = v:draw()
        if remove then
            table.remove(spots,i)
        end
    end

    screen.draw()

    table.remove(fps,1)
    fps[#fps+1] = DeltaTime
    local afps = 0
    for _,v in ipairs(fps) do
        afps = afps + v
    end
    afps = math.floor(10/afps)


    fill(255)
    textMode(CORNER)
    fontSize(30)
    text("FPS: "..afps,10,10)
end

function touched(t)
    screen.touched(t)
end

function deadScreen()
    local img = image(WIDTH,HEIGHT)
    setContext(img)
    img.premultiplied = false
    background(255,170)
    fill(255)
    font("Georgia-Bold")
    fontSize(100)
    text("Spots",WIDTH*0.5,HEIGHT*0.75)
    Menu.Begin:draw()
    setContext()
    return img
end

function brighten(c,a)
    return color(c.r+a,c.g+a,c.b+a,c.a)
end

function pointInRectCenter(pointX, pointY, x, y, w, h)
    return pointX >= x - w*0.5 and pointX <= x + w*0.5 and pointY >= y - h*0.5 and pointY <= y + h*0.5
end

Button = class()
function Button:init(data)
    self.callback = data.callback
    if data.pos then
        self.pos = data.pos * 1 -- * 1 to make it a new 2D vector
        elseif data.x and data.y then
        self.pos = vec2(data.x,data.y)
        else
        self.pos = vec2(0,0)
    end
    self.visible = true
    self.txt = data.text or "Button"
    self.txtC = data.textColour or color(40)
    self.size = data.size or 50
    self.font = "Futura-Medium"
    font(self.font)
    fontSize(self.size)
    self.w,self.h = textSize(self.txt)
    self.c = data.colour or color(200)
    self.cSpread = data.colourSharpness or 140
    self.mesh = mesh()
    local left = self.pos.x - self.w*0.5
    local right = self.pos.x + self.w*0.5
    local top = self.pos.y + self.h*0.5
    local bottom = self.pos.y - self.h*0.5
    self.mesh.vertices = {vec2(left,bottom),vec2(left,top),vec2(right,top)
                        ,vec2(left,bottom),vec2(right,top),vec2(right,bottom)}
    self.mesh.colors = {brighten(self.c,-self.cSpread),self.c,self.c
                        ,brighten(self.c,-self.cSpread),self.c,brighten(self.c,-self.cSpread)}
end

function Button:draw()
    if self.visible then
        self.mesh:draw()
        fill(self.txtC)
        font(self.font)
        fontSize(self.size/1.2)
        textMode(CENTER)
        textAlign(CENTER)
        text(self.txt,self.pos.x,self.pos.y)
    end
end

function Button:touched(t)
    if not self.visible then return end

    local pressing = pointInRectCenter(t.x,t.y,self.pos.x,self.pos.y,self.w,self.h)
    if pressing and t.state == BEGAN then
        self.mesh.colors = {self.c,brighten(self.c,-self.cSpread),brighten(self.c,-self.cSpread)
                    ,self.c,brighten(self.c,-self.cSpread),self.c}
    end
    if not pressing or t.state == ENDED then
        if pressing and t.state == ENDED then
            if self.callback then
                self.callback()
            end
        end
        self.mesh.colors = {brighten(self.c,-self.cSpread),self.c,self.c
                        ,brighten(self.c,-self.cSpread),self.c,brighten(self.c,-self.cSpread)}
    end
end

Menu = {alpha = 0}
function Menu.setup()
    Menu.mesh = mesh()
    Menu.mesh:addRect(WIDTH*0.5,HEIGHT*0.5,WIDTH,HEIGHT)
    Menu.mesh.texture = menuImg
    Menu.tID = tween(2,Menu,{alpha = 255},tween.easing.cubicOut,function() Menu.fadedIn = true end)
end

function Menu.draw()
    Menu.mesh:setColors(255,255,255,Menu.alpha)
    Menu.mesh:draw()
    if Menu.fadedIn then Menu.Begin:draw() end
    --[[
    fill(230,200,0)
    noSmooth()
    noStroke()
    rectMode(CENTER)
    rect(WIDTH/255*Menu.alpha, 100, 250, 100) ]]
end

function Menu.touched(t)
    Menu.Begin:touched(t)
end

Playing = {}
function Playing:draw()
    Player.draw()
end

function Playing.touched(t)
    Player.pos.x,Player.pos.y = Player.pos.x + (t.deltaX*1.5), Player.pos.y + (t.deltaY*1.5)
    if Player.pos.x < 0 then
        Player.pos.x = 0
        elseif Player.pos.x > WIDTH then
        Player.pos.x = WIDTH
    end
    if Player.pos.y < 0 then
        Player.pos.y = 0
        elseif Player.pos.y > HEIGHT then
        Player.pos.y = HEIGHT
    end
end

screen = Menu

Player = {diameter = 20, pos = vec2(WIDTH*0.5, HEIGHT*0.5)}
function Player.draw()
    fill(255)
    ellipse(Player.pos.x,Player.pos.y,Player.diameter)
end

Spot = class()
function Spot:init()
    self.diameter = math.random(15,250)
    local radius = self.diameter*0.5
    self.pos = vec2(0,0)
    if math.random(2) == 1 then
        if math.random(2) == 1 then
            self.pos.x = math.random(0,WIDTH)
            self.pos.y = -radius
            else
            self.pos.x = math.random(0,WIDTH)
            self.pos.y = HEIGHT+radius
        end
        else
        if math.random(2) == 1 then
            self.pos.x = -radius
            self.pos.y = math.random(0,HEIGHT)
            else
            self.pos.x = WIDTH+radius
            self.pos.y = math.random(0,HEIGHT)
        end
    end
    local speed = math.random(4,8)
    self.dir = vec2(math.random(0,WIDTH)-self.pos.x,math.random(0,HEIGHT)-self.pos.y):normalize()
    self.dir.x = self.dir.x * speed
    self.dir.y = self.dir.y * speed
    self.colour = color((255*0.2)*math.random(1,5),(255*0.2)*math.random(1,5),(255*0.2)*math.random(1,5))
end

function Spot:draw()
    local posx,posy = self.pos.x,self.pos.y

    pushStyle()

    self.pos = vec2(posx+self.dir.x,posy+self.dir.y)

    fill(self.colour)
    noStroke()
    ellipseMode(CENTER)
    ellipse(posx,posy,self.diameter)

    popStyle()

    local removeMe = false

    if screen == Playing then
        if self.pos:dist(Player.pos) <= (self.diameter+Player.diameter)*0.5 then
            if self.diameter > Player.diameter then
                Player.diameter = 20
                Player.pos = vec2(WIDTH*0.5, HEIGHT*0.5)
                screen = Menu
                screen.alpha = 0
                screen.setup()
                self.diameter = self.diameter + (Player.diameter*0.5)
                elseif self.diameter < Player.diameter then
                Player.diameter = Player.diameter + (self.diameter*0.5)
                removeMe = true
            end
        end
    end

    removeMe = not pointInRectCenter(posx,posy,WIDTH*0.5,HEIGHT*0.5,WIDTH+self.diameter,HEIGHT+self.diameter) or removeMe

    return removeMe
end
Tagged:

Comments

  • Posts: 28

    It's great. Maybe you could make the larger fast ones a little slower.
    I really feel like playing Osmos now, also a great agar.io game

  • Posts: 160

    Thank-you, @Kire for the feedback! When I was programming this game I was also wondering if I should make the bigger ones slower. I think I will do that for the next update. I might also make the map bigger and make the camera follow your spot, like agar.io. I know I said that I want it to be different from agar.io, but I just think the game would be better if there was more space.

  • AnatolyAnatoly Mod
    Posts: 891

    Col game, but i couldn't start for 5 seconds, there were to many circles in the middle. I reached like one minute

  • Posts: 160

    @Tokout Yeah, I know about that problem. I can fix that by giving the player invulnerability for a few seconds so they can get out of the way of larger spots.

  • Posts: 160

    New Update!:
    I'm so sorry it took so long to update this game. It's just that I was planning and later started on an FPS. But I finally got around to releasing an update!

    Here is the new code!:

    --# Main
    
    supportedOrientations(CurrentOrientation)
    displayMode(FULLSCREEN)
    -- Use this function to perform your initial setup
    function setup()
    
        -- Below are variables you can change! :D
    
        maximumSpots = 35 -- maximum spots at once
        mapW,mapH = 2000,2000 -- the size of the map
        spawnRate = 20 -- the rate at which the spots spawn
    
        -- End of variables you can change... D:
    
        Menu.Begin = Button({text="Begin",colour=color(255),colourSharpness=100, size=70, pos=vec2(0,-100), callback=function()
            screen = Playing
            Menu.fadedIn = false
            Menu.alpha = 0
            tween.reset(Menu.tID)
        end})
        Playing.border = mesh()
        do
            local b = Playing.border -- b is much faster to type than Playing.border
    
            b:addRect(-mapW*.5 - WIDTH*.25, 0, WIDTH*.5, mapH + HEIGHT) -- Left wall
            b:addRect(mapW*.5 + WIDTH*.25, 0, WIDTH*.5, mapH + HEIGHT) -- Right wall
            b:addRect(0, -mapH*.5 - HEIGHT*.25, mapW + WIDTH, HEIGHT*.5) -- Bottom wall
            b:addRect(0, mapH*.5 + HEIGHT*.25, mapW + WIDTH, HEIGHT*.5) -- Top wall
            b:setColors(255,0,0)
        end
    
        spots = {}
        menuImg = deadScreen()
        screen.setup()
        spotSpawningTimer = 0
    
    
        fps = {}
        for k=1,10 do
            table.insert(fps,1/60)
        end
    end
    
    -- This function gets called once every frame
    function draw()
        background(0)
    
        if #spots < maximumSpots then
            spotSpawningTimer = spotSpawningTimer - 1
            if spotSpawningTimer < 0 then
                spotSpawningTimer = spotSpawningTimer + spawnRate
                spots[#spots+1] = Spot()
            end
        end
    
        screen.draw()
    
        table.remove(fps,1)
        fps[#fps+1] = DeltaTime
        local afps = 0
        for _,v in ipairs(fps) do
            afps = afps + v
        end
        afps = math.floor(10/afps)
    
        resetMatrix()
        fill(255)
        textMode(CORNER)
        fontSize(30)
        text("FPS: "..afps.."   Spots: "..#spots,10,10)
    end
    
    function touched(t)
        screen.touched(t)
    end
    
    function drawSpots()
        for i=#spots, 1, -1 do
            local v = spots[i]
            local remove = v:draw()
            if remove then
                table.remove(spots,i)
            end
        end
    end
    
    function deadScreen()
        local img = image(WIDTH,HEIGHT)
        setContext(img)
        img.premultiplied = false
        background(255,170)
        fill(255)
        font("Georgia-Bold")
        fontSize(100)
        text("Spots",WIDTH*0.5,HEIGHT*0.75)
        translate(WIDTH*.5,HEIGHT*.5)
        Menu.Begin:draw()
        setContext()
        return img
    end
    
    function brighten(c,a)
        return color(c.r+a,c.g+a,c.b+a,c.a)
    end
    
    function pointInRectCenter(pointX, pointY, x, y, w, h)
        return pointX >= x - w*0.5 and pointX <= x + w*0.5 and pointY >= y - h*0.5 and pointY <= y + h*0.5
    end
    
    Button = class()
    function Button:init(data)
        self.callback = data.callback
        if data.pos then
            self.pos = data.pos * 1 -- * 1 to make it a new 2D vector
            elseif data.x and data.y then
            self.pos = vec2(data.x,data.y)
            else
            self.pos = vec2(0,0)
        end
        self.visible = true
        self.txt = data.text or "Button"
        self.txtC = data.textColour or color(40)
        self.size = data.size or 50
        self.font = "Futura-Medium"
        font(self.font)
        fontSize(self.size)
        self.w,self.h = textSize(self.txt)
        self.c = data.colour or color(200)
        self.cSpread = data.colourSharpness or 140
        self.mesh = mesh()
        local left = self.pos.x - self.w*0.5
        local right = self.pos.x + self.w*0.5
        local top = self.pos.y + self.h*0.5
        local bottom = self.pos.y - self.h*0.5
        self.mesh.vertices = {vec2(left,bottom),vec2(left,top),vec2(right,top)
                            ,vec2(left,bottom),vec2(right,top),vec2(right,bottom)}
        self.mesh.colors = {brighten(self.c,-self.cSpread),self.c,self.c
                            ,brighten(self.c,-self.cSpread),self.c,brighten(self.c,-self.cSpread)}
    end
    
    function Button:draw()
        if self.visible then
            self.mesh:draw()
            fill(self.txtC)
            font(self.font)
            fontSize(self.size/1.2)
            textMode(CENTER)
            textAlign(CENTER)
            text(self.txt,self.pos.x,self.pos.y)
        end
    end
    
    function Button:touched(t)
        if not self.visible then return end
    
        local pressing = pointInRectCenter(t.x,t.y,self.pos.x,self.pos.y,self.w,self.h)
        if pressing and t.state == BEGAN then
            self.mesh.colors = {self.c,brighten(self.c,-self.cSpread),brighten(self.c,-self.cSpread)
                        ,self.c,brighten(self.c,-self.cSpread),self.c}
        end
        if not pressing or t.state == ENDED then
            if pressing and t.state == ENDED then
                if self.callback then
                    self.callback()
                end
            end
            self.mesh.colors = {brighten(self.c,-self.cSpread),self.c,self.c
                            ,brighten(self.c,-self.cSpread),self.c,brighten(self.c,-self.cSpread)}
        end
    end
    
    Menu = {alpha = 0}
    function Menu.setup()
        Menu.mesh = mesh()
        Menu.mesh:addRect(0,0,WIDTH,HEIGHT)
        Menu.mesh.texture = menuImg
        Menu.tID = tween(1,Menu,{alpha = 255},tween.easing.cubicOut,function() Menu.fadedIn = true end)
    end
    
    function Menu.draw()
        translate(WIDTH*.5,HEIGHT*.5)
        drawSpots()
        Menu.mesh:setColors(255,255,255,Menu.alpha)
        Menu.mesh:draw()
        if Menu.fadedIn then Menu.Begin:draw() end
    end
    
    function Menu.touched(t)
        local t = {x=t.x-WIDTH*.5,y=t.y-HEIGHT*.5,state=t.state}
        Menu.Begin:touched(t)
    end
    
    Playing = {}
    function Playing:draw()
        if Playing.movement then
            Player.pos.x, Player.pos.y = Player.pos.x + Playing.movement.x, Player.pos.y + Playing.movement.y
        end
        local hlfW,hlfH = mapW*.5,mapH*.5
        if Player.pos.x < -hlfW then
            Player.pos.x = -hlfW
            elseif Player.pos.x > hlfW then
            Player.pos.x = hlfW
        end
        if Player.pos.y < -hlfH then
            Player.pos.y = -hlfH
            elseif Player.pos.y > hlfH then
            Player.pos.y = hlfH
        end
        translate(-Player.pos.x,-Player.pos.y)
        translate(WIDTH*.5,HEIGHT*.5)
        Player.draw()
        drawSpots()
        Playing.border:draw()
    end
    
    function Playing.touched(t)
        if t.state == ENDED or t.state == CANCELLED then
            Playing.movement = nil
            else
            Playing.movement = vec2(t.x - WIDTH/2, t.y - HEIGHT/2):normalize()* (1/(Player.diameter*.005))*Player.speed
        end
    end
    
    screen = Menu
    
    Player = {diameter = 20, pos = vec2(0, 0), speed = readLocalData("Player Speed",1)}
    function Player.draw()
        fill(255)
        ellipse(Player.pos.x,Player.pos.y,Player.diameter)
    end
    
    Spot = class()
    function Spot:init()
        self.diameter = math.random(15,250)
        local radius = self.diameter*0.5
    
        local hlfW,hlfH = mapW*.5,mapH*.5
        self.pos = vec2(0,0)
        if math.random(2) == 1 then
            if math.random(2) == 1 then
                self.pos.x = math.random(-hlfW,hlfW)
                self.pos.y = -hlfH - radius
                else
                self.pos.x = math.random(-hlfW,hlfW)
                self.pos.y = hlfH+radius
            end
            else
            if math.random(2) == 1 then
                self.pos.x = -hlfW - radius
                self.pos.y = math.random(-hlfH,hlfH)
                else
                self.pos.x = hlfW+radius
                self.pos.y = math.random(-hlfH,hlfH)
            end
        end
    
        local speed = 1/(self.diameter*.005)
        self.dir = vec2(math.random(-hlfW,hlfW)-self.pos.x,math.random(-hlfH,hlfH)-self.pos.y):normalize()
        self.dir.x = self.dir.x * speed
        self.dir.y = self.dir.y * speed
        self.colour = color((255*0.2)*math.random(1,5),(255*0.2)*math.random(1,5),(255*0.2)*math.random(1,5))
    end
    
    function Spot:draw()
        local posx,posy = self.pos.x,self.pos.y
        pushStyle()
    
        self.pos = vec2(posx+self.dir.x,posy+self.dir.y)
    
        fill(self.colour)
        noStroke()
        ellipseMode(CENTER)
        ellipse(posx,posy,self.diameter)
    
        popStyle()
    
        local removeMe = false
    
        if screen == Playing then
            if self.pos:dist(Player.pos) <= (self.diameter+Player.diameter)*0.5 then
                if self.diameter > Player.diameter then
                    Player.diameter = 20
                    Player.pos = vec2(0,0)
                    screen = Menu
                    screen.alpha = 0
                    screen.setup()
                    self.diameter = self.diameter + (Player.diameter*0.5)
                    elseif self.diameter < Player.diameter then
                    Player.diameter = Player.diameter + (self.diameter*0.5)
                    removeMe = true
                end
            end
        end
    
        removeMe = not pointInRectCenter(posx,posy,0,0,mapW+self.diameter,mapH+self.diameter) or removeMe
    
        return removeMe
    end
    

    What's new?:
    -Changed the controls.
    -The map is now bigger!
    -The camera now follows the player (because the map cannot fit on the screen)
    -Bigger blobs are slower than smaller ones.
    -And a few smaller changes.

    Sorry the update is kinda small. I made it within a few hours.

    Enjoy! :smile:

Sign In or Register to comment.