diff --git a/board.gd b/board.gd index c3a2514..962d2af 100644 --- a/board.gd +++ b/board.gd @@ -18,11 +18,12 @@ func bottom_right_aabb() -> AABB: # todo: Array[Piece] func pieces() -> Array: + # todo: sort for consistency return get_children() func pieces_at(pos: Vector2i) -> Array[Piece]: var out: Array[Piece] = [] - for piece in get_children(): + for piece in pieces(): if piece.lpos == pos: out.push_back(piece) return out @@ -36,8 +37,12 @@ func find_piece_at(pos: Vector2i, filter: Callable) -> Piece: func any_at(pos: Vector2i, filter: Callable) -> bool: return pieces_at(pos).any(filter) +func type_at(pos: Vector2i, type: Piece.Type) -> Piece: + return find_piece_at(pos, func(p): return p.type == type) + +# TODO: ball collisions func solid_at(pos: Vector2i) -> bool: - return any_at(pos, func(p): return p.type == Piece.Type.Wall or p.type == Piece.Type.Box) + return any_at(pos, func(p): return p.type == Piece.Type.Wall or p.type == Piece.Type.Ball) func passable_at(pos: Vector2i) -> bool: return not solid_at(pos) @@ -71,9 +76,22 @@ static func from_string(src: String) -> Board: var pos := Vector2i(x, y) match c: ".": board.add_piece(Piece.goal(pos)) - "*": board.add_pieces([Piece.goal(pos), Piece.box(pos)]) "+": board.add_pieces([Piece.goal(pos), Piece.player(pos)]) - "$": board.add_piece(Piece.box(pos)) + "o": board.add_piece(Piece.ball(pos)) + "O": assert(false) "@": board.add_piece(Piece.player(pos)) "#": board.add_piece(Piece.wall(pos)) + "_": board.add_piece(Piece.floor_ice(pos)) return board + +func do_step(): + for piece in pieces(): + piece.do_step(self) + +func undo_step() -> Callable: + var undos: Array[Callable] = [] + for piece in pieces(): + undos.push_back(piece.undo_step()) + return func(): + for undo in undos: + undo.call() diff --git a/box.tres b/box.tres deleted file mode 100644 index 35813f1..0000000 --- a/box.tres +++ /dev/null @@ -1,10 +0,0 @@ -[gd_resource type="BoxMesh" load_steps=2 format=3 uid="uid://dlg5x0pi6xfnf"] - -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ig7tw"] -transparency = 1 -albedo_color = Color(0.858824, 0.52549, 0.32549, 0.784314) -metallic_specular = 0.0 - -[resource] -lightmap_size_hint = Vector2i(9, 13) -material = SubResource("StandardMaterial3D_ig7tw") diff --git a/goal.tres b/goal.tres deleted file mode 100644 index 22644ad..0000000 --- a/goal.tres +++ /dev/null @@ -1,22 +0,0 @@ -[gd_resource type="QuadMesh" load_steps=4 format=3 uid="uid://qxdm8y8lm754"] - -[sub_resource type="Gradient" id="Gradient_qb4hq"] -interpolation_mode = 1 -offsets = PackedFloat32Array(0, 0.373134) -colors = PackedColorArray(0.345925, 0.659465, 0.817842, 1, 1, 1, 1, 1) - -[sub_resource type="GradientTexture2D" id="GradientTexture2D_5y0qn"] -gradient = SubResource("Gradient_qb4hq") -width = 512 -height = 512 -fill = 1 -fill_from = Vector2(0.5, 0.5) -fill_to = Vector2(1, 1) - -[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_66cou"] -albedo_texture = SubResource("GradientTexture2D_5y0qn") -metallic_specular = 0.0 - -[resource] -material = SubResource("StandardMaterial3D_66cou") -orientation = 1 diff --git a/levels.txt b/levels.txt new file mode 100644 index 0000000..be860a6 --- /dev/null +++ b/levels.txt @@ -0,0 +1,43 @@ +; legend: +; # - wall +; @ - player +; o - ball +; O - big ball (more momentum! l8r) +; . - goal +; space - default, rough floor (-1 dlvel) +; _ - ice (0 dlvel) + +; cool idea for first two levels: +; first level just plays like slightly weird sokoban +; second level is the same layout but the *floor* is different +; TODO: multiple levels (could just be stacked on top) +; TODO: notation for ball on ice + +; 1 + +####### +# # +#@ o.# +# o ### +# # +# . # +##### + +; 2 + +####### +# # +#@ o.# +# o ### +# _ # +# . # +##### + +; 3 (diagonal movement should definitely be a sick twist for l8r) + +##### +#@ # +# o ## +# o# +###o.# + #### diff --git a/main.gd b/main.gd index 4161bb3..12fb0ea 100644 --- a/main.gd +++ b/main.gd @@ -1,12 +1,19 @@ extends Node3D +# moving and pushing take no time. +# MOVING. AND PUSHING. TAKE NO TIME. +# YES YES YES +# maybe only one move phase to keep things interesting? +# we lose some sokobanness, but is that a bad thing? @onready var camera: Camera3D = $Camera var hist := UndoRedo.new() @onready var board: Board = $Board var player: Piece -var level_num := -1 +var level_num := 0 var levels_src: PackedStringArray +var time := 0 +var advancing := false @onready var sound: AudioStreamPlayer = $Sound @onready var sounds_hit := audio_stream_randomizer_from_dir("res://sfx/hit") @@ -14,7 +21,7 @@ var levels_src: PackedStringArray @onready var sounds_redo := audio_stream_randomizer_from_dir("res://sfx/redo") func _ready() -> void: - var file := FileAccess.open("res://microban-1.txt", FileAccess.READ) + var file := FileAccess.open("res://levels.txt", FileAccess.READ) levels_src = file.get_as_text().split("\n\n") advance_level() @@ -22,6 +29,7 @@ func _process(delta: float) -> void: $UndoButton.disabled = not hist.has_undo() $RedoButton.disabled = not hist.has_redo() $RestartButton.disabled = not hist.has_undo() + $Clock.text = "T = %d" % time if $TopLeft.is_on_screen() and $BottomRight.is_on_screen(): return camera.position.y += 10*delta @@ -41,6 +49,8 @@ func _input(event: InputEvent) -> void: redo() elif event.is_action_pressed("restart", true, true): restart() + elif event.is_action_pressed("wait", true, true): + step(Vector2i.ZERO) func undo(): if hist.undo(): @@ -60,47 +70,82 @@ func restart(): # scratch that i like that, don't clear the history # you can like replay your steps up to a point +# time advancing, basically +func board_step(): + hist.add_do_property(self, "time", time+1) + hist.add_do_method(board.do_step) + hist.add_undo_method(board.undo_step()) + hist.add_undo_property(self, "time", time) + +# TODO: OH MY GOSH OG MY GOSH OH MY GOSH +# CONSOLIDATE ALL MOVEMENT INTO APPLYING VELOCITY +# INCLUDING PLAYER MOVEMENT +# I REALLY REALLY REALLY REALLY LIKE ADDING VELOCITY WITH TIME +# NOT CHANGING OH MY GOSH THAT IS *GOOD* func step(move: Vector2i): + if advancing: + return + # the ability to wait removes some parity stuff + # but that stuff kinda sucks + if move == Vector2i.ZERO: + hist.create_action("wait") + board_step() + hist.commit_action() + if won(): + advance_level() + return + var pos := player.lpos - var box := board.find_piece_at(pos + move, func(p): return p.type == Piece.Type.Box) + var ball := board.find_piece_at(pos + move, func(p): return p.type == Piece.Type.Ball) if board.passable_at(pos + move): hist.create_action("move") hist.add_do_method(player.do_move(move)) hist.add_undo_method(player.undo_move()) hist.commit_action() - elif box != null and board.passable_at(pos + move * 2): + elif ball != null: hist.create_action("push") - hist.add_do_method(player.do_move(move)) - hist.add_do_method(box.do_move(move)) - hist.add_undo_method(player.undo_move()) - hist.add_undo_method(box.undo_move()) + hist.add_do_method(ball.do_push(move)) + hist.add_do_method(func(): + player.lpos = pos + move + player.lpos = pos + player.anim_progress = 0.5 + ) + hist.add_undo_method(func(): + player.lpos = pos + move + player.lpos = pos + player.anim_progress = 0.5 + ) + hist.add_undo_method(ball.undo_push()) hist.commit_action() else: sound.stream = sounds_hit sound.play() - - if won() or Input.is_action_pressed("restart"): - advance_level() func won() -> bool: for piece in board.pieces(): if piece.type == Piece.Type.Goal: - var covered := board.any_at(piece.lpos, func(p): return p.type == Piece.Type.Box) + var covered := board.any_at(piece.lpos, func(p): return p.type == Piece.Type.Ball) if !covered: return false return true func advance_level(): hist.clear_history() + advancing = true + if level_num != 0: + print("level won") + await get_tree().create_timer(2).timeout + advancing = false + time = 0 level_num += 1 if level_num >= levels_src.size(): print("you win") return - while "@" not in levels_src[level_num] and "+" not in levels_src[level_num]: + while levels_src[level_num].contains(";") or ("@" not in levels_src[level_num] and "+" not in levels_src[level_num]): level_num += 1 + print(levels_src[level_num]) board.queue_free() board = Board.from_string(levels_src[level_num]) - var wall_count := 0 for piece in board.pieces(): if piece.type == Piece.Type.Player: player = piece diff --git a/main.tscn b/main.tscn index a61d153..42ca8b0 100644 --- a/main.tscn +++ b/main.tscn @@ -2,9 +2,9 @@ [ext_resource type="Script" uid="uid://c707s0tgd88pg" path="res://main.gd" id="1_ig7tw"] [ext_resource type="Script" uid="uid://c8ywa33v3jq7t" path="res://board.gd" id="2_0xm2m"] -[ext_resource type="Texture2D" uid="uid://bl73lsxse1roj" path="res://undo.png" id="3_lquwl"] -[ext_resource type="Texture2D" uid="uid://cs7ofsoatkhpk" path="res://redo.png" id="4_7mycd"] -[ext_resource type="Texture2D" uid="uid://dkl0lf6wlidup" path="res://restart.png" id="5_272bh"] +[ext_resource type="Texture2D" uid="uid://crahyipmcudoy" path="res://ui/undo.png" id="3_lquwl"] +[ext_resource type="Texture2D" uid="uid://dyj5el5iro1cb" path="res://ui/redo.png" id="4_7mycd"] +[ext_resource type="Texture2D" uid="uid://cbb1q0usxd6ex" path="res://ui/restart.png" id="5_272bh"] [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_ig7tw"] ground_bottom_color = Color(0.270778, 0.538085, 0.397052, 1) @@ -15,6 +15,7 @@ sky_material = SubResource("ProceduralSkyMaterial_ig7tw") [sub_resource type="Environment" id="Environment_ig7tw"] background_mode = 2 sky = SubResource("Sky_0xm2m") +ambient_light_color = Color(1, 1, 1, 1) [node name="Main" type="Node3D"] script = ExtResource("1_ig7tw") @@ -67,6 +68,16 @@ icon = ExtResource("5_272bh") flat = true expand_icon = true +[node name="Clock" type="RichTextLabel" parent="."] +offset_left = 1063.0 +offset_top = 28.0 +offset_right = 1244.0 +offset_bottom = 76.0 +theme_override_font_sizes/normal_font_size = 32 +text = "T = 0" +fit_content = true +horizontal_alignment = 2 + [connection signal="pressed" from="UndoButton" to="." method="undo"] [connection signal="pressed" from="RedoButton" to="." method="redo"] [connection signal="pressed" from="RestartButton" to="." method="restart"] diff --git a/microban-1.txt b/microban-1.txt deleted file mode 100644 index 656e21d..0000000 --- a/microban-1.txt +++ /dev/null @@ -1,1822 +0,0 @@ -; 1 all of these are by David W. Skinner - -#### -# .# -# ### -#*@ # -# $ # -# ### -#### - -; 2 - -###### -# # -# #@ # -# $* # -# .* # -# # -###### - -; 3 - - #### -### #### -# $ # -# # #$ # -# . .#@ # -######### - -; 4 - -######## -# # -# .**$@# -# # -##### # - #### - -; 5 - - ####### - # # - # .$. # -## $@$ # -# .$. # -# # -######## - -; 6 - -###### ##### -# ### # -# $$ #@# -# $ #... # -# ######## -##### - -; 7 - -####### -# # -# .$. # -# $.$ # -# .$. # -# $.$ # -# @ # -####### - -; 8 - - ###### - # ..@# - # $$ # - ## ### - # # - # # -#### # -# ## -# # # -# # # -### # - ##### - -; 9 - -##### -#. ## -#@$$ # -## # - ## # - ##.# - ### - -; 10 - - ##### - #. # - #.# # -#######.# # -# @ $ $ $ # -# # # # ### -# # -######### - -; 11 - - ###### - # # - # ##@## -### # $ # -# ..# $ # -# # -# ###### -#### - -; 12 - -##### -# ## -# $ # -## $ #### - ###@. # - # .# # - # # - ####### - -; 13 - -#### -#. ## -#.@ # -#. $# -##$ ### - # $ # - # # - # ### - #### - -; 14 - -####### -# # -# # # # -#. $*@# -# ### -##### - -; 15 - - ### -######@## -# .* # -# # # -#####$# # - # # - ##### - -; 16 - - #### - # #### - # ## -## ## # -#. .# @$## -# # $$ # -# .# # -########## - -; 17 - -##### -# @ # -#...# -#$$$## -# # -# # -###### - -; 18 - -####### -# # -#. . # -# ## ## -# $ # -###$ # - #@ # - # # - #### - -; 19 - -######## -# .. # -# @$$ # -##### ## - # # - # # - # # - #### - -; 20 - -####### -# ### -# @$$..# -#### ## # - # # - # #### - # # - #### - -; 21 - -#### -# #### -# . . # -# $$#@# -## # - ###### - -; 22 - -##### -# ### -#. . # -# # # -## # # - #@$$ # - # # - # ### - #### - -; 23 - -####### -# * # -# # -## # ## - #$@.# - # # - ##### - -; 24 - -# ##### - # # -###$$@# -# ### -# # -# . . # -####### - -; 25 - - #### - # ### - # $$ # -##... # -# @$ # -# ### -##### - -; 26 - - ##### - # @ # - # # -###$ # -# ...# -# $$ # -### # - #### - -; 27 - -###### -# .# -# ## ## -# $$@# -# # # -#. ### -##### - -; 28 - -##### -# # -# @ # -# $$### -##. . # - # # - ###### - -; 29 - - ##### - # ## - # # - ###### # -## #. # -# $ $ @ ## -# ######.# -# # -########## - -; 30 - -#### -# ### -# $$ # -#... # -# @$ # -# ## -##### - -; 31 - - #### - ## # -##@$.## -# $$ # -# . . # -### # - ##### - -; 32 - - #### -## ### -# # -#.**$@# -# ### -## # - #### - -; 33 - -####### -#. # # -# $ # -#. $#@# -# $ # -#. # # -####### - -; 34 - - #### -### #### -# # -#@$***. # -# # -######### - -; 35 - - #### - ## # - #. $# - #.$ # - #.$ # - #.$ # - #. $## - # @# - ## # - ##### - -; 36 - -#### -# ############ -# $ $ $ $ $ @ # -# ..... # -############### - -; 37 - - ### -##### #.# -# ###.# -# $ #.# -# $ $ # -#####@# # - # # - ##### - -; 38 - -########## -# # -# ##.### # -# # $$ . # -# . @$## # -##### # - ###### - -; 39 - -##### -# #### -# # # .# -# $ ### -### #$. # -# #@ # -# # ###### -# # -##### - -; 40 - - ##### - # # -## ## -# $$$ # -# .+. # -####### - -; 41 - -####### -# # -#@$$$ ## -# #...# -## ## - ###### - -; 42 - - #### - # # - #@ # -####$.# -# $.# -# # $.# -# ## -###### - -; 43 - - #### - # @# - # # -###### .# -# $ .# -# $$# .# -# #### -### # - #### - -; 44 'Duh!' - -##### -#@$.# -##### - -; 45 - -###### -#... # -# $ # -# #$## -# $ # -# @ # -###### - -; 46 - - ###### -## # -# ## # -# # $ # -# * .# -## #@## - # # - ##### - -; 47 - - ####### -### # -# $ $ # -# ### ##### -# @ . . # -# ### # -##### ##### - -; 48 - -###### -# @ # -# # ## -# .# ## -# .$$$ # -# .# # -#### # - ##### - -; 49 - -###### -# @ # -# $# # -# $ # -# $ ## -### #### - # # # - #... # - # # - ####### - -; 50 - - #### -### ##### -# $ @..# -# $ # # -### #### # - # # - ######## - -; 51 - -#### -# ### -# ### -# $*@ # -### .# # - # # - ###### - -; 52 - - #### -### @# -# $ # -# *.# -# *.# -# $ # -### # - #### - -; 53 - - ##### -##. .## -# * * # -# # # -# $ $ # -## @ ## - ##### - -; 54 - - ###### - # # - ##### . # -### ###. # -# $ $ . ## -# @$$ # . # -## ##### - ###### - -; 55 - -######## -# @ # # -# # -#####$ # - # ### - ## #$ ..# - ## # ### - #### - -; 56 - -##### -# ### -# $ # -##* . # - # @# - ###### - -; 57 - - #### - # # - #@ # - # # -### #### -# * # -# $ # -#####. # - #### - -; 58 - -#### -# #### -#.*$ # -# .$# # -## @ # - # ## - ##### - -; 59 - -############ -# # -# ####### @## -# # # -# # $ # # -# $$ ##### # -### # # ...# - #### # # - ###### - -; 60 - - ######### - # # -##@##### # -# # # # -# # $.# -# ##$##.# -##$## #.# -# $ #.# -# # ### -######## - -; 61 - -######## -# # -# #### # -# #...@# -# ###$### -# # # -# $$ $ # -#### ## - #.### - ### - -; 62 - - ########## -#### ## # -# $$$....$@# -# ### # -# #### #### -##### - -; 63 - -##### #### -# ##### .# -# $ ######## -### #### .$ @ # - # # # #### # - #### #### ##### - -; 64 - - ###### -## # -# $ # -# $$ # -### .##### - ##.# @ # - #. $ # - #. #### - #### - -; 65 - - ###### - # # - # $ # - ####$ # -## $ $ # -#....# ## -# @ # -## # # - ######## - -; 66 - - ### - #@# - ###$### -## . ## -# # # # -# # # # -# # # # -# # # # -# # # # -## $ $ ## - ##. .## - # # - # # - ##### - -; 67 - -##### -# ## -# # # -#@$*.## -## . # - # $# # - ## # - ##### - -; 68 - - #### - # ###### -## $ # -# .# $ # -# .#$##### -# .@ # -###### - -; 69 - -#### #### -# #### # -# # # # -# # $## -# . .#$ # -#@ ## # $ # -# . # # -########### - -; 70 - -##### -# @ #### -# # -# $ $$ # -##$## # -# #### -# .. # -##.. # - ### # - #### - -; 71 - -########### -# # ### -# $@$ # . .# -# ## ### ## # -# # # # -# # # # # -# ######### # -# # -############# - -; 72 - - #### - ## ##### - # $ @ # - # $# # -#### ##### -# # # -# $ # -# ..# # -# .#### -# ## -#### - -; 73 - -#### -# ##### -# $$ $ # -# # -## ## ## -#...#@# -# ### ## -# # -# # # -######## - -; 74 - - #### - # ####### - #$ @# .# -## #$$ .# -# $ ##..# -# # ##### -### # - ##### - -; 75 - - ####### -## ....## -# ###### -# $ $ @# -### $ $ # - ### # - ###### - -; 76 - - ##### -## # -# ##### -# #.# # -#@ #.# $ # -# #.# ## -# # # -## ##$$# - ## # - # #### - #### - -; 77 - -########## -# @ .... # -# ####$## -## # $ $ # - # $ # - # ###### - ##### - -; 78 - - ####### -## ## -# $ $ # -# $ $ $ # -## ### #### - #@ .....# - ## ### - ####### - -; 79 - - ######### - # # # -## $#$# # -# .$.@ # -# .# # -########## - -; 80 - -#### -# ####### -# . ## .# -# $# .# -## ## # .# - # # # - #### # # - # @$ ### - # $$ # - # # - ###### - -; 81 - - ##### - # # - # . # -## * # -# *## -# @## -## $ # - # # - ##### - -; 82 - -##### -# ### -# . ## -##*#$ # -# .# $ # -# @## ## -# # -####### - -; 83 - -###### -# ## -# $ $ ## -## $$ # - # # # - # ## ## - # . .# - # @. .# - # #### - #### - -; 84 - -######## -# ... # -# ### ## -# # $ # -## #@$ # - # # $ # - # ### ##### - # # - # ### # - ##### ##### - -; 85 - - #### - ####### # - # $ # - # $ $ # - # ######## -## # . # -# # # # -# @ . ## -## # # # - # . # - ####### - -; 86 - - #### - ### ## - ## $ # -## $ # # -# @#$$ # -# .. ### -# ..### -##### - -; 87 - - #### -###### # -# # -# ... .# -##$###### -# $ # -# $### -## $ # - ## @ # - ###### - -; 88 - - #### - # ### # - # # # - # # # # - # #$ #.# - # # # # # - # #$ #.# # - # # # # -####$ #.# # -# @ # # -# # ## # -######## - -; 89 - -########## -# ## # -# $ $@# # -#### # $ # - #.# ## - # #.# $# - # #. # - # #. # - ###### - -; 90 - - ######## - # @ # - # $ $ # -### ## ### -# $..$ # -# .. # -########## - -; 91 - -########### -# .## # -# $$@..$$ # -# ##. # -########### - -; 92 - - #### - # # ##### - # # # # - # ######.# # -#### $ . # -# $$# ###.# # -# # # # # -######### #@ ## - # # - #### - -; 93 - - ######### -## # ## -# # # -# $ # $ # -# *.* # -####.@.#### -# *.* # -# $ # $ # -# # # -## # ## - ######### - -; 94 - -######### -# @ # # -# $ $ # -##$### ## -# ... # -# # # -###### # - #### - -; 95 - -######## -#@ # -# .$$. # -# $..$ # -# $..$ # -# .$$. # -# # -######## - -; 96 - - ###### - # # - # # -##### # -# #.##### -# $@$ # -#####.# # - ## ## ## - # $.# - # ### - ##### - -; 97 - - #### - # ######## -#### $ $.....# -# $ ###### -#@### ### -# $ # -# $ # # -## # # - # # - ###### - -; 98 - -##### -# ## #### -# $ ### .# -# $ $ .# -## $#####.# #### -# $ # # .### # -# # # .# @ # -### # # # - #### ## ## - ####### - -; 99 - - ##### - # # -####### ####### # # -# # # # # -# @ #### # #### -# # ....## #### # -# ##### ## $$ $ $ # -###### # # - # ########## - #### - -; 100 - -####### -# @# # -#.$ # -#. # $## -#.$# # -#. # $ # -# # # -######## - -; 101 'Lockdown' - - ##### - # # - # # ####### - # * # # - ## ## # # - # #* # -### # # # ### -# *#$+ # -# # ## ## -# # * # -####### # # - # # - ##### - -; 102 - -########### -#....# # -# # $$ # -# @ ## # -# ##$ # -###### $ # - # # - ###### - -; 103 - - ##### - # . ## -### $ # -# . $#@# -# #$ . # -# $ ### -## . # - ##### - -; 104 - - ##### -##### # -# $ # -# $#$#@# -### # # - # ... # - ### ## - # # - #### - -; 105 - - #### #### -## ### ## -# # # # -# *. .* # -###$ $### - # @ # -###$ $### -# *. .* # -# # # # -## ### ## - #### #### - -; 106 - - ######## - # # - #@ $ # -## ###$ # -# .....### -# $ $ $ # -###### # # - # # - ##### - -; 107 - -######## -# # -# $*** # -# * * # -# * * # -# ***. # -# @# -######## - -; 108 - -#### ##### -# ### # ## -# # #$ $ # -#..# ##### # # -# @ # $ $ # -#..# ## -## ######### - ##### - -; 109 - - ####### -# # # -# # # # # - # @ $ # -### ### # -# ### # -# $ ##.# -## $ #.# - ## $ .# -# ## $#.# -## ## #.# -### # # -### ##### - -; 110 - - #### - # # - # $#### -###. . # -# $ # $ # -# . .### -####$ # - # @# - #### - -; 111 - -###### -# #### -# ...# -# ...# -###### # - # # # - # $$ ## - # @$ # - # $$ # - ## $# # - # # - ###### - -; 112 - - ##### -## #### -# $$$ # -# # $ # -# $## ## -### #. # - # # # - ##### ### - # # ## - # @....# - # # - # # # - ######## - -; 113 - - ##### - ## # -### # # -# . # -# ## ##### -# . . # ## -# # @ $ ### -#####. # $ # - #### $ # - ## $ ## - # ## - # # - #### - -; 114 - -###### -# ### -# # $ # -# $ @ # -## ## ##### -# #......# -# $ $ $ $ # -## ###### - ##### - -; 115 - - ##### -##### #### -# # # -# #..... # -## ## # ### - #$$@$$$ # - # ### - ####### - -; 116 - - ##### - ### # -####.....# -# @$$$$$ # -# # ## -##### # - ##### - -; 117 - - #### #### - # ### ## - # @ # -##..### # -# # # -#...#$ # # -# ## $$ $ # -# $ ### -#### ### - #### - -; 118 - - ##### -## ## -# $ ## -# $ $ ## -###$# . ## - # # . # - ## ##. # - # @ . ## - # # # - ######## - -; 119 - - ###### - # ## - ## ## # - # $$ # # - # @$ # # - # # # -#### # # -# ... ## -# ## -####### - -; 120 - - #### -####### # -# $ ## -# $##### # -# @# # # -## ##.. # -# # ..#### -# $ ### -# $### -# # -#### - -; 121 - - ###### - # . # -##$.# # -# * # -# ..### -##$ # ##### -## ## # # -# #### # # -# @ $ $ # -## # # - ########## - -; 122 - -##### -# ### -# #$ # -# $ # -# $ $ # -# $# # -# @### -## ######## -# ...# -# # -########..# - #### - -; 123 - -######## -# # -# $ $$ ######## -##### @##. . # - #$ # . # - # #. . ## - #$# ## # # - # # - # ### ## - # # #### - #### - -; 124 - -############## -# # # -# $@$$ # . ..# -## ## ### ## # - # # # # - # # # # # - # ######### # - # # - ############# - -; 125 - - ##### - # ## - # $ # -######## #@## -# . # $ $ # -# $# # -#...##### # -##### ##### - -; 126 - - ########### -##....... # -# $$$$$$$@ # -# # # # ## -# # # # -# ####### -##### - -; 127 - -## #### -#### #### - # $ $. # -## # .$ # -# ##.### -# $ . # -# @ # # -# ###### -#### - -; 128 - - ######### -### # # -# * $ . . # -# $ ## ## -####*# # - # @ ### - # ### - ##### - -; 129 - - ######### -### @ # # -# * $ *.. # -# $ # # -####*# ### - # ## - # ### - ##### - -; 130 - -##### ##### -# ####.. # -# $$$ # -# $# .. # -### @# ## # - # ## # - ########## - -; 131 - -##### -# # -# . # -#.@.### -##.# # -# $ # -# $ # -##$$ # - # ### - # # - #### - -; 132 - -#### -# @### -#.* ##### -#..#$$ $ # -## # - # # ## # - # ##### - ##### - -; 133 - - ####### - # . .### - # . . . # -### #### # -# @$ $ # -# $$ $ # -#### ### - ##### - -; 134 - - #### -######### # -# ## $ # -# $ ## # -### #. .# ## - # #. .#$## - # # # # - # @ $ # - # ####### - #### - -; 135 - -####### -# ##### -# $$#@##..# -# # # -# $ # # # -#### $ ..# - ######## - -; 136 - - ####### - # # -## ###$## -#.$ @ # -# .. #$ # -#.## $ # -# #### -###### - -; 137 - - #### - ## ### -#### # $ # -# #### $ $ # -# ..# #$ # -# # @ ### -## #..# ### - # ## # # - # # - ######## - -; 138 - - #### -### # -# ### -# # . .# -# @ ...#### -# # # # ## -# # $$ # -##### $ $ # - ##$ # ## - # # - ###### - -; 139 - - #### -## #### -# ...# -# ...# -# # ## -# #@ #### #### -##### $ ### # - # ##$ $ # - ### $$ # - # $ ## ### - # ###### - ###### - -; 140 - -######## ##### -# # ### # -# ## $ # -#.# @ ## $ ## -#.# # $ ## -#.# $ ## -#. ## ##### -## # - ###### - -; 141 - - ######## - # # . # - # .*.# - # # * # -####$##.## -# $ # -# $ ## $ # -# @# # -########## - -; 142 - - #### - # # - # #### -###$.$ # -# .@. # -# $.$### -#### # - # # - #### - -; 143 - -#### -# #### -# $ # -# .# # -# $# ## -# . # -#### # - # # - ### ### - # $ # -## #$# ## -# $ @ $ # -# ..#.. # -### ### - ##### - -; 144 - - #### - ### ##### - # $$ # # - # $ . .$$## - # .. #. $ # -### #** . # -# . **# ### -# $ .# .. # -##$$.@. $ # - # # $$ # - ##### ### - #### - -; 145 - - ##### - # @ # - ## ## -###.$$$.### -# $...$ # -# $.#.$ # -# $...$ # -###.$$$.### - ## ## - # # - ##### - -; 146 - - ####### -## . ## -# .$$$. # -# $. .$ # -#.$ @ $.# -# $. .$ # -# .$$$. # -## . ## - ####### - -; 147 - - ##### -######## # -#. . @#.# -# ### # -## $ # # - # $ ##### - # $# # - ## # # - # ## - ##### - -; 148 'from (Original 18)' - -########### -# . # # -# #. @ # -# #..# ####### -## ## $$ $ $ # - ## # - ############# - -; 149 'from (Boxxle 43)' - - #### -## ### -#@$ # -### $ # - # ###### - # $....# - # # #### - ## # # - # $# # - # # - # ### - #### - -; 150 'from (Original 47)' - - #### - ##### # - # $####### -## ## ..# ...# -# $ $$#$ @ # -# ### # -####### # #### - #### - -; 151 'from (Original 47)' - - #### - # # - ### # -## $ # -# # # -# #$$ ###### -# # # .# -# $ @ .# -### ####..# - #### #### - -; 152 - -###### #### -# # # -#.## #$## # -# # # # -#$ # ### # # -# # # # # -# # #### # # # -#. @ $ * . # -############### - -; 153 - -############# -#.# @# # # -#.#$$ # $ # -#.# # $# # -#.# $# # $## -#.# # $# # -#.# $# # $# -#.. # $ # -#.. # # # -############ - -; 154 'Take the long way home.' - - ############################ - # # - # ######################## # - # # # # - # # #################### # # - # # # # # # - # # # ################ # # # - # # # # # # # # - # # # # ############ # # # # - # # # # # # # # # - # # # # # ############ # # # - # # # # # # # # - # # # # ################ # # - # # # # # # -##$# # #################### # -#. @ # # -############################# - -; 155 'The Dungeon' - - ###### #### -#####*# ################# ## -# ### # -# ######## #### ## # -### #### # #### #### ## -#*# # .# # # # # # # -#*# # # # ## # ## ## # -### ### ### # ## # ## ## - # # #*# # # # # - # # ### ##### #### # # - ##### ##### ####### ###### - # # # #**# # -## # # #**# ####### ## # -# ######### # ##### ### -# # # $ #*# -# ######### ### @##### #*# -##### #### #### ###### diff --git a/model/ball.tres b/model/ball.tres new file mode 100644 index 0000000..40bc2da --- /dev/null +++ b/model/ball.tres @@ -0,0 +1,9 @@ +[gd_resource type="SphereMesh" load_steps=2 format=3 uid="uid://bxuewsvlsvexw"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_yae82"] +albedo_color = Color(0.997528, 0.415884, 0.114771, 1) + +[resource] +material = SubResource("StandardMaterial3D_yae82") +radius = 0.3 +height = 0.6 diff --git a/model/floor_ice.tres b/model/floor_ice.tres new file mode 100644 index 0000000..6745a5d --- /dev/null +++ b/model/floor_ice.tres @@ -0,0 +1,8 @@ +[gd_resource type="QuadMesh" load_steps=2 format=3 uid="uid://cs4ct3wp7xqeo"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_yh6g8"] +albedo_color = Color(0.607843, 1, 1, 1) + +[resource] +material = SubResource("StandardMaterial3D_yh6g8") +orientation = 1 diff --git a/model/goal.tres b/model/goal.tres new file mode 100644 index 0000000..41b289f --- /dev/null +++ b/model/goal.tres @@ -0,0 +1,10 @@ +[gd_resource type="CylinderMesh" load_steps=2 format=3 uid="uid://dip4i2st1vn1j"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_tr67r"] +albedo_color = Color(0.345098, 0.658824, 0.819608, 1) + +[resource] +material = SubResource("StandardMaterial3D_tr67r") +top_radius = 0.25 +bottom_radius = 0.3 +height = 0.1 diff --git a/player.tres b/model/player.tres similarity index 100% rename from player.tres rename to model/player.tres diff --git a/wall.tres b/model/wall.tres similarity index 100% rename from wall.tres rename to model/wall.tres diff --git a/piece.gd b/piece.gd index 16be161..94230c7 100644 --- a/piece.gd +++ b/piece.gd @@ -1,22 +1,26 @@ class_name Piece extends MeshInstance3D -const WALL = preload("res://wall.tres") -const GOAL = preload("res://goal.tres") -const BOX = preload("res://box.tres") -const PLAYER = preload("res://player.tres") +const WALL = preload("res://model/wall.tres") +const GOAL = preload("res://model/goal.tres") +const BALL = preload("res://model/ball.tres") +const PLAYER = preload("res://model/player.tres") +const FLOOR_ICE = preload("res://model/floor_ice.tres") enum Type { Wall, Goal, - Box, + Ball, Player, + FloorIce, } +# idea: SLOW MO KEY!!!!!!!!!!!!!!! ## squares per second -@export_range(0.1, 100) var anim_speed := 10.0 +@export_range(0.1, 50) var anim_speed := 10.0 +@export_range(0.1, 50) var anim_speed_slow := 2.0 -# logical position +## logical position @export var lpos: Vector2i: get: return lpos @@ -27,11 +31,46 @@ enum Type { target_pos = Vector3(lpos.x, position.y, lpos.y) anim_progress = 0 +## logical velocity +@export var lvel: Vector2i: + get: + return lvel + set(val): + lvel = val + display_vel = target_vel + start_vel = target_vel + target_vel = lvel + anim_progress = 0 + @export var type: Piece.Type @onready var start_pos := position @onready var target_pos := position +@onready var start_vel := Vector2(lvel) +@onready var target_vel := Vector2(lvel) +@onready var display_vel := Vector2(lvel) @onready var anim_progress := 1.0 +var speedometer: Label3D + +# TODO: this is *complex*, transfer momentum and stuff +func do_step(board: Board): + if lvel == Vector2i.ZERO: + return + if board.solid_at(lpos + lvel.clampi(-1, 1)): + lpos = lpos + lvel -= lvel.clampi(-1, 1) + return + lpos += lvel.clampi(-1, 1) + var on_ice := !!board.type_at(lpos, Piece.Type.FloorIce) + if not on_ice: + lvel -= lvel.clampi(-1, 1) + +func undo_step() -> Callable: + var old_pos := lpos + var old_vel := lvel + return func(): + lpos = old_pos + lvel = old_vel func do_move(move: Vector2i) -> Callable: return func(): @@ -42,6 +81,17 @@ func undo_move() -> Callable: return func(): lpos = old_pos +func do_push(move: Vector2i) -> Callable: + return func(): + lvel += move + anim_progress = 1 + +func undo_push() -> Callable: + var old_vel := lvel + return func(): + lvel = old_vel + anim_progress = 1 + static func make(lpos: Vector2i, type: Piece.Type, mesh: Mesh) -> Piece: var piece := Piece.new() piece.lpos = lpos @@ -55,16 +105,42 @@ static func wall(lpos: Vector2i) -> Piece: static func goal(lpos: Vector2i) -> Piece: return make(lpos, Piece.Type.Goal, GOAL) -static func box(lpos: Vector2i) -> Piece: - return make(lpos, Piece.Type.Box, BOX) +static func ball(lpos: Vector2i) -> Piece: + return make(lpos, Piece.Type.Ball, BALL) static func player(lpos: Vector2i) -> Piece: return make(lpos, Piece.Type.Player, PLAYER) +static func floor_ice(lpos: Vector2i) -> Piece: + return make(lpos, Piece.Type.FloorIce, FLOOR_ICE) + func _ready() -> void: lpos = lpos + lvel = Vector2i.ZERO anim_progress = 1 + speedometer = Label3D.new() + speedometer.billboard = BaseMaterial3D.BILLBOARD_ENABLED + speedometer.text = "0" + speedometer.no_depth_test = true + speedometer.font_size = 64 + add_child(speedometer) + +func format_vel(vel: Vector2) -> String: + if vel.is_zero_approx(): + return "" + else: + return "%d,%d" % [vel.x,vel.y] + #if is_zero_approx(vel.x) or is_zero_approx(vel.y): + #if is_equal_approx(round(abs(vel.x)), abs(vel.x)) or is_equal_approx(round(abs(vel.y)), abs(vel.y)): + #return "%.1d" % vel.length() + #else: + #return "%.1f" % vel.length() + #else: + #return "%d,%d" % [vel.x,vel.y] func _process(delta: float) -> void: - anim_progress = min(1, anim_progress + anim_speed*delta) + var speed := anim_speed_slow if Input.is_action_pressed("slowmo") else anim_speed + anim_progress = min(1, anim_progress + speed*delta) position = start_pos.lerp(target_pos, anim_progress) + display_vel = start_vel.lerp(target_vel, anim_progress) + speedometer.text = format_vel(display_vel) diff --git a/project.godot b/project.godot index ba28499..157adb9 100644 --- a/project.godot +++ b/project.godot @@ -57,6 +57,7 @@ undo={ , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194308,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":true,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"key_label":0,"unicode":113,"location":0,"echo":false,"script":null) ] } restart={ @@ -75,6 +76,18 @@ redo={ , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":85,"key_label":0,"unicode":85,"location":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":90,"location":0,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":80,"key_label":0,"unicode":112,"location":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null) +] +} +wait={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":46,"key_label":0,"unicode":46,"location":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null) +] +} +slowmo={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":77,"key_label":0,"unicode":109,"location":0,"echo":false,"script":null) ] } diff --git a/redo.png b/ui/redo.png similarity index 100% rename from redo.png rename to ui/redo.png diff --git a/redo.png.import b/ui/redo.png.import similarity index 70% rename from redo.png.import rename to ui/redo.png.import index 5e0571b..14da20a 100644 --- a/redo.png.import +++ b/ui/redo.png.import @@ -2,16 +2,16 @@ importer="texture" type="CompressedTexture2D" -uid="uid://cs7ofsoatkhpk" -path="res://.godot/imported/redo.png-ee35da30d5564f6349e0e057a85ac757.ctex" +uid="uid://dyj5el5iro1cb" +path="res://.godot/imported/redo.png-95e24a6c96a9add7c18b43f15a89bf3b.ctex" metadata={ "vram_texture": false } [deps] -source_file="res://redo.png" -dest_files=["res://.godot/imported/redo.png-ee35da30d5564f6349e0e057a85ac757.ctex"] +source_file="res://ui/redo.png" +dest_files=["res://.godot/imported/redo.png-95e24a6c96a9add7c18b43f15a89bf3b.ctex"] [params] diff --git a/restart.png b/ui/restart.png similarity index 100% rename from restart.png rename to ui/restart.png diff --git a/restart.png.import b/ui/restart.png.import similarity index 70% rename from restart.png.import rename to ui/restart.png.import index 6a8d4b4..2dc0791 100644 --- a/restart.png.import +++ b/ui/restart.png.import @@ -2,16 +2,16 @@ importer="texture" type="CompressedTexture2D" -uid="uid://dkl0lf6wlidup" -path="res://.godot/imported/restart.png-26b7c787948cb57c7b611be1d72180b7.ctex" +uid="uid://cbb1q0usxd6ex" +path="res://.godot/imported/restart.png-65b435632e6da2e7f4f11ad8211d6d0c.ctex" metadata={ "vram_texture": false } [deps] -source_file="res://restart.png" -dest_files=["res://.godot/imported/restart.png-26b7c787948cb57c7b611be1d72180b7.ctex"] +source_file="res://ui/restart.png" +dest_files=["res://.godot/imported/restart.png-65b435632e6da2e7f4f11ad8211d6d0c.ctex"] [params] diff --git a/undo.png b/ui/undo.png similarity index 100% rename from undo.png rename to ui/undo.png diff --git a/undo.png.import b/ui/undo.png.import similarity index 70% rename from undo.png.import rename to ui/undo.png.import index 5f1d43d..a8347e6 100644 --- a/undo.png.import +++ b/ui/undo.png.import @@ -2,16 +2,16 @@ importer="texture" type="CompressedTexture2D" -uid="uid://bl73lsxse1roj" -path="res://.godot/imported/undo.png-84d838c088789c9f3b743b68335cbb34.ctex" +uid="uid://crahyipmcudoy" +path="res://.godot/imported/undo.png-cbb1283b73560b70f3ede868fc4c9024.ctex" metadata={ "vram_texture": false } [deps] -source_file="res://undo.png" -dest_files=["res://.godot/imported/undo.png-84d838c088789c9f3b743b68335cbb34.ctex"] +source_file="res://ui/undo.png" +dest_files=["res://.godot/imported/undo.png-cbb1283b73560b70f3ede868fc4c9024.ctex"] [params]