The first step of implementing any application is writing the foundational code that keeps the program running until we or the user decide it’s time to quit. This code is often called the application loop, main loop, or, if we’re making a game, the game loop.
Typically, every iteration of the loop involves 3Â steps:
On most platforms, multiple applications can be open at once. However, when the user is providing input on their keyboard, they typically only intend to provide that input to one of the open applications.
Users can select which application is active by, for example, clicking within its window.
Operating systems typically apply more vibrant styling to the active window. In the following example, the left window is inactive, while the right is active.
Accordingly, the user will not expect the left window to react to keyboard events, as their input is likely intended for the right window instead:
In desktop environments, users can have multiple windows open at once. On most platforms, only a single window can have input focus at a time, which is typically gained by the user clicking on the window:
This is referred to as input focus, and we covered it in more detail in our earlier lesson on keyboard input:
In this lesson, we’ll introduce the related concept of mouse focus. A window has mouse focus if the user’s pointer is currently hovering over it. The window with mouse focus is not necessarily the same as the window with input focus.
Previously, we introduced how SDL dispatches events when the player moves their mouse within our window, or when they click their mouse buttons when our window has input focus:
#include <SDL.h>
#include <iostream>
#include "Window.h"
void HandleButton(SDL_MouseButtonEvent& E) {
if (E.button == SDL_BUTTON_LEFT) {
if (E.state == SDL_PRESSED) {
std::cout << "Left button pressed at ("
<< E.x << ", " << E.y << ")\n";
} else if (E.state == SDL_RELEASED) {
std::cout << "Left button released at ("
<< E.x << ", " << E.y << ")\n";
}
}
}
void HandleMotion(SDL_MouseMotionEvent& E) {
std::cout << "Mouse moved to ("
<< E.x << ", " << E.y << ")\n";
}
int main(int argc, char** argv) {
SDL_Init(SDL_INIT_VIDEO);
Window GameWindow;
SDL_Event E;
while (true) {
while (SDL_PollEvent(&E)) {
if (E.type == SDL_MOUSEBUTTONDOWN
|| E.type == SDL_MOUSEBUTTONUP) {
HandleButton(E.button);
} else if (E.type == SDL_MOUSEMOTION) {
HandleMotion(E.motion);
}
}
GameWindow.Update();
}
SDL_Quit();
return 0;
}
Mouse moved to (226, 4)
Left button pressed at (226, 4)
Mouse moved to (227, 4)
Mouse moved to (228, 5)
Left button released at (228, 5)
This allows us to react to our user’s mouse input, but it is not the only approach that we can use. Instead of reacting to events, we are free to query the mouse’s current position and which buttons are pressed at any time.
We covered how to track mouse motion and clicking through the event loop in our introductory lesson:
In this introductory lesson, we'll create our first program in C++! We will start very simply. We'll just be outputting some text to the screen.
Things will ramp up quickly, but first, our priority is to make sure we have everything we need to start writing and running C++Â programs.
If you do not have a development environment set up yet, let's start by going through some options we have.
Welcome to our exploration of numeric variables! In this lesson, we explore numeric data types and their operations in C++.
Building on our previous discussion about integers and floating-point numbers, we will expand your understanding of how numbers work in C++ and how you can manipulate them.
As a reminder, here is how we create variables. This is similar to what we saw in the previous chapter, except we're now also showing the creation of a float
type. A float
is a number with a decimal point:
bool isDead { false };
int Level { 5 };
float Armor { 0.2 };
int LargeNumber { 100000000 };
true
and false
valuesIn this lesson, we introduce the concept of booleans in C++. Booleans are one of the simplest yet most powerful data types in programming. They represent the concept of binary states — true
or false
. You can think of them as the answer to a yes-or-no question.
Understanding Booleans is crucial because they form the backbone of decision-making in code. They help us answer questions like: "Is this condition met?" or "Should this action be performed?"
They are the key to controlling how a program behaves and responds to different scenarios. We've already seen a glimpse of how we can create booleans:
bool isAlive { true };
bool isDead { false };
In this lesson, we'll explore more on how to create, manipulate, and use these fundamental types to direct the flow of our programs. We'll start with the basics of creating booleans through comparisons and then move on to more complex operations.
Programming languages can be categorized as either "high-level" or "low-level". High-level languages (like Python) focus on making it easy for humans to write code, hiding many technical details about how computers work.
Low-level languages give programmers more direct control over the computer's hardware and memory, which can make programs faster and more efficient.
C++ is considered a relatively low-level language, which means we sometimes need to understand what's happening "under the hood" when we write our code. This is particularly true when it comes to how our programs use computer memory.
In our journey so far, we have discovered how functions and variables work with specific data types. Each type, like int
or float
, plays a unique role. But what happens when we mix these types - for example, what happens when we use an int
where a float
is expected?
This scenario introduces us to the concept of implicit conversion.
It allows us to use different types of values interchangeably in some situations, without needing to manually convert them. For instance, using an int
value where a float
is needed. The compiler, our code's translator, handles this conversion for us.
However, there's a twist. Not all conversions are equal. Some are straightforward, like turning an int
into a float
. Others, like converting a string
to an int
, are not possible implicitly.
In this lesson, we’ll explore how implicit conversions work with variables, functions, and operators. We'll also tackle the concept of narrowing casts, a special type of conversion that needs extra attention.
In a previous section, we saw how we could declare and define a function in two separate steps.
The declaration of a function uses its prototype. The prototype includes the function’s return type, its name, and the types of its parameters.
// A function declaration
int Add(int x, int y);
The definition includes all those things, but also includes the body of the function, where its behavior is implemented:
// A function definition
int Add(int x, int y) {
return x + y;
}