Game Development

by: 呂家睿

What is game development?

  • drawing, coding
  • designing, testing, debuging, releasing

Game Engine

Game Framework

Graphic API

Comparison

difficulty limit editor/GUI
Game Engine       dependent, large full set
Game Framework        fine but depend         on libraries no or minimal
Graphic API        same but free-er not at all

Game Engine(Unity)

Game Framework(SFML)

Graphic API(OpenGL)

      SFML

Simple Fast Multimedia Library

WHY  SFML????

  • based on C99(a version of C)

  • can do both 2D and 3D

  • based on C
  • for 2D only
  • a bit lower level
  • based on C++
  • for 2D only
  • clean and has more stuff

More Details For SFML

  • Simple, fast, and lightway
  • Good for 2D but not 3D
    • raylib and graphic api for 3D
  • Good for beginners
  • Good for practicing object oriented programming
  •  powerful libraries for audio, networking, window......

Setting up SFML

(can skip for school)

1-1. search "vscode" and click the website 

1-2. click the download button on the top right

Setting up SFML

(can skip for school)

1-3. download the one for your OS

1-4. open the thing you downloaded, hit agree, and just keep going next step, and finally hit install

Setting up SFML

(can skip for school)

2-1. install c++ extensions in vscode

2-2. install MinGW-x64 on windows

 

basically, just open the installer and follow it.

**This is for windows OS only**

Setting up SFML

(can skip for school)

2-3.MinGW command prompt stuff

 

once you finished the download, a command prompt will appear

 

do the following:

  • enter this command
  • follow its instructions
  • basically press enter twice
  • enter "Y" 
  • press enter
pacman -S --needed base-devel mingw-w64-ucrt-x86_64-toolchain

Setting up SFML

(can skip for school)

2-4.adding path

  • open "settings"
  • search for "Edit environment variables for your account"
  • select path and click edit
  • click new and add the destination folder of migw-w64
  • click Ok and click Ok in the environment variable window
//the path for default settings will be:
C:\msys64\ucrt64\bin

Setting up SFML

(can skip for school)

2-5.checking

  • open "command prompt"
  • type in:
gcc --version
g++ --version
gdb --version
  • you should see the version of each of them if installed correctly
  • if you don't, well, you did something wrong. But its fine just try to check what step you missed

still can't figure out?

click me for video

Setting up SFML

Step 3. Install the library

3-1.download

go to the sfml website and download

64bit GCC 14.2.0 MinGW (SEH) (UCRT) version

3-2. unzip the file you downloaded to a location you will remember

3-3. create a folder for sfml project

inside the folder create a main.cpp file

run it

Yes you can also use visual studio

its good but not for this class

Setting up SFML

4-1. dependencies

inside your sfml project folder create a folder called dependencies and paste your include and lib folders inside it.

ignore this 

Setting up SFML

4-2.paste the tutorial code in  your main.cpp file (it's normal that you see an error)

//this is the tutorial code
#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow window(sf::VideoMode({200, 200}), "SFML works!");
    sf::CircleShape shape(100.f);
    shape.setFillColor(sf::Color::Green);

    while (window.isOpen())
    {
        while (const std::optional event = window.pollEvent())
        {
            if (event->is<sf::Event::Closed>())
                window.close();
        }

        window.clear();
        window.draw(shape);
        window.display();
    }
}

4-3.put your mouse on the error 

vscode will show a recommendation

click quick fix -> include path settings

-> c_cpp_properties.json

Setting up SFML

4-4. in the c_cpp_properties json file

there's an "includePath" section

add in this:

"${workspaceFolder}/dependencies/include"

don't forget the comma and to save

Setting up SFML

4-4.open the tasks.json file

<------paste this in the arg section

"-fdiagnostics-color=always",
"-g",
"${file}",
"-I\"${workspaceFolder}/dependencies/include\"",
"-DSFML_STATIC",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe",
"-L\"${workspaceFolder}/dependencies/lib\"",
"-lsfml-graphics-s",
"-lsfml-window-s",
"-lsfml-audio-s",
"-lsfml-network-s",
"-lsfml-system-s",
"-lfreetype",
"-lopengl32",
"-lwinmm",
"-lgdi32",
"-lflac",
"-lvorbisenc",
"-lvorbisfile",
"-lvorbis",
"-logg",
"-lws2_32"

you should find your tasks.json here

final step - run main.cpp

If you did it, congrats!!!

if you didn't, its normal to fail at first,

be sure to follow the steps, if you still can't figure it out, check out the videos and resources

This window should pop out after you run main.cpp

The simple stuff

(maybe not that simple)

C++ basics

  • IO
  • Variables
  • loops
  • if statement
  • data types
  • array
  • math operation

Practice!!!!

Pizza ordering program:

 

You’re running a small pizza shop and want to analyze your daily orders. Write a program that:

 

  1. Asks how many pizza orders were made that day (max 50).
     

  2. For each order, enter how many slices the customer ordered.
     

  3. After all orders:

    • Calculate total slices sold

    • Calculate average slices 

    • Find the largest single order

    • Count how many customers ordered more than 10 slices

C++ basics

Sample Answer:

#include <iostream>

int main() 
{
    const int MAX_ORDERS = 50;
    int order_count;
    int slices[MAX_ORDERS];
    int total_slices = 0;
    int max_slices = 0;
    int eat_a_lot = 0;

    do
    {
        std::cout << "Enter number of pizza orders today (max 50): ";
        std::cin >> order_count;
    } while (order_count < 1 || order_count > MAX_ORDERS);
    

    for (int i = 0; i < order_count; i++) 
    {
        std::cout << "Enter slices ordered for customer " << (i + 1) << ": ";
        std::cin >> slices[i];
        total_slices += slices[i];

        if (slices[i] > max_slices) 
        {
            max_slices = slices[i];
        }

        if (slices[i] > 10) 
        {
            eat_a_lot++;
        }
    }

    float average_slices = static_cast<float>(total_slices) / order_count;

    std::cout << "\n--------------- Pizza Order Summary ---------------\n";
    std::cout << "Total slices sold: " << total_slices << '\n';
    std::cout << "Average slices per order: " << average_slices << '\n';
    std::cout << "Largest order: " << max_slices << " slices\n";
    std::cout << "Customers who ordered more than 6 slices: " << eat_a_lot << '\n';

    return 0;
}

functions

  • a chunk of code that can do sth

  • can be used repeatedly

  • makes your code neat

  • arguments and parameters

  • ex: printf(), sum()

#include <iostream>
#include <cmath>   

double hypotenuse(double side_1, double side_2)//declaration
{
    //definition
    double hyp = sqrt(side_1*side_1 + side_2*side_2);
    return hyp;
}

void hello()//declaration
{
	//definition
    std::cout << "Hello~~~!\n";
}

int main()
{
    double a, b;
    hello();
    std::cout << "Enter side a of the right triangle: ";
    std::cin >> a;
    std::cout << "Enter side b of the right triangle: ";
    std::cin >> b;
    std::cout << "The hypotenuse of the triangle is " << hypotenuse(a,b);
    return 0;
}

built in library, just using it for the square root funciton

function's return type

function's name

parameters ( or  variables declared inside a function) are used to pass arguments into the function

things that you do inside the function

return's the value(hyp in this case) and ends the function

the void type means the function returns nothing

a and b are arguments passed into the function

#include <iostream>
#include <cmath>    

double hypotenuse(double side_1, double side_2);
void hello();

int main()
{
    double a, b;
    hello();
    std::cout << "Enter side a of the right triangle: ";
    std::cin >> a;
    std::cout << "Enter side b of the right triangle: ";
    std::cin >> b;
    std::cout << "The hypotenuse of the triangle is " << hypotenuse(a,b);
}

double hypotenuse(  double side_1,  double side_2)
{
    double hyp = sqrt(side_1*side_1 + side_2*side_2);
    return hyp;
}

void hello()
{
    std::cout << "Hello~~~!\n";
}

You can also define them below the main function

But remember to declare them at the top or an error will occur

class

  • like a type or a blueprint
  • can have variables and functions (members)
  • object oriented programming
  • ex: string ,  RenderWindow

writing a class

#include <iostream>

class Car
{
    public:
        std::string brand;
        std::string color;
        int price = 0;
        int horse_power = 0;

        void check();
};

void Car::check()
{
    std::cout << "This is a " << color << ' ' << brand << '\n';
    std::cout << "It is " << price << "$ "<< "and has a horse power of " << horse_power << '\n'; 
}

int main()
{
    Car a;
    a.brand = "Toyota";
    a.color = "red";
    a.price = 500000;
    a.horse_power = 100;

    Car b;
    b.brand = "Benz";
    b.color = "white";
    b.price = 3000000;
    b.horse_power = 250;

    a.check();
    b.check();

    return 0;
}

Defining a class

the class' (Car's) variable

the class' (Car's)

function

let a be an object of the Car class

an object can has its own variable(it needs to be in the class)

defining Car's check function

constructor function

#include <iostream>

class Cup
{
    public:
        Cup(std::string c, std::string s);
        std::string color;
        std::string size;
};

Cup::Cup(std::string c = "white", std::string s = "big")
{
    color = c;
    size = s;
    std::cout << "Hmm seems like you have a " << size << " " << color << " cup!\n";
}

int main(){
    Cup glass_cup("red", "big");
    std::cout << glass_cup.color << '\n';

    return 0;
}

the constructor function

the constructor function has the same name as the class

creating an object

it doesn't have a type(not even void)

#include <iostream>

class Cup
{
    public:
        Cup(std::string c, std::string s);
        ~Cup();
        std::string color;
        std::string size;
};

Cup::Cup(std::string c , std::string s)
{
    color = c;
    size = s;
    std::cout << "Hmm seems like you have a " << size << " " << color << " cup!\n";
}

Cup::~Cup()
{
    std::cout << "Nooooo~~~\n";
    std::cout << "You killed a " << size << " " << color << " cup\n";
}

int main()
{
    Cup glass_cup("red", "big");
    std::cout << glass_cup.color << '\n';
    
    return 0;
}

the destructor function

~(class name)

cannot take arguments

also no return type

math

(just a little bit)

Game Core Logic

Initialization

Game Loop

Cleanup

Game Loop

  1. Handle Inputs
  2. Update
    • ​physics, game logic, collision....
  3. Draw
    • ​​clear       draw      display
  4. Handle Timing
    • ​​FPS --Vsync & delta time
  5. Check for Exit

Cleanup

  • Saving Game Data
  • Free Memory
  • Ending Program

Simple Sample

#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow window(sf::VideoMode({800, 600}), "Makin Shapes");
    
    sf::CircleShape circle(100.f);
    
    while (window.isOpen())
    {
        window.clear(sf::Color(0, 170, 255, 100));
        window.draw(circle);
        window.display();
    }
}

Creating a window

class

object

size of window

name of window

Creating a shape

radius

Game Loop

clear window

draw on buffer

display(switch buffer)

Initialization

Code Result

Circle

sf::CircleShape circle(100.f);

circle.setPosition({200.f, 300.f});
circle.setFillColor(sf::Color(0, 150, 150));
circle.setOutlineColor(sf::Color::Black);
circle.setOutlineThickness(10.f);
circle.setScale({2.f, 1.f});
circle.setRotation(sf::degrees(45));
    sf::CircleShape circle(100.f);

    circle.setPosition({200.f, 300.f});
    circle.setOrigin({100.f, 100.f});
    circle.setFillColor(sf::Color(0, 150, 150));
    circle.setOutlineColor(sf::Color::Black);
    circle.setScale({2.f, 1.f});
    circle.setOutlineThickness(10.f);
    circle.setRotation(sf::degrees(45));

(200,300)

(200,300)

Rectangle

sf::RectangleShape rect({200.f, 100.f});
rect.setOrigin({100.f, 50.f});
rect.setFillColor(sf::Color(255,215,0));
rect.setOutlineColor(sf::Color::Yellow);
rect.setOutlineThickness(-5.f);
// rect.setScale({0.5f, 1.5f});
// rect.setRotation(sf::degrees(90));
rect.setPosition({400.f, 300.f});

Polygons

sf::CircleShape pentagon(100.f, 5);

pentagon.setPosition({400.f, 300.f});
pentagon.setOrigin({100.f, 100.f});
pentagon.setFillColor(sf::Color(0, 150, 150));
pentagon.setOutlineColor(sf::Color(255, 215, 0));
pentagon.setOutlineThickness(10.f);

number of vertice

sf::CircleShape circle(100.f, 20);
circle.setPosition({400.f, 300.f});
circle.setOrigin({100.f, 100.f});
sf::CircleShape rounder_circle(100.f);
rounder_circle.setPosition({400.f, 300.f});
rounder_circle.setOrigin({100.f, 100.f});

Convex Shapes

sf::ConvexShape shape;
shape.setPointCount(5);
shape.setPoint(0, {60.f, 20.f});
shape.setPoint(1, {20.f, 100.f});
shape.setPoint(2, {100.f, 100.f});
shape.setPoint(3, {150.f, 60.f});
shape.setPoint(4, {100.f, 20.f});

Order!!!

Point number

coords

Antialiasing

sf::ConvexShape triangle;
triangle.setPointCount(3);
triangle.setPoint(0, {60.f, 20.f});
triangle.setPoint(1, {500.f, 100.f});
triangle.setPoint(2, {100.f, 350.f});
sf::ContextSettings settings;
settings.antiAliasingLevel = 8;
sf::RenderWindow window(sf::VideoMode({800, 600}), "Makin Shapes", sf::Style::Default, sf::State::Windowed, settings);

Player

Texture

  • moves
  • scales
  • rotates
  • has a texture

+

Sprite Sheet

  • for animation
  • multiple frames
  • all in one

Making a Sprite

Location

same layer

sf::Texture player_texture;
player_texture.loadFromFile("Assets/Player/Texture/sprite_sheet.png");
sf::Sprite player_sprite(player_texture);

Location

bool

Better pic maybe?

Making a Sprite

sf::Texture player_texture;
sf::Sprite player_sprite(player_texture);

if(player_texture.loadFromFile("Assets/sprite_sheet.png"))
{
  std::cout << "Player Image Loaded\n";
  player_sprite.setTexture(player_texture);
  player_sprite.setTextureRect(sf::IntRect({0, 0}, {64, 64}));
  player_sprite.setScale({2.f, 2.f});
}
else
{
	std::cout << "Player Image Failed to Load\n";
}

No default constructor

(0, 0)

64px

64px

for debugging

Making a Sprite

#include <SFML/Graphics.hpp>
#include <iostream>
int main()
{
    sf::ContextSettings settings;
    settings.antiAliasingLevel = 8;
    sf::RenderWindow window(sf::VideoMode({800, 600}), "Makin Shapes", sf::Style::Default, sf::State::Windowed, settings);
    sf::Texture player_texture;
    sf::Sprite player_sprite(player_texture);

    if(player_texture.loadFromFile("Assets/sprite_sheet.png"))
    {
        std::cout << "Player Image Loaded\n";
        player_sprite.setTexture(player_texture);
        player_sprite.setTextureRect(sf::IntRect({0, 0}, {64, 64}));
        player_sprite.setScale({2.f, 2.f});
    }
    else
    {
        std::cout << "Player Image Failed to Load\n";
    }

    while (window.isOpen())
    {
        window.clear(sf::Color(0, 170, 255, 100));
        window.draw(player_sprite);
        window.display();
    }
}

Loop

clear

draw

display

Init

window

player

Move a Sprite

Input

Update

while (window.isOpen())
{
  while (std::optional event = window.pollEvent())
  {
    if (event->is<sf::Event::Closed>())
    {
    	window.close();
    }
  }
  window.clear(sf::Color(0, 170, 255, 100));
  window.draw(player_sprite);
  window.display();
}

Closed

Resized

Poll Event

if (const auto* keyPressed = event->getIf<sf::Event::KeyPressed>())
{
	if (keyPressed->scancode == sf::Keyboard::Scan::D)
    {
    	sf::Vector2f player_position = player_sprite.getPosition();
    	player_sprite.setPosition(player_position + sf::Vector2f(1.f, 0.f));
    }
}

Slow

Polling Rate

Event

while (window.isOpen())
{
    while (const std::optional event = window.pollEvent())
    {
        if (event->is<sf::Event::Closed>())
        {
            window.close();
        }
        
    }
    if (sf::Keyboard::Key::D)
    {
        sf::Vector2f player_position = player_sprite.getPosition();
        player_sprite.setPosition(player_position + sf::Vector2f(1.f, 0.f));
    }
    window.clear(sf::Color(0, 170, 255, 100));
    window.draw(player_sprite);
    window.display();
}

Fast & Smooth

Full Code

#include <SFML/Graphics.hpp>
#include <iostream>
int main()
{
    sf::ContextSettings settings;
    settings.antiAliasingLevel = 8;
    sf::RenderWindow window(sf::VideoMode({800, 600}), "Makin Shapes", sf::Style::Default, sf::State::Windowed, settings);
    window.setVerticalSyncEnabled(true);
    
    sf::Texture player_texture;
    sf::Sprite player_sprite(player_texture);

    if(player_texture.loadFromFile("Assets/sprite_sheet.png"))
    {
        std::cout << "Player Image Loaded\n";
        player_sprite.setTexture(player_texture);
        player_sprite.setTextureRect(sf::IntRect({0, 0}, {64, 64}));
        player_sprite.setScale({2.f, 2.f});
    }
    else
    {
        std::cout << "Player Image Failed to Load\n";
    }

    while (window.isOpen())
    {
        while (const std::optional event = window.pollEvent())
        {
            if (event->is<sf::Event::Closed>())
            {
                window.close();
            }
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::D))
        {
            sf::Vector2f player_position = player_sprite.getPosition();
            player_sprite.setPosition(player_position + sf::Vector2f(1.f, 0.f));
        }
        window.clear(sf::Color(0, 170, 255, 100));
        window.draw(player_sprite);
        window.display();
    }
}

Frame Rate Control

Congratulations!

Resources

sfml simple stuff  - video

sfml rpg game(visual studio)  - video

sfml tutorial -official website

OpenGameArt- open access game art

**remember to pay attention to every information's version**

Copy of Game Developing

By ck11300111呂家睿

Copy of Game Developing

  • 160