mirror of https://github.com/dsrw/enu.git
Updated nph
This commit is contained in:
parent
e91909688e
commit
b0e871a329
|
@ -1,6 +1,2 @@
|
|||
# Formatted with nph v0.3-10-g3947a41-dirty
|
||||
d02b42b06eafd770cc1339459805fb6bf3e19709
|
||||
# Formatted with nph v0.3-9-gdd146ed-dirty
|
||||
3f0302c4b68c33aba42de9c657a100dd781de195
|
||||
# Formatted with nph v0.3-11-gaeceee1
|
||||
48639ef4af9d86817c8897ed8d78adf480050606
|
||||
# Formatted with nph v0.4-4-g5e613fb-dirty
|
||||
b1dd9d43a59785e33b8e778a832cd65edf958292
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
import nimibook
|
||||
|
||||
var book =
|
||||
init_book_with_toc:
|
||||
section "Introduction", "intro":
|
||||
entry "Tutorial", "intro/tutorial"
|
||||
entry "Install or Build", "intro/building"
|
||||
entry "Controls and Usage", "intro/controls"
|
||||
entry "Examples", "intro/examples"
|
||||
entry "Multiplayer (Experimental)", "intro/multiplayer"
|
||||
entry "Config", "intro/config"
|
||||
var book = init_book_with_toc:
|
||||
section "Introduction", "intro":
|
||||
entry "Tutorial", "intro/tutorial"
|
||||
entry "Install or Build", "intro/building"
|
||||
entry "Controls and Usage", "intro/controls"
|
||||
entry "Examples", "intro/examples"
|
||||
entry "Multiplayer (Experimental)", "intro/multiplayer"
|
||||
entry "Config", "intro/config"
|
||||
|
||||
section "Coding Enu", "coding":
|
||||
entry "Concepts", "coding/concepts"
|
||||
entry "Built-in Commands", "coding/commands"
|
||||
entry "Shorthand Commands", "coding/shorthand"
|
||||
entry "Random Numbers", "coding/random_numbers"
|
||||
section "Coding Enu", "coding":
|
||||
entry "Concepts", "coding/concepts"
|
||||
entry "Built-in Commands", "coding/commands"
|
||||
entry "Shorthand Commands", "coding/shorthand"
|
||||
entry "Random Numbers", "coding/random_numbers"
|
||||
|
||||
section "Command Loops", "command_loops":
|
||||
entry "Writing Commands", "command_loops/commands"
|
||||
entry "Arrows", "command_loops/arrows"
|
||||
entry "Loops", "command_loops/loops"
|
||||
entry "Child Loops", "command_loops/child_loops"
|
||||
entry "More About Command Loops", "command_loops/more"
|
||||
section "Command Loops", "command_loops":
|
||||
entry "Writing Commands", "command_loops/commands"
|
||||
entry "Arrows", "command_loops/arrows"
|
||||
entry "Loops", "command_loops/loops"
|
||||
entry "Child Loops", "command_loops/child_loops"
|
||||
entry "More About Command Loops", "command_loops/more"
|
||||
|
||||
entry "Goals", "goals"
|
||||
entry "Demos", "demos"
|
||||
entry "TODO", "todo"
|
||||
entry "Goals", "goals"
|
||||
entry "Demos", "demos"
|
||||
entry "TODO", "todo"
|
||||
|
||||
nimibook_cli(book)
|
||||
|
|
|
@ -4,14 +4,16 @@ import enuib
|
|||
nb_init(theme = use_enu)
|
||||
nb_text:
|
||||
"""
|
||||
# Introduction
|
||||
|
||||
Build 3D worlds in Nim.
|
||||
# Introduction
|
||||
|
||||
![Enu Screenshot](assets/screenshot_3.webp)
|
||||
Build 3D worlds in Nim.
|
||||
|
||||
Enu lets you build and explore worlds using a familiar block-building interface
|
||||
and a Logo inspired API. It tries to make 3D development easier, and will
|
||||
eventually be able to create standalone games.
|
||||
"""
|
||||
![Enu Screenshot](assets/screenshot_3.webp)
|
||||
|
||||
Enu lets you build and explore worlds using a familiar block-building interface
|
||||
and a Logo inspired API. It tries to make 3D development easier, and will
|
||||
eventually be able to create standalone games.
|
||||
|
||||
"""
|
||||
nb_save
|
||||
|
|
|
@ -48,8 +48,8 @@ proc add_to_scene(unit: Unit) =
|
|||
if node.owner != nil:
|
||||
fail \"{T.name} node shouldn't be owned. unit = {unit.id}"
|
||||
unit.node.visible =
|
||||
Visible in unit.global_flags() and
|
||||
ScriptInitializing notin unit.global_flags()
|
||||
Visible in unit.global_flags and
|
||||
(ScriptInitializing notin unit.global_flags)
|
||||
|
||||
parent_node.add_child(unit.node)
|
||||
unit.node.owner = parent_node
|
||||
|
|
|
@ -95,10 +95,9 @@ proc new_instance(self: Worker, src: Unit, dest: PNode) =
|
|||
|
||||
var clone = src.clone(self.active_unit, id)
|
||||
assert not clone.is_nil
|
||||
clone.script_ctx =
|
||||
ScriptCtx.init(
|
||||
owner = clone, clone_of = src, interpreter = self.interpreter
|
||||
)
|
||||
clone.script_ctx = ScriptCtx.init(
|
||||
owner = clone, clone_of = src, interpreter = self.interpreter
|
||||
)
|
||||
|
||||
self.map_unit(clone, dest)
|
||||
|
||||
|
@ -193,15 +192,14 @@ proc begin_move(
|
|||
|
||||
proc sleep_impl(self: Worker, ctx: ScriptCtx, seconds: float) =
|
||||
var duration = 0.0
|
||||
ctx.callback =
|
||||
proc(delta: float, _: MonoTime): TaskStates =
|
||||
duration += delta
|
||||
if seconds > 0 and duration < seconds:
|
||||
Running
|
||||
elif seconds <= 0 and duration <= 0.5 and ctx.timer > get_mono_time():
|
||||
Running
|
||||
else:
|
||||
Done
|
||||
ctx.callback = proc(delta: float, _: MonoTime): TaskStates =
|
||||
duration += delta
|
||||
if seconds > 0 and duration < seconds:
|
||||
Running
|
||||
elif seconds <= 0 and duration <= 0.5 and ctx.timer > get_mono_time():
|
||||
Running
|
||||
else:
|
||||
Done
|
||||
ctx.last_ran = MonoTime.default
|
||||
self.pause_script()
|
||||
|
||||
|
@ -342,14 +340,13 @@ proc sees(
|
|||
return
|
||||
|
||||
let future = result
|
||||
unit.script_ctx.callback =
|
||||
proc(delta: float, timeout: MonoTime): TaskStates =
|
||||
let query = unit.sight_query
|
||||
if ?query.answer:
|
||||
future.complete(query.answer.get)
|
||||
result = Done
|
||||
else:
|
||||
result = Running
|
||||
unit.script_ctx.callback = proc(delta: float, timeout: MonoTime): TaskStates =
|
||||
let query = unit.sight_query
|
||||
if ?query.answer:
|
||||
future.complete(query.answer.get)
|
||||
result = Done
|
||||
else:
|
||||
result = Running
|
||||
|
||||
unit.script_ctx.last_ran = MonoTime.default
|
||||
self.pause_script()
|
||||
|
@ -428,8 +425,9 @@ proc draw_position_set(self: Build, position: Vector3) =
|
|||
(position - self.position).local_to(self.parent)
|
||||
|
||||
proc save(self: Build, name: string) =
|
||||
self.save_points[name] =
|
||||
(self.draw_transform, self.color_value.value, self.drawing)
|
||||
self.save_points[name] = (
|
||||
self.draw_transform, self.color_value.value, self.drawing
|
||||
)
|
||||
|
||||
proc restore(self: Build, name: string) =
|
||||
(self.draw_transform, self.color_value.value, self.drawing) =
|
||||
|
@ -486,17 +484,16 @@ proc new_markdown_sign(
|
|||
size: int,
|
||||
billboard: bool,
|
||||
): Unit =
|
||||
result =
|
||||
Sign.init(
|
||||
message,
|
||||
more = more,
|
||||
owner = self.active_unit,
|
||||
transform = drop_transform(unit),
|
||||
width = width,
|
||||
height = height,
|
||||
size = size,
|
||||
billboard = billboard,
|
||||
)
|
||||
result = Sign.init(
|
||||
message,
|
||||
more = more,
|
||||
owner = self.active_unit,
|
||||
transform = drop_transform(unit),
|
||||
width = width,
|
||||
height = height,
|
||||
size = size,
|
||||
billboard = billboard,
|
||||
)
|
||||
|
||||
info "creating sign", id = result.id
|
||||
self.map_unit(result, pnode)
|
||||
|
|
|
@ -76,51 +76,48 @@ macro bridged_from_vm(
|
|||
let
|
||||
symbol = bind_sym($proc_ref)
|
||||
proc_impl = (if symbol.kind == nnkSym: symbol
|
||||
else: symbol[0]
|
||||
).get_impl
|
||||
else: symbol[0]
|
||||
).get_impl
|
||||
proc_name = proc_impl[0].str_val
|
||||
proc_impl_name = proc_name.replace("=", "_set") & "_impl"
|
||||
return_node = proc_impl[3][0]
|
||||
arg_nodes = proc_impl[3][1 ..^ 1]
|
||||
|
||||
let args =
|
||||
collect:
|
||||
block:
|
||||
var pos = -1
|
||||
for ident_def in arg_nodes:
|
||||
let typ = ident_def[1].str_val
|
||||
if typ == $Worker.type:
|
||||
ident"script_engine"
|
||||
elif typ == "VmArgs":
|
||||
ident"a"
|
||||
elif typ == "ScriptCtx":
|
||||
quote:
|
||||
script_engine.active_unit.script_ctx
|
||||
elif typ in ["Unit", "Bot", "Build", "Sign"]:
|
||||
let getter = "get_" & typ
|
||||
pos.inc
|
||||
new_call(
|
||||
bind_sym(getter), ident"script_engine", ident"a", new_lit(pos)
|
||||
)
|
||||
else:
|
||||
let getter = "get_" & typ
|
||||
pos.inc
|
||||
new_call(bind_sym(getter), ident"a", new_lit(pos))
|
||||
let args = collect:
|
||||
block:
|
||||
var pos = -1
|
||||
for ident_def in arg_nodes:
|
||||
let typ = ident_def[1].str_val
|
||||
if typ == $Worker.type:
|
||||
ident"script_engine"
|
||||
elif typ == "VmArgs":
|
||||
ident"a"
|
||||
elif typ == "ScriptCtx":
|
||||
quote:
|
||||
script_engine.active_unit.script_ctx
|
||||
elif typ in ["Unit", "Bot", "Build", "Sign"]:
|
||||
let getter = "get_" & typ
|
||||
pos.inc
|
||||
new_call(
|
||||
bind_sym(getter), ident"script_engine", ident"a", new_lit(pos)
|
||||
)
|
||||
else:
|
||||
let getter = "get_" & typ
|
||||
pos.inc
|
||||
new_call(bind_sym(getter), ident"a", new_lit(pos))
|
||||
|
||||
var call = new_call(proc_ref, args)
|
||||
if return_node.kind == nnk_sym:
|
||||
if return_node.str_val in ["Unit", "Bot", "Build", "Sign"]:
|
||||
call =
|
||||
new_call(
|
||||
bind_sym"set_result",
|
||||
ident"a",
|
||||
new_call(bind_sym"to_node", ident"script_engine", call),
|
||||
)
|
||||
call = new_call(
|
||||
bind_sym"set_result",
|
||||
ident"a",
|
||||
new_call(bind_sym"to_node", ident"script_engine", call),
|
||||
)
|
||||
else:
|
||||
call =
|
||||
new_call(
|
||||
bind_sym"set_result", ident"a", new_call(bind_sym"to_result", call)
|
||||
)
|
||||
call = new_call(
|
||||
bind_sym"set_result", ident"a", new_call(bind_sym"to_result", call)
|
||||
)
|
||||
elif return_node.kind == nnk_bracket_expr and return_node.len == 2 and
|
||||
return_node[0].str_val == "Future":
|
||||
call = new_call(bind_sym"await_future", call, ident"a")
|
||||
|
|
|
@ -14,23 +14,21 @@ proc init*(
|
|||
clone_of: Unit = nil,
|
||||
interpreter: Interpreter,
|
||||
): ScriptCtx =
|
||||
result =
|
||||
ScriptCtx(
|
||||
module_name: if ?clone_of: clone_of.id else: "",
|
||||
interpreter: interpreter,
|
||||
timeout_at: MonoTime.high,
|
||||
timer: MonoTime.high,
|
||||
)
|
||||
result = ScriptCtx(
|
||||
module_name: if ?clone_of: clone_of.id else: "",
|
||||
interpreter: interpreter,
|
||||
timeout_at: MonoTime.high,
|
||||
timer: MonoTime.high,
|
||||
)
|
||||
|
||||
proc extract_file_info(msg: string): tuple[name: string, info: TLineInfo] =
|
||||
if msg =~ re"unhandled exception: (.*)\((\d+), (\d+)\)":
|
||||
result =
|
||||
(
|
||||
matches[0],
|
||||
TLineInfo(
|
||||
line: matches[1].parse_int.uint16, col: matches[2].parse_int.int16
|
||||
),
|
||||
)
|
||||
result = (
|
||||
matches[0],
|
||||
TLineInfo(
|
||||
line: matches[1].parse_int.uint16, col: matches[2].parse_int.int16
|
||||
),
|
||||
)
|
||||
|
||||
proc script_error*(self: Worker, unit: Unit, e: ref VMQuit) =
|
||||
var msg = e.msg
|
||||
|
@ -83,48 +81,49 @@ proc init_interpreter*[T](self: Worker, _: T) {.gcsafe.} =
|
|||
raise (ref VMQuit)(info: info, msg: msg, location: loc)
|
||||
|
||||
var count: byte = 0
|
||||
interpreter.enter_hook =
|
||||
proc(c: PCtx, pc: int, tos: PStackFrame, instr: TInstr) =
|
||||
assert ?controller
|
||||
assert ?controller.active_unit
|
||||
assert ?controller.active_unit.script_ctx
|
||||
interpreter.enter_hook = proc(
|
||||
c: PCtx, pc: int, tos: PStackFrame, instr: TInstr
|
||||
) =
|
||||
assert ?controller
|
||||
assert ?controller.active_unit
|
||||
assert ?controller.active_unit.script_ctx
|
||||
|
||||
let ctx = controller.active_unit.script_ctx
|
||||
let info = c.debug[pc]
|
||||
inc count
|
||||
if count == 255:
|
||||
# don't call get_mono_time for every instruction for a 5-10% speedup.
|
||||
count = 0
|
||||
let now = get_mono_time()
|
||||
if ctx.timeout_at < now:
|
||||
let duration = script_timeout
|
||||
raise (ref VMQuit)(
|
||||
info: info,
|
||||
kind: Timeout,
|
||||
msg:
|
||||
\"Timeout. Script {ctx.script} executed for too long without " &
|
||||
\"yielding: {duration}",
|
||||
)
|
||||
let ctx = controller.active_unit.script_ctx
|
||||
let info = c.debug[pc]
|
||||
inc count
|
||||
if count == 255:
|
||||
# don't call get_mono_time for every instruction for a 5-10% speedup.
|
||||
count = 0
|
||||
let now = get_mono_time()
|
||||
if ctx.timeout_at < now:
|
||||
let duration = script_timeout
|
||||
raise (ref VMQuit)(
|
||||
info: info,
|
||||
kind: Timeout,
|
||||
msg:
|
||||
\"Timeout. Script {ctx.script} executed for too long without " &
|
||||
\"yielding: {duration}",
|
||||
)
|
||||
|
||||
# We don't care about the line info if we're not in our enu script.
|
||||
# Store the file index the first time we hit our file and only change
|
||||
# current_line/previous_line if the current instruction has that index.
|
||||
if ctx.file_index == -1 and info.file_index.int >= 0 and
|
||||
info.file_index.int < interpreter.config.m.file_infos.len:
|
||||
let file_name =
|
||||
interpreter.config.m.file_infos[info.file_index.int].full_path.string
|
||||
if file_name == ctx.file_name:
|
||||
ctx.file_index = info.file_index.int
|
||||
elif ctx.file_index == info.file_index.int:
|
||||
if ctx.previous_line != info:
|
||||
(ctx.previous_line, ctx.current_line) = (ctx.current_line, info)
|
||||
# We don't care about the line info if we're not in our enu script.
|
||||
# Store the file index the first time we hit our file and only change
|
||||
# current_line/previous_line if the current instruction has that index.
|
||||
if ctx.file_index == -1 and info.file_index.int >= 0 and
|
||||
info.file_index.int < interpreter.config.m.file_infos.len:
|
||||
let file_name =
|
||||
interpreter.config.m.file_infos[info.file_index.int].full_path.string
|
||||
if file_name == ctx.file_name:
|
||||
ctx.file_index = info.file_index.int
|
||||
elif ctx.file_index == info.file_index.int:
|
||||
if ctx.previous_line != info:
|
||||
(ctx.previous_line, ctx.current_line) = (ctx.current_line, info)
|
||||
|
||||
if ctx.pause_requested:
|
||||
ctx.ctx = c
|
||||
ctx.pc = pc
|
||||
ctx.tos = tos
|
||||
ctx.pause_requested = false
|
||||
raise VMPause.new_exception("vm paused")
|
||||
if ctx.pause_requested:
|
||||
ctx.ctx = c
|
||||
ctx.pc = pc
|
||||
ctx.tos = tos
|
||||
ctx.pause_requested = false
|
||||
raise VMPause.new_exception("vm paused")
|
||||
|
||||
proc load_script*(self: Worker, unit: Unit, timeout = script_timeout) =
|
||||
let ctx = unit.script_ctx
|
||||
|
|
|
@ -124,10 +124,9 @@ proc watch_units(
|
|||
self: Worker,
|
||||
units: ZenSeq[Unit],
|
||||
parent: Unit,
|
||||
body:
|
||||
proc(unit: Unit, change: Change[Unit], added: bool, removed: bool) {.
|
||||
gcsafe
|
||||
.},
|
||||
body: proc(unit: Unit, change: Change[Unit], added: bool, removed: bool) {.
|
||||
gcsafe
|
||||
.},
|
||||
) {.gcsafe.} =
|
||||
units.track proc(changes: seq[Change[Unit]]) {.gcsafe.} =
|
||||
for change in changes:
|
||||
|
@ -156,14 +155,13 @@ proc worker_thread(params: (ZenContext, GameState)) {.gcsafe.} =
|
|||
worker_lock.acquire
|
||||
|
||||
var listen_address = main_thread_state.config.listen_address
|
||||
let worker_ctx =
|
||||
ZenContext.init(
|
||||
id = \"work-{generate_id()}",
|
||||
chan_size = 500,
|
||||
buffer = false,
|
||||
listen_address = listen_address,
|
||||
label = "worker",
|
||||
)
|
||||
let worker_ctx = ZenContext.init(
|
||||
id = \"work-{generate_id()}",
|
||||
chan_size = 500,
|
||||
buffer = false,
|
||||
listen_address = listen_address,
|
||||
label = "worker",
|
||||
)
|
||||
|
||||
Zen.thread_ctx = worker_ctx
|
||||
ctx.subscribe(Zen.thread_ctx)
|
||||
|
@ -262,18 +260,17 @@ proc worker_thread(params: (ZenContext, GameState)) {.gcsafe.} =
|
|||
player.script_ctx.interpreter = worker.interpreter
|
||||
worker.load_script_and_dependents(player)
|
||||
|
||||
var sign =
|
||||
Sign.init(
|
||||
"",
|
||||
"",
|
||||
width = 4,
|
||||
height = 3.05,
|
||||
owner = state.player,
|
||||
size = 244,
|
||||
billboard = true,
|
||||
text_only = true,
|
||||
transform = Transform.init(origin = vec3(0, 4, 0)),
|
||||
)
|
||||
var sign = Sign.init(
|
||||
"",
|
||||
"",
|
||||
width = 4,
|
||||
height = 3.05,
|
||||
owner = state.player,
|
||||
size = 244,
|
||||
billboard = true,
|
||||
text_only = true,
|
||||
transform = Transform.init(origin = vec3(0, 4, 0)),
|
||||
)
|
||||
|
||||
state.player.units += sign
|
||||
sign.global_flags -= Visible
|
||||
|
|
18
src/core.nim
18
src/core.nim
|
@ -142,12 +142,13 @@ proc wrap*[T](value, min, max: T): float =
|
|||
when not defined(no_godot):
|
||||
import pkg/godot
|
||||
|
||||
default_chronicles_stream.output.writer =
|
||||
proc(logLevel: LogLevel, msg: LogOutputStr) {.gcsafe.} =
|
||||
when defined(release):
|
||||
godot.print msg
|
||||
else:
|
||||
echo msg
|
||||
default_chronicles_stream.output.writer = proc(
|
||||
logLevel: LogLevel, msg: LogOutputStr
|
||||
) {.gcsafe.} =
|
||||
when defined(release):
|
||||
godot.print msg
|
||||
else:
|
||||
echo msg
|
||||
|
||||
# misc
|
||||
|
||||
|
@ -217,9 +218,8 @@ proc update_action_index*(state: GameState, change: int) =
|
|||
template watch*[T, O](zen: Zen[T, O], unit: untyped, body: untyped) =
|
||||
when unit is Unit:
|
||||
mixin thread_ctx
|
||||
let zid =
|
||||
zen.changes:
|
||||
body
|
||||
let zid = zen.changes:
|
||||
body
|
||||
unit.zids.add(zid)
|
||||
make_discardable(zid)
|
||||
else:
|
||||
|
|
45
src/game.nim
45
src/game.nim
|
@ -62,14 +62,16 @@ gdobj Game of Node:
|
|||
|
||||
self.stats.text =
|
||||
\"""
|
||||
FPS: {fps}
|
||||
scale_factor: {state.scale_factor}
|
||||
vram: {vram}
|
||||
units: {unit_count}
|
||||
zen objects: {Zen.thread_ctx.len}
|
||||
level: {state.level_name}
|
||||
{get_stats()}
|
||||
"""
|
||||
|
||||
FPS: {fps}
|
||||
scale_factor: {state.scale_factor}
|
||||
vram: {vram}
|
||||
units: {unit_count}
|
||||
zen objects: {Zen.thread_ctx.len}
|
||||
level: {state.level_name}
|
||||
{get_stats()}
|
||||
|
||||
"""
|
||||
state.voxel_tasks =
|
||||
parse_int($get_stats()["tasks"].as_dictionary["main_thread"])
|
||||
|
||||
|
@ -119,13 +121,12 @@ gdobj Game of Node:
|
|||
|
||||
var initial_user_config = load_user_config(get_user_data_dir())
|
||||
|
||||
Zen.thread_ctx =
|
||||
ZenContext.init(
|
||||
id = \"main-{generate_id()}",
|
||||
chan_size = 2000,
|
||||
buffer = true,
|
||||
label = "main",
|
||||
)
|
||||
Zen.thread_ctx = ZenContext.init(
|
||||
id = \"main-{generate_id()}",
|
||||
chan_size = 2000,
|
||||
buffer = true,
|
||||
label = "main",
|
||||
)
|
||||
|
||||
state = GameState.init
|
||||
state.nodes.game = self
|
||||
|
@ -289,10 +290,12 @@ gdobj Game of Node:
|
|||
if Connecting.added:
|
||||
state.status_message =
|
||||
\"""
|
||||
# Connecting...
|
||||
|
||||
Trying to connect to {state.config.connect_address}.
|
||||
"""
|
||||
# Connecting...
|
||||
|
||||
Trying to connect to {state.config.connect_address}.
|
||||
|
||||
"""
|
||||
elif Connecting.removed:
|
||||
state.status_message = ""
|
||||
|
||||
|
@ -360,9 +363,9 @@ gdobj Game of Node:
|
|||
if event of InputEventKey:
|
||||
let event = InputEventKey(event)
|
||||
# Left alt support. raw_code is an enu specific addition
|
||||
if (host_os == "macosx" and event.raw_code == 58) or (
|
||||
host_os == "windows" and event.raw_code == 56
|
||||
) or (host_os == "linux" and event.raw_code == 65513):
|
||||
if (host_os == "macosx" and event.raw_code == 58) or
|
||||
(host_os == "windows" and event.raw_code == 56) or
|
||||
(host_os == "linux" and event.raw_code == 65513):
|
||||
if event.pressed:
|
||||
state.push_flag CommandMode
|
||||
else:
|
||||
|
|
|
@ -45,9 +45,8 @@ proc processModule*(
|
|||
while true:
|
||||
syntaxes.openParser(p, fileIdx, s, graph.cache, graph.config)
|
||||
|
||||
if not belongsToStdlib(graph, module) or (
|
||||
belongsToStdlib(graph, module) and module.name.s == "distros"
|
||||
):
|
||||
if not belongsToStdlib(graph, module) or
|
||||
(belongsToStdlib(graph, module) and module.name.s == "distros"):
|
||||
# XXX what about caching? no processing then? what if I change the
|
||||
# modules to include between compilation runs? we'd need to track that
|
||||
# in ROD files. I think we should enable this feature only
|
||||
|
@ -129,13 +128,12 @@ proc selectRoutine*(i: Interpreter, name: string, module_name: string): PSym =
|
|||
## The routine needs to have the export marker ``*``. The only matching
|
||||
## routine is returned and ``nil`` if it is overloaded.
|
||||
{.gcsafe.}:
|
||||
result =
|
||||
selectUniqueSymbol(
|
||||
i,
|
||||
name,
|
||||
{skTemplate, skMacro, skFunc, skMethod, skProc, skConverter},
|
||||
moduleName,
|
||||
)
|
||||
result = selectUniqueSymbol(
|
||||
i,
|
||||
name,
|
||||
{skTemplate, skMacro, skFunc, skMethod, skProc, skConverter},
|
||||
moduleName,
|
||||
)
|
||||
|
||||
proc resetModule*(i: Interpreter, moduleName: string) =
|
||||
for iface in i.graph.ifaces:
|
||||
|
@ -254,9 +252,8 @@ proc `enter_hook=`*(
|
|||
|
||||
proc `error_hook=`*(
|
||||
i: Interpreter,
|
||||
hook:
|
||||
proc(config: ConfigRef, info: TLineInfo, msg: string, severity: Severity) {.
|
||||
gcsafe
|
||||
.},
|
||||
hook: proc(
|
||||
config: ConfigRef, info: TLineInfo, msg: string, severity: Severity
|
||||
) {.gcsafe.},
|
||||
) =
|
||||
i.registerErrorHook(hook)
|
||||
|
|
|
@ -18,12 +18,11 @@ proc init*(_: type Interpreter, script_dir, vmlib: string): Interpreter =
|
|||
let std_paths = STDLIB_PATHS.map_it join_path(vmlib, "stdlib", it)
|
||||
let source_paths = std_paths & join_path(vmlib, "enu") & @[script_dir]
|
||||
{.gcsafe.}:
|
||||
result =
|
||||
create_interpreter(
|
||||
"base_api.nim",
|
||||
source_paths,
|
||||
defines = @{"nimscript": "true", "nimconfig": "true"},
|
||||
)
|
||||
result = create_interpreter(
|
||||
"base_api.nim",
|
||||
source_paths,
|
||||
defines = @{"nimscript": "true", "nimconfig": "true"},
|
||||
)
|
||||
result.config.max_loop_iterations_vm = int.high
|
||||
|
||||
proc pause*(ctx: ScriptCtx) =
|
||||
|
@ -80,8 +79,8 @@ proc call_proc*(
|
|||
self.interpreter.select_routine(proc_name, module_name = self.module_name)
|
||||
if foreign_proc == nil:
|
||||
raise new_exception(
|
||||
VMError, \"script does not export a proc of the name: '{proc_name}'"
|
||||
)
|
||||
VMError, \"script does not export a proc of the name: '{proc_name}'"
|
||||
)
|
||||
result =
|
||||
try:
|
||||
{.gcsafe.}:
|
||||
|
|
|
@ -4,12 +4,11 @@ import core, models/[states, units, colors]
|
|||
include "bot_code_template.nim.nimf"
|
||||
|
||||
method code_template*(self: Bot, imports: string): string =
|
||||
result =
|
||||
bot_code_template(
|
||||
read_file(self.script_ctx.script).encode(safe = true),
|
||||
self.script_ctx.script,
|
||||
imports,
|
||||
)
|
||||
result = bot_code_template(
|
||||
read_file(self.script_ctx.script).encode(safe = true),
|
||||
self.script_ctx.script,
|
||||
imports,
|
||||
)
|
||||
|
||||
method on_begin_move*(
|
||||
self: Bot, direction: Vector3, steps: float, moving_mode: int
|
||||
|
@ -20,17 +19,16 @@ method on_begin_move*(
|
|||
moving = -self.transform.basis.z
|
||||
finish_time = 1.0 / self.speed * steps
|
||||
|
||||
result =
|
||||
proc(delta: float, _: MonoTime): TaskStates =
|
||||
duration += delta
|
||||
if duration >= finish_time:
|
||||
self.velocity_value.touch(vec3())
|
||||
self.transform_value.origin =
|
||||
self.transform.origin.snapped(vec3(0.1, 0.1, 0.1))
|
||||
return Done
|
||||
else:
|
||||
self.velocity_value.touch(moving * self.speed)
|
||||
return Running
|
||||
result = proc(delta: float, _: MonoTime): TaskStates =
|
||||
duration += delta
|
||||
if duration >= finish_time:
|
||||
self.velocity_value.touch(vec3())
|
||||
self.transform_value.origin =
|
||||
self.transform.origin.snapped(vec3(0.1, 0.1, 0.1))
|
||||
return Done
|
||||
else:
|
||||
self.velocity_value.touch(moving * self.speed)
|
||||
return Running
|
||||
|
||||
method on_begin_turn*(
|
||||
self: Bot, axis: Vector3, degrees: float, lean: bool, move_mode: int
|
||||
|
@ -39,19 +37,16 @@ method on_begin_turn*(
|
|||
let degrees = degrees * -axis.x
|
||||
var duration = 0.0
|
||||
var final_basis = self.transform.basis.rotated(UP, deg_to_rad(degrees))
|
||||
result =
|
||||
proc(delta: float, _: MonoTime): TaskStates =
|
||||
duration += delta
|
||||
self.transform_value.basis =
|
||||
self.transform.basis.rotated(
|
||||
UP, deg_to_rad(degrees * delta * self.speed)
|
||||
)
|
||||
result = proc(delta: float, _: MonoTime): TaskStates =
|
||||
duration += delta
|
||||
self.transform_value.basis =
|
||||
self.transform.basis.rotated(UP, deg_to_rad(degrees * delta * self.speed))
|
||||
|
||||
if duration <= 1.0 / self.speed:
|
||||
Running
|
||||
else:
|
||||
self.transform_value.basis = final_basis
|
||||
Done
|
||||
if duration <= 1.0 / self.speed:
|
||||
Running
|
||||
else:
|
||||
self.transform_value.basis = final_basis
|
||||
Done
|
||||
|
||||
proc bot_at*(state: GameState, position: Vector3): Bot =
|
||||
for unit in state.units:
|
||||
|
@ -81,16 +76,15 @@ proc init*(
|
|||
global = true,
|
||||
parent: Unit = nil,
|
||||
): Bot =
|
||||
var self =
|
||||
Bot(
|
||||
id: id,
|
||||
start_transform: transform,
|
||||
animation_value: ~"auto",
|
||||
speed: 1.0,
|
||||
clone_of: clone_of,
|
||||
start_color: action_colors[black],
|
||||
parent: parent,
|
||||
)
|
||||
var self = Bot(
|
||||
id: id,
|
||||
start_transform: transform,
|
||||
animation_value: ~"auto",
|
||||
speed: 1.0,
|
||||
clone_of: clone_of,
|
||||
start_color: action_colors[black],
|
||||
parent: parent,
|
||||
)
|
||||
|
||||
self.init_unit
|
||||
|
||||
|
|
|
@ -22,12 +22,11 @@ var
|
|||
proc draw*(self: Build, position: Vector3, voxel: VoxelInfo) {.gcsafe.}
|
||||
|
||||
method code_template*(self: Build, imports: string): string =
|
||||
result =
|
||||
build_code_template(
|
||||
read_file(self.script_ctx.script).encode(safe = true),
|
||||
self.script_ctx.script,
|
||||
imports,
|
||||
)
|
||||
result = build_code_template(
|
||||
read_file(self.script_ctx.script).encode(safe = true),
|
||||
self.script_ctx.script,
|
||||
imports,
|
||||
)
|
||||
|
||||
proc buffer(position: Vector3): Vector3 =
|
||||
(position / ChunkSize).floor
|
||||
|
@ -210,9 +209,8 @@ proc remove(self: Build) =
|
|||
state.skip_block_paint = true
|
||||
draw_normal = self.target_normal
|
||||
let point =
|
||||
self.target_point - self.target_normal - (
|
||||
self.target_normal.inverse_normalized * 0.5
|
||||
)
|
||||
self.target_point - self.target_normal -
|
||||
(self.target_normal.inverse_normalized * 0.5)
|
||||
|
||||
skip_point = vec3()
|
||||
last_point = self.target_point
|
||||
|
@ -271,17 +269,16 @@ method on_begin_move*(
|
|||
finish = self.transform.origin + moving * steps
|
||||
finish_time = 1.0 / self.speed * steps
|
||||
|
||||
result =
|
||||
proc(delta: float, _: MonoTime): TaskStates =
|
||||
duration += delta
|
||||
if duration >= finish_time:
|
||||
self.transform_value.origin = finish
|
||||
return Done
|
||||
else:
|
||||
self.transform_value.origin =
|
||||
self.transform.origin + (moving * self.speed * delta)
|
||||
result = proc(delta: float, _: MonoTime): TaskStates =
|
||||
duration += delta
|
||||
if duration >= finish_time:
|
||||
self.transform_value.origin = finish
|
||||
return Done
|
||||
else:
|
||||
self.transform_value.origin =
|
||||
self.transform.origin + (moving * self.speed * delta)
|
||||
|
||||
return Running
|
||||
return Running
|
||||
else:
|
||||
if self.speed == 0:
|
||||
self.voxels_per_frame = float.high
|
||||
|
@ -290,20 +287,19 @@ method on_begin_move*(
|
|||
self.voxels_per_frame = self.speed
|
||||
var count = 0
|
||||
|
||||
result =
|
||||
proc(delta: float, timeout: MonoTime): TaskStates =
|
||||
while count.float < steps and self.voxels_remaining_this_frame >= 1 and
|
||||
get_mono_time() < timeout:
|
||||
if steps < 1:
|
||||
self.draw_transform =
|
||||
self.draw_transform.translated(direction * steps)
|
||||
else:
|
||||
self.draw_transform = self.draw_transform.translated(direction)
|
||||
inc count
|
||||
self.voxels_remaining_this_frame -= 1
|
||||
self.drop_block()
|
||||
result = proc(delta: float, timeout: MonoTime): TaskStates =
|
||||
while count.float < steps and self.voxels_remaining_this_frame >= 1 and
|
||||
get_mono_time() < timeout:
|
||||
if steps < 1:
|
||||
self.draw_transform =
|
||||
self.draw_transform.translated(direction * steps)
|
||||
else:
|
||||
self.draw_transform = self.draw_transform.translated(direction)
|
||||
inc count
|
||||
self.voxels_remaining_this_frame -= 1
|
||||
self.drop_block()
|
||||
|
||||
if count.float >= steps: NextTask else: Running
|
||||
if count.float >= steps: NextTask else: Running
|
||||
|
||||
method on_begin_turn*(
|
||||
self: Build, axis: Vector3, degrees: float, lean: bool, move_mode: int
|
||||
|
@ -326,19 +322,17 @@ method on_begin_turn*(
|
|||
.rotated(axis, deg_to_rad(degrees)).orthonormalized
|
||||
.scaled(vec3(scale, scale, scale))
|
||||
|
||||
result =
|
||||
proc(delta: float, _: MonoTime): TaskStates =
|
||||
duration += delta
|
||||
self.transform_value.basis =
|
||||
self.transform.basis.rotated(
|
||||
axis, deg_to_rad(degrees * delta * self.speed)
|
||||
)
|
||||
result = proc(delta: float, _: MonoTime): TaskStates =
|
||||
duration += delta
|
||||
self.transform_value.basis = self.transform.basis.rotated(
|
||||
axis, deg_to_rad(degrees * delta * self.speed)
|
||||
)
|
||||
|
||||
if duration <= 1.0 / self.speed:
|
||||
Running
|
||||
else:
|
||||
self.transform = final_transform
|
||||
Done
|
||||
if duration <= 1.0 / self.speed:
|
||||
Running
|
||||
else:
|
||||
self.transform = final_transform
|
||||
Done
|
||||
else:
|
||||
let axis = self.draw_transform.basis.xform(axis)
|
||||
self.draw_transform_value.basis =
|
||||
|
@ -402,20 +396,19 @@ proc init*(
|
|||
bot_collisions = true,
|
||||
parent: Unit = nil,
|
||||
): Build =
|
||||
var self =
|
||||
Build(
|
||||
id: id,
|
||||
chunks: ~(Table[Vector3, Chunk], {SyncLocal, SyncRemote}),
|
||||
start_transform: transform,
|
||||
draw_transform_value: ~(Transform.init, flags = {}),
|
||||
start_color: color,
|
||||
drawing: true,
|
||||
bounds_value: ~init_aabb(vec3(), vec3(-1, -1, -1)),
|
||||
speed: 1.0,
|
||||
clone_of: clone_of,
|
||||
bot_collisions: bot_collisions,
|
||||
parent: parent,
|
||||
)
|
||||
var self = Build(
|
||||
id: id,
|
||||
chunks: ~(Table[Vector3, Chunk], {SyncLocal, SyncRemote}),
|
||||
start_transform: transform,
|
||||
draw_transform_value: ~(Transform.init, flags = {}),
|
||||
start_color: color,
|
||||
drawing: true,
|
||||
bounds_value: ~init_aabb(vec3(), vec3(-1, -1, -1)),
|
||||
speed: 1.0,
|
||||
clone_of: clone_of,
|
||||
bot_collisions: bot_collisions,
|
||||
parent: parent,
|
||||
)
|
||||
|
||||
self.init_unit
|
||||
|
||||
|
@ -438,16 +431,16 @@ method main_thread_joined*(self: Build) =
|
|||
root.walk_tree proc(unit: Unit) =
|
||||
unit.local_flags -= Highlight
|
||||
if TargetMoved.touched:
|
||||
let length =
|
||||
(
|
||||
self.target_point * self.target_normal -
|
||||
last_point * self.target_normal
|
||||
).length
|
||||
let length = (
|
||||
self.target_point * self.target_normal - last_point * self.target_normal
|
||||
).length
|
||||
|
||||
if state.skip_block_paint:
|
||||
state.skip_block_paint = false
|
||||
elif state.draw_unit_id == self.id and self.target_normal == draw_normal and
|
||||
length <= 5 and self.target_point != skip_point:
|
||||
elif (
|
||||
state.draw_unit_id == self.id and self.target_normal == draw_normal and
|
||||
length <= 5 and self.target_point != skip_point
|
||||
):
|
||||
if SecondaryDown in state.local_flags:
|
||||
self.remove
|
||||
elif PrimaryDown in state.local_flags:
|
||||
|
@ -495,16 +488,15 @@ method clone*(self: Build, clone_to: Unit, id: string): Unit =
|
|||
# we need this off for Potato Zombies, but on for the
|
||||
# tutorials. Make it configurable somehow.
|
||||
let bot_collisions = true #not (clone_to of Bot)
|
||||
let clone =
|
||||
Build.init(
|
||||
id = id,
|
||||
transform = transform,
|
||||
clone_of = self,
|
||||
global = global,
|
||||
color = self.start_color,
|
||||
bot_collisions = bot_collisions,
|
||||
parent = clone_to,
|
||||
)
|
||||
let clone = Build.init(
|
||||
id = id,
|
||||
transform = transform,
|
||||
clone_of = self,
|
||||
global = global,
|
||||
color = self.start_color,
|
||||
bot_collisions = bot_collisions,
|
||||
parent = clone_to,
|
||||
)
|
||||
|
||||
for loc, info in self.shared.edits[self.id]:
|
||||
if info.kind != Hole and loc notin clone.shared.edits[clone.id]:
|
||||
|
|
|
@ -12,12 +12,11 @@ proc fire(self: Ground, append = false) {.gcsafe.} =
|
|||
let local = point.local_to(add_to)
|
||||
add_to.draw(local, (Manual, state.selected_color))
|
||||
else:
|
||||
add_to =
|
||||
Build.init(
|
||||
transform = Transform.init(origin = point),
|
||||
global = true,
|
||||
color = state.selected_color,
|
||||
)
|
||||
add_to = Build.init(
|
||||
transform = Transform.init(origin = point),
|
||||
global = true,
|
||||
color = state.selected_color,
|
||||
)
|
||||
|
||||
state.units += add_to
|
||||
add_to.global_flags += Dirty
|
||||
|
@ -28,11 +27,10 @@ proc fire(self: Ground, append = false) {.gcsafe.} =
|
|||
bot.global_flags += Dirty
|
||||
|
||||
proc init*(_: type Ground, node: Spatial): Ground =
|
||||
let self =
|
||||
Ground(
|
||||
global_flags: ~set[GlobalModelFlags],
|
||||
local_flags: ~(set[LocalModelFlags], {SyncLocal}),
|
||||
)
|
||||
let self = Ground(
|
||||
global_flags: ~set[GlobalModelFlags],
|
||||
local_flags: ~(set[LocalModelFlags], {SyncLocal}),
|
||||
)
|
||||
|
||||
state.local_flags.changes:
|
||||
if PrimaryDown.added and Hover in self.local_flags:
|
||||
|
|
|
@ -3,14 +3,13 @@ import godotapi/spatial
|
|||
import core, models/units
|
||||
|
||||
proc init*(_: type Player): Player =
|
||||
result =
|
||||
Player(
|
||||
id: \"player-{Zen.thread_ctx.id}",
|
||||
rotation_value: ~0.0,
|
||||
start_transform: Transform.init(origin = vec3(0, 1, 0)),
|
||||
input_direction_value: ~Vector3,
|
||||
cursor_position_value: ~((0, 0)),
|
||||
)
|
||||
result = Player(
|
||||
id: \"player-{Zen.thread_ctx.id}",
|
||||
rotation_value: ~0.0,
|
||||
start_transform: Transform.init(origin = vec3(0, 1, 0)),
|
||||
input_direction_value: ~Vector3,
|
||||
cursor_position_value: ~((0, 0)),
|
||||
)
|
||||
result.init_unit(shared = false)
|
||||
result.global_flags += Global
|
||||
|
||||
|
|
|
@ -80,12 +80,11 @@ proc from_json_hook(self: var Transform, json: JsonNode) =
|
|||
|
||||
proc from_json_hook(self: var Build, json: JsonNode) =
|
||||
let color = json["start_color"].json_to(Color)
|
||||
self =
|
||||
Build.init(
|
||||
id = json["id"].json_to(string),
|
||||
transform = json["start_transform"].json_to(Transform),
|
||||
color = color,
|
||||
)
|
||||
self = Build.init(
|
||||
id = json["id"].json_to(string),
|
||||
transform = json["start_transform"].json_to(Transform),
|
||||
color = color,
|
||||
)
|
||||
|
||||
if load_chunks:
|
||||
var edit = ~Table[Vector3, VoxelInfo]()
|
||||
|
@ -95,11 +94,10 @@ proc from_json_hook(self: var Build, json: JsonNode) =
|
|||
self.shared.edits.from_json(json["edits"])
|
||||
|
||||
proc from_json_hook(self: var Bot, json: JsonNode) =
|
||||
self =
|
||||
Bot.init(
|
||||
id = json["id"].json_to(string),
|
||||
transform = json["start_transform"].json_to(Transform),
|
||||
)
|
||||
self = Bot.init(
|
||||
id = json["id"].json_to(string),
|
||||
transform = json["start_transform"].json_to(Transform),
|
||||
)
|
||||
|
||||
if not load_chunks:
|
||||
self.shared.edits.from_json(json["edits"])
|
||||
|
@ -117,16 +115,14 @@ proc `$`(self: tuple[voxel: Vector3, info: VoxelInfo]): string =
|
|||
\"[{self.voxel}, [{int self.info.kind}, {self.info.color}]]"
|
||||
|
||||
proc `$`(self: ZenTable[string, ZenTable[Vector3, VoxelInfo]]): string =
|
||||
let edits =
|
||||
collect:
|
||||
for id, edit in self.value:
|
||||
let json =
|
||||
collect:
|
||||
for voxel, info in edit.value:
|
||||
$(voxel, info)
|
||||
if json.len > 0:
|
||||
let elements = json.join(",\n").indent(2)
|
||||
\"\"{id}\": [\n{elements}\n]"
|
||||
let edits = collect:
|
||||
for id, edit in self.value:
|
||||
let json = collect:
|
||||
for voxel, info in edit.value:
|
||||
$(voxel, info)
|
||||
if json.len > 0:
|
||||
let elements = json.join(",\n").indent(2)
|
||||
\"\"{id}\": [\n{elements}\n]"
|
||||
result = edits.join(",\n")
|
||||
|
||||
proc `$`(self: Unit): string =
|
||||
|
@ -134,20 +130,23 @@ proc `$`(self: Unit): string =
|
|||
let edits = $self.shared.edits
|
||||
result =
|
||||
\"""
|
||||
{{
|
||||
"id": "{self.id}",
|
||||
"start_transform": {{
|
||||
"basis": [
|
||||
{elements.indent(6)}
|
||||
],
|
||||
"origin": {$self.start_transform.origin}
|
||||
}},
|
||||
"start_color": {self.start_color},
|
||||
"edits": {{
|
||||
{edits.indent(4)}
|
||||
}}
|
||||
}}
|
||||
"""
|
||||
|
||||
{{
|
||||
"id": "{self.id}",
|
||||
"start_transform": {{
|
||||
"basis": [
|
||||
{elements.indent(6)}
|
||||
],
|
||||
"origin": {$self.start_transform.origin}
|
||||
}},
|
||||
"start_color": {self.start_color},
|
||||
"edits": {{
|
||||
{edits.indent(4)}
|
||||
}}
|
||||
}}
|
||||
|
||||
|
||||
"""
|
||||
|
||||
proc save*(unit: Unit) =
|
||||
if not ?unit.clone_of:
|
||||
|
@ -184,8 +183,9 @@ proc backup_level*(level_dir: string) =
|
|||
backup_dir / state.config.level & "_" &
|
||||
times.now().format("yyyy-MM-dd-HH-mm-ss") & ".zip"
|
||||
|
||||
let backups =
|
||||
walk_files(backup_dir / state.config.level & "_????-??-??-??-??-??.zip").to_seq.sorted
|
||||
let backups = walk_files(
|
||||
backup_dir / state.config.level & "_????-??-??-??-??-??.zip"
|
||||
).to_seq.sorted
|
||||
|
||||
if backups.len > 19:
|
||||
for file in backups[0 ..^ 20]:
|
||||
|
|
|
@ -13,22 +13,21 @@ proc init*(
|
|||
billboard = false,
|
||||
text_only = false,
|
||||
): Sign =
|
||||
var self =
|
||||
Sign(
|
||||
id: "sign_" & generate_id(),
|
||||
message_value: ~message,
|
||||
more_value: ~more,
|
||||
width_value: ~width,
|
||||
height_value: ~height,
|
||||
size_value: ~size,
|
||||
billboard_value: ~billboard,
|
||||
frame_created: state.frame_count,
|
||||
start_color: action_colors[black],
|
||||
start_transform: transform,
|
||||
owner_value: ~owner,
|
||||
text_only: text_only,
|
||||
parent: owner,
|
||||
)
|
||||
var self = Sign(
|
||||
id: "sign_" & generate_id(),
|
||||
message_value: ~message,
|
||||
more_value: ~more,
|
||||
width_value: ~width,
|
||||
height_value: ~height,
|
||||
size_value: ~size,
|
||||
billboard_value: ~billboard,
|
||||
frame_created: state.frame_count,
|
||||
start_color: action_colors[black],
|
||||
start_transform: transform,
|
||||
owner_value: ~owner,
|
||||
text_only: text_only,
|
||||
parent: owner,
|
||||
)
|
||||
self.init_unit
|
||||
result = self
|
||||
|
||||
|
|
|
@ -124,24 +124,23 @@ proc err*(self: GameState, args: varargs[string, `$`]) =
|
|||
|
||||
proc init*(_: type GameState): GameState =
|
||||
let flags = {SyncLocal}
|
||||
let self =
|
||||
GameState(
|
||||
player_value: ~(Player, flags),
|
||||
local_flags: ~(set[LocalStateFlags], flags),
|
||||
global_flags: ~(set[GlobalStateFlags], id = "state_global_flags"),
|
||||
units: ~(seq[Unit], id = "root_units"),
|
||||
open_unit_value: ~(Unit, flags),
|
||||
config_value: ~(Config, flags, id = "config"),
|
||||
tool_value: ~(BlueBlock, flags),
|
||||
gravity: -80.0,
|
||||
console: ConsoleModel(log: ~(seq[string], flags)),
|
||||
open_sign_value: ~(Sign, flags),
|
||||
wants: ~(seq[LocalStateFlags], flags),
|
||||
level_name_value: ~("", id = "level_name"),
|
||||
queued_action_value: ~("", flags),
|
||||
status_message_value: ~("", flags),
|
||||
voxel_tasks_value: ~(0, flags),
|
||||
)
|
||||
let self = GameState(
|
||||
player_value: ~(Player, flags),
|
||||
local_flags: ~(set[LocalStateFlags], flags),
|
||||
global_flags: ~(set[GlobalStateFlags], id = "state_global_flags"),
|
||||
units: ~(seq[Unit], id = "root_units"),
|
||||
open_unit_value: ~(Unit, flags),
|
||||
config_value: ~(Config, flags, id = "config"),
|
||||
tool_value: ~(BlueBlock, flags),
|
||||
gravity: -80.0,
|
||||
console: ConsoleModel(log: ~(seq[string], flags)),
|
||||
open_sign_value: ~(Sign, flags),
|
||||
wants: ~(seq[LocalStateFlags], flags),
|
||||
level_name_value: ~("", id = "level_name"),
|
||||
queued_action_value: ~("", flags),
|
||||
status_message_value: ~("", flags),
|
||||
voxel_tasks_value: ~(0, flags),
|
||||
)
|
||||
result = self
|
||||
self.open_unit_value.changes:
|
||||
if added and change.item != nil:
|
||||
|
|
|
@ -56,9 +56,8 @@ proc find_root*(self: Unit, all_clones = false): Unit =
|
|||
while parent != nil:
|
||||
result = parent
|
||||
|
||||
if (all_clones and not ?parent.clone_of) or (
|
||||
not all_clones and Global in parent.global_flags
|
||||
):
|
||||
if (all_clones and not ?parent.clone_of) or
|
||||
(not all_clones and Global in parent.global_flags):
|
||||
parent = nil
|
||||
else:
|
||||
parent = parent.parent
|
||||
|
|
|
@ -88,8 +88,9 @@ gdobj AimTarget of Sprite3D:
|
|||
self.look_at(align_normal, self.transform.basis.x)
|
||||
|
||||
if ?unit:
|
||||
if (unit.target_point, unit.target_normal) !=
|
||||
(local_point, local_normal):
|
||||
if (unit.target_point, unit.target_normal) != (
|
||||
local_point, local_normal
|
||||
):
|
||||
unit.target_point = local_point
|
||||
unit.target_normal = local_normal
|
||||
unit.local_flags.touch TargetMoved
|
||||
|
|
|
@ -112,11 +112,10 @@ gdobj BotNode of KinematicBody:
|
|||
var velocity_zid: ZID
|
||||
if self.model of Bot:
|
||||
let bot = Bot(self.model)
|
||||
velocity_zid =
|
||||
bot.velocity_value.watch:
|
||||
if touched:
|
||||
if bot.animation == "auto":
|
||||
self.set_walk_animation(change.item.length, false)
|
||||
velocity_zid = bot.velocity_value.watch:
|
||||
if touched:
|
||||
if bot.animation == "auto":
|
||||
self.set_walk_animation(change.item.length, false)
|
||||
bot.animation_value.watch:
|
||||
if added or touched and change.item in ["", "auto"]:
|
||||
self.animation_player.play("idle")
|
||||
|
@ -152,10 +151,9 @@ gdobj BotNode of KinematicBody:
|
|||
if added:
|
||||
self.set_color(change.item)
|
||||
|
||||
self.transform_zid =
|
||||
self.model.transform_value.watch:
|
||||
if added:
|
||||
self.transform = change.item
|
||||
self.transform_zid = self.model.transform_value.watch:
|
||||
if added:
|
||||
self.transform = change.item
|
||||
|
||||
self.model.sight_query_value.watch:
|
||||
if added:
|
||||
|
|
|
@ -78,9 +78,11 @@ gdobj BuildNode of VoxelTerrain:
|
|||
"emission", self.model.shared.emission_colors[i].to_variant
|
||||
)
|
||||
|
||||
if Highlight in self.model.local_flags or (
|
||||
HighlightError in self.model.local_flags and self.error_highlight_on
|
||||
):
|
||||
if Highlight in self.model.local_flags or
|
||||
(
|
||||
HighlightError in self.model.local_flags and
|
||||
self.error_highlight_on
|
||||
):
|
||||
m.set_shader_param("emission_energy", highlight_glow.to_variant)
|
||||
else:
|
||||
m.set_shader_param("emission_energy", self.model.glow.to_variant)
|
||||
|
@ -88,14 +90,13 @@ gdobj BuildNode of VoxelTerrain:
|
|||
proc track_chunk(chunk_id: Vector3) =
|
||||
if chunk_id in self.model.chunks:
|
||||
self.draw_block(self.model.chunks[chunk_id])
|
||||
self.active_chunks[chunk_id] =
|
||||
self.model.chunks[chunk_id].watch:
|
||||
# `and not modified` isn't required, but the block will be
|
||||
# replaced on the next iteration anyway.
|
||||
if removed and not modified:
|
||||
self.draw(change.item.key, action_colors[eraser])
|
||||
elif added:
|
||||
self.draw(change.item.key, change.item.value.color)
|
||||
self.active_chunks[chunk_id] = self.model.chunks[chunk_id].watch:
|
||||
# `and not modified` isn't required, but the block will be
|
||||
# replaced on the next iteration anyway.
|
||||
if removed and not modified:
|
||||
self.draw(change.item.key, action_colors[eraser])
|
||||
elif added:
|
||||
self.draw(change.item.key, change.item.value.color)
|
||||
self.draw_block(self.model.chunks[chunk_id])
|
||||
else:
|
||||
self.active_chunks[chunk_id] = empty_zid
|
||||
|
@ -126,14 +127,13 @@ gdobj BuildNode of VoxelTerrain:
|
|||
self.visible = false
|
||||
|
||||
proc track_chunks() =
|
||||
self.chunks_zid =
|
||||
self.model.chunks.watch:
|
||||
let id = change.item.key
|
||||
if id in self.active_chunks:
|
||||
if added:
|
||||
self.track_chunk(change.item.key)
|
||||
elif removed:
|
||||
self.active_chunks[id] = empty_zid
|
||||
self.chunks_zid = self.model.chunks.watch:
|
||||
let id = change.item.key
|
||||
if id in self.active_chunks:
|
||||
if added:
|
||||
self.track_chunk(change.item.key)
|
||||
elif removed:
|
||||
self.active_chunks[id] = empty_zid
|
||||
|
||||
proc untrack_chunks() =
|
||||
Zen.thread_ctx.untrack(self.chunks_zid)
|
||||
|
@ -191,10 +191,9 @@ gdobj BuildNode of VoxelTerrain:
|
|||
self.model.transform = self.transform
|
||||
self.max_view_distance = int(self.default_view_distance.float / scale)
|
||||
|
||||
self.transform_zid =
|
||||
self.model.transform_value.watch:
|
||||
if added:
|
||||
self.transform = change.item
|
||||
self.transform_zid = self.model.transform_value.watch:
|
||||
if added:
|
||||
self.transform = change.item
|
||||
|
||||
self.model.sight_query_value.watch:
|
||||
if added:
|
||||
|
|
|
@ -160,15 +160,13 @@ gdobj PlayerNode of KinematicBody:
|
|||
self.transform = change.item
|
||||
|
||||
self.camera_rig.rotation = vec3(0, deg_to_rad self.model.rotation, 0)
|
||||
self.rotation_zid =
|
||||
self.model.rotation_value.watch:
|
||||
if added or touched:
|
||||
self.camera_rig.rotation = vec3(0, deg_to_rad change.item, 0)
|
||||
self.rotation_zid = self.model.rotation_value.watch:
|
||||
if added or touched:
|
||||
self.camera_rig.rotation = vec3(0, deg_to_rad change.item, 0)
|
||||
|
||||
self.velocity_zid =
|
||||
self.model.velocity_value.watch:
|
||||
if added:
|
||||
self.velocity = change.item
|
||||
self.velocity_zid = self.model.velocity_value.watch:
|
||||
if added:
|
||||
self.velocity = change.item
|
||||
|
||||
proc current_raycast*(): RayCast =
|
||||
if MouseCaptured in state.local_flags: self.aim_ray else: self.world_ray
|
||||
|
@ -176,8 +174,7 @@ gdobj PlayerNode of KinematicBody:
|
|||
method process*(delta: float) =
|
||||
self.model.velocity_value.pause self.velocity_zid:
|
||||
self.model.velocity = self.velocity
|
||||
if EditorVisible notin state.local_flags or
|
||||
CommandMode in state.local_flags:
|
||||
if EditorVisible notin state.local_flags or CommandMode in state.local_flags:
|
||||
var transform = self.camera_rig.global_transform
|
||||
transform.origin = self.global_transform.origin + self.position_start
|
||||
|
||||
|
@ -243,20 +240,18 @@ gdobj PlayerNode of KinematicBody:
|
|||
move_direction.y = 0
|
||||
move_direction += up
|
||||
|
||||
var velocity =
|
||||
self.calculate_velocity(
|
||||
self.velocity, move_direction, delta, self.flying, self.alt_speed
|
||||
)
|
||||
var velocity = self.calculate_velocity(
|
||||
self.velocity, move_direction, delta, self.flying, self.alt_speed
|
||||
)
|
||||
|
||||
self.model.input_direction = input_direction
|
||||
self.velocity = self.move_and_slide(velocity, UP)
|
||||
|
||||
self.model.transform = self.transform
|
||||
|
||||
let collisions =
|
||||
collect:
|
||||
for i in 0 .. (self.get_slide_count - 1):
|
||||
self.get_slide_collision(i)
|
||||
let collisions = collect:
|
||||
for i in 0 .. (self.get_slide_count - 1):
|
||||
self.get_slide_collision(i)
|
||||
|
||||
handle_collisions(self.model, collisions)
|
||||
|
||||
|
@ -304,9 +299,8 @@ gdobj PlayerNode of KinematicBody:
|
|||
self.input_relative += event.as(InputEventMouseMotion).relative()
|
||||
else:
|
||||
self.skip_next_mouse_move = false
|
||||
if EditorVisible in state.local_flags and not self.skip_release and (
|
||||
event of InputEventJoypadButton or event of InputEventJoypadMotion
|
||||
):
|
||||
if EditorVisible in state.local_flags and not self.skip_release and
|
||||
(event of InputEventJoypadButton or event of InputEventJoypadMotion):
|
||||
let active_input = self.has_active_input(event.device.int)
|
||||
if CommandMode in state.local_flags and not active_input:
|
||||
self.command_timer = input_command_timeout
|
||||
|
|
|
@ -82,8 +82,9 @@ gdobj Editor of TextEdit:
|
|||
state.player.open_code = self.text
|
||||
|
||||
method on_cursor_changed*() =
|
||||
state.player.cursor_position =
|
||||
(int self.cursor_get_line, int self.cursor_get_column)
|
||||
state.player.cursor_position = (
|
||||
int self.cursor_get_line, int self.cursor_get_column
|
||||
)
|
||||
|
||||
method ready*() =
|
||||
self.bind_signals(self, "text_changed", "cursor_changed")
|
||||
|
@ -107,14 +108,13 @@ gdobj Editor of TextEdit:
|
|||
self.visible = false
|
||||
state.player.open_code = ""
|
||||
else:
|
||||
line_zid =
|
||||
unit.current_line_value.changes:
|
||||
if added:
|
||||
# only update the executing line if the code hasn't been changed.
|
||||
if self.text == state.open_unit.code.nim:
|
||||
self.executing_line = change.item - 1
|
||||
else:
|
||||
self.clear_executing_line()
|
||||
line_zid = unit.current_line_value.changes:
|
||||
if added:
|
||||
# only update the executing line if the code hasn't been changed.
|
||||
if self.text == state.open_unit.code.nim:
|
||||
self.executing_line = change.item - 1
|
||||
else:
|
||||
self.clear_executing_line()
|
||||
self.visible = true
|
||||
self.text = state.open_unit.code.nim
|
||||
state.player.open_code = self.text
|
||||
|
|
|
@ -114,10 +114,9 @@ gdobj MarkdownLabel of ScrollContainer:
|
|||
self.og_text_edit.add_font_override("font", self.local_mono_font)
|
||||
self.og_label.add_font_override("normal_font", self.local_default_font)
|
||||
|
||||
self.zid =
|
||||
state.config_value.changes:
|
||||
if added:
|
||||
self.set_font_sizes()
|
||||
self.zid = state.config_value.changes:
|
||||
if added:
|
||||
self.set_font_sizes()
|
||||
|
||||
self.update
|
||||
|
||||
|
|
|
@ -40,11 +40,10 @@ gdobj RightPanel of MarginContainer:
|
|||
var sign = change.item
|
||||
self.label.markdown = md(sign, sign.more)
|
||||
self.label.update
|
||||
self.zid =
|
||||
sign.more_value.changes:
|
||||
if added:
|
||||
self.label.markdown = md(sign, change.item)
|
||||
self.label.update
|
||||
self.zid = sign.more_value.changes:
|
||||
if added:
|
||||
self.label.markdown = md(sign, change.item)
|
||||
self.label.update
|
||||
if removed and change.item != nil:
|
||||
if change.item.more_value.valid:
|
||||
change.item.more_value.untrack(self.zid)
|
||||
|
@ -63,8 +62,7 @@ gdobj RightPanel of MarginContainer:
|
|||
self.modulate = solid_alpha
|
||||
|
||||
method unhandled_input*(event: InputEvent) =
|
||||
if DocsFocused in state.local_flags and
|
||||
event.is_action_pressed("ui_cancel"):
|
||||
if DocsFocused in state.local_flags and event.is_action_pressed("ui_cancel"):
|
||||
if not (event of InputEventJoypadButton) or
|
||||
CommandMode notin state.local_flags:
|
||||
state.open_sign = nil
|
||||
|
|
|
@ -27,12 +27,11 @@ gdobj Toolbar of HBoxContainer:
|
|||
self.visible = true
|
||||
state.tool = BlueBlock
|
||||
|
||||
self.zid =
|
||||
state.tool_value.changes:
|
||||
if added:
|
||||
let b = self.get_child(int(change.item)) as Button
|
||||
if ?b:
|
||||
b.set_pressed true
|
||||
self.zid = state.tool_value.changes:
|
||||
if added:
|
||||
let b = self.get_child(int(change.item)) as Button
|
||||
if ?b:
|
||||
b.set_pressed true
|
||||
|
||||
method process*(delta: float) =
|
||||
if self.preview_result.is_some:
|
||||
|
|
|
@ -24,7 +24,7 @@ block:
|
|||
echo "count1: " & $count1 & " count2: " & $count2
|
||||
nil -> task1
|
||||
if count1 > 5:
|
||||
task1 -> task2:
|
||||
task1 -> task2 do:
|
||||
echo "finished in main"
|
||||
do:
|
||||
inc count2
|
||||
|
@ -102,7 +102,7 @@ block:
|
|||
nil -> action_b(name)
|
||||
inc counter
|
||||
if counter == 2:
|
||||
action_b -> loop_b as loop_b2:
|
||||
action_b -> loop_b as loop_b2 do:
|
||||
counter = -20
|
||||
loop_b2 -> action_c(name)
|
||||
if counter == 6:
|
||||
|
@ -119,19 +119,19 @@ block:
|
|||
counter = 0
|
||||
var name = "loop_main"
|
||||
loop nil:
|
||||
nil -> loop_a as initial_loop:
|
||||
nil -> loop_a as initial_loop do:
|
||||
echo "initial loop "
|
||||
inc counter
|
||||
if done:
|
||||
initial_loop -> action_a(name):
|
||||
initial_loop -> action_a(name) do:
|
||||
counter = 0
|
||||
if counter == 3:
|
||||
action_a -> action_b(name):
|
||||
action_a -> action_b(name) do:
|
||||
counter = 0
|
||||
action_b -> action_c(name) as ac:
|
||||
action_b -> action_c(name) as ac do:
|
||||
counter = 0
|
||||
ac -> loop_a:
|
||||
ac -> loop_a do:
|
||||
counter = 0
|
||||
if counter == 70:
|
||||
loop_a -> nil:
|
||||
loop_a -> nil do:
|
||||
echo "loop_main done ", counter
|
||||
|
|
|
@ -7,14 +7,12 @@ let
|
|||
vmlib = "vmlib"
|
||||
e = Engine()
|
||||
script_dir = nim_filename().parent_dir & "/scripts/instancing"
|
||||
script_1 =
|
||||
"""
|
||||
script_1 = """
|
||||
var place = "script 1 header"
|
||||
proc in_script_1_header*() = echo "in script 1 header"
|
||||
include "script_1.nim"
|
||||
""".dedent
|
||||
script_2 =
|
||||
"""
|
||||
""".dedent
|
||||
script_2 = """
|
||||
import script_1
|
||||
var place = "script 2 header"
|
||||
proc in_script_2_header*() = echo "in script 2 header"
|
||||
|
@ -23,7 +21,7 @@ let
|
|||
in_script_1_body()
|
||||
in_script_2_header()
|
||||
in_script_2_body()
|
||||
""".dedent
|
||||
""".dedent
|
||||
|
||||
e.load(script_dir, script_dir & "/script_1.nim", script_1, vmlib)
|
||||
assert not e.run()
|
||||
|
|
|
@ -5,9 +5,8 @@ import libs/[interpreters, eval]
|
|||
|
||||
var state = GameState.active
|
||||
|
||||
state.logger =
|
||||
proc(level, msg: string) =
|
||||
echo level, ": ", msg
|
||||
state.logger = proc(level, msg: string) =
|
||||
echo level, ": ", msg
|
||||
|
||||
state.config.script_dir =
|
||||
current_source_path().parent_dir / "scripts" / "instancing"
|
||||
|
|
|
@ -9,8 +9,7 @@ let f: float = 1 .. 100
|
|||
echo "float: ", f
|
||||
var position = vec3(1.0, 1.0, 1.0)
|
||||
|
||||
position =
|
||||
vec3(
|
||||
position.x + -2.0 .. 2.0, position.y + -2.0 .. 2.0, position.z + -2.0 .. 2.0
|
||||
)
|
||||
position = vec3(
|
||||
position.x + -2.0 .. 2.0, position.y + -2.0 .. 2.0, position.z + -2.0 .. 2.0
|
||||
)
|
||||
echo position
|
||||
|
|
|
@ -8,28 +8,26 @@ let
|
|||
e = Engine()
|
||||
script_dir = nim_filename().parent_dir & "/scripts"
|
||||
prefix = "proc log*(s:string) = discard\n"
|
||||
user_classes1 =
|
||||
"""
|
||||
user_classes1 = """
|
||||
type
|
||||
Type1* = object
|
||||
name*: string
|
||||
""".dedent
|
||||
user_classes2 =
|
||||
"""
|
||||
""".dedent
|
||||
user_classes2 = """
|
||||
type
|
||||
Type1* = object
|
||||
name*: string
|
||||
size*: int
|
||||
Type2* = object
|
||||
name*: string
|
||||
""".dedent
|
||||
""".dedent
|
||||
script1 =
|
||||
prefix &
|
||||
"""
|
||||
import user_classes
|
||||
let a = Type1(name: "type1")
|
||||
log "a=" & a.repr
|
||||
""".dedent
|
||||
""".dedent
|
||||
script2 =
|
||||
prefix &
|
||||
"""
|
||||
|
@ -38,7 +36,7 @@ let
|
|||
let b = Type2(name: "type2")
|
||||
log "a=" & a.repr
|
||||
log "b=" & b.repr
|
||||
""".dedent
|
||||
""".dedent
|
||||
|
||||
e.load(script_dir, script_dir & "/user_classes.nim", user_classes1, vmlib)
|
||||
assert not e.run()
|
||||
|
@ -62,4 +60,4 @@ assert output ==
|
|||
a=(name: "type1")
|
||||
a=(name: "type1", size: 5)
|
||||
b=(name: "type2")
|
||||
""".dedent
|
||||
""".dedent
|
||||
|
|
|
@ -3,17 +3,14 @@ import globals, os
|
|||
proc echo(args: varargs[string, `$`]) =
|
||||
stdout.write "Enu: " & args.join() & "\n"
|
||||
|
||||
echo_console =
|
||||
proc(msg: string) =
|
||||
echo msg
|
||||
echo_console = proc(msg: string) =
|
||||
echo msg
|
||||
|
||||
logger =
|
||||
proc(level, msg: string) =
|
||||
echo level, ": ", msg
|
||||
logger = proc(level, msg: string) =
|
||||
echo level, ": ", msg
|
||||
|
||||
game_node = gdnew[Node]()
|
||||
config =
|
||||
Config(
|
||||
lib_dir: get_current_dir() & "/../vmlib",
|
||||
script_dir: nim_filename().parent_dir & "/scripts",
|
||||
)
|
||||
config = Config(
|
||||
lib_dir: get_current_dir() & "/../vmlib",
|
||||
script_dir: nim_filename().parent_dir & "/scripts",
|
||||
)
|
||||
|
|
|
@ -24,7 +24,7 @@ block:
|
|||
echo "count1: " & $count1 & " count2: " & $count2
|
||||
nil -> task1
|
||||
if count1 > 5:
|
||||
task1 -> task2:
|
||||
task1 -> task2 do:
|
||||
echo "finished in main"
|
||||
do:
|
||||
inc count2
|
||||
|
@ -102,7 +102,7 @@ block:
|
|||
nil -> action_b(name)
|
||||
inc counter
|
||||
if counter == 2:
|
||||
action_b -> loop_b as loop_b2:
|
||||
action_b -> loop_b as loop_b2 do:
|
||||
counter = -20
|
||||
loop_b2 -> action_c(name)
|
||||
if counter == 6:
|
||||
|
@ -119,19 +119,19 @@ block:
|
|||
counter = 0
|
||||
var name = "loop_main"
|
||||
loop nil:
|
||||
nil -> loop_a as initial_loop:
|
||||
nil -> loop_a as initial_loop do:
|
||||
echo "initial loop "
|
||||
inc counter
|
||||
if done:
|
||||
initial_loop -> action_a(name):
|
||||
initial_loop -> action_a(name) do:
|
||||
counter = 0
|
||||
if counter == 3:
|
||||
action_a -> action_b(name):
|
||||
action_a -> action_b(name) do:
|
||||
counter = 0
|
||||
action_b -> action_c(name) as ac:
|
||||
action_b -> action_c(name) as ac do:
|
||||
counter = 0
|
||||
ac -> loop_a:
|
||||
ac -> loop_a do:
|
||||
counter = 0
|
||||
if counter == 70:
|
||||
loop_a -> nil:
|
||||
loop_a -> nil do:
|
||||
echo "loop_main done ", counter
|
||||
|
|
|
@ -457,9 +457,8 @@ template x*(count: int, body: untyped): untyped =
|
|||
|
||||
macro dump*(x: typed): untyped =
|
||||
let s = x.toStrLit
|
||||
let r =
|
||||
quote:
|
||||
echo(`s` & " = " & $`x`)
|
||||
let r = quote:
|
||||
echo(`s` & " = " & $`x`)
|
||||
return r
|
||||
|
||||
template cycle*[T](args: varargs[T]): T =
|
||||
|
|
|
@ -81,13 +81,12 @@ proc params_to_accessors(type_name: NimNode, nodes: seq[NimNode]): NimNode =
|
|||
proc build_ctors(
|
||||
name_str: string, type_name: NimNode, params: seq[NimNode]
|
||||
): NimNode =
|
||||
var ctor_body =
|
||||
quote:
|
||||
assert not instance.is_nil
|
||||
link_dependency(instance)
|
||||
result = `type_name`()
|
||||
result.seed = active_unit().seed
|
||||
new_instance(instance, result)
|
||||
var ctor_body = quote:
|
||||
assert not instance.is_nil
|
||||
link_dependency(instance)
|
||||
result = `type_name`()
|
||||
result.seed = active_unit().seed
|
||||
new_instance(instance, result)
|
||||
|
||||
for param in params:
|
||||
let prop = param[0]
|
||||
|
@ -129,13 +128,12 @@ proc build_ctors(
|
|||
|
||||
# add baked in constructor params for speed, color, etc.
|
||||
# probably shouldn't be here.
|
||||
result =
|
||||
new_proc(
|
||||
name = "new".ident.postfix("*"),
|
||||
params = params,
|
||||
pragmas = nnkPragma.new_tree("discardable".ident),
|
||||
body = ctor_body,
|
||||
)
|
||||
result = new_proc(
|
||||
name = "new".ident.postfix("*"),
|
||||
params = params,
|
||||
pragmas = nnkPragma.new_tree("discardable".ident),
|
||||
body = ctor_body,
|
||||
)
|
||||
|
||||
proc extract_class_info(
|
||||
name_node: NimNode
|
||||
|
@ -166,9 +164,8 @@ proc build_class(name_node: NimNode, base_type: NimNode): NimNode =
|
|||
result = new_stmt_list()
|
||||
|
||||
let name_str = name
|
||||
var type_def =
|
||||
quote:
|
||||
type `type_name`* = ref object of `base_type`
|
||||
var type_def = quote:
|
||||
type `type_name`* = ref object of `base_type`
|
||||
|
||||
type_def[0][2][0][2] = params_to_properties(params)
|
||||
let accessors = params_to_accessors(type_name, params)
|
||||
|
@ -240,13 +237,12 @@ proc auto_insert_receiver(
|
|||
proc build_proc(sig, body: NimNode, return_type = new_empty_node()): NimNode =
|
||||
let (name, params, vars) = sig.parse_sig(return_type)
|
||||
let new_body = new_stmt_list(vars, body)
|
||||
result =
|
||||
new_proc(
|
||||
name = ident(name),
|
||||
params = params,
|
||||
body = new_body,
|
||||
pragmas = new_nim_node(nnkPragma).add(ident"discardable"),
|
||||
)
|
||||
result = new_proc(
|
||||
name = ident(name),
|
||||
params = params,
|
||||
body = new_body,
|
||||
pragmas = new_nim_node(nnkPragma).add(ident"discardable"),
|
||||
)
|
||||
|
||||
proc transform_commands(parent: NimNode): NimNode =
|
||||
for i, node in parent:
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
var context: Context
|
||||
|
||||
me.advance_state_machine =
|
||||
proc(): bool =
|
||||
result =
|
||||
if not context.is_nil:
|
||||
context.advance()
|
||||
else:
|
||||
true
|
||||
me.advance_state_machine = proc(): bool =
|
||||
result =
|
||||
if not context.is_nil:
|
||||
context.advance()
|
||||
else:
|
||||
true
|
||||
|
||||
proc loop_started(ctx: Context, main_loop: bool) =
|
||||
if main_loop:
|
||||
|
|
|
@ -114,12 +114,11 @@ macro loop*(body: untyped) =
|
|||
macro loop*(sig: untyped, body: untyped): untyped =
|
||||
var (name, params, vars) = sig.parse_sig
|
||||
|
||||
let proc_body =
|
||||
quote:
|
||||
const this_state {.inject.} = `name . ast_to_str`
|
||||
`vars`
|
||||
loop:
|
||||
`body`
|
||||
let proc_body = quote:
|
||||
const this_state {.inject.} = `name . ast_to_str`
|
||||
`vars`
|
||||
loop:
|
||||
`body`
|
||||
|
||||
result = new_stmt_list()
|
||||
params.add new_ident_defs(ident"ctx", ident"Context", new_nil_lit())
|
||||
|
@ -129,9 +128,8 @@ macro loop*(sig: untyped, body: untyped): untyped =
|
|||
macro smart_call*(call: untyped) =
|
||||
var call_without_ctx = call.copy_nim_tree
|
||||
call_without_ctx.del call_without_ctx.len - 1
|
||||
result =
|
||||
quote:
|
||||
when compiles(`call`): `call` else: `call_without_ctx`
|
||||
result = quote:
|
||||
when compiles(`call`): `call` else: `call_without_ctx`
|
||||
|
||||
proc transition(from_state, to_state, body, immediate: NimNode): NimNode =
|
||||
var
|
||||
|
@ -208,35 +206,34 @@ proc transition(from_state, to_state, body, immediate: NimNode): NimNode =
|
|||
includes_str = includes.join(",")
|
||||
excludes_str = excludes.join(",")
|
||||
|
||||
result =
|
||||
quote:
|
||||
when not declared(current_state) or not declared(ctx):
|
||||
{.error: "`->` or `==>` must be inside a `loop` ".}
|
||||
if `immediate` or (active and done):
|
||||
let
|
||||
from_includes: seq[string] = `includes_str`.split(",")
|
||||
from_excludes: seq[string] = `excludes_str`.split(",")
|
||||
if (
|
||||
current_state in from_includes or (
|
||||
current_state != "nil" and (
|
||||
("others" in from_includes and `to_state_name` != current_state) or
|
||||
"any" in from_includes
|
||||
)
|
||||
result = quote:
|
||||
when not declared(current_state) or not declared(ctx):
|
||||
{.error: "`->` or `==>` must be inside a `loop` ".}
|
||||
if `immediate` or (active and done):
|
||||
let
|
||||
from_includes: seq[string] = `includes_str`.split(",")
|
||||
from_excludes: seq[string] = `excludes_str`.split(",")
|
||||
if (
|
||||
current_state in from_includes or (
|
||||
current_state != "nil" and (
|
||||
("others" in from_includes and `to_state_name` != current_state) or
|
||||
"any" in from_includes
|
||||
)
|
||||
) and current_state notin from_excludes:
|
||||
current_state = `to_state_name`
|
||||
first_iteration = true
|
||||
proc action() =
|
||||
if first_iteration:
|
||||
`body`
|
||||
smart_call(`to_state`)
|
||||
first_iteration = false
|
||||
)
|
||||
) and current_state notin from_excludes:
|
||||
current_state = `to_state_name`
|
||||
first_iteration = true
|
||||
proc action() =
|
||||
if first_iteration:
|
||||
`body`
|
||||
smart_call(`to_state`)
|
||||
first_iteration = false
|
||||
|
||||
if `to_state_name` != "nil":
|
||||
frame.action = action
|
||||
else:
|
||||
frame.action = nil
|
||||
raise (ref Halt)()
|
||||
if `to_state_name` != "nil":
|
||||
frame.action = action
|
||||
else:
|
||||
frame.action = nil
|
||||
raise (ref Halt)()
|
||||
|
||||
macro `==>`*(from_state: untyped, to_state: untyped, body: untyped = nil) =
|
||||
result = transition(from_state, to_state, body, ident"true")
|
||||
|
@ -257,7 +254,7 @@ when is_main_module:
|
|||
echo "count: " & $count
|
||||
nil -> task1
|
||||
if count > 5:
|
||||
task1 -> task2:
|
||||
task1 -> task2 do:
|
||||
echo "finished in main"
|
||||
if count > 10:
|
||||
echo "true true"
|
||||
|
@ -288,7 +285,7 @@ when is_main_module:
|
|||
loop:
|
||||
if counter > 100:
|
||||
(little_square, big_square) -> nil
|
||||
(nil, big_square) -> square(counter) as little_square:
|
||||
(nil, big_square) -> square(counter) as little_square do:
|
||||
inc counter
|
||||
little_square -> square(2) as big_square
|
||||
|
||||
|
@ -321,7 +318,7 @@ when is_main_module:
|
|||
nil -> action_b(name)
|
||||
inc counter
|
||||
if counter == 2:
|
||||
action_b ==> loop_b:
|
||||
action_b ==> loop_b do:
|
||||
counter = -20
|
||||
loop_b ==> action_c(name)
|
||||
if counter == 6:
|
||||
|
@ -337,21 +334,21 @@ when is_main_module:
|
|||
counter = 0
|
||||
var name = "loop_main"
|
||||
loop:
|
||||
nil ==> loop_a as initial_loop:
|
||||
nil ==> loop_a as initial_loop do:
|
||||
echo "initial loop "
|
||||
inc counter
|
||||
if done:
|
||||
initial_loop ==> action_a(name):
|
||||
initial_loop ==> action_a(name) do:
|
||||
counter = 0
|
||||
if counter == 3:
|
||||
action_a ==> action_b(name):
|
||||
action_a ==> action_b(name) do:
|
||||
counter = 0
|
||||
action_b ==> action_c(name) as ac:
|
||||
action_b ==> action_c(name) as ac do:
|
||||
counter = 0
|
||||
ac ==> loop_a:
|
||||
ac ==> loop_a do:
|
||||
counter = 0
|
||||
if counter == 70:
|
||||
loop_a ==> nil:
|
||||
loop_a ==> nil do:
|
||||
echo "loop_main done ", counter
|
||||
|
||||
loop:
|
||||
|
|
|
@ -31,9 +31,8 @@ macro bridged_to_host*(body: untyped): untyped =
|
|||
let params = node.params
|
||||
var call = new_call impl_proc
|
||||
var def = copy_nim_tree(node)
|
||||
def.body =
|
||||
quote:
|
||||
raise_assert `impl_proc` & " must be implemented by host"
|
||||
def.body = quote:
|
||||
raise_assert `impl_proc` & " must be implemented by host"
|
||||
def[0] = ident(impl_proc)
|
||||
|
||||
if params.len > 1:
|
||||
|
|
|
@ -5,29 +5,33 @@ lock = true
|
|||
|
||||
let overview =
|
||||
\"""
|
||||
World `{world_name()}`
|
||||
|
||||
Level `{level_name()}`
|
||||
"""
|
||||
World `{world_name()}`
|
||||
|
||||
Level `{level_name()}`
|
||||
|
||||
"""
|
||||
|
||||
let details =
|
||||
\"""
|
||||
# Menu
|
||||
|
||||
Welcome to level `{level_name()}` of world `{world_name()}`.
|
||||
# Menu
|
||||
|
||||
- [Next Level](<nim://press_action("next_level")>)
|
||||
Welcome to level `{level_name()}` of world `{world_name()}`.
|
||||
|
||||
- [Previous Level](<nim://press_action("prev_level")>)
|
||||
- [Next Level](<nim://press_action("next_level")>)
|
||||
|
||||
- [Help](https://ē.nu/docs/intro.html)
|
||||
- [Previous Level](<nim://press_action("prev_level")>)
|
||||
|
||||
- [Load Tutorial](<nim://load_level("tutorial-1", "tutorial")>)
|
||||
- [Help](https://ē.nu/docs/intro.html)
|
||||
|
||||
- [Load Examples](<nim://load_level("tutorial-2", "tutorial")>)
|
||||
- [Load Tutorial](<nim://load_level("tutorial-1", "tutorial")>)
|
||||
|
||||
- [Reset Level](<nim://reset_level()>)
|
||||
"""
|
||||
- [Load Examples](<nim://load_level("tutorial-2", "tutorial")>)
|
||||
|
||||
- [Reset Level](<nim://reset_level()>)
|
||||
|
||||
"""
|
||||
|
||||
turn 180
|
||||
up 5
|
||||
|
|
|
@ -39,30 +39,32 @@ proc get_bot(): Bot =
|
|||
-movement_info:
|
||||
say "# . . .",
|
||||
"""
|
||||
# Welcome to Enu!
|
||||
|
||||
Enu is a 3D world where you can code and create almost anything using a
|
||||
programming language called [Nim](https://nim-lang.org). It's a place to
|
||||
make games, experiment, and learn to code. You're using an early prototype
|
||||
that's missing important features and is full of bugs, but it's getting
|
||||
better quickly. Please contact me at [dsrw@me.com](mailto:dsrw@me.com) if
|
||||
you have any questions or suggestions.
|
||||
# Welcome to Enu!
|
||||
|
||||
In this tutorial you'll learn to move and do some simple coding. In later
|
||||
tutorials we'll make towers, tunnels, characters, and will finish with a 3D
|
||||
survival game called `Inky: Isolation`.
|
||||
Enu is a 3D world where you can code and create almost anything using a
|
||||
programming language called [Nim](https://nim-lang.org). It's a place to make
|
||||
games, experiment, and learn to code. You're using an early prototype that's
|
||||
missing important features and is full of bugs, but it's getting better quickly.
|
||||
Please contact me at [dsrw@me.com](mailto:dsrw@me.com) if you have any questions
|
||||
or suggestions.
|
||||
|
||||
Move with the `W`, `A`, `S`, and `D` keys, or with the left stick of your
|
||||
game controller. Look around with the mouse, trackpad, or right stick of
|
||||
your game controller.
|
||||
In this tutorial you'll learn to move and do some simple coding. In later
|
||||
tutorials we'll make towers, tunnels, characters, and will finish with a 3D
|
||||
survival game called `Inky: Isolation`.
|
||||
|
||||
You can close this window by pressing `ESC` on your keyboard or `B` on your
|
||||
controller, and can come back at any time by clicking on the text block next
|
||||
to the `Bot`. You can also move without closing the window by using your
|
||||
controller, or by holding down left `alt/option (⌥)` on your keyboard.
|
||||
Move with the `W`, `A`, `S`, and `D` keys, or with the left stick of your game
|
||||
controller. Look around with the mouse, trackpad, or right stick of your game
|
||||
controller.
|
||||
|
||||
Sneak behind the `Bot` to continue the tutorial.
|
||||
""",
|
||||
You can close this window by pressing `ESC` on your keyboard or `B` on your
|
||||
controller, and can come back at any time by clicking on the text block next to
|
||||
the `Bot`. You can also move without closing the window by using your
|
||||
controller, or by holding down left `alt/option (⌥)` on your keyboard.
|
||||
|
||||
Sneak behind the `Bot` to continue the tutorial.
|
||||
|
||||
""",
|
||||
width = 0.6
|
||||
|
||||
menu.show = true
|
||||
|
@ -72,20 +74,22 @@ proc get_bot(): Bot =
|
|||
-flying_info:
|
||||
say "- Good!",
|
||||
"""
|
||||
# Jumping and Flying
|
||||
|
||||
Jump with the `space` bar, or the `A` button on your game controller.
|
||||
# Jumping and Flying
|
||||
|
||||
Fly by jumping twice quickly. Fly upwards by holding the jump button, and
|
||||
downwards by holding crouch (`C` on the keyboard or `B` on a game
|
||||
controller). Return to the ground by pressing the `jump` button twice.
|
||||
Jump with the `space` bar, or the `A` button on your game controller.
|
||||
|
||||
Flying is a great way to see things from a better angle and to zip around
|
||||
your world at high speed. It also lets you move through objects and blocks,
|
||||
so if you ever get yourself stuck you can probably fly your way out.
|
||||
Fly by jumping twice quickly. Fly upwards by holding the jump button, and
|
||||
downwards by holding crouch (`C` on the keyboard or `B` on a game controller).
|
||||
Return to the ground by pressing the `jump` button twice.
|
||||
|
||||
Jump, fly, then returning to the ground to continue the tutorial.
|
||||
""",
|
||||
Flying is a great way to see things from a better angle and to zip around your
|
||||
world at high speed. It also lets you move through objects and blocks, so if you
|
||||
ever get yourself stuck you can probably fly your way out.
|
||||
|
||||
Jump, fly, then returning to the ground to continue the tutorial.
|
||||
|
||||
""",
|
||||
width = 1.4
|
||||
|
||||
speed = 1
|
||||
|
@ -107,22 +111,24 @@ proc get_bot(): Bot =
|
|||
-tool_info:
|
||||
say "- Switch to `Place Bot`",
|
||||
"""
|
||||
# Changing tools
|
||||
|
||||
Tools are selected from the `Tool Bar` on the bottom of the screen.
|
||||
# Changing tools
|
||||
|
||||
Change tools with the keyboard keys `1` - `8`, the `L1` and `R1` controller
|
||||
buttons, or by releasing the mouse with `ESC` and selecting a tool with the
|
||||
mouse pointer.
|
||||
Tools are selected from the `Tool Bar` on the bottom of the screen.
|
||||
|
||||
Enu currently has 8 tools. Tool `1` on the left is the `Code` tool. It can
|
||||
program almost anything in Enu, and will be explained in more detail later.
|
||||
Tool `8` on the right is the `Place Bot` tool. Use it to fill your world
|
||||
with friendly robots. Tools `2` - `7` are the `blue`, `red`, `green`,
|
||||
`black`, `white`, and `brown` colored blocks.
|
||||
Change tools with the keyboard keys `1` - `8`, the `L1` and `R1` controller
|
||||
buttons, or by releasing the mouse with `ESC` and selecting a tool with the
|
||||
mouse pointer.
|
||||
|
||||
Select the `Place Bot` tool to continue the tutorial.
|
||||
""",
|
||||
Enu currently has 8 tools. Tool `1` on the left is the `Code` tool. It can
|
||||
program almost anything in Enu, and will be explained in more detail later.
|
||||
Tool `8` on the right is the `Place Bot` tool. Use it to fill your world with
|
||||
friendly robots. Tools `2` - `7` are the `blue`, `red`, `green`, `black`,
|
||||
`white`, and `brown` colored blocks.
|
||||
|
||||
Select the `Place Bot` tool to continue the tutorial.
|
||||
|
||||
""",
|
||||
width = 2.5
|
||||
|
||||
sign.open = true
|
||||
|
@ -133,15 +139,17 @@ proc get_bot(): Bot =
|
|||
-bot_info:
|
||||
say "- Place a `Bot`",
|
||||
"""
|
||||
# Bots
|
||||
|
||||
`Bots` are NPCs in Enu, and can be programmed to explore, change their
|
||||
appearance, or offer information.
|
||||
# Bots
|
||||
|
||||
They can be placed with the `left` mouse button or the `R1` gamepad trigger.
|
||||
`Bots` are NPCs in Enu, and can be programmed to explore, change their
|
||||
appearance, or offer information.
|
||||
|
||||
Place a `Bot` on the ground to continue the tutorial.
|
||||
""",
|
||||
They can be placed with the `left` mouse button or the `R1` gamepad trigger.
|
||||
|
||||
Place a `Bot` on the ground to continue the tutorial.
|
||||
|
||||
""",
|
||||
width = 2.0
|
||||
|
||||
sign.open = true
|
||||
|
@ -170,15 +178,17 @@ proc get_bot(): Bot =
|
|||
-code_info:
|
||||
say "- Coding",
|
||||
"""
|
||||
# Coding Enu
|
||||
|
||||
We control Enu using [Nim](https://nim-lang.org), a powerful programming
|
||||
language that's useful for a wide variety of tasks. Almost everything in Enu
|
||||
can be coded with Nim. Let's start by teaching our `Bot` to walk to the end
|
||||
of the course.
|
||||
# Coding Enu
|
||||
|
||||
Switch to the `Code` tool to continue the tutorial.
|
||||
"""
|
||||
We control Enu using [Nim](https://nim-lang.org), a powerful programming
|
||||
language that's useful for a wide variety of tasks. Almost everything in Enu
|
||||
can be coded with Nim. Let's start by teaching our `Bot` to walk to the end of
|
||||
the course.
|
||||
|
||||
Switch to the `Code` tool to continue the tutorial.
|
||||
|
||||
"""
|
||||
|
||||
sign.open = true
|
||||
while player.tool != CodeMode:
|
||||
|
@ -188,13 +198,15 @@ proc get_bot(): Bot =
|
|||
-open_code:
|
||||
sign.more =
|
||||
"""
|
||||
# Coding Enu
|
||||
|
||||
With the `Code` tool selected, you can code anything you've created by
|
||||
clicking on it with the `left` mouse button, or `R1` on the controller
|
||||
# Coding Enu
|
||||
|
||||
Open the code for your `Bot` to continue the tutorial.
|
||||
"""
|
||||
With the `Code` tool selected, you can code anything you've created by clicking
|
||||
on it with the `left` mouse button, or `R1` on the controller
|
||||
|
||||
Open the code for your `Bot` to continue the tutorial.
|
||||
|
||||
"""
|
||||
|
||||
sign.open = true
|
||||
var bot = get_bot()
|
||||
|
@ -206,40 +218,42 @@ proc get_bot(): Bot =
|
|||
-bot_navigation:
|
||||
sign.more =
|
||||
"""
|
||||
# Coding Bots
|
||||
|
||||
We control the bot with simple commands like `forward` and `turn`. Here's
|
||||
some code to get our `Bot` partway through the course:
|
||||
# Coding Bots
|
||||
|
||||
```nim
|
||||
forward 17
|
||||
turn right
|
||||
forward 10
|
||||
turn left
|
||||
```
|
||||
We control the bot with simple commands like `forward` and `turn`. Here's some
|
||||
code to get our `Bot` partway through the course:
|
||||
|
||||
Please finish the code to get the `Bot` get to the end of the course.
|
||||
```nim
|
||||
forward 17
|
||||
turn right
|
||||
forward 10
|
||||
turn left
|
||||
```
|
||||
|
||||
Run your code by pressing left `alt/option (⌥)`. Keep left `alt/option (⌥)`
|
||||
held down to move around while you're coding. Flying is a great way to get
|
||||
yourself into position to see what's happening, so try double jumping to get
|
||||
a better view.
|
||||
Please finish the code to get the `Bot` get to the end of the course.
|
||||
|
||||
If your `Bot` is moving too slowly for your tastes, make her run by setting
|
||||
the `speed` value.
|
||||
Run your code by pressing left `alt/option (⌥)`. Keep left `alt/option (⌥)` held
|
||||
down to move around while you're coding. Flying is a great way to get yourself
|
||||
into position to see what's happening, so try double jumping to get a better
|
||||
view.
|
||||
|
||||
```nim
|
||||
speed = 10
|
||||
If your `Bot` is moving too slowly for your tastes, make her run by setting the
|
||||
`speed` value.
|
||||
|
||||
forward 17
|
||||
turn right
|
||||
forward 10
|
||||
turn left
|
||||
```
|
||||
```nim
|
||||
speed = 10
|
||||
|
||||
Good luck! We'll conclude this tutorial when your `Bot` goes past the
|
||||
`FINISH HERE!` sign at the end of the course.
|
||||
"""
|
||||
forward 17
|
||||
turn right
|
||||
forward 10
|
||||
turn left
|
||||
```
|
||||
|
||||
Good luck! We'll conclude this tutorial when your `Bot` goes past the
|
||||
`FINISH HERE!` sign at the end of the course.
|
||||
|
||||
"""
|
||||
|
||||
sign.open = true
|
||||
var bot = get_bot()
|
||||
|
@ -253,27 +267,28 @@ proc get_bot(): Bot =
|
|||
sleep 15
|
||||
say "- All Done!",
|
||||
"""
|
||||
# Great Job!
|
||||
|
||||
Good work! You learned the basics of Enu, and you coded your first robot.
|
||||
There's a lot more to come. Everything here - the signs, the course, the
|
||||
giant spinning confetti monster, were created with `Nim` code inside Enu,
|
||||
and we'll cover how to do all of it in future tutorials.
|
||||
# Great Job!
|
||||
|
||||
This is supposed to be where you move to the next tutorial, but it hasn't
|
||||
been written yet. For now, you can try some
|
||||
[Enu examples](<nim://load_level("tutorial-2")>) or load
|
||||
[Inky: Isolation](<nim://load_level("tutorial-3")>), a simple
|
||||
game written in Enu that's loosley inspired by **Alien: Isolation**, but
|
||||
features Inky, the blue ghost from Pac-Man. If you're curious how this
|
||||
tutorial was written, click
|
||||
[HERE](<nim://player.god = true;sign.open = false>) to turn on `God Mode`,
|
||||
which will let you see and modify its code. It's a bit of a mess, but some
|
||||
folks might find it interesting.
|
||||
Good work! You learned the basics of Enu, and you coded your first robot.
|
||||
There's a lot more to come. Everything here - the signs, the course, the giant
|
||||
spinning confetti monster, were created with `Nim` code inside Enu, and we'll
|
||||
cover how to do all of it in future tutorials.
|
||||
|
||||
Contact me at [dsrw@me.com](mailto:dsrw@me.com) if you have any questions or
|
||||
suggestions. Thanks for trying Enu!
|
||||
"""
|
||||
This is supposed to be where you move to the next tutorial, but it hasn't been
|
||||
written yet. For now, you can try some
|
||||
[Enu examples](<nim://load_level("tutorial-2")>) or load
|
||||
[Inky: Isolation](<nim://load_level("tutorial-3")>), a simple
|
||||
game written in Enu that's loosley inspired by **Alien: Isolation**, but
|
||||
features Inky, the blue ghost from Pac-Man. If you're curious how this tutorial
|
||||
was written, click [HERE](<nim://player.god = true;sign.open = false>) to turn
|
||||
on `God Mode`, which will let you see and modify its code. It's a bit of a mess,
|
||||
but some folks might find it interesting.
|
||||
|
||||
Contact me at [dsrw@me.com](mailto:dsrw@me.com) if you have any questions or
|
||||
suggestions. Thanks for trying Enu!
|
||||
|
||||
"""
|
||||
|
||||
sign.open = true
|
||||
|
||||
|
|
|
@ -94,15 +94,13 @@ proc scroller(sign: Sign, msg: string, pause = 0, len = msg.len): proc() =
|
|||
var current = msg
|
||||
var counter = 0
|
||||
|
||||
result =
|
||||
proc() =
|
||||
if current == msg and counter < pause:
|
||||
inc counter
|
||||
else:
|
||||
counter = 0
|
||||
current = current[1 ..^ 1] & current[0]
|
||||
sign.message =
|
||||
"`" & current[0 .. (len - 1)].strip(leading = false) & "`"
|
||||
result = proc() =
|
||||
if current == msg and counter < pause:
|
||||
inc counter
|
||||
else:
|
||||
counter = 0
|
||||
current = current[1 ..^ 1] & current[0]
|
||||
sign.message = "`" & current[0 .. (len - 1)].strip(leading = false) & "`"
|
||||
|
||||
var start_scroller1 = start_sign1.scroller(" START HERE! ", 0, 7)
|
||||
|
||||
|
|
|
@ -6,36 +6,38 @@ lock = true
|
|||
|
||||
let overview =
|
||||
"""
|
||||
# ` ` Menu
|
||||
# ` ` Menu
|
||||
|
||||
- `Reset Tutorial`
|
||||
- `Help`
|
||||
- `...`
|
||||
"""
|
||||
- `Reset Tutorial`
|
||||
- `Help`
|
||||
- `...`
|
||||
|
||||
"""
|
||||
|
||||
let details =
|
||||
"""
|
||||
# Menu
|
||||
|
||||
Welcome! This is Tutorial 1, which covers the basics of playing and coding in
|
||||
Enu. If you're new, you should try it. It won't take long.
|
||||
# Menu
|
||||
|
||||
If you're not new, here are some other things to do:
|
||||
Welcome! This is Tutorial 1, which covers the basics of playing and coding in
|
||||
Enu. If you're new, you should try it. It won't take long.
|
||||
|
||||
- [Clear Changes and Reset Tutorial](<nim://reset_level()>). This resets and
|
||||
restarts this tutorial. Any changes you've made to the world will be lost.
|
||||
If you're not new, here are some other things to do:
|
||||
|
||||
- [Help](https://ē.nu/docs/intro.html). Help!
|
||||
- [Clear Changes and Reset Tutorial](<nim://reset_level()>). This resets and
|
||||
restarts this tutorial. Any changes you've made to the world will be lost.
|
||||
|
||||
- [Load Examples](<nim://load_level("tutorial-2")>). See some other things you
|
||||
can build with Enu.
|
||||
- [Help](https://ē.nu/docs/intro.html). Help!
|
||||
|
||||
- [Load Inky: Isolation](<nim://load_level("tutorial-3")>). `Inky: Isolation`
|
||||
is a simple game made with Enu. You can see how it was built in
|
||||
[this video](https://youtu.be/9e9sLsmsu_o).
|
||||
- [Load Examples](<nim://load_level("tutorial-2")>). See some other things you can build with Enu.
|
||||
|
||||
- [Load default world](<nim://load_level("default-1", "default")>).
|
||||
"""
|
||||
- [Load Inky: Isolation](<nim://load_level("tutorial-3")>). `Inky: Isolation` is
|
||||
a simple game made with Enu. You can see how it was built in
|
||||
[this video](https://youtu.be/9e9sLsmsu_o).
|
||||
|
||||
- [Load default world](<nim://load_level("default-1", "default")>).
|
||||
|
||||
"""
|
||||
|
||||
say overview, details, height = 3, width = 3, size = 320
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ loop:
|
|||
if player.near(10) and start_position.near(30):
|
||||
# `chase` if the player is near and we're not too far
|
||||
# from home base
|
||||
(wander, wander_home) ==> chase:
|
||||
(wander, wander_home) ==> chase do:
|
||||
# this will be called when the command switches
|
||||
say cycle(hellos)
|
||||
|
||||
|
|
|
@ -2,11 +2,13 @@ lock = true
|
|||
|
||||
let text =
|
||||
"""
|
||||
# Towers. Too Many Towers.
|
||||
|
||||
Code a building and name it `tower`. Give it some friends with `tower.new`.
|
||||
# Towers. Too Many Towers.
|
||||
|
||||
This is an example of a [Prototype](https://ē.nu/docs/coding/concepts.html).
|
||||
"""
|
||||
Code a building and name it `tower`. Give it some friends with `tower.new`.
|
||||
|
||||
This is an example of a [Prototype](https://ē.nu/docs/coding/concepts.html).
|
||||
|
||||
"""
|
||||
|
||||
say text, text, width = 3, height = 3
|
||||
|
|
|
@ -3,11 +3,13 @@ turn left
|
|||
|
||||
let text =
|
||||
"""
|
||||
# Annoying Robot
|
||||
|
||||
Annoying Robot offers words of wisdom while trying to chase you down.
|
||||
# Annoying Robot
|
||||
|
||||
This is an example of a [Command Loop](https://ē.nu/docs/command_loops.html).
|
||||
"""
|
||||
Annoying Robot offers words of wisdom while trying to chase you down.
|
||||
|
||||
This is an example of a [Command Loop](https://ē.nu/docs/command_loops.html).
|
||||
|
||||
"""
|
||||
|
||||
say text, text, height = 4
|
||||
|
|
|
@ -3,11 +3,13 @@ lock = true
|
|||
turn right
|
||||
let text =
|
||||
"""
|
||||
# ???
|
||||
|
||||
I'm not sure what this is supposed to be.
|
||||
# ???
|
||||
|
||||
It uses Nim's [math](https://nim-lang.org/docs/math.html) module to build with sine waves.
|
||||
"""
|
||||
I'm not sure what this is supposed to be.
|
||||
|
||||
It uses Nim's [math](https://nim-lang.org/docs/math.html) module to build with sine waves.
|
||||
|
||||
"""
|
||||
|
||||
say text, text, height = 3
|
||||
|
|
|
@ -6,28 +6,32 @@ let blurb =
|
|||
|
||||
let text =
|
||||
\"""
|
||||
# Examples
|
||||
|
||||
{blurb}
|
||||
# Examples
|
||||
|
||||
- Load Tutorial
|
||||
- Load Default World
|
||||
- Clear Changes and Reset Examples
|
||||
"""
|
||||
{blurb}
|
||||
|
||||
- Load Tutorial
|
||||
- Load Default World
|
||||
- Clear Changes and Reset Examples
|
||||
|
||||
"""
|
||||
|
||||
let more =
|
||||
\"""
|
||||
# Menu
|
||||
|
||||
{blurb}
|
||||
# Menu
|
||||
|
||||
- [Load Tutorial](<nim://load_level("tutorial-1")>) - Leave this level and load the Enu tutorial.
|
||||
{blurb}
|
||||
|
||||
- [Load Default World](<nim://load_level("default-1", "default")>).
|
||||
- [Load Tutorial](<nim://load_level("tutorial-1")>) - Leave this level and load the Enu tutorial.
|
||||
|
||||
- [Clear Changes and Reset Examples](<nim://reset_level()>) - Reset and reload this level. Be careful, all of your changes will be lost.
|
||||
- [Load Default World](<nim://load_level("default-1", "default")>).
|
||||
|
||||
- [Load Inky: Isolation](<nim://load_level("tutorial-3")>) - Load `Inky: Isolation`, a simple game made with Enu.
|
||||
"""
|
||||
- [Clear Changes and Reset Examples](<nim://reset_level()>) - Reset and reload this level. Be careful, all of your changes will be lost.
|
||||
|
||||
- [Load Inky: Isolation](<nim://load_level("tutorial-3")>) - Load `Inky: Isolation`, a simple game made with Enu.
|
||||
|
||||
"""
|
||||
|
||||
say text, more, height = 4, width = 3
|
||||
|
|
|
@ -4,11 +4,11 @@ move me
|
|||
loop:
|
||||
nil -> up(home + 0.2)
|
||||
if player.hit:
|
||||
up -> down(home + 0.2):
|
||||
up -> down(home + 0.2) do:
|
||||
door.open = true
|
||||
ghost.charge_player = true
|
||||
else:
|
||||
sleep -> up(home + 0.2):
|
||||
sleep -> up(home + 0.2) do:
|
||||
door.open = false
|
||||
down -> sleep(pause)
|
||||
glow = cycle(0.0, 0.05)
|
||||
|
|
|
@ -10,20 +10,18 @@ proc stop_playing*() =
|
|||
|
||||
proc level_menu*(me: Build, show_restart = true) =
|
||||
let blurb =
|
||||
"""
|
||||
`Inky: Isolation` is a simple survivial game created in Enu. Find buttons to
|
||||
open new areas of the space station. Hit the top of Inky's head to defeat
|
||||
them.
|
||||
"""
|
||||
"`Inky: Isolation` is a simple survivial game created in Enu. Find buttons to open new areas of the space station. Hit the top of Inky's head to defeat them."
|
||||
|
||||
let copy =
|
||||
\"""
|
||||
# Inky: Isolation
|
||||
|
||||
{blurb}
|
||||
# Inky: Isolation
|
||||
|
||||
- CLICK TO OPEN MENU
|
||||
"""
|
||||
{blurb}
|
||||
|
||||
- CLICK TO OPEN MENU
|
||||
|
||||
"""
|
||||
|
||||
me.right 3
|
||||
|
||||
|
@ -48,23 +46,24 @@ proc level_menu*(me: Build, show_restart = true) =
|
|||
|
||||
let more =
|
||||
\"""
|
||||
# Menu
|
||||
|
||||
{blurb}
|
||||
# Menu
|
||||
|
||||
See how `Inky: Isolation` was built in the video [Inky: Isolation. A 90
|
||||
minute game built with Enu and Nim](https://youtu.be/9e9sLsmsu_o)
|
||||
{blurb}
|
||||
|
||||
{toolbar_action}
|
||||
See how `Inky: Isolation` was built in the video [Inky: Isolation. A 90 minute game built with Enu and Nim](https://youtu.be/9e9sLsmsu_o)
|
||||
|
||||
{return_action}
|
||||
{toolbar_action}
|
||||
|
||||
- [LOAD TUTORIAL](<nim://load_level("tutorial-1")>)
|
||||
{return_action}
|
||||
|
||||
- [LOAD EXAMPLES](<nim://load_level("tutorial-2")>)
|
||||
- [LOAD TUTORIAL](<nim://load_level("tutorial-1")>)
|
||||
|
||||
- [CLEAR CHANGES AND RESET LEVEL](<nim://reset_level()>)
|
||||
"""
|
||||
- [LOAD EXAMPLES](<nim://load_level("tutorial-2")>)
|
||||
|
||||
- [CLEAR CHANGES AND RESET LEVEL](<nim://reset_level()>)
|
||||
|
||||
"""
|
||||
sign1.more = more
|
||||
sign2.more = more
|
||||
sleep 1
|
||||
|
|
Loading…
Reference in New Issue