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
|
-- 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
print("hc:", hc)
--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) ->
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)
@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!
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
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
|