summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ambient.moon1
-rw-r--r--src/bobber.moon78
-rw-r--r--src/color.moon23
-rw-r--r--src/controllers/fish.moon54
-rw-r--r--src/controllers/mouse_keyboard.moon136
-rw-r--r--src/ecs.moon14
-rw-r--r--src/islandgen.moon153
-rw-r--r--src/main.lua9
-rw-r--r--src/player.moon238
-rw-r--r--src/prefab/cabin.moon63
-rw-r--r--src/preload.lua24
-rw-r--r--src/router.moon6
-rw-r--r--src/settings.moon11
-rw-r--r--src/shaders/lake.frag92
-rw-r--r--src/shaders/land.frag72
-rw-r--r--src/shaders/land.vert16
-rw-r--r--src/shaders/stars.frag5
-rw-r--r--src/shaders/stars.lua77
-rw-r--r--src/shaders/stars.vert30
-rw-r--r--src/spawn_fish.moon130
-rw-r--r--src/test_entity.moon36
-rw-r--r--src/window.moon4
-rw-r--r--src/world.moon149
-rw-r--r--src/worldgen.moon8
24 files changed, 1243 insertions, 186 deletions
diff --git a/src/ambient.moon b/src/ambient.moon
new file mode 100644
index 0000000..e99dae8
--- /dev/null
+++ b/src/ambient.moon
@@ -0,0 +1 @@
+-- frog croak: 35895209
diff --git a/src/bobber.moon b/src/bobber.moon
new file mode 100644
index 0000000..6f52c6b
--- /dev/null
+++ b/src/bobber.moon
@@ -0,0 +1,78 @@
+world = require("world")
+sprites = require("world.sprites")
+ecs = require("ecs")
+
+class BobberGraphicsComponent extends world.GraphicsComponent
+ @loctbl = {
+ {-1,-1}
+ {-1,1}
+ {1,1}
+ {1,1}
+ {1,-1}
+ {-1,-1}
+ }
+ buf_size: () =>
+ 6
+ populate_buf: (geom_view, normal_view, offset) =>
+ @buf = geom_view
+ h = 0.1
+ uv = sprites.player_normal
+ utbl = {
+ [-1]: {uv.s1, uv.t1}
+ [1]: {uv.s2, uv.t2}
+ }
+ z = -0.1
+ print("Bobber created at", @properties.pos)
+ for i = 1,6
+ loctbl = @@loctbl[i]
+ geom_view[i] = vec3(@@loctbl[i][1] * h, @@loctbl[i][2] * h, z) + vec3(@properties.pos.x, @properties.pos.y, z)
+ normal_view[i] = vec2(utbl[@@loctbl[i][1]][1], utbl[@@loctbl[i][2]][2])
+
+class BobberPhysicsComponent extends world.PhysicsComponent
+ new: (name, properties, shape, args) =>
+ super(name, properties)
+ join: (entity) =>
+ super(entity)
+ @gc = entity\get("graphics")
+
+
+class Bobber extends ecs.Entity
+ new: (name, position) =>
+ c = {
+ bobber: BobberGraphicsComponent("bobber",{pos: position})
+ pc: world.PhysicsComponent("pc",{},"circle", {position.x, position.y, 0.1})
+ }
+ super(name, c)
+ check: () =>
+ --print("Bobber is looking for fish")
+ bp = @get("pc")
+ for other, _ in pairs(bp\collisions!)
+ --print("Found entity in collisions:", other)
+ if other.component and other.component.entity
+ --print("And it's component.entity is:", other.component.entity)
+ @which = other.component.entity
+ return true
+ return false
+
+
+class BubblesGraphicsComponent extends world.GraphicsComponent
+ buf_size: () =>
+ 6
+ populate_buf: (geom_view, normal_view, offset) =>
+ h = 1
+ geom_view[1] = vec3(-h,-h,1)
+ geom_view[2] = vec3(-h,h,1)
+ geom_view[3] = vec3(-h,-h,1)
+ geom_view[4] = vec3(h,h,1)
+ geom_view[5] = vec3(h,-h,1)
+ geom_view[6] = vec3(-h,-h,1)
+ uv = sprites.player_normal
+ normal_view[1] = vec2(uv.s1,uv.t1)
+ normal_view[2] = vec2(uv.s1,uv.t2)
+ normal_view[3] = vec2(uv.s2,uv.t2)
+ normal_view[4] = vec2(uv.s2,uv.t2)
+ normal_view[5] = vec2(uv.s2,uv.t1)
+ normal_view[6] = vec2(uv.s1,uv.t1)
+ bind = @.node("bind")
+
+{:BobberGraphicsComponent, :BobberPhysicsComponent, :Bobber}
diff --git a/src/color.moon b/src/color.moon
index 447ae32..ebbdddd 100644
--- a/src/color.moon
+++ b/src/color.moon
@@ -1,11 +1,10 @@
color =
+ highlight: {191,228,230}
+ foreground: {186,161,196}
+ midground: {139,126,168}
background: {100,113,136}
shadow: {62,81,84}
- midground: {139,126,168}
- foreground: {186,161,196}
- highlight: {191,228,230}
- outline: {44,54,52}
black: {34,40,37}
am_color = {k, vec4(v[1]/255,v[2]/255,v[3]/255,1) for k,v in pairs(color)}
@@ -20,7 +19,19 @@ am.ascii_color_map = {
o: am_color.outline
}
+lake_color =
+ highlight: color.highlight
+ foreground: {113, 224, 214}
+ midground: {90, 172, 188}
+ background: {75, 120, 156}
+ shadow: {51, 78, 120}
+ black: color.black
+
+am_lake_color = {k, vec4(v[1]/255, v[2]/255, v[3]/255,1) for k,v in pairs(lake_color)}
+
{
- color: color
- am_color: am_color
+ :color
+ :am_color
+ :lake_color
+ :am_lake_color
}
diff --git a/src/controllers/fish.moon b/src/controllers/fish.moon
new file mode 100644
index 0000000..1516574
--- /dev/null
+++ b/src/controllers/fish.moon
@@ -0,0 +1,54 @@
+ecs = require("ecs")
+world = require("world")
+controller = {}
+
+class FishControllerComponent extends ecs.Component
+ new: () =>
+ print("Fish controller started")
+ @node = am.group!
+ join: (entity) =>
+ super(entity)
+ graphic = entity\get("graphic")
+ assert(graphic, "Fish controller must have a graphic")
+ pred_component = entity\get("pred")
+ assert(pred_component, "Fish controller must have a predicted component")
+ net_component = entity\get("net")
+ assert(net_component, "Fish controller must have a net component")
+ @net = net_component
+ graphic.node\append(@node)
+ comp = @
+ locpicker = coroutine.create(() =>
+ comp\pick_next_location!
+ coroutine.yield!
+ )
+ --either "swimming", "waiting", or "catching"
+ @state = "swimming"
+ @node\action(coroutine.create(() =>
+ while comp.state == "swimming"
+ comp.state = "waiting"
+ start_wait = world.sync_time!
+ while world.sync_time! - start_wait < 4
+ --TODO: look for nearby hooks and get caught
+ coroutine.yield!
+ if comp.state == "waiting"
+ comp\pick_next_location!
+ comp.state = "swimming"
+ while math.distance(pred_component.properties.pos, net_component.properties.next_loc) > 0.01
+ --print("At ", pred_component.properties.pos, "waiting to get to next location, ", net_component.properties.next_loc, "it is ", math.distance(pred_component.properties.pos, net_component.properties.next_loc), " away")
+ coroutine.yield!
+
+ ))
+ pick_next_location: () =>
+ -- Pick somewhere to swim based on where we are?
+ -- This can only be done on the host.
+ if @net.properties.pos.x > 10 -- pick somewhere to the right
+ @net.properties.next_loc = vec2(
+ math.random(10.3,12),
+ math.random(-10,10)
+ )
+ @net.properties.next_loc_time = world.sync_time!
+ --@net.properties.next_loc = @net.properties.pos + vec2(0,1)
+ --@net.properties.next_loc_time = world.sync_time!
+ print("Picking next location, it was ", @net.properties.next_loc)
+
+{:FishControllerComponent}
diff --git a/src/controllers/mouse_keyboard.moon b/src/controllers/mouse_keyboard.moon
index b0b63b6..28c4f58 100644
--- a/src/controllers/mouse_keyboard.moon
+++ b/src/controllers/mouse_keyboard.moon
@@ -1,6 +1,11 @@
ecs = require("ecs")
win = require("window")
world = require("world")
+fish = require("spawn_fish")
+rng = require("rng")
+us = require("ui.sprites")
+ui = require("ui")
+assert(fish.Fish, "Failed to find fish from spawn_fish")
controller = {}
class MouseKeyboardControllerComponent extends ecs.Component
@@ -10,21 +15,26 @@ class MouseKeyboardControllerComponent extends ecs.Component
join: (ent) =>
graphic = ent\get("graphic")
@node = am.group!
- graphic.properties.node\append(@node)
+ graphic.node\append(@node)
net_component = ent\get("net")
+ @net = net_component
pred_component = ent\get("pred")
- bind_node = graphic.properties.node("bind")
+ @pred = pred_component
+ bind_node = graphic.node("bind")
+ line = ent\get("line")
+ comp = @
+ @minigame_started = false
@node\action(() =>
x,y = 0,0
accel = {x:0,y:0} -- x,y
if win\key_down("w")
- y += 0.001
+ y += 0.0006
if win\key_down("s")
- y -= 0.001
+ y -= 0.0006
if win\key_down("a")
- x -= 0.001
+ x -= 0.0006
if win\key_down("d")
- x += 0.001
+ x += 0.0006
mouse_loc = win\mouse_position!
angle = -math.atan(mouse_loc.x / mouse_loc.y)
if mouse_loc.y > 0
@@ -43,10 +53,122 @@ class MouseKeyboardControllerComponent extends ecs.Component
pred_loc = pred_component.properties.pos
world.world_x = pred_loc.x
world.world_y = pred_loc.y
+ --graphic\move(pred_loc.x, pred_loc.y)
bind_node.world_x = pred_loc.x
bind_node.world_y = pred_loc.y
-
+ if win\mouse_pressed("left")
+ if net_component.properties.casted and not pred_component.properties.can_reel and net_component.properties.reeling == 0
+ --rectract line
+ net_component.properties.casted = false
+ elseif net_component.properties.casted and pred_component.properties.can_reel and net_component.properties.reeling == 0
+ --catch a fish, gather all the info and delete the fish here.
+ print("Before starting, reeling is", net_component.properties.reeling)
+ net_component.properties.reeling = 1
+ comp.bobber = ent.bobber
+ f = ent.bobber.which
+ f.state = "catching"
+ comp\start_minigame(f)
+ f\destroy!
+ elseif net_component.properties.reeling > 0
+ print("Reeling in fish!")
+ else
+ worldpos = world.fromscreen(win\mouse_position!)
+ net_component.properties.cast = worldpos
+ net_component.properties.casted = true
+ net_component.properties.cast_time = world.sync_time!
+ print("Set cast", net_component.properties)
+ --test = require("test_entity")
+ --ent = test.TestEntity(nil, vec3(worldpos,-1.1))
+ if win\mouse_pressed("right")
+ worldpos = world.fromscreen(win\mouse_position!)
+ print("fish is:", fish)
+ f = fish.Fish(nil,worldpos)
+ f\get("net").properties.next_loc = worldpos + vec2(0,5)
+ f\get("net").properties.next_loc_time = am.current_time!
)
+ start_minigame: (fish) =>
+ @minigame_started = true
+ node = am.group!
+ hook_location = 0 -- 0 -> 1?
+ hook_width = 5
+ hook_gravity = 5 -- how quickly do we fall
+ hook_force = 80 -- how quickly do we accelerate
+ hook_vel = 0
+ hook_length = 1
+ hook_bounce_damp = 0.2 --how elastic is the bottom and top?
+ fish_width = fish.width
+ fish_force = 100
+ fish_gravity = 0
+ fish_activity = 0.1
+ fish_vel = 0
+ fish_bounce_damp = 1 -- perfectly elsastic bounce
+ reel_progress = 0
+ escape_progress = 0
+ reel_speed = 0.1
+ escape_speed = 0.01
+ reel_cutoff = 10
+ escape_cutoff = 10
+ fish_location = math.random(-256,256)
+ bar_sprite = require("ui.button")(40,-256,64,512,"").node
+ node\append(bar_sprite)
+ hook_sprite = am.translate(0,0)\append(am.scale(1)\append(am.sprite(us.hook)))
+ node\append(hook_sprite)
+ fish_g_sprite = am.sprite(us.fish_purple)
+ fish_b_sprite = am.sprite(us.fish_blue)
+ fish_sprite = am.translate(0,0)\append(am.scale(1)\append(am.group(fish_g_sprite, fish_b_sprite)))
+ node\append(fish_sprite)
+ ui.node\append(node)
+ net = @net
+ bobber = @bobber
+ assert(bobber, "Failed to find bobber")
+ node\action(() =>
+ if win\mouse_pressed("left")
+ hook_vel += hook_force
+ else
+ hook_vel -= hook_gravity
+ hook_location += hook_vel * am.delta_time
+ if hook_location < -256 + 16 -- bounce
+ hook_vel = -hook_vel * hook_bounce_damp
+ hook_location = -256 + 16
+ elseif hook_location > 256 - 16
+ hook_vel = -hook_vel * hook_bounce_damp
+ hook_location = 256 - 16
+ if math.random! < fish_activity
+ fish_vel = fish_force * math.random(-1,1)
+ fish_location += fish_vel * am.delta_time
+ if fish_location < -256 + 16 -- bounce
+ fish_vel = -fish_vel * fish_bounce_damp
+ fish_location = -256 + 16
+ elseif fish_location > 256 - 16
+ fish_vel = -fish_vel * fish_bounce_damp
+ fish_location = 256 - 16
+
+ if hook_location - hook_width > fish_location - fish_width and hook_location + hook_width < fish_location + fish_width
+ fish_b_sprite.hidden = true
+ fish_g_sprite.hidden = false
+ reel_progress += reel_speed
+ else
+ escape_progress += escape_speed
+ fish_g_sprite.hidden = true
+ fish_b_sprite.hidden = false
+ if reel_progress > reel_cutoff
+ net.properties.fish_caught += 1
+ net.properties.casted = false
+ net.properties.reeling = 0
+ ui.node\remove(node)
+ bobber.which = nil
+ elseif escape_progress > escape_cutoff
+ net.properties.casted = false
+ net.properties.reeling = 0
+ ui.node\remove(node)
+ bobber.which = nil
+ --print("reel:", reel_progress, "escape:", escape_progress)
+ -- Updates all sprites at the end?
+ hook_sprite("translate").y = hook_location
+ fish_sprite("translate").y = fish_location
+
+ )
+ --error("Starting fishing minigame")
controller.text_size = 1
controller.Controller = MouseKeyboardControllerComponent
diff --git a/src/ecs.moon b/src/ecs.moon
index 182f09d..a865801 100644
--- a/src/ecs.moon
+++ b/src/ecs.moon
@@ -9,8 +9,12 @@ class Component
@properties = properties or {}
join: (e) =>
@
+ post_join: (e) =>
+ @
leave: (e) =>
@
+ __tostring: () =>
+ return string.format("%s<%s> {\n%s\n}",@@__name,@name or "no name given",tostring(@properties))
-- Base entity of our ECS
class Entity
@@ -34,10 +38,13 @@ class Entity
@c_by_type[component.__class] = @c_by_type[component.__class] or {}
@c_by_type[component.__class][name] = component
for name, component in pairs(@components)
+ assert(component.join, "Component " .. name .. " does not have a join method.")
component\join(@)
+ component\post_join(@)
add: (cid, component) =>
component.entity = @
component\join(@)
+ component\post_join(@)
if cid == nil
cid = #@components
while @components[cid]
@@ -53,8 +60,14 @@ class Entity
component
@components[cid] = nil
@c_by_type[component.__class][cid] = nil
+ destroy: () =>
+ for name, component in pairs(@components)
+ @remove(name)
+
get: (cid) =>
@components[cid]
+ __tostring: () =>
+ return string.format("%s {\n%s\n}",@@__name,tostring(@components))
class NetworkedComponent extends Component
pack: () =>
@@ -69,6 +82,7 @@ class PredictedComponent extends Component
new: (name, properties, netc_name, calculate) =>
super(name, properties)
@netc_name = netc_name
+ assert(calculate and type(calculate) == "table", "Calculate must be a table")
@calculate = calculate
join: (entity) =>
@net = @entity\get(@netc_name)
diff --git a/src/islandgen.moon b/src/islandgen.moon
index 95e8b07..1fdd3eb 100644
--- a/src/islandgen.moon
+++ b/src/islandgen.moon
@@ -3,6 +3,10 @@ shim = require("shader_shim")
world = require("world")
color = require("color")
win = require("window")
+settings = require("settings")
+sprites = require("world.sprites")
+ecs = require("ecs")
+fish = require("spawn_fish")
gen = {}
-- Generate roughly rectangular islands
@@ -69,50 +73,111 @@ gen.generate = (seed) ->
if i < 25
gview[gi+1] = 1
-gen.protogen = (seed) ->
- geom = am.buffer(6 * 3 * 4)
- gview = geom\view("vec3")
- z = 0
- gview[1] = vec3(-10,-10,z)
- gview[2] = vec3(-10,10,z)
- gview[3] = vec3(10,10,z)
- gview[4] = vec3(10,10,z)
- gview[5] = vec3(10,-10,z)
- gview[6] = vec3(-10,-10,z)
- aspect = win.width / win.height
- s_mv = mat4(
- 1, 0, 0, 0,
- 0, aspect, 0, 0,
- 0, 0, 1, 0,
- -0.5, 0.5, 0, 4
- )
- node = shim.land\append(am.depth_test("less")\append(am.bind({
- MV: s_mv
- P: mat4(1)
- land: gview
- lamp1: vec4(0,0,0,0.1)
- lamp2: vec4(0,0,0,0)
- lamp3: vec4(0,0,0,0)
- time: am.current_time!
- background: color.am_color.background
- shadow: color.am_color.shadow
- midground: color.am_color.midground
- foreground: color.am_color.foreground
- highlight: color.am_color.highlight
- outline: color.am_color.outline
- black: color.am_color.black
- world_x: 5
- world_y: 5
- })\append(am.draw("triangles"))))
- node\action(() =>
- bind = self("bind")
- bind.time = am.current_time!
- bind.world_x = world.world_x
- bind.world_y = world.world_y
- print(world.world_x, world.world_y)
- bind.lamp1 = vec4(math.sin(am.current_time!), 0, 0, math.cos(am.current_time! * 3) + math.pi)
- )
+aspect = win.width / win.height
+aspect_inv = win.height / win.width
+class IslandGraphicsComponent extends world.GraphicsComponent
+ action: (bind) =>
+ bind.time = am.current_time! % 1000 -- loop back around so noise doesn't look wonky after a while
+ --bind.lamp1 = vec4(world.world_x + 3.35, world.world_y + 1.9, 0, 2.2) --no idea why these magic numbers
+ --bind.lamp1 = vec4(world.world_x + (0.5 * 4 * aspect) - 0.3, world.world_y + (0.5 * 4 * (aspect_inv)) + 0.7, 0, 2.2) --no idea why these magic numbers
+ --bind.lamp2 = vec4(0,0,0,3)
+ buf_size: () =>
+ 6
+ populate_buf: (geom_view, normal_view, offset) =>
+ z = 0
+ size = 10
+ --@lamp = world.level.add_lamp(vec4(0,0,0,3))
+ geom_view[1] = vec3(-size,-size,z)
+ geom_view[2] = vec3(-size,size,z)
+ geom_view[3] = vec3(size,size,z)
+ geom_view[4] = vec3(size,size,z)
+ geom_view[5] = vec3(size,-size,z)
+ geom_view[6] = vec3(-size,-size,z)
+ normal_view[1] = vec2(sprites.rocks_normal.s1, sprites.rocks_normal.t1)
+ normal_view[2] = vec2(sprites.rocks_normal.s1, sprites.rocks_normal.t2)
+ normal_view[3] = vec2(sprites.rocks_normal.s2, sprites.rocks_normal.t2)
+ normal_view[4] = vec2(sprites.rocks_normal.s2, sprites.rocks_normal.t2)
+ normal_view[5] = vec2(sprites.rocks_normal.s2, sprites.rocks_normal.t1)
+ normal_view[6] = vec2(sprites.rocks_normal.s1, sprites.rocks_normal.t1)
+
+class WaterGraphicsComponent extends world.GraphicsComponent
+ action: (bind) =>
+ bind.time = am.current_time! % 1000
+ buf_size: () =>
+ 24
+ populate_buf: (geom_view, normal_view, offset) =>
+ z = 1
+ island_size = 10 - 1
+ water_size = 20
+ uv = sprites.sea_normal
+ --down
+ geom_view[1] = vec3(-water_size,-water_size,z)
+ geom_view[2] = vec3(-island_size,-island_size,z)
+ geom_view[3] = vec3(island_size,-island_size,z)
+ geom_view[4] = vec3(island_size,-island_size,z)
+ geom_view[5] = vec3(water_size,-water_size,z)
+ geom_view[6] = vec3(-water_size,-water_size,z)
+ --left
+ geom_view[7] = vec3(-water_size,-water_size,z)
+ geom_view[8] = vec3(-island_size,island_size,z)
+ geom_view[9] = vec3(-island_size,-island_size,z)
+ geom_view[10] = vec3(-water_size,-water_size,z)
+ geom_view[11] = vec3(-water_size,water_size,z)
+ geom_view[12] = vec3(-island_size,island_size,z)
- node
+ --top
+ geom_view[13] = vec3(-water_size,water_size,z)
+ geom_view[14] = vec3(water_size,water_size,z)
+ geom_view[15] = vec3(-island_size,island_size,z)
+ geom_view[16] = vec3(-island_size,island_size,z)
+ geom_view[17] = vec3(water_size,water_size,z)
+ geom_view[18] = vec3(island_size,island_size,z)
+
+ --right
+ geom_view[19] = vec3(island_size,island_size,z)
+ geom_view[20] = vec3(water_size,water_size,z)
+ geom_view[21] = vec3(island_size,-island_size,z)
+ geom_view[22] = vec3(water_size,water_size,z)
+ geom_view[23] = vec3(water_size,-water_size,z)
+ geom_view[24] = vec3(island_size,-island_size,z)
+
+ normal_view[1] = vec2(uv.s1,uv.t1)
+ normal_view[2] = vec2(uv.s1,uv.t1)
+ normal_view[3] = vec2(uv.s2,uv.t1)
+ normal_view[4] = vec2(uv.s2,uv.t1)
+ normal_view[5] = vec2(uv.s2,uv.t1)
+ normal_view[6] = vec2(uv.s1,uv.t1)
+ normal_view[7] = vec2(uv.s1,uv.t1)
+ normal_view[8] = vec2(uv.s1,uv.t2)
+ normal_view[9] = vec2(uv.s1,uv.t1)
+ normal_view[10] = vec2(uv.s1,uv.t1)
+ normal_view[11] = vec2(uv.s1,uv.t2)
+ normal_view[12] = vec2(uv.s1,uv.t2)
+ normal_view[13] = vec2(uv.s1,uv.t2)
+ normal_view[14] = vec2(uv.s2,uv.t2)
+ normal_view[15] = vec2(uv.s1,uv.t2)
+ normal_view[16] = vec2(uv.s1,uv.t2)
+ normal_view[17] = vec2(uv.s2,uv.t2)
+ normal_view[18] = vec2(uv.s2,uv.t2)
+ normal_view[19] = vec2(uv.s2,uv.t2)
+ normal_view[20] = vec2(uv.s2,uv.t2)
+ normal_view[21] = vec2(uv.s2,uv.t1)
+ normal_view[22] = vec2(uv.s2,uv.t2)
+ normal_view[23] = vec2(uv.s2,uv.t1)
+ normal_view[24] = vec2(uv.s2,uv.t1)
+ setup: (node) =>
+ bind = node("bind")
+ print("Found bind node:",node)
+ for k,v in pairs(color.am_lake_color)
+ bind[k] = v
+ bind.water = 2
+
+gen.protogen = (seed) ->
+ ecs.Entity(nil, {
+ IslandGraphicsComponent("island")
+ })
+ ecs.Entity(nil, {
+ WaterGraphicsComponent("water")
+ })
gen
diff --git a/src/main.lua b/src/main.lua
index d57afde..517e3fd 100644
--- a/src/main.lua
+++ b/src/main.lua
@@ -2,7 +2,9 @@ require("preload")
local win = require("window")
local pp = am.postprocess({
clear_color = vec4(0.2, 0.2, 0.3, 1),
- depth_buffer = true
+ depth_buffer = true,
+ width = win.width,
+ height = win.height,
})
local world = require("world")
world.node = pp
@@ -10,10 +12,10 @@ local stars = require("shaders.stars")
pp:append(stars)
--win.scene:append(stars)
-local world_shader = require("shaders.world")
+--local world_shader = require("shaders.world")
--print("World shader:",world_shader)
--win.scene:append(world_shader.node)
-pp:append(world_shader.node)
+--pp:append(world_shader.node)
--local lake_shader = require("shaders.lake")
--pp:append(lake_shader)
@@ -41,5 +43,6 @@ require("log").observe(function(chunk)
end
print(table.concat({"[",chunk.level:upper(),"]",os.date()," > ",chunk.message}))
end)
+pp.clear_color = require("color").am_color.background
--am.eval_js(require("js_bridge"))
--local a,b = pcall(am.eval_js, require("js_bridge"))
diff --git a/src/player.moon b/src/player.moon
index fcd624b..da1c8dc 100644
--- a/src/player.moon
+++ b/src/player.moon
@@ -3,14 +3,12 @@ shim = require("shader_shim")
win = require("window")
sprites = require("world.sprites")
world = require("world")
+color = require("color")
+bobber = require("bobber")
+settings = require("settings")
aspect = win.width / win.height
+aspect_inv = win.height / win.width
player_tiny = 6
-s_mv = mat4(
- 1, 0, 0, 0,
- 0, aspect, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, player_tiny
- )
class Player extends ecs.Entity
new: (router, controller, alias) =>
@router = router
@@ -20,59 +18,141 @@ class Player extends ecs.Entity
else
error("Implement other players")
+class PlayerLineGraphicComponent extends world.GraphicsComponent
+ @line_width = 1
+ @static = false
+ @loctbl = {
+ {-1,-1}
+ {-1,1}
+ {1,1}
+ {1,1}
+ {1,-1}
+ {-1,-1}
+ }
+ buf_size: () =>
+ 6
+ populate_buf: (geom_view, normal_view, offset) =>
+ @buf = geom_view
+ h = 0.5
+ --@lamp_offset = vec4(2.5,1.4,0,0)
+ aspect = win.width / win.height
+ --@lamp = world.level.add_lamp(vec4(0,0,0,0.1 * aspect) + @lamp_offset)
+ uv = sprites.player_normal
+ utbl = {
+ [-1]: {uv.s1, uv.t1}
+ [1]: {uv.s2, uv.t2}
+ }
+ for i = 1,6
+ loctbl = @@loctbl[i]
+ geom_view[i] = vec3(@@loctbl[i][1] * h, @@loctbl[i][2] * h, -1.5)
+ normal_view[i] = vec2(utbl[@@loctbl[i][1]][1], utbl[@@loctbl[i][2]][2])
+ join: (entity) =>
+ super(entity)
+ @net = entity\get("net")
+ assert(@net, "Failed to find network component on " .. tostring(entity))
+ @pred = entity\get("pred")
+ @gc = entity\get("graphic")
+ [[
+ @gc.node\append(@node)
+ ]]
+ s = @
+ width = 0.01
+ @node\action(() =>
+ --to rotate correcly, we need to start at 00, and set the length
+ -- then rotate the whole thing
+ ce = s.pred.properties.cast_end
+ offset = s.net.properties.cast - s.pred.properties.pos
+ direction = math.atan(offset.x / offset.y) + math.pi
+ if offset.y > 0
+ direction += math.pi
+ rot = math.rotate4(direction)
+ move2 = vec3(s.pred.properties.pos, 0)
+ scale = s.pred.properties.cast_end
+ z = -0.12
+ local1 = vec4(-width, 0,z,1) * rot
+ local2 = vec4(-width, scale,z,1) * rot
+ local3 = vec4(width, scale,z,1) * rot
+ local4 = vec4(width, scale,z,1) * rot
+ local5 = vec4(width, 0,z,1) * rot
+ local6 = vec4(-width,0,z,1) * rot
+ s.buf[1] = local1.xyz + move2
+ s.buf[2] = local2.xyz + move2
+ s.buf[3] = local3.xyz + move2
+ s.buf[4] = local4.xyz + move2
+ s.buf[5] = local5.xyz + move2
+ s.buf[6] = local6.xyz + move2
+ if s.net.properties.casted and world.sync_time! - 1 > s.net.properties.cast_time and entity.bobber == nil
+ entity.bobber = bobber.Bobber(nil, s.net.properties.cast)
+ if world.level.on_land(s.net.properties.cast)
+ @action("bobbersfx", am.play(19726308, false, 1, settings.volume))
+ else
+ @action("bobbersfx", am.play(82979201, false, 1, settings.volume))
+ print("Should create bobber")
+ elseif not s.net.properties.casted and entity.bobber ~= nil
+ entity.bobber\destroy!
+ @action("bobberretract", am.play(57368801, false, 1, settings.volume))
+ entity.bobber = nil
+ )
+ forward: () =>
+ --print("Forward called", @properties)
+ super!
+ @gc\move(@properties.pos.x, @properties.pos.y)
+ face: (direction) =>
+ @.node("bind").rot = (direction ) % (math.pi * 2)
+
class PlayerGraphicComponent extends world.GraphicsComponent
- @player_size = 1
- @static = true
- new: (name, properties) =>
- properties = properties or {}
- buf = am.buffer(6 * 3 * 4)
- buf.usage = "dynamic"
- @playerbuf = buf\view("vec3")
- @playerbuf[1] = vec3(0,0,0)
- @playerbuf[2] = vec3(0,@@player_size,0)
- @playerbuf[3] = vec3(@@player_size,@@player_size,0)
- @playerbuf[4] = vec3(@@player_size,@@player_size,0)
- @playerbuf[5] = vec3(@@player_size,0,0)
- @playerbuf[6] = vec3(0,0,0)
- properties.node = shim.player\append(am.depth_test("less")\append(am.bind({
- MV: s_mv
- P: mat4(1)
- world_x: 0,
- world_y: 0,
- player: @playerbuf
- texuv: am.vec2_array({
- vec2(0,0),
- vec2(0,1),
- vec2(1,1),
- vec2(1,1),
- vec2(1,0),
- vec2(0,0)
- })
- dir: 0
- textures: sprites.guy_diffuse.texture
- })\append(am.draw("triangles"))))
- properties.node\action(() =>
- --print("Player graphic action")
+ @player_size = 0.25
+ @static = false
+ buf_size: () =>
+ 6
+ populate_buf: (geom_view, normal_view, offset) =>
+ @playerbuf = geom_view
+ h = @@player_size / 2
+ @lamp_offset = vec4(2.5,1.4,0,0)
+ @lamp = world.level.add_lamp(vec4(0,0,0,1 * aspect) + @lamp_offset)
+ geom_view[1] = vec3(-h,-h,1)
+ geom_view[2] = vec3(-h,h,1)
+ geom_view[3] = vec3(-h,-h,1)
+ geom_view[4] = vec3(h,h,1)
+ geom_view[5] = vec3(h,-h,1)
+ geom_view[6] = vec3(-h,-h,1)
+ uv = sprites.player_normal
+ normal_view[1] = vec2(uv.s1,uv.t1)
+ normal_view[2] = vec2(uv.s1,uv.t2)
+ normal_view[3] = vec2(uv.s2,uv.t2)
+ normal_view[4] = vec2(uv.s2,uv.t2)
+ normal_view[5] = vec2(uv.s2,uv.t1)
+ normal_view[6] = vec2(uv.s1,uv.t1)
+ join: (entity) =>
+ super(entity)
+ aspect = win.width / win.height
+ -- inject nodes into the scene graph
+ program = @.node("use_program")
+ pred_component = entity\get("pred")
+ graphic = entity\get("graphic")
+ @node\remove(program)
+ @node\append(am.blend("alpha")\append(program))
+ @node\action(() =>
+ pred_loc = pred_component.properties.pos
+ graphic\move(pred_loc.x, pred_loc.y)
)
- --print("Properties node is:", properties.node)
- super(name, properties)
- --print("finished init")
- @
+ --@.node("bind").highlight = color.am_color.black
move: (x,y) =>
assert(x, "x required")
assert(y, "y required")
+ world.level.move_lamp(@lamp, x + @lamp_offset.x, y + @lamp_offset.y)
h = @@player_size / 2
- @playerbuf[1] = vec3(x-h,y-h,0)
- @playerbuf[2] = vec3(x-h,y+h,0)
- @playerbuf[3] = vec3(x+h,y+h,0)
- @playerbuf[4] = vec3(x+h,y+h,0)
- @playerbuf[5] = vec3(x+h,y-h,0)
- @playerbuf[6] = vec3(x-h,y-h,0)
+ z = -1.5
+ @playerbuf[1] = vec3(x-h,y-h,z)
+ @playerbuf[2] = vec3(x-h,y+h,z)
+ @playerbuf[3] = vec3(x+h,y+h,z)
+ @playerbuf[4] = vec3(x+h,y+h,z)
+ @playerbuf[5] = vec3(x+h,y-h,z)
+ @playerbuf[6] = vec3(x-h,y-h,z)
--print("Move called", @playerbuf[1])
face: (direction) =>
- print("direction",direction)
- @properties.node("bind").dir = (direction ) % (math.pi * 2)
- --@properties.node("bind").MV =
+ --print("direction",direction)
+ @.node("bind").rot = (direction ) % (math.pi * 2)
-- In a normal simulation, velocity adds acceleration * delta time every tick, minus some friction coefficient * current velocity
@@ -97,49 +177,85 @@ class PlayerGraphicComponent extends world.GraphicsComponent
-- we want to find the location based on inital velocity and position, constant acceleration, and delta time
friction = 0.1
+cast_delay = 1
class PlayerPredictedComponent extends ecs.PredictedComponent
new: (name) =>
- super(name, {vel: vec2(0,0), pos:vec2(0,0), accel: vec2(0,0)}, "net", {
+ super(name, {vel: vec2(0,0), pos:vec2(0,0), accel: vec2(0,0), cast_end: 0, can_reel:false}, "net", {
accel:() =>
- vec2(@net.properties.accel)
+ vec2(@net.properties.accel) * (world.level.on_land(@properties.pos) and 1 or 0.5)
vel: () =>
--print("Net is ", @net.properties)
delta = world.sync_time! - @net.properties.last_update
- (@net.properties.accel / friction) + ((@net.properties.vel - (@net.properties.accel / friction)) * math.exp(-friction * delta))
+ (@properties.accel / friction) + ((@net.properties.vel - (@properties.accel / friction)) * math.exp(-friction * delta))
pos: () =>
delta = world.sync_time! - @net.properties.last_update
- friction_loss = @net.properties.accel / friction
+ friction_loss = @properties.accel / friction
-- when delta = 0 (up to date)
-- pos = (1/friction) * (velocity - friction_loss) * 1 + position
-- = 2 * (2 - 2) * 1 + position
-- = position
- (friction_loss * delta) - ((1/friction) * (@net.properties.vel - friction_loss) * (math.exp(-friction * delta))) + @properties.pos
+ (friction_loss * delta) - ((1/friction) * (@properties.vel - friction_loss) * (math.exp(-friction * delta))) + @properties.pos
+ cast_end: () =>
+ if not @net.properties.casted
+ return 0
+ since_cast = world.sync_time! - @net.properties.cast_time
+ dist = math.distance(@properties.pos, @net.properties.cast)
+ len = math.mix(0, dist, since_cast / cast_delay)
+ math.clamp(len,0,dist)
+ can_reel: () =>
+ @ent.bobber and @ent.bobber\check!
+
})
print("Right after creation, properties is",@properties)
@node = am.group!
join: (entity) =>
+ @ent = entity
@gc = entity\get("graphic")
@net = entity\get("net")
- @gc.properties.node\append(@node)
+ @gc.node\append(@node)
s = @
@node\action(() =>
s\forward!
)
+ @last_step = am.current_time!
forward: () =>
+ step_time = 0.4
+ -- Step sound effect
+ land = world.level.on_land(@properties.pos)
+ if am.current_time! - @last_step > (step_time * (land and 1 or 0.75)) and math.length(@properties.vel) > 0
+ print("Step playing")
+ if land
+ @node\action("stepsfx", am.play(60861008 + math.random(10) * 100, false, 1, settings.volume))
+ else
+ @node\action("stepsfx", am.play(78618302 + math.random(8) * 10, false, 1, settings.volume))
+ @last_step = am.current_time!
+ if @properties.cast_end > 0 and @properties.cast_end < 0.1
+ @node\action("castsfx", am.play(41228309, false, 1, settings.volume))
--print("Forward called", @properties)
super!
@gc\move(@properties.pos.x, @properties.pos.y)
-
-
class ProtoPlayer extends ecs.Entity
new: () =>
@controller = require("controllers.mouse_keyboard")
cc = require("controllers.mouse_keyboard").Controller()
gc = PlayerGraphicComponent("graphic")
pc = PlayerPredictedComponent("pred")
- nc = ecs.NetworkedComponent("net",{accel: vec2(0,0), vel: vec2(0,0), pos: vec2(0,0), name: "test", last_update: 0, dir: 0})
+ nc = ecs.NetworkedComponent("net",{
+ accel: vec2(0,0),
+ vel: vec2(0,0),
+ pos: vec2(0,0),
+ name: "test",
+ last_update: 0,
+ dir: 0
+ cast: vec2(0,0)
+ casted: false
+ cast_time: 0
+ reeling: 0
+ fish_caught: 0
+ })
+ lc = PlayerLineGraphicComponent("line")
print("Protoplayer created")
- super("test",{graphic:gc,net:nc,controller:cc,pred:pc})
+ super("test",{graphic:gc,net:nc,controller:cc,pred:pc,line:lc})
{:Player, :ProtoPlayer}
diff --git a/src/prefab/cabin.moon b/src/prefab/cabin.moon
new file mode 100644
index 0000000..915ea92
--- /dev/null
+++ b/src/prefab/cabin.moon
@@ -0,0 +1,63 @@
+world = require("world")
+sprites = require("world.sprites")
+ecs = require("ecs")
+
+class CabinGraphicsComponent extends world.GraphicsComponent
+ --
+ -- #####
+ -- # #
+ -- ##/##
+ -- 3x3 floor, 1x3 * 3 walls, 1x1 * 2 door side walls, 1x1 door
+ buf_size: () =>
+ (6*9) + (6*9) + (6* 2) + (6 * 1)
+
+ populate_buf: (geom_view, normal_view, offset) =>
+ z1 = -0.01
+ z2 = -1
+ iuv = sprites.wall_inside_normal
+ ouv = sprites.wall_outside_normal
+ fuv = sprites.floor_normal
+ wall = (geom, uv, offset, start, finish, texture) ->
+ geom[offset + 0] = vec3(start.x, start.y, z1)
+ geom[offset + 1] = vec3(start.x, start.y, z2)
+ geom[offset + 2] = vec3(finish.x, finish.y, z2)
+ geom[offset + 3] = vec3(finish.x, finish.y, z2)
+ geom[offset + 4] = vec3(finish.x, finish.y, z1)
+ geom[offset + 5] = vec3(start.x, start.y, z1)
+ uv[offset+0] = vec2(texture.s1,texture.t1)
+ uv[offset+1] = vec2(texture.s1,texture.t2)
+ uv[offset+2] = vec2(texture.s2,texture.t2)
+ uv[offset+3] = vec2(texture.s2,texture.t2)
+ uv[offset+4] = vec2(texture.s2,texture.t1)
+ uv[offset+5] = vec2(texture.s1,texture.t1)
+
+ floor = (geom, uv, offset, start, finish) ->
+ geom[offset + 0] = vec3(start.x,start.y,z1)
+ geom[offset + 1] = vec3(start.x,finish.y,z1)
+ geom[offset + 2] = vec3(finish.x,finish.y,z1)
+ geom[offset + 3] = vec3(finish.x,finish.y,z1)
+ geom[offset + 4] = vec3(finish.x,start.y,z1)
+ geom[offset + 5] = vec3(start.x,start.y,z1)
+ normal_view[offset + 0] = vec2(fuv.s1, fuv.t1)
+ normal_view[offset + 1] = vec2(fuv.s1, fuv.t2)
+ normal_view[offset + 2] = vec2(fuv.s2, fuv.t2)
+ normal_view[offset + 3] = vec2(fuv.s2, fuv.t2)
+ normal_view[offset + 4] = vec2(fuv.s2, fuv.t1)
+ normal_view[offset + 5] = vec2(fuv.s1, fuv.t1)
+
+ --left wall
+ j = 1
+ wall(geom_view, normal_view, j, vec2(-2,-2),vec2(-2,0), sprites.wall_inside_normal)
+ j += 6
+ for floorx = 1,3
+ for floory = 1,3
+ floor(geom_view, normal_view, j, vec2(-2 + (2*floorx), -2 + (2*floory)), vec2(2*floorx, 2*floory))
+ j += 6
+
+
+
+cabin = ecs.Entity("cabin",{
+ graphic: CabinGraphicsComponent("graphic")
+})
+
+cabin
diff --git a/src/preload.lua b/src/preload.lua
index ca2dc9a..5b4034d 100644
--- a/src/preload.lua
+++ b/src/preload.lua
@@ -3,6 +3,7 @@
--[[
rewrite traceback function to map file names and line numbers to moonscript
]]
+local require_order = {}
local old_traceback = debug.traceback
debug.traceback = function(...)
local orig_traceback = old_traceback(...)
@@ -23,9 +24,30 @@ debug.traceback = function(...)
end
end
return string.format("%s:%d:", filename, linenum)
- end)
+ end) .. "\nRequire order: [" .. table.concat(require_order, ",\n") .. "]"
end
+local old_require = require
+local required = {}
+require = function(...)
+ args = {...}
+ if not required[args[1]] then
+ required[args[1]] = true
+ table.insert(require_order, args[1])
+ end
+ return old_require(...)
+end
+
+--[[
+Display where print statements are comming from
+
+local oldprint = print
+print = function(...)
+ oldprint(...)
+ oldprint(debug.traceback())
+end
+]]
+
-- Override tostring to display more info about the table
local old_tostring = tostring
local numtabs = 0
diff --git a/src/router.moon b/src/router.moon
index 2001952..94dbedd 100644
--- a/src/router.moon
+++ b/src/router.moon
@@ -88,6 +88,8 @@ class Router
-- "uninitialized", "peer", "candidate", "elected"
@state = "uninitialized"
+ -- Methods to call when our state changes
+ @onchange = {}
-- [peerid] = "votes for peerid"
@nonce = 0
@@ -202,6 +204,10 @@ class Router
net.pump!
return ret
+ onchange: (callback) =>
+ table.insert(@onchange, callback)
+ #@onchange
+
broadcast: (msgfmt, message) =>
for peerid, conn in pairs(@peerlist)
if peerid ~= @peer.id
diff --git a/src/settings.moon b/src/settings.moon
new file mode 100644
index 0000000..0cd1d76
--- /dev/null
+++ b/src/settings.moon
@@ -0,0 +1,11 @@
+-- like world, just holds state, but the per-client state instead of any shared state.
+
+settings = {}
+
+-- Passed to the land shader to add noise to lamps
+settings.streamer = 0
+
+-- Volume for sound effects
+settings.volume = 1
+
+settings
diff --git a/src/shaders/lake.frag b/src/shaders/lake.frag
index d45917e..c1c23f0 100644
--- a/src/shaders/lake.frag
+++ b/src/shaders/lake.frag
@@ -1,5 +1,93 @@
precision mediump float;
-uniform vec4 color;
+uniform vec4 black;
+uniform vec4 outline;
+uniform vec4 highlight;
+uniform vec4 foreground;
+uniform vec4 midground;
+uniform vec4 shadow;
+uniform vec4 background;
+uniform vec4 lamp1; //vec3 position, float strength
+uniform vec4 lamp2;
+uniform vec4 lamp3; // max 3 lamps per shaded vertex
+uniform vec4 lamp4;
+uniform vec4 lamp5;
+uniform vec4 lamp6;
+uniform vec4 lamp7;
+uniform vec4 lamp8;
+uniform float streamer; // turn off the noise in the light
+uniform float time; //used for noise
+uniform sampler2D atlas;
+uniform sampler2D previous;
+uniform float nlamps;
+varying vec2 worldxy;
+varying vec2 norm;
+
+// Author @patriciogv - 2015
+float random (vec2 st) {
+ return fract(
+ sin(
+ dot(st.xy,vec2(12.9898,78.233))
+ ) *
+ 43758.5453123
+ );
+}
+
+// stolen from https://www.shadertoy.com/view/Msf3WH
+float noise( in vec2 p )
+{
+ const float K1 = 0.366025404; // (sqrt(3)-1)/2;
+ const float K2 = 0.211324865; // (3-sqrt(3))/6;
+
+ vec2 i = floor( p + (p.x+p.y)*K1 );
+ vec2 a = p - i + (i.x+i.y)*K2;
+ float m = step(a.y,a.x);
+ vec2 o = vec2(m,1.0-m);
+ vec2 b = a - o + K2;
+ vec2 c = a - 1.0 + 2.0*K2;
+ vec3 h = max( 0.5-vec3(dot(a,a), dot(b,b), dot(c,c) ), 0.0 );
+ vec3 n = h*h*h*h*vec3( dot(a,random(i+0.0)), dot(b,random(i+o)), dot(c,random(i+1.0)));
+ return dot( n, vec3(70.0) );
+}
+
void main() {
- gl_FragColor = color;
+ vec4 coord = gl_FragCoord + vec4(worldxy * 256., 0, 0);
+ /*
+ coord.x -= worldxy.x;
+ coord.y -= worldxy.y;
+ */
+ //coord = coord / 1000.;
+ // calculate color at this pixel
+ vec4 normal = texture2D(atlas, norm);
+ float color = 0.;
+ vec4 lamp1_norm = lamp1 * 256.;
+ color += lamp1_norm.w - distance(lamp1_norm.xy - worldxy, coord.xy);
+ color = max(color,(lamp2.w * 256.) - distance((lamp2.xy * 256.) - worldxy, coord.xy));
+ color = max(color,(lamp3.w * 256.) - distance((lamp3.xy * 256.) - worldxy, coord.xy));
+ // divide to get a normalized color
+ //color /= (256. * max(max(lamp1.w, lamp2.w), lamp3.w));
+ color /= 256. * 5.;
+ //color = sqrt(color / 2046.);
+ // Sett the normal texture under our lamplight
+ color = dot(vec4(color),normal) / 1.;
+ // make the colors fuzzy near the border (or don't if we're streaming)
+ float rng = random(vec2(coord.x, coord.y) + vec2(color, time));
+ color -= (pow(rng / 1.3, 10. * color)) * streamer;
+ // add noise to the water
+ /* */
+ if(color > 1.)
+ gl_FragColor = highlight * normal.a;
+ else if(color > 0.8)
+ gl_FragColor = foreground * normal.a;
+ else if(color > 0.6)
+ gl_FragColor = midground * normal.a;
+ else if(color > 0.4)
+ gl_FragColor = background * normal.a;
+ else if(color > 0.2)
+ gl_FragColor = shadow * normal.a;
+ else
+ gl_FragColor = black * normal.a;
+ /*
+ gl_FragColor = normal* vec4(color , color, color,1.);
+ */
+ //gl_FragColor = normal* vec4(color , color / 10., color / 1024.,1.);
}
diff --git a/src/shaders/land.frag b/src/shaders/land.frag
index 3c23990..1eb8d93 100644
--- a/src/shaders/land.frag
+++ b/src/shaders/land.frag
@@ -9,8 +9,18 @@ uniform vec4 background;
uniform vec4 lamp1; //vec3 position, float strength
uniform vec4 lamp2;
uniform vec4 lamp3; // max 3 lamps per shaded vertex
+uniform vec4 lamp4;
+uniform vec4 lamp5;
+uniform vec4 lamp6;
+uniform vec4 lamp7;
+uniform vec4 lamp8;
+uniform float streamer; // turn off the noise in the light
+uniform float time; //used for noise
+uniform sampler2D atlas;
+uniform float nlamps;
+uniform float water;
varying vec2 worldxy;
-varying mat4 pre;
+varying vec2 norm;
// Author @patriciogv - 2015
float random (vec2 st) {
@@ -22,6 +32,28 @@ float random (vec2 st) {
);
}
+// stolen from https://www.shadertoy.com/view/Msf3WH
+vec2 hash( vec2 p ) // replace this by something better
+{
+ p = vec2( dot(p,vec2(127.1,311.7)), dot(p,vec2(269.5,183.3)) );
+ return -1.0 + 2.0*fract(sin(p)*43758.5453123);
+}
+float noise( in vec2 p )
+{
+ const float K1 = 0.366025404; // (sqrt(3)-1)/2;
+ const float K2 = 0.211324865; // (3-sqrt(3))/6;
+
+ vec2 i = floor( p + (p.x+p.y)*K1 );
+ vec2 a = p - i + (i.x+i.y)*K2;
+ float m = step(a.y,a.x);
+ vec2 o = vec2(m,1.0-m);
+ vec2 b = a - o + K2;
+ vec2 c = a - 1.0 + 2.0*K2;
+ vec3 h = max( 0.5-vec3(dot(a,a), dot(b,b), dot(c,c) ), 0.0 );
+ vec3 n = h*h*h*h*vec3( dot(a,hash(i+0.0)), dot(b,hash(i+o)), dot(c,hash(i+1.0)));
+ return dot( n, vec3(70.0) );
+}
+
void main() {
vec4 coord = gl_FragCoord + vec4(worldxy * 256., 0, 0);
/*
@@ -29,22 +61,40 @@ void main() {
coord.y -= worldxy.y;
*/
//coord = coord / 1000.;
+ // calculate color at this pixel
+ vec4 normal = texture2D(atlas, norm);
float color = 0.;
- vec2 lamppos = (lamp1.xy * 256.) - (worldxy * 1.);
- color += (lamp1.w * 256.) - distance((lamp1.xy * 256.) - worldxy, coord.xy);
- /*
+ vec4 lamp1_norm = lamp1 * 256.;
+ color += lamp1_norm.w - distance(lamp1_norm.xy - worldxy, coord.xy);
+ color = max(color,(lamp2.w * 256.) - distance((lamp2.xy * 256.) - worldxy, coord.xy));
+ color = max(color,(lamp3.w * 256.) - distance((lamp3.xy * 256.) - worldxy, coord.xy));
+ // divide to get a normalized color
+ //color /= (256. * max(max(lamp1.w, lamp2.w), lamp3.w));
+ color /= 256. * 5.;
+ //color = sqrt(color / 2046.);
+ // see the normal texture under the color
+ color = dot(vec4(color),normal) / 1.;
+ // make the colors fuzzy near the border (or don't if we're streaming)
+ float rng = random(vec2(coord.x, coord.y) + vec2(color, time));
+ color -= (pow(rng / 1.3, 10. * color)) * streamer;
+ // add noise to water
+ if(water > 1.)
+ color += (noise(coord.xy + vec2(time, time)) - 0.0) * 0.1;
+ /* */
if(color > 1.)
- gl_FragColor = highlight;
+ gl_FragColor = highlight * normal.a;
else if(color > 0.8)
- gl_FragColor = foreground;
+ gl_FragColor = foreground * normal.a;
else if(color > 0.6)
- gl_FragColor = midground;
+ gl_FragColor = midground * normal.a;
else if(color > 0.4)
- gl_FragColor = background;
+ gl_FragColor = background * normal.a;
else if(color > 0.2)
- gl_FragColor = shadow;
+ gl_FragColor = shadow * normal.a;
else
- gl_FragColor = black;
+ gl_FragColor = black * normal.a;
+ /*
+ gl_FragColor = normal* vec4(color , color, color,1.);
*/
- gl_FragColor = vec4(color / (256. * lamp1.w), color / (256. * lamp1.w), color / (256. * lamp1.w),1.);
+ //gl_FragColor = normal* vec4(color , color / 10., color / 1024.,1.);
}
diff --git a/src/shaders/land.vert b/src/shaders/land.vert
index 2004ab3..1c9b9f3 100644
--- a/src/shaders/land.vert
+++ b/src/shaders/land.vert
@@ -1,14 +1,26 @@
precision highp float;
attribute vec3 land;
-uniform float time; //used for noise
+attribute vec2 landnormal;
+uniform float rot;
uniform float world_x;
uniform float world_y;
uniform mat4 MV;
uniform mat4 P;
varying vec2 worldxy;
varying mat4 pre;
+varying vec2 norm;
void main() {
+ norm = landnormal;
+ mat2 rotate = mat2(
+ cos(rot), -sin(rot),
+ sin(rot), cos(rot)
+ );
worldxy = vec2(world_x, world_y);
pre = P * MV;
- gl_Position = P * MV * vec4(land.x - world_x, land.y - world_y, 0., 1.0);
+ vec2 local = (land.xy - worldxy) * rotate;
+ float z_scale = 0.5;
+ // clamp so that everything becomes orthographic once we move away
+ float xoff = clamp(land.z * local.x * z_scale, -0.5, 0.5);
+ float yoff = clamp(land.z * local.y * z_scale, -0.5, 0.5);
+ gl_Position = P * MV * vec4(local.xy - vec2(xoff, yoff), land.z, 1.0);
}
diff --git a/src/shaders/stars.frag b/src/shaders/stars.frag
new file mode 100644
index 0000000..d45917e
--- /dev/null
+++ b/src/shaders/stars.frag
@@ -0,0 +1,5 @@
+precision mediump float;
+uniform vec4 color;
+void main() {
+ gl_FragColor = color;
+}
diff --git a/src/shaders/stars.lua b/src/shaders/stars.lua
index 8d54b16..3e4138e 100644
--- a/src/shaders/stars.lua
+++ b/src/shaders/stars.lua
@@ -1,57 +1,43 @@
local win = require("window")
local color = require("color")
local world = require("world")
-local numstars = 400 -- we might have as many as 4 over
+local shim = require("shader_shim")
+local numstars = 500 -- we might have as many as 4 over
local genned_stars = 0
local period_x = 3
local period_y = 3
local stars = {}
-while genned_stars < numstars do
+local tries = 0
+aspect = win.width / win.height
+while genned_stars < numstars and tries < 100000 do
local rngx = math.random()
local xpos = rngx * win.width --* (period_x - 1)
local rngy = math.random()
local ypos = rngy * win.height --* (period_y - 1)
local blinks = math.random() > 0.3 and (math.random() * 2 * math.pi) or 0
- stars[#stars+1] = vec3(xpos, ypos, blinks)
- genned_stars = genned_stars + 1
- if xpos < win.width then
- -- duplicate on the last screen
- stars[#stars+1] = vec3(xpos + (win.width * (period_x-2)), ypos, blinks)
- genned_stars = genned_stars + 1
- end
- if ypos < win.height then
- stars[#stars+1] = vec3(xpos, ypos + (win.height * (period_y-2)), blinks)
- genned_stars = genned_stars + 1
- end
- if xpos < win.width and ypos < win.height then
- stars[#stars+1] = vec3(xpos + (win.width * (period_x-2)), ypos+(win.height * (period_y-2)),blinks)
+ --if math.distance(vec2(rngx,rngy), vec2(0.53,0.5)) > 0.5 then
+ local off = vec2(math.abs(rngx - 0.50) * aspect, math.abs(rngy-0.5))
+ if math.length(off) > 0.5 then
+ stars[#stars+1] = vec3(xpos, ypos, blinks)
genned_stars = genned_stars + 1
+ if xpos < win.width then
+ -- duplicate on the last screen
+ stars[#stars+1] = vec3(xpos + (win.width * (period_x-2)), ypos, blinks)
+ genned_stars = genned_stars + 1
+ end
+ if ypos < win.height then
+ stars[#stars+1] = vec3(xpos, ypos + (win.height * (period_y-2)), blinks)
+ genned_stars = genned_stars + 1
+ end
+ if xpos < win.width and ypos < win.height then
+ stars[#stars+1] = vec3(xpos + (win.width * (period_x-2)), ypos+(win.height * (period_y-2)),blinks)
+ genned_stars = genned_stars + 1
+ end
end
+ tries = tries + 1
end
-local node = am.use_program(am.program([[
- precision highp float;
- attribute vec3 stars;
- uniform float time;
- uniform float world_x;
- uniform float world_y;
- uniform float world_x_period;
- uniform float world_y_period;
- uniform mat4 MV;
- uniform mat4 P;
- void main() {
- float world_x_off = mod(world_x, world_x_period);
- float world_y_off = mod(world_y, world_y_period);
- gl_Position = P * MV * vec4(stars.x - world_x_off, stars.y - world_y_off, 0., 1.0);
- float intensity = sin(stars.z + time) * cos(time) + 1.;
- gl_PointSize = pow(intensity, 2.) * stars.z * 0.3;
- }
- ]],[[
- precision mediump float;
- uniform vec4 color;
- void main() {
- gl_FragColor = color;
- }
-]]))
+assert(genned_stars == numstars, "Failed to generate stars")
+local node = am.blend("premult") ^ shim.stars
^ am.bind({
MV = mat4(
1, 0, 0, 0,
@@ -66,11 +52,24 @@ local node = am.use_program(am.program([[
world_y = am.current_time(),
world_y_period = (period_y - 2) * win.height,
time = am.current_time(),
+ lamp1 = vec3(0),
+ lamp2 = vec3(0),
+ lamp3 = vec3(0),
+ lamp4 = vec3(0),
+ lamp5 = vec3(0),
+ lamp6 = vec3(0),
+ lamp7 = vec3(0),
+ lamp8 = vec3(0)
})
^ am.draw("points")
node:action(function(self)
self("bind").time = am.current_time()
self("bind").world_x = world.world_x
self("bind").world_y = world.world_y
+ local lamps = world.level.lamps_on_screen()
+ for i,v in pairs(lamps) do
+ print("Setting lamp", i, "to", v)
+ self("bind")["lamp" .. tostring(i)] = v
+ end
end)
return node
diff --git a/src/shaders/stars.vert b/src/shaders/stars.vert
new file mode 100644
index 0000000..8737482
--- /dev/null
+++ b/src/shaders/stars.vert
@@ -0,0 +1,30 @@
+precision highp float;
+attribute vec3 stars;
+uniform float time;
+uniform float world_x;
+uniform float world_y;
+uniform float world_x_period;
+uniform float world_y_period;
+uniform vec4 lamp1;
+uniform vec4 lamp2;
+uniform vec4 lamp3;
+uniform vec4 lamp4;
+uniform vec4 lamp5;
+uniform vec4 lamp6;
+uniform vec4 lamp7;
+uniform vec4 lamp8;
+uniform mat4 MV;
+uniform mat4 P;
+void main() {
+ float world_x_off = mod(world_x, world_x_period);
+ float world_y_off = mod(world_y, world_y_period);
+ vec4 pos = P * MV * vec4(stars.x - world_x_off, stars.y - world_y_off, -0.1, 1.0);
+ gl_Position = pos;
+ float intensity = sin(stars.z + time) * cos(time) + 1.;
+ /*
+ if(distance(pos.xyz, lamp1.xyz) < 80.)
+ intensity = 0.;
+ */
+ gl_PointSize = pow(intensity, 2.) * stars.z * 0.3;
+ //gl_PointSize = distance(pos.xyz, lamp1.xyz);
+}
diff --git a/src/spawn_fish.moon b/src/spawn_fish.moon
new file mode 100644
index 0000000..5bc090b
--- /dev/null
+++ b/src/spawn_fish.moon
@@ -0,0 +1,130 @@
+router = require("router")
+ecs = require("ecs")
+world = require("world")
+win = require("window")
+sprites = require("world.sprites")
+
+class FishGraphicComponent extends world.GraphicsComponent
+ @fish_size = 0.5
+ @static = false
+ @loctbl = {
+ {-1,-1}
+ {-1,1}
+ {1,1}
+ {1,1}
+ {1,-1}
+ {-1,-1}
+ }
+ buf_size: () =>
+ 6
+ populate_buf: (geom_view, normal_view, offset) =>
+ @buf = geom_view
+ h = @@fish_size / 2
+ --@lamp_offset = vec4(2.5,1.4,0,0)
+ aspect = win.width / win.height
+ --@lamp = world.level.add_lamp(vec4(0,0,0,0.1 * aspect) + @lamp_offset)
+ for i = 1,6
+ loctbl = @@loctbl[i]
+ geom_view[i] = vec3(@@loctbl[i][1] * h, @@loctbl[i][2] * h, -1.5)
+ uv = sprites.player_normal
+ normal_view[1] = vec2(uv.s1,uv.t1)
+ normal_view[2] = vec2(uv.s1,uv.t2)
+ normal_view[3] = vec2(uv.s2,uv.t2)
+ normal_view[4] = vec2(uv.s2,uv.t2)
+ normal_view[5] = vec2(uv.s2,uv.t1)
+ normal_view[6] = vec2(uv.s1,uv.t1)
+ join: (entity) =>
+ super(entity)
+ aspect = win.width / win.height
+ program = @.node("use_program")
+ @pred = entity\get("pred")
+ graphic = entity\get("graphic")
+ assert(@pred, "Fish graphic must have a predicted component")
+ @node\remove(program)
+ @node\append(am.blend("alpha")\append(program))
+ @ent = entity
+ comp = @
+ move: (pos) =>
+ h = @@fish_size / 2
+ --print("Calling move with", pos)
+ --if @ent.state ~= "swimming"
+ -- error("called move while not swimming")
+ for i = 1,6
+ @buf[i] = vec3(@@loctbl[i][1] * h, @@loctbl[i][2] * h, -0.13) + vec3(pos.x, pos.y, 0)
+
+friction = 0.1
+class FishPredictedComponent extends ecs.PredictedComponent
+ new: (id) =>
+ fish_speed = 0.00001
+ super(id, {accel: vec2(0,0), vel: vec2(0,0), pos: vec2(0,0)}, "netc", {
+ accel: () =>
+ --print("ent state:", @cc.state)
+ if @cc.state ~= "swimming"
+ return vec2(0,0)
+ localized = @net.properties.next_loc - @properties.pos
+ --direction = math.atan(localized.y / localized.x)
+ math.normalize(localized + @properties.vel) * fish_speed
+ vel: () =>
+ --print("Before calculating vel, properties was ", @properties)
+ delta = world.sync_time! - @net.properties.next_loc_time
+ --print("Delta time:", delta)
+ (@properties.accel / friction) + ((@properties.vel - (@properties.accel / friction)) * math.exp(-friction * delta))
+ pos: () =>
+ if @properties.pos.x > 20
+ error("Very far, stopping")
+ delta = world.sync_time! - @net.properties.next_loc_time
+ friction_loss = @properties.accel / friction
+ (friction_loss * delta) - ((1/friction) * (@properties.vel - friction_loss) * (math.exp(-friction * delta))) + @properties.pos
+ })
+ @node = am.group!
+ join: (entity) =>
+ @net = entity\get("net")
+ @gc = entity\get("graphic")
+ @properties.pos = @net.properties.pos
+ @cc = entity\get("control")
+ @ent = entity
+ print("Got graphic component:",@gc, @gc.node)
+ print("And my node is", @node)
+ @gc.node\append(@node)
+ s = @
+ @node\action(() =>
+ s\forward!
+ )
+ forward: () =>
+ super!
+ if @ent.state == "catching"
+ @gc.node.hidden=true
+ else
+ @gc\move(@properties.pos)
+
+class Fish extends ecs.Entity
+ new: (id, pos) =>
+ @width = 40 -- TODO: randomize fish width
+ components = {
+ pred: FishPredictedComponent("pred")
+ net: ecs.NetworkedComponent("net",{pos: pos, next_loc: pos, next_loc_time: am.current_time!})
+ graphic: FishGraphicComponent("graphic")
+ control: require("controllers.fish").FishControllerComponent()
+ phys: world.PhysicsComponent("phys",{},"circle",{pos.x, pos.y, @width / 256})
+ }
+ super(id, components)
+ destroy: (...) =>
+ super(...)
+ error("Where did fish go")
+
+class SpawnFishComponent extends ecs.Component
+ new: (id, properties, spawnrect) =>
+ super(id, properties)
+
+ join: (entity) =>
+ graphic = entity\get("graphic")
+ router = router.r!
+ set_spawnable = () ->
+ if router.state == "elected"
+ graphic\action(() ->
+ error("Spawn fish callback")
+ )
+ set_spawnable!
+ router\onchange(set_spawnable)
+
+{:Fish, :SpawnFishComponent}
diff --git a/src/test_entity.moon b/src/test_entity.moon
new file mode 100644
index 0000000..a9ae170
--- /dev/null
+++ b/src/test_entity.moon
@@ -0,0 +1,36 @@
+
+ecs = require("ecs")
+world = require("world")
+sprites = require("world.sprites")
+
+class TestGraphicComponent extends world.GraphicsComponent
+ @test_size = 0.5
+ @static = false
+ buf_size: () =>
+ 6
+ populate_buf: (geom_view, normal_view, offset) =>
+ assert(@properties.pos, "Test entity needs a position")
+ @buf = geom_view
+ h = @@test_size / 2
+ pos = @properties.pos
+ geom_view[1] = vec3(-h,-h,1) + pos
+ geom_view[2] = vec3(-h,h,1) + pos
+ geom_view[3] = vec3(-h,-h,1) + pos
+ geom_view[4] = vec3(h,h,1) + pos
+ geom_view[5] = vec3(h,-h,1) + pos
+ geom_view[6] = vec3(-h,-h,1) + pos
+ uv = sprites.player_normal
+ normal_view[1] = vec2(uv.s1,uv.t1)
+ normal_view[2] = vec2(uv.s1,uv.t2)
+ normal_view[3] = vec2(uv.s2,uv.t2)
+ normal_view[4] = vec2(uv.s2,uv.t2)
+ normal_view[5] = vec2(uv.s2,uv.t1)
+ normal_view[6] = vec2(uv.s1,uv.t1)
+
+class TestEntity extends ecs.Entity
+ new: (id, pos) =>
+ super(id,{
+ graphic: TestGraphicComponent("graphic",{pos: pos})
+ })
+
+{:TestEntity}
diff --git a/src/window.moon b/src/window.moon
index 8aa8f2a..367cd1c 100644
--- a/src/window.moon
+++ b/src/window.moon
@@ -1,10 +1,10 @@
-
+color = require("color")
-- Special file to hold the window, no dependencies!
win = am.window{
title: "ggj25"
width: 1280
height: 720
- clear_color: vec4(0.2, 0.2, 0.3, 1)
+ clear_color: color.am_color.background
--depth_buffer: true
}
win.scene = am.group!
diff --git a/src/world.moon b/src/world.moon
index 6a0eed8..60cb57b 100644
--- a/src/world.moon
+++ b/src/world.moon
@@ -2,8 +2,12 @@
win = require("window")
hc = require("party.hc.init")
ecs = require("ecs")
+settings = require("settings")
+color = require("color")
+shim = require("shader_shim")
+log = require("log")
-
+MAX_LAMPS = 8
print("hc:", hc)
--Use a collider to decide what to render
x = {
@@ -20,22 +24,155 @@ x = {
graphics:{}
entities:{}
graphic_world: hc.new(5)
+ physics_world: hc.new(1)
+ lamps: {}
+ lamps_rev: {}
}
sync_time: () ->
am.current_time!
}
-x.level.collider = x.level.graphic_world\rectangle(0,0,1,1/win.width)
+x.level.collider = x.level.graphic_world\rectangle(-1,-1,2,2)
+x.level.add_lamp = (lamp) -> --vector4, vec3 position, strength
+ shape = x.level.graphic_world\circle(lamp.x, lamp.y, lamp.w * 2)
+ x.level.lamps[#x.level.lamps+1] = {lamp, shape}
+ x.level.lamps_rev[shape] = #x.level.lamps
+ #x.level.lamps
+x.level.move_lamp = (id,newx, newy) ->
+ oldlamp = x.level.lamps[id][1]
+ x.level.lamps[id][2]\moveTo(newx, newy)
+ x.level.lamps[id][1] = vec4(newx, newy, oldlamp.z, oldlamp.w)
+x.level.remove_lap = (id) ->
+ lamp = table.remove(x.level.lamps,id)
+ x.level.lamps_rev[lamp[2]] = nil
+ x.level.graphic_world\remove(lamp[2])
+x.level.lamps_on_screen = () ->
+ lamps = {}
+ i = 0
+ -- collider world is not alligned to the graphic world
+ x.level.collider\moveTo(x.world_x + 3, x.world_y + 3)
+ for shape,_ in pairs(x.level.graphic_world\collisions(x.level.collider))
+ index = x.level.lamps_rev[shape]
+ lamp = x.level.lamps[index]
+ table.insert(lamps, lamp[1])
+ i += i
+ if i > MAX_LAMPS
+ return lamps
+ lamps
+x.fromscreen = (pos) ->
+ print("fromscreen pos is", pos)
+ -- convert creen pixel coords to world xy coords
+ localx = (pos.x * (win.width / win.height) * 4) / (win.width + 1)
+ localy = (pos.y * 1 * 4) / win.height
+ globalx = x.world_x + localx
+ globaly = x.world_y + localy
+ vec2(globalx, globaly)
+x.level.on_land = (pos) ->
+ not (pos.x > 10 or pos.x < -10 or pos.y > 10 or pos.y < -10)
+
+class PhysicsComponent extends ecs.Component
+ new: (name, properties, shape, args) =>
+ log.info("Created a physics component " .. shape .. " with " .. tostring(args), {"phys"})
+ assert(args, "Physcs Component must be passed args")
+ assert(type(shape) == "string" , "Shape must be a string, was " .. tostring(shape))
+ @node = am.group!
+ super(name, properties)
+ hc = x.level.physics_world
+ table.insert(args,1,hc)
+ print("Creating a physics component with", args)
+ @shape = hc[shape](unpack(args))
+ @shape.component = @
+ join: (entity) =>
+ super(entity)
+ @ent = entity
+ leave: () =>
+ super!
+ x.level.physics_world\remove(@shape)
+ collisions: () =>
+ x.level.physics_world\collisions(@shape)
+
class GraphicsComponent extends ecs.Component
new: (name, properties) =>
print("Got name", name, "and properties", properties)
- assert(properties and properties.node , "Failed to find node for graphics component")
+ @node = am.group!
+ --assert(properties and properties.node , "Failed to find node for graphics component")
super(name, properties)
- x.node\append(properties.node)
+ --x.node\append(properties.node)
+ join: (entity) =>
+ buf_size = @buf_size!
+ print("Creating entity " .. entity.id .. " with graphic component with " .. buf_size .. " vertexes")
+ @geom_buffer = am.buffer(buf_size * 3 * 4)\view("vec3") -- 3 floats per vertex, 4 bytes per float
+ @norm_buffer = am.buffer(buf_size * 2 * 4)\view("vec2") -- 2 floats per uv, 4 bytes per float
+ @populate_buf(@geom_buffer, @norm_buffer)
+ aspect = win.width / win.height
+ s_mv = mat4(
+ 1, 0, 0, 0,
+ 0, aspect, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 4
+ )
+ binds = {
+ MV: s_mv
+ P: mat4(1)
+ land: @geom_buffer
+ landnormal: @norm_buffer
+ time: am.current_time!
+ atlas: require("world.sprites").rocks_normal.texture
+ streamer: 1
+ world_x: x.world_x
+ world_y: x.world_y
+ rot: 0
+ water: 0
+ }
+ for color, value in pairs(color.am_color)
+ binds[color] = value
+ for i = 1,8 do
+ binds["lamp" .. tostring(i)] = vec4(0)
+ @node\append(
+ shim.land\append(
+ am.depth_test("less")\append(
+ am.cull_face("front")\append(
+ am.bind(binds)\append(
+ am.draw("triangles")
+ )))))
+ print("graphic node created for",@,@node)
+ component = @
+ @node\action(() =>
+ bind = component.node("bind")
+ if component.action
+ component\action(bind)
+ bind.world_x = x.world_x
+ bind.world_y = x.world_y
+ --find the lamps in screen to render
+ lamps = x.level.lamps_on_screen!
+ --print("Found lamps:", lamps, "at",x.world_x, x.world_y)
+ for i = 1,8 do
+ if i <= #lamps
+ --print("Setting lamp",i,"to",lamps[i])
+ bind["lamp" .. tostring(i)] = lamps[i]
+ else
+ bind["lamp" .. tostring(i)] = vec4(0)
+ --bind.lamps = am.vec4_array(lamps)
+ --bind.nlamps = #lamps
+ --print(world.world_x, world.world_y)
+ --bind.lamp1 = vec4(math.sin(am.current_time!), 0, 0, math.cos(am.current_time! * 3) + math.pi)
+ -- magic numbers to center the player :/
+ bind.time = am.current_time! % 1000 -- loop back around so noise doesn't look wonky after a while
+ bind.streamer = settings.streamer
+ )
+ if @setup
+ @setup(@node)
+ print("Appending ", @node, " to the scene")
+ x.node\append(@node)
+ leave: () =>
+ x.node\remove(@node)
static: () =>
@@static
- node: () =>
- @properties.node
+ buf_size: () =>
+ error("Subclasses of GraphicsComponent must implement buffer size")
+ populate_buf: (geom_view, normal_view, offset) =>
+ error("Subclasses of GraphicsComponent must implement buffer populate method")
x.GraphicsComponent = GraphicsComponent
+x.PhysicsComponent = PhysicsComponent
x
diff --git a/src/worldgen.moon b/src/worldgen.moon
index 5fcefaf..e4818d4 100644
--- a/src/worldgen.moon
+++ b/src/worldgen.moon
@@ -9,9 +9,13 @@ island = require("islandgen")
--Check for setup
--char = player.Player(world.router, world.controller ,text.text.text)
--level = island.generate(1234)
-level = island.protogen(1234)
-world.node\append(level)
+island_ent = island.protogen(1234)
+cabin = require("prefab.cabin")
+--world.node\append(level)
--world.controller = require("controllers.mouse_keyboard")
--world.node\append(world.controller.node)
char = player.ProtoPlayer()
gc = char\get("graphic")
+nc = char\get("net")
+nc.properties.accel = vec2(0.1,0)
+nc.properties.last_update = am.current_time! - 0.1