If I Lose My Save Data for Lets Go Pikachu Can I Get Mew Again

In this tutorial, we will:

  • create the outset card – here, you can find the menu items to start a new a game, load the saved one, and quit the game;
  • develop the salvage and load functionality (to keep things simple, we'll but take one salve slot);
  • edit the in-game menu and the game over screen to bring u.s.a. dorsum to the start screen.

Creating the outset card scene

The following image shows the final result we will get. It's very similar to the in-game menu we built in Part 16: Break menu. Restart and quit game:

Graphically, it's a very basic menu – feel free to add your game logo and whatsoever graphics you desire.

To start, let's create a new scene for the start menu by clicking on Scene → New Scene. And so, in the Scene panel, click the 2D Sceneast button to create a Node2D root node. Rename it StartScreen.

Add a ColorRect node to StartScreen and resize it to 320×180 pixels: it volition be our card background. Change its Color property to black (0,0,0,255).

Now, add another ColorRect to StartScreen and rename it NewGame. Set Rect → Positiodue north to (70, l) and Rect → Size to (180, xx). Now add together a Label to NewGame. In the Custom Fonts property load Font.tres (you'll find it in the Fonts folder) and in Custom Colors set Font Colour to blackness. Write NEW GAME in the Text holding of the label, then set both Align and Valign to Center. Finally, set the Rect → Size of the label to (180, 20).

At present, duplicate NewGame two times. Rename one copy to LoadGame and the other to Quit.

Ready LoadGame's Rect → Position to (lxx, 80), then alter its label'southward text to LOAD GAME. Select the Quit node and set its Rect → Position to (70, 110). Finally, change its label'southward text to QUIT.

Finally, let'due south add together some groundwork music to our bill of fare. Add an AudioStreamPlayer node to StartScreen and in the Stream property load the dark-chip.ogg file (you can find it in the Sounds binder). Enable the Autoplay property to play music when the game starts.

You'll finish up with this node structure for the StartScreen scene:

Save the scene in the Scenes folder and call it StartScreen.tscn.

Get-go menu script

Attach a new script to the StartScreen node, telephone call information technology StartScreen.gd and save it in the GUI folder. Copy this code inside the script:

          extends Node2D  var selected_menu = 0  func change_menu_color(): 	$NewGame.color = Colour.grey 	$LoadGame.color = Color.gray 	$Quit.color = Color.gray 	 	friction match selected_menu: 		0: 			$NewGame.color = Color.greenyellow 		1: 			$LoadGame.color = Color.greenyellow 		2: 			$Quit.color = Color.greenyellow  func _ready(): 	change_menu_color()  func _input(event): 	if Input.is_action_just_pressed("ui_down"): 		selected_menu = (selected_menu + 1) % 3; 		change_menu_color() 	elif Input.is_action_just_pressed("ui_up"): 		if selected_menu > 0: 			selected_menu = selected_menu - 1 		else: 			selected_menu = 2 		change_menu_color() 	elif Input.is_action_just_pressed("set on"): 		lucifer selected_menu: 			0: 				# New game 				get_tree().change_scene("res://Scenes/Main.tscn") 			1: 				# Load game 				var next_level_resource = load("res://Scenes/Main.tscn"); 				var next_level = next_level_resource.example() 				next_level.load_saved_game = truthful 				get_tree().root.call_deferred("add_child", next_level) 				queue_free() 			ii: 				# Quit game 				get_tree().quit()        

The inner workings of the menu are the aforementioned every bit the in-game menu that we built in Part 16. Allow's take a closer look at what happens when nosotros select one of the menu items.

When we select NEW GAME, the script calls the change_scene() function of the current SceneTree to load the main scene of the game.

Instead, when we select LOAD GAME, we use a different method to load the primary scene:

  • First, we use the load() statement to load the scene in memory equally a PackedScene resources.
  • The scene is at present in memory, just information technology'due south not nonetheless a node. To create the actual node, nosotros must phone call the instance() part of PackedScene.
  • At present that the scene is an bodily node, we ready the load_saved_game variable to true. This variable (which nosotros will declare shortly) will be used by the Root node of the primary scene to decide whether to load the data from the saved game or non.
  • At this signal, we add the newly created node to the current scene. We must telephone call add_child() via call_deferred() because nosotros take to wait for the node to be completely initialized (i.e., all kid nodes loaded).
  • Finally, we tell Godot to remove the start menu from the node tree by calling the queue_free() function.

The last menu particular is QUIT. To go out the game, we just call the quit() function of the current SceneTree.

As seen to a higher place, the script we only created refers to the load_saved_game variable that doesn't exist yet. To declare it, get to the Principal.tscn scene and adhere a script to the Root node. Call it SaveLoadGame.gd and put it in a new binder named Scripts. For now, simply enter this code to declare the load_saved_game variable and to add a new function called save (we'll implement information technology later when we save the game):

          var load_saved_game = simulated  func salvage(): 	pass        

Now click the Project → Project Settings menu and go to the Application → Run department. Change the Chief Scene setting to run the StartScreen.tscn scene at game start. Run the game to test the carte du jour.

In-game carte

Before seeing how to save the game, we need to update the in-game card to add the salve and the return to start carte items. In the main scene, become to the MenuPopup node. Rename the Restart node to SaveGame and the Quit node to MainMenu, then change the text of their labels to Salve GAME and MAIN MENU. Then, open the MenuPopup.gd script and in the change_menu_color() function supersede any reference to $Restart with $SaveGame, and those to $Quit with $MainMenu:

          func change_menu_color(): 	$Resume.colour = Color.grayness 	$SaveGame.color = Colour.grey 	$MainMenu.colour = Colour.gray 	 	lucifer selected_menu: 		0: 			$Resume.color = Color.greenyellow 		ane: 			$SaveGame.color = Color.greenyellow 		2: 			$MainMenu.color = Color.greenyellow        

Now, in the _input() role, we need to replace the code of the updated bill of fare items (alphabetize 1 and ii). The new code is as follows:

          ...  1: 	# Save Game 	get_node("/root/Root").salvage() 	get_tree().paused = imitation 	hide() two: 	# Dorsum to kickoff screen 	get_node("/root/Root").queue_free() 	get_tree().change_scene("res://Scenes/StartScreen.tscn") 	get_tree().paused = faux        

The code for the salvage game card particular calls the salvage() part of the Root node than cancel the pause and hide the in-game bill of fare. To return to the chief menu, nosotros costless the current scene, loads the start screen scene, and cancels the break.

Salve file data

Saving a game is the action of creating or updating a file that contains all the progress made by the players. This allows them to interrupt the game and resume it later, or even to retry the game several times in case of defeat, restarting from a previous moment in time.

To salvage the game, we need to:

  1. identify all the information necessary to rebuild the current state of the game;
  2. choose the most constructive method to store this information.

Allow's beginning from point 1. The entities that change during the game, and therefore must be stored, are the post-obit:

  • The player: to rebuild its state, nosotros must salvage its position, its wellness, its mana, the experience points, the level, and its inventory.
  • Fiona: to store the country of Fiona, information technology's plenty to know the status of her quest and if her necklace has been found or not.
  • The skeletons: we have to store a list of skeletons, saving each one's position and wellness.
  • Pickable objects: at the starting time of the game, on the map at that place are two potions that the player tin can pick up; we accept to shop whether they have already been taken or not.

Every bit for point 2, I decided to salve the country of the game in JSON format. JSON (JavaScript Object Notation) is a data format that uses man-readable text to store information in attribute-value pairs.

A significant advantage of using JSON to save data is the remarkable resemblance to Godot's dictionaries. A dictionary is a data type that contains values referenced by unique keys (and then it is equanimous of pairs of keys and values similar JSON). Y'all tin define a dictionary by placing a comma-separated list of fundamental: value pairs in curly braces {}, as we volition run across soon.

In Godot, some very convenient functions can be used to convert dictionaries direct into JSON strings and vice versa. Saving the game requires building a dictionary that contains data of all the entities in the game and then converting it to JSON format and saving information technology every bit a file.

The well-nigh convenient way to build this dictionary is for each object to exist able to create a "translation" of itself as a dictionary. This lexicon tin, in plough, exist used as a value within some other dictionary, thus creating a tree construction that can be converted into a single JSON file. So, we will provide each node that needs to exist saved with a to_dictionary() function that will handle this translation.

Listed beneath are all the scripts to exist modified and their corresponding functions to be added:

Player.gd

          func to_dictionary(): 	return { 		"position" : [position.x, position.y], 		"health" : health, 		"health_max" : health_max, 		"mana" : mana, 		"mana_max" : mana_max, 		"xp" : xp, 		"xp_next_level" : xp_next_level, 		"level" : level, 		"health_potions" : health_potions, 		"mana_potions" : mana_potions 	}        

The variable position is a Vector2, which is a Godot blazon that cannot exist converted direct to JSON. So, we volition store it as an array containing 2 elements (the x and y coordinates).

Fiona.gd

          func to_dictionary(): 	return { 		"quest_status" : quest_status, 		"necklace_found" : necklace_found 	}        

Skeleton.gd

          func to_dictionary(): 	return { 		"position" : [position.ten, position.y], 		"wellness" : health 	}        

SkeletonSpawner.gd

          func to_dictionary(): 	var skeletons = [] 	for node in get_children(): 		if node.name.find("Skeleton") >= 0: 			skeletons.suspend(node.to_dictionary()) 	render skeletons        

This function returns an array of dictionaries, each containing the information of a skeleton.

The last slice of information we want to relieve is if the ii potions present at the first of the game have already been taken or not. In this example, we don't demand to create the function to_dictionary(), but we will just check that the potions are present or non in the scene tree. But to distinguish these potions from those instantiated later, we must first rename them respectively to StartPotion1 and StartPotion2.

At this point, we are ready to write the code that actually saves the game.

Saving the game

Let's go to the SaveLoadGame.gd script and edit the salvage() function in this fashion:

          func save(): 	var information = { 		"thespian" : $Role player.to_dictionary(), 		"fiona" : $Fiona.to_dictionary(), 		"skeletons" : $SkeletonSpawner.to_dictionary(), 		"potion1" : is_instance_valid(get_node("/root/Root/StartPotion1")), 		"potion2" : is_instance_valid(get_node("/root/Root/StartPotion2")) 	} 	 	var file = File.new() 	file.open("user://savegame.json", File.WRITE) 	var json = to_json(data) 	file.store_line(json) 	file.close()        

Get-go, the function creates a dictionary called data, which contains some backdrop whose values are the dictionaries generated by the to_dictionary() functions we saw earlier.

For the two potions, we apply the is_instance_valid() function to find out if they are still valid nodes (and therefore still present in the game).

To relieve the file, we first create a new object of type File. Then we phone call the open() method, which requires two parameters: the path to the file to be opened and the opening way (in this case, we want to write to the file).

The file path uses the special path user://, which represents, in a platform-independent way, the location bachelor to the user to save files. The bodily location of this folder depends on the operating arrangement; for example, in Windows, it'southward %APPDATA%\Godot\app_userdata\Projection-Name, while in Linux is ~/.local/share/godot/Project-Proper noun.

The next line uses the to_json() function to catechumen the given lexicon into a string, which is saved in the json variable. So the file store_line() function is called to save the string inside the file.

Finally, we call the close() function to close the file and finish the operation.

If yous want to know more about how to use all the file system features in Godot, you can consult my Essential Guide to Godot Filesystem API.

Below yous can encounter an example of saved game in JSON format. I formatted the JSON file for reading convenience; information technology is actually saved as a single line.

          {    "fiona":{       "necklace_found":truthful,       "quest_status":2    },    "player":{       "health":100,       "health_max":100,       "health_potions":five,       "level":three,       "mana":104.221565,       "mana_max":200,       "mana_potions":3,       "position":[          256.913422,          90.034714       ],       "xp":250,       "xp_next_level":400    },    "potion1":false,    "potion2":imitation,    "skeletons":[       {          "health":100,          "position":[             43.824348,             353.437714          ]       },       {          "health":100,          "position":[             346.069458,             453.682861          ]       },       {          "health":100,          "position":[             300.874878,             483.28363          ]       },       {          "health":100,          "position":[             621.517029,             735.957458          ]       },       {          "wellness":100,          "position":[             579.305176,             753.475708          ]       },       {          "health":100,          "position":[             55.37022,             306.615692          ]       },       {          "health":100,          "position":[             614.484924,             237.107681          ]       },       {          "health":100,          "position":[             331.521759,             776.349609          ]       },       {          "health":100,          "position":[             685.134583,             241.07724          ]       },       {          "health":100,          "position":[             754.878662,             417.91452          ]       },       {          "health":100,          "position":[             323.712311,             456.731567          ]       },       {          "wellness":100,          "position":[             691.614624,             501.519104          ]       },       {          "wellness":100,          "position":[             747.091858,             733.033936          ]       },       {          "wellness":100,          "position":[             189.58287,             764.28302          ]       },       {          "health":100,          "position":[             641.547668,             570.008911          ]       }    ] }        

Loading the game from save file

To load the game from the save file, we'll have to do the opposite procedure to that seen previously, converting the JSON file into a lexicon, and using the latter to restore the values of the various nodes. To exercise this, we will create the from_dictionary() functions for each node that needs to exist loaded.

Listed below are all the scripts to be modified and their respective functions to be added:

Player.gd

          func from_dictionary(data): 	position = Vector2(data.position[0], data.position[1]) 	health = data.wellness 	health_max = data.health_max 	mana = data.mana 	mana_max = data.mana_max 	xp = information.xp 	xp_next_level = data.xp_next_level 	level = information.level 	health_potions = data.health_potions 	mana_potions = data.mana_potions        

Fiona.gd

          func from_dictionary(data): 	necklace_found = data.necklace_found 	quest_status = int(information.quest_status)        

Skeleton.gd

          func from_dictionary(data): 	position = Vector2(data.position[0], information.position[1]) 	wellness = data.wellness        

SkeletonSpawner.gd

          func from_dictionary(data): 	skeleton_count = data.size() 	for skeleton_data in information: 		var skeleton = skeleton_scene.instance() 		skeleton.from_dictionary(skeleton_data) 		add_child(skeleton) 		skeleton.get_node("Timer").start() 		 		# Connect Skeleton'due south death signal to the spawner 		skeleton.connect("expiry", self, "_on_Skeleton_death")        

When loading the game from a save file, skeletons do not have to be instantiated in the _ready() function similar when starting a new game. So, in SkeletonSpawner.gd, yous take to change the _ready() function similar this:

          ...  # Create skeletons if non get_parent().load_saved_game: 	for i in range(start_skeletons): 		instance_skeleton() 	skeleton_count = start_skeletons  ...        

The actual loading of the game volition accept identify in the _ready() function of SaveLoadGame.gd. Open the script and add the part:

          func _ready(): 	var file = File.new() 	if load_saved_game and file.file_exists("user://savegame.json"): 		file.open("user://savegame.json", File.READ) 		var data = parse_json(file.get_as_text()) 		file.shut() 		 		$Actor.from_dictionary(information.player) 		$Fiona.from_dictionary(information.fiona) 		$SkeletonSpawner.from_dictionary(data.skeletons) 		if($Fiona.necklace_found): 			$Necklace.queue_free() 		if(not data.potion1): 			$StartPotion1.queue_free() 		if(not data.potion2): 			$StartPotion2.queue_free()        

To load the game, the save file is opened for reading, the JSON string is read with the get_as_text() method and converted into a dictionary using the parse_json function. Side by side, we use the from_dictionary() functions to rebuild the state of the various nodes. Finally, we check some dictionary values to decide whether to remove the potions and Fiona's necklace from the scene tree.

And with this, nosotros have completed the saving and loading of the game!

Game Over screen

he final thing to do is to change the Game Over screen to take us back to the get-go screen when we press the Escape key.

Find the GameOver node and temporarily set its Modulate holding to (255,255,255,255) to make it visible. Indistinguishable its label and motion it down, then alter the text to Press ESC TO Render TO MAIN Card and center it horizontally.

Fix Modulate to (255,255,255,0) to hibernate it again.

Now open the MenuPopop.gd script and edit the _input() role similar this:

          func _input(consequence): 	if not visible: 		if Input.is_action_just_pressed("menu"): 			# If player is dead, get to offset screen 			if role player.health <= 0: 				get_node("/root/Root").queue_free() 				get_tree().change_scene("res://Scenes/StartScreen.tscn") 				get_tree().paused = false 				return 			# Pause game 			already_paused = get_tree().paused 			get_tree().paused = truthful 			# Reset the popup 			selected_menu = 0 			change_menu_color() 			# Show popup 			thespian.set_process_input(false) 			popup()  			...        

In this way, when the actor is expressionless, pressing the Escape key will bring us back to the showtime screen.

Conclusions

In this tutorial we learned:

  • how to switch from one scene to another, using both change_scene() and load();
  • how to gear up data for saving, using dictionaries and JSON format;
  • how to salve and load data to and from the file system, using the File form, to_json(), and parse_json().

You lot can effort what we've done so far past clicking here:

Did you lot savor this article? And then consider buying me a coffee! Your support will help me comprehend site expenses and pay writers to create new blog content.

erwinlefor1943.blogspot.com

Source: https://www.davidepesce.com/2020/07/31/godot-tutorial-19-start-menu-changing-scene-saving-loading-game/

0 Response to "If I Lose My Save Data for Lets Go Pikachu Can I Get Mew Again"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel