I am trying to create a mathematics related game and I would need to have multiple enemies with different values (numbers and operations; i.e. an enemy for +3, -4, x2, etc.). This values are generated randomly when the enemy is created, since having a different enemy for each operation and number combination sounds ridiculous.
I’m looking for a way to get the operation and value combination in STRING form and use that as a mathematical operation that would apply to the player’s current number. To clarify, the goal of the game is to get your current number (i.e. 3) to match the goal number (i.e. 18) by killing the operation/value enemies, so if the player’s current number is 3 and he wants to reach 18 he would need to kill an enemy displaying the “x6” operation. I need to take that operation from string form and activelly multiply, divide, add, or subtract to the player’s current number.
The easiest way I can think of would be to use the “Expression” class.
I don’t generally use GDScript, but I cobbled together an example code that might help illustrate how it could be done:
func _ready() -> void:
var expression = Expression.new()
var error = expression.parse("2x5")
if error != OK:
print("error parsing expression")
pass
var result = expression.execute()
if (expression.has_execute_failed()):
print("error executing expression")
pass
# Here you can use result!
Of course, you should replace “2x5” with your own expression, and possibly put this into a function instead of calling it in _ready, but I hope that’s a good starting point!
I managed to do it, firstly I created to global variables: operation and value. Then, I got each operation and value from each enemy instance (these were randomized when the enemy spawned in), when the enemy was killed I changed the global variables to match the enemies operation and values (the operation variable was a String in a array and the value was an Int). Later, in the main game scene, I match the operations names to the operations they need to do using the player’s current number and the value it got from the enemy.
Enemy code:
extends CharacterBody2D
var health:int = 2
var value:int
var operation_array:Array = ["Add","Sub","Mult","Div"]
var operation:String
func _ready():
add_to_group("Enemy")
#randomize numerical value
value = randi_range(1,10)
#randomize operation
operation_array.shuffle()
operation = operation_array[0]
func _physics_process(_delta):
if health <= 0:
death()
$Label.text = str(operation) + str(" ") + str(value)
func death():
OperationControl.current_operation = operation
OperationControl.current_number = value
queue_free()
World Scene code:
extends Node2D
#Label
@onready var score_label = $ScoreLabel
@onready var goal_label = $GoalLabel
@onready var player_label = $Player/PlayerLabel
#Path
@onready var path_2d = $Path2D
@onready var path_follow_2d = $Path2D/PathFollow2D
const ENEMY = preload("res://enemy.tscn")
var max_enemies = 5
func _ready():
OperationControl.score = 0
OperationControl.player_number = 0
randomize_goal_range()
func _process(_delta):
#Set Lavels
goal_label.text = str("Goal:") + str(OperationControl.goal-1) + str(" to ") + str(OperationControl.goal+1)
score_label.text = str("Score:") + str(OperationControl.score)
player_label.text = str(OperationControl.player_number)
match_operation()
reach_goal()
func randomize_goal_range():
OperationControl.goal = randi_range(-20,20)
func match_operation():
match OperationControl.current_operation:
"Add":
OperationControl.player_number += OperationControl.current_number
OperationControl.current_number = 0
"Sub":
OperationControl.player_number -= OperationControl.current_number
OperationControl.current_number = 0
"Mult":
OperationControl.player_number = OperationControl.player_number*OperationControl.current_number
OperationControl.current_number = 1
"Div":
if OperationControl.player_number!=0:
OperationControl.player_number = round(OperationControl.player_number/OperationControl.current_number)
OperationControl.current_number = 1
else: OperationControl.player_number==0
func reach_goal():
if OperationControl.player_number >=0:
if OperationControl.player_number >= OperationControl.goal-1 and OperationControl.player_number < OperationControl.goal+1:
OperationControl.score += 10
randomize_goal_range()
else:
if OperationControl.player_number < OperationControl.goal-1 and OperationControl.player_number < OperationControl.goal+1:
OperationControl.score += 10
randomize_goal_range()
func spawn_enemy():
path_follow_2d.progress_ratio = randf()
var enemy_inst = ENEMY.instantiate()
enemy_inst.global_position = path_follow_2d.global_position
add_child(enemy_inst)
func _on_enemy_spawn_timeout():
var enemy_group = get_tree().get_nodes_in_group("Enemy")
if enemy_group.size() < max_enemies:
spawn_enemy()