Subscribe to Blog of a Wizzy        RSS Feed
-----

2D Tile Engine in C++ - Pt.1

Icon Leave Comment
2D Tile Engine in C++ - Pt.1
(released early for your learning)

Hello, everybody! :bigsmile:

With the beginning of this tutorial, I have deemed it necessary to continue in RevTorA's place. I'll be starting a new series, using SFML's newest 2.0 syntax. For the start of my tutorial, I will be heavily borrowing from RevTorA's code, though it's because he gave a brilliant framework to start with.

What are we making?
We'll be making a 2D tile engine, like the ones they use in top-down RPGs, like:

  • Zelda: Link to the Past
  • Chrono Trigger
  • Dragon Warrior
  • Shining Force
  • Earlier Final Fantasy games

If you don't know or recognize any of those names, it's recommended you take a peek. We'll be making a top-down RPG tile engine.

If you're not sure why I'm using the term 'engine' instead of 'game,' it's because a game runs using an engine, or you could say and engine is what makes the game run. An engine is the backbone of a game as it loads and renders and updates and processes everything that goes on with the game. If you press a key on your keyboard that's tied to movement, the engine will process the keypress and act accordingly, by moving your character, starting an animation or showing a notice on the screen.

What will we use?
We'll be programming using C++. I personally like C++ because it's pretty easy to learn; it's also low-level enough to do tricks close to the hardware, while being high-level enough to create clever solutions.

Since creating the media API (Application Programming Interface) for our engine would require some really low-level knowledge of C++, we'll be using a media library called SFML. Go ahead and go to SFML's website and download SFML 2.0 adn then follow one of these tutorials for installing SFML to your IDE.

Since I'm a Mac fanboy, I'll be using Apple's Xcode 4. If you're on a Windows machine, I recommend Microsoft's Visual C++ Express. Either way, you'll need a good IDE to develop in.

Setting up SFML for a project.
Now that you have your IDE ready and a copy of SFML 2.0, then it's time to set up SFML for our project. For setting up the project, you'll have to add library dependencies and modify the Linker rules.

For Apple's Xcode 4
For us Mac junkies, the process is a tad more involved. To set up SFML properly for Xcode 4, follow this thread. When you're done installing SFML, go into your project's panel, under the Build Settings tab, look for Other Linker flags and type this there:

g++ -framework SFML -lsfml-graphics -lsfml-audio -lsfml-window -lsfml-system

For Microsoft's Visual C++ Express
(instructions borrowed from RevTorA)
First, create a new Win32 Project in Visual Studio. Make sure Empty Project is checked under Application Settings. Now do "Add->New Item" to the project and create a .cpp file named "Main.cpp"

Next, you have to set up the project so it will compile and link correctly. Open up the project properties and do the following:

  • Under "Linker->General->Additional Library Dependencies", add the "\lib\Debug" directory from your SFML binaries
  • Under "Linker->Input->Additional Dependencies", add
    • sfml-main-d.lib
    • sfml-system-d.lib
    • sfml-window-d.lib
    • sfml-graphics-d.lib

  • Under "Debugging->Working Directory", change the value to "$(OutDir)


Finally! We get to code!
It's finally time to work the magic of programming! :sorcerer:

First, we'll need a class that defines what our engine has. Make a new header file and name it "Engine.cpp" and write this:
#ifndef Engine_h
#define Engine_h

#include <SFML/Graphics.hpp>
#include <SFML/window.hpp>

class Engine 
{
private:
    sf::RenderWindow* window;
    
    bool Initialize();
    void MainLoop();
    void RenderFrame();
    void ProcessInput();
    void Update();
    
public:
    Engine();
    ~Engine();
    
    void Go();
};

#endif


Hopefully you can already see how our engine "flows." I'll expand on it more when we begin to flesh out our Engine, but I'll give you a brief run-down on sf::RenderWindow; the RenderWindow class creates a window where we can render 2D graphics. This is what we'll be drawing to and communicating with in the engine.

Next, we'll start to work out the mechanics of our engine. Since our goal here is to simply create a blank window, there won't be much to write. Create a new .cpp file and name it "Engine.cpp" then write the following code:
#include "Engine.h"

Engine::Engine()
{
    
}

Engine::~Engine()
{
    delete window;
}

bool Engine::Initialize()
{
    window = new sf::RenderWindow(sf::VideoMode(800, 600), "RPG");
    
    if(!window)
        return false;
    else
        return true;
}

void Engine::MainLoop()
{
    while(window->isOpen())
    {
        ProcessInput();
        Update();
        RenderFrame();
    }
}

void Engine::RenderFrame()
{
    
}

void Engine::ProcessInput()
{
    sf::Event evt;
    
    while(window->pollEvent(evt))
    {
        if(evt.type == sf::Event::Closed)
            window->close();
    }
    
    window->display();
}

void Engine::Update()
{
    
}

void Engine::Go()
{
    if(!Initialize())
        throw "Could not initialize the Engine.";
    else
        MainLoop();
}


Alright. Not too bad, right? :neat:/>

This part is relatively simple. I'll start from the beginning: when some part of our code (say, launching the game or pressing "Play") calls the Go() method, it either successfully Initializes and moves on to MainLoop(), or it throws back an error. When we're in Initialize(), we're creating a new RenderWindow instance; the one we referenced in Engine.h. If the window didn't succeed, we throw an error, otherwise we'll continue. In MainLoop(), we're continuously looping as long as the window is open. First, we ProcessInput() from the user; currently we have a Closed event in there. If we, say, pressed the red X to close the window, it would call the close() method on our window and the whole loop would stop. Next, we Update() anything that changed due to user input, and then RenderFrame() those changes to the window.

Now, I'll explain a little more in-depth about the VideoMode() in RenderWindow() and how pollEvent() works. Grab a quick cup of joe and we'll continue. Posted Image

When we created the RenderWindow, we had to assign the VideoMode() and Title parameters respectively. Title is self-explanatory. VideoMode is simple a SFML class that assigns our RenderWindow a height, width and bit-depth respectively. We didn't add a bit-depth here, but don't worry about that for now.
So what about pollEvent()? Well, pollEvent constantly polls the window for events caused by user input. If it detects an event happened - e.g. the user presses the spacebar, or moves their mouse - it adds that event to a queue, which it plucks events from periodically and acts accordingly. For example, when we hit a key-combo or the red X to close the window, it detects this event, adds it to the queue, then runs over it and closes our window.

Time to open a window.
We finally got past all the boring coding and explanations! Time to open our window. :D

In your Main.cpp file, write this last bit of code:
#include <iostream>
#include "Engine.h"

int main() 
{
    Engine* engine = new Engine();
    
    try 
    {
        engine->Go();
    } 
    catch (char* e) 
    {
        throw "An error occured trying to launch the engine.";
        return 0;
    }
}


The simplest of our code. We're simply creating a new instance of our Engine and then attempting to run the Go() method. If we failed, throw an error. Else, continue!

You should get a pretty white (or black, if display() worked right) window! We're done. :bananaman:

Next tutorial, we'll draw an image to the screen based on keyboard input. For now, admire our pretty blank window. I'd like to give RevTorA a bajillion-and-one thanks for his showing me SFML, and helping me learn the basics of game programming.

0 Comments On This Entry

 

Trackbacks for this entry [ Trackback URL ]

There are no Trackbacks for this entry

December 2014

S M T W T F S
 123456
78910111213
141516171819 20
21222324252627
28293031   

Tags

    Recent Entries

    Search My Blog

    0 user(s) viewing

    0 Guests
    0 member(s)
    0 anonymous member(s)

    Categories