Solutions

Countdown Timer

Node Structure:

CountdownTimer(Control) (Script|countdown_timer.gd)
|-- Time(Label) 
|-- Timer(Timer) (Signal|_on_timer_timeout())

countdown_timer.gd

class_name CountdownTimer
extends Control

enum State {
	NORMAL,
	WARNING,
	ALERT,
	TIMES_UP,
} 

var startDays := 0
var startHours := 0
var startMinutes := 0
var startSeconds := 0
var timerWarningInSeconds := 0
var timerAlertInSeconds := 0

var totalStartTimeInSeconds := 0
var totalRemainingTimeInSeconds := 0
var lastTotalTimeInSeconds := 0
var days := 0
var hours := 0
var minutes := 0
var seconds := 0
var timerState : CountdownTimer.State
var timerStartingState := CountdownTimer.State.NORMAL
var timerOldState : CountdownTimer.State
var timerAutoStart := true
var timerWaitTime := 1
var isTimerActive := false

var timerFontSize = 20
var timerFontOutlineSize = 7
var timerFontOutlineColor = Color(0,0,0,1)
var timerNormalFontColor := Color(255,255,255,1)
var timerWarningFontColor := Color(255,255,0,1)
var timerAlertFontColor := Color(255,0,0,1)

signal times_up

func init(
        _startDays : int,
        _startHours : int,
        _startMinutes : int,
        _startSeconds : int,
        _timerWarningInSeconds : int,
        _timerAlertInSeconds : int) -> void:
        
        self.startDays = _startDays
        self.startHours = _startHours
        self.startMinutes = _startMinutes
        self.startSeconds = _startSeconds
        self.timerWarningInSeconds = _timerWarningInSeconds
        self.timerAlertInSeconds = _timerAlertInSeconds 
        
	var normalTimerLabelSettings:LabelSettings = LabelSettings.new()
	normalTimerLabelSettings.font_color = self.timerNormalFontColor
	normalTimerLabelSettings.font_size = self.timerFontSize
	normalTimerLabelSettings.outline_color = self.timerFontOutlineColor
	normalTimerLabelSettings.outline_size = self.timerFontOutlineSize
	$Time.label_settings = normalTimerLabelSettings
	
	$Timer.autostart = self.timerAutoStart
	$Timer.wait_time = self.timerWaitTime
	
	self.timerState = self.timerStartingState
	
	# Convert Days to Seconds
	self.totalStartTimeInSeconds += self.startDays * 24 * 60 * 60
	# Convert Hours to Seconds
	self.totalStartTimeInSeconds += self.startHours * 60 * 60
	# Convert Minutes to Seconds
	self.totalStartTimeInSeconds += self.startMinutes * 60
	# Add Seconds
	self.totalStartTimeInSeconds += self.startSeconds
	
	self.totalRemainingTimeInSeconds = self.totalStartTimeInSeconds
	
	# Activate Timer
	self.isTimerActive = true
	$Timer.start()
	
func calculate_time_display() -> void:
	self.lastTotalTimeInSeconds = self.totalRemainingTimeInSeconds
	
	var strDays := ""
	var strHours := ""
	var strMinutes := ""
	var strSeconds := ""
	
	self.timerOldState = self.timerState

	# Calculate Days
	self.days = floor(self.totalRemainingTimeInSeconds / 86400)
	if (self.days > 0):
		if (self.days >= 10):
			strDays = str(self.days)
		else:
			strDays = "0" + str(self.days)
	else:
		strDays = "00"
	
	# Calculate Hours
	self.hours = floor((self.totalRemainingTimeInSeconds - self.days * 86400) / 3600)
	if (self.hours > 0):
		if (self.hours >= 10):
			strHours = str(self.hours)
		else:
			strHours = "0" + str(self.hours)
	else:
		strHours = "00"
		
	# Calculate Minutes
	self.minutes = floor((self.totalRemainingTimeInSeconds - self.days * 86400 - self.hours * 3600) / 60)
	if (self.minutes > 0):
		if (self.minutes >= 10):
			strMinutes = str(self.minutes)
		else:
			strMinutes = "0" + str(self.minutes)
	else:
		strMinutes = "00"
		
	# Calculate Seconds
	self.seconds = (self.totalRemainingTimeInSeconds - self.days * 86400 - self.hours * 3600 - self.minutes * 60)
	if (self.seconds >= 10):
		strSeconds = str(self.seconds)
	else:
		strSeconds = "0" + str(self.seconds)
	
	# Change Font Color Based on Warning and Alert Thresholds
	if (self.timerWarningInSeconds != 0 and self.timerAlertInSeconds != 0):
		if (self.totalRemainingTimeInSeconds <= self.timerWarningInSeconds):	
			if (self.totalRemainingTimeInSeconds <= self.timerAlertInSeconds):
				self.timerState = CountdownTimer.State.ALERT
			else:
				self.timerState = CountdownTimer.State.WARNING
	
	# Update Timer Based on Timer State Change
	if (self.timerState != self.timerOldState):
		var changeTimerLabelSettings:LabelSettings = LabelSettings.new()
		changeTimerLabelSettings.font_size = self.timerFontSize
		changeTimerLabelSettings.outline_color = self.timerFontOutlineColor
		changeTimerLabelSettings.outline_size = self.timerFontOutlineSize
		
		match self.timerState:
			CountdownTimer.State.WARNING:
				changeTimerLabelSettings.font_color = self.timerWarningFontColor
			CountdownTimer.State.ALERT:
				changeTimerLabelSettings.font_color = self.timerAlertFontColor

		$Time.label_settings = changeTimerLabelSettings
		
	$Time.text = strDays + "d " + strHours + ":" + strMinutes + ":" + strSeconds
	
		# Timer Hit Zeros Stop Countdown
	if (self.totalRemainingTimeInSeconds == 0):
		self.timerState = CountdownTimer.State.TIMES_UP

func _process(delta) -> void:
	if (self.isTimerActive):
		if (self.timerState != CountdownTimer.State.TIMES_UP):
			# Only need to Calculate Every Second, not Every Frame
			if (self.totalRemainingTimeInSeconds != self.lastTotalTimeInSeconds):
				self.calculate_time_display()
		else:
			self.emit_signal("times_up")
			# Wait 3 Seconds Before Freeing Queue
			await get_tree().create_timer(3).timeout
			self.queue_free()

func _on_timer_timeout() -> void:
	# Count Down by 1 Second
	self.totalRemainingTimeInSeconds -= 1

Instantiate New Timer Scene:

Fade Out Message

Node Structure:

Message.gd

Instantiate New Message Scene

Last updated