Learn Godot 4 by Making a 2D Platformer — Part 24: Project Testing, Export, & Conclusion
Tags: gamedev, beginners, tutorial, programming
Published: 2023-08-12 03:01:00

**You can find the links to the previous parts at the bottom of this tutorial.*

Congratulations on making it to the end of our 2D Platformer tutorial! Your persistence throughout this series is impressive, and it will with no doubt come in handy later on in your game dev journey. With our game created, you need to go back and test it to make sure that it is as bug-free as possible.

---

***WHAT YOU WILL LEARN IN THIS PART:***

* *Basic game testing.*
* *Project exporting.*

---

For this, you need to delve into the world of gameplay testing. Since this is a small-scale game, we’ll focus on the aspects of manual testing, which includes testing the game’s mechanics by playing it and trying to break it.

**Here’s a general guideline for manual testing:**

 1. **Gameplay Mechanics**: This involves testing all of the game’s mechanics to ensure they work correctly. In our game, the mechanics to test would include moving and jumping, climbing ladders, breaking obstacles, and the ability to win and lose the game. The interaction of the player’s character with enemies (e.g., bomb spawner and box spawner) should also be tested. Are they colliding properly? Do the animations play correctly? Make sure to separate each factor of the game into a checklist which you can then test individually.

 2. **Levels**: Each level should be tested thoroughly. This includes testing all pathways, making sure the player can reach the end, jump over obstacles with enough space, and that they can’t accidentally get out of bounds. The placement of spawners, ladders, pickups, and other obstacles should be checked.

 3. **User Interface (UI) and Controls**: You should test that the game’s controls work correctly, and that the UI displays the right information. For example, you might check that the number of lives is displayed correctly and that it decreases when you lose a life.

 4. **Difficulty and Progression**: Check that the game gets harder as you progress through the levels. For example, more spawners and moving platforms are introduced in later levels. Make sure that this progression feels fair and balanced.

 5. **Audio and Visuals**: Test the game’s sound effects, music, and graphics. This would involve testing things like the sounds of picking up items, jumping, and breaking obstacles, as well as the animations for these actions.

 6. **Performance**: Check the game’s performance. It should run smoothly without lagging or stuttering, even when there are lots of obstacles on the screen.

 7. **Bugs and Glitches**: Play the game while actively trying to cause bugs and glitches. This might involve things like trying to move into walls, pausing and unpausing the game, or trying to interact with objects in unexpected ways.

 8. **Edge Cases**: Test unusual or extreme situations. For example, what happens if the player doesn’t move at all? What if they try to climb a ladder while a bomb is rolling down it?

 9. **Player Experience**: Lastly, test the overall player experience. Is the game fun to play? Are there any frustrating parts? This will be subjective, so it can be useful to get multiple people to playtest the game.

When I tested my game, I encountered two bugs that needed fixing. There could be more, but I just did a light playthrough to test all the items above. The first bug was my player’s particle effects playing when in the ladder scene’s collision.
```python
    ### Player.gd
    
    #older code
    
    #singular input captures
    func _input(event):
                
        #on climbing ladders
        if Global.is_climbing == true:
            if !Input.is_anything_pressed():
                $AnimatedSprite2D.play("idle")
                $Effects/RunningParticles.emitting = false
            if Input.is_action_pressed("ui_up"):
                $AnimatedSprite2D.play("climb") 
                gravity = 100
                velocity.y = -160
                Global.is_jumping = true
                $Music/JumpSFX.play()
```
The other one was my animation being stuck if my player collides with a bomb or a box whilst climbing.
```python
    ### Box.gd
    
    #older code
    
    func _on_body_entered(body):
        # If the bomb collides with the player, play the explosion animation and disable spawning
        if body.name == "Player":
            $AnimatedSprite2D.play("explode")
            # Disable spawning in BoxSpawner
            Global.disable_spawning()
            #deal damage
            if Global.can_hurt == true:
                body.take_damage()
                Global.is_climbing = false
                Global.is_jumping = false
```
```python
    ### Bomb.gd
    
    #older code
    func _on_body_entered(body):
        #if the bomb collides with the player, play the explosion animation and start the timer
        if body.name == "Player":
            $AnimatedSprite2D.play("explode")
            $Timer.start()
            Global.is_bomb_moving = false
            #deal damage
            if Global.can_hurt == true:
                body.take_damage()
                Global.is_climbing = false
                Global.is_jumping = false
```
I also fixed the timer that was starting before you closed the Instructions node. This occurred because we set the timer at the top of the code, instead of in certain execution blocks — so it would always run first.
```python
    ### Player.gd
    
    #older code
    
    #time we started the level
    var level_start_time 
    
    func _ready():
        #older code
        
        #show instructions
        if Global.get_current_level_number() == 1:
            #stop processing
            set_process(false)
            $Instructions.visible = true
        else:
            level_start_time = Time.get_ticks_msec()
            
        #play background music
        $Music/BackgroundMusic.play()
    
        
    #hide popup
    func _on_accept_button_pressed():
        #hide popup
        $Instructions.visible = false
        #unpause game
        get_tree().paused = false
        set_process(true) 
        level_start_time = Time.get_ticks_msec()
```
I also removed all the print statements that I added throughout my game for testing purposes, as this is no longer needed. I also checked my Errors panel to fix any errors that arose. We got a notification that our max_lives variable is never used, so I removed it. Leave the errors related to the ‘delta’ issue, as your process functions require the parameter by default.

![Godot 2D Platformer](https://cdn-images-1.medium.com/max/2000/1*Fwb1FAv3iX2r9Q6_pVX4_w.png)

The final code can be found [here](https://github.com/christinec-dev/CastleClimbersParts/tree/main/Part24).

You can also use the [Profiler](https://docs.godotengine.org/en/stable/tutorials/scripting/debug/the_profiler.html) below to monitor your game’s performance when you run it. This helps you measure your code according to the performance measurements of your frame time, physics frame, idle time, and physics time. This helps you identify which functions need optimization.

![Godot 2D Platformer](https://cdn-images-1.medium.com/max/2452/1*XMolJ74a96qKrnYDmh1kcA.png)

After you’ve tested your game, and you are satisfied with your fixes, you can then go ahead and [export ](https://docs.godotengine.org/en/stable/tutorials/export/exporting_projects.html)the project. Open up your Project Settings > Export window.

![Godot 2D Platformer](https://cdn-images-1.medium.com/max/2000/1*MJKFjwsfD3TaeiFORuf_0g.png)

This will open up the Export Window, which will be empty since we do not have any export presets added. This is the basic template that Godot will use to export our project to certain platforms. To create an export preset, click the **Add…** button at the top of the export menu. This will open a drop-down list of platforms to choose from for an export preset. Select the “Windows Desktop” option since our game will be made for desktops.

![Godot 2D Platformer](https://cdn-images-1.medium.com/max/2000/1*3XHB5pyUMHru2N2u0aK0yQ.png)

Once it’s done, you’ll see that your preset has been added. The default options are often fine to export, so tweaking them is usually not necessary. Additionally, Godot needs export templates installed to create packages. The export menu will complain when something is missing and will not allow the user to export for that platform until they resolve it.

![Godot 2D Platformer](https://cdn-images-1.medium.com/max/2000/1*XKEOTAHFWh3tD_6wDMtWuw.png)

![Godot 2D Platformer](https://cdn-images-1.medium.com/max/2116/1*xPunLgt5wEAxC853PhXj8g.png)

For this, select the “Manage Exports” option to install the latest template.

![Godot 2D Platformer](https://cdn-images-1.medium.com/max/2000/1*CdPgfPnsdDNqVmXfa2Q6Bw.png)

Enter your project’s name and choose its save location underneath the “Export Path”.

![Godot 2D Platformer](https://cdn-images-1.medium.com/max/2000/1*GgRAzZ8QDyK9e8qdrrF5oQ.png)

Then select the “Export Project” option.

![Godot 2D Platformer](https://cdn-images-1.medium.com/max/2000/1*xWGYgbOZCK7qPoELy2JgnQ.png)

Now when you navigate to the directory where you exported it, your game should be there in .exe format! You can now play and share it as much as you’d like.

![Godot 2D Platformer](https://cdn-images-1.medium.com/max/2000/1*Ya1u7IOfwAEbdP5FpujOtw.png)

![Godot 2D Platformer](https://cdn-images-1.medium.com/max/3840/1*F7INZoNdZyYjXQ8DBeI6xg.png)

![Godot 2D Platformer](https://cdn-images-1.medium.com/max/3840/1*dihhBJPwsYwFxRXoM0fjmg.png)

And there you have it! You have finally completed your Castle Climber 2D Platformer game. Give yourself a pat on the back, because this was a lot of work, and it takes effort to get up every day just and learn. Now would be a great time to back up your project one last time — and then, take a break!

I’d appreciate it if you would give me feedback on this tutorial series, as I need to know if you found it valuable, and where I could improve. I work hard on these series, but I know there’s always room for improvement. I’ll see you again in the future (hopefully) with more tutorials. By the time you’re reading this, I’ll be busy making more advanced series on inventory systems and quest systems. Thank you for supporting this series and following along this journey, and good luck with whatever awaits you from here on out!

---

## Previous Parts to the Tutorial Series

The tutorial series has 24 chapters. I’ll be posting all of the chapters in sectional daily parts over the next couple of weeks. You can find the updated list of the tutorial links for all 24 parts of this series on my [GitBook](https://oops-i-devd.gitbook.io/christinedevs/godot-tutorials/castle-climbers/tutorial). If you don’t see a link added to a part yet, then that means that it hasn’t been posted yet. Also, if there are any future [updates ](https://oops-i-devd.gitbook.io/christinedevs/communication/updates-and-notifications)to the series, my GitBook would be the place where you can keep up-to-date with everything!

![Godot 2D Platformer](https://cdn-images-1.medium.com/max/2000/0*TLFhoNqnjMYLWAGA.png)

---

## Support the Series!

If you like this series and would like to support me, you could [donate](https://ko-fi.com/christinedevs) any amount to my KoFi shop or you could [purchase the offline PDF](https://ko-fi.com/s/75433f1d4b) that has the entire series in one on-the-go booklet!

The booklet gives you lifelong access to the full, offline version of the “**Learn Godot 4 by Making a 2D Platformer**” PDF booklet. This is a 451-page document that contains all the tutorials of this series in a sequenced format, plus you get dedicated help from me if you ever get stuck or need advice. This means you don’t have to wait for me to release the next part of the tutorial series on Dev.to or Medium. You can just move on and continue the tutorial at your own pace — anytime and anywhere!

![Godot 2D Platformer](https://cdn-images-1.medium.com/max/2000/0*S6n1i41QDrVlLJUy.png)

*This book will be updated continuously to fix newly discovered bugs, or to fix compatibility issues with newer versions of Godot 4.*