This lesson is a GDScript walkthrough: a tic-tac-toe board in Godot. The film is the explanation. The two scripts are the board and the button that fills with X and O.
The board
# Game
extends Node
var background: Panel
@onready var centerContainer: CenterContainer = CenterContainer.new()
@onready var mainContainer: VBoxContainer = VBoxContainer.new()
@onready var row1: HBoxContainer = HBoxContainer.new()
@onready var row2: HBoxContainer = HBoxContainer.new()
@onready var row3: HBoxContainer = HBoxContainer.new()
var nextSignX: bool = true
var buttons: Array[OurButton] = []
var game_over: bool = false
# Called when the node enters the scene tree for the first time.
func _ready():
background = Panel.new()
background.set_anchors_preset(Control.PRESET_FULL_RECT)
background.set_self_modulate(Color(1,0,0))
add_child(background)
generate_buttons()
mainContainer.add_child(row1);
mainContainer.add_child(row2);
mainContainer.add_child(row3);
centerContainer.add_child(mainContainer);
centerContainer.set_anchors_preset(Control.PRESET_FULL_RECT)
add_child(centerContainer);
func generate_buttons():
for i in range(9):
var new_button: Button = OurButton.new()
new_button.pressed.connect(on_click.bind(new_button))
buttons.append(new_button)
if i < 3:
row1.add_child(new_button)
elif i < 6:
row2.add_child(new_button)
else:
row3.add_child(new_button)
func on_click(button: Button):
if button.text != "" or game_over:
return
if nextSignX:
button.text = "X"
else:
button.text = "O"
if check_win():
handle_win()
if check_draw():
restart()
nextSignX = !nextSignX
func wait(seconds: float) -> void:
await get_tree().create_timer(seconds).timeout
func restart():
game_over = true
await wait(1)
get_tree().reload_current_scene()
func handle_win():
var winLabel: Label = Label.new()
winLabel.text = "X win" if nextSignX else "O win"
winLabel.add_theme_font_size_override("font_size", 64)
add_child(winLabel)
restart()
func check_draw():
for button in buttons:
if button.text == "":
return false
return true
func check_win():
if buttons[0].text == buttons[1].text and buttons[1].text == buttons[2].text and buttons[0].text != "" :
return true
if buttons[3].text == buttons[4].text and buttons[4].text == buttons[5].text and buttons[3].text != "":
return true
if buttons[6].text == buttons[7].text and buttons[7].text == buttons[8].text and buttons[6].text != "":
return true
if buttons[0].text == buttons[3].text and buttons[3].text == buttons[6].text and buttons[0].text != "":
return true
if buttons[1].text == buttons[4].text and buttons[4].text == buttons[7].text and buttons[1].text != "":
return true
if buttons[2].text == buttons[5].text and buttons[5].text == buttons[8].text and buttons[2].text != "":
return true
if buttons[0].text == buttons[4].text and buttons[4].text == buttons[8].text and buttons[0].text != "":
return true
if buttons[2].text == buttons[4].text and buttons[4].text == buttons[6].text and buttons[2].text != "":
return true
return false
OurButton
# OurButton
extends Button
class_name OurButton
# Called when the node enters the scene tree for the first time.
func _ready():
set_self_modulate(Color(0,1,0))
custom_minimum_size = Vector2(190,190)
add_theme_font_size_override("font_size", 64)