tetris
tetris
bendn 2022-08-14
parent de2dcf1 · commit 523f9b5
-rw-r--r--.github/workflows/export.yml3
-rw-r--r--.gitmodules3
-rw-r--r--Logic.gd66
-rw-r--r--Main.tscn14
-rw-r--r--README.md38
-rw-r--r--Tetris.gd121
-rw-r--r--TetrisPiece.gd74
l---------addons/gdcli1
-rw-r--r--autoloads/CLI.gd11
-rw-r--r--project.godot39
-rw-r--r--submodules/.gdignore0
m---------submodules/gdcli0
12 files changed, 298 insertions, 72 deletions
diff --git a/.github/workflows/export.yml b/.github/workflows/export.yml
index d3a34af..80bc4ec 100644
--- a/.github/workflows/export.yml
+++ b/.github/workflows/export.yml
@@ -14,14 +14,13 @@ on:
env:
GODOT_VERSION: 3.5
- RELEASE: rc
NAME: ${{ github.event.repository.name }}
jobs:
export:
runs-on: ubuntu-latest
container:
- image: ghcr.io/bend-n/godot-2d:3.5.rc
+ image: ghcr.io/bend-n/godot-2d:3.5
name: ${{ matrix.name }}
strategy:
matrix:
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 68b663d..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "gdcli"]
- path = submodules/gdcli
- url = https://github.com/bend-n/gdcli
diff --git a/Logic.gd b/Logic.gd
new file mode 100644
index 0000000..946604d
--- /dev/null
+++ b/Logic.gd
@@ -0,0 +1,66 @@
+extends Reference
+class_name Logic
+
+const shapes = [
+ [ 0, 0, 0, 0,
+ 1, 1, 1, 1],
+ [ 0, 0, 0, 0,
+ 1, 1, 1, 0,
+ 1 ],
+ [ 1, 1, 1, 0,
+ 0, 0, 1 ],
+ [ 0, 1, 1, 0,
+ 0, 1, 1 ],
+ [ 1, 1, 0, 0,
+ 0, 1, 1 ],
+ [ 0, 1, 1, 0,
+ 1, 1 ],
+ [ 0, 1, 0, 0,
+ 1, 1, 1 ]
+];
+
+
+static func create_matrix(rows: int, columns: int) -> Array:
+ var matrix = []
+ for y in range(rows):
+ matrix.append([])
+ for _x in range(columns):
+ matrix[y].append(0)
+
+ return matrix
+
+
+static func valid_move(matrix: Array, piece, offset := Vector2()) -> bool:
+ offset += piece.position
+ for y in range(4):
+ for x in range(4):
+ if get_index_or_null(piece.shape, y, x) > 0:
+ #warning-ignore-all:narrowing_conversion
+ if (
+ get_index_or_null(matrix, y + offset.y, x + offset.x) == null
+ or get_index_or_null(matrix, y + offset.y, x + offset.x) > 0
+ or x + offset.x < 0
+ or y + offset.y >= len(matrix)
+ or x + offset.x >= len(matrix[y])
+ ):
+ return false
+ return true
+
+
+static func clear_lines(matrix: Array) -> void:
+ var y = len(matrix)
+ while y > 0:
+ y -= 1
+ if matrix[y].min() > 0:
+ for yy in range(y, 1, -1):
+ matrix[yy] = matrix[yy - 1]
+ y += 1
+
+
+static func get_index_or_null(arr: Array, y: int, x: int) -> int:
+ return arr[y][x] if y < len(arr) and x < len(arr[y]) else null
+
+
+static func print_matrix(mat: Array):
+ for i in mat:
+ print(i)
diff --git a/Main.tscn b/Main.tscn
index 70a653e..ede399a 100644
--- a/Main.tscn
+++ b/Main.tscn
@@ -1,3 +1,13 @@
-[gd_scene format=2]
+[gd_scene load_steps=2 format=2]
-[node name="Main" type="Node2D"]
+[ext_resource path="res://Tetris.gd" type="Script" id=1]
+
+[node name="Main" type="Control"]
+anchor_right = 1.0
+anchor_bottom = 1.0
+
+[node name="Tetris" type="AspectRatioContainer" parent="."]
+anchor_right = 1.0
+anchor_bottom = 1.0
+script = ExtResource( 1 )
+colors = PoolColorArray( 0.811765, 0.176471, 0.176471, 1, 0.427451, 0.721569, 0.278431, 1, 0.156863, 0.270588, 0.709804, 1, 0.615686, 0.164706, 0.611765, 1, 0.717647, 0.713726, 0.282353, 1, 0.47451, 0.47451, 0.47451, 1, 0.835294, 0.588235, 0.113725, 1 )
diff --git a/README.md b/README.md
index 7575a7e..8113488 100644
--- a/README.md
+++ b/README.md
@@ -1,37 +1,5 @@
-# godot-template
+# tetris
-Godot template repository for my programs
+[![version](https://img.shields.io/badge/3.x-blue?logo=godot-engine&logoColor=white&label=godot&style=for-the-badge)](https://godotengine.org "Made with godot")
----
-
-# How to use
-
-- To use: click use this template button.
-- Clone your repository
-- Add your files
-- Commit
-- Push
-
-<details>
-<summary>For itch.io depoloyment</summary>
-<br>
-Add a secret called BUTLER_CREDENTIALS with your butler api key.
-</details>
-
-<details>
-<summary>For android builds</summary>
-<br>
-Add two secrets:
- ANDROID_KEYSTORE_BASE64
- ANDROID_KEYSTORE_PASSWORD
-</details>
-
----
-
-### Availability:
-
-| windows | ios | linux | android | mac | html | |
-|:------------------:|:---:|:------------------:|:------------------:|:------------------:|:------------------:|:-------------:|
-| :x: | :x: | :x: | :x: | :x: | :heavy_check_mark: | github pages |
-| :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | itch.io |
-| :heavy_check_mark: | :x: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | godot exports |
+simple tetris
diff --git a/Tetris.gd b/Tetris.gd
new file mode 100644
index 0000000..459b088
--- /dev/null
+++ b/Tetris.gd
@@ -0,0 +1,121 @@
+class_name Tetris
+extends AspectRatioContainer
+
+const ROWS = 20
+const COLUMNS = 10
+
+export(PoolColorArray) var colors
+
+var current_shape: TetrisPiece
+var matrix := Logic.create_matrix(ROWS, COLUMNS)
+var bg_squares := []
+var squares := []
+
+
+func get_square(at: Vector2) -> Control:
+ return squares[at.y * COLUMNS + at.x]
+
+
+func init_squares():
+ var bg := create_grid_container("background")
+ add_child(bg)
+ var fg := create_grid_container("foreground")
+ add_child(fg)
+ for _i in range(ROWS * COLUMNS):
+ var bg_square := ReferenceRect.new()
+ bg_square.editor_only = false
+ bg_square.border_width = 1.5
+ bg_square.border_color = Color.ghostwhite
+ bg_square.name = "%d" % _i
+ expand_control(bg_square)
+ bg.add_child(bg_square)
+ var fg_square = ColorRect.new()
+ fg_square.color = Color.transparent
+ fg_square.name = "%d" % _i
+ expand_control(fg_square)
+ fg.add_child(fg_square)
+ squares.append(fg_square)
+
+
+func create_grid_container(name: String) -> GridContainer:
+ var g := GridContainer.new()
+ g.columns = COLUMNS
+ g.name = name
+ g.add_constant_override("hseparation", 0)
+ g.add_constant_override("vseparation", 0)
+ g.set_anchors_and_margins_preset(PRESET_WIDE)
+ return g
+
+
+func expand_control(c: Control) -> void:
+ c.size_flags_horizontal = SIZE_EXPAND_FILL
+ c.size_flags_vertical = SIZE_EXPAND_FILL
+ c.set_anchors_and_margins_preset(PRESET_WIDE)
+
+
+func _ready() -> void:
+ set_process(false)
+ assert(len(colors) == Logic.shapes.size()) # 7
+ ratio = float(COLUMNS) / float(ROWS)
+ init_squares()
+ start()
+
+
+func start() -> void:
+ set_process(true)
+ # warning-ignore-all:integer_division
+ current_shape = TetrisPiece.new(Vector2((COLUMNS / 2) - 2, 0))
+ tick()
+
+
+func draw_board(mat: Array = matrix.duplicate(true), shape: TetrisPiece = current_shape) -> void:
+ shape.embed(mat)
+ for y in range(ROWS):
+ for x in range(COLUMNS):
+ get_square(Vector2(x, y)).color = colors[mat[y][x] - 1] if mat[y][x] > 0 else Color.transparent
+
+
+func _process(_delta):
+ if Input.is_action_just_pressed("ui_left"):
+ current_shape.move(Vector2(-1, 0), matrix)
+ elif Input.is_action_just_pressed("ui_right"):
+ current_shape.move(Vector2(1, 0), matrix)
+ if Input.is_action_just_pressed("ui_up"):
+ current_shape.rotate(matrix, true)
+ if Input.is_action_just_pressed("ui_down"):
+ while current_shape.move(Vector2(0, 1), matrix):
+ continue
+ tick(false)
+ else:
+ draw_board()
+
+
+func tick(create_timer := true):
+ if create_timer:
+ var t := get_tree().create_timer(.25)
+ t.connect("timeout", self, "tick")
+
+ if not current_shape.move(Vector2(0, 1), matrix): # invalid move: cant go down
+ current_shape.embed(matrix)
+ current_shape = TetrisPiece.new(Vector2(randi() % (COLUMNS - 4), 0))
+ Logic.clear_lines(matrix)
+ print(ascii(matrix))
+ draw_board()
+
+
+#warning-ignore:shadowed_variable
+func ascii(matrix):
+ var s = "+"
+ for _x in range(COLUMNS):
+ s += "-"
+ s += "+"
+ #warning-ignore:shadowed_variable
+ for y in range(ROWS):
+ s += "\n" + ("|" if y != ROWS - 1 else "+")
+ for x in range(COLUMNS):
+ if matrix[y][x] > 0:
+ s += "ﱢ"
+ else:
+ s += "-"
+ s += ("|" if y != ROWS - 1 else "+")
+ return s
diff --git a/TetrisPiece.gd b/TetrisPiece.gd
new file mode 100644
index 0000000..9d9dc38
--- /dev/null
+++ b/TetrisPiece.gd
@@ -0,0 +1,74 @@
+extends Resource
+class_name TetrisPiece
+
+var shape_type: int
+var shape := []
+var position: Vector2
+
+
+func _init(pos: Vector2) -> void:
+ position = pos
+ randomize()
+ shape_type = randi() % len(Logic.shapes)
+ var s: PoolIntArray = [0, 0, 0, 0]
+ s.append_array(Logic.shapes[shape_type])
+
+ for y in range(4):
+ shape.append([])
+ for x in range(4):
+ var i: int = y * 4 + x
+ if len(s) > i and s[i] > 0:
+ shape[y].append(1)
+ else:
+ shape[y].append(0)
+
+
+# 90 deg
+func _rotate_cw() -> void:
+ var new_shape = shape.duplicate(true)
+ new_shape[0][0] = shape[3][0]
+ new_shape[0][1] = shape[2][0]
+ new_shape[0][2] = shape[1][0]
+ new_shape[0][3] = shape[0][0]
+ new_shape[1][3] = shape[0][1]
+ new_shape[2][3] = shape[0][2]
+ new_shape[3][3] = shape[0][3]
+ new_shape[3][2] = shape[1][3]
+ new_shape[3][1] = shape[2][3]
+ new_shape[3][0] = shape[3][3]
+ new_shape[2][0] = shape[3][2]
+ new_shape[1][0] = shape[3][1]
+
+ new_shape[1][1] = shape[2][1]
+ new_shape[1][2] = shape[1][1]
+ new_shape[2][2] = shape[1][2]
+ new_shape[2][1] = shape[2][2]
+ shape = new_shape
+
+
+func embed(matrix: Array) -> Array:
+ for y in range(4):
+ for x in range(4):
+ if shape[y][x] > 0:
+ matrix[y + position.y][x + position.x] = 1 + shape_type
+ return matrix
+
+
+func move(direction: Vector2, matrix: Array) -> bool:
+ if Logic.valid_move(matrix, self, direction):
+ position += direction
+ return true
+ return false
+
+
+func rotate(matrix: Array, cw := true):
+ var s = shape.duplicate(true)
+ if cw:
+ _rotate_cw()
+ else:
+ for _i in range(3):
+ _rotate_cw()
+ if !Logic.valid_move(matrix, self):
+ shape = s
+ return false
+ return true
diff --git a/addons/gdcli b/addons/gdcli
deleted file mode 120000
index ac119d8..0000000
--- a/addons/gdcli
+++ /dev/null
@@ -1 +0,0 @@
-../submodules/gdcli/addons/gdcli/ \ No newline at end of file
diff --git a/autoloads/CLI.gd b/autoloads/CLI.gd
deleted file mode 100644
index 095bfd3..0000000
--- a/autoloads/CLI.gd
+++ /dev/null
@@ -1,11 +0,0 @@
-extends Node
-
-func _ready() -> void:
- var p := Parser.new()
- p.add_argument(Arg.new({triggers=["-h", "--help", "-?"], help="show this help message and exit", action="store_true"}))
- var args = p.parse_arguments()
- if args == null:
- get_tree().quit()
- elif args.get("help", false):
- print(p.help())
- get_tree().quit() \ No newline at end of file
diff --git a/project.godot b/project.godot
index 663e841..308345a 100644
--- a/project.godot
+++ b/project.godot
@@ -10,30 +10,32 @@ config_version=4
_global_script_classes=[ {
"base": "Reference",
-"class": "Arg",
+"class": "Logic",
"language": "GDScript",
-"path": "res://addons/gdcli/Arg.gd"
+"path": "res://Logic.gd"
}, {
-"base": "Reference",
-"class": "Parser",
+"base": "AspectRatioContainer",
+"class": "Tetris",
+"language": "GDScript",
+"path": "res://Tetris.gd"
+}, {
+"base": "Resource",
+"class": "TetrisPiece",
"language": "GDScript",
-"path": "res://addons/gdcli/Parser.gd"
+"path": "res://TetrisPiece.gd"
} ]
_global_script_class_icons={
-"Arg": "",
-"Parser": ""
+"Logic": "",
+"Tetris": "",
+"TetrisPiece": ""
}
[application]
-config/name="Godot Template"
+config/name="tetris"
run/main_scene="res://Main.tscn"
config/use_custom_user_dir=true
-config/custom_user_dir_name="GodotTemplate"
-
-[autoload]
-
-CLI="*res://autoloads/CLI.gd"
+config/custom_user_dir_name="tetris"
[debug]
@@ -41,13 +43,13 @@ gdscript/warnings/return_value_discarded=false
[display]
-window/size/width=320
-window/size/height=180
-window/size/test_width=1280
-window/size/test_height=720
+window/size/width=180
+window/size/height=320
+window/size/test_width=720
+window/size/test_height=1280
window/dpi/allow_hidpi=true
window/stretch/mode="2d"
-window/stretch/aspect="keep"
+window/stretch/aspect="expand"
[logging]
@@ -61,3 +63,4 @@ quality/intended_usage/framebuffer_allocation=0
quality/intended_usage/framebuffer_allocation.mobile=0
2d/snapping/use_gpu_pixel_snap=true
vram_compression/import_etc=true
+environment/default_clear_color=Color( 0.937255, 0.937255, 0.937255, 1 )
diff --git a/submodules/.gdignore b/submodules/.gdignore
deleted file mode 100644
index e69de29..0000000
--- a/submodules/.gdignore
+++ /dev/null
diff --git a/submodules/gdcli b/submodules/gdcli
deleted file mode 160000
-Subproject 6040364dae05d331f8d6c9d3d52186df1d0399c