Skip to content

Space Shooter Tutorial

svntax edited this page Oct 1, 2021 · 14 revisions

Space Shooter Tutorial

This tutorial will show you how to use the NEAR SDK in an existing space shooter game.

Setup

  1. Clone the project from here: https://github.com/svntax/near-space-shooter
  2. Open the project using the C# Mono version of Godot 3.3.3.
  3. Have Godot generate the C# project files by adding a C# script (you can delete it afterwards). See here for more info.

You should now have a simple space shooter game working.

TODO screenshot here

Smart Contract Setup

TODO

The project already comes with the NEAR SDK, so the rest of the tutorial will be about implementation.

High Scores Screen

The game is missing a high scores screen, so let's add one. First, we can duplicate one of the existing buttons in the main menu, rename it, and set up a new function in MainMenu.gd for its pressed() signal.

TODO screenshot of new high scores button

Next, let's create a new scene for the high scores screen, name it HighScoresMenu, and save it in the root project folder, the same place where the main menu scene is saved. We'll also create a new script for it with the same name, which later on will handle fetching the high scores from NEAR.

TODO screenshot of new files for high score menu

Now we can go back to the MainMenu.gd script, and make the game change to this new scene when the high scores button is pressed. The script should now look something like the following:

extends Node2D

func _on_StartButton_pressed():
    get_tree().change_scene("res://Gameplay.tscn")

func _on_ExitButton_pressed():
    get_tree().quit()

func _on_HighScoresButton_pressed():
    get_tree().change_scene("res://HighScoresMenu.tscn")

We can start setting up the high scores menu by adding backgrounds, text labels, buttons, and other necessary UI elements. At this point, it's up to you how you want to set up the menu. As long as there's a button to go back and a table or container of some sort with rows for the high scores, the setup will work fine.

Here is how I'll be setting up the scene:

TODO screenshot of high scores menu with UI elements

I copied the background and header label from the main menu, added a button for going back to the main menu, and then added a new GridContainer node with 2 columns and two placeholder Label nodes for the player's name and score. These label nodes have their horizontal size flags set to Fill and Expand in order to make them take up the entire width of the column. The player label is left-aligned, and the score label is right-aligned.

Now we can start working on the high scores script. To start, we need to connect to the NEAR network. In our MainMenu.gd script, let's check if a connection exists, and if not, connect to the testnet.

extends Node2D

var config = {
    "network_id": "testnet",
    "node_url": "https://rpc.testnet.near.org",
    "wallet_url": "https://wallet.testnet.near.org",
}

func _ready():
    if Near.near_connection == null:
        Near.start_connection(config)

func _on_StartButton_pressed():
    get_tree().change_scene("res://Gameplay.tscn")

func _on_ExitButton_pressed():
    get_tree().quit()

func _on_HighScoresButton_pressed():
    get_tree().change_scene("res://HighScoresMenu.tscn")

Then in our high scores menu script, we'll call the getScores() method from our smart contract to retrieve the high scores. The return value will be a JSON string, which when parsed, will be an array of dictionaries, each with a username and value field. Our strategy here is to use the placeholder label nodes as templates by hiding them, duplicating them and setting their respective values for each score in the array, and at the end, add them to the grid container node.

The HighScoresMenu.gd script should now look something like the following, including a new function for the back button:

extends Node2D

const CONTRACT_NAME = "name of your smart contract here"

onready var scores_grid = $ScoresGrid
onready var player_name_label = $ScoresGrid/PlayerName
onready var player_score_label = $ScoresGrid/PlayerScore

func _ready():
    # First, hide the placeholder labels
    player_name_label.hide()
    player_score_label.hide()
    
    # Next, fetch the high scores and create new labels for each score
    var result = Near.call_view_method(CONTRACT_NAME, "getScores")
    if result is GDScriptFunctionState:
        result = yield(result, "completed")
	if result.has("error"):
            pass # Error handling here
    else:
        var data = result.data
        var json_data = JSON.parse(data)
        var high_scores: Array = json_data.result
        for score in high_scores:
            var name_label = player_name_label.duplicate()
            name_label.set_text(score.username)
            scores_grid.add_child(name_label)
            name_label.show()

            var score_label = player_score_label.duplicate()
            score_label.set_text(str(score.value))
            scores_grid.add_child(score_label)
            score_label.show()

func _on_BackButton_pressed():
    get_tree().change_scene("res://MainMenu.tscn")

Now when you run the game and go to the high scores screen, you should see something like this:

TODO screenshot of high scores after being fetched

NEAR Wallet Login

TODO

Submitting Your Score

TODO

Clone this wiki locally