-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathexample04.lua
227 lines (181 loc) · 5.93 KB
/
example04.lua
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
local lpugl = require"lpugl_opengl"
local nvg = require"nvg"
local color = require"nvg.color"
local floor = math.floor
local ceil = math.ceil
local abs = math.abs
local sqrt = math.sqrt
local unpack = table.unpack or unpack -- for Lua 5.1
math.randomseed(os.time())
local world = lpugl.newWorld("example04.lua")
local scale = world:getScreenScale()
local drawBall
do
local function drawBallImpl(ctx, x, y, r,
rgba1,
rgba2)
ctx:beginPath()
local alpha = 0.7
local d = r*0.75
ctx:arc(x, y, r, 0, math.pi * 2)
ctx.fillStyle = ctx:radialGradient(x - d, y - d, r - d, 2*r, rgba1, rgba2)
ctx:fill()
end
local alpha = 0.7
local gradientTable = {
{ color.rgba(1.0, 0.8, 0.8, alpha),
color.rgba(1.0, 0.0, 0.0, alpha) },
{ color.rgba(0.7, 1.0, 0.7, alpha),
color.rgba(0.0, 1.0, 0.0, alpha) },
{ color.rgba(0.7, 0.7, 1.0, alpha),
color.rgba(0.0, 0.0, 1.0, alpha) },
}
drawBall = function(ctx, x, y, r, gradientIndex)
drawBallImpl(ctx, x, y, r,
unpack(gradientTable[gradientIndex]))
end
end
local initialWidth, initialHeight = 640*scale, 480*scale
local objects_draw
local objects_push
local objects_process
do
local objects = {}
for i = 1, 500 do
local obj = {}
objects[i] = obj
obj.r = math.random(floor(10*scale), floor(30*scale))
obj.x = math.random(obj.r, floor(initialWidth - 2 * obj.r))
obj.y = math.random(obj.r, floor(initialHeight - 2 * obj.r))
obj.g = math.random(1, 3)
obj.dx = 5 * math.random() / 20 * scale
obj.dy = 5 * math.random() / 20 * scale
end
objects_draw = function(ctx, w, h)
for i = 1, #objects do
local obj = objects[i]
drawBall(ctx, obj.x, obj.y, obj.r, obj.g)
end
end
objects_push = function(bx, by)
for i = 1, #objects do
local obj = objects[i]
local x, y = obj.x, obj.y
local bdx, bdy = x - bx, y - by
local bd = sqrt(bdx^2 + bdy^2)/scale
local a = (bd + 0.01)^-1.5
obj.dx = obj.dx + a * bdx
obj.dy = obj.dy + a * bdy
end
end
local lastT = world:getTime()
objects_process = function(w, h)
local currT = world:getTime()
local dt = (currT - lastT) * 1000
for i = 1, #objects do
local obj = objects[i]
local x, y = obj.x, obj.y
x = x + obj.dx * dt
if x + obj.r > w then
x = w - obj.r
obj.dx = -obj.dx
elseif x - obj.r < 0 then
x = obj.r
obj.dx = -obj.dx
end
y = y + obj.dy * dt
if y + obj.r > h then
y = h - obj.r
obj.dy = -obj.dy
elseif y - obj.r < 0 then
y = obj.r
obj.dy = -obj.dy
end
obj.x, obj.y = x, y
obj.dx = obj.dx * (1 - dt * 0.0001)
obj.dy = obj.dy * (1 - dt * 0.0001)
end
lastT = currT
end
end
local lastDisplayTime = 0
local renderStartTime = nil
local renderTime = 0
local renderCount = 0
local lastRender = 0
local frameTime = 0
local frameCount = 0
local processTime = 0
local processCount = 0
local ctx = nil
local view = world:newView
{
title = "example04",
size = {initialWidth, initialHeight},
resizable = true,
eventFunc = function(view, event, ...)
if event == "CREATE" then
ctx = nvg.new("antialias")
elseif event == "EXPOSE" then
local startTime = world:getTime()
frameTime = frameTime + startTime - lastRender
frameCount = frameCount + 1
lastRender = startTime
local w, h = view:getSize()
ctx:beginFrame(w, h)
ctx:clear("#ffffff")
objects_draw(ctx, w, h)
ctx:endFrame()
renderStartTime = startTime
world:setNextProcessTime(0)
elseif event == "BUTTON_PRESS" then
local bx, by, bn = ...
if bn == 1 then
objects_push(bx, by)
end
elseif event == "CLOSE" then
view:close()
end
end
}
view:show()
local lastP = world:getTime()
local REFRESH_PERIOD = 0.015
world:setProcessFunc(function()
if not view:isClosed() then
local startTime = world:getTime()
if renderStartTime then
renderTime = renderTime + (startTime - renderStartTime)
renderCount = renderCount + 1
lastDisplayTime = renderStartTime
renderStartTime = nil
end
local now = world:getTime()
if now >= lastDisplayTime + REFRESH_PERIOD then
objects_process(view:getSize())
processTime = processTime + world:getTime() - startTime
processCount = processCount + 1
view:postRedisplay()
world:setNextProcessTime(REFRESH_PERIOD)
else
world:setNextProcessTime(lastDisplayTime + REFRESH_PERIOD - now)
end
if startTime > lastP + 2 and renderCount > 0 and processCount > 0 then
print(string.format("render: %5.1fms, process: %5.1fms, period: %5.1fms",
renderTime/renderCount * 1000,
processTime/processCount * 1000,
frameTime/frameCount * 1000))
renderTime = 0
renderCount = 0
processTime = 0
processCount = 0
frameTime = 0
frameCount = 0
lastP = startTime
end
end
end)
world:setNextProcessTime(0)
while world:hasViews() do
world:update()
end