its alive
bendn 2022-04-22
commit e0b4ef2
-rw-r--r--.gitignore2
-rw-r--r--Block.gd14
-rw-r--r--Block.tscn28
-rw-r--r--Constants.gd47
-rw-r--r--Constants.tscn9
-rw-r--r--Grid.gd102
-rw-r--r--LabelTheme.tres6
-rw-r--r--Logic.gd143
-rw-r--r--SwipeHandler.gd38
-rw-r--r--UI.tscn3
-rw-r--r--Verdana.tres7
-rw-r--r--World.tscn18
-rw-r--r--project.godot46
-rw-r--r--verdana-bold.ttfbin0 -> 208456 bytes
14 files changed, 463 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..68c3732
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.log
+.import/
diff --git a/Block.gd b/Block.gd
new file mode 100644
index 0000000..8101e48
--- /dev/null
+++ b/Block.gd
@@ -0,0 +1,14 @@
+extends Node2D
+var bg
+var label: Label
+
+
+func configure(text: String, background: Color, text_color: Color = Color.white):
+ if !bg:
+ bg = $ColorRect
+ if !label:
+ label = $Label
+ bg.color = background
+ label.text = text
+ if text_color != Color.white:
+ label.add_color_override("font_color", text_color)
diff --git a/Block.tscn b/Block.tscn
new file mode 100644
index 0000000..c5aa4d8
--- /dev/null
+++ b/Block.tscn
@@ -0,0 +1,28 @@
+[gd_scene load_steps=3 format=2]
+
+[ext_resource path="res://Block.gd" type="Script" id=1]
+[ext_resource path="res://LabelTheme.tres" type="Theme" id=2]
+
+[node name="Block" type="Node2D"]
+script = ExtResource( 1 )
+
+[node name="ColorRect" type="ColorRect" parent="."]
+anchor_left = 0.5
+anchor_top = 0.5
+anchor_right = 0.5
+anchor_bottom = 0.5
+margin_right = 30.0
+margin_bottom = 30.0
+color = Color( 0.823529, 0.517647, 0.517647, 1 )
+
+[node name="Label" type="Label" parent="."]
+anchor_left = 0.5
+anchor_top = 0.5
+anchor_right = 0.5
+anchor_bottom = 0.5
+margin_right = 30.0
+margin_bottom = 30.0
+theme = ExtResource( 2 )
+text = "2"
+align = 1
+valign = 1
diff --git a/Constants.gd b/Constants.gd
new file mode 100644
index 0000000..dc18293
--- /dev/null
+++ b/Constants.gd
@@ -0,0 +1,47 @@
+extends Node
+
+export(Color) var LOSE_COLOR_TEXT
+const SIZE = 400
+const GRID_LEN = 4
+const BLOCK_SIZE = 32
+
+export(Color) var BACKGROUND_COLOR_GAME = "#92877d"
+export(Color) var BACKGROUND_COLOR_CELL_EMPTY = "#9e948a"
+
+export(Array, Color) var BACKGROUND_COLOR_ARRAY: Array # go up to 65536
+export(Array, Color) var CELL_COLOR_ARRAY: Array # go up to 65536
+
+const cells = {
+ 2: 1,
+ 4: 2,
+ 8: 3,
+ 16: 4,
+ 32: 5,
+ 64: 6,
+ 128: 7,
+ 256: 8,
+ 512: 9,
+ 1024: 10,
+ 2048: 11,
+ 4096: 12,
+ 8192: 13,
+ 16384: 14,
+ 32768: 15,
+ 65536: 16
+}
+
+
+func _ready():
+ assert(
+ BACKGROUND_COLOR_ARRAY.size() == CELL_COLOR_ARRAY.size(),
+ "BACKGROUND_COLOR_ARRAY and CELL_COLOR_ARRAY must have the same length"
+ )
+ assert(
+ BACKGROUND_COLOR_ARRAY.size() == cells.size(),
+ (
+ "there is not enough entrys in BACKGROUND_COLOR_ARRAY and CELL_COLOR_ARRAY to reach %s"
+ % cells.size()
+ )
+ )
+ print(cells.size())
+ print(BACKGROUND_COLOR_ARRAY.size())
diff --git a/Constants.tscn b/Constants.tscn
new file mode 100644
index 0000000..68397ab
--- /dev/null
+++ b/Constants.tscn
@@ -0,0 +1,9 @@
+[gd_scene load_steps=2 format=2]
+
+[ext_resource path="res://Constants.gd" type="Script" id=1]
+
+[node name="Constants" type="Node2D"]
+script = ExtResource( 1 )
+LOSE_COLOR_TEXT = Color( 0.192157, 0.192157, 0.192157, 1 )
+BACKGROUND_COLOR_ARRAY = [ Color( 0.988235, 0.960784, 0.960784, 1 ), Color( 0.909804, 0.882353, 0.803922, 1 ), Color( 0.905882, 0.611765, 0.415686, 1 ), Color( 0.878431, 0.568627, 0.341176, 1 ), Color( 0.870588, 0.462745, 0.317647, 1 ), Color( 0.776471, 0.352941, 0.352941, 1 ), Color( 0.87451, 0.741176, 0.384314, 1 ), Color( 0.976471, 0.72549, 0.294118, 1 ), Color( 0.92549, 0.729412, 0.2, 1 ), Color( 0.894118, 0.74902, 0.176471, 1 ), Color( 0.862745, 0.792157, 0.2, 1 ), Color( 0.976471, 0.933333, 0.933333, 1 ), Color( 0.898039, 0.8, 0.498039, 1 ), Color( 0.929412, 0.701961, 0.380392, 1 ), Color( 0.901961, 0.564706, 0.231373, 1 ), Color( 0.878431, 0.619608, 0.619608, 1 ) ]
+CELL_COLOR_ARRAY = [ Color( 0.466667, 0.431373, 0.396078, 1 ), Color( 0.466667, 0.431373, 0.396078, 1 ), Color( 0.976471, 0.964706, 0.94902, 1 ), Color( 0.976471, 0.964706, 0.94902, 1 ), Color( 0.976471, 0.964706, 0.94902, 1 ), Color( 0.976471, 0.964706, 0.94902, 1 ), Color( 0.976471, 0.964706, 0.94902, 1 ), Color( 0.976471, 0.964706, 0.94902, 1 ), Color( 0.976471, 0.964706, 0.94902, 1 ), Color( 0.976471, 0.964706, 0.94902, 1 ), Color( 0.976471, 0.964706, 0.94902, 1 ), Color( 0.466667, 0.431373, 0.396078, 1 ), Color( 0.976471, 0.964706, 0.94902, 1 ), Color( 0.466667, 0.431373, 0.396078, 1 ), Color( 0.466667, 0.431373, 0.396078, 1 ), Color( 0.976471, 0.964706, 0.94902, 1 ) ]
diff --git a/Grid.gd b/Grid.gd
new file mode 100644
index 0000000..930d09b
--- /dev/null
+++ b/Grid.gd
@@ -0,0 +1,102 @@
+extends Node2D
+
+var matrix
+var grid_cells
+var history_matrixs
+var won = false
+var lost = false
+
+
+func _ready():
+ randomize()
+ grid_cells = []
+ init_grid()
+ matrix = Logic.new_game(Constants.GRID_LEN)
+ history_matrixs = []
+ update_grid_cells()
+
+
+const Block = preload("res://Block.tscn")
+
+
+func init_grid():
+ for i in range(Constants.GRID_LEN):
+ var grid_row = []
+ for j in range(Constants.GRID_LEN):
+ var block = Block.instance()
+ add_child(block)
+ block.global_position += Vector2(
+ i * Constants.BLOCK_SIZE + 10, j * Constants.BLOCK_SIZE + 10
+ )
+ grid_row.append(block)
+ grid_cells.append(grid_row)
+
+
+func update_grid_cells():
+ for i in range(Constants.GRID_LEN):
+ for j in range(Constants.GRID_LEN):
+ var new_number = matrix[i][j]
+ if new_number == 0:
+ grid_cells[i][j].configure("", Constants.BACKGROUND_COLOR_CELL_EMPTY)
+ else:
+ grid_cells[i][j].configure(
+ str(new_number),
+ Constants.BACKGROUND_COLOR_ARRAY[Constants.cells[new_number]],
+ Constants.CELL_COLOR_ARRAY[Constants.cells[new_number]]
+ )
+
+
+func _input(event):
+ var input = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
+ if event.is_action("quit"):
+ get_tree().quit()
+ # elif event.is_action("undo") and history_matrixs.size() > 1: # dont want the undo feature anymore
+ # self.matrix = history_matrixs.pop_back()
+ # update_grid_cells()
+ # print('back on step total step:' + str(history_matrixs.size()))
+ elif input != Vector2.ZERO:
+ handle_input(input)
+
+
+func handle_input(input):
+ if lost:
+ return
+ var tmp
+ match input:
+ Vector2.UP:
+ tmp = Logic.up(matrix)
+ Vector2.DOWN:
+ tmp = Logic.down(matrix)
+ Vector2.LEFT:
+ tmp = Logic.left(matrix)
+ Vector2.RIGHT:
+ tmp = Logic.right(matrix)
+ _:
+ return
+ matrix = tmp[0]
+ if tmp[1]:
+ matrix = Logic.add_two(matrix)
+ # history_matrixs.append(matrix)
+ update_grid_cells()
+
+ var state = Logic.game_state(matrix)
+ if state == "win" and not won:
+ won = true
+ grid_cells[0][0].configure(
+ "You", Constants.BACKGROUND_COLOR_CELL_EMPTY, Constants.LOSE_COLOR_TEXT
+ )
+ grid_cells[1][0].configure(
+ "won", Constants.BACKGROUND_COLOR_CELL_EMPTY, Constants.LOSE_COLOR_TEXT
+ )
+ elif state == "lose":
+ lost = true
+ grid_cells[0][0].configure(
+ "You", Constants.BACKGROUND_COLOR_CELL_EMPTY, Constants.LOSE_COLOR_TEXT
+ )
+ grid_cells[1][0].configure(
+ "lost", Constants.BACKGROUND_COLOR_CELL_EMPTY, Constants.LOSE_COLOR_TEXT
+ ) # lmao L
+
+
+func _on_SwipeHandler_swiped(swipe):
+ handle_input(swipe)
diff --git a/LabelTheme.tres b/LabelTheme.tres
new file mode 100644
index 0000000..e730cc0
--- /dev/null
+++ b/LabelTheme.tres
@@ -0,0 +1,6 @@
+[gd_resource type="Theme" load_steps=2 format=2]
+
+[ext_resource path="res://Verdana.tres" type="DynamicFont" id=1]
+
+[resource]
+Label/fonts/font = ExtResource( 1 )
diff --git a/Logic.gd b/Logic.gd
new file mode 100644
index 0000000..176752e
--- /dev/null
+++ b/Logic.gd
@@ -0,0 +1,143 @@
+# logic
+extends Node
+
+var done
+
+
+func new_game(n):
+ var matrix = []
+ for i in range(n):
+ matrix.append([])
+ for _j in range(n):
+ matrix[i].append(0)
+ matrix = add_two(matrix)
+ matrix = add_two(matrix)
+ return matrix
+
+
+func add_two(mat):
+ var a = round(rand_range(0, mat.size() - 1))
+ var b = round(rand_range(0, mat.size() - 1))
+ while mat[a][b] != 0:
+ a = round(rand_range(0, mat.size() - 1))
+ b = round(rand_range(0, mat.size() - 1))
+ mat[a][b] = 4 if rand_range(0, 1) > .9 else 2
+ return mat
+
+
+func game_state(mat):
+ # check for win cell
+ var zero = false
+ for i in range(mat.size()):
+ for j in range(mat[0].size()):
+ if mat[i][j] == 2048:
+ return "win"
+ elif zero == false and mat[i][j] == 0:
+ zero = true
+ if zero:
+ return "not over"
+
+ # check for same cells that touch each other
+ for i in range(len(mat) - 1):
+ # intentionally reduced to check the row on the right and below
+ # more elegant to use exceptions but most likely this will be their solution
+ for j in range(len(mat[0]) - 1):
+ if mat[i][j] == mat[i + 1][j] or mat[i][j + 1] == mat[i][j]:
+ return "not over"
+ for k in range(len(mat) - 1): # to check the left/right entries on the last row
+ if mat[len(mat) - 1][k] == mat[len(mat) - 1][k + 1]:
+ return "not over"
+ for j in range(len(mat) - 1): # check up/down entries on last column
+ if mat[j][len(mat) - 1] == mat[j + 1][len(mat) - 1]:
+ return "not over"
+ return "lose"
+
+
+func reverse(mat):
+ var new = []
+ for i in range(mat.size()):
+ new.append([])
+ for j in range(mat[0].size()):
+ new[i].append(mat[i][mat[0].size() - j - 1])
+ return new
+
+
+func transpose(mat):
+ var new = []
+ for i in range(mat[0].size()):
+ new.append([])
+ for j in range(mat.size()):
+ new[i].append(mat[j][i])
+ return new
+
+
+func cover_up(mat, no_done = false):
+ var new = []
+ for _j in range(Constants.GRID_LEN):
+ var partial_new = []
+ for _i in range(Constants.GRID_LEN):
+ partial_new.append(0)
+ new.append(partial_new)
+ if !no_done:
+ done = false
+ for i in range(Constants.GRID_LEN):
+ var count = 0
+ for j in range(Constants.GRID_LEN):
+ if mat[i][j] != 0:
+ new[i][count] = mat[i][j]
+ if !no_done and j != count:
+ done = true
+ count += 1
+ return new
+
+
+func merge(mat):
+ for i in range(Constants.GRID_LEN):
+ for j in range(Constants.GRID_LEN - 1):
+ if mat[i][j] == mat[i][j + 1] and mat[i][j] != 0:
+ mat[i][j] *= 2
+ mat[i][j + 1] = 0
+ done = true
+ return mat
+
+
+func left(game):
+ print("<")
+ # return matrix after shifting left
+ game = transpose(game)
+ game = cover_up(game)
+ game = merge(game)
+ game = cover_up(game, true)
+ game = transpose(game)
+ return [game, done]
+
+
+func right(game):
+ print(">")
+ # return matrix after shifting right
+ game = reverse(transpose(game))
+ game = cover_up(game)
+ game = merge(game)
+ game = cover_up(game, true)
+ game = transpose(reverse(game))
+ return [game, done]
+
+
+func up(game):
+ print("^")
+ # return matrix after shifting up
+ game = cover_up(game)
+ game = merge(game)
+ game = cover_up(game, true)
+ return [game, done]
+
+
+func down(game):
+ print("v")
+ # return matrix after shifting down
+ game = reverse(game)
+ game = cover_up(game)
+ game = merge(game)
+ game = cover_up(game, true)
+ game = reverse(game)
+ return [game, done]
diff --git a/SwipeHandler.gd b/SwipeHandler.gd
new file mode 100644
index 0000000..362ebf7
--- /dev/null
+++ b/SwipeHandler.gd
@@ -0,0 +1,38 @@
+extends Node2D
+
+signal swiped(direction)
+
+var first_touch_position := Vector2.ZERO
+var touch_release_position := Vector2.ZERO
+var swiping := false
+
+export var swipe_limit : float
+export var touch_y_limit : int
+
+func _process(_delta):
+ if Input.is_action_just_pressed("touch"):
+ if ( get_global_mouse_position().y > touch_y_limit):
+ first_touch_position = get_global_mouse_position()
+ swiping = true
+ if Input.is_action_just_released("touch") and swiping :
+ touch_release_position = get_global_mouse_position()
+ calculate_direction()
+ swiping = false
+
+func calculate_direction():
+ var swipe_vector = touch_release_position - first_touch_position
+ if swipe_vector.length() > swipe_limit:
+ var temp = rad2deg(swipe_vector.angle()) + 180 # right = 0
+ first_touch_position = Vector2.ZERO
+ touch_release_position = Vector2.ZERO
+
+ if temp > 45 and temp <= 135:
+ emit_signal("swiped", Vector2.UP)
+ elif temp > 135 and temp <= 225:
+ emit_signal("swiped", Vector2.RIGHT)
+ elif temp > 225 and temp <= 300:
+ emit_signal("swiped", Vector2.DOWN)
+ else:
+ emit_signal("swiped", Vector2.LEFT)
+
+
diff --git a/UI.tscn b/UI.tscn
new file mode 100644
index 0000000..b174e02
--- /dev/null
+++ b/UI.tscn
@@ -0,0 +1,3 @@
+[gd_scene format=2]
+
+[node name="UI" type="CanvasLayer"]
diff --git a/Verdana.tres b/Verdana.tres
new file mode 100644
index 0000000..ea78c0d
--- /dev/null
+++ b/Verdana.tres
@@ -0,0 +1,7 @@
+[gd_resource type="DynamicFont" load_steps=2 format=2]
+
+[ext_resource path="res://verdana-bold.ttf" type="DynamicFontData" id=1]
+
+[resource]
+size = 10
+font_data = ExtResource( 1 )
diff --git a/World.tscn b/World.tscn
new file mode 100644
index 0000000..81a497f
--- /dev/null
+++ b/World.tscn
@@ -0,0 +1,18 @@
+[gd_scene load_steps=4 format=2]
+
+[ext_resource path="res://Grid.gd" type="Script" id=1]
+[ext_resource path="res://SwipeHandler.gd" type="Script" id=2]
+[ext_resource path="res://UI.tscn" type="PackedScene" id=3]
+
+[node name="World" type="Node2D"]
+
+[node name="Grid" type="Node2D" parent="."]
+script = ExtResource( 1 )
+
+[node name="SwipeHandler" type="Node2D" parent="."]
+script = ExtResource( 2 )
+swipe_limit = 15.0
+
+[node name="UI" parent="." instance=ExtResource( 3 )]
+
+[connection signal="swiped" from="SwipeHandler" to="Grid" method="_on_SwipeHandler_swiped"]
diff --git a/project.godot b/project.godot
new file mode 100644
index 0000000..1b6028a
--- /dev/null
+++ b/project.godot
@@ -0,0 +1,46 @@
+; Engine configuration file.
+; It's best edited using the editor UI and not directly,
+; since the parameters that go here are not all obvious.
+;
+; Format:
+; [section] ; section goes between []
+; param=value ; assign values to parameters
+
+config_version=4
+
+[application]
+
+run/main_scene="res://World.tscn"
+
+[autoload]
+
+Constants="*res://Constants.tscn"
+Logic="*res://Logic.gd"
+
+[display]
+
+window/size/width=148
+window/size/height=148
+window/size/test_width=720
+window/size/test_height=720
+window/stretch/mode="2d"
+window/stretch/aspect="keep"
+
+[input]
+
+quit={
+"deadzone": 0.5,
+"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777217,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
+ ]
+}
+undo={
+"deadzone": 0.5,
+"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":true,"meta":false,"command":true,"pressed":false,"scancode":90,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":90,"physical_scancode":0,"unicode":0,"echo":false,"script":null)
+ ]
+}
+touch={
+"deadzone": 0.5,
+"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null)
+ ]
+}
diff --git a/verdana-bold.ttf b/verdana-bold.ttf
new file mode 100644
index 0000000..e54bccd
--- /dev/null
+++ b/verdana-bold.ttf
Binary files differ