С последней статьи прошло уже приличное количество времени, а прогресса в моём деле не так много как хотелось бы...
Почитал, посмотрел множество информации по Godot и его возможностях, установил на данный момент последнюю доступную версию (4.3 stable) через Steam.
Пока что организовал следующую структуру в себя проекте
В папке autoload(автозагрузка) скрипты, которые будут загружаться при старте проекта и доступны из в любом месте для исполнения. В моем случае я пока вынес туда систему сигналов и общий словарь систем доступных в игре и методы работы с этим словарем.
signals.gd
extends Node
signal radioEnabled(currentValue:bool)
signal radioOff
signal airEnabled(currentValue:bool)
signal airOff
signal navigationEnabled(currentValue:bool)
signal navigationOff
signal controlEnabled(currentValue:bool)
signal controlOff
signal climateEnabled(currentValue:bool)
signal climateOff
systems.gd
extends Node
var system:Dictionary = {
'radioEnabled': true,
'airEnabled': true,
'navigationEnabled': true,
'controlEnabled': true,
'climateEnabled': true
}
func getSystem(name:String):
return system.get(name, false)
func setSystem(name:String, value:bool):
var val = null
if system.has(name):
system[name] = value
val = system[name]
return val
В папке components (компоненты) я решил сделать отдельные папки со сценами и скриптами отдельных элементов игры. Попробую на примере, что было понятнее о чем я.
Представим что мы находимся в космическом корабле за пультом управления. Перед нами несколько всяких панелей управления разными системами
Все относятся к панели управления, поэтому я объединил их все в одну папку в компонентах и назвал Panel.
Так как каждая из панелей будет иметь несколько одинаковых методов работы с ними я создал собственный класс в котором описал методы работы панели.
panelSystem.gd
class_name panelSystem
extends Node
var signalSystem:Signal
var signalSystemOff:Signal
var systemStatus:bool
var button:Node2D
var buttonPress:Button
var systemName:String
func _ready() -> void:
systemStatus = Systems.getSystem(systemName)
buttonPress.connect("pressed", _on_change_enabled)
signalSystemOff.connect(_on_system_off)
button.enable(systemStatus)
func _on_change_enabled():
systemStatus = Systems.setSystem(systemName, !systemStatus)
button.enable(systemStatus)
send_current_status()
func _on_system_off():
systemStatus = Systems.setSystem(systemName, false)
button.enable(systemStatus)
send_current_status()
func send_current_status():
signalSystem.emit(systemStatus)
И далее уже при создании сцены конкретной панели например, навигации я просто указал в качестве родителя мой класс и на основе его дополнил логику.
navigation.gd
extends panelSystem
@onready var eButton = $Button
@onready var eButtonPress = $Button/ButtonPress
func _ready() -> void:
button = eButton
buttonPress = eButtonPress
signalSystemOff = Signals.navigationOff
signalSystem = Signals.navigationEnabled
systemName = 'navigationEnabled'
super._ready()
Так же у нас есть одна панель которая по логике отличается от всех остальных.
У меня она называется Electro, по задумке в ней будет выводиться информация о кол-ве свободной энергии которую можно направить например на работу другой системы.
button.gd
extends Node2D
var imgButtonOff:Theme = preload("res://components/Panel/styles/ButtonOff.tres")
var imgButtonOn:Theme = preload("res://components/Panel/styles/ButtonOn.tres")
@onready var buttonPress = $ButtonPress
@onready var isEnabled:bool = true
@onready var soundButtonOn:AudioStreamPlayer2D = $ButtonOn
@onready var soundButtonOff:AudioStreamPlayer2D = $ButtonOff
func enable(enable:bool = true):
isEnabled = true if enable else false
if isEnabled:
buttonPress.theme = imgButtonOn
soundButtonOn.play()
else:
buttonPress.theme = imgButtonOff
soundButtonOff.play()
Так же у нас есть одна панель которая по логике отличается от всех остальных. У меня она называется Electro, по задумке в ней будет выводится информация о кол-ве свободной энергии которую можно направить например на работу другой системы.
electro.gd
extends Node2D
@onready var label = $Electro/Label
const maxElectro:int = 100
const oneElemPower:int = 10
var currentElectro:int = 0
func _ready() -> void:
changeLabelText(currentElectro)
Signals.radioEnabled.connect(_on_system_change)
Signals.airEnabled.connect(_on_system_change)
Signals.navigationEnabled.connect(_on_system_change)
Signals.controlEnabled.connect(_on_system_change)
Signals.climateEnabled.connect(_on_system_change)
func changeLabelText(addValue:int = 0, delValue:int = 0):
var newValue = currentElectro
if addValue > 0:
newValue = int(label.text) + addValue
if newValue > maxElectro:
newValue = maxElectro
label.text = str(newValue)
if delValue > 0:
newValue = int(label.text) - delValue
if (newValue < 0):
newValue = protectionSystem(newValue)
label.text = str(newValue)
currentElectro = newValue
func protectionSystem(tmpValue) -> int:
var newPower = tmpValue
if Systems.getSystem('radioEnabled'):
Signals.radioOff.emit()
newPower = calcNewPower(newPower)
if newPower >= 0:
return newPower
if Systems.getSystem('airEnabled'):
Signals.airOff.emit()
newPower = calcNewPower(newPower)
if newPower >= 0:
return newPower
if Systems.getSystem('navigationEnabled'):
Signals.navigationOff.emit()
newPower = calcNewPower(newPower)
if newPower >= 0:
return newPower
if Systems.getSystem('controlEnabled'):
Signals.controlOff.emit()
newPower = calcNewPower(newPower)
if newPower >= 0:
return newPower
if Systems.getSystem('climateEnabled'):
Signals.climateOff.emit()
newPower = calcNewPower(newPower)
if newPower >= 0:
return newPower
return 0
func calcNewPower(currentPower):
return currentPower + oneElemPower
func _on_system_change(value:bool):
if value:
changeLabelText(0, oneElemPower)
else:
changeLabelText(oneElemPower)
Пока копировал и смотрел на этот код понял, что он получится запутанным и скорее всего, это не то место где он должен быть, так что возможно в будущем будет рефактор, но пока он остается таким.
Так же я еще реализовал систему диалога, но об этом уже в следующей статье.