Platformer Player

Player Movement

The Player character will be controlled via standard platformer keybindings: the 'A' key moves the player left, the 'D' key moves them right, and the Spacebar initiates a jump, but only when the player is currently grounded. Additionally, gravity will constantly affect the player's movement.

game/player.h
#pragma once

#include <SFML/Audio/Sound.hpp> // Add: Include Sound.
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Sprite.hpp>

#include "engine/app.h"
#include "engine/tilemap.h" // Add: Include Tilemap.

namespace game {

class Player {
 public:
  Player(ng::App* app, const ng::Tilemap* tilemap); // Change: Add tilemap parameter and remove explicit keyword.

  void Update();
  void Draw(sf::RenderTarget& target);

 private:
  ng::App* app_ = nullptr;
  const ng::Tilemap* tilemap_ = nullptr; // Add: tilemap pointer.
  sf::Sprite sprite_;
  sf::Vector2f player_velocity_; // Add: current player velocity.
  bool is_on_ground_ = false; // Add: is the player on the ground?
  sf::Sound jump_sound_; // Add: sound played when jumping.
};

}  // namespace game

The ResourceManager still doesn't implement sound loading. The next page in the guide addresses that aspect.

Player Collision with Tilemap

The Tilemap represents the game world, requiring the Player to interact with it and be stopped by solid tiles like the ground and walls. The player's movement system computes the next position and validates it by checking if all four corners of the player's collision box are clear of solid tiles. Collision checks are performed per side, and if a solid tile is hit, the player's new position is adjusted (clamped) to prevent passing through. Attempting to move outside the tilemap boundaries results in the player's movement being frozen, indicating a fall off the map (player death and losing will be added later). Once any necessary collision resolution is complete, the player's sprite is moved to the validated position.

Note that before we said that we only check the 4 corners of the player's box. That would lead to a curious bug, because the player's collision square (32x48) is larger than the tile size (32x32). If we only check the 4 corners of the player, the player could technically walk through a 1-tile-tall wall because the collision steps are done every 24 pixels of height, and the checks wouldn't catch it. The solution is to add 2 new checks in the middle of the player, one on the left and one on the right, making them 6 checks in total.

Last updated