Get Started Now

Intro to C++ Programming

Starting from the fundamentals, become a C++ software engineer, step by step.

LATEST UPDATES

Screenshot from Cyberpunk 2077
Module One

Intro to C++ Programming

Starting from the basics, become a C++ software engineer, step by step

Screenshot from Cyberpunk 2077
Screenshot from The Witcher 3: Wild Hunt
Screenshot from Warhammer: Total War
Screenshot from Cyberpunk 2077
Capstone Project

Building Minesweeper with C++ and SDL2

Apply what we learned to build an interactive, portfolio-ready capstone project using C++ and the SDL2 library

Screenshot from Cyberpunk 2077
Screenshot from The Witcher 3: Wild Hunt
Screenshot from Warhammer: Total War
Screenshot from Cyberpunk 2077
Module Two

Professional C++

Learn C++ and SDL development by recreating classic retro games

Screenshot from Cyberpunk 2077
Screenshot from The Witcher 3: Wild Hunt
Screenshot from Warhammer: Total War
MOST POPULAR

Ticking

Using Tick() functions to update game objects independently of events
Abstract art representing computer programming
Ryan McCombe
Published

In our previous projects, we’ve updated the state of our objects based on events detected in our application loop:

// Application Loop
while (shouldContinue) {
  // Handle Events
  while (SDL_PollEvent(&Event)) {
    if (Event.type == SDL_QUIT) {
      shouldContinue = false;
    }
    GameObject.HandleEvent(Event);
  }
    
  // Render Objects
  GameWindow.Render();
  GameObject.Render(GameWindow.GetSurface());
    
  // Update Frame
  GameWindow.Update();
}

However, in more complex projects, most objects may need to update their state consistently, even when they’re not receiving any events. For example, characters not controlled by our player may need to continue to act and move, and animation, and visual effects should continue to update.

Writing Data to Files

Learn to write and append data to files using SDL2's I/O functions.
Abstract art representing computer programming
Ryan McCombe
Published

In this lesson, we’ll introduce how to write data from our program to external sources. We’ll focus on writing to files for now, but the techniques we cover lay the foundations for working with other data streams, such as network traffic.

As we might expect, SDL’s mechanism for writing data shares much in common with their API for reading data. We’ll rely on SDL_RWops objects, and the functions we use will be familiar to what we learned in the previous lesson.

Like before, we’ll start with a basic main function that initializes SDL, and calls Write() and Read() functions within an included File namespace.

// main.cpp
#include <SDL.h>
#include "File.h"

int main(int argc, char** argv) {
  SDL_Init(0);
  File::Write("output.txt");
  File::Read("output.txt");
  return 0;
}

Our Read() function logs out the file’s contents, using techniques we covered in the previous lesson. In this lesson, we’ll work on the Write() function, which is currently empty:

// File.h
#pragma once
#include <iostream>
#include <SDL.h>

namespace File {
  void Read(const std::string& Path) {
    char* Content{static_cast<char*>(
      SDL_LoadFile(Path.c_str(), nullptr)
    )};
    
    if (Content) {
      std::cout << "Content: " << Content;
    } else {
      std::cout << "Error loading file: "
        << SDL_GetError();
    }
    
    SDL_free(Content);
  }
  
  void Write(const std::string& Path) {
    // ...
  }

}

Running our program, we should see an error output from our Read() function, as it’s trying to read a file that we haven’t created yet:

Error loading file: Parameter 'src' is invalid

Managing Memory Manually

Learn the techniques and pitfalls of manual memory management in C++
Abstract art representing computer programming
Ryan McCombe
Published

Throughout this chapter, we’ve started to take more proactive control over the memory used in our programs, and controlling the lifecycle of objects (when they’re created, and when they’re destroyed)

We’ve used standard library utilities like std::unique_ptr and std::vector to help with this. In this lesson, we’ll learn how to take full control by manually managing our object lifecycles.

We’ll also see how this can be difficult, dangerous, and something to avoid where possible.

However, avoiding it is not always an option. In larger projects, we’ll interact with libraries or other systems that implement manual memory management, and understanding the techniques involved and problems to avoid will be extremely useful.

Copy Constructors and Operators

Explore advanced techniques for managing object copying and resource allocation
Abstract art representing computer programming
Ryan McCombe
Updated
Published

In this lesson, we’ll explore how objects are copied in more depth. There are two scenarios where our objects get copied. The first is when a new object is created by passing an existing object of the same type to the constructor:

struct Weapon{/*...*/};

int main() {
  Weapon SwordA;
  
  // Create SwordB by copying SwordA
  Weapon SwordB{SwordA};
}

This copying process also happens when we pass an argument by value to a function. The function parameter is created by copying the object provided as the corresponding argument:

struct Weapon{/*...*/};

void SomeFunction(Weapon W) {/*...*/}

int main() {
  Weapon Sword;
  
  // Create the W parameter by copying Sword
  SomeFunction(Sword);
}

The second scenario is when an existing object is provided as the right operand to the = operator. In the following example, we’re expecting an existing PlayerTwo to be updated by copying values from PlayerOne:

struct Weapon{/*...*/};

int main() {
  Weapon SwordA;
  Weapon SwordB;
  
  // Update SwordA by copying values from SwordB
  SwordA = SwordB;
}

As we’ve likely noticed, C++ supports these behaviors by default, even when the objects we’re copying use our custom types. In this lesson, we’ll explore what that default behavior does, and learn how to override it when our classes and structs have more complex requirements.

Dynamic Arrays using std::vector

Explore the fundamentals of dynamic arrays with an introduction to std::vector
Abstract art representing computer programming
Ryan McCombe
Updated
Published

Inevitably, we will want to store a group of related objects. That might be a collection of characters in a party, a collection of buttons on a UI, or countless other use cases.

Let's imagine we have these objects, which we want to store and manage as a single collection:

class Character {};
Character Frodo;
Character Gandalf;
Character Gimli;
Character Legolas;
Character Aragorn;

Programmers have invented a huge range of options for storing collections of objects. These containers are broadly called data structures, and which data structure we should use depends on our specific requirements. We’ll cover a much wider range of data structures in the next course. Here, we’ll introduce the most common choice - the dynamic array.

Under the hood, arrays are contiguous blocks of memory, big enough to store multiple objects in sequence.

Reading Data from Files

Learn how to read and parse game data stored in external files using SDL_RWops
Abstract art representing computer programming
Ryan McCombe
Published

In this chapter, we’ll introduce read/write operations, specifically using SDL_RWops. This is the API that SDL provides for reading from and writing to files on our players’ hard drives.

Many of the topics covered here additionally lay the foundation for more advanced capabilities. Streaming data to and from files has much in common with streaming data over a network, for example, which is fundamental for creating multiplayer games.

In this lesson, we’ll create a basic SDL application that calls Write() and then Read() within a File namespace we’ll create. The file I/O system is initialized by default, so we can simply pass 0 as the initialization flag to SDL_Init():

#include <SDL.h>
#include "File.h"

int main(int argc, char** argv) {
  SDL_Init(0);
  File::Write("data.txt");
  File::Read("data.txt");
  return 0;
}

The following code example shows the content of our File namespace.

We’ll focus on the Read() function in this lesson and will cover writing in the next lesson. For now, we can just note that Write() creates a file on our hard drive containing the text "Hello World", so we have something to test our Read() function with:

// File.h
#pragma once
#include <iostream>
#include <SDL.h>

namespace File{
  void Read(const std::string& Path) {}
  
  void Write(const std::string& Path) {
    SDL_RWops* Context{
      SDL_RWFromFile(Path.c_str(), "wb")};
    const char* Content{"Hello World"};
    SDL_RWwrite(Context, Content, sizeof(char),
                strlen(Content));
    SDL_RWclose(Context);
  }
}

Placing Flags

Implement flag placement and tracking to complete your Minesweeper project.
Abstract art representing computer programming
Ryan McCombe
Updated
Published

In this final part of our Minesweeper series, we'll add the ability for players to place flags on suspected mine locations.

We'll update our game logic to handle flag placement and removal, create a visual representation for flags, and implement a counter to track the number of flags placed.

By the end of this lesson, you'll have a fully functional Minesweeper game with all the classic features players expect!

Engine Overview

An introduction to the generic engine classes we'll use to create the game
Abstract art representing computer programming
Ryan McCombe
Updated
Published

In this series, we'll build a fully functional Minesweeper game from scratch, giving you hands-on experience with game development concepts and C++ programming.

We'll separate our project into two main parts:

  1. An "Engine" module containing components that are generally useful across a wide range of projects, not specific to Minesweeper.
  2. A Minesweeper-specific module that builds upon our engine to create the actual game.

For example, we'll create a general Button class in our engine that can be used across various projects. The cells of our Minesweeper grid will then inherit from this Button class, expanding it with Minesweeper-specific logic such as whether the cell contains a bomb and counting the number of bombs in adjacent cells.

Building a Versatile Image Class

Designing a flexible component for handling images in SDL-based applications
Abstract art representing computer programming
Ryan McCombe
Published

In this lesson, we’ll combine the techniques we’ve covered so far in this chapter into a cohesive Image class. We’ll focus on creating a friendly API so external code can easily control how images are rendered onto their surfaces We’ll cover:

  • Creating a flexible API for image handling
  • Implementing file loading and error checking
  • Setting up source and destination rectangles
  • Adding different scaling modes for rendering
  • Optimizing performance for game loops

As a starting point, we’ll be building upon a basic Window and application loop, built using topics we covered earlier in the course:

Expanding the Image API

Key techniques for implementing class designs in more complex scenarios
Abstract art representing computer programming
Ryan McCombe
Published

In this lesson, we’ll discuss some ways we can improve upon the Image class created in the previous lesson. We’ll cover three topics:

  • Techniques for dealing with errors and unexpected situations
  • Adding flexibility to our class, and working around some common problems that can occur when implementing a versatile API
  • Using comments to document how our API works

The examples we use here are based on the Image class we created previously:

Ending and Restarting Games

Implement win/loss detection and add a restart feature to complete the game loop
Abstract art representing computer programming
Ryan McCombe
Published

In this lesson, we’ll update our game to detect and react to the player winning or losing.

  • To win, the player must clear all the cells that do not have bombs
  • If the player clears a cell that has a bomb, they lose

Let’s get this working!

Introduction to SDL_Image

Learn to load, manipulate, and save various image formats using SDL_Image.
3D art representing computer programming
Ryan McCombe
Updated
Published

In this lesson, we’ll start using the SDL_Image extension we installed earlier. We’ll cover 3 main topics:

  • Initializing and closing SDL_Image
  • Using the IMG_Load() function to load and render a wide variety of image types, rather than being restricted to the basic bitmap (.bmp) format.
  • Using surface blending modes to use transparency and other techniques when blitting
  • Creating image files from our surfaces using IMG_SaveJPG() and IMG_SavePNG()

We’ll be building upon the basic application loop and surface-blitting concepts we covered earlier in the course:

Rendering Text with SDL_ttf

Learn to render and manipulate text in SDL2 applications using the official SDL_ttf extension
3D art representing computer programming
Ryan McCombe
Updated
Published

In this lesson, we’ll see how we can render text within our programs. We’ll use the official SDL_ttf extension we installed earlier in the course.

We’ll build upon the concepts we introduced in the previous chapters. Our main.cpp looks like below.

The key thing to note is that we have created a Text class, and instantiated an object from it called TextExample. This object is being asked to Render() onto the window surface every frame:

Text Performance, Fitting and Wrapping

Explore advanced techniques for optimizing and controlling text rendering when using SDL_ttf
3D art representing computer programming
Ryan McCombe
Updated
Published

In this lesson, we’ll build on our text rendering capabilities with some new tools:

  • The ability to adjust the rasterizing process to optimize performance when appropriate
  • Dynamically choosing a font size to fit a target pixel size for our rasterized surface
  • Calculating how much text we can fit within a designated space
  • Rendering multi-line text areas using word wrapping, and controlling the alignment of the lines

Our main.cpp is below. Compared to the last lesson, we’ve added a GetWidth() method to the Window class.

Module One
3D art showing a progammer setting up a development environment

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Free, unlimited access

This course includes:

  • 59 Lessons
  • Over 200 Quiz Questions
  • 95% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Capstone Project
3D art representing computer programming

Building Minesweeper with C++ and SDL2

Apply what we learned to build an interactive, portfolio-ready capstone project using C++ and the SDL2 library

Free, unlimited access

This course includes:

  • 37 Lessons
  • 100+ Code Samples
  • 92% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Module Two
A computer programmer

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 124 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Get Started Now

Intro to C++ Programming

Starting from the fundamentals, become a C++ software engineer, step by step.

Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved