Skip to content

Commit 3fec18d

Browse files
committed
Made gameloop logic a system in a plugin
1 parent efa4e58 commit 3fec18d

5 files changed

Lines changed: 51 additions & 57 deletions

File tree

src/App.jl

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Will create a new global instance of a CruiseApp. Note that a program can only h
4545
The next call to CruiseApp will return the same object.
4646
"""
4747
mutable struct CruiseApp
48-
const plugins::Dict{Symbol, CRPlugin}
48+
const plugins::CRPlugin
4949
app::ODApp
5050
render::HorizonManager
5151
running::Bool
@@ -61,8 +61,7 @@ function CruiseApp()
6161
global app_lock
6262
lock(app_lock)
6363
if !isassigned(app)
64-
app[] = CruiseApp(Dict{Symbol, CRPlugin}(:preupdate => CRPlugin(), :postupdate => CRPlugin()),
65-
ODApp(), HorizonManager(),false, false)
64+
app[] = CruiseApp(CRPlugin(), ODApp(), HorizonManager(),false, false)
6665
end
6766
unlock(app_lock)
6867
return app[]
@@ -93,10 +92,7 @@ Initialize all the systems in the given CRPlugin.
9392
function awake!()
9493
a = CruiseApp()
9594
a.running = true
96-
awake!(a.app)
97-
for sg in values(a.plugins)
98-
awake!(sg)
99-
end
95+
awake!(a.plugins)
10096

10197
ON_CRUISE_STARTUP.emit
10298
end
@@ -112,15 +108,7 @@ Update for the current frame the CruiseApp and all his plugins.
112108
113109
Update for the current frame all the systems in the given CRPlugin.
114110
"""
115-
function update!()
116-
a = CruiseApp()
117-
update!(a.app)
118-
for sg in values(a.plugins)
119-
update!(sg)
120-
end
121-
update!(a.render)
122-
end
123-
update!(a::CruiseApp, phase::Symbol) = update!(a.plugins[phase])
111+
update!() = update!(CruiseApp().plugins)
124112
update!(sg::CRPlugin) = pmap!(update!, sg)
125113
update!(n::CRPluginNode) = nothing
126114

@@ -135,17 +123,13 @@ This will stop the given system graph by topologically calling shutdown! on the
135123
"""
136124
function shutdown!()
137125
a = CruiseApp()
138-
shutdown!(a.app)
139-
shutdown!(a.render)
140126
if on(a)
141127
a.running = false
142-
for sg in values(a.plugins)
143-
shutdown!(sg)
144-
end
128+
shutdown!(a.plugins)
145129
end
146130
end
147131
shutdown!(sg::CRPlugin) = smap!(shutdown!, sg)
148-
shutdown!(n::CRPluginNode) = (n.status[] = CRPluginStatus.OFF)
132+
shutdown!(n::CRPluginNode) = (n.status[] = PLUGIN_OFF)
149133

150134
"""
151135
on(a::CruiseApp)
@@ -161,13 +145,9 @@ Returns true if the CruiseApp isn't running.
161145
"""
162146
off(a::CruiseApp) = !a.running
163147

164-
merge_plugin!(app::CruiseApp, plugin::CRPlugin, phase=:postupdate) = merge_plugin!(app.plugins[phase], plugin)
148+
merge_plugin!(app::CruiseApp, plugin::CRPlugin) = merge_plugin!(app.plugins, plugin)
165149
merge_plugin!(plugin1::CRPlugin, plugin2::CRPlugin) = merge_graphs!(plugin1, plugin2)
166150

167-
preupdate_plugins(a::CruiseApp) = a.plugins[:preupdate]
168-
169-
postupdate_plugins(a::CruiseApp) = a.plugins[:postupdate]
170-
171151
########################################################### OUTDOORS ################################################################
172152

173153
function Outdoors.CreateWindow(style::Type{<:AbstractStyle}, args...)

src/game_loop.jl

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ end
5555

5656
const LOOP_VAR_REF = Ref{GameLoop}(GameLoop())
5757

58+
"""
59+
This struct represent the code you passed on to the game loop object.
60+
That code will be used to generate a new system that will be used to execute your code
61+
"""
62+
mutable struct GameCode
63+
expr::Expr
64+
code::Function
65+
end
66+
5867
function reset!(l::GameLoop)
5968
l.last_frame_time_ns = 0
6069
l.frame_idx = 0
@@ -91,13 +100,14 @@ end
91100
```
92101
"""
93102
macro gameloop(args...)
94-
length(args) < 2 && error("@gameloop should take at least 2 argument.")
103+
length(args) < 1 && error("@gameloop should take at least 1 argument.")
95104
code = args[end]
96-
main = args[end-1]
105+
rawcode = QuoteNode(code)
97106

98107
max_fps = 60
99108
max_duration = 0.3
100-
for i in 1:length(args)-2
109+
for i in 1:length(args)-1
110+
args[i] isa Symbol && error("@gameloop should take keyword arguments not `$(args[i])")
101111
arg = args[i].args
102112
if arg[1] == :max_fps
103113
max_fps = arg[2]
@@ -107,25 +117,21 @@ macro gameloop(args...)
107117
error("Unknow keyword $(arg[1])")
108118
end
109119
end
120+
110121
body = esc(quote
111-
app = Cruise.CruiseApp()
112122
Cruise.off(app) && Cruise.awake!()
123+
124+
# Adding the user code as a system in the plugin
125+
codeid = add_system!(app.plugins, Cruise.GameCode($rawcode, () -> $code))
126+
113127
tolerance = 0.02
114128
LOOP_VAR = LOOP_VAR_REF[]
115129
Cruise.reset!(LOOP_VAR)
116130
LOOP_VAR.max_fps = $max_fps
117131
LOOP_VAR.max_frame_duration = $max_duration
118132
while Cruise.on(app)
119133

120-
# First pump events and initialize every windows
121-
Cruise.update!(app.app)
122-
Cruise.update!(app, :preupdate)
123-
124-
# Then execute the loop code
125-
$code
126-
127-
Cruise.update!(app, :postupdate)
128-
Cruise.update!(app.render)
134+
Cruise.update!() # Traverse the graph and execute each node
129135

130136
# Advance the timer.
131137
LOOP_VAR.frame_idx += 1
@@ -161,8 +167,14 @@ macro gameloop(args...)
161167
end
162168

163169
on(app) && shutdown!()
170+
remove_system!(app.plugins, codeid)
164171
end)
165172

166-
# A noted by William, global code is slow in julia, better wrap it in an anonymous function
167-
return :(((app) -> $body)($main))
173+
# As noted by William, global code is slow in julia, better wrap it in an anonymous function
174+
return :(((app) -> $body)(Cruise.CruiseApp()))
175+
end
176+
177+
function Cruise.update!(n::CRPluginNode{GameCode})
178+
gamelogic = n.obj
179+
gamelogic.code()
168180
end

src/plugin/operations.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ Add the given obj to the system graph.
9999
function add_system!(sg::CRPlugin, args...; sort=true, mainthread=false)
100100
id = get_available_id(sg)
101101
node = CRPluginNode(args...; mainthread=mainthread)
102+
103+
for n in values(sg.idtonode)
104+
typeof(n) == typeof(node) && return
105+
end
102106
add_node!(sg, id, node)
103107
add_vertex!(sg.graph)
104108
node.id = id

test/runtests.jl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
include("..\\src\\Cruise.jl")
2-
3-
using .Cruise
1+
using Cruise
42
using Test
53

64
include("test_temp_storage.jl")

test/test_gameloop.jl

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11

2-
mutable struct Counter
3-
c::Int
2+
mutable struct Counter{T}
3+
c::T
44
end
55

66
app = CruiseApp()
77

88
pl1 = CRPlugin()
99
pl2 = CRPlugin()
10-
counter1 = Counter(0)
11-
counter2 = Counter(0)
10+
counter1 = Counter{Int}(0)
11+
counter2 = Counter{Float64}(0)
1212
add_system!(pl1, counter1)
1313
add_system!(pl2, counter2)
1414

15-
Cruise.awake!(n::CRPluginNode{Counter}) = (n.obj.c = 0)
16-
Cruise.update!(n::CRPluginNode{Counter}) = (n.obj.c += 1)
17-
Cruise.shutdown!(n::CRPluginNode{Counter}) = (n.obj.c)
15+
Cruise.awake!(n::CRPluginNode{<:Counter}) = (n.obj.c = 0)
16+
Cruise.update!(n::CRPluginNode{<:Counter}) = (n.obj.c += 1)
17+
Cruise.shutdown!(n::CRPluginNode{<:Counter}) = (n.obj.c)
1818

19-
merge_plugin!(app, pl1, :preupdate)
20-
merge_plugin!(app, pl2, :postupdate)
19+
merge_plugin!(app, pl1)
20+
merge_plugin!(app, pl2)
2121

2222
@testset "GameLoop struct" begin
2323
gl = GameLoop()
@@ -50,7 +50,7 @@ end
5050
@testset "@gameloop default arguments" begin
5151
cnt = Ref(0)
5252

53-
@gameloop app begin
53+
@gameloop begin
5454
cnt[] += 1
5555
cnt[] >= 2 && shutdown!()
5656
end
@@ -73,7 +73,7 @@ end
7373
counter = Ref(0)
7474
deltas = Float32[]
7575

76-
@gameloop max_fps=30 app begin
76+
@gameloop max_fps=30 begin
7777
counter[] += 1
7878
push!(deltas, LOOP_VAR.delta_seconds)
7979
counter[] >= 3 && shutdown!()
@@ -86,7 +86,7 @@ end
8686
@testset "GameLoop progression" begin
8787
frame_indices = Int[]
8888

89-
@gameloop max_fps=10 app begin
89+
@gameloop max_fps=10 begin
9090
push!(frame_indices, LOOP_VAR.frame_idx)
9191
LOOP_VAR.frame_idx >= 2 && shutdown!()
9292
end

0 commit comments

Comments
 (0)