How to Make a Google Chrome T-Rex Style Sidescroller In Godot | Beginner Tutorial

How to Make a Google Chrome T-Rex Style Sidescroller In Godot | Beginner Tutorial

Creating a Chrome T-Rex Game in GDO

Overview of Game Mechanics

  • The speaker discusses their version of the Chrome T-Rex game, highlighting three main mechanics: parallax scrolling background, physics for jumping, and obstacle spawning with collision detection.

Implementing Parallax Background

  • The parallax background is created by layering images that move at different speeds to simulate depth. The furthest layer moves slowest while the nearest moves fastest.
  • A new scene is initiated with a parallax background node named "BG." A solid green image is added as the first layer using a Sprite 2D node.
  • Additional child nodes are created for each parallax layer, ensuring they have their own Sprite 2D nodes to contain respective images.
  • Mirroring is applied to create an infinite scrolling effect; the width of the image (1152 pixels) is used in the mirroring property.
  • Each layer's speed is adjusted by increasing motion scale values incrementally from 0.6 to 0.9 for layers closer to the viewer.

Setting Up Dinosaur Scene and Physics

  • The dinosaur character uses a CharacterBody2D node for user control, along with animated sprites and collision shapes for running and ducking actions.
  • An audio stream player node is included to play sound effects during gameplay. Configuration begins on various nodes while addressing warning signs in setup.

Configuring Animated Sprites

  • The animated sprite node provides visual representation through animation frames. A new set of sprite frames must be created within this node.
  • Various animations are defined including idle, running, jumping, taking damage, and ducking; however, not all frames will be utilized in gameplay.

Animation Setup Process

  • For jumping animation, only one frame will be used instead of multiple frames typically associated with other actions like taking damage or ducking down.
  • Idle animation setup involves selecting specific frames from a sprite sheet located in the assets folder; adjustments are made based on frame organization (4 rows x 4 columns).

Finalizing Animation Appearance

  • After adding selected frames into the idle animation sequence, scaling adjustments are made at the parent node level to enhance visibility without losing quality by changing texture filtering settings.

This structured approach captures key insights from creating a game using GDO while providing timestamps for easy reference back to specific parts of the discussion.

Animation Setup and Game Mechanics

Configuring Animation Speed

  • The animation speed is adjusted to 10 frames per second, doubling the playback speed for smoother transitions.
  • The idle animation is set to autoplay at the game's start, ensuring a seamless introduction to the character's state.

Collision Shapes Configuration

  • Two collision shapes are created: one for running and another for ducking. The first shape captures the character's body from feet to stomach.
  • The second collision shape is adjusted based on the new head position when ducking, allowing for accurate hit detection during gameplay.

Sound Effects Integration

  • A jump sound effect is added with volume reduced to -25 dB to prevent it from being disruptive during gameplay.

Ground Scene Creation

  • A new scene is established for the ground where a static body node holds an image of "ground.png," positioned at the bottom of the game window.
  • The ground image must be twice as wide as the game window due to manual parallax scrolling implemented through code.

Main Scene Assembly

  • A main scene is created that incorporates previously designed elements: background, ground, and dinosaur.
  • A Camera2D node follows the player across the map; its position is adjusted to align perfectly with half of both screen dimensions.

Testing and Adjustments

  • Initial testing reveals successful integration of animations and backgrounds; however, proper layering ensures that obstacles do not obscure character visibility.
  • To maintain visibility over other nodes, the dinosaur's Z index is set higher so it always appears in front during gameplay.

Player Controls Implementation

  • A script extending CharacterBody2D adds jumping mechanics by defining upward force (jump speed) and downward force (gravity), essential for player movement dynamics.

Implementing Physics and Animations in a Dinosaur Game

Applying Forces and Jump Mechanics

  • The dinosaur's vertical velocity is increased by gravity within a physics process function, allowing for realistic jumping mechanics when the space bar is pressed.
  • A jump sound effect is played upon jumping; however, it can become repetitive, leading to its temporary deactivation during testing.
  • To prevent continuous jumping while holding the space bar, a check for whether the player is on the ground is implemented using is_on_floor.
  • An L statement is added to switch animations: if not on the ground, the animation changes to "jumping"; otherwise, it remains "running."

Animation States and Collision Handling

  • The game now correctly transitions between running, jumping, and ducking animations based on player input (down key for ducking).
  • Collision shapes are toggled based on actions: running collision shape is disabled when ducking. This visual feedback helps players understand active states.

Creating Obstacles

  • Obstacles are created as Area2D nodes with Sprite2D children; initial focus is on creating a stump obstacle with appropriate scaling and collision shapes.
  • The stump image's scale is adjusted to eliminate blurriness by changing texture filtering settings. A polygon collision shape captures its outer limits.

Additional Obstacles Configuration

  • Other obstacles like barrels and rocks are similarly configured; specific adjustments include using rectangular collision shapes for square objects.
  • For animated obstacles like birds, an AnimatedSprite node with flying animation frames at 10 FPS is set up alongside custom collision shapes.

Finalizing Motion Script

  • After configuring obstacles, attention shifts back to the main scene where a new script for motion will be defined with constants at the top of the code.

Creating a 2D Dinosaur Game

Setting Up the Game Environment

  • The initial setup involves defining the starting position for both the dinosaur and the 2D camera node, along with speed variables to control movement across the screen.
  • A new game function is created to reset all elements back to their starting coordinates, including the dinosaur's position, speed, camera position, and ground position.

Implementing Game Logic

  • The game logic is executed within a process function where the start speed is assigned to a current speed variable that moves both the dinosaur and camera rightward by increasing their x-coordinates.
  • To prevent the dinosaur from falling off-screen, an additional variable for screen size is defined. This helps in tracking how far everything has scrolled.

Ground Movement Mechanics

  • A check ensures that if the camera's x-position exceeds 1.5 times the screen size, it triggers repositioning of the ground to create an infinite scrolling effect.
  • When repositioning occurs, it effectively shifts ground back into view as soon as its right edge aligns with the screen's right edge.

Scoring System Development

  • A score variable is introduced to track points earned while running; this resets alongside other nodes when starting a new game.
  • The score updates based on current speed and prints out during gameplay for testing purposes.

Displaying Score on Screen

  • To improve user experience, a heads-up display (HUD) is created using a canvas layer node that will always be visible above other elements.
  • Labels are added for displaying scores and instructions; temporary text placeholders are set up initially before finalizing design aspects like font size and alignment.

Finalizing HUD Elements

  • Additional labels are suggested for high scores and gameplay instructions ("press space to play"), ensuring they follow similar formatting principles as score labels.
  • After saving changes in HUD design, integration into main script allows real-time updating of displayed scores during gameplay.

Linking Score Functionality

  • A function called showcore is defined to update score text dynamically; linking this functionality requires accessing specific nodes within HUD structure.
  • The score label’s text property gets updated with current score values converted from integers to strings for proper display.

Game Development: Enhancing Gameplay Mechanics

Modifying Score Display and Game Start Conditions

  • Introduced a new variable score_mod_modifier to adjust the score display, dividing the score by 10 for a more reasonable rate of increase.
  • Created a game_running variable to control when the game starts, ensuring it only begins after player input (space bar press).
  • Implemented logic to execute game code only if game_running is true; otherwise, it waits for player input.
  • Added functionality to hide the start label upon pressing space, enhancing user experience at game initiation.
  • Ensured that the score updates correctly by calling the update function right after resetting nodes.

Animation States and Game Speed Adjustments

  • Fixed initial score display issue by running the show score function at game start to reflect current scores accurately.
  • Modified dinosaur animation states based on game_running, allowing it to start in an idle state until gameplay begins.
  • Updated speed mechanics within the process function, linking speed increases directly to player scores while defining a speed modifier variable for clarity.
  • Established maximum speed limits using previously defined variables to prevent gameplay from becoming unmanageable as speeds increase with scores.

Generating Obstacles in Code

  • Preloaded obstacle scenes into variables at the top of the script for efficient management during gameplay.
  • Grouped obstacles into an array for easier handling but excluded birds due to their unique generation and behavior characteristics.

Game Development: Generating Obstacles

Defining Variables for Bird and Obstacles

  • A new array is defined to specify the heights at which birds will spawn, introducing variety in gameplay by allowing birds to appear either high up or just above the player.
  • The variable lastOBS is introduced to track the last obstacle created, setting the stage for generating obstacles in a separate function.

Creating Obstacle Generation Function

  • The function generateObstacles is established to handle obstacle creation, called within the main process function after adjusting the score.
  • Ground obstacles are designed with unique logic compared to airborne ones; an initial obstacle is created immediately when the game starts if no obstacles exist.

Randomizing Obstacle Types

  • To add variety, one of three pre-defined obstacle types (excluding birds) is randomly selected for generation each time an obstacle is created.
  • After creating an instance of an obstacle type, it’s stored in both lastObstacle and added as a child node in the main scene while also being included in the obstacles array.

Positioning Obstacles Correctly

  • Proper positioning requires knowledge of both ground height and individual obstacle height; properties from nodes are accessed to gather necessary data.
  • The height of each obstacle's sprite texture and its scale must be considered since they may not be uniformly scaled across different images.

Calculating Coordinates for Obstacles

  • The Y-coordinate for positioning involves subtracting ground height from screen height, ensuring that obstacles sit correctly above ground level.
  • For X-coordinates, calculations include screen width plus score with a buffer added so that obstacles enter smoothly rather than abruptly appearing on-screen.

Refactoring Code for Clarity

  • A new function named addObstacle is created to streamline code organization by encapsulating position assignment logic into this reusable method.
  • To generate multiple obstacles instead of just one, conditions are adjusted. An additional check ensures that new obstacles can spawn based on the position of existing ones rather than relying solely on whether the array is empty.

Obstacle Generation and Difficulty Adjustment in Game Development

Implementing Randomized Obstacles

  • The introduction of a random range (300 to 500) for obstacle generation prevents fixed intervals, adding variability to the game.
  • A new variable, maxObstacles, is created and set to three, allowing for clusters of obstacles instead of single items.
  • Code indentation within a for loop is necessary to space out obstacles; without it, multiple obstacles align at the same position.

Scaling Difficulty with Gameplay Progression

  • The initial number of obstacles starts at one and increases as difficulty rises, enhancing gameplay challenge.
  • Two variables are introduced: currentDifficulty and maxDifficulty, which control how difficulty scales with player progress.
  • An adjustDifficulty function is implemented to modify difficulty based on score while ensuring it does not exceed maximum limits.

Dynamic Obstacle Generation Based on Difficulty

  • The maximum number of obstacles generated can now be linked directly to the current difficulty level plus one, creating more dynamic gameplay experiences.
  • Testing shows that initially only one obstacle appears; as scores increase past certain thresholds (e.g., 500), the number of obstacles varies between one and three.

Introducing Bird Obstacles

  • A random chance mechanism is added for generating bird obstacles once maximum difficulty is reached, introducing an additional layer of challenge.
  • Birds will spawn based on a 50/50 chance determined by dividing a random number by two, similar to stationary obstacles' logic.

Enhancing Bird Movement Mechanics

  • The bird's x-coordinate is defined using screen width and current score with an added buffer for entry from the right side.
  • Y-coordinates are randomized from a predefined array representing different heights where birds can appear during gameplay.
  • To test bird generation effectively, checks against max difficulty are temporarily disabled; this allows observation of their spawning behavior.

Final Adjustments for Natural Movement

  • Birds require movement code in their script so they do not remain static. This involves adjusting their position based on speed variables from the main game node.
  • By controlling bird speed relative to player movement speed, birds exhibit natural motion across the screen rather than appearing frozen in place.

Game Development: Managing Obstacles and Collision Detection

Cleaning Up Off-Screen Obstacles

  • The game retains off-screen obstacles in memory, which can lead to performance issues. A cleanup process is necessary to remove these items as they exit the screen.
  • An iteration through the obstacles array is implemented to check each obstacle's x-coordinate against the camera's position, identifying those that have moved off-screen for removal.

Implementing Obstacle Removal

  • A custom function named remove_obstacle is created to handle the deletion of obstacles from both the scene and the obstacles array, ensuring efficient memory management.
  • The function utilizes Q free to remove the node from the main scene while also erasing it from the array, streamlining obstacle generation.

Setting Up Collision Detection

  • Collision detection is introduced by utilizing an Area2D node for obstacles (e.g., a stump), which emits a signal when another body enters its defined area.
  • The signal emitted upon collision must be filtered to ensure only relevant objects (like the player character) trigger responses.

Connecting Signals and Handling Collisions

  • In the add_obstacles function, a connection is established between newly created obstacle nodes and their collision signals, linking them to a new handler function called hit_obstacle.
  • The hit_obstacle function checks if a colliding body matches the player's name property (e.g., "Dino"), allowing for specific collision handling based on object identity.

Game Over Logic Implementation

  • Upon detecting a collision with an obstacle, a message indicating "collision" is printed. This triggers further development of game over functionality.
  • A new function named game_over pauses gameplay and sets a variable indicating that the game has stopped running when collisions occur.

Creating and Integrating Game Over Scene

  • A game over scene featuring a restart button is designed using canvas layers. Button properties such as size and font are adjusted for visual clarity.
  • The game over scene is instantiated within the main scene but initially hidden; it will be displayed upon triggering a game-over condition during gameplay.

Game Development: Implementing Restart Functionality

Connecting Button Signals

  • The button for restarting the game is not functioning because it isn't connected to the node. Each button has its own signals, and the relevant one here is the "button press" signal.

Triggering New Game Function

  • The new game function needs to be triggered in two scenarios: when starting a new game and when a game over condition occurs. This ensures that pressing the restart button resets everything.

Handling Game Pause State

  • The entire game is paused during gameplay, which affects functionality. To resolve this, change the mode of the game over scene to operate only when paused.

Resetting Game Elements

  • After clicking restart, it's essential to unpause the game before resetting elements like difficulty. This allows players to start fresh after a game over.

Managing Obstacles on Restart

  • Obstacles are not resetting upon restarting; they remain from previous runs. To fix this, iterate through the obstacles array and clean up each node before clearing it entirely.

Enhancing Gameplay Experience

Randomizing Obstacle Generation

  • There was an issue with birds appearing consistently upon restarts due to commented-out code affecting their generation. Ensure birds are generated based on maximum difficulty reached.

Implementing High Score Tracking

  • A high score variable needs creation at the top of the script. A function will check if current scores exceed previous high scores and update accordingly.

Updating High Score Display

  • When updating high scores, ensure that both score comparison and label updates occur within heads-up display nodes for accurate representation during gameplay.

Final Testing of Features

  • Upon testing, high scores should reflect accurately after dying or restarting. For instance, achieving higher scores updates displayed high scores correctly as intended.
Video description

Learn the basics of Godot by making a side scroller game from scratch. The code for the game is built from scratch and will re-create all the features of the t-rex game. This will use a parallax background node to create the scrolling background with a 3D effect. I'll have a spawner to generate enemies as well as collision detection. Complete project files for this video: https://www.patreon.com/posts/godot-dino-run-143421927 Assets used: https://github.com/russs123/dino-run-assets Credits for assets: background - https://jesse-m.itch.io/jungle-pack dinos - https://arks.itch.io/dino-characters obstacles - https://free-game-assets.itch.io/free-swamp-2d-tileset-pixel-art font - https://www.dafont.com/retro-gaming.font sound - https://freesound.org/people/MATRIXXX_/sounds/458641/ Timestamps: 0:00 Intro 0:23 Parallax Background 3:15 Dinosaur 08:15 Scrolling Ground 14:22 Obstacle Scenes 17:02 Writing Code 20:30 Heads Up Display 27:25 Obstacle Spawner 41:30 Collision Detection 44:10 Game Over Scene 48:02 High Score