In Churning Seas (my modest humble tiny little first app)

Thanks to all the help I get here (and to the example files from codea…), I’m on my way to develop a little something. It’s a short game where one tries to build the highest possible island from piling up randomly shaped polygons as the tide rises. The game stops when the sea submerges the top polygon… I’m trying to implement elements of ecosystem modelling in the game (yes, it’s odd), but that’s in its early stage, and I have some thinking to do…

In the video, we can see that the next shape is display so that the player can plan and place it in the right spot. We also kind of see a school of fish (black triangles) being chased by a flock of sea birds (white triangles) when the venture too close to the surface. There is some rudimentary light effects (as rays from a moving sun), wind, etc.

Lots to work on, this is exciting!

https://www.youtube.com/watch?v=8hAJqRG0hn0

https://www.youtube.com/watch?v=6ay-0Zj2Rlg

The second video is private, so we can’t see it. :slight_smile: But the game seems fun and origional. I would (and hopefully will) try it.

Thanks! (the video should be good now) :slight_smile:

Thats a cool idea. It seems to relate to islands rising from the sea due to under water volcanos pilling up molten rock over the years. Is that how you got the idea?

I love the irony in calling the game humble! (Also, the game looks pretty amazing, keep up the good work!)

Oops, sorry, I didn’t notice the answers. Thanks! thanks! I’m not too sure how I got the idea. I’m a geographer and I found my few geology classes too complicated, this game is an attempt to an easier theory for island formation, I guess :smiley:

@rodolphe your background lighting is amazing!! Could you mail me the source code for the background and may I use it in my projects?

Oh wow, that’s an ooooold version. I was experimenting with this, but found that the frame rate was suffering, as so was the game play, so I got rid of it. I can try and explain how I did it though, if you want?

It’s basically physics.raycast() from a random place at the top, to a random place at the bottom. I get a line from the top to the first object towards the bottom (that the first side of on of the polygons that will eventually be representing light), I do this ray cast a random number of times with small increments towards the right, put the coordinates in a table, which will build a polygon (shaped by the objects it intersects, like light would kind of do). This polygon has an “age” attribute, which I use to make the light more or less visible in time. I randomly called this function from different place on top to different place at the bottom. That’s it, really.

Looking a it after all these months, it kind of looks alright, I realize, I might try to re-implement a “cheaper” version of it…

Oh no! sorry, I misunderstood you. This is much simpler. It’s basically only graphic assets. I made two colour backgrounds (of different colours), one of which has a strong lens falloff, or vignetting. they both are displayed on top of one another, the bottom one has 255 opacity, but the top one has a changing opacity. In this case, the opacity is relative to the position of the top polygon. That’s it! :slight_smile:

Is that how you have the background a paler shade of whatever the background color is? In the center of the screen it’s brighter and darkens as you go out to the edges of the screen…is that what you did for that

@Rodolphe Game play wise, is there anything stopping you from tapping the screen faster then a fed Yorick to fill the screen with pieces?

Well, it’s not a good strategy as the player only has a certain amount of polygons to use. Also, if not placed carefully, the structure tends to collapse! :slight_smile:

@Rodolphe, for the lighting, is the physics raycast necessary? could you not just draw a line all the way top to bottom as the first thing after background, with everything else on top and it will give the same effect?

For extra “realism” (hum), I wanted the light to stop at the first physics object on its way, and keep the rest in shadow. That’s why!

Here’s a video of the latest beta!

https://www.youtube.com/watch?v=PW9uI9WoyG4&feature=youtu.be

@Rodolphe, very nice. Looking at your latest video I can see why you did it the way you do. It wasn’t very clear to me in the other videos.

This is a really good take on stacking games, can’t wait to play it.

@Rodolphe, how expensive is your light beam? I was curious so I built one myself, it is not too bad but i think it could be optimized. Is this similar to how you did it?


--# Main
-- Light

function setup()
    light = Lightbeam()
    light:cast()
    
    parameter.watch("1 / DeltaTime")
    
    bodies = {}
    for i = 1, 10 do
        local m = vec2(math.random(WIDTH), math.random(HEIGHT))
        local w, h = math.random(100), math.random(100)
        bodies[i] = physics.body(POLYGON, vec2(m.x - w, m.y + h), vec2(m.x + w, m.y + h), vec2(m.x + w, m.y - h), vec2(m.x - w, m.y - h))
        
        bodies[i].gravityScale = 0.1
    end
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(0, 148, 255, 255)

    -- This sets the line thickness
    strokeWidth(2)

    -- Do your drawing here
    light:draw()
    
    for i,body in ipairs(bodies) do
        pushMatrix()
        translate(body.x, body.y)
        rotate(body.angle)
    
        stroke(150,255,150,255)
    
        strokeWidth(3.0)
        local points = body.points
        for j = 1,#points do
            a = points[j]
            b = points[(j % #points)+1]
            line(a.x, a.y, b.x, b.y)
        end
        
        popMatrix()
    end 
end


--# Lightbeam
Lightbeam = class()

function Lightbeam:init()
    self.mesh = mesh()
    
    self.color = color(220, 220, 155, 255)
    
    self.minWidth = WIDTH / 30
    self.maxWidth = WIDTH / 10
    
    self.tpos, self.bpos, self.twidth, self.bwidth = 0,0,0,0
end

function Lightbeam:cast()
    self.tpos, self.bpos = math.random(WIDTH), math.random(WIDTH)
    self.twidth = math.random(self.minWidth, self.maxWidth)
    self.bwidth = math.random(self.twidth, self.maxWidth)
    
    self:update()
end

function Lightbeam:update()
    local twidth, bwidth = vec2(self.twidth / 2, 0), vec2(self.bwidth / 2, 0)
    local p1, p2 = vec2(self.tpos, HEIGHT), vec2(self.bpos, 0)
    local points = {}
    local n = 10
    for p = 1, n do
        points[p] = p1 - twidth + (((twidth*2) / (n - 1)) * (p - 1))
        points[p + n] = p2 + bwidth - (((bwidth*2) / (n - 1)) * (p - 1))
    end

    for i = 1, n do
        local ray = physics.raycast(points[i], points[#points - (i - 1)])
        if ray ~= nil and ray.point ~= nil then
            points[#points - (i - 1)] = ray.point
        end
    end
    
    self.mesh.vertices = triangulate(points)
    self.mesh:setColors(self.color)
end

function Lightbeam:draw()
    self:update()
    
    self.mesh:draw()
end

@JakAttak, I’m not too too sure how expensive it is, having a very rudimentary understanding of this kind of stuff, but I keep the number of lights seen at any given time under 3, just to be sure. Reading through your code, it looks like what I’ve done, except I did use a class, so my code is a right mess :smiley: yours looks very neat indeed, good job (I should study it, really)!

Thanks @Luatee !!!

I’ve got a testflight thing running, by the way, if some of you want to play it… :slight_smile: