Template and Runtime Commit

Includes the godot runtime and the project files from the Match3 template.
This commit is contained in:
Jordan Wages 2022-02-09 15:51:01 -06:00
parent 1f18527c58
commit 978769d657
26 changed files with 638 additions and 0 deletions

Binary file not shown.

16
project/.gitignore vendored Normal file
View file

@ -0,0 +1,16 @@
# Godot 4+ specific ignores
.godot/
# Godot-specific ignores
.import/
export.cfg
export_presets.cfg
icon.png.import
# Imported translations (automatically generated from CSV files)
*.translation
# Mono-specific ignores
.mono/
data_*/
mono_crash.*.json

View file

@ -0,0 +1,3 @@
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="64" cy="64" r="64" fill="#3E77AB"/>
</svg>

After

Width:  |  Height:  |  Size: 155 B

View file

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/blue.svg-a42ad444b08fc2fd100f5c23f40200a1.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Dots/blue.svg"
dest_files=[ "res://.import/blue.svg-a42ad444b08fc2fd100f5c23f40200a1.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -0,0 +1,3 @@
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="64" cy="64" r="64" fill="#2C6655"/>
</svg>

After

Width:  |  Height:  |  Size: 155 B

View file

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/green.svg-1eed087a526827ecaabefae6a064e589.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Dots/green.svg"
dest_files=[ "res://.import/green.svg-1eed087a526827ecaabefae6a064e589.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -0,0 +1,3 @@
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="64" cy="64" r="64" fill="#913C93"/>
</svg>

After

Width:  |  Height:  |  Size: 155 B

View file

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/pink.svg-bcf5fbe4009604c30372094ff14e7f7c.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Dots/pink.svg"
dest_files=[ "res://.import/pink.svg-bcf5fbe4009604c30372094ff14e7f7c.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -0,0 +1,3 @@
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="64" cy="64" r="64" fill="#A43238"/>
</svg>

After

Width:  |  Height:  |  Size: 155 B

View file

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/red.svg-f35596819128c83df274f6d2808d304e.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Dots/red.svg"
dest_files=[ "res://.import/red.svg-f35596819128c83df274f6d2808d304e.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -0,0 +1,3 @@
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="64" cy="64" r="64" fill="#AE8337"/>
</svg>

After

Width:  |  Height:  |  Size: 155 B

View file

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/yellow.svg-f2aa811297a648861c15d5c673f8d564.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Assets/Dots/yellow.svg"
dest_files=[ "res://.import/yellow.svg-f2aa811297a648861c15d5c673f8d564.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

21
project/LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Mehmet Akif Duba
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

2
project/README.md Normal file
View file

@ -0,0 +1,2 @@
# Godot Engine Match3 Game Template
![screenshot](https://user-images.githubusercontent.com/31243845/140289774-6552bb39-0747-4c4a-bd5f-6e92ae855b99.png)

11
project/Scenes/Dot.tscn Normal file
View file

@ -0,0 +1,11 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://Scripts/Dot.gd" type="Script" id=1]
[node name="Dot" type="Node2D"]
scale = Vector2( 0.5, 0.5 )
script = ExtResource( 1 )
[node name="Sprite" type="Sprite" parent="."]
[node name="Tween" type="Tween" parent="."]

View file

@ -0,0 +1,10 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://Assets/Dots/blue.svg" type="Texture" id=1]
[ext_resource path="res://Scenes/Dot.tscn" type="PackedScene" id=2]
[node name="blue_dot" instance=ExtResource( 2 )]
color = "blue"
[node name="Sprite" parent="." index="0"]
texture = ExtResource( 1 )

View file

@ -0,0 +1,10 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://Assets/Dots/green.svg" type="Texture" id=1]
[ext_resource path="res://Scenes/Dot.tscn" type="PackedScene" id=2]
[node name="green_dot" instance=ExtResource( 2 )]
color = "green"
[node name="Sprite" parent="." index="0"]
texture = ExtResource( 1 )

View file

@ -0,0 +1,10 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://Assets/Dots/pink.svg" type="Texture" id=1]
[ext_resource path="res://Scenes/Dot.tscn" type="PackedScene" id=2]
[node name="pink_dot" instance=ExtResource( 2 )]
color = "pink"
[node name="Sprite" parent="." index="0"]
texture = ExtResource( 1 )

View file

@ -0,0 +1,10 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://Assets/Dots/red.svg" type="Texture" id=1]
[ext_resource path="res://Scenes/Dot.tscn" type="PackedScene" id=2]
[node name="red_dot" instance=ExtResource( 2 )]
color = "red"
[node name="Sprite" parent="." index="0"]
texture = ExtResource( 1 )

View file

@ -0,0 +1,10 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://Assets/Dots/yellow.svg" type="Texture" id=1]
[ext_resource path="res://Scenes/Dot.tscn" type="PackedScene" id=2]
[node name="yellow_dot" instance=ExtResource( 2 )]
color = "yellow"
[node name="Sprite" parent="." index="0"]
texture = ExtResource( 1 )

21
project/Scenes/Game.tscn Normal file
View file

@ -0,0 +1,21 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://Scripts/Grid.gd" type="Script" id=1]
[node name="Game" type="Node"]
[node name="ColorRect" type="ColorRect" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
color = Color( 0, 0, 0, 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Grid" type="Node2D" parent="."]
script = ExtResource( 1 )
width = 7
height = 7
offset = 70
y_offset = -2
empty_spaces = PoolVector2Array( 0, 0, 0, 6, 6, 6, 6, 0, 2, 3, 3, 3, 4, 3 )

18
project/Scripts/Dot.gd Normal file
View file

@ -0,0 +1,18 @@
extends Node2D
export (String) var color
onready var move_tween = $Tween
onready var sprite = get_node("Sprite")
var matched = false
func _ready():
pass
func move(target):
move_tween.interpolate_property(self, "position", position, target, 0.2, Tween.TRANS_LINEAR, Tween.EASE_OUT)
move_tween.start()
pass
func dim():
sprite.modulate = Color(1, 1, 1, 0.5)

261
project/Scripts/Grid.gd Normal file
View file

@ -0,0 +1,261 @@
extends Node2D
enum {wait, move}
var state
export (int) var width
export (int) var height
export (int) var offset
export (int) var y_offset
onready var x_start = ((OS.window_size.x / 2.0) - ((width/2.0) * offset ) + (offset / 2))
onready var y_start = ((OS.window_size.y / 2.0) + ((height/2.0) * offset ) - (offset / 2))
export (PoolVector2Array) var empty_spaces
onready var possible_dots = [
preload("res://Scenes/Dots/blue_dot.tscn"),
preload("res://Scenes/Dots/green_dot.tscn"),
preload("res://Scenes/Dots/pink_dot.tscn"),
preload("res://Scenes/Dots/red_dot.tscn"),
preload("res://Scenes/Dots/yellow_dot.tscn"),
]
var destroy_timer = Timer.new()
var collapse_timer = Timer.new()
var refill_timer = Timer.new()
var all_dots = []
var dot_one = null
var dot_two = null
var last_place = Vector2(0,0)
var last_direction = Vector2(0,0)
var move_checked = false
var first_touch = Vector2(0,0)
var final_touch = Vector2(0,0)
var controlling = false
func _ready():
state = move
setup_timers()
randomize()
all_dots = make_2d_array()
spawn_dots()
func setup_timers():
destroy_timer.connect("timeout",self,"destroy_matches")
destroy_timer.set_one_shot(true)
destroy_timer.set_wait_time(0.2)
add_child(destroy_timer)
collapse_timer.connect("timeout",self,"collapse_columns")
collapse_timer.set_one_shot(true)
collapse_timer.set_wait_time(0.2)
add_child(collapse_timer)
refill_timer.connect("timeout",self,"refill_columns")
refill_timer.set_one_shot(true)
refill_timer.set_wait_time(0.2)
add_child(refill_timer)
func restricted_fill(place):
if is_in_array(empty_spaces, place):
return true
return false
func is_in_array(array, item):
for i in array.size():
if array[i] == item:
return true
return false
func make_2d_array():
var array = []
for i in width:
array.append([])
for j in height:
array[i].append(null)
return array
func spawn_dots():
for i in width:
for j in height:
if !restricted_fill(Vector2(i, j)):
var rand = floor(rand_range(0, possible_dots.size()))
var dot = possible_dots[rand].instance()
var loops = 0
while (match_at(i, j, dot.color) && loops < 100):
rand = floor(rand_range(0,possible_dots.size()))
loops += 1
dot = possible_dots[rand].instance()
add_child(dot)
dot.position = grid_to_pixel(i, j)
all_dots[i][j] = dot
func match_at(i, j, color):
if i > 1:
if all_dots[i - 1][j] != null && all_dots[i - 2][j] != null:
if all_dots[i - 1][j].color == color && all_dots[i - 2][j].color == color:
return true
if j > 1:
if all_dots[i][j - 1] != null && all_dots[i][j - 2] != null:
if all_dots[i][j - 1].color == color && all_dots[i][j - 2].color == color:
return true
pass
func grid_to_pixel(column, row):
var new_x = x_start + offset * column
var new_y = y_start + -offset * row
return Vector2(new_x, new_y)
func pixel_to_grid(pixel_x,pixel_y):
var new_x = round((pixel_x - x_start) / offset)
var new_y = round((pixel_y - y_start) / -offset)
return Vector2(new_x, new_y)
pass
func is_in_grid(grid_position):
if grid_position.x >= 0 && grid_position.x < width:
if grid_position.y >= 0 && grid_position.y < height:
return true
return false
func touch_input():
if Input.is_action_just_pressed("ui_touch"):
if is_in_grid(pixel_to_grid(get_global_mouse_position().x,get_global_mouse_position().y)):
first_touch = pixel_to_grid(get_global_mouse_position().x,get_global_mouse_position().y)
controlling = true
if Input.is_action_just_released("ui_touch"):
if is_in_grid(pixel_to_grid(get_global_mouse_position().x,get_global_mouse_position().y)) && controlling:
controlling = false
final_touch = pixel_to_grid(get_global_mouse_position().x,get_global_mouse_position().y )
touch_difference(first_touch, final_touch)
func swap_dots(column, row, direction):
var first_dot = all_dots[column][row]
var other_dot = all_dots[column + direction.x][row + direction.y]
if first_dot != null && other_dot != null:
store_info(first_dot, other_dot, Vector2(column, row), direction)
state = wait
all_dots[column][row] = other_dot
all_dots[column + direction.x][row + direction.y] = first_dot
first_dot.move(grid_to_pixel(column + direction.x, row + direction.y))
other_dot.move(grid_to_pixel(column, row))
if !move_checked:
find_matches()
func store_info(first_dot, other_dot, place, direciton):
dot_one = first_dot
dot_two = other_dot
last_place = place
last_direction = direciton
pass
func swap_back():
if dot_one != null && dot_two != null:
swap_dots(last_place.x, last_place.y, last_direction)
state = move
move_checked = false
func touch_difference(grid_1, grid_2):
var difference = grid_2 - grid_1
if abs(difference.x) > abs(difference.y):
if difference.x > 0:
swap_dots(grid_1.x, grid_1.y, Vector2(1, 0))
elif difference.x < 0:
swap_dots(grid_1.x, grid_1.y, Vector2(-1, 0))
elif abs(difference.y) > abs(difference.x):
if difference.y > 0:
swap_dots(grid_1.x, grid_1.y, Vector2(0, 1))
elif difference.y < 0:
swap_dots(grid_1.x, grid_1.y, Vector2(0, -1))
func _process(_delta):
if state == move:
touch_input()
func find_matches():
for i in width:
for j in height:
if all_dots[i][j] != null:
var current_color = all_dots[i][j].color
if i > 0 && i < width -1:
if !is_piece_null(i - 1, j) && !is_piece_null(i + 1, j):
if all_dots[i - 1][j].color == current_color && all_dots[i + 1][j].color == current_color:
match_and_dim(all_dots[i - 1][j])
match_and_dim(all_dots[i][j])
match_and_dim(all_dots[i + 1][j])
if j > 0 && j < height -1:
if !is_piece_null(i, j - 1) && !is_piece_null(i, j + 1):
if all_dots[i][j - 1].color == current_color && all_dots[i][j + 1].color == current_color:
match_and_dim(all_dots[i][j - 1])
match_and_dim(all_dots[i][j])
match_and_dim(all_dots[i][j + 1])
destroy_timer.start()
func is_piece_null(column, row):
if all_dots[column][row] == null:
return true
return false
func match_and_dim(item):
item.matched = true
item.dim()
func destroy_matches():
var was_matched = false
for i in width:
for j in height:
if all_dots[i][j] != null:
if all_dots[i][j].matched:
was_matched = true
all_dots[i][j].queue_free()
all_dots[i][j] = null
move_checked = true
if was_matched:
collapse_timer.start()
else:
swap_back()
func collapse_columns():
for i in width:
for j in height:
if all_dots[i][j] == null && !restricted_fill(Vector2(i,j)):
for k in range(j + 1, height):
if all_dots[i][k] != null:
all_dots[i][k].move(grid_to_pixel(i, j))
all_dots[i][j] = all_dots[i][k]
all_dots[i][k] = null
break
refill_timer.start()
func refill_columns():
for i in width:
for j in height:
if all_dots[i][j] == null && !restricted_fill(Vector2(i,j)):
var rand = floor(rand_range(0, possible_dots.size()))
var dot = possible_dots[rand].instance()
var loops = 0
while (match_at(i, j, dot.color) && loops < 100):
rand = floor(rand_range(0,possible_dots.size()))
loops += 1
dot = possible_dots[rand].instance()
add_child(dot)
dot.position = grid_to_pixel(i, j - y_offset)
dot.move(grid_to_pixel(i,j))
all_dots[i][j] = dot
after_refill()
func after_refill():
for i in width:
for j in height:
if all_dots[i][j] != null:
if match_at(i, j, all_dots[i][j].color):
find_matches()
destroy_timer.start()
return
state = move
move_checked = false

7
project/default_env.tres Normal file
View file

@ -0,0 +1,7 @@
[gd_resource type="Environment" load_steps=2 format=2]
[sub_resource type="ProceduralSky" id=1]
[resource]
background_mode = 2
background_sky = SubResource( 1 )

BIN
project/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

41
project/project.godot Normal file
View file

@ -0,0 +1,41 @@
; 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
_global_script_classes=[ ]
_global_script_class_icons={
}
[application]
config/name="Godot Match 3 Template"
run/main_scene="res://Scenes/Game.tscn"
boot_splash/bg_color=Color( 0, 0, 0, 1 )
config/icon="res://icon.png"
[display]
window/size/width=540
window/size/height=960
window/handheld/orientation="portrait"
window/stretch/mode="2d"
window/stretch/aspect="keep_width"
[input]
ui_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)
]
}
[rendering]
quality/driver/driver_name="GLES2"
environment/default_environment="res://default_env.tres"