its alive
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | Block.gd | 14 | ||||
| -rw-r--r-- | Block.tscn | 28 | ||||
| -rw-r--r-- | Constants.gd | 47 | ||||
| -rw-r--r-- | Constants.tscn | 9 | ||||
| -rw-r--r-- | Grid.gd | 102 | ||||
| -rw-r--r-- | LabelTheme.tres | 6 | ||||
| -rw-r--r-- | Logic.gd | 143 | ||||
| -rw-r--r-- | SwipeHandler.gd | 38 | ||||
| -rw-r--r-- | UI.tscn | 3 | ||||
| -rw-r--r-- | Verdana.tres | 7 | ||||
| -rw-r--r-- | World.tscn | 18 | ||||
| -rw-r--r-- | project.godot | 46 | ||||
| -rw-r--r-- | verdana-bold.ttf | bin | 0 -> 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 ) ] @@ -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) + + @@ -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 Binary files differnew file mode 100644 index 0000000..e54bccd --- /dev/null +++ b/verdana-bold.ttf |