bad mechanical poc
This commit is contained in:
parent
082100ec2f
commit
046690353c
20 changed files with 276 additions and 1897 deletions
26
board.gd
26
board.gd
|
|
@ -18,11 +18,12 @@ func bottom_right_aabb() -> AABB:
|
||||||
|
|
||||||
# todo: Array[Piece]
|
# todo: Array[Piece]
|
||||||
func pieces() -> Array:
|
func pieces() -> Array:
|
||||||
|
# todo: sort for consistency
|
||||||
return get_children()
|
return get_children()
|
||||||
|
|
||||||
func pieces_at(pos: Vector2i) -> Array[Piece]:
|
func pieces_at(pos: Vector2i) -> Array[Piece]:
|
||||||
var out: Array[Piece] = []
|
var out: Array[Piece] = []
|
||||||
for piece in get_children():
|
for piece in pieces():
|
||||||
if piece.lpos == pos:
|
if piece.lpos == pos:
|
||||||
out.push_back(piece)
|
out.push_back(piece)
|
||||||
return out
|
return out
|
||||||
|
|
@ -36,8 +37,12 @@ func find_piece_at(pos: Vector2i, filter: Callable) -> Piece:
|
||||||
func any_at(pos: Vector2i, filter: Callable) -> bool:
|
func any_at(pos: Vector2i, filter: Callable) -> bool:
|
||||||
return pieces_at(pos).any(filter)
|
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:
|
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:
|
func passable_at(pos: Vector2i) -> bool:
|
||||||
return not solid_at(pos)
|
return not solid_at(pos)
|
||||||
|
|
@ -71,9 +76,22 @@ static func from_string(src: String) -> Board:
|
||||||
var pos := Vector2i(x, y)
|
var pos := Vector2i(x, y)
|
||||||
match c:
|
match c:
|
||||||
".": board.add_piece(Piece.goal(pos))
|
".": 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_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.player(pos))
|
||||||
"#": board.add_piece(Piece.wall(pos))
|
"#": board.add_piece(Piece.wall(pos))
|
||||||
|
"_": board.add_piece(Piece.floor_ice(pos))
|
||||||
return board
|
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()
|
||||||
|
|
|
||||||
10
box.tres
10
box.tres
|
|
@ -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")
|
|
||||||
22
goal.tres
22
goal.tres
|
|
@ -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
|
|
||||||
43
levels.txt
Normal file
43
levels.txt
Normal file
|
|
@ -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.#
|
||||||
|
####
|
||||||
73
main.gd
73
main.gd
|
|
@ -1,12 +1,19 @@
|
||||||
extends Node3D
|
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
|
@onready var camera: Camera3D = $Camera
|
||||||
|
|
||||||
var hist := UndoRedo.new()
|
var hist := UndoRedo.new()
|
||||||
@onready var board: Board = $Board
|
@onready var board: Board = $Board
|
||||||
var player: Piece
|
var player: Piece
|
||||||
var level_num := -1
|
var level_num := 0
|
||||||
var levels_src: PackedStringArray
|
var levels_src: PackedStringArray
|
||||||
|
var time := 0
|
||||||
|
var advancing := false
|
||||||
|
|
||||||
@onready var sound: AudioStreamPlayer = $Sound
|
@onready var sound: AudioStreamPlayer = $Sound
|
||||||
@onready var sounds_hit := audio_stream_randomizer_from_dir("res://sfx/hit")
|
@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")
|
@onready var sounds_redo := audio_stream_randomizer_from_dir("res://sfx/redo")
|
||||||
|
|
||||||
func _ready() -> void:
|
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")
|
levels_src = file.get_as_text().split("\n\n")
|
||||||
advance_level()
|
advance_level()
|
||||||
|
|
||||||
|
|
@ -22,6 +29,7 @@ func _process(delta: float) -> void:
|
||||||
$UndoButton.disabled = not hist.has_undo()
|
$UndoButton.disabled = not hist.has_undo()
|
||||||
$RedoButton.disabled = not hist.has_redo()
|
$RedoButton.disabled = not hist.has_redo()
|
||||||
$RestartButton.disabled = not hist.has_undo()
|
$RestartButton.disabled = not hist.has_undo()
|
||||||
|
$Clock.text = "T = %d" % time
|
||||||
if $TopLeft.is_on_screen() and $BottomRight.is_on_screen():
|
if $TopLeft.is_on_screen() and $BottomRight.is_on_screen():
|
||||||
return
|
return
|
||||||
camera.position.y += 10*delta
|
camera.position.y += 10*delta
|
||||||
|
|
@ -41,6 +49,8 @@ func _input(event: InputEvent) -> void:
|
||||||
redo()
|
redo()
|
||||||
elif event.is_action_pressed("restart", true, true):
|
elif event.is_action_pressed("restart", true, true):
|
||||||
restart()
|
restart()
|
||||||
|
elif event.is_action_pressed("wait", true, true):
|
||||||
|
step(Vector2i.ZERO)
|
||||||
|
|
||||||
func undo():
|
func undo():
|
||||||
if hist.undo():
|
if hist.undo():
|
||||||
|
|
@ -60,47 +70,82 @@ func restart():
|
||||||
# scratch that i like that, don't clear the history
|
# scratch that i like that, don't clear the history
|
||||||
# you can like replay your steps up to a point
|
# 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):
|
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 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):
|
if board.passable_at(pos + move):
|
||||||
hist.create_action("move")
|
hist.create_action("move")
|
||||||
hist.add_do_method(player.do_move(move))
|
hist.add_do_method(player.do_move(move))
|
||||||
hist.add_undo_method(player.undo_move())
|
hist.add_undo_method(player.undo_move())
|
||||||
hist.commit_action()
|
hist.commit_action()
|
||||||
elif box != null and board.passable_at(pos + move * 2):
|
elif ball != null:
|
||||||
hist.create_action("push")
|
hist.create_action("push")
|
||||||
hist.add_do_method(player.do_move(move))
|
hist.add_do_method(ball.do_push(move))
|
||||||
hist.add_do_method(box.do_move(move))
|
hist.add_do_method(func():
|
||||||
hist.add_undo_method(player.undo_move())
|
player.lpos = pos + move
|
||||||
hist.add_undo_method(box.undo_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()
|
hist.commit_action()
|
||||||
else:
|
else:
|
||||||
sound.stream = sounds_hit
|
sound.stream = sounds_hit
|
||||||
sound.play()
|
sound.play()
|
||||||
|
|
||||||
if won() or Input.is_action_pressed("restart"):
|
|
||||||
advance_level()
|
|
||||||
|
|
||||||
func won() -> bool:
|
func won() -> bool:
|
||||||
for piece in board.pieces():
|
for piece in board.pieces():
|
||||||
if piece.type == Piece.Type.Goal:
|
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:
|
if !covered:
|
||||||
return false
|
return false
|
||||||
return true
|
return true
|
||||||
|
|
||||||
func advance_level():
|
func advance_level():
|
||||||
hist.clear_history()
|
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
|
level_num += 1
|
||||||
if level_num >= levels_src.size():
|
if level_num >= levels_src.size():
|
||||||
print("you win")
|
print("you win")
|
||||||
return
|
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
|
level_num += 1
|
||||||
|
print(levels_src[level_num])
|
||||||
board.queue_free()
|
board.queue_free()
|
||||||
board = Board.from_string(levels_src[level_num])
|
board = Board.from_string(levels_src[level_num])
|
||||||
var wall_count := 0
|
|
||||||
for piece in board.pieces():
|
for piece in board.pieces():
|
||||||
if piece.type == Piece.Type.Player:
|
if piece.type == Piece.Type.Player:
|
||||||
player = piece
|
player = piece
|
||||||
|
|
|
||||||
17
main.tscn
17
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://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="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://crahyipmcudoy" path="res://ui/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://dyj5el5iro1cb" path="res://ui/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://cbb1q0usxd6ex" path="res://ui/restart.png" id="5_272bh"]
|
||||||
|
|
||||||
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_ig7tw"]
|
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_ig7tw"]
|
||||||
ground_bottom_color = Color(0.270778, 0.538085, 0.397052, 1)
|
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"]
|
[sub_resource type="Environment" id="Environment_ig7tw"]
|
||||||
background_mode = 2
|
background_mode = 2
|
||||||
sky = SubResource("Sky_0xm2m")
|
sky = SubResource("Sky_0xm2m")
|
||||||
|
ambient_light_color = Color(1, 1, 1, 1)
|
||||||
|
|
||||||
[node name="Main" type="Node3D"]
|
[node name="Main" type="Node3D"]
|
||||||
script = ExtResource("1_ig7tw")
|
script = ExtResource("1_ig7tw")
|
||||||
|
|
@ -67,6 +68,16 @@ icon = ExtResource("5_272bh")
|
||||||
flat = true
|
flat = true
|
||||||
expand_icon = 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="UndoButton" to="." method="undo"]
|
||||||
[connection signal="pressed" from="RedoButton" to="." method="redo"]
|
[connection signal="pressed" from="RedoButton" to="." method="redo"]
|
||||||
[connection signal="pressed" from="RestartButton" to="." method="restart"]
|
[connection signal="pressed" from="RestartButton" to="." method="restart"]
|
||||||
|
|
|
||||||
1822
microban-1.txt
1822
microban-1.txt
File diff suppressed because it is too large
Load diff
9
model/ball.tres
Normal file
9
model/ball.tres
Normal file
|
|
@ -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
|
||||||
8
model/floor_ice.tres
Normal file
8
model/floor_ice.tres
Normal file
|
|
@ -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
|
||||||
10
model/goal.tres
Normal file
10
model/goal.tres
Normal file
|
|
@ -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
|
||||||
96
piece.gd
96
piece.gd
|
|
@ -1,22 +1,26 @@
|
||||||
class_name Piece
|
class_name Piece
|
||||||
extends MeshInstance3D
|
extends MeshInstance3D
|
||||||
|
|
||||||
const WALL = preload("res://wall.tres")
|
const WALL = preload("res://model/wall.tres")
|
||||||
const GOAL = preload("res://goal.tres")
|
const GOAL = preload("res://model/goal.tres")
|
||||||
const BOX = preload("res://box.tres")
|
const BALL = preload("res://model/ball.tres")
|
||||||
const PLAYER = preload("res://player.tres")
|
const PLAYER = preload("res://model/player.tres")
|
||||||
|
const FLOOR_ICE = preload("res://model/floor_ice.tres")
|
||||||
|
|
||||||
enum Type {
|
enum Type {
|
||||||
Wall,
|
Wall,
|
||||||
Goal,
|
Goal,
|
||||||
Box,
|
Ball,
|
||||||
Player,
|
Player,
|
||||||
|
FloorIce,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# idea: SLOW MO KEY!!!!!!!!!!!!!!!
|
||||||
## squares per second
|
## 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:
|
@export var lpos: Vector2i:
|
||||||
get:
|
get:
|
||||||
return lpos
|
return lpos
|
||||||
|
|
@ -27,11 +31,46 @@ enum Type {
|
||||||
target_pos = Vector3(lpos.x, position.y, lpos.y)
|
target_pos = Vector3(lpos.x, position.y, lpos.y)
|
||||||
anim_progress = 0
|
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
|
@export var type: Piece.Type
|
||||||
|
|
||||||
@onready var start_pos := position
|
@onready var start_pos := position
|
||||||
@onready var target_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
|
@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:
|
func do_move(move: Vector2i) -> Callable:
|
||||||
return func():
|
return func():
|
||||||
|
|
@ -42,6 +81,17 @@ func undo_move() -> Callable:
|
||||||
return func():
|
return func():
|
||||||
lpos = old_pos
|
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:
|
static func make(lpos: Vector2i, type: Piece.Type, mesh: Mesh) -> Piece:
|
||||||
var piece := Piece.new()
|
var piece := Piece.new()
|
||||||
piece.lpos = lpos
|
piece.lpos = lpos
|
||||||
|
|
@ -55,16 +105,42 @@ static func wall(lpos: Vector2i) -> Piece:
|
||||||
static func goal(lpos: Vector2i) -> Piece:
|
static func goal(lpos: Vector2i) -> Piece:
|
||||||
return make(lpos, Piece.Type.Goal, GOAL)
|
return make(lpos, Piece.Type.Goal, GOAL)
|
||||||
|
|
||||||
static func box(lpos: Vector2i) -> Piece:
|
static func ball(lpos: Vector2i) -> Piece:
|
||||||
return make(lpos, Piece.Type.Box, BOX)
|
return make(lpos, Piece.Type.Ball, BALL)
|
||||||
|
|
||||||
static func player(lpos: Vector2i) -> Piece:
|
static func player(lpos: Vector2i) -> Piece:
|
||||||
return make(lpos, Piece.Type.Player, PLAYER)
|
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:
|
func _ready() -> void:
|
||||||
lpos = lpos
|
lpos = lpos
|
||||||
|
lvel = Vector2i.ZERO
|
||||||
anim_progress = 1
|
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:
|
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)
|
position = start_pos.lerp(target_pos, anim_progress)
|
||||||
|
display_vel = start_vel.lerp(target_vel, anim_progress)
|
||||||
|
speedometer.text = format_vel(display_vel)
|
||||||
|
|
|
||||||
|
|
@ -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":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":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":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={
|
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":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":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":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)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
|
@ -2,16 +2,16 @@
|
||||||
|
|
||||||
importer="texture"
|
importer="texture"
|
||||||
type="CompressedTexture2D"
|
type="CompressedTexture2D"
|
||||||
uid="uid://cs7ofsoatkhpk"
|
uid="uid://dyj5el5iro1cb"
|
||||||
path="res://.godot/imported/redo.png-ee35da30d5564f6349e0e057a85ac757.ctex"
|
path="res://.godot/imported/redo.png-95e24a6c96a9add7c18b43f15a89bf3b.ctex"
|
||||||
metadata={
|
metadata={
|
||||||
"vram_texture": false
|
"vram_texture": false
|
||||||
}
|
}
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
|
|
||||||
source_file="res://redo.png"
|
source_file="res://ui/redo.png"
|
||||||
dest_files=["res://.godot/imported/redo.png-ee35da30d5564f6349e0e057a85ac757.ctex"]
|
dest_files=["res://.godot/imported/redo.png-95e24a6c96a9add7c18b43f15a89bf3b.ctex"]
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
|
@ -2,16 +2,16 @@
|
||||||
|
|
||||||
importer="texture"
|
importer="texture"
|
||||||
type="CompressedTexture2D"
|
type="CompressedTexture2D"
|
||||||
uid="uid://dkl0lf6wlidup"
|
uid="uid://cbb1q0usxd6ex"
|
||||||
path="res://.godot/imported/restart.png-26b7c787948cb57c7b611be1d72180b7.ctex"
|
path="res://.godot/imported/restart.png-65b435632e6da2e7f4f11ad8211d6d0c.ctex"
|
||||||
metadata={
|
metadata={
|
||||||
"vram_texture": false
|
"vram_texture": false
|
||||||
}
|
}
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
|
|
||||||
source_file="res://restart.png"
|
source_file="res://ui/restart.png"
|
||||||
dest_files=["res://.godot/imported/restart.png-26b7c787948cb57c7b611be1d72180b7.ctex"]
|
dest_files=["res://.godot/imported/restart.png-65b435632e6da2e7f4f11ad8211d6d0c.ctex"]
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
|
@ -2,16 +2,16 @@
|
||||||
|
|
||||||
importer="texture"
|
importer="texture"
|
||||||
type="CompressedTexture2D"
|
type="CompressedTexture2D"
|
||||||
uid="uid://bl73lsxse1roj"
|
uid="uid://crahyipmcudoy"
|
||||||
path="res://.godot/imported/undo.png-84d838c088789c9f3b743b68335cbb34.ctex"
|
path="res://.godot/imported/undo.png-cbb1283b73560b70f3ede868fc4c9024.ctex"
|
||||||
metadata={
|
metadata={
|
||||||
"vram_texture": false
|
"vram_texture": false
|
||||||
}
|
}
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
|
|
||||||
source_file="res://undo.png"
|
source_file="res://ui/undo.png"
|
||||||
dest_files=["res://.godot/imported/undo.png-84d838c088789c9f3b743b68335cbb34.ctex"]
|
dest_files=["res://.godot/imported/undo.png-cbb1283b73560b70f3ede868fc4c9024.ctex"]
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
|
|
||||||
Loading…
Reference in a new issue