summaryrefslogtreecommitdiff
path: root/src/world.moon
blob: 5c76187e11339d8fadec4ae6c8f76a02e8ad4abd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
-- Global state
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
--Use a collider to decide what to render
x = {
	world_e: ecs.Entity(1)
	-- local offsets from the world
	world_x: 0 
	world_y: 0
	-- Have we selected an input type yet?
	controller: {
		text_size: 4
	}
	-- Level information
	level: {
		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(-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) ->
		-- 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)
x.level.in_sea = (pos) ->
	pos.x > 15 or pos.x < -15 or pos.y > 15 or pos.y < -15
-- Each pixel is 4 bytes, 1 byte per channel
x.level.bubble_buffer = am.buffer(1024 * 4 * 4, "dynamic")

bubble_view = x.level.bubble_buffer\view("vec4") -- xy location, w time?
bubble_texture = am.texture2d(am.image_buffer(x.level.bubble_buffer, 1024 * 4, 1))
class Bubble
	@wrap = 1
	new: (pos) =>
		bubble_view[@@wrap] = vec4(pos.x, pos.y, -1, am.current_time!)

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)
		@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) =>
		@node = am.group!
		--assert(properties and properties.node , "Failed to find node for graphics component")
		super(name, properties)
		--x.node\append(properties.node)
	join: (entity) =>
		buf_size = @buf_size!
		@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, 3.5
		)
		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
			--bubbles: bubble_texture
		}
		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")
		)))))
		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)
		x.node\append(@node)
	leave: () =>
		x.node\remove(@node)
	static: () =>
		@@static
	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.Bubble = Bubble
x