• (3 Pages)
  • +
  • 1
  • 2
  • 3

C++ Tile Engine from Scratch -- Part 1

#1 RevTorA  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 76
  • View blog
  • Posts: 246
  • Joined: 22-April 11

Posted 03 May 2011 - 06:07 PM

*
POPULAR

C++ Tile Engine from Scratch -- Part 1

Hey there DICers. This series of tutorials is meant for newer game programmers to show some basic game programming concepts through example. I'm going to walk you through creating as complete a 2D tile engine as I can muster, so hang on to your hats and lets get this started!

What we're making
For this series of tutorials we'll be making a 2D tile engine used in popular Top-Down RPGs, such as:
  • Zelda: Link to the Past
  • Dragon Warrior
  • Shining Force
  • Final Fantasy
  • Chrono Trigger

Hopefully you're familiar with at least one of those games. We're going to make a top-down 2D tile engine.

I should elaborate on why we're using the word "engine" instead of "game". An engine is the backbone of any game. We're not going to cover the creation media and data assets such as artwork or music that make up the content of a game. Instead, we'll be programming a framework that will then allow us to add in content to make a fully playable game.

What we're using
The language we'll be using for the engine is C++. I like C++ for game programming because it is fast, extensible, and powerful. It is low-level enough that you can do all sorts of tricks close to the hardware, but high-level enough to allow for some really clever game design solutions.

Because I'm such a fan of Microsoft's Visual Studio, I will be using Visual C++ Express 2010 to make the engine. I highly recommend it, since it is free and quite simply awesome.

However, creating the engine from scratch with C++ would be time consuming and rather difficult. It would require low-level graphical and hardware knowledge which is too advanced of a subject for this tutorial. So instead we'll use a media API (Application Programming Interface) called SFML to help us with the graphical and audio implementations. We'll need SFML to run our example code. So head on over to http://www.sfml-dev.org and download a copy of SFML 2.0 (currently in beta). Follow this tutorial to get SFML set up for Visual Studio.

Setting Up
I'll spare you all the game design concepts and questions you should ask your self before starting a project like this and jump straight into getting a solution set up for our project.

First, create a new "Win32 Project" in visual studio, and make sure "Empty Project" is checked under "Application Settings". Now we do "Add->New Item" to the project and create a .cpp file named "Main.cpp".

Now we 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)"


After that, your project should be ready to use SFML

Finally some code!
Okay, so now we can begin laying some ground work for our engine, as well as make sure that we set up our project correctly. The first thing we want to do is create a class that will represent our actual engine, so add a new header file called "Engine.h" and write the following code in it:
#ifndef _ENGINE_H
#define _ENGINE_H

#include <SFML\Graphics.hpp>

class Engine
{
private:
	//SFML Render Window
	sf::RenderWindow* window;

	//Initializes the engine
	bool Init();				
	//Main Game Loop
	void MainLoop();			
	//Renders one frame
	void RenderFrame();
	//Processes user input
	void ProcessInput();
	//Updates all Engine internals
	void Update();				

public:
	Engine();
	~Engine();

	void Go();					//Starts the engine
};

#endif


You can already see how the engine "flows". Almost every game engine requires some kind of loop to constantly update everything that is going on. In that loop, typically three things need to be done.
  • Get any input, either from the user (via the keyboard or mouse), or from the operating system, and perform any actions needed.
  • Update all of the engine internals, such as animations, character movements, etc.
  • Present all this information to the user by rendering a graphical frame.

You can see that in the above class I have setup a framework for this list by adding class methods for getting input, updating, and rendering. These will all be called from the method "MainLoop". "window" is our way of communicating with the user via the RenderWindow class implemented by SFML. Now that we have the skeleton for the Engine class, let's flesh it out by adding a new code file named "Engine.cpp". Fill it with the following code:
#include "Engine.h"
#include <SFML\Graphics.hpp>

Engine::Engine()
{

}

Engine::~Engine()
{

}

bool Engine::Init()
{
	window = new sf::RenderWindow(sf::VideoMode(800, 600, 32), "RPG");

	if(!window)
		return false;

	return true;
}

void Engine::RenderFrame()
{

}

void Engine::ProcessInput()
{
	sf::Event evt;
	//Loop through all window events
	while(window->PollEvent(evt))
	{
		if(evt.Type == sf::Event::Closed)
			window->Close();
	}
}

void Engine::Update()
{

}

void Engine::MainLoop()
{
	//Loop until our window is closed
	while(window->IsOpened())
	{
		ProcessInput();
		Update();
		RenderFrame();
	}
}

void Engine::Go()
{
	if(!Init())
		throw "Could not initialize Engine";

	MainLoop();
}



All we're doing for now is creating our RenderWindow, and then waiting for the user to close it. When we instantiate a new RenderWindow, we supply it with a VideoMode and a Title. The VideoMode's parameters are the width, height, and bit-depth of the window respectively. Once a RenderWindow has been created, SFML will keep it open until we tell it to close with the Close() method.

While the window is open, it constantly retrieves input from the user in the form of events, and stores the events in a queue until we retrieve them. So, at the beginning of our main loop we call ProcessInput, which polls the window until there are no more events in the queue. If we find an Event::Closed event, i.e. the user closed the window, then we call window->Close(), which then breaks our MainLoop (while(window->IsOpened())), and exits the program.

So, with that all ready, we need only to create our program's entry point, so add another code file called "Main.cpp", and put in the following code:
#include <Windows.h>

#include "Engine.h"

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
	Engine* engine = new Engine();

	try
	{
		engine->Go();
	}
	catch(char* e)
	{
		MessageBoxA(NULL, e, "Exception Occured", MB_OK | MB_IConerror);
	}
}



Awesome, now we have our starting code. There's one more thing you need to do before this will run though. You must copy all the ".dll" files from SFML's "\lib\Debug" folder into your project's "Debug" folder. After you've done that, run the program, and admire the pretty blank window :D.

Conclusion
Alright, that was a lot of talk with not a lot of satisfying results, but don't worry! There's more coming up so move on to the next tutorial!

Thanks to BronzeBeard and everyone else in #ogre3d for helping me get this together!

Is This A Good Question/Topic? 8
  • +

Replies To: C++ Tile Engine from Scratch -- Part 1

#2 SuicidalCookie  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 20-May 11

Posted 20 May 2011 - 03:06 AM

I followed all the steps but
#ifndef
is underlined in red and the error says "the #endif for this directive is missing"
Was This Post Helpful? 0
  • +
  • -

#3 SuicidalCookie  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 20-May 11

Posted 20 May 2011 - 03:14 AM

View PostSuicidalCookie, on 20 May 2011 - 03:06 AM, said:

I followed all the steps but
#ifndef
is underlined in red and the error says "the #endif for this directive is missing"

EDIT
I feel sooo stupid im sorry for the stupid question. I figured out what I did wrong.
Was This Post Helpful? 0
  • +
  • -

#4 RevTorA  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 76
  • View blog
  • Posts: 246
  • Joined: 22-April 11

Posted 20 May 2011 - 09:12 PM

View PostSuicidalCookie, on 20 May 2011 - 03:14 AM, said:

View PostSuicidalCookie, on 20 May 2011 - 03:06 AM, said:

I followed all the steps but
#ifndef
is underlined in red and the error says "the #endif for this directive is missing"

EDIT
I feel sooo stupid im sorry for the stupid question. I figured out what I did wrong.


Hehe, didn't quite paste everything eh? :P
Was This Post Helpful? 0
  • +
  • -

#5 C++Noobster  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 3
  • Joined: 19-July 11

Posted 19 July 2011 - 12:13 PM

I dont understand how to install SFML
Was This Post Helpful? 0
  • +
  • -

#6 C++Noobster  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 3
  • Joined: 19-July 11

Posted 20 July 2011 - 10:34 AM

View PostC++Noobster, on 19 July 2011 - 12:13 PM, said:

I dont understand how to install SFML


After a long search i found a video which solved my questions.
http://www.youtube.c...h?v=cDNo4bzrFW8

I followed all the steps of your post but still get errors like "Can not open include file:'SFML/Graphics.hpp': No such file or directory"
and
IntelliSense:indentifer MB_IConerror is unidentfied
Was This Post Helpful? 0
  • +
  • -

#7 shrugo  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 1
  • Joined: 24-July 11

Posted 24 July 2011 - 10:07 PM

View PostC++Noobster, on 20 July 2011 - 10:34 AM, said:

View PostC++Noobster, on 19 July 2011 - 12:13 PM, said:

I dont understand how to install SFML


After a long search i found a video which solved my questions.
http://www.youtube.c...h?v=cDNo4bzrFW8

I followed all the steps of your post but still get errors like "Can not open include file:'SFML/Graphics.hpp': No such file or directory"
and
IntelliSense:indentifer MB_IConerror is unidentfied

Both of your errors are actually minor errors or missing steps from the tutorial poster. It's nothing major, just assuming that the reader was probably a bit more experienced with C++ than someone such as yourself.

For the first error you posted, the problem is most likely that you must go back to your project properties and add your include directory, otherwise your compiler will be completely without an idea what Graphics.hpp is, for the linker itself doesn't have a reference.
If you watched that tutorial video and followed the narrator's directory paths, you will need to add "c:\sfml\sfml2\include" to the end of the Include Directories under VC++.
Basically, the creator of this tutorial assumed the reader knew what to do here, which was probably a bit too much to ask, since this is, of course, the Internet.

Your second error is actually a simple formatting error that this forum has. (This should really be fixed because we're here to code.)
Instead of "IConerror", capitalize all the letters.
I hope this helps.

This post has been edited by shrugo: 24 July 2011 - 10:09 PM

Was This Post Helpful? 1
  • +
  • -

#8 C++Noobster  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 3
  • Joined: 19-July 11

Posted 25 July 2011 - 08:58 PM

Oh jeez thank you sooo much! You sir need a kudo!
Was This Post Helpful? 0
  • +
  • -

#9 Timeclawk  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 23-August 11

Posted 23 August 2011 - 03:58 PM

Hello all I am very new to programming and am starting with c++, I intended to use this tile engine tutorial for some insight and a little fun, everything went well except the Engine.cpp gives me this error when I compile,

void Engine::ProcessInput()
{
	   sf::Event evt;
	   //Loop through all window events
	   while(window->PollEvent(evt))
	   {
	       if(evt.Type == sf::Event::Closed)
	           window->Close();
	   }
}


Quote

Engine.cpp
c:\documents and settings\hp_administrator\my documents\visual studio 2010\projects\gameengine\gameengine\engine.cpp(33): error C2039: 'PollEvent' : is not a member of 'sf::RenderWindow'
c:\program files\microsoft visual studio 10.0\vc\include\sfml\graphics\renderwindow.hpp(45) : see declaration of 'sf::RenderWindow'
c:\documents and settings\hp_administrator\my documents\visual studio 2010\projects\gameengine\gameengine\engine.cpp(33): fatal error C1903: unable to recover from previous error(s); stopping compilation


The error in the code is "Pollevent" from line 5, it's error description reads,

Quote

Error: class "sf;;RenderWindow" has no member "PollEvent"


I haven't really tried anything because VS 2010 seems to differ somewhat from this tutorial. Furthermore I am using SFML 1.6 and I do not see a debug folder where it says it should be, C:/x/SFML-1.6/lib/debug.

Any help is appreciated.
Was This Post Helpful? 0
  • +
  • -

#10 gammaman  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 20-March 10

Posted 27 August 2011 - 09:56 AM

I am getting the following error when compiling. I am using Visual Studio 2010.

Tile.cpp
1>c:\users\matt\documents\visual studio 2010\projects\gameengine\gameengine\tile.cpp(6):
error C2039: 'SetImage' : is not a member of 'sf::Sprite'
1> c:\sfml\smfl2\laurentgomila-sfml-b9b3888\include\sfml\graphics\sprite.hpp(45) : see declaration of 'sf::Sprite'

#include "Tiles.h"
#include <C:\SFML\SMFL2\LaurentGomila-SFML-b9b3888\include\SFML\Graphics.hpp>
#include <stdlib.h>
Tile::Tile(sf::Image& image)
{
	baseSprite.SetImage(image, true);
}

Tile::~Tile()
{

}

void Tile::Draw(int x, int y, sf::RenderWindow* rw)
{
	baseSprite.SetPosition(x, y);
	rw->Draw(baseSprite);
}



#ifndef _TILE_H
#define _TILE_H

#include <C:\SFML\SMFL2\LaurentGomila-SFML-b9b3888\include\SFML\Graphics.hpp>

class Tile
{
private:
	sf::Sprite baseSprite;

public:
	Tile(sf::Image& image);
	~Tile();

	void Draw(int x, int y, sf::RenderWindow* rw);
};

#endif




This is the only error I get. I would really like to continue with the tutorial so any help would be greatly appreciated.

This post has been edited by gammaman: 27 August 2011 - 09:57 AM

Was This Post Helpful? 0
  • +
  • -

#11 SergeantBalthazar  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 14-March 12

Posted 14 March 2012 - 03:12 PM

The error in the code is "Pollevent" from line 5, it's error description reads,

Quote

Error: class "sf;;RenderWindow" has no member "PollEvent"


I haven't really tried anything because VS 2010 seems to differ somewhat from this tutorial. Furthermore I am using SFML 1.6 and I do not see a debug folder where it says it should be, C:/x/SFML-1.6/lib/debug.

[/quote]
in SFML 1,6 PollEvent is named GetEvent. Hope this helps ;)
Was This Post Helpful? 0
  • +
  • -

#12 icelated  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 15
  • Joined: 24-May 09

Posted 01 April 2012 - 05:45 PM

Did i miss something but did the tutorials stop? is there a part 5?
Was This Post Helpful? 0
  • +
  • -

#13 TheNexus  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 2
  • Joined: 13-May 12

Posted 13 May 2012 - 01:13 AM

Your code contains some mistakes and questionable style I'd like to point out:

#ifndef _ENGINE_H
#define _ENGINE_H
Identifiers that begin with underscore and captial letter are reserved for compiler and implementation. Anyway, I would use a header guard that is less likely to collide, e.g. REVTORA_TILE_ENGINE_H.

#include <SFML\Graphics.hpp>
Prefer slashes instead of backslashes, as they are portable.

Engine::Engine()
{

}

Engine::~Engine()
{

}
Empty constructor and destructor are automatically generated by the compiler. But why don't you move the Init() functionality to the constructor? That's why constructors exist, to initialize objects.

bool Engine::Init()
{
	window = new sf::RenderWindow(sf::VideoMode(800, 600, 32), "RPG");

	if(!window)
		return false;

	return true;
}
new without std::nothrow never returns a nullpointer, thus the check is useless. Furthermore, you have a memory leak, because the dynamically allocated memory is never freed. You can just use sf::RenderWindow without a pointer, there's no need for dynamic memory here. If there were, you should still prefer std::unique_ptr.

Engine* engine = new Engine();
Again, this leads to a memory leak. Is there a reason why you don't use
Engine engine;
?
Was This Post Helpful? 1
  • +
  • -

#14 stackoverflow  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 164
  • View blog
  • Posts: 545
  • Joined: 06-July 11

Posted 06 July 2012 - 06:52 PM

Very nice!
Was This Post Helpful? 0
  • +
  • -

#15 Pixelier  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 3
  • Joined: 01-August 12

Posted 01 August 2012 - 05:46 PM

Okay I need help can anyone help me asap? Okay here is what happens when i try press F5.

1>------ Build started: Project: First Game, Configuration: Debug Win32 ------
1> Engine.cpp
1>c:\users\user\documents\visual studio 2010\projects\first game\first game\engine.cpp(33): error C2039: 'PollEvent' : is not a member of 'sf::RenderWindow'
1> c:\sfml\sfml2\include\sfml\graphics\renderwindow.hpp(44) : see declaration of 'sf::RenderWindow'
1>c:\users\user\documents\visual studio 2010\projects\first game\first game\engine.cpp(33): fatal error C1903: unable to recover from previous error(s); stopping compilation
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Please help me I am fairly new to coding.
Was This Post Helpful? 0
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3