From 59b74b946a090dd0b95e21814fe2ed7751b6e09b Mon Sep 17 00:00:00 2001 From: Andrew Tang Date: Mon, 11 Jul 2022 01:16:34 +0800 Subject: [PATCH] Complete DiceRoller Singleton Version Created script: "DiceRoller.gd" to be the only dice script attached to a node and will act as a singleton. A single DieManager object is created in this script. The DieManager's values can be changed and methods can be called through the DiceRoller Script --- .../DiceRoller/DiceRoller.gd | 69 +++++++ .../DiceRoller/DiceRoller.tscn | 11 +- .../DiceRoller/Die.gd | 7 +- .../DiceRoller/DieManager.gd | 172 ++++++++---------- .../DiceRoller/project.godot | 14 +- 5 files changed, 162 insertions(+), 111 deletions(-) create mode 100644 Phase2/Godot ===(Game Code)===/DiceRoller/DiceRoller.gd diff --git a/Phase2/Godot ===(Game Code)===/DiceRoller/DiceRoller.gd b/Phase2/Godot ===(Game Code)===/DiceRoller/DiceRoller.gd new file mode 100644 index 0000000..858415a --- /dev/null +++ b/Phase2/Godot ===(Game Code)===/DiceRoller/DiceRoller.gd @@ -0,0 +1,69 @@ +#This script is for the overarching node that will contain the diemanager singleton +#It should be the only one of the die scripts that is attached onto a node. + +extends Control + +#desired dice types and needed percentage to pass are selected by game/user +#desiredDice takes an int array representing the # sides on the die/dice +#neededPercentageToPass takes a float that +export var desiredDice: Array +export var neededPercentageToPass: float + +#Define dieManager variable +var dieManager + +func _ready(): + #create diemanager object + dieManager = DieManager.new(desiredDice, neededPercentageToPass) + +#function gets the result of the roll(s) and shows it in the UI +func _on_Die_button_down(): + #rollDice function returns an array with the following elements in the following positions: + #rollDice result: [[rolledValues], percentRolled, passResult, neededPercent, degreeOfSuccess, dice] + var result = dieManager.rollDice() + + + #assigning variable names to each of them for better clarity + var rolledValues = result[0] + var percentRolled = result[1] + var passResult = result[2] + var neededPercent = result[3] + var degreeOfSuccess = result[4] + var dice = result[5] + + + #Check if passed or not + if passResult: + $Outcome.text = "Successful Roll!" + else: + $Outcome.text = "Failed Roll!" + + var diceResultText = "Rolled Values:\n" + + #Prints the integer calues of each die rolled in the form: "D(num faces): (value rolled)" + for i in range(dice.size()): + diceResultText += ("D" + str(dice[i]) + ": " + str(rolledValues[i]) + "\n") + + #changing labels on screen + $RolledValues.text = diceResultText + $PercentNeeded.text = "Percent Needed to Pass: " + str(neededPercent * 100) + "%" + $PercentRolled.text = "Percent Rolled: " + str(percentRolled * 100) + "%" + $DegreeOfSuccess.text = "Degree of Success: " + str(degreeOfSuccess * 100) + "%" + + #revealing labels to user + $Outcome.show() + $RolledValues.show() + $PercentNeeded.show() + $PercentRolled.show() + $DegreeOfSuccess.show() + + +#Calls the cleardata method for the diemanager and hides the text on screen +func _on_Reset_button_down(): + $Outcome.hide() + $PercentNeeded.hide() + $PercentRolled.hide() + $DegreeOfSuccess.hide() + $RolledValues.hide() + dieManager.clearData() + dieManager.setDieManager(desiredDice, neededPercentageToPass) diff --git a/Phase2/Godot ===(Game Code)===/DiceRoller/DiceRoller.tscn b/Phase2/Godot ===(Game Code)===/DiceRoller/DiceRoller.tscn index 15b38bb..49188e8 100644 --- a/Phase2/Godot ===(Game Code)===/DiceRoller/DiceRoller.tscn +++ b/Phase2/Godot ===(Game Code)===/DiceRoller/DiceRoller.tscn @@ -1,13 +1,13 @@ -[gd_scene load_steps=3 format=2] +[gd_scene load_steps=2 format=2] -[ext_resource path="res://DieManager.gd" type="Script" id=1] -[ext_resource path="res://Die.gd" type="Script" id=2] +[ext_resource path="res://DiceRoller.gd" type="Script" id=1] [node name="DieManager" type="Control"] anchor_right = 1.0 anchor_bottom = 1.0 script = ExtResource( 1 ) -desiredDice = [ 20, 7, 10 ] +desiredDice = [ 10, 4, 6, 20 ] +neededPercentageToPass = 0.4 [node name="ColorRect" type="ColorRect" parent="."] anchor_right = 1.0 @@ -24,7 +24,6 @@ margin_top = 2.0 margin_right = 92.0 margin_bottom = 91.0 text = "Roll Die/Dice" -script = ExtResource( 2 ) [node name="RolledValues" type="Label" parent="."] visible = false @@ -95,4 +94,4 @@ margin_bottom = 469.0 text = "Reset" [connection signal="button_down" from="Die" to="." method="_on_Die_button_down"] -[connection signal="pressed" from="Reset" to="." method="_on_Reset_pressed"] +[connection signal="button_down" from="Reset" to="." method="_on_Reset_button_down"] diff --git a/Phase2/Godot ===(Game Code)===/DiceRoller/Die.gd b/Phase2/Godot ===(Game Code)===/DiceRoller/Die.gd index 3ddab3d..e2c7c66 100644 --- a/Phase2/Godot ===(Game Code)===/DiceRoller/Die.gd +++ b/Phase2/Godot ===(Game Code)===/DiceRoller/Die.gd @@ -1,11 +1,11 @@ #Die class - -extends Button +extends Node2D class_name Die #value of selected die type var numFaces: int + #Class constructor func _init(value): numFaces = value @@ -19,3 +19,6 @@ func rollDie(): return rolledNum +#Returns the number of faces on this die +func getNumFaces(): + return numFaces diff --git a/Phase2/Godot ===(Game Code)===/DiceRoller/DieManager.gd b/Phase2/Godot ===(Game Code)===/DiceRoller/DieManager.gd index d7bc50d..4605559 100644 --- a/Phase2/Godot ===(Game Code)===/DiceRoller/DieManager.gd +++ b/Phase2/Godot ===(Game Code)===/DiceRoller/DieManager.gd @@ -1,13 +1,17 @@ #This is the diemanager script that controls the rolling of the die/dice as well as calculates #the end result -extends Control +class_name DieManager -export var desiredDice = [20, 8] +extends Node2D + +#Array of the desired dice values to mod god wants +var desiredDice: Array + +#User can select the percentage needed for a successful roll +var neededPercentageToPass: float var validDieTypes = [4, 6, 8, 10, 12, 20] - - #boolean for if a percentageroll is taking place #we need a boolean for this because the way a percentage roll is calculated #with two D10s is different than if one were using other dice @@ -16,143 +20,109 @@ var isPercentageRoll = false #diceUsed holds the dice objects that are rolled var diceUsed = [] -#diceInPlay holds the die objects as well. -#This and diceUsed are essentially the same arrays (holding the dice objects), but I had to use -#two arrays due to the parameters in returnDiePercentage -var diceInPlay = [] - #rolledValues holds the integer value rolled from each die var rolledValues = [] -#User can select the percentage needed for a successful roll -export var neededPercentageToPass = .2 - #boolean based on whether the overall roll passed or not var passedRoll #float holding the degree of success (rolledVal - neededPercentageToPass) var degreeOfSuccess +#Constructor for diemanager class +func _init(dice, percent): + desiredDice = dice + neededPercentageToPass = percent + loadData() +#set values of diemanager +func setDieManager(dice, percent): + desiredDice = dice + neededPercentageToPass = percent + loadData() + #Load the diceInPlay array -func _ready(): +func loadData(): for elem in desiredDice: if elem in validDieTypes: - diceInPlay.append(Die.new(elem)) + diceUsed.append(Die.new(elem)) #conditional to check if two D10s are being used #if so, we know that a percentage roll is taking place if len(desiredDice) == 2 && desiredDice[0] == 10 && desiredDice[1] == 10: isPercentageRoll = true - - -#This is the function that returns the percentage of a rolled die (rolled val / total sides) -#The UML showed that this function only had one parameter, "inputedDie," so I assumed that -#was the rolled integer value. However, in order to find the percetage we need the total sides as well -#As a result, I would get the total sides by ensuring that the inputedDie corresponds to the die at index 0 -#of the diceInPlay array. +#Resets the data in the script +func clearData(): + isPercentageRoll = false + rolledValues = [] + desiredDice = [] + diceUsed = [] + neededPercentageToPass = 0 + +#Returns the percent value of an individual die +#Stores the rolled value in rolledValues func returnDiePercentage(inputedDie): + #In case this method is being called on no dice + if len(diceUsed) == 0: + push_error("Cannot roll without any dice!") + + var rolledVal = inputedDie.rollDie() - var totalSides = diceInPlay[0].numFaces - - #ensuring we don't lose the die objects in memory by storing them in another array - diceUsed.append(diceInPlay[0]) - diceInPlay.remove(0) + #add rolled integer value to array + rolledValues.append(rolledVal) #Checks if a percentageroll is being done if isPercentageRoll: - #This conditional is used to detemrine if the rolled value is #for the tens or ones digit - if (len(diceUsed) == 1): - return float(inputedDie % 10) / 10.0 - else: - return float(inputedDie % 10) / 100.0 - - var result = float(inputedDie) / float(totalSides) - return result + return float(rolledVal % 10) + return float(rolledVal) / float(inputedDie.numFaces) -#Function to show all of the results on screen -func showOnUI(passResult, percentRolled) -> void: - if passResult: - $Outcome.text = "Successful Roll!" - else: - $Outcome.text = "Failed Roll!" - - var diceResultText = "Rolled Values:\n" - - #Prints the integer calues of each die rolled in the form: "D(num faces): (value rolled)" - for i in range(diceUsed.size()): - diceResultText += ("D" + str(diceUsed[i].numFaces) + ": " + str(rolledValues[i]) + "\n") - - - #NOTE: degree of success is always calculated regardlesss of success/failure. Let me know if this should be changed - degreeOfSuccess = percentRolled - neededPercentageToPass - - #changing labels on screen - $RolledValues.text = diceResultText - $PercentNeeded.text = "Percent Needed to Pass: " + str(neededPercentageToPass * 100) + "%" - $PercentRolled.text = "Percent Rolled: " + str(percentRolled * 100) + "%" - $DegreeOfSuccess.text = "Degree of Success: " + str(degreeOfSuccess * 100) + "%" - - #revealing labels to user - $Outcome.show() - $RolledValues.show() - $PercentNeeded.show() - $PercentRolled.show() - $DegreeOfSuccess.show() +#Rolls all of the dice in diceUsed +#returns the average of all the percentages +func rollDice(): + #In case this method is being called on no dice + if len(diceUsed) == 0: + push_error("Cannot roll without any dice!") - -#function for when "roll" button is clicked -func _on_Die_button_down(): #denominator will equal the total number of dice rolled var denominator = 0 #sum of floats of all rolled die percentages var sumOfPercentages = 0 - #stores the rolled integer value of die in loop - var rolledVal + if isPercentageRoll: + sumOfPercentages += (returnDiePercentage(diceUsed[0]) / 10.0) + (returnDiePercentage(diceUsed[1]) / 100.0) + else: + for die in diceUsed: + sumOfPercentages += returnDiePercentage(die) + denominator += 1 + + var result = [] + + result.append(rolledValues) - #remember that the size of diceInPlay decrements by 1 each time returnDiePercentage is called - while diceInPlay.size() > 0: - rolledVal = diceInPlay[0].rollDie() - - #add rolled integer vaslue to array - rolledValues.append(rolledVal) - - #add percentage to sum - sumOfPercentages += returnDiePercentage(rolledVal) - - #increment denominator - denominator += 1 - - var result if isPercentageRoll: #Percentage roll result remains the sum of the rolls - result = sumOfPercentages + result.append(sumOfPercentages) else: - #result is average of sum of percentages otherwise - result = sumOfPercentages / denominator + if denominator == 0: + result.append(0) + #result is average of sum of percentages otherwise rounded to 2 decimcal places + + result.append(stepify((float(sumOfPercentages) / float(denominator)), 0.0001)) + + passedRoll = (result[1] >= neededPercentageToPass) +#NOTE: degree of success is always calculated regardlesss of success/failure. Let me know if this should be changed + degreeOfSuccess = result[1] - neededPercentageToPass + result.append(passedRoll) + result.append(neededPercentageToPass) + result.append(degreeOfSuccess) + result.append(desiredDice) - passedRoll = (result >= neededPercentageToPass) - - showOnUI(passedRoll, result) + #rollDice result: [[rolledValues], percentRolled, passResult, neededPercent, degreeOfSuccess, dice] return result - -#Reset stored values and text -func _on_Reset_pressed(): - $Outcome.hide() - $PercentNeeded.hide() - $PercentRolled.hide() - $DegreeOfSuccess.hide() - $RolledValues.hide() - #Fill diceInPlay again and empty diceUsed - for die in diceUsed: - diceInPlay.append(die) - diceUsed = [] - rolledValues = [] diff --git a/Phase2/Godot ===(Game Code)===/DiceRoller/project.godot b/Phase2/Godot ===(Game Code)===/DiceRoller/project.godot index cad39e9..b95a96b 100644 --- a/Phase2/Godot ===(Game Code)===/DiceRoller/project.godot +++ b/Phase2/Godot ===(Game Code)===/DiceRoller/project.godot @@ -9,13 +9,19 @@ config_version=4 _global_script_classes=[ { -"base": "Button", +"base": "Node2D", "class": "Die", "language": "GDScript", "path": "res://Die.gd" +}, { +"base": "Node2D", +"class": "DieManager", +"language": "GDScript", +"path": "res://DieManager.gd" } ] _global_script_class_icons={ -"Die": "" +"Die": "", +"DieManager": "" } [application] @@ -24,6 +30,10 @@ config/name="GodotDiceRoller_Andrew" run/main_scene="res://DiceRoller.tscn" config/icon="res://icon.png" +[autoload] + +DiceRoller="*res://DiceRoller.gd" + [physics] common/enable_pause_aware_picking=true