<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dev Hub &#187; SDL Tutorials</title>
	<atom:link href="http://www.sdltutorials.com/category/sdl-tutorials/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.sdltutorials.com</link>
	<description>SDL Tutorials - Game Tutorials - Programming Tutorials</description>
	<lastBuildDate>Wed, 10 Mar 2010 21:06:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>SDL Per Pixel Collision</title>
		<link>http://www.sdltutorials.com/sdl-per-pixel-collision/</link>
		<comments>http://www.sdltutorials.com/sdl-per-pixel-collision/#comments</comments>
		<pubDate>Thu, 28 Jan 2010 21:52:40 +0000</pubDate>
		<dc:creator>Jason Norris</dc:creator>
				<category><![CDATA[SDL Tutorials]]></category>

		<guid isPermaLink="false">http://www.sdltutorials.com/?p=213</guid>
		<description><![CDATA[Are bounding box and circle collisions just not cutting it? Well, now we&#8217;re going to dive right down into pixel precision!

Before we start, I&#8217;d like to say that this is an advanced SDL tutorial. You should have experience with creating SDL applications and some basic knowledge of getting a program with it&#8217;s libraries up and [...]]]></description>
			<content:encoded><![CDATA[<p>Are bounding box and circle collisions just not cutting it? Well, now we&#8217;re going to dive right down into pixel precision!<br />
<span id="more-213"></span></p>
<p>Before we start, I&#8217;d like to say that this is an advanced SDL tutorial. You should have experience with creating SDL applications and some basic knowledge of getting a program with it&#8217;s libraries up and running.</p>
<p>First, we&#8217;ll start off with a very simple Game class to build the foundation of our demo project.</p>
<p><strong>Game.h</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef GAME_H</span><br />
<span class="co2">#define GAME_H</span></p>
<p><span class="co2">#include &quot;SDL.h&quot;</span></p>
<p><span class="kw2">class</span> Game<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; Game<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; ~Game<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnExecute<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnThink<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnUpdate<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnRender<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">private</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> ScreenWidth;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> ScreenHeight;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> ScreenBPP;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Uint32 ScreenFlags;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">bool</span> done;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">double</span> thisTime;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">double</span> lastTime;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">double</span> deltaTime;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; SDL_Surface* screen;<br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Event event;<br />
<span class="br0">&#125;</span>;</p>
<p><span class="co2">#endif</span><br />
&nbsp;</div>
<p><strong>Game.cpp</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;Game.h&quot;</span></p>
<p>Game::<span class="me2">Game</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; ScreenWidth = <span class="nu0">800</span>;<br />
&nbsp; &nbsp; ScreenHeight = <span class="nu0">600</span>;<br />
&nbsp; &nbsp; ScreenBPP = <span class="nu0">32</span>;<br />
&nbsp;&nbsp; &nbsp;ScreenFlags = SDL_HWSURFACE | SDL_DOUBLEBUF;</p>
<p>&nbsp; &nbsp; thisTime = <span class="nu0">0.0</span>;<br />
&nbsp; &nbsp; lastTime = <span class="nu0">0.0</span>;<br />
&nbsp; &nbsp; deltaTime = <span class="nu0">0.0</span>;</p>
<p>&nbsp; &nbsp; done = <span class="kw2">false</span>;</p>
<p>&nbsp; &nbsp; SDL_Init<span class="br0">&#40;</span>SDL_INIT_EVERYTHING<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; SDL_WM_SetCaption<span class="br0">&#40;</span><span class="st0">&quot;SDL Per Pixel Collision&quot;</span>, <span class="kw2">NULL</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; SDL_ShowCursor<span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; screen = SDL_SetVideoMode<span class="br0">&#40;</span>ScreenWidth, ScreenHeight, ScreenBPP, ScreenFlags<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p>Game::~Game<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_Quit<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> Game::<span class="me2">OnExecute</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">while</span><span class="br0">&#40;</span>!done<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; OnThink<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; OnUpdate<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; OnRender<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> Game::<span class="me2">OnThink</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">while</span><span class="br0">&#40;</span>SDL_PollEvent<span class="br0">&#40;</span>&amp;event<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>event.<span class="me1">type</span> == SDL_QUIT<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; done = <span class="kw2">true</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>event.<span class="me1">type</span> == SDL_KEYDOWN<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>event.<span class="me1">key</span>.<span class="me1">keysym</span>.<span class="me1">sym</span> == SDLK_ESCAPE<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; done = <span class="kw2">true</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> Game::<span class="me2">OnUpdate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; lastTime = thisTime;<br />
&nbsp; &nbsp; thisTime = SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; deltaTime = <span class="br0">&#40;</span>thisTime &#8211; lastTime<span class="br0">&#41;</span> / <span class="nu0">1000.0</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> Game::<span class="me2">OnRender</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_FillRect<span class="br0">&#40;</span>screen, <span class="kw2">NULL</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; SDL_Flip<span class="br0">&#40;</span>screen<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">int</span> main<span class="br0">&#40;</span><span class="kw4">int</span> argc, <span class="kw4">char</span>* args<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; Game game;<br />
&nbsp; &nbsp; game.<span class="me1">OnExecute</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>You should be able to compile and run at this point. Now we have a nice 800&#215;600 window prepared for our bidding! The three <strong>double</strong> variables are used at keep track of elapsed time each tick. You can simply substitute in your favorite Timer class if you wish. I also turn off cursor visibility since we&#8217;ll be controlling an object with the mouse and we don&#8217;t want it to obscure our view.</p>
<p>Now we&#8217;ll need some sort of objects that we can collide together!</p>
<p><strong>Entity.h</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef ENTITY_H</span><br />
<span class="co2">#define ENTITY_H</span></p>
<p><span class="co2">#include &quot;SDL.h&quot;</span><br />
<span class="co2">#include &quot;SDL_image.h&quot;</span></p>
<p><span class="kw4">struct</span> Vector<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">float</span> X;<br />
&nbsp; &nbsp; <span class="kw4">float</span> Y;</p>
<p>&nbsp; &nbsp; Vector<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; X = <span class="nu0">0</span>.0f;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Y = <span class="nu0">0</span>.0f;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span>;</p>
<p><span class="kw2">class</span> Entity<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; Entity<span class="br0">&#40;</span><span class="kw4">char</span>* filename, <span class="kw4">int</span> tilesX, <span class="kw4">int</span> tilesY, <span class="kw4">double</span> frameRate<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; ~Entity<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; Vector position;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Vector origin;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Surface* surface;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> tilesX;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> tilesY;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> tileWidth;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> tileHeight;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> frame;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> frameCount;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">double</span> frameInterval;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">double</span> frameTimeRemaining;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:&nbsp;&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> Update<span class="br0">&#40;</span><span class="kw4">double</span> deltaTime<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> Render<span class="br0">&#40;</span>SDL_Surface* screen<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;</p>
<p><span class="co2">#endif</span><br />
&nbsp;</div>
<p>Simple enough, I hope. For each Entity we create, we&#8217;ll take in a filename for the for the image we&#8217;ll be loading. If you didn&#8217;t notice, SDL_image is included, as I&#8217;ll be working with PNG files with alpha transparency. Next, we take in the tiles across and tiles down in the spritesheet we&#8217;ll be using. Finally, a frame rate to determine how fast the sprite will animate.</p>
<p>Next, the member variables. I&#8217;ve created a simple Vector struct to hold position and origin information. Position is where the Entity will sit on the screen and origin is the center of the tile currently being drawn. This will make things simpler when we want to draw a sprite centered on it&#8217;s position. Of course, an SDL_Surface pointer to hold the image data we&#8217;ll be using. And last, variables to hold information about the spritesheet we&#8217;ll be using and handling animation.</p>
<p>Finally, two methods to update and render the given Entity. Now let&#8217;s implement these!</p>
<p><strong>Entity.cpp</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;Entity.h&quot;</span></p>
<p>Entity::<span class="me2">Entity</span><span class="br0">&#40;</span><span class="kw4">char</span>* filename, <span class="kw4">int</span> tilesX, <span class="kw4">int</span> tilesY, <span class="kw4">double</span> frameRate<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; this-&gt;surface = IMG_Load<span class="br0">&#40;</span>filename<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; this-&gt;tilesX = tilesX;<br />
&nbsp; &nbsp; this-&gt;tilesY = tilesY;<br />
&nbsp; &nbsp; this-&gt;tileWidth = surface-&gt;w / tilesX;<br />
&nbsp; &nbsp; this-&gt;tileHeight = surface-&gt;h / tilesY;<br />
&nbsp; &nbsp; this-&gt;frame = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; this-&gt;frameCount = tilesX * tilesY;<br />
&nbsp; &nbsp; this-&gt;frameInterval = <span class="nu0">1</span> / frameRate;<br />
&nbsp; &nbsp; this-&gt;frameTimeRemaining = frameInterval;</p>
<p>&nbsp; &nbsp; this-&gt;origin.<span class="me1">X</span> = tileWidth / <span class="nu0">2</span>.0f;<br />
&nbsp; &nbsp; this-&gt;origin.<span class="me1">Y</span> = tileHeight / <span class="nu0">2</span>.0f;<br />
<span class="br0">&#125;</span></p>
<p>Entity::~Entity<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_FreeSurface<span class="br0">&#40;</span>surface<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> Entity::<span class="me2">Update</span><span class="br0">&#40;</span><span class="kw4">double</span> deltaTime<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; frameTimeRemaining -= deltaTime;<br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>frameTimeRemaining &lt; <span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; frame++;<br />
&nbsp; &nbsp; &nbsp; &nbsp; frame %= frameCount;<br />
&nbsp; &nbsp; &nbsp; &nbsp; frameTimeRemaining = frameInterval;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> Entity::<span class="me2">Render</span><span class="br0">&#40;</span>SDL_Surface* screen<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_Rect location = GetBounds<span class="br0">&#40;</span><span class="br0">&#41;</span>;&nbsp; &nbsp; <br />
&nbsp; &nbsp; SDL_Rect clip = GetFrameBounds<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; SDL_BlitSurface<span class="br0">&#40;</span>surface, &amp;clip, screen, &amp;location<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>The constructor loads in our image using IMG_Load() and stores all our data about the sprite sheet. The destructor ensures we have no memory leaks by freeing our SDL_Surface. Update chips away at our frameTimeRemaining with a given deltaTime. Once we hit or are under zero, we increase the frame, wrap around to the beginning if need be, and reset our frameTimeRemaining with our given frameInterval. Render finds our location and clip rectangles and then blits the surface to the screen. But wait, we haven&#8217;t added GetBounds or GetFrameBounds() yet. I&#8217;m sure those will be useful to have! Let&#8217;s get to that!</p>
<p>Add these method definitions in:</p>
<p><strong>Entity.h</strong></p>
<div class="dean_ch" style="white-space: wrap;">
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Rect GetBounds<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Rect GetFrameBounds<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>And now we&#8217;ll implement them:</p>
<p><strong>Entity.cpp</strong></p>
<div class="dean_ch" style="white-space: wrap;">
SDL_Rect Entity::<span class="me2">GetBounds</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_Rect bounds;<br />
&nbsp; &nbsp; bounds.<span class="me1">x</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>position.<span class="me1">X</span> &#8211; origin.<span class="me1">X</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; bounds.<span class="me1">y</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>position.<span class="me1">Y</span> &#8211; origin.<span class="me1">Y</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; bounds.<span class="me1">w</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>tileWidth<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; bounds.<span class="me1">h</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>tileHeight<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> bounds;<br />
<span class="br0">&#125;</span></p>
<p>SDL_Rect Entity::<span class="me2">GetFrameBounds</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_Rect frameBounds;<br />
&nbsp; &nbsp; frameBounds.<span class="me1">x</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>frame % tilesX * tileWidth<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; frameBounds.<span class="me1">y</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>frame / tilesX * tileHeight<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; frameBounds.<span class="me1">w</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>tileWidth<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; frameBounds.<span class="me1">h</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>tileHeight<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">return</span> frameBounds;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>GetBounds() takes our position and shifts it over by our origin. This places the position at the center of the sprite, rather than the top left. GetFramesBound() checks what frame we&#8217;re on and finds the matching coordinates. Very important for animation!</p>
<p>Now lets slap a couple of these suckers into our demo!</p>
<p><strong>Game.h</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;Entity.h&quot;</span></p>
<p><span class="kw2">class</span> Game<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &#8230;</p>
<p>&nbsp; &nbsp; <span class="kw2">private</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; Entity* ship;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Entity* asteroid;<br />
<span class="br0">&#125;</span>;<br />
&nbsp;</div>
<p>Make sure you include Entity.h so we can actually use the class and we&#8217;ll add two Entity pointers to our Game class.</p>
<p><strong>Game.cpp</strong></p>
<div class="dean_ch" style="white-space: wrap;">
Game::<span class="me2">Game</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &#8230;</p>
<p>&nbsp; &nbsp; <span class="me1">ship</span> = <span class="kw3">new</span> Entity<span class="br0">&#40;</span><span class="st0">&quot;images/ship.png&quot;</span>, <span class="nu0">4</span>, <span class="nu0">3</span>, <span class="nu0">10</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; asteroid = <span class="kw3">new</span> Entity<span class="br0">&#40;</span><span class="st0">&quot;images/asteroid.png&quot;</span>, <span class="nu0">5</span>, <span class="nu0">6</span>, <span class="nu0">30</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; asteroid-&gt;position.<span class="me1">X</span> = <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span>ScreenWidth / <span class="nu0">2</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; asteroid-&gt;position.<span class="me1">Y</span> = <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span>ScreenHeight / <span class="nu0">2</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p>Game::~Game<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw3">delete</span> ship;<br />
&nbsp; &nbsp; <span class="kw3">delete</span> asteroid;</p>
<p>&nbsp; &nbsp; &#8230;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Image: <a href="http://i49.tinypic.com/2zq6849.png">Ship</a><br />
Image: <a href="http://i45.tinypic.com/t4zs6q.png">Asteroid</a><br />
(Special thanks to 3DBuzz for these images.)</p>
<p>We&#8217;ll now dynamically allocate memory for our two new Entity objects. I have my images sitting in an &#8220;images&#8221; folder, but you may do whatever you want! I then position the asteroid at the center of the screen. And because we&#8217;re mindful programmers, we&#8217;ll delete the allocated memory once we&#8217;re all done.</p>
<p><strong>Game.cpp</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> Game::<span class="me2">OnThink</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">while</span><span class="br0">&#40;</span>SDL_PollEvent<span class="br0">&#40;</span>&amp;event<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>event.<span class="me1">type</span> == SDL_QUIT<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; done = <span class="kw2">true</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>event.<span class="me1">type</span> == SDL_KEYDOWN<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>event.<span class="me1">key</span>.<span class="me1">keysym</span>.<span class="me1">sym</span> == SDLK_ESCAPE<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; done = <span class="kw2">true</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>event.<span class="me1">type</span> == SDL_MOUSEMOTION<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ship-&gt;position.<span class="me1">X</span> = event.<span class="me1">motion</span>.<span class="me1">x</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ship-&gt;position.<span class="me1">Y</span> = event.<span class="me1">motion</span>.<span class="me1">y</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> Game::<span class="me2">OnUpdate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; lastTime = thisTime;<br />
&nbsp; &nbsp; thisTime = SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; deltaTime = <span class="br0">&#40;</span>thisTime &#8211; lastTime<span class="br0">&#41;</span> / <span class="nu0">1000.0</span>;</p>
<p>&nbsp; &nbsp; ship-&gt;Update<span class="br0">&#40;</span>deltaTime<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; asteroid-&gt;Update<span class="br0">&#40;</span>deltaTime<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> Game::<span class="me2">OnRender</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_FillRect<span class="br0">&#40;</span>screen, <span class="kw2">NULL</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; ship-&gt;Render<span class="br0">&#40;</span>screen<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; asteroid-&gt;Render<span class="br0">&#40;</span>screen<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; SDL_Flip<span class="br0">&#40;</span>screen<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>In OnThink, we&#8217;ll mouse movement to our ship by looking for an SDL_MOUSEMOTION event while polling for events. In OnUpdate, we&#8217;ll simply call each Entity&#8217;s Update method with the deltaTime we found. Lastly, in OnRender, we&#8217;ll just call the Render method by passing our screen.</p>
<p>Compile, run, and give it a whirl! Weeee! We now have two animated sprites, one centered in the screen and one controlled by our mouse. But where&#8217;s the collision? Oh yeah, we haven&#8217;t implemented it yet!</p>
<p>We&#8217;ll need a bit more functionally in our Entity class, so let&#8217;s work on that. This one&#8217;s a doozy, so hold on tight! But don&#8217;t worry, we&#8217;ll take it one step at a time&#8230;</p>
<p><strong>Entity.h</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw2">class</span> Entity<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &#8230;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Rect NormalizeBounds<span class="br0">&#40;</span><span class="kw4">const</span> SDL_Rect&amp; rect<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> SDL_Rect Intersection<span class="br0">&#40;</span><span class="kw4">const</span> SDL_Rect&amp; boundsA, <span class="kw4">const</span> SDL_Rect&amp; boundsB<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">bool</span> CheckCollision<span class="br0">&#40;</span>Entity* entityA, Entity* entityB<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">bool</span> GetAlphaXY<span class="br0">&#40;</span>Entity* entity, <span class="kw4">int</span> x, <span class="kw4">int</span> y<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;<br />
&nbsp;</div>
<p><strong>Entity.cpp</strong></p>
<div class="dean_ch" style="white-space: wrap;">
SDL_Rect Entity::<span class="me2">NormalizeBounds</span><span class="br0">&#40;</span><span class="kw4">const</span> SDL_Rect&amp; rect<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_Rect normalized;<br />
&nbsp; &nbsp; normalized.<span class="me1">x</span> = rect.<span class="me1">x</span> &#8211; <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span>position.<span class="me1">X</span> + <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span>origin.<span class="me1">X</span> + GetFrameBounds<span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">x</span>;<br />
&nbsp; &nbsp; normalized.<span class="me1">y</span> = rect.<span class="me1">y</span> &#8211; <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span>position.<span class="me1">Y</span> + <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span>origin.<span class="me1">Y</span> + GetFrameBounds<span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">y</span>;<br />
&nbsp; &nbsp; normalized.<span class="me1">w</span> = rect.<span class="me1">w</span>;<br />
&nbsp; &nbsp; normalized.<span class="me1">h</span> = rect.<span class="me1">h</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">return</span> normalized;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Given the SDL_Rect of a collision rectangle, we want to find what pixels on the sprite sheet correlate to it. A little messy, but it gets the job done.</p>
<p><strong>Entity.cpp</strong></p>
<div class="dean_ch" style="white-space: wrap;">
SDL_Rect Entity::<span class="me2">Intersection</span><span class="br0">&#40;</span><span class="kw4">const</span> SDL_Rect&amp; boundsA, <span class="kw4">const</span> SDL_Rect&amp; boundsB<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">int</span> x1 = Maximum<span class="br0">&#40;</span>boundsA.<span class="me1">x</span>, boundsB.<span class="me1">x</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">int</span> y1 = Maximum<span class="br0">&#40;</span>boundsA.<span class="me1">y</span>, boundsB.<span class="me1">y</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">int</span> x2 = Minimum<span class="br0">&#40;</span>boundsA.<span class="me1">x</span> + boundsA.<span class="me1">w</span>, boundsB.<span class="me1">x</span> + boundsB.<span class="me1">w</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">int</span> y2 = Minimum<span class="br0">&#40;</span>boundsA.<span class="me1">y</span> + boundsA.<span class="me1">h</span>, boundsB.<span class="me1">y</span> + boundsB.<span class="me1">h</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw4">int</span> width = x2 &#8211; x1;<br />
&nbsp; &nbsp; <span class="kw4">int</span> height = y2 &#8211; y1;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>width &gt; <span class="nu0">0</span> &amp;&amp; height &gt; <span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Rect intersect = <span class="br0">&#123;</span>x1, y1, width, height<span class="br0">&#125;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> intersect;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Rect intersect = <span class="br0">&#123;</span><span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span><span class="br0">&#125;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> intersect;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Given the two bounds of two entities, we want to find how much they intersect, if at all. If they do, we&#8217;re given their intersection rectangle, if not, we&#8217;re given an empty rectangle. For Max and Min, you can either include &#8220;cmath&#8221; or use a couple macros such as this:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#define Maximum(a, b) ((a &gt; b) ? a : b)</span><br />
<span class="co2">#define Minimum(a, b) ((a &lt; b) ? a : b)</span><br />
&nbsp;</div>
<p><strong>Entity.cpp</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">bool</span> Entity::<span class="me2">CheckCollision</span><span class="br0">&#40;</span>Entity* entityA, Entity* entityB<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_Rect collisionRect = Intersection<span class="br0">&#40;</span>entityA-&gt;GetBounds<span class="br0">&#40;</span><span class="br0">&#41;</span>, entityB-&gt;GetBounds<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>collisionRect.<span class="me1">w</span> == <span class="nu0">0</span> &amp;&amp; collisionRect.<span class="me1">h</span> == <span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;</p>
<p>&nbsp; &nbsp; SDL_Rect normalA = entityA-&gt;NormalizeBounds<span class="br0">&#40;</span>collisionRect<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; SDL_Rect normalB = entityB-&gt;NormalizeBounds<span class="br0">&#40;</span>collisionRect<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> y = <span class="nu0">0</span>; y &lt; collisionRect.<span class="me1">h</span>; y++<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> x = <span class="nu0">0</span>; x &lt; collisionRect.<span class="me1">w</span>; x++<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>GetAlphaXY<span class="br0">&#40;</span>entityA, normalA.<span class="me1">x</span> + x, normalA.<span class="me1">y</span> + y<span class="br0">&#41;</span> &amp;&amp; GetAlphaXY<span class="br0">&#40;</span>entityB, normalB.<span class="me1">x</span> + x, normalB.<span class="me1">y</span> + y<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>This is where bulk of our per pixel collision check happens. First, we ensure there&#8217;s even a bounding box collision. No use going through all the trouble when we know nothing will happen. Then we normalize the bounds of each entity with the found collision rectangle. This will give us the region of pixels we&#8217;ll be comparing against each other. You&#8217;ll notice this GetAlphaXY() function. This is where we&#8217;ll get down into the pixels and determine if they&#8217;re solid enough for collision. You&#8217;ll see that it&#8217;s called twice in one if-statement. This is because we&#8217;re searching for a solid enough pixel in each surface at the same position. Once that is found, we&#8217;ll confirm a hit!</p>
<p><strong>Entity.cpp</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">bool</span> Entity::<span class="me2">GetAlphaXY</span><span class="br0">&#40;</span>Entity* entity, <span class="kw4">int</span> x, <span class="kw4">int</span> y<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">int</span> bpp = entity-&gt;surface-&gt;format-&gt;BytesPerPixel;<br />
&nbsp; &nbsp; Uint8* p = <span class="br0">&#40;</span>Uint8*<span class="br0">&#41;</span>entity-&gt;surface-&gt;pixels + y * entity-&gt;surface-&gt;pitch + x * bpp;<br />
&nbsp; &nbsp; Uint32 pixelColor;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">switch</span><span class="br0">&#40;</span>bpp<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pixelColor = *p;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span><span class="br0">&#40;</span><span class="nu0">2</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pixelColor = *<span class="br0">&#40;</span>Uint16*<span class="br0">&#41;</span>p;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span><span class="br0">&#40;</span><span class="nu0">3</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>SDL_BYTEORDER == SDL_BIG_ENDIAN<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pixelColor = p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> &lt;&lt; <span class="nu0">16</span> | p<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> &lt;&lt; <span class="nu0">8</span> | p<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pixelColor = p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> | p<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> &lt;&lt; <span class="nu0">8</span> | p<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span> &lt;&lt; <span class="nu0">16</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span><span class="br0">&#40;</span><span class="nu0">4</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pixelColor = *<span class="br0">&#40;</span>Uint32*<span class="br0">&#41;</span>p;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; Uint8 red, green, blue, alpha;<br />
&nbsp; &nbsp; SDL_GetRGBA<span class="br0">&#40;</span>pixelColor, entity-&gt;surface-&gt;format, &amp;red, &amp;green, &amp;blue, &amp;alpha<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> alpha &gt; <span class="nu0">200</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Oh my, some crazy looking stuff here! It&#8217;s not that bad. Let me explain a few things here.</p>
<p>We&#8217;re passing in a pointer to an Entity and an (x,y) coordinate. All we&#8217;re doing in this function is finding the pixel at that coordinate and determining what colors its composed of. The first two lines give us a pointer to the pixel in question. The funky looking switch-statement is finding the color composition depending on the image&#8217;s bytes-per-pixel format, either 8-bit, 16-bit, 24-bit, or 32-bit. In our case, it will always land on case(4), but this should give you an idea on how to expand to other formats.</p>
<p>Finally, we&#8217;re grabbing the RGBA components of the pixel using SDL_GetRGBA. All we care about is alpha, but you can experiment with collision where hits will only happen when a pixel is red or blue enough. Alpha will range between 0 and 255. I wanted collision to happen with not just pixels that were completely opaque, but not too transparent. I found 200 to be a nice number, but you&#8217;re free to tweak as you please.</p>
<p>Well that&#8217;s it! Our Entity class has the functionally to test for per pixel collision&#8230; so lets show it off!</p>
<p> <strong>Game.cpp</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> Game::<span class="me2">OnRender</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_FillRect<span class="br0">&#40;</span>screen, <span class="kw2">NULL</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; SDL_Rect collisionRect = Entity::<span class="me2">Intersection</span><span class="br0">&#40;</span>ship-&gt;GetBounds<span class="br0">&#40;</span><span class="br0">&#41;</span>, asteroid-&gt;GetBounds<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>collisionRect.<span class="me1">w</span> != <span class="nu0">0</span> &amp;&amp; collisionRect.<span class="me1">h</span> != <span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>Entity::<span class="me2">CheckCollision</span><span class="br0">&#40;</span>ship, asteroid<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDL_FillRect<span class="br0">&#40;</span>screen, &amp;collisionRect, SDL_MapRGB<span class="br0">&#40;</span>screen-&gt;format, <span class="nu0">255</span>, <span class="nu0">0</span>, <span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDL_FillRect<span class="br0">&#40;</span>screen, &amp;collisionRect, SDL_MapRGB<span class="br0">&#40;</span>screen-&gt;format, <span class="nu0">0</span>, <span class="nu0">255</span>, <span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; ship-&gt;Render<span class="br0">&#40;</span>screen<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; asteroid-&gt;Render<span class="br0">&#40;</span>screen<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; SDL_Flip<span class="br0">&#40;</span>screen<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Adding this checks for collision between our ship and asteroid. When bounding box collision happens, a green box will be drawn behind them. When per pixel collision happens, the box will turn red!</p>
<p>Well, that&#8217;s about it. Run, compile, and enjoy! You now have per pixel collision checks between your two Entity objects! Feel free to tweak numbers, use different images, or control them in different ways! I&#8217;ve given you the foundation, now go out there and create some interesting implementations!</p>
<p>Here&#8217;s the final code in case you may have some errors and need to check against my own.</p>
<p><strong>Game.h</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef GAME_H</span><br />
<span class="co2">#define GAME_H</span></p>
<p><span class="co2">#include &quot;Entity.h&quot;</span></p>
<p><span class="kw2">class</span> Game<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; Game<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; ~Game<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnExecute<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnThink<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnUpdate<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnRender<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">private</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> ScreenWidth;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> ScreenHeight;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> ScreenBPP;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Uint32 ScreenFlags;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">bool</span> done;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">double</span> thisTime;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">double</span> lastTime;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">double</span> deltaTime;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; SDL_Surface* screen;<br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Event event;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; Entity* ship;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Entity* asteroid;<br />
<span class="br0">&#125;</span>;</p>
<p><span class="co2">#endif</span><br />
&nbsp;</div>
<p><strong>Game.cpp</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;Game.h&quot;</span></p>
<p>Game::<span class="me2">Game</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; ScreenWidth = <span class="nu0">800</span>;<br />
&nbsp; &nbsp; ScreenHeight = <span class="nu0">600</span>;<br />
&nbsp; &nbsp; ScreenBPP = <span class="nu0">32</span>;<br />
&nbsp; &nbsp; ScreenFlags = SDL_HWSURFACE | SDL_DOUBLEBUF;</p>
<p>&nbsp; &nbsp; done = <span class="kw2">false</span>;</p>
<p>&nbsp; &nbsp; thisTime = <span class="nu0">0.0</span>;<br />
&nbsp; &nbsp; lastTime = <span class="nu0">0.0</span>;<br />
&nbsp; &nbsp; deltaTime = <span class="nu0">0.0</span>;</p>
<p>&nbsp; &nbsp; SDL_Init<span class="br0">&#40;</span>SDL_INIT_EVERYTHING<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; SDL_WM_SetCaption<span class="br0">&#40;</span><span class="st0">&quot;SDL Per Pixel Collision&quot;</span>, <span class="kw2">NULL</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; SDL_ShowCursor<span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; screen = SDL_SetVideoMode<span class="br0">&#40;</span>ScreenWidth, ScreenHeight, ScreenBPP, ScreenFlags<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; ship = <span class="kw3">new</span> Entity<span class="br0">&#40;</span><span class="st0">&quot;images/ship.png&quot;</span>, <span class="nu0">4</span>, <span class="nu0">3</span>, <span class="nu0">10</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; asteroid = <span class="kw3">new</span> Entity<span class="br0">&#40;</span><span class="st0">&quot;images/asteroid.png&quot;</span>, <span class="nu0">5</span>, <span class="nu0">6</span>, <span class="nu0">30</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; asteroid-&gt;position.<span class="me1">X</span> = <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span>ScreenWidth / <span class="nu0">2</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; asteroid-&gt;position.<span class="me1">Y</span> = <span class="br0">&#40;</span><span class="kw4">float</span><span class="br0">&#41;</span><span class="br0">&#40;</span>ScreenHeight / <span class="nu0">2</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p>Game::~Game<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw3">delete</span> ship;<br />
&nbsp; &nbsp; <span class="kw3">delete</span> asteroid;</p>
<p>&nbsp; &nbsp; SDL_Quit<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> Game::<span class="me2">OnExecute</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">while</span><span class="br0">&#40;</span>!done<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; OnThink<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; OnUpdate<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; OnRender<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> Game::<span class="me2">OnThink</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">while</span><span class="br0">&#40;</span>SDL_PollEvent<span class="br0">&#40;</span>&amp;event<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>event.<span class="me1">type</span> == SDL_QUIT<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; done = <span class="kw2">true</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>event.<span class="me1">type</span> == SDL_KEYDOWN<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>event.<span class="me1">key</span>.<span class="me1">keysym</span>.<span class="me1">sym</span> == SDLK_ESCAPE<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; done = <span class="kw2">true</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>event.<span class="me1">type</span> == SDL_MOUSEMOTION<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ship-&gt;position.<span class="me1">X</span> = event.<span class="me1">motion</span>.<span class="me1">x</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ship-&gt;position.<span class="me1">Y</span> = event.<span class="me1">motion</span>.<span class="me1">y</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> Game::<span class="me2">OnUpdate</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; lastTime = thisTime;<br />
&nbsp; &nbsp; thisTime = SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; deltaTime = <span class="br0">&#40;</span>thisTime &#8211; lastTime<span class="br0">&#41;</span> / <span class="nu0">1000.0</span>;</p>
<p>&nbsp; &nbsp; ship-&gt;Update<span class="br0">&#40;</span>deltaTime<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; asteroid-&gt;Update<span class="br0">&#40;</span>deltaTime<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> Game::<span class="me2">OnRender</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_FillRect<span class="br0">&#40;</span>screen, <span class="kw2">NULL</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>collisionRect.<span class="me1">w</span> != <span class="nu0">0</span> &amp;&amp; collisionRect.<span class="me1">h</span> != <span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>Entity::<span class="me2">CheckCollision</span><span class="br0">&#40;</span>ship, asteroid<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDL_FillRect<span class="br0">&#40;</span>screen, &amp;collisionRect, SDL_MapRGB<span class="br0">&#40;</span>screen-&gt;format, <span class="nu0">255</span>, <span class="nu0">0</span>, <span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDL_FillRect<span class="br0">&#40;</span>screen, &amp;collisionRect, SDL_MapRGB<span class="br0">&#40;</span>screen-&gt;format, <span class="nu0">0</span>, <span class="nu0">255</span>, <span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; ship-&gt;Render<span class="br0">&#40;</span>screen<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; asteroid-&gt;Render<span class="br0">&#40;</span>screen<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; SDL_Flip<span class="br0">&#40;</span>screen<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">int</span> main<span class="br0">&#40;</span><span class="kw4">int</span> argc, <span class="kw4">char</span>* args<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; Game game;<br />
&nbsp; &nbsp; game.<span class="me1">OnExecute</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span></p>
<p>&nbsp;</p></div>
<p><strong>Entity.h</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef ENTITY_H</span><br />
<span class="co2">#define ENTITY_H</span></p>
<p><span class="co2">#include &quot;SDL.h&quot;</span><br />
<span class="co2">#include &quot;SDL_image.h&quot;</span></p>
<p><span class="kw4">struct</span> Vector<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">float</span> X;<br />
&nbsp; &nbsp; <span class="kw4">float</span> Y;</p>
<p>&nbsp; &nbsp; Vector<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; X = <span class="nu0">0</span>.0f;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Y = <span class="nu0">0</span>.0f;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span>;</p>
<p><span class="kw2">class</span> Entity<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; Entity<span class="br0">&#40;</span><span class="kw4">char</span>* filename, <span class="kw4">int</span> tilesX, <span class="kw4">int</span> tilesY, <span class="kw4">double</span> frameRate<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; ~Entity<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; Vector position;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Vector origin;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Surface* surface;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> tilesX;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> tilesY;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> tileWidth;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> tileHeight;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> frame;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> frameCount;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">double</span> frameInterval;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">double</span> frameTimeRemaining;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:&nbsp;&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> Update<span class="br0">&#40;</span><span class="kw4">double</span> deltaTime<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> Render<span class="br0">&#40;</span>SDL_Surface* screen<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Rect GetBounds<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Rect GetFrameBounds<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Rect NormalizeBounds<span class="br0">&#40;</span><span class="kw4">const</span> SDL_Rect&amp; rect<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> SDL_Rect Intersection<span class="br0">&#40;</span><span class="kw4">const</span> SDL_Rect&amp; boundsA, <span class="kw4">const</span> SDL_Rect&amp; boundsB<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">bool</span> CheckCollision<span class="br0">&#40;</span>Entity* entityA, Entity* entityB<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">bool</span> GetAlphaXY<span class="br0">&#40;</span>Entity* entity, <span class="kw4">int</span> x, <span class="kw4">int</span> y<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;</p>
<p><span class="co2">#endif</span><br />
&nbsp;</div>
<p><strong>Entity.cpp</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;Entity.h&quot;</span></p>
<p><span class="co2">#define Maximum(a, b) ((a &gt; b) ? a : b)</span><br />
<span class="co2">#define Minimum(a, b) ((a &lt; b) ? a : b)</span></p>
<p>Entity::<span class="me2">Entity</span><span class="br0">&#40;</span><span class="kw4">char</span>* filename, <span class="kw4">int</span> tilesX, <span class="kw4">int</span> tilesY, <span class="kw4">double</span> frameRate<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; this-&gt;surface = IMG_Load<span class="br0">&#40;</span>filename<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; this-&gt;tilesX = tilesX;<br />
&nbsp; &nbsp; this-&gt;tilesY = tilesY;<br />
&nbsp; &nbsp; this-&gt;tileWidth = surface-&gt;w / tilesX;<br />
&nbsp; &nbsp; this-&gt;tileHeight = surface-&gt;h / tilesY;<br />
&nbsp; &nbsp; this-&gt;frame = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; this-&gt;frameCount = tilesX * tilesY;<br />
&nbsp; &nbsp; this-&gt;frameInterval = <span class="nu0">1</span> / frameRate;<br />
&nbsp; &nbsp; this-&gt;frameTimeRemaining = frameInterval;</p>
<p>&nbsp; &nbsp; this-&gt;origin.<span class="me1">X</span> = tileWidth / <span class="nu0">2</span>.0f;<br />
&nbsp; &nbsp; this-&gt;origin.<span class="me1">Y</span> = tileHeight / <span class="nu0">2</span>.0f;<br />
<span class="br0">&#125;</span></p>
<p>Entity::~Entity<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_FreeSurface<span class="br0">&#40;</span>surface<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> Entity::<span class="me2">Update</span><span class="br0">&#40;</span><span class="kw4">double</span> deltaTime<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; frameTimeRemaining -= deltaTime;<br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>frameTimeRemaining &lt; <span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; frame++;<br />
&nbsp; &nbsp; &nbsp; &nbsp; frame %= frameCount;<br />
&nbsp; &nbsp; &nbsp; &nbsp; frameTimeRemaining = frameInterval;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> Entity::<span class="me2">Render</span><span class="br0">&#40;</span>SDL_Surface* screen<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_Rect location = GetBounds<span class="br0">&#40;</span><span class="br0">&#41;</span>;&nbsp; &nbsp; <br />
&nbsp; &nbsp; SDL_Rect clip = GetFrameBounds<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; SDL_BlitSurface<span class="br0">&#40;</span>surface, &amp;clip, screen, &amp;location<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p>SDL_Rect Entity::<span class="me2">GetBounds</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_Rect bounds;<br />
&nbsp; &nbsp; bounds.<span class="me1">x</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>position.<span class="me1">X</span> &#8211; origin.<span class="me1">X</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; bounds.<span class="me1">y</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>position.<span class="me1">Y</span> &#8211; origin.<span class="me1">Y</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; bounds.<span class="me1">w</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>tileWidth<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; bounds.<span class="me1">h</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>tileHeight<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> bounds;<br />
<span class="br0">&#125;</span></p>
<p>SDL_Rect Entity::<span class="me2">GetFrameBounds</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_Rect frameBounds;<br />
&nbsp; &nbsp; frameBounds.<span class="me1">x</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>frame % tilesX * tileWidth<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; frameBounds.<span class="me1">y</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>frame / tilesX * tileHeight<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; frameBounds.<span class="me1">w</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>tileWidth<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; frameBounds.<span class="me1">h</span> = <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span><span class="br0">&#40;</span>tileHeight<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">return</span> frameBounds;<br />
<span class="br0">&#125;</span></p>
<p>SDL_Rect Entity::<span class="me2">NormalizeBounds</span><span class="br0">&#40;</span><span class="kw4">const</span> SDL_Rect&amp; rect<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_Rect normalized;<br />
&nbsp; &nbsp; normalized.<span class="me1">x</span> = rect.<span class="me1">x</span> &#8211; <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span>position.<span class="me1">X</span> + <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span>origin.<span class="me1">X</span> + GetFrameBounds<span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">x</span>;<br />
&nbsp; &nbsp; normalized.<span class="me1">y</span> = rect.<span class="me1">y</span> &#8211; <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span>position.<span class="me1">Y</span> + <span class="br0">&#40;</span>Sint16<span class="br0">&#41;</span>origin.<span class="me1">Y</span> + GetFrameBounds<span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">y</span>;<br />
&nbsp; &nbsp; normalized.<span class="me1">w</span> = rect.<span class="me1">w</span>;<br />
&nbsp; &nbsp; normalized.<span class="me1">h</span> = rect.<span class="me1">h</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">return</span> normalized;<br />
<span class="br0">&#125;</span></p>
<p>SDL_Rect Entity::<span class="me2">Intersection</span><span class="br0">&#40;</span><span class="kw4">const</span> SDL_Rect&amp; boundsA, <span class="kw4">const</span> SDL_Rect&amp; boundsB<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">int</span> x1 = Maximum<span class="br0">&#40;</span>boundsA.<span class="me1">x</span>, boundsB.<span class="me1">x</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">int</span> y1 = Maximum<span class="br0">&#40;</span>boundsA.<span class="me1">y</span>, boundsB.<span class="me1">y</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">int</span> x2 = Minimum<span class="br0">&#40;</span>boundsA.<span class="me1">x</span> + boundsA.<span class="me1">w</span>, boundsB.<span class="me1">x</span> + boundsB.<span class="me1">w</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw4">int</span> y2 = Minimum<span class="br0">&#40;</span>boundsA.<span class="me1">y</span> + boundsA.<span class="me1">h</span>, boundsB.<span class="me1">y</span> + boundsB.<span class="me1">h</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw4">int</span> width = x2 &#8211; x1;<br />
&nbsp; &nbsp; <span class="kw4">int</span> height = y2 &#8211; y1;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>width &gt; <span class="nu0">0</span> &amp;&amp; height &gt; <span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Rect intersect = <span class="br0">&#123;</span>x1, y1, width, height<span class="br0">&#125;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> intersect;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Rect intersect = <span class="br0">&#123;</span><span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span>, <span class="nu0">0</span><span class="br0">&#125;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> intersect;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">bool</span> Entity::<span class="me2">CheckCollision</span><span class="br0">&#40;</span>Entity* entityA, Entity* entityB<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_Rect collisionRect = Intersection<span class="br0">&#40;</span>entityA-&gt;GetBounds<span class="br0">&#40;</span><span class="br0">&#41;</span>, entityB-&gt;GetBounds<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>collisionRect.<span class="me1">w</span> == <span class="nu0">0</span> &amp;&amp; collisionRect.<span class="me1">h</span> == <span class="nu0">0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;</p>
<p>&nbsp; &nbsp; SDL_Rect normalA = entityA-&gt;NormalizeBounds<span class="br0">&#40;</span>collisionRect<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; SDL_Rect normalB = entityB-&gt;NormalizeBounds<span class="br0">&#40;</span>collisionRect<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> y = <span class="nu0">0</span>; y &lt; collisionRect.<span class="me1">h</span>; y++<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> x = <span class="nu0">0</span>; x &lt; collisionRect.<span class="me1">w</span>; x++<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>GetAlphaXY<span class="br0">&#40;</span>entityA, normalA.<span class="me1">x</span> + x, normalA.<span class="me1">y</span> + y<span class="br0">&#41;</span> &amp;&amp; GetAlphaXY<span class="br0">&#40;</span>entityB, normalB.<span class="me1">x</span> + x, normalB.<span class="me1">y</span> + y<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">bool</span> Entity::<span class="me2">GetAlphaXY</span><span class="br0">&#40;</span>Entity* entity, <span class="kw4">int</span> x, <span class="kw4">int</span> y<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">int</span> bpp = entity-&gt;surface-&gt;format-&gt;BytesPerPixel;<br />
&nbsp; &nbsp; Uint8* p = <span class="br0">&#40;</span>Uint8*<span class="br0">&#41;</span>entity-&gt;surface-&gt;pixels + y * entity-&gt;surface-&gt;pitch + x * bpp;<br />
&nbsp; &nbsp; Uint32 pixelColor;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">switch</span><span class="br0">&#40;</span>bpp<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pixelColor = *p;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span><span class="br0">&#40;</span><span class="nu0">2</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pixelColor = *<span class="br0">&#40;</span>Uint16*<span class="br0">&#41;</span>p;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span><span class="br0">&#40;</span><span class="nu0">3</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>SDL_BYTEORDER == SDL_BIG_ENDIAN<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pixelColor = p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> &lt;&lt; <span class="nu0">16</span> | p<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> &lt;&lt; <span class="nu0">8</span> | p<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pixelColor = p<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> | p<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> &lt;&lt; <span class="nu0">8</span> | p<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span> &lt;&lt; <span class="nu0">16</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span><span class="br0">&#40;</span><span class="nu0">4</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pixelColor = *<span class="br0">&#40;</span>Uint32*<span class="br0">&#41;</span>p;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; Uint8 red, green, blue, alpha;<br />
&nbsp; &nbsp; SDL_GetRGBA<span class="br0">&#40;</span>pixelColor, entity-&gt;surface-&gt;format, &amp;red, &amp;green, &amp;blue, &amp;alpha<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> alpha &gt; <span class="nu0">200</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>I hope you enjoyed my first tutorial for SDLTutorials.com and learned a lot! I plan to do more in the future!</p>
<p><strong>SDL Per Pixel Collision – Tutorial Files:</strong><br />
<strong>Win32:</strong> <a href="http://www.megaupload.com/?d=DISXV67Q">RAR</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.sdltutorials.com/sdl-per-pixel-collision/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>SDL Net &#8211; Part 1 (User Tutorial)</title>
		<link>http://www.sdltutorials.com/sdl-net-part-1-user-tutorial/</link>
		<comments>http://www.sdltutorials.com/sdl-net-part-1-user-tutorial/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 12:01:09 +0000</pubDate>
		<dc:creator>Tim Jones</dc:creator>
				<category><![CDATA[SDL Tutorials]]></category>

		<guid isPermaLink="false">http://www.sdltutorials.com/?p=188</guid>
		<description><![CDATA[The following user tutorial was created by Kahshoo-heem, for the purpose of expanding upon the SDLTutorials.com series, and expounding upon the use of SDL. This tutorial, though not purposely a part of the SDLTutorials.com or created for the series, may be a branch or addition to the series. Please read notes by the author for [...]]]></description>
			<content:encoded><![CDATA[<p>The following user tutorial was created by Kahshoo-heem, for the purpose of expanding upon the SDLTutorials.com series, and expounding upon the use of SDL. This tutorial, though not purposely a part of the SDLTutorials.com or created for the series, may be a branch or addition to the series. Please read notes by the author for any additional code and/or framework used by the author. If you wish to submit your own tutorial to this site, please visit the &#8220;User Tutorials&#8221; page.</p>
<hr/>
<p>In this tutorial, I will show you a simple c++ library to add network resources to your game.</p>
<p>Firstly, we have to add the SDL_net headers and libraries to your desktop environment. If you are using a linux distro like Ubuntu, it is enough to download the libsdl-netx.x-dev package from the repositories. If not, the process is analogous of including sdl mixer, image, etc, better explained by Tim&#8217;s Tutorials.<br />
Don&#8217;t forget, as well, to set the linker options in your IDE, adding the SDL_net library.</p>
<p><span id="more-188"></span></p>
<p>So, let&#8217;s create our two files, CNet.h and CNet.cpp, that will build our framework that we&#8217;ll help us at making network games. It&#8217;s necessary to say that this library, for the time being, only works with TCP/IP protocol.</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &lt;stdio.h&gt;</span><br />
<span class="co2">#include &lt;stdlib.h&gt;</span><br />
<span class="co2">#include &lt;string.h&gt;</span><br />
<span class="co2">#include &lt;iostream&gt;</span><br />
<span class="co2">#include &lt;string&gt;</span><br />
<span class="co2">#include &lt;cstring&gt;</span><br />
<span class="co2">#include &quot;SDL_net.h&quot;</span></p>
<p><span class="kw4">typedef</span> <span class="kw4">char</span> charbuf <span class="br0">&#91;</span><span class="nu0">256</span><span class="br0">&#93;</span>;</p>
<p>class CNet<span class="br0">&#123;</span><br />
&nbsp; public:<br />
&nbsp; &nbsp; <span class="kw4">static</span> bool Init<span class="br0">&#40;</span><span class="br0">&#41;</span>; <span class="co1">//Initialize SDL_net</span><br />
&nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">void</span> Quit<span class="br0">&#40;</span><span class="br0">&#41;</span>; <span class="co1">//Exit SDL_net</span><br />
<span class="br0">&#125;</span>;<br />
&nbsp;</div>
<p>Here is our header file, and, after the includes and the charbuf declaration, our first class. Its aim is initialize and end the network environment, with two static functions. However, they are unnecessary, if we&#8217;re using SDL_Init(SDL_INIT_EVERYTHING).</p>
<div class="dean_ch" style="white-space: wrap;">
class CNetMessage <span class="br0">&#123;</span><br />
&nbsp; protected:<br />
&nbsp; &nbsp; charbuf buffer; <span class="co1">//message stored in buffer, limited to 256 bytes</span><br />
&nbsp; &nbsp; <span class="kw2">enum</span> bufstates <span class="br0">&#123;</span> <span class="co1">//message states</span><br />
&nbsp; &nbsp; EMPTY,<br />
&nbsp; &nbsp; READING,<br />
&nbsp; &nbsp; WRITING,<br />
&nbsp; &nbsp; FULL <span class="br0">&#125;</span>;<br />
&nbsp; &nbsp; bufstates state; <span class="co1">//the message state</span><br />
&nbsp; &nbsp; <span class="kw4">void</span> reset<span class="br0">&#40;</span><span class="br0">&#41;</span>; <span class="co1">// reset message: fulfill it with zeroes and change its state to EMPTY</span><br />
&nbsp; public:<br />
&nbsp; &nbsp; CNetMessage<span class="br0">&#40;</span><span class="br0">&#41;</span>; <span class="co1">//constructor</span><br />
<span class="co1">//Virtual member function that indicates how many bytes may have to be loaded into the instance. By default, it works with strings that have a maximum</span><br />
<span class="co1">//of 255 characters.</span><br />
&nbsp; &nbsp; virtual <span class="kw4">int</span> NumToLoad<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p><span class="co1">//Virtual member function that indicates how many bytes may have to be downloaded from the instance.</span><br />
&nbsp; &nbsp; virtual <span class="kw4">int</span> NumToUnLoad<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw4">void</span> LoadBytes<span class="br0">&#40;</span>charbuf&amp; inputbuffer, <span class="kw4">int</span> n<span class="br0">&#41;</span>; <span class="co1">//Load a char set into the message buffer</span><br />
&nbsp; &nbsp; <span class="kw4">void</span> UnLoadBytes<span class="br0">&#40;</span>charbuf&amp; destbuffer<span class="br0">&#41;</span>; <span class="co1">//Unload a char set from the buffer</span><br />
&nbsp; &nbsp; <span class="kw4">void</span> finish<span class="br0">&#40;</span><span class="br0">&#41;</span>; <span class="co1">//set the state object to full. No more data to be loaded</span><br />
<span class="br0">&#125;</span>;<br />
&nbsp;</div>
<p>The class above provides the needed interface for the application to deal with the packets sent through the network. It&#8217;s limited to a maximum of 256 bytes.</p>
<p>Regardless this class uses a buffer with a fixed length, the packets sent through the network can be much more smaller, according to the program&#8217;s needs. In our TIC TAC TOE game, only one byte is sent. To work with this customization, we put some message states, to help the framework user to build a derived class.</p>
<p>The LoadBytes and UnloadBytes member functions load and unload in a buffer the wanted chars. They were determined by the virtual functions NumToLoad and NumToUnload, each of which indicates how many bytes have to be loaded or unloaded. By default, this class is able to work with strings that have a maximum of 255 characters. If you want to work with other data structures, as we&#8217;ll do at the game making, you may override this member function.</p>
<p>Last,  the finish() member function, which sets the class ready to be used. So, we can send through the socket, in the same packet, a message with two different data structures, avoiding unnecessary network pollution. Below, the implementation code of this and the latter classes:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;CNet.h&quot;</span></p>
<p>bool CNet::<span class="me2">Init</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>SDLNet_Init<span class="br0">&#40;</span><span class="br0">&#41;</span> &lt; <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; std::<span class="me2">cerr</span> &lt;&lt; <span class="st0">&quot;SDLNet_Init: &quot;</span> &lt;&lt; SDLNet_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span> &lt;&lt; std::<span class="me2">endl</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CNet::<span class="me2">Quit</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDLNet_Quit<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p>
CNetMessage::<span class="me2">CNetMessage</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; reset<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CNetMessage::<span class="me2">reset</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i =<span class="nu0">0</span>; i &lt; <span class="nu0">256</span>; i++<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; buffer <span class="br0">&#91;</span>i<span class="br0">&#93;</span> = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; state = EMPTY;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CNetMessage::<span class="me2">finish</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>state == READING<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; state = FULL;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">int</span> CNetMessage::<span class="me2">NumToLoad</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>state == EMPTY<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">255</span>;<br />
&nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">int</span> CNetMessage::<span class="me2">NumToUnLoad</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>state == FULL<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> strlen<span class="br0">&#40;</span>buffer<span class="br0">&#41;</span> + <span class="nu0">1</span>;<br />
&nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CNetMessage::<span class="me2">LoadBytes</span><span class="br0">&#40;</span>charbuf&amp; inputbuffer, <span class="kw4">int</span> n<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; n; i++<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; buffer<span class="br0">&#91;</span>i<span class="br0">&#93;</span> = inputbuffer<span class="br0">&#91;</span>i<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; state = READING;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CNetMessage::<span class="me2">UnLoadBytes</span><span class="br0">&#40;</span>charbuf&amp; destbuffer<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i=<span class="nu0">0</span>; i &lt; this-&gt;NumToUnLoad<span class="br0">&#40;</span><span class="br0">&#41;</span>; i++<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; destbuffer<span class="br0">&#91;</span>i<span class="br0">&#93;</span> = buffer<span class="br0">&#91;</span>i<span class="br0">&#93;</span>;<br />
&nbsp; &nbsp; reset<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Now, back to the header file. Let&#8217;s take a look at the CIpAddress class:</p>
<div class="dean_ch" style="white-space: wrap;">
class CIpAddress <span class="br0">&#123;</span><br />
&nbsp; private:<br />
&nbsp; &nbsp; IPaddress m_Ip; <span class="co1">//the IPaddress structure</span><br />
&nbsp; public:<br />
&nbsp; &nbsp; CIpAddress<span class="br0">&#40;</span><span class="br0">&#41;</span>; <span class="co1">//constructor</span><br />
&nbsp; &nbsp; CIpAddress <span class="br0">&#40;</span>Uint16 port<span class="br0">&#41;</span>; <span class="co1">//create and associate a port to the instance</span><br />
&nbsp; &nbsp; CIpAddress <span class="br0">&#40;</span>std::<span class="kw4">string</span> host, Uint16 port<span class="br0">&#41;</span>; <span class="co1">//create and associate a port and a host to the instance</span><br />
&nbsp; &nbsp; <span class="kw4">void</span> SetIp <span class="br0">&#40;</span>IPaddress sdl_ip<span class="br0">&#41;</span>; <span class="co1">//set a CIpAddress object from an existing SDL IPaddress</span><br />
&nbsp; &nbsp; bool Ok<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw4">const</span>; <span class="co1">//True if the object have a port and a host associated to it</span><br />
&nbsp; &nbsp; IPaddress GetIpAddress<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw4">const</span>; <span class="co1">//return a SDL_net IPaddress structure</span><br />
&nbsp; &nbsp; Uint32 GetHost<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw4">const</span>; <span class="co1">//return the host</span><br />
&nbsp; &nbsp; Uint16 GetPort<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw4">const</span>; <span class="co1">//return the port</span><br />
<span class="br0">&#125;</span>;<br />
&nbsp;</div>
<p>Basically, that is a C++ interface for the SDL NET structure IPaddress. It has informations about the host IP address, and the port which the program is associated to. Here is the definition of the class members, at CNet.cpp:</p>
<div class="dean_ch" style="white-space: wrap;">
CIpAddress::<span class="me2">CIpAddress</span> <span class="br0">&#40;</span>Uint16 port<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>SDLNet_ResolveHost<span class="br0">&#40;</span>&amp;m_Ip, <span class="kw2">NULL</span>, port<span class="br0">&#41;</span> &lt; <span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; std::<span class="me2">cerr</span> &lt;&lt; <span class="st0">&quot;SDLNet_ResolveHost: &quot;</span> &lt;&lt; SDLNet_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span> &lt;&lt; std::<span class="me2">endl</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m_Ip.<span class="me1">host</span> = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m_Ip.<span class="me1">port</span> = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p>
CIpAddress::<span class="me2">CIpAddress</span> <span class="br0">&#40;</span>std::<span class="kw4">string</span> host, Uint16 port<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>SDLNet_ResolveHost<span class="br0">&#40;</span>&amp;m_Ip, host.<span class="me1">c_str</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, port<span class="br0">&#41;</span> &lt; <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; std::<span class="me2">cerr</span> &lt;&lt; <span class="st0">&quot;SDLNet_ResolveHost: &quot;</span> &lt;&lt; SDLNet_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span> &lt;&lt; std::<span class="me2">endl</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m_Ip.<span class="me1">host</span> = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m_Ip.<span class="me1">port</span> = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p>CIpAddress::<span class="me2">CIpAddress</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; m_Ip.<span class="me1">host</span> = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; m_Ip.<span class="me1">port</span> = <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span></p>
<p>bool CIpAddress::<span class="me2">Ok</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw4">const</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> !<span class="br0">&#40;</span>m_Ip.<span class="me1">port</span> == <span class="nu0">0</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CIpAddress::<span class="me2">SetIp</span> <span class="br0">&#40;</span>IPaddress sdl_ip<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="co1">//sets a CTcpSocket object from a existing SDL socket</span><br />
&nbsp; &nbsp; m_Ip = sdl_ip;<br />
<span class="br0">&#125;</span></p>
<p>IPaddress CIpAddress::<span class="me2">GetIpAddress</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw4">const</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> m_Ip;<br />
<span class="br0">&#125;</span></p>
<p>Uint32 CIpAddress::<span class="me2">GetHost</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw4">const</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> m_Ip.<span class="me1">host</span>;<br />
<span class="br0">&#125;</span></p>
<p>Uint16 CIpAddress::<span class="me2">GetPort</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw4">const</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> m_Ip.<span class="me1">port</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Again, back to header, let&#8217;s analyze CTcpSocket, a framework to the SDL NET TCP socket structure. In a few words, a socket is a connection, a &#8220;pipe&#8221; between two computers, that delivers messages to them, in and out. In a TCP socket, there are necessarily two fixed computers in each pipe&#8217;s end, and messages always are got in the right order that they have sent.</p>
<div class="dean_ch" style="white-space: wrap;">
class CTcpSocket <span class="br0">&#123;</span><br />
&nbsp; protected:<br />
&nbsp; &nbsp; TCPsocket m_Socket; <span class="co1">//the TCP socket structure</span><br />
&nbsp; &nbsp; SDLNet_SocketSet set; <span class="co1">//a set of sockets. Used here only to check existing packets</span><br />
&nbsp; public:<br />
&nbsp; &nbsp; CTcpSocket<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; virtual ~CTcpSocket<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> SetSocket <span class="br0">&#40;</span>TCPsocket &nbsp;the_sdl_socket<span class="br0">&#41;</span>; <span class="co1">//set a CTcpSocket object from a existing SDL socket</span><br />
&nbsp; &nbsp; bool Ok<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw4">const</span>; <span class="co1">//indicate if theres is a TCPsocket associated to the instance</span><br />
&nbsp; &nbsp; bool Ready<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw4">const</span>; <span class="co1">//True if there are bytes ready to be read</span><br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> OnReady<span class="br0">&#40;</span><span class="br0">&#41;</span>; <span class="co1">//pure virtual</span><br />
<span class="br0">&#125;</span>;<br />
&nbsp;</div>
<p>In the code above, the member function Ready() plays an important role: it checks whether there is or not activity in the socket, freeing the program&#8217;s flow to do what they have to do, without waiting messages from the other side of the pipe.<br />
Below, the code in CNet.cpp:</p>
<div class="dean_ch" style="white-space: wrap;">
CTcpSocket::<span class="me2">CTcpSocket</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; m_Socket = <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; set = SDLNet_AllocSocketSet<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p>CTcpSocket::~CTcpSocket<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!<span class="br0">&#40;</span>m_Socket == <span class="kw2">NULL</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDLNet_TCP_DelSocket<span class="br0">&#40;</span>set,m_Socket<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; SDLNet_FreeSocketSet<span class="br0">&#40;</span>set<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; SDLNet_TCP_Close <span class="br0">&#40;</span>m_Socket<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CTcpSocket::<span class="me2">SetSocket</span> <span class="br0">&#40;</span>TCPsocket the_sdl_socket<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!<span class="br0">&#40;</span>m_Socket == <span class="kw2">NULL</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDLNet_TCP_DelSocket<span class="br0">&#40;</span>set,m_Socket<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDLNet_TCP_Close <span class="br0">&#40;</span>m_Socket<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; m_Socket = the_sdl_socket;<br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>SDLNet_TCP_AddSocket<span class="br0">&#40;</span>set,m_Socket<span class="br0">&#41;</span>==<span class="nu0">-1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; std::<span class="me2">cerr</span> &lt;&lt; <span class="st0">&quot;SDLNet_TCP_AddSocket: &quot;</span> &lt;&lt; SDLNet_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span> &lt;&lt; std::<span class="me2">endl</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; m_Socket = <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p>bool CTcpSocket::<span class="me2">Ok</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw4">const</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> !<span class="br0">&#40;</span>m_Socket == <span class="kw2">NULL</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p>bool CTcpSocket::<span class="me2">Ready</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw4">const</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; bool rd = <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="kw4">int</span> numready = SDLNet_CheckSockets<span class="br0">&#40;</span>set, <span class="nu0">0</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>numready == <span class="nu0">-1</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::<span class="me2">cerr</span> &lt;&lt; <span class="st0">&quot;SDLNet_CheckSockets: &quot;</span> &lt;&lt; SDLNet_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span> &lt;&lt; std:: <span class="me2">endl</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>numready<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rd = SDLNet_SocketReady <span class="br0">&#40;</span>m_Socket<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; <span class="kw1">return</span> rd;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CTcpSocket::<span class="me2">OnReady</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></p>
<p><span class="br0">&#125;</span><br />
&nbsp;</div>
<p>From this class, we will derive CHostSocket, according to the piece of code of CNet.h:</p>
<div class="dean_ch" style="white-space: wrap;">
class CClientSocket;</p>
<p>
class CHostSocket : public CTcpSocket <span class="br0">&#123;</span><br />
&nbsp; public:<br />
&nbsp; &nbsp; CHostSocket <span class="br0">&#40;</span>CIpAddress&amp; the_ip_address<span class="br0">&#41;</span>; <span class="co1">//create and open a new socket, with an existing CIpAddress object</span></p>
<p>&nbsp; &nbsp; CHostSocket <span class="br0">&#40;</span>Uint16 port<span class="br0">&#41;</span>; <span class="co1">//create and open a new socket with the desired port</span><br />
&nbsp; &nbsp; bool Accept <span class="br0">&#40;</span>CClientSocket&amp;<span class="br0">&#41;</span>; <span class="co1">//set a client CTcpSocket object after listening to the port</span><br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> OnReady<span class="br0">&#40;</span><span class="br0">&#41;</span>; <span class="co1">//pure virtual</span><br />
<span class="br0">&#125;</span>;<br />
&nbsp;</div>
<p>A host socket is a socket whose utility is listen to a certain port, to check whether there is someone wanting to connect to the service provided by the program, in the machine it runs. If found, we have to use the member Accept to associate another socket to the client. Here is the implementation:</p>
<div class="dean_ch" style="white-space: wrap;">
CHostSocket::<span class="me2">CHostSocket</span> <span class="br0">&#40;</span>CIpAddress&amp; the_ip_address<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; CTcpSocket::<span class="me2">CTcpSocket</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; IPaddress iph = the_ip_address.<span class="me1">GetIpAddress</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!<span class="br0">&#40;</span>m_Socket = SDLNet_TCP_Open<span class="br0">&#40;</span>&amp;iph<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDLNet_FreeSocketSet<span class="br0">&#40;</span>set<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::<span class="me2">cerr</span> &lt;&lt; <span class="st0">&quot;SDLNet_TCP_Open: &quot;</span> &lt;&lt; SDLNet_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span> &lt;&lt; std::<span class="me2">endl</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p>CHostSocket::<span class="me2">CHostSocket</span> <span class="br0">&#40;</span>Uint16 port<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; CIpAddress iplistener <span class="br0">&#40;</span>port<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!iplistener.<span class="me1">Ok</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; m_Socket = <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CTcpSocket::<span class="me2">CTcpSocket</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; IPaddress iph = iplistener.<span class="me1">GetIpAddress</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!<span class="br0">&#40;</span>m_Socket = SDLNet_TCP_Open<span class="br0">&#40;</span>&amp;iph<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SDLNet_FreeSocketSet<span class="br0">&#40;</span>set<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::<span class="me2">cerr</span> &lt;&lt; <span class="st0">&quot;SDLNet_TCP_Open: &quot;</span> &lt;&lt; SDLNet_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span> &lt;&lt; std::<span class="me2">endl</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p>
bool CHostSocket::<span class="me2">Accept</span> <span class="br0">&#40;</span>CClientSocket&amp; the_client_socket<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; TCPsocket cs;<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>cs = SDLNet_TCP_Accept<span class="br0">&#40;</span>m_Socket<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; the_client_socket.<span class="me1">SetSocket</span><span class="br0">&#40;</span>cs<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CHostSocket::<span class="me2">OnReady</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></p>
<p><span class="br0">&#125;</span><br />
&nbsp;</div>
<p>So, a tcp socket client is a socket whose aim is to communicate with a remote host, who, in turn, is using a tcp client to send and receive messages too. Below, the header file for this class:</p>
<div class="dean_ch" style="white-space: wrap;">
class CClientSocket : public CTcpSocket <span class="br0">&#123;</span><br />
&nbsp; private:<br />
&nbsp; &nbsp; CIpAddress m_RemoteIp; <span class="co1">//the CIpAddress object corresponding to the remote host</span><br />
&nbsp; public:<br />
&nbsp; &nbsp; CClientSocket<span class="br0">&#40;</span><span class="br0">&#41;</span>; <span class="co1">//constructor</span><br />
&nbsp; &nbsp; CClientSocket <span class="br0">&#40;</span>std::<span class="kw4">string</span> host, Uint16 port<span class="br0">&#41;</span>; <span class="co1">//Create the object and connect to a host, in a given port</span><br />
&nbsp; &nbsp; bool Connect <span class="br0">&#40;</span>CIpAddress&amp; remoteip<span class="br0">&#41;</span>; <span class="co1">//make a connection to communicate with a remote host</span><br />
&nbsp; &nbsp; bool Connect <span class="br0">&#40;</span>CHostSocket&amp; the_listener_socket<span class="br0">&#41;</span>; <span class="co1">//make a connection to communicate with a client</span><br />
&nbsp; &nbsp; <span class="kw4">void</span> SetSocket <span class="br0">&#40;</span>TCPsocket &nbsp;the_sdl_socket<span class="br0">&#41;</span>; <span class="co1">//set a CTcpSocket object from an existing SDL_net socket</span><br />
&nbsp; &nbsp; CIpAddress getIpAddress <span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw4">const</span>; <span class="co1">//return a CIpAddress object associated to the remote host</span><br />
&nbsp; &nbsp; virtual <span class="kw4">void</span> OnReady<span class="br0">&#40;</span><span class="br0">&#41;</span>; <span class="co1">//pure virtual</span><br />
&nbsp; &nbsp; bool Receive<span class="br0">&#40;</span>CNetMessage&amp; rData<span class="br0">&#41;</span>; <span class="co1">//receive data and load it into a CNetMessage object</span><br />
&nbsp; &nbsp; bool Send <span class="br0">&#40;</span>CNetMessage&amp; sData<span class="br0">&#41;</span>; <span class="co1">//send data from a CNetMessage object</span><br />
<span class="br0">&#125;</span>;<br />
&nbsp;</div>
<p>The same way CHostSocket is, this class is derived from CTcpSocket, and uses the constructor or Connect() to make a connection to the host. If so, the object uses the Send() and Receive() member functions to throw and get messages through the network. Below, the implementation:</p>
<div class="dean_ch" style="white-space: wrap;">
CClientSocket::<span class="me2">CClientSocket</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; CTcpSocket::<span class="me2">CTcpSocket</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p>CClientSocket::<span class="me2">CClientSocket</span> <span class="br0">&#40;</span>std::<span class="kw4">string</span> host, Uint16 port<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; CIpAddress remoteip <span class="br0">&#40;</span>host.<span class="me1">c_str</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, port<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!remoteip.<span class="me1">Ok</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; m_Socket = <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CTcpSocket::<span class="me2">CTcpSocket</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Connect<span class="br0">&#40;</span>remoteip<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p>bool CClientSocket::<span class="me2">Connect</span> <span class="br0">&#40;</span>CHostSocket&amp; the_listener_socket<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="br0">&#125;</span></p>
<p>bool CClientSocket::<span class="me2">Connect</span> <span class="br0">&#40;</span>CIpAddress&amp; remoteip<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; TCPsocket cs;<br />
&nbsp; &nbsp; IPaddress ip = remoteip.<span class="me1">GetIpAddress</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>cs = SDLNet_TCP_Open<span class="br0">&#40;</span>&amp;ip<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; SetSocket<span class="br0">&#40;</span>cs<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; std::<span class="me2">cerr</span> &lt;&lt; <span class="st0">&quot;SDLNet_TCP_Open: &quot;</span> &lt;&lt; SDLNet_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span> &lt;&lt; std::<span class="me2">endl</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CClientSocket::<span class="me2">SetSocket</span> <span class="br0">&#40;</span>TCPsocket the_sdl_socket<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; CTcpSocket::<span class="me2">SetSocket</span> <span class="br0">&#40;</span>the_sdl_socket<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; IPaddress* ips;<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>ips = SDLNet_TCP_GetPeerAddress<span class="br0">&#40;</span>m_Socket<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="coMULTI">/* Print the address, converting it onto the host format */</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; m_RemoteIp.<span class="me1">SetIp</span><span class="br0">&#40;</span>*ips<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Uint32 hbo = m_RemoteIp.<span class="me1">GetHost</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Uint16 pbo = m_RemoteIp.<span class="me1">GetPort</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; std::<a href="http://www.opengroup.org/onlinepubs/009695399/functions/cout.html"><span class="kw3">cout</span></a> &lt;&lt; <span class="st0">&quot;Client connected: &quot;</span> &lt;&lt; SDLNet_Read32<span class="br0">&#40;</span>&amp;hbo<span class="br0">&#41;</span> &lt;&lt; <span class="st0">&#8216; &#8216;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;&lt; SDLNet_Read16 <span class="br0">&#40;</span>&amp;pbo<span class="br0">&#41;</span> &lt;&lt; std::<span class="me2">endl</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; std::<span class="me2">cerr</span> &lt;&lt; <span class="st0">&quot;SDLNet_TCP_GetPeerAddress: &quot;</span> &lt;&lt; SDLNet_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span> &lt;&lt; std::<span class="me2">endl</span>;<br />
<span class="br0">&#125;</span></p>
<p>CIpAddress CClientSocket::<span class="me2">getIpAddress</span> <span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw4">const</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> m_RemoteIp;<br />
<span class="br0">&#125;</span></p>
<p>bool CClientSocket::<span class="me2">Receive</span><span class="br0">&#40;</span>CNetMessage&amp; rData<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="co1">//Firstly, check if there is a socket</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>m_Socket == <span class="kw2">NULL</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; charbuf buf;</p>
<p><span class="co1">//Check if the instance can receive bytes, if it can, load the number of bytes specified by NumToLoad() virtual function</span><br />
&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>rData.<span class="me1">NumToLoad</span><span class="br0">&#40;</span><span class="br0">&#41;</span> &gt; <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>SDLNet_TCP_Recv<span class="br0">&#40;</span>m_Socket, buf, rData.<span class="me1">NumToLoad</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> &gt; <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rData.<span class="me1">LoadBytes</span> <span class="br0">&#40;</span>buf, rData.<span class="me1">NumToLoad</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; rData.<span class="me1">finish</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">&#125;</span></p>
<p>bool CClientSocket::<span class="me2">Send</span> <span class="br0">&#40;</span>CNetMessage&amp; sData<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="co1">//check if there is a socket</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>m_Socket == <span class="kw2">NULL</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; charbuf buf;<br />
&nbsp; &nbsp; <span class="kw4">int</span> len;</p>
<p><span class="co1">//Check if the instance can send bytes, if it can, unload the number of bytes specified by NumToLoad() virtual function</span><br />
&nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>len = sData.<span class="me1">NumToUnLoad</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> &gt; <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sData.<span class="me1">UnLoadBytes</span> <span class="br0">&#40;</span>buf<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>SDLNet_TCP_Send<span class="br0">&#40;</span>m_Socket, <span class="br0">&#40;</span><span class="kw4">void</span> *<span class="br0">&#41;</span>buf, len<span class="br0">&#41;</span> &lt; len<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; std::<span class="me2">cerr</span> &lt;&lt; <span class="st0">&quot;SDLNet_TCP_Send: &quot;</span> &lt;&lt; SDLNet_GetError<span class="br0">&#40;</span><span class="br0">&#41;</span> &lt;&lt; std::<span class="me2">endl</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CClientSocket::<span class="me2">OnReady</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></p>
<p><span class="br0">&#125;</span><br />
&nbsp;</div>
<p>So that, we have finished the first part of our tutorial. Next, we&#8217;ll change the TIC TAC TOE source code to add playability over a network.</p>
<p><b>SDL Net Tutorial Files:</b><br />
<a href="/tutorials/sdl-net-clientfiles.tar">sdl-net-clientfiles.tar</a><br />
<a href="/tutorials/sdl-net-commonfiles.tar">sdl-net-commonfiles.tar</a><br />
<a href="/tutorials/sdl-net-serverfiles.tar">sdl-net-serverfiles.tar</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.sdltutorials.com/sdl-net-part-1-user-tutorial/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>SDL Collision Events</title>
		<link>http://www.sdltutorials.com/sdl-collision-events/</link>
		<comments>http://www.sdltutorials.com/sdl-collision-events/#comments</comments>
		<pubDate>Tue, 04 Aug 2009 11:27:56 +0000</pubDate>
		<dc:creator>Tim Jones</dc:creator>
				<category><![CDATA[SDL Tutorials]]></category>

		<guid isPermaLink="false">http://www.sdltutorials.com/?p=119</guid>
		<description><![CDATA[Finally! The next tutorial. This is the 2nd part to the SDL Collision tutorial. We&#8217;ll be looking at collision events, the part we left unfinished in the last tutorial. To refresh your memory, a collision event is an event that is stored in queue after a collision has taken place. Take our recent shooter contest [...]]]></description>
			<content:encoded><![CDATA[<p>Finally! The next tutorial. This is the 2nd part to the SDL Collision tutorial. We&#8217;ll be looking at collision events, the part we left unfinished in the last tutorial. To refresh your memory, a collision event is an event that is stored in queue after a collision has taken place. Take our recent shooter contest for an example. When the player fires a bullet, the bullet flies through the air, and then hits the enemy. The moment the bullet and the enemy collide, an event is triggered and stored in the queue. After all movement has taken place, the queue is iterated through, and events can appropriately respond.<br />
<span id="more-119"></span></p>
<p>So lets get started. Open up your project from the last tutorial. We&#8217;re first going to make a few prelimary changes. Make a new file called CEntityCol.cpp. Inside that file, put the following:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;CEntity.h&quot;</span></p>
<p>std::<span class="me2">vector</span>&lt;CEntityCol&gt; CEntityCol::<span class="me2">EntityColList</span>;</p>
<p>CEntityCol::<span class="me2">CEntityCol</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; this-&gt;EntityA = <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; this-&gt;EntityB = <span class="kw2">NULL</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Now, get rid of that code from CEntity.cpp. I am basically moving the code to its own file so that everything is much neater. The second thing. Open up CEntity.h and change:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw2">virtual</span> <span class="kw4">void</span> OnCollision<span class="br0">&#40;</span>CEntity* Entity<span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>To this:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw2">virtual</span> <span class="kw4">bool</span> OnCollision<span class="br0">&#40;</span>CEntity* Entity<span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>Also, change the void to bool in CEntity.cpp, CPlayer.h, and CPlayer.cpp. Why the change? Well, you&#8217;ll see in a minute. <img src='http://www.sdltutorials.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>We&#8217;re already storing the collision events in a queue, now we need to do something with them. Open up CApp_OnLoop.cpp. You&#8217;ll notice we already have a loop going for entities and we&#8217;re calling OnLoop. We&#8217;re basically going to do the same thing again, but after our first loop:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>;i &lt; CEntity::<span class="me2">EntityList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>!CEntity::<span class="me2">EntityList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="kw1">continue</span>;</p>
<p>&nbsp; &nbsp; CEntity::<span class="me2">EntityList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;OnLoop<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="co1">//Collision Events</span><br />
<span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>;i &lt; CEntityCol::<span class="me2">EntityColList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; CEntity* EntityA = CEntityCol::<span class="me2">EntityColList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">EntityA</span>;<br />
&nbsp; &nbsp; CEntity* EntityB = CEntityCol::<span class="me2">EntityColList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">EntityB</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>EntityA == <span class="kw2">NULL</span> || EntityB == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="kw1">continue</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>EntityA-&gt;OnCollision<span class="br0">&#40;</span>EntityB<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; EntityB-&gt;OnCollision<span class="br0">&#40;</span>EntityA<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p>CEntityCol::<span class="me2">EntityColList</span>.<span class="me1">clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>Not much going on here. We&#8217;re first iterating through every event in the queue. We then grab the two entities involved (EntityA, and EntityB), and we make sure they are valid pointers. If so, we first tell EntityA that it has collided with EntityB by calling OnCollision. Now, this is where that void to bool change comes in. EntityA can choose to prevent EntityB from knowing it has collided with him. If you remember, only Entities that are moving check for collision. This would mean EntityA is definitly a moving entity, and EntityB may or may not be moving.</p>
<p>Here&#8217;s an example to explain why you wouldn&#8217;t want to waste time calling EntityB&#8217;s OnCollision. Say you fire a bullet, and it hits a rock entity. Now, lets say the rock has a flag stating it&#8217;s indestructable. Our rock doesn&#8217;t care its been hit. So, when the OnCollision is called for the bullet, the bullet can see the entity it has hit is indestructable. And because of that, it can create a little &#8220;bullet being destroyed&#8221; animation, and then we can ignore telling the rock about it.</p>
<p>This is about the extent of entity collisions. So, now that we have this base, lets do something semi-useful with it.</p>
<p>Open up CEntity.h and add this new function, and variable:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw2">protected</span>:<br />
&nbsp; &nbsp; <span class="kw4">bool</span>&nbsp; &nbsp; CanJump;</p>
<p><span class="kw2">public</span>:<br />
&nbsp; &nbsp; <span class="kw4">bool</span> &nbsp; &nbsp;Jump<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>Then, open up CEntity.cpp, and add the Jump function. Also make CanJump = false in the constructor:</p>
<div class="dean_ch" style="white-space: wrap;">
CEntity::<span class="me2">CEntity</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; CanJump = <span class="kw2">false</span>;</p>
<p>&nbsp; &nbsp; <span class="co1">// &#8230; Other code &#8230; </span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">bool</span> CEntity::<span class="me2">Jump</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>CanJump == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="kw1">return</span> <span class="kw2">false</span>;</p>
<p>&nbsp; &nbsp; SpeedY = -MaxSpeedY;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Finally, go to the OnMove function. We&#8217;re going to figure out when our entity is allowed to jump. An entity is allowed to jump whenever it is touching the ground &#8211; or, in other words, whenever the entity is no longer moving on the positive Y-axis. So, at the top, we are first always going to reset CanJump to false:</p>
<div class="dean_ch" style="white-space: wrap;">
CanJump = <span class="kw2">false</span>;<br />
&nbsp;</div>
<p>Now, go down a bit, and modify the PosValid for the Y-axis to the following:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">if</span><span class="br0">&#40;</span>PosValid<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span><span class="br0">&#40;</span>X<span class="br0">&#41;</span>, <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span><span class="br0">&#40;</span>Y + NewY<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; Y += NewY;<br />
<span class="br0">&#125;</span><span class="kw1">else</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>MoveY &gt; <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CanJump = <span class="kw2">true</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; SpeedY = <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Now, to run through everything we did. First, we have a flag that states if an entity can jump. When set to true, we are allowed to call the Jump function. This CanJump variable is always false, unless our feet are on the ground. Whenever we actually do want to jump, we simply set our SpeedY in the negative Y-axis direction (up). Remember, gravity is always pushing us down, but at a slow speed. So, if we have a SpeedY of -5, and a AccelY of 0.75, we&#8217;ll move up for a time, gravity will kick in, and then we will eventually be pushed back down. Thus, giving the effect of a real jump. The trick here is to get the Speed and Acceleration variables just right.</p>
<p>Also, as a side note, the reason we made Jump return true/false is simply for informational purposes. Meaning, when a key is pressed by the player to jump, they won&#8217;t always be allowed to jump. And, if you wanted, you could do something based upon what Jump() returns.</p>
<p>So a few more tweaks before we try this out. In the constructor of CEntity, change the MaxSpeedX and MaxSpeedY to 10. Then, open up CApp_OnEvent.cpp and add the following to OnKeyDown:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">case</span> SDLK_SPACE: <span class="br0">&#123;</span><br />
&nbsp; &nbsp; Player.<span class="me1">Jump</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw2">break</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>And one last thing. Open up CPlayer.cpp, and change the OnCollision function to this:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">bool</span> CPlayer::<span class="me2">OnCollision</span><span class="br0">&#40;</span>CEntity* Entity<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; Jump<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>That&#8217;s it! Compile, run, and have fun with Yoshi jumping all over the place. You&#8217;ll notice the simple collision event we added is that when Yoshi 1 collides with Yoshi 2, it causes Yoshi 1 to jump. Kind of lame, but you should get the idea.</p>
<p><b>SDL Collision Events &#8211; Tutorial Files:</b><br />
<b>Win32:</b> <a href="../tutorials/sdl-collision-events.zip">Zip</a>, <a href="../tutorials/sdl-collision-events.rar">Rar</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.sdltutorials.com/sdl-collision-events/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>SDL Collision</title>
		<link>http://www.sdltutorials.com/sdl-collision/</link>
		<comments>http://www.sdltutorials.com/sdl-collision/#comments</comments>
		<pubDate>Fri, 31 Oct 2008 13:31:15 +0000</pubDate>
		<dc:creator>Tim Jones</dc:creator>
				<category><![CDATA[SDL Tutorials]]></category>

		<guid isPermaLink="false">http://www.sdltutorials.com/sdl-collision/</guid>
		<description><![CDATA[If you are still trying to catch your breath from the last tutorial, I recommend you sit down, because this next tutorial won&#8217;t be any nicer. In this tutorial we will be extending our entity class a bit further with collisions, and movement. So hold on to your pants, and get ready.

The first order of [...]]]></description>
			<content:encoded><![CDATA[<p>If you are still trying to catch your breath from the last tutorial, I recommend you sit down, because this next tutorial won&#8217;t be any nicer. In this tutorial we will be extending our entity class a bit further with collisions, and movement. So hold on to your pants, and get ready.</p>
<p><span id="more-47"></span></p>
<p>The first order of business we&#8217;ll tackle is movement. A seemingly simple idea that can be a bit tricky. Now, I am going to introduce a method that has worked for me for quiet some time, though I am not sure if it can be readily optimized, changed, or whatever. So save the criticism. The reason I like it so much is that it&#8217;s pixel perfect now matter what system you are on, and it&#8217;s already fast for its purpose.</p>
<p>But before we get into that, we&#8217;re going to need a standard for movement. You see, when we play our games on old Pentium 2 as opposed to a quad core, there are apparent differences in speed. So, if we did a simple X++; on the older machine, the entity would move slower than the newer machine. So the idea is simple, figure out the frame rate of the machine, and base our movements off of the frame rate. I call that the speed factor. Now, in order for this to work, we have to have a base frame rate. I usually pick 32, as that is a good number. So if our machine had a frame rate of 32, our speed factor would be 1. If our frame rate was 64, our speed factor would be 0.5. We move twice as slower on the faster machine, that way speeds are consistent across different machines.</p>
<p>So, lets create this class. Create two new files called CFPS.h and CFPS.cpp. Open up the header file first:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef _CFPS_H_</span><br />
&nbsp; &nbsp; <span class="co2">#define _CFPS_H_</span></p>
<p><span class="co2">#include &lt;SDL.h&gt;</span></p>
<p><span class="kw2">class</span> CFPS <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> CFPS FPSControl;</p>
<p>&nbsp; &nbsp; <span class="kw2">private</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> &nbsp; &nbsp; OldTime;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> &nbsp; &nbsp; LastTime;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> &nbsp; SpeedFactor;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span>&nbsp;NumFrames;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> &nbsp; &nbsp; Frames;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; CFPS<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> &nbsp; &nbsp;OnLoop<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> &nbsp; &nbsp; GetFPS<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> &nbsp; GetSpeedFactor<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;</p>
<p><span class="co2">#endif</span><br />
&nbsp;</div>
<p>First, we have a single control for accessing our speed facor, and frame rate. Again, a singleton object that we should be used to using by now. Next, we have OldTime, which is used to calculate the Frames per second. Then we have LastTime, which is used to calculate the speed factor. SpeedFactor is the current speed factor of the game (of course), NumFrames is the games current FPS, and Frames is the frame count when calculating the frames per second (explanation for all these below). Notice that all of them are private members, so to access our FPS and SpeedFactor we have two get functions. We don&#8217;t need anyone messing with those variables directly. Then, we have a simple constructor, and an OnLoop function to calculate everything.</p>
<p>Now, open up CFPS.cpp to add the actual code:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;CFPS.h&quot;</span></p>
<p>CFPS CFPS::<span class="me2">FPSControl</span>;</p>
<p>CFPS::<span class="me2">CFPS</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; OldTime &nbsp; &nbsp; = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; LastTime &nbsp; &nbsp;= <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; SpeedFactor&nbsp;= <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; Frames &nbsp; &nbsp; &nbsp;= <span class="nu0">0</span>;<br />
&nbsp; &nbsp; NumFrames &nbsp; = <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CFPS::<span class="me2">OnLoop</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>OldTime + <span class="nu0">1000</span> &lt; SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; OldTime = SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; NumFrames = Frames;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; Frames = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; SpeedFactor = <span class="br0">&#40;</span><span class="br0">&#40;</span>SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span> &#8211; LastTime<span class="br0">&#41;</span> / <span class="nu0">1000</span>.0f<span class="br0">&#41;</span> * <span class="nu0">32</span>.0f;</p>
<p>&nbsp; &nbsp; LastTime = SDL_GetTicks<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; Frames++;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">int</span> CFPS::<span class="me2">GetFPS</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> NumFrames;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">float</span> CFPS::<span class="me2">GetSpeedFactor</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> SpeedFactor;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>I thought I&#8217;d drop a note in here, since I have had some people miss this; whenever you make a variable of a class static, you also need to declare it elsewhere. Notice I have CFPS::FPSControl at the top. If you fail to do this, you&#8217;ll get an undeclared error.</p>
<p>Okay, we have a basic constructor, setting everything to 0. Next, we have our OnLoop function where all the magic happens. The first calculation we do, is finding the Frames per Second of the game. This is where SDL_GetTicks comes in. SDL_GetTicks returns the number of milliseconds that have passed since we have called SDL_Init. So, effectively, 1000 milliseconds equals 1 second. Now, notice the condition I am checking. I am checking if the OldTime (which is currently set to 0) + 1000, is less than the current tick count. Think about it, if OldTime is 0 + 1000, and 1001 milliseconds have passed, that means at least 1 second has passed. Why is that important? That tells use to restart the FPS counter.</p>
<p>Notice inside the if statement we then set OldTime to SDL_GetTicks, set NumFrames to the Frames count, and reset our Frames counter. So, going with the example above, OldTime now becomes 1001. Now, 1001 + 1000, is the next calculation, so another second must pass. Concurrent with this, is the Frames++ at the bottom of that function. This continuelly counts up, until the OldTime resets it. I hope that is easy to understand.</p>
<p>Next, we have the actual calculation for the SpeedFactor. Like I mentioned earlier, the SpeedFactor determines how fast to move objects. Now, for a better explanation. Say we are on a really slow computer that gets 1 FPS per second. That&#8217;s a really bad computer by the way. We have the base movement rate set at 32 (our made up number). So, ideally, any computer will move objects 32 pixels per second. So this 1 FPS computer will move the object 32 pixels every second. Now, jump to a 10 FPS computer. We still want to move 32 pixels per second. So, that&#8217;s 1/10 of 32 right? So, for each calculation we move 3.2 pixels, and after 1 second, we&#8217;ll have moved 32 pixels.</p>
<p>To calculate this, we base it on how fast the computer is currently going. This is what LastTime is for. LastTime holds the time it took for the last loop in the game. So, in the constructor it&#8217;s currently 0. Now, say we have an FPS of 10. That means we have 10 loops in the game every second. How many milliseconds is that? That&#8217;s 100 milliseconds. So, 100 / 1000 (for 1 second), is 1/10. The same number we got above. Now multiply this by our desired movement rate, and we have our Speed Factor! I&#8217;ll be showing you how to use this later on, just try to understand how we calculated it.</p>
<p>And lastly, we have our two get functions that return NumFrames (FPS), and the SpeedFactor.</p>
<p>Okay, so much already and we still have a long way to go!</p>
<p>From the last tutorial we loaded an area, 1.area, we&#8217;ll be leaving this, as well as everything else from that code. But, we&#8217;re going to take one thing out right now. Open up CApp_OnEvent.cpp and remove the following:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">case</span> SDLK_UP: &nbsp; &nbsp;CCamera::<span class="me2">CameraControl</span>.<span class="me1">OnMove</span><span class="br0">&#40;</span> <span class="nu0">0</span>, &nbsp;<span class="nu0">5</span><span class="br0">&#41;</span>; <span class="kw2">break</span>;<br />
<span class="kw1">case</span> SDLK_DOWN: &nbsp;CCamera::<span class="me2">CameraControl</span>.<span class="me1">OnMove</span><span class="br0">&#40;</span> <span class="nu0">0</span>, <span class="nu0">-5</span><span class="br0">&#41;</span>; <span class="kw2">break</span>;<br />
<span class="kw1">case</span> SDLK_LEFT: &nbsp;CCamera::<span class="me2">CameraControl</span>.<span class="me1">OnMove</span><span class="br0">&#40;</span> <span class="nu0">5</span>, &nbsp;<span class="nu0">0</span><span class="br0">&#41;</span>; <span class="kw2">break</span>;<br />
<span class="kw1">case</span> SDLK_RIGHT: CCamera::<span class="me2">CameraControl</span>.<span class="me1">OnMove</span><span class="br0">&#40;</span><span class="nu0">-5</span>, &nbsp;<span class="nu0">0</span><span class="br0">&#41;</span>; <span class="kw2">break</span>;<br />
&nbsp;</div>
<p>We aren&#8217;t going to be controlling the camera anymore, but we&#8217;ll be controlling our main Player who will dictate where the camera goes. <b>Note:</b> In the last tutorial I had some values backwards for the camera! Please read the notes in the last tutorial for the fix. This new tutorial will have the fixes already in place, but without any explanation. </p>
<p>Now, lets go ahead and add this new Player to the game. But first, some explanation. Remember, anything that moves in the game or that can be interacted with (besides the Map), is an Entity. So, our main Player will be an entity. But, Player is distinct, he likes certain things other Entities do not. So, instead of simply doing CEntity Player; we need to create a class just for Player. But! Before we can even to get to making the Player class, we&#8217;re going to need to extend the Entity class. Things like this include the ability to Move an Entity, Collision (what we&#8217;ve all been waiting for), Animation states, and Entity Flags. Jumping and a few other things will have to wait until the next lesson (sorry).</p>
<p>So open up CEntity.h and change it to the following:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef _CENTITY_H_</span><br />
&nbsp; &nbsp; <span class="co2">#define _CENTITY_H_</span></p>
<p><span class="co2">#include &lt;vector&gt;</span></p>
<p><span class="co2">#include &quot;CArea.h&quot;</span><br />
<span class="co2">#include &quot;CAnimation.h&quot;</span><br />
<span class="co2">#include &quot;CCamera.h&quot;</span><br />
<span class="co2">#include &quot;CFPS.h&quot;</span><br />
<span class="co2">#include &quot;CSurface.h&quot;</span></p>
<p><span class="kw2">enum</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; ENTITY_TYPE_PLAYER = <span class="nu0">0</span><br />
<span class="br0">&#125;</span>;</p>
<p><span class="kw2">enum</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; ENTITY_FLAG_NONE &nbsp; &nbsp;= <span class="nu0">0</span>,</p>
<p>&nbsp; &nbsp; ENTITY_FLAG_GRAVITY&nbsp;= 0&#215;00000001,<br />
&nbsp; &nbsp; ENTITY_FLAG_GHOST&nbsp; &nbsp;= 0&#215;00000002,<br />
&nbsp; &nbsp; ENTITY_FLAG_MAPONLY&nbsp;= 0&#215;00000004<br />
<span class="br0">&#125;</span>;</p>
<p><span class="kw2">class</span> CEntity <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> std::<span class="me2">vector</span>&lt;CEntity*&gt; &nbsp; &nbsp;EntityList;</p>
<p>&nbsp; &nbsp; <span class="kw2">protected</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; CAnimation &nbsp; &nbsp; &nbsp;Anim_Control;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; SDL_Surface* &nbsp; &nbsp;Surf_Entity;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; X;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Y;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Width;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Height;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">bool</span>&nbsp; &nbsp; &nbsp; &nbsp; MoveLeft;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">bool</span>&nbsp; &nbsp; &nbsp; &nbsp; MoveRight;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span>&nbsp;&nbsp; &nbsp; Type;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">bool</span>&nbsp; &nbsp; &nbsp; &nbsp; Dead;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span>&nbsp;&nbsp; &nbsp; Flags;</p>
<p>&nbsp; &nbsp; <span class="kw2">protected</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span>&nbsp; &nbsp;&nbsp; &nbsp; SpeedX;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span>&nbsp; &nbsp;&nbsp; &nbsp; SpeedY;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span>&nbsp; &nbsp;&nbsp; &nbsp; AccelX;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span>&nbsp; &nbsp;&nbsp; &nbsp; AccelY;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span>&nbsp; &nbsp;&nbsp; &nbsp; MaxSpeedX;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span>&nbsp; &nbsp;&nbsp; &nbsp; MaxSpeedY;</p>
<p>&nbsp; &nbsp; <span class="kw2">protected</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CurrentFrameCol;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CurrentFrameRow;</p>
<p>&nbsp; &nbsp; <span class="kw2">protected</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span>&nbsp;&nbsp; &nbsp; Col_X;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span>&nbsp;&nbsp; &nbsp; Col_Y;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span>&nbsp;&nbsp; &nbsp; Col_Width;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span>&nbsp;&nbsp; &nbsp; Col_Height;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; CEntity<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">virtual</span> ~CEntity<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">bool</span> OnLoad<span class="br0">&#40;</span><span class="kw4">char</span>* <span class="kw4">File</span>, <span class="kw4">int</span> Width, <span class="kw4">int</span> Height, <span class="kw4">int</span> MaxFrames<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> OnLoop<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> OnRender<span class="br0">&#40;</span>SDL_Surface* Surf_Display<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> OnCleanup<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> OnAnimate<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> OnCollision<span class="br0">&#40;</span>CEntity* Entity<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> &nbsp; &nbsp;OnMove<span class="br0">&#40;</span><span class="kw4">float</span> MoveX, <span class="kw4">float</span> MoveY<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> &nbsp; &nbsp;StopMove<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">bool</span> &nbsp; &nbsp;Collides<span class="br0">&#40;</span><span class="kw4">int</span> oX, <span class="kw4">int</span> oY, <span class="kw4">int</span> oW, <span class="kw4">int</span> oH<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">private</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">bool</span> &nbsp; &nbsp;PosValid<span class="br0">&#40;</span><span class="kw4">int</span> NewX, <span class="kw4">int</span> NewY<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">bool</span> &nbsp; &nbsp;PosValidTile<span class="br0">&#40;</span>CTile* Tile<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">bool</span> &nbsp; &nbsp;PosValidEntity<span class="br0">&#40;</span>CEntity* Entity, <span class="kw4">int</span> NewX, <span class="kw4">int</span> NewY<span class="br0">&#41;</span>;&nbsp; &nbsp; &nbsp; &nbsp; <br />
<span class="br0">&#125;</span>;</p>
<p><span class="kw2">class</span> CEntityCol <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> std::<span class="me2">vector</span>&lt;CEntityCol&gt;&nbsp; EntityColList;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; CEntity* EntityA;<br />
&nbsp; &nbsp; &nbsp; &nbsp; CEntity* EntityB;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; CEntityCol<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;</p>
<p><span class="co2">#endif</span><br />
&nbsp;</div>
<p>Oh geez, what happened, and where did all this code come from?! Sorry, for all of you who just fainted, maybe you&#8217;ll understand a little bit more now why this tutorial is so long and took so long. It&#8217;s a lot to handle, let alone trying to teach to everyone. One step at a time.</p>
<p>First, we have the basic things still there, OnLoad, OnLoop, OnRender, and OnCleanup. The two new virtual functions are OnAnimate and OnCollision. Now, OnAnimate is used to define Animation States, like I mentioned earlier. This is useful for selecting the right animation when the Player moves left or right. The second, OnCollision, is called when an Entity collides with another Entity.</p>
<p>So, for example, if EntityA and EntityB collide, what happens? Well, first, neither can pass through each other; that&#8217;s the easy part. The other part, is that EntityA needs to know EntityB collided with him. Such as, Mario falling on a spike. The spike notifies Mario, &#8220;Hey, I killed you! Change your animation and die.&#8221; Well, the thing is, we cannot notify the other entity when the collision happens. One important reason is that, if the Spike kills Mario, Mario may not have been able to notify the Goomba that he killed him. So, what we do instead is store everything in a queue. This is the new vector called CEntityColList. This stores any collision that have happened when all the entities have moved. And once all movement has taken place, that is when we&#8217;ll notify all the Entities of collisions, and call OnCollision. </p>
<p>Whew. Also, in correlation with this, is Collides function, which is used to determine the actual collision (more on this later). Also with this, is four Col_ variables. These variables are used to offset a collision for an entity. Back in previous tutorials we had a Yoshi image we were using. If you notice, it would make little sense to use the width of the image for collision purposes. Yoshi doesn&#8217;t actually come to the edges of the images; so, we have to offset it a little, so when Yoshi runs into a wall it actually looks like his nose is hitting the wall, and not being a few pixels away. And since these variables are used to collision purposes only, I have prefixed them with Col_.</p>
<p>Now, for some movement explanation. Whenever an Entity wants to move, we do not move it to where it wants to go immediately. What we do instead, is move it in the direction we want it to go at a certain speed. Remember the whole CFPS class? That&#8217;s why time based movement is so important. So, in the new OnMove function, we pass it how fast we want our Entity to go. If we want the Entity to move 1 pixel a second to the right, we would do OnMove(1, 0). Now, I wish it was this simple, but it&#8217;s not. In real life we don&#8217;t move in steps. We move according to speed and acceleration. Meaning, it takes us a little time to start moving at first (inertia). It looks unnatural to have entities jumping around. </p>
<p>So, to get past this, we have six variables SpeedX, SpeedY, AccelX, AccelY, MaxSpeedX, and MaxSpeedY. Using these is simple. First, the MaxSpeed variables cap how fast the entity can go; if we didn&#8217;t cap it, the Entities would continue to go faster and faster into infinity. The SpeedX and SpeedY are the current speed of the entity. If these were 1, again, that would be 1 pixel per second. Now, the AccelX and AccelY, determine how fast we increase or decrease our speed. If AccelX and AccelY are 0, then we aren&#8217;t moving at all. If AccelX is 1, then our SpeedX is increasing over time. Now, this is where it gets a little confusing with the Speed factor. </p>
<p>I want my player to increase in speed 1 pixel per second. This would be:</p>
<div class="dean_ch" style="white-space: wrap;">
AccelX = <span class="nu0">1</span>;</p>
<p>SpeedX += AccelX * CFPS::<span class="me2">FPSControl</span>.<span class="me1">GetSpeedFactor</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>Notice we multiply the AccelX by the Speed Factor. That&#8217;s because we want to increase the speed 1 pixel <u>every second</u>. If I wanted to increase the speed 1 pixel every loop, I would leave the speed factor out of it. Now, when OnMove receives these Speed variables, it also has to figure in the speed factor:</p>
<div class="dean_ch" style="white-space: wrap;">
MoveX *= CFPS::<span class="me2">FPSControl</span>.<span class="me1">GetSpeedFactor</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
MoveY *= CFPS::<span class="me2">FPSControl</span>.<span class="me1">GetSpeedFactor</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>(MoveX and MoveY are the arguments passed to OnMove). Now, the SpeedX and SpeedY only determine how fast we want to move <u>per second</u>. So we have to multiply it by the speed factor. A little hint for you people out there, the entire speed of the game is determined by the Speed Factor! If we changed the Speed Factor of the game, it would determine how fast anything in the games moves. Slow motion deaths anyone?</p>
<p>Now, whenever an Entity moves, there are some things to consider. Say in one loop we are supposed to move the Entity 4 pixels (slow computer perhaps, or really fast entity). Now, lets say 2 pixels away there is a wall. Now, if we checked 4 pixels in front of use, we wouldn&#8217;t let our guy move. But, we still want him to move as close as he can. So, to move this 2 pixel distance, we have to check every pixel along the way. Now, you might be thinking this will be slow. Well, not really. Someone with a 100 FPS who wants to move 5 pixels a second (a reasonable speed), will move less than one pixel every loop (0.05 to be exact). So, every loop, this entity moves 0.05 pixels over. That means we have 1 or 2 checks when checking for collisions for that entity. More explanation on this later when we actually implement moving.</p>
<p>Before an entity is allowed to move, we have to check a few things. The first is if the entity collides with the map, and the second is if the entity collides with another entity. This is where the three PosValid functions come in. The first, PosValid(), is the main function that handles the other two. It checks to see if the tile the entity is trying to move to is valid, and also checks the entities. The other two PosValid functions determine what a valid tile is, and what a valid entity is. Again, more explanation later.</p>
<p>Now, last for movement, we have MoveLeft, MoveRight, Flags, and StopMove. Now, MoveLeft and MoveRight are simply flags, true or false, that determine if the entity is moving left or right. If true, the AccelX will be set a value, causing the entity to move. Now, StopMove simply sets the AccelX in the opposite direction until we reach 0. Again, we don&#8217;t stop suddenly in real life, we gradually stop. The last item, Flags, is used to determine a few things. In the second enum, you&#8217;ll notice several flags.</p>
<div class="dean_ch" style="white-space: wrap;">
ENTITY_FLAG_NONE<br />
ENTITY_FLAG_GRAVITY<br />
ENTITY_FLAG_GHOST<br />
ENTITY_FLAG_MAPONLY<br />
&nbsp;</div>
<p>These are used to determine certain properties about an entity. For example, an entity that is affected by gravity will have the ENTITY_FLAG_GRAVITY turned on. An Entity that can go through walls, will have ENTITY_FLAG_GHOST turned on. An entity that only collides with the map, and not other entities, will have ENTITY_FLAG_MAPONLY turned on. Now, notice how we have them numbered in hex. This is because we&#8217;re treating the Flags in binary. This way, we can activate multiple flags at once:</p>
<div class="dean_ch" style="white-space: wrap;">
Flags = ENTITY_FLAG_GRAVITY | ENTITY_FLAG_GHOST;</p>
<p>To check <span class="kw1">for</span> a single flag is simple:</p>
<p><span class="kw1">if</span><span class="br0">&#40;</span>Flags &amp; ENTITY_FLAG_MAPONLY<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="co1">//Map only</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Wow, what a load, but still more in the class to explain. Next, we have some Animation variables. There are only two of them: CurrentFrameCol, and CurrentFrameRow. These two determine where on our image we start to find individual frames of an animation. A CurrentFrameCol and CurrentFrameRow would be the top left of the image. Moving over one column would change things. Think of it like tilesets. Look at the example image below:</p>
<p><center><img src="../tutorials/sdl-collision-image1.jpg" alt=""/></center></p>
<p><center><img src="../tutorials/yoshi.png" alt=""/><br/>(Save this Image for this Tutorial)</center></p>
<p>Last, but not least, we have variables to indicate if a variable is dead, and the type of entity. You&#8217;ll notice we have another enum, like the Flags, to specify the type of entity. This is important when dealing with collision events. So, back to the Mario and Spike example; lets say a Goomba happens to step in a spike. Now, in Mario world, the Goomba would not die. So, the Spike needs to know that entities type. Simple enough I think.</p>
<p>Okay, lets get into the core of the class now. Open up CEntity.cpp and lets have some more fun. Since we have had so many drastic changes, I am going to go through this line by line with the basics, and then move on to specific areas of the class. So, starting at the top we have our basic constructor, and statics:</p>
<div class="dean_ch" style="white-space: wrap;">
std::<span class="me2">vector</span>&lt;CEntity*&gt; &nbsp; CEntity::<span class="me2">EntityList</span>;</p>
<p>std::<span class="me2">vector</span>&lt;CEntityCol&gt; CEntityCol::<span class="me2">EntityColList</span>;</p>
<p>CEntityCol::<span class="me2">CEntityCol</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; EntityA = <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; EntityB = <span class="kw2">NULL</span>;<br />
<span class="br0">&#125;</span></p>
<p>CEntity::<span class="me2">CEntity</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; Surf_Entity = <span class="kw2">NULL</span>;</p>
<p>&nbsp; &nbsp; X = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; Y = <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; Width &nbsp; = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; Height &nbsp;= <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; MoveLeft &nbsp;= <span class="kw2">false</span>;<br />
&nbsp; &nbsp; MoveRight = <span class="kw2">false</span>;</p>
<p>&nbsp; &nbsp; Type = &nbsp;ENTITY_TYPE_GENERIC;</p>
<p>&nbsp; &nbsp; Dead = <span class="kw2">false</span>;<br />
&nbsp; &nbsp; Flags = ENTITY_FLAG_GRAVITY;</p>
<p>&nbsp; &nbsp; SpeedX = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; SpeedY = <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; AccelX = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; AccelY = <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; MaxSpeedX = <span class="nu0">5</span>;<br />
&nbsp; &nbsp; MaxSpeedY = <span class="nu0">5</span>;</p>
<p>&nbsp; &nbsp; CurrentFrameCol = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; CurrentFrameRow = <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; Col_X = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; Col_Y = <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; Col_Width &nbsp;= <span class="nu0">0</span>;<br />
&nbsp; &nbsp; Col_Height = <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Everything is simply set to 0, NULL, or some respective value. One thing to notice is the MaxSpeed variables. Set these to whatever you like. Usually this will depend on the particular entity that is in the game. Such as Mario will be able to move faster than a Goomba. Notice that I have grouped two classes into one file; that is okay to do sometimes! OnLoad is the exact same, so skip over that, and then move on to OnLoop:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> CEntity::<span class="me2">OnLoop</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="co1">//We&#8217;re not Moving</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>MoveLeft == <span class="kw2">false</span> &amp;&amp; MoveRight == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; StopMove<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>MoveLeft<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; AccelX = <span class="nu0">-0.5</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="kw1">else</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>MoveRight<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; AccelX = <span class="nu0">0.5</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>Flags &amp; ENTITY_FLAG_GRAVITY<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; AccelY = <span class="nu0">0</span>.75f;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; SpeedX += AccelX * CFPS::<span class="me2">FPSControl</span>.<span class="me1">GetSpeedFactor</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; SpeedY += AccelY * CFPS::<span class="me2">FPSControl</span>.<span class="me1">GetSpeedFactor</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>SpeedX &gt; MaxSpeedX<span class="br0">&#41;</span> &nbsp;SpeedX = &nbsp;MaxSpeedX;<br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>SpeedX &lt; -MaxSpeedX<span class="br0">&#41;</span> SpeedX = -MaxSpeedX;<br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>SpeedY &gt; MaxSpeedY<span class="br0">&#41;</span> &nbsp;SpeedY = &nbsp;MaxSpeedY;<br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>SpeedY &lt; -MaxSpeedY<span class="br0">&#41;</span> SpeedY = -MaxSpeedY;</p>
<p>&nbsp; &nbsp; OnAnimate<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; OnMove<span class="br0">&#40;</span>SpeedX, SpeedY<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Lots of new things here. First, remember MoveLeft and MoveRight are used to indicate if the entity is moving left or right (duh). If both are these are false, we call StopMove, which will handle settings Acceleration in the reverse direction so we come to a gradual stop. Below that, if MoveLeft or MoveRight are true, we give AccelX a value. 0.5 is an arbitrary number, you probably want to mess with this until you find a value that you like. Just below that, we have a condition checking if gravity is turned on for that particular entity. If it is, we set AccelY. This will cause our entity to fall down. Again, this is whatever value you want. The larger the number, the faster you will fall. Next, below that we have our SpeedX and SpeedY. Again, we increase the Speed of the entity over time in correlation to our Speed Factor. Then, below that, we check against our MaxSpeed variables to make sure we only go a certain speed. Finally, we call OnAnimate for our entity to animate, and then OnMove, which will actually move our entity.</p>
<p>Moving on, we have a few changes to OnRender:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> CEntity::<span class="me2">OnRender</span><span class="br0">&#40;</span>SDL_Surface* Surf_Display<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>Surf_Entity == <span class="kw2">NULL</span> || Surf_Display == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="kw1">return</span>;</p>
<p>&nbsp; &nbsp; CSurface::<span class="me2">OnDraw</span><span class="br0">&#40;</span>Surf_Display, Surf_Entity, X &#8211; CCamera::<span class="me2">CameraControl</span>.<span class="me1">GetX</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, Y &#8211; CCamera::<span class="me2">CameraControl</span>.<span class="me1">GetY</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, CurrentFrameCol * Width, <span class="br0">&#40;</span>CurrentFrameRow + Anim_Control.<span class="me1">GetCurrentFrame</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> * Height, Width, Height<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>First, we have added the Camera X and Y to the rendering coordinates for the entity. This makes the entities render in connection to where the camera is. This way, if the camera moves, all the entities will in respect to the camera position. Next, we have added CurrentFrameCol and CurrentFrameRow to the X2 and Y2 of OnDraw. This makes it so we can set different animations.</p>
<p>The first column has Yoshi facing the left, while the second column has Yoshi facing to the right. When we move to the left, we will want to set CurrentFrameCol = 0, so that Yoshi appears to be walking left. And when we move to the right, we will set CurrentFrameCol = 1, so that Yoshi appears to be walking to the right.</p>
<p>Skip over OnCleanup, nothing new there. We then have OnAnimate:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> CEntity::<span class="me2">OnAnimate</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>MoveLeft<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CurrentFrameCol = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="kw1">else</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>MoveRight<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CurrentFrameCol = <span class="nu0">1</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; Anim_Control.<span class="me1">OnAnimate</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>This is fairly straight forward. Like I said above, depending on which direction we are moving, we set the animation. Next, we have OnCollision:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> CEntity::<span class="me2">OnCollision</span><span class="br0">&#40;</span>CEntity* Entity<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Yay, an empty function. This function will be called whenever two entities hit each other. This entire time we&#8217;ve been creating an class for basic entities. In order to take advantage of this function, you will need to create our own class (like CPlayer, which we&#8217;ll do later on in this tutorial) and override this function. This is because the action taken by an entity depends upon it&#8217;s type. Like my earlier examples, a Goomba will not react the same way to a collision with a spike as Mario would.</p>
<p>Next, we our OnMove function.</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> CEntity::<span class="me2">OnMove</span><span class="br0">&#40;</span><span class="kw4">float</span> MoveX, <span class="kw4">float</span> MoveY<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>MoveX == <span class="nu0">0</span> &amp;&amp; MoveY == <span class="nu0">0</span><span class="br0">&#41;</span> <span class="kw1">return</span>;</p>
<p>&nbsp; &nbsp; <span class="kw4">double</span> NewX = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; <span class="kw4">double</span> NewY = <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; MoveX *= CFPS::<span class="me2">FPSControl</span>.<span class="me1">GetSpeedFactor</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; MoveY *= CFPS::<span class="me2">FPSControl</span>.<span class="me1">GetSpeedFactor</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>MoveX != <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>MoveX &gt;= <span class="nu0">0</span><span class="br0">&#41;</span> &nbsp;NewX = &nbsp;CFPS::<span class="me2">FPSControl</span>.<span class="me1">GetSpeedFactor</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; NewX = -CFPS::<span class="me2">FPSControl</span>.<span class="me1">GetSpeedFactor</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>MoveY != <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>MoveY &gt;= <span class="nu0">0</span><span class="br0">&#41;</span> &nbsp;NewY = &nbsp;CFPS::<span class="me2">FPSControl</span>.<span class="me1">GetSpeedFactor</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; NewY = -CFPS::<span class="me2">FPSControl</span>.<span class="me1">GetSpeedFactor</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">while</span><span class="br0">&#40;</span><span class="kw2">true</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>Flags &amp; ENTITY_FLAG_GHOST<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PosValid<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span><span class="br0">&#40;</span>X + NewX<span class="br0">&#41;</span>, <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span><span class="br0">&#40;</span>Y + NewY<span class="br0">&#41;</span><span class="br0">&#41;</span>; <span class="co1">//We don&#8217;t care about collisions, but we need to send events to other entities</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; X += NewX;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Y += NewY;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="kw1">else</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>PosValid<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span><span class="br0">&#40;</span>X + NewX<span class="br0">&#41;</span>, <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span><span class="br0">&#40;</span>Y<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; X += NewX;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="kw1">else</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SpeedX = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>PosValid<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span><span class="br0">&#40;</span>X<span class="br0">&#41;</span>, <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span><span class="br0">&#40;</span>Y + NewY<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Y += NewY;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="kw1">else</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SpeedY = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; MoveX += -NewX;<br />
&nbsp; &nbsp; &nbsp; &nbsp; MoveY += -NewY;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>NewX &gt; <span class="nu0">0</span> &amp;&amp; MoveX &lt;= <span class="nu0">0</span><span class="br0">&#41;</span> NewX = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>NewX &lt; <span class="nu0">0</span> &amp;&amp; MoveX &gt;= <span class="nu0">0</span><span class="br0">&#41;</span> NewX = <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>NewY &gt; <span class="nu0">0</span> &amp;&amp; MoveY &lt;= <span class="nu0">0</span><span class="br0">&#41;</span> NewY = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>NewY &lt; <span class="nu0">0</span> &amp;&amp; MoveY &gt;= <span class="nu0">0</span><span class="br0">&#41;</span> NewY = <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>MoveX == <span class="nu0">0</span><span class="br0">&#41;</span> NewX = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>MoveY == <span class="nu0">0</span><span class="br0">&#41;</span> NewY = <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>MoveX == <span class="nu0">0</span> &amp;&amp; MoveY &nbsp;== <span class="nu0">0</span><span class="br0">&#41;</span> &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>NewX &nbsp;== <span class="nu0">0</span> &amp;&amp; NewY &nbsp; == <span class="nu0">0</span><span class="br0">&#41;</span> &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>This function is quite a bit to take in. Lets see if we can straighten it all out. First, MoveX and MoveY are the where we want to move our entity. Remember up above, we call this passing our SpeedX and SpeedY. So, calling OnMove(1, 0) we would want to move 1 pixel to the right <u>every second</u>. At the top, we check our Speed, and if 0, we don&#8217;t do anything (duh). Below that, we do something I explained earlier. We multiply MoveX and MoveY by the speed factor. This gives us the correct movement per second. Just below that, we figure out the values for two new variables, NewX and NewY. These will be our X and Y increments. Remember, I mentioned above that this method is pixel perfect, so we need to inch closer and closer to our desired position. Now, we set our NewX and NewY to our speed factor because this is how much we should use to inch closer and closer to our desired position.</p>
<p>Below that, we have a seemingly infinite loop. This is where the movement magic happens and collision. First, we have a condition to check if the entity is a ghost, if it is, we increase the X and Y regardless if a collision has happened. We still call PosValid though, because this will notify entities of any collision that have taken place. Notice in PosValid we pass the current X and Y, along with adding NewX and NewY. This is where we <u>want to go</u>, so we check if that spot is empty.</p>
<p>If the entity is not a ghost, we do normal collision. We check X and Y separatly because we may be able to move up but not forward (think jumping into a wall). If the position is valid (empty), we increase the X or Y, if not, we set SpeedX or SpeedY to 0 which causes you to immediately stop (this is as close to reality as we need, if you do run into a wall you usually stop immediately). Now, below that, we change MoveX and MoveY depending upon our NewX. Say our MoveX was 2, and our NewX was 0.5. We would slowly decrease MoveX until it reaches 0. Once it does, we have come to our desired position and we are done. The 8 if statements below check if MoveX and MoveY have reached 0, and break out of the loop.</p>
<p>Moving on, we have StopMove:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> CEntity::<span class="me2">StopMove</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>SpeedX &gt; <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; AccelX = <span class="nu0">-1</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>SpeedX &lt; <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; AccelX = &nbsp;<span class="nu0">1</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>SpeedX &lt; <span class="nu0">2</span>.0f &amp;&amp; SpeedX &gt; <span class="nu0">-2</span>.0f<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; AccelX = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; SpeedX = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>This one is fairly straight forward. Depending on our Speed, we set the Acceleration in the reverse direction. So, if we are moving right, we set the acceleration to the left. The last if statement is simply a boundary to how slow we need to be going until we stop. If we didn&#8217;t do that, it&#8217;s possible that we could be stuck in a loop of moving left to right.</p>
<p>Next, we have a function that determines collision of two boxes. I will say right now that this function was borrowed from Cone3D (), and then modified. If it works, why fix it? </p>
<p>Anyway, lets take a look at it to see if I can help explain. At the top we define 8 variables, to define 8 sides. 4 sides are for the first object, and 4 sides are for the second object. Basically, we are doing bounding box collision:</p>
<p><center><img src="../tutorials/sdl-collision-image2.jpg" alt=""/></center></p>
<p>So, in a very basic sense, we want to check if two boxes have overlapped. The easiest method, is to determine if we <u>have not</u> collided on all 4 sides. So first, we determine the locations of all the sides:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">int</span> left1, left2;<br />
<span class="kw4">int</span> right1, right2;<br />
<span class="kw4">int</span> top1, top2;<br />
<span class="kw4">int</span> bottom1, bottom2;</p>
<p><span class="kw4">int</span> tX = <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>X + Col_X;<br />
<span class="kw4">int</span> tY = <span class="br0">&#40;</span><span class="kw4">int</span><span class="br0">&#41;</span>Y + Col_Y;</p>
<p>left1 = tX;<br />
left2 = oX;</p>
<p>right1 = left1 + Width &#8211; <span class="nu0">1</span> &#8211; Col_Width;<br />
right2 = oX + oW &#8211; <span class="nu0">1</span>;</p>
<p>top1 = tY;<br />
top2 = oY;</p>
<p>bottom1 = top1 + Height &#8211; <span class="nu0">1</span> &#8211; Col_Height;<br />
bottom2 = oY + oH &#8211; <span class="nu0">1</span>;<br />
&nbsp;</div>
<p>Look at the figure below to get an idea:</p>
<p>The top and left, are the X,Y of the object, and the right and bottom, are the X+Width-1, Y+Height-1. We subtract one in order to get the true coordinate of the side.</p>
<p>Next, we finally do the checking. What we do here is to check if one of the 4 sides of the first object are out of range of the second object. If one is, then we cannot possibly be colliding. But, if all 4 checks fail, we are colliding. So, if bottom1 is less than top2, that means the Bottom side of the first object is higher up on the screen then the Top of the second object:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">if</span> <span class="br0">&#40;</span>bottom1 &lt; top2<span class="br0">&#41;</span> <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="kw1">if</span> <span class="br0">&#40;</span>top1 &gt; bottom2<span class="br0">&#41;</span> <span class="kw1">return</span> <span class="kw2">false</span>;</p>
<p><span class="kw1">if</span> <span class="br0">&#40;</span>right1 &lt; left2<span class="br0">&#41;</span> <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="kw1">if</span> <span class="br0">&#40;</span>left1 &gt; right2<span class="br0">&#41;</span> <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp;</div>
<p>Finally, if all checks pass, then we return true for a collision. One note, remember that the Col_ variables are used to simply offset the size of the entity. If the entity is 32 width, but we offset by 2, that means when we check collision we use the Width of 30.</p>
<p>Moving on we find some more fun. We have our 3 last functions, the 3 PosValid functions. Overall, this functions basically determine if a collision has taken place. Remember, earlier OnMove will call PosValid to determine if a requested position is open to move to. So, keep in mind that NewX, and NewY in these functions is where the Entity <u>wants</u> to move to, not where it currently is. </p>
<p>Lets first look at PosValid. This function will determine any type of collision that has taken place, and return true or false. Now, this function basically has only two type of collision, Entity to Entity, and Map to Entity. That&#8217;s what PosValidTile and PosValidEntity are used for. </p>
<p>Now, the first collision we check for is a Map Collision. This is done by first grabbing 4 variables about our Entity. Basically, we want to know all the TileIDs that this entity is over. This is done by grabbing the X (and the Col_ offset) and dividing by the TILE_SIZE. This gives us our TileID for our X. The same goes for the Y variable. These two calculations determine our StartX and StartY. Now, EndX and EndY are determined in a similiar fashion, but we want to also add the Width and Height (just like we determined sides in the Collision function above). This will give us an area of tiles that this entity is over:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">int</span> StartX &nbsp;= <span class="br0">&#40;</span>NewX + Col_X<span class="br0">&#41;</span> / TILE_SIZE;<br />
<span class="kw4">int</span> StartY &nbsp;= <span class="br0">&#40;</span>NewY + Col_Y<span class="br0">&#41;</span> / TILE_SIZE;</p>
<p><span class="kw4">int</span> EndX&nbsp; &nbsp; = <span class="br0">&#40;</span><span class="br0">&#40;</span>NewX + Col_X<span class="br0">&#41;</span> + Width &#8211; Col_Width &#8211; <span class="nu0">1</span><span class="br0">&#41;</span> &nbsp;/ TILE_SIZE;<br />
<span class="kw4">int</span> EndY&nbsp; &nbsp; = <span class="br0">&#40;</span><span class="br0">&#40;</span>NewY + Col_Y<span class="br0">&#41;</span> + Height &#8211; Col_Height &#8211; <span class="nu0">1</span><span class="br0">&#41;</span>&nbsp; &nbsp; / TILE_SIZE;<br />
&nbsp;</div>
<p>Now that we have the Start and End of tiles, we simply loop through them:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> iY = StartY;iY &lt;= EndY;iY++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> iX = StartX;iX &lt;= EndX;iX++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Inside of this loop, this is where we check each tile to see if it&#8217;s a valid tile to move into. It the tile happens to be a wall, we would set the Return variable to false, to indicate that this requested position (hence the name PosValid) is not good:</p>
<div class="dean_ch" style="white-space: wrap;">
CTile* Tile = CArea::<span class="me2">AreaControl</span>.<span class="me1">GetTile</span><span class="br0">&#40;</span>iX * TILE_SIZE, iY * TILE_SIZE<span class="br0">&#41;</span>;</p>
<p><span class="kw1">if</span><span class="br0">&#40;</span>PosValidTile<span class="br0">&#40;</span>Tile<span class="br0">&#41;</span> == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">Return</span> = <span class="kw2">false</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Notice the new function GetTile, we&#8217;ll define this later on in this tutorial. But to explain it here, GetTile will return the CTile of any X and Y coordinate. After we get the tile, we pass it on to PosValidTile for it to figure out if the tile can be moved over or not. So, for a moment, jump on over to PosValidTile:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">bool</span> CEntity::<span class="me2">PosValidTile</span><span class="br0">&#40;</span>CTile* Tile<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>Tile == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>Tile-&gt;TypeID == TILE_TYPE_BLOCK<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Remember the enum in CTile.h at the top? Those enums were a list of types that you could give a tile. They are used here now, to determine if a tile can be moved on or not. So, that&#8217;s basically what we do here. First, if the Tile is NULL (which you should always check your pointers), we return true (meaning, yes, they can walk on this tile). Next, we check if the tile is a TILE_TYPE_BLOCK, if so, then no, the entity cannot walk on this tile. And finally, for all other types, yes, they can walk on this tile. Simple enough.</p>
<p>Now, jump back to the PosValid function. You will then find another loop:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">if</span><span class="br0">&#40;</span>Flags &amp; ENTITY_FLAG_MAPONLY<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="br0">&#125;</span><span class="kw1">else</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>;i &lt; EntityList.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>PosValidEntity<span class="br0">&#40;</span>EntityList<span class="br0">&#91;</span>i<span class="br0">&#93;</span>, NewX, NewY<span class="br0">&#41;</span> == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">Return</span> = <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>First, we do a simple check with our Flags again, this will check if we have the ENTITY_FLAG_MAPONLY flag turned on. If so, this means we&#8217;re only checking collisions against the map, so we don&#8217;t worry about Entity collisions. If we are checking collisions, then we jump to the loop. The loop is fairly simply, we go through the EntityList and pass each entity to the PosValidEntity, along with NewX and NewY. So, Jump on over to PosValidEntity:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">bool</span> CEntity::<span class="me2">PosValidEntity</span><span class="br0">&#40;</span>CEntity* Entity, <span class="kw4">int</span> NewX, <span class="kw4">int</span> NewY<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span><span class="kw3">this</span> != Entity &amp;&amp; Entity != <span class="kw2">NULL</span> &amp;&amp; Entity-&gt;Dead == <span class="kw2">false</span> &amp;&amp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Entity-&gt;Flags ^ ENTITY_FLAG_MAPONLY &amp;&amp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Entity-&gt;Collides<span class="br0">&#40;</span>NewX + Col_X, NewY + Col_Y, Width &#8211; Col_Width &#8211; <span class="nu0">1</span>, Height &#8211; Col_Height &#8211; <span class="nu0">1</span><span class="br0">&#41;</span> == <span class="kw2">true</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; CEntityCol EntityCol;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; EntityCol.<span class="me1">EntityA</span> = <span class="kw3">this</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; EntityCol.<span class="me1">EntityB</span> = Entity;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; CEntityCol::<span class="me2">EntityColList</span>.<span class="me1">push_back</span><span class="br0">&#40;</span>EntityCol<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Okay, this function is actually quite simple. We do some checks first on the Entity (the Entity we are wanting to collide with) to determine that this Entity is not the same Entity we&#8217;re moving (Mario cannot collide with Mario). That&#8217;s the &#8220;this != Entity.&#8221; It simply checks to make sure the Entities are not the same. We then check to make sure the Entity is not NULL, not Dead, and doesn&#8217;t have the ENTITY_FLAG_MAPONLY flag turned on. So far, so good. If all these checks pass, then we finally pass it to the Collides function of that Entity, passing along our Entities coordinates and Width/Height (with Col_ offsets). Remember, if any part of an if statement fails, like this != Entity, none of the other code in the if statement will be executed.</p>
<p>So, if the Entities do collide, finally, we use our new CEntityCol class. This will be a queue of collisions that have taken place. So, we push our Entity into EntityA, and the other Entity into EntityB, and then push it into the list. Finally, we return false, to indicate that this position is not valid. Wow, we are almost done!</p>
<p>Don&#8217;t rush out to compile, it won&#8217;t work. Why? Because, remember that GetTile function? <img src='http://www.sdltutorials.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>So, let&#8217;s add this into our code. Open CArea.h and add two functions at the bottom of the class:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw2">public</span>:<br />
&nbsp; &nbsp; CMap*&nbsp; &nbsp;GetMap<span class="br0">&#40;</span><span class="kw4">int</span> X, <span class="kw4">int</span> Y<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; CTile*&nbsp; GetTile<span class="br0">&#40;</span><span class="kw4">int</span> X, <span class="kw4">int</span> Y<span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>Then, open CArea.cpp and add the functions:</p>
<div class="dean_ch" style="white-space: wrap;">
CMap* CArea::<span class="me2">GetMap</span><span class="br0">&#40;</span><span class="kw4">int</span> X, <span class="kw4">int</span> Y<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">int</span> MapWidth &nbsp;= MAP_WIDTH * TILE_SIZE;<br />
&nbsp; &nbsp; <span class="kw4">int</span> MapHeight = MAP_HEIGHT * TILE_SIZE;</p>
<p>&nbsp; &nbsp; <span class="kw4">int</span> ID = X / MapWidth;<br />
&nbsp; &nbsp; &nbsp; &nbsp; ID = ID + <span class="br0">&#40;</span><span class="br0">&#40;</span>Y / MapHeight<span class="br0">&#41;</span> * AreaSize<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>ID &lt; <span class="nu0">0</span> || ID &gt;= MapList.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> &amp;MapList<span class="br0">&#91;</span>ID<span class="br0">&#93;</span>;<br />
<span class="br0">&#125;</span></p>
<p>CTile* CArea::<span class="me2">GetTile</span><span class="br0">&#40;</span><span class="kw4">int</span> X, <span class="kw4">int</span> Y<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">int</span> MapWidth &nbsp;= MAP_WIDTH * TILE_SIZE;<br />
&nbsp; &nbsp; <span class="kw4">int</span> MapHeight = MAP_HEIGHT * TILE_SIZE;</p>
<p>&nbsp; &nbsp; CMap* Map = GetMap<span class="br0">&#40;</span>X, Y<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>Map == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="kw1">return</span> <span class="kw2">NULL</span>;</p>
<p>&nbsp; &nbsp; X = X % MapWidth;<br />
&nbsp; &nbsp; Y = Y % MapHeight;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> Map-&gt;GetTile<span class="br0">&#40;</span>X, Y<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>I know, I know&#8230; they are more complicated than they look. First, look at GetMap. GetMap simply returns a CMap pointer at the given coordinates. It&#8217;s just like GetTile, but for Maps. Now, how it works is first by determining the size of our maps. We then translate our X,Y into an ID, and then return the CMap pointer. I won&#8217;t go into how translating X,Y into an ID works, because I believe this is explained in the last tutorial.</p>
<p>Now, go to GetTile. We determine the MapWidth and MapHeight, again (and I suppose this can be optimized), and then grab the Map with GetMap. We do a simple check for a NULL pointer (hint, hint), and then turn our X and Y into Tile coordinates. So, if our TILE_SIZE was 16, and our X was at 128, our Tile coordinate for X would be 8. Meaning, we are 8 tiles over. We finally then send this over to the Map GetTile. (Oh yes, one other function). This is why we have a GetMap function, if you are wondering. Rememember, CArea is a bunch of maps making one big area. So, we will have to determine which map is needed when grabbing tiles.</p>
<p>So, jump over to CMap.h now, and add this at the bottom:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw2">public</span>:<br />
&nbsp; &nbsp; CTile*&nbsp; GetTile<span class="br0">&#40;</span><span class="kw4">int</span> X, <span class="kw4">int</span> Y<span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>Then, open CMap.cpp and add this at the bottom:</p>
<div class="dean_ch" style="white-space: wrap;">
CTile* CMap::<span class="me2">GetTile</span><span class="br0">&#40;</span><span class="kw4">int</span> X, <span class="kw4">int</span> Y<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">int</span> ID = <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; ID = X / TILE_SIZE;<br />
&nbsp; &nbsp; ID = ID + <span class="br0">&#40;</span>MAP_WIDTH * <span class="br0">&#40;</span>Y / TILE_SIZE<span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>ID &lt; <span class="nu0">0</span> || ID &gt;= TileList.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> &amp;TileList<span class="br0">&#91;</span>ID<span class="br0">&#93;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>This is basically just like GetMap, but uses the TileList instead.</p>
<p>We&#8217;re almost done!</p>
<p>Just a few more changes to go. Create two new files called CPlayer.h and CPlayer.cpp. This class will be our main player and will extend our new CEntity class. So, open up CPlayer.h:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef _CPLAYER_H_</span><br />
&nbsp; &nbsp; <span class="co2">#define _CPLAYER_H_</span></p>
<p><span class="co2">#include &quot;CEntity.h&quot;</span></p>
<p><span class="kw2">class</span> CPlayer : <span class="kw2">public</span> CEntity <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; CPlayer<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">bool</span> OnLoad<span class="br0">&#40;</span><span class="kw4">char</span>* <span class="kw4">File</span>, <span class="kw4">int</span> Width, <span class="kw4">int</span> Height, <span class="kw4">int</span> MaxFrames<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnLoop<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnRender<span class="br0">&#40;</span>SDL_Surface* Surf_Display<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnCleanup<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnAnimate<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnCollision<span class="br0">&#40;</span>CEntity* Entity<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;</p>
<p><span class="co2">#endif</span><br />
&nbsp;</div>
<p>I won&#8217;t explain any of this other than it&#8217;s overriding all the virtual functions from CEntity.</p>
<p>Now, open up CPlayer.cpp:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;CPlayer.h&quot;</span></p>
<p>CPlayer::<span class="me2">CPlayer</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">bool</span> CPlayer::<span class="me2">OnLoad</span><span class="br0">&#40;</span><span class="kw4">char</span>* <span class="kw4">File</span>, <span class="kw4">int</span> Width, <span class="kw4">int</span> Height, <span class="kw4">int</span> MaxFrames<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>CEntity::<span class="me2">OnLoad</span><span class="br0">&#40;</span><span class="kw4">File</span>, Width, Height, MaxFrames<span class="br0">&#41;</span> == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CPlayer::<span class="me2">OnLoop</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; CEntity::<span class="me2">OnLoop</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CPlayer::<span class="me2">OnRender</span><span class="br0">&#40;</span>SDL_Surface* Surf_Display<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; CEntity::<span class="me2">OnRender</span><span class="br0">&#40;</span>Surf_Display<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CPlayer::<span class="me2">OnCleanup</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; CEntity::<span class="me2">OnCleanup</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CPlayer::<span class="me2">OnAnimate</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>SpeedX != <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Anim_Control.<span class="me1">MaxFrames</span> = <span class="nu0">8</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="kw1">else</span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Anim_Control.<span class="me1">MaxFrames</span> = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; CEntity::<span class="me2">OnAnimate</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CPlayer::<span class="me2">OnCollision</span><span class="br0">&#40;</span>CEntity* Entity<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Again, just like CEntity, but simply overriding the functions. One minor note, look at OnAnimate. In there we check our SpeedX to make a modification to our MaxFrames. Basically, if SpeedX != 0, (which means we are moving) we set our MaxFrames to 8. If we aren&#8217;t moving we set it to 0. Now, remember our Yoshi animation above, it has 8 frames for walking. So, if our Speed is not 0, we make Yoshi walk, otherwise we make it look like he&#8217;s standing still. This is the area where you would define other animations, like Idle, Walking, Running, Jumping, and so on.</p>
<p>Now, open up CApp.h and add the header file at the top:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;CPlayer.h&quot;</span><br />
&nbsp;</div>
<p>Then, add two Players in your class:</p>
<div class="dean_ch" style="white-space: wrap;">
CPlayer&nbsp;Player;<br />
CPlayer Player2;<br />
&nbsp;</div>
<p>Then, open up CApp_OnInit.cpp and initialize them:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">if</span><span class="br0">&#40;</span>Player.<span class="me1">OnLoad</span><span class="br0">&#40;</span><span class="st0">&quot;yoshi.png&quot;</span>, <span class="nu0">64</span>, <span class="nu0">64</span>, <span class="nu0">8</span><span class="br0">&#41;</span> == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw1">if</span><span class="br0">&#40;</span>Player2.<span class="me1">OnLoad</span><span class="br0">&#40;</span><span class="st0">&quot;yoshi.png&quot;</span>, <span class="nu0">64</span>, <span class="nu0">64</span>, <span class="nu0">8</span><span class="br0">&#41;</span> == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="br0">&#125;</span></p>
<p>Player2.<span class="me1">X</span> = <span class="nu0">100</span>;</p>
<p>CEntity::<span class="me2">EntityList</span>.<span class="me1">push_back</span><span class="br0">&#40;</span>&amp;Player<span class="br0">&#41;</span>;<br />
CEntity::<span class="me2">EntityList</span>.<span class="me1">push_back</span><span class="br0">&#40;</span>&amp;Player2<span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>Simple enough. We set PlayerX, the other Yoshi, over, so that we&#8217;re not on top of each other initially. Now, just below this add this extra code:</p>
<div class="dean_ch" style="white-space: wrap;">
CCamera::<span class="me2">CameraControl</span>.<span class="me1">TargetMode</span> = TARGET_MODE_CENTER;<br />
CCamera::<span class="me2">CameraControl</span>.<span class="me1">SetTarget</span><span class="br0">&#40;</span>&amp;Player.<span class="me1">X</span>, &amp;Player.<span class="me1">Y</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>Remember I said earlier, we&#8217;re going to make the camera follow our Yoshi. Now, open up CApp_OnRender and change this:</p>
<div class="dean_ch" style="white-space: wrap;">
CArea::<span class="me2">AreaControl</span>.<span class="me1">OnRender</span><span class="br0">&#40;</span>Surf_Display, CCamera::<span class="me2">CameraControl</span>.<span class="me1">GetX</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, CCamera::<span class="me2">CameraControl</span>.<span class="me1">GetY</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>To this:</p>
<div class="dean_ch" style="white-space: wrap;">
CArea::<span class="me2">AreaControl</span>.<span class="me1">OnRender</span><span class="br0">&#40;</span>Surf_Display, -CCamera::<span class="me2">CameraControl</span>.<span class="me1">GetX</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, -CCamera::<span class="me2">CameraControl</span>.<span class="me1">GetY</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>This change is also related to the Camera bug I mentioned above earlier. Open up CCamera.h and change the TargetX and TargetY from ints to floats. Also change the SetTarget ints to floats. </p>
<p>One last change now! Open up CApp.h and add this to your code (you should already have OnKeyDown):</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> OnKeyUp<span class="br0">&#40;</span>SDLKey sym, SDLMod mod, Uint16 unicode<span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>Then, open up CApp_OnEvent.cpp:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> CApp::<span class="me2">OnKeyDown</span><span class="br0">&#40;</span>SDLKey sym, SDLMod mod, Uint16 unicode<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">switch</span><span class="br0">&#40;</span>sym<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> SDLK_LEFT: <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Player.<span class="me1">MoveLeft</span> = <span class="kw2">true</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> SDLK_RIGHT: <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Player.<span class="me1">MoveRight</span> = <span class="kw2">true</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">default</span>: <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CApp::<span class="me2">OnKeyUp</span><span class="br0">&#40;</span>SDLKey sym, SDLMod mod, Uint16 unicode<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">switch</span><span class="br0">&#40;</span>sym<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> SDLK_LEFT: <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Player.<span class="me1">MoveLeft</span> = <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> SDLK_RIGHT: <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Player.<span class="me1">MoveRight</span> = <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">default</span>: <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>To go over this quickly, we basically check if Left or Right is pressed, and set MoveLeft or MoveRight on our Entity to true. If the key is depressed, we set it to false. </p>
<p>Now, we&#8217;re done! Remember to grab the Yoshi picture above to make sure he shows up right. Also, I changed the 1.map to have TILE_TYPE_BLOCKs in it. You can grab an updated one here: <a href="../tutorials/1.map">Example Map</a>. Since this tutorial is so lengthy, and took me a long time (sorry), please be sure to let me know of any bugs or something I forgot to address. Thanks.</p>
<p>P.S.<br />
In the next tutorial, we&#8217;ll see how to react to collisions that happen. In this tutorial, though we pushed collisions into a queue, we didn&#8217;t do anything with the queue yet.</p>
<p><b>SDL Collision &#8211; Tutorial Files:</b><br />
<b>Win32:</b> <a href="../tutorials/sdl-collision.zip">Zip</a>, <a href="../tutorials/sdl-collision.rar">Rar</a><br />
<b>Linux (CodeBlocks):</b> <a href="../tutorials/sdl-collision.tar.gz">Tar</a> (Thanks Jason!)<br />
<b>Linux (Makefile):</b> <a href="../tutorials/sdl-collision-linux.zip">Zip</a> (Thanks Sergey!)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sdltutorials.com/sdl-collision/feed/</wfw:commentRss>
		<slash:comments>60</slash:comments>
		</item>
		<item>
		<title>SDL Scale Surface</title>
		<link>http://www.sdltutorials.com/sdl-scale-surface/</link>
		<comments>http://www.sdltutorials.com/sdl-scale-surface/#comments</comments>
		<pubDate>Tue, 15 Jul 2008 11:22:13 +0000</pubDate>
		<dc:creator>Tim Jones</dc:creator>
				<category><![CDATA[SDL Tutorials]]></category>

		<guid isPermaLink="false">http://www.sdltutorials.com/sdl-scale-surface/</guid>
		<description><![CDATA[The following user tutorial was created by Mod J., for the purpose of expanding upon the SDLTutorials.com series, and expounding upon the use of SDL. This tutorial, though not purposely a part of the SDLTutorials.com or created for the series, may be a branch or addition to the series. Please read notes by the author [...]]]></description>
			<content:encoded><![CDATA[<p>The following user tutorial was created by Mod J., for the purpose of expanding upon the SDLTutorials.com series, and expounding upon the use of SDL. This tutorial, though not purposely a part of the SDLTutorials.com or created for the series, may be a branch or addition to the series. Please read notes by the author for any additional code and/or framework used by the author. If you wish to submit your own tutorial to this site, please visit the <a href="/user-tutorials/">&#8220;User Tutorials&#8221;</a> page.</p>
<hr/>
<p>Today we&#8217;re going to learn something about extending the capabilities of SDL_Surfaces. If we take a look at OpenGL, what happens when we load a Surface and we render it specifying a width and height bigger than the Surface&#8217;s original width and height? It gets automatically scaled (unless you specify you want to be repeated). In SDL there is no automatic way of scaling surfaces, so we&#8217;re going to make a (relatively simple) routine that does the trick.</p>
<p><span id="more-42"></span></p>
<p>First, the prototype of the function:</p>
<div class="dean_ch" style="white-space: wrap;">
SDL_Surface* SDL_ScaleSurface<span class="br0">&#40;</span>SDL_Surface* Surface, Uint16 Width, Uint16 Height<span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>What are these parameters? Well:<br />
Surface: The original surface the caller of the function wants to be scaled.<br />
Width: The width the caller wants the scaled surface to be (we use Uint16 because this is SDL&#8217;s standard for width).<br />
Height: The height the caller wants the scaled surface to be (we use Uint16 because this is SDL&#8217;s standard for height).</p>
<p>Got that? If you didn&#8217;t, try reading it over again; if you did, then let&#8217;s move on.</p>
<p>First, we have to check if the Surface&#8217;s width and height are valid; this is simple to accomplish:</p>
<div class="dean_ch" style="white-space: wrap;">
SDL_Surface* SDL_ScaleSurface<span class="br0">&#40;</span>SDL_Surface* Surface, Uint16 Width, Uint16 Height<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>!Surface || !Width || !Height<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>We don&#8217;t want a null pointer specified, since it will make BAD things happen when we try to read data from the surface. Secondly, a surface with 0 width or 0 height wouldn&#8217;t be a good idea, so let&#8217;s just return a null pointer when either of these things happen.</p>
<p>Now we need to create a surface that suits our needs; we&#8217;ll do this using the SDL_CreateRGBSurface function:</p>
<div class="dean_ch" style="white-space: wrap;">
SDL_Surface* SDL_ScaleSurface<span class="br0">&#40;</span>SDL_Surface* Surface, Uint16 Width, Uint16 Height<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_Surface *_ret = SDL_CreateRGBSurface<span class="br0">&#40;</span>Surface-&gt;flags, Width, Height, Surface-&gt;format-&gt;BitsPerPixel,<br />
&nbsp; &nbsp; &nbsp; &nbsp; Surface-&gt;format-&gt;Rmask, Surface-&gt;format-&gt;Gmask, Surface-&gt;format-&gt;Bmask, Surface-&gt;format-&gt;Amask<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Here we&#8217;re declaring and defining the return surface. We want its specifications to be the same as the surface we got from the caller, so we do so, and then the width and the height should be the same as the ones the caller specified. Looks pretty simple to me <img src='http://www.sdltutorials.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .</p>
<p>Now comes the math part. We need to calculate the scaling (or stretching) factor to be applied when we copy the surface&#8217;s pixels. It&#8217;s not as hard as it seems, we just divide the width the caller wants by the width of the surface, what have we calculated then? If you calculate the scaling factor for the widths, you&#8217;ll get the number of pixels you need for each individual source pixel, in other words, each pixel you read from the source surface has to be drawn SCALING_FACTOR_X times over the width in order to stretch it (the same goes for the height).</p>
<p>Calculations:</p>
<div class="dean_ch" style="white-space: wrap;">
SDL_Surface* SDL_ScaleSurface<span class="br0">&#40;</span>SDL_Surface* Surface, Uint16 Width, Uint16 Height<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">double</span>&nbsp; _stretch_factor_x = <span class="br0">&#40;</span>static_cast&lt;double&gt;<span class="br0">&#40;</span>Width<span class="br0">&#41;</span> &nbsp;/ static_cast&lt;double&gt;<span class="br0">&#40;</span>Surface-&gt;w<span class="br0">&#41;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; _stretch_factor_y = <span class="br0">&#40;</span>static_cast&lt;double&gt;<span class="br0">&#40;</span>Height<span class="br0">&#41;</span> / static_cast&lt;double&gt;<span class="br0">&#40;</span>Surface-&gt;h<span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Casting might be bad to some of you, but it&#8217;s necessary here since we need the scaling factors as a double. This probably could have been done better, like checking for w = 0 and h = 0, but this is just a simple tutorial <img src='http://www.sdltutorials.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> . We&#8217;re just doing here what I explained before.</p>
<p>Now we need to do the actual drawing. This might look overwhelming, but it&#8217;s not as hard as it seems. We&#8217;re just going to make 2 for-loops to run across all the pixels on the source surface, and then 2 more loops for drawing STRETCHING_FACTOR pixels for each pixel that gets read from the source surface.</p>
<p>Here we go!</p>
<div class="dean_ch" style="white-space: wrap;">
SDL_Surface* SDL_ScaleSurface<span class="br0">&#40;</span>SDL_Surface *Surface, Uint16 Width, Uint16 Height<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span>Sint32 y = <span class="nu0">0</span>; y &lt; Surface-&gt;h; y++<span class="br0">&#41;</span> <span class="co1">//Run across all Y pixels.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span>Sint32 x = <span class="nu0">0</span>; x &lt; Surface-&gt;w; x++<span class="br0">&#41;</span> <span class="co1">//Run across all X pixels.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span>Sint32 o_y = <span class="nu0">0</span>; o_y &lt; _stretch_factor_y; ++o_y<span class="br0">&#41;</span> <span class="co1">//Draw _stretch_factor_y pixels for each Y pixel.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span>Sint32 o_x = <span class="nu0">0</span>; o_x &lt; _stretch_factor_x; ++o_x<span class="br0">&#41;</span> <span class="co1">//Draw _stretch_factor_x pixels for each X pixel.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DrawPixel<span class="br0">&#40;</span>_ret, static_cast&lt;Sint32&gt;<span class="br0">&#40;</span>_stretch_factor_x * x<span class="br0">&#41;</span> + o_x, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; static_cast&lt;Sint32&gt;<span class="br0">&#40;</span>_stretch_factor_y * y<span class="br0">&#41;</span> + o_y, ReadPixel<span class="br0">&#40;</span>Surface, x, y<span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>I&#8217;m not going to specify the DrawPixel and ReadPixel functions here, as they can be gotten from the SDL documentation wiki (<a href="http://www.libsdl.org/cgi/docwiki.cgi/Pixel_Access">http://www.libsdl.org/cgi/docwiki.cgi/Pixel_Access</a>), though my prototype might be a little different, they work like this:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> DrawPixel<span class="br0">&#40;</span>SDL_Surface* Target, Sint16 X, Sint16 Y, Uint16 Color<span class="br0">&#41;</span>; <span class="co1">//Draws the specified color at the specified X and Y on the target surface.</span><br />
Uint32 ReadPixel<span class="br0">&#40;</span>SDL_Surface* Source, Sint16 X, Sint16 Y<span class="br0">&#41;</span>; <span class="co1">//Returns the color of the specified surface on the specified X and Y coordinates.</span><br />
&nbsp;</div>
<p>The principle is pretty easy:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">for</span><span class="br0">&#40;</span>each_source_pixel<span class="br0">&#41;</span> -&gt; draw<span class="br0">&#40;</span>scaling_factor_amount_of_pixels_on_the_return_value<span class="br0">&#41;</span><br />
&nbsp;</div>
<p>The DrawPixel call might look weird to you, but actually what happens inside is this: Draw a pixel on(the return value, stretching_factor_x * source_x because the destination moves each time and then blit the amount of pixels we need, same for y, what color do we need? The color that&#8217;s on the source surface at the x and y position, because we need to blit it scaling_factor amount of times).</p>
<p>Why the strange X and Y coordinates? Well, imagine we need to make the width twice as bug, look at this crappy drawing:</p>
<pre>
Source surface:
---------------------------------------------
|x,y       |0,0       |1,0       |2,0       |
---------------------------------------------

Destination:
---------------------------------------------
|x,y       |0,0 &#038; 1,0 |2,0 &#038; 3,0 |4,0 &#038; 5,0 |
---------------------------------------------
</pre>
<p>See? When at pixel (0,0) we need to draw a pixel at (0,0) and (1,0) because we need 2 pixels on the destination for each 1 pixel on the source (following the X-axis because it&#8217;s the width), the same goes for the Y. We&#8217;re actually just skipping what we&#8217;ve already drawn, _stretch_factor_x * x is actually &#8216;Move to the corresponding pixel on the destination. It makes the (2,0) on the drawing say that it should begin its drawing at (4,0) on the destination, then it loops o_x untill it&#8217;s smaller than 2, drawing first at (4,0) and then when o_x increments at (5,0). It&#8217;s THAT easy.</p>
<p>Finally we return the desired surface:</p>
<div class="dean_ch" style="white-space: wrap;">
SDL_Surface *SDL_ScaleSurface<span class="br0">&#40;</span>SDL_Surface *Surface, Uint16 Width, Uint16 Height<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> _ret;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Here an overview of the full function:</p>
<div class="dean_ch" style="white-space: wrap;">
SDL_Surface *ScaleSurface<span class="br0">&#40;</span>SDL_Surface *Surface, Uint16 Width, Uint16 Height<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>!Surface || !Width || !Height<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span>;<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; SDL_Surface *_ret = SDL_CreateRGBSurface<span class="br0">&#40;</span>Surface-&gt;flags, Width, Height, Surface-&gt;format-&gt;BitsPerPixel,<br />
&nbsp; &nbsp; &nbsp; &nbsp; Surface-&gt;format-&gt;Rmask, Surface-&gt;format-&gt;Gmask, Surface-&gt;format-&gt;Bmask, Surface-&gt;format-&gt;Amask<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw4">double</span>&nbsp; _stretch_factor_x = <span class="br0">&#40;</span>static_cast&lt;double&gt;<span class="br0">&#40;</span>Width<span class="br0">&#41;</span> &nbsp;/ static_cast&lt;double&gt;<span class="br0">&#40;</span>Surface-&gt;w<span class="br0">&#41;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; _stretch_factor_y = <span class="br0">&#40;</span>static_cast&lt;double&gt;<span class="br0">&#40;</span>Height<span class="br0">&#41;</span> / static_cast&lt;double&gt;<span class="br0">&#40;</span>Surface-&gt;h<span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span>Sint32 y = <span class="nu0">0</span>; y &lt; Surface-&gt;h; y++<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span>Sint32 x = <span class="nu0">0</span>; x &lt; Surface-&gt;w; x++<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span>Sint32 o_y = <span class="nu0">0</span>; o_y &lt; _stretch_factor_y; ++o_y<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span>Sint32 o_x = <span class="nu0">0</span>; o_x &lt; _stretch_factor_x; ++o_x<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DrawPixel<span class="br0">&#40;</span>_ret, static_cast&lt;Sint32&gt;<span class="br0">&#40;</span>_stretch_factor_x * x<span class="br0">&#41;</span> + o_x, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; static_cast&lt;Sint32&gt;<span class="br0">&#40;</span>_stretch_factor_y * y<span class="br0">&#41;</span> + o_y, ReadPixel<span class="br0">&#40;</span>Surface, x, y<span class="br0">&#41;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> _ret;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>I hope you learned something with this tutorial, maybe I&#8217;ll write more tutorials in the future (perhaps something on texture repeating? <img src='http://www.sdltutorials.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> ).</p>
<p>See ya!<br />
Creature</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sdltutorials.com/sdl-scale-surface/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>SDL Sokoban (User Tutorial)</title>
		<link>http://www.sdltutorials.com/sdl-sokoban/</link>
		<comments>http://www.sdltutorials.com/sdl-sokoban/#comments</comments>
		<pubDate>Mon, 09 Jun 2008 20:11:18 +0000</pubDate>
		<dc:creator>Tim Jones</dc:creator>
				<category><![CDATA[SDL Tutorials]]></category>

		<guid isPermaLink="false">http://www.sdltutorials.com/sdl-sokoban-user-tutorial/</guid>
		<description><![CDATA[The following user tutorial was created by Arseniy B., for the purpose of expanding upon the SDLTutorials.com series, and expounding upon the use of SDL. This tutorial, though not purposely a part of the SDLTutorials.com or created for the series, may be a branch or addition to the series. Please read notes by the author [...]]]></description>
			<content:encoded><![CDATA[<p>The following user tutorial was created by Arseniy B., for the purpose of expanding upon the SDLTutorials.com series, and expounding upon the use of SDL. This tutorial, though not purposely a part of the SDLTutorials.com or created for the series, may be a branch or addition to the series. Please read notes by the author for any additional code and/or framework used by the author. If you wish to submit your own tutorial to this site, please visit the <a href="/user-tutorials/">&#8220;User Tutorials&#8221;</a> page.</p>
<hr/>
<p>IMPORTANT NOTE: I DON&#8217;T NAME SURFACES LIKE TIM DOES. WHEN HE CALLS IT Surf_Display, MINE IS SIMPLY SurfDisplay, WITHOUT THE UNDERSCORE. MAKE SURE YOU KNOW THIS, AND ADAPT TO THE TUTORIAL ACCORDINGLY. ALSO, WHEN I MAKE PROTOTYPES IN CLASS DEFINITIONS, THE ONLY STUFF I WRITE IN THE PARAMETERS AREA (I.E. THE PARENTHESES) IS THE TYPE OF DATA TAKEN, NOT THE NAME OF THE DATA TAKEN. THAT NAME IS ONLY IN THE ACTUAL FUNCTION DEFINITION, AT LEAST FOR ME.</p>
<p>This tutorial is based on everything you&#8217;ve learned by now, if you&#8217;ve been following the tutorials in order and have just finished the Maps tutorial. Get ready to get a glimpse of creating your first real game! (Not counting that fabulous tic-tac-toe.) Similarly, the code this comes from is from all the code you&#8217;ve written up to the Maps tutorial, and including it. It would be wise to make a new Code::Blocks project (or a new DevC++ project, or whatever), because this tutorial will delve a different way for a bit, and you don&#8217;t want to mess up your existing code for the upcoming Collision Detection tutorial. Speaking of that, this tutorial will introduce you to very simple collision detection, on a tile-based board.</p>
<p><span id="more-39"></span></p>
<p>If you&#8217;re all ready, open up your [new] project and let&#8217;s begin!</p>
<p>First, we need an introduction to Sokoban. For those of you who have never played this unusually fun and addicting puzzle game, here&#8217;s how it goes. There&#8217;s a player that you control with the arrow keys, and he pushes boxes on tiles to their &#8216;home&#8217; locations. Those locations are special tiles on the board. Once all the boxes are at &#8216;home&#8217;, the level ends. The challenge, though, is that the boxes are positioned initially in such a way that makes it a puzzle. A box can&#8217;t be pushed into a wall, or out of a corner, etc., so it becomes harder. That&#8217;s all there is to it!</p>
<p>Here we go. This tutorial, like the last few, will only instruct you as to where to put the code I write; there will be no full documents, unless they&#8217;re new. First and foremost, we need to modify CTile. Add another element to the typedef enum statement at the top.</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">typedef</span> <span class="kw2">enum</span> <span class="br0">&#123;</span>TILE_TYPE_NONE = <span class="nu0">0</span>, TILE_TYPE_NORMAL, TILE_TYPE_BLOCK, TILE_TYPE_HOMEOFBLOCK<span class="br0">&#125;</span>;<br />
&nbsp;</div>
<p>You&#8217;ll see why soon.</p>
<p>Also, we need to make a new function in the CMap class that checks what the TypeID of a given tile is. Add the appropriate prototype in the class definition, and add this function in CMap.cpp:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">int</span> CMap::<span class="me2">TypeOfTileAt</span><span class="br0">&#40;</span><span class="kw4">int</span> X, <span class="kw4">int</span> Y<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">int</span> CheckID = <span class="br0">&#40;</span>X / TILE_SIZE<span class="br0">&#41;</span> + <span class="br0">&#40;</span><span class="br0">&#40;</span>Y / TILE_SIZE<span class="br0">&#41;</span> * MAP_WIDTH<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">return</span> TileList<span class="br0">&#91;</span>CheckID<span class="br0">&#93;</span>.<span class="me1">TypeID</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Simple enough.</p>
<p>Sokoban needs blocks. Let&#8217;s make a block! The CBlock class is going to extend CEntity. We&#8217;re going to make this new class for the block inherit all the attributes (variables) and methods (functions) of the CEntity class. It also has its own attributes and methods that don&#8217;t exist in the CEntity class alone. A good example to illustrate this is geometry. The &#8216;parent&#8217; class is the Shape class. It has the attributes of area, color, and perimeter. A child is Square, which has those same attributes due to inheritance, but also has side (because it&#8217;s a square), and Shape doesn&#8217;t have side because it could be a shape with no straight lines. Circle is also a child, because it inherits area, color, and perimeter, but it has a radius attribute for itself; etc.</p>
<p><img src="images/sokoban-shapeinheritancetree.png"></p>
<p>So open up two new files, CBlock.h and CBlock.cpp.</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef CBLOCK_H_INCLUDED</span><br />
<span class="co2">#define CBLOCK_H_INCLUDED</span><br />
<span class="co2">#include &quot;CEntity.h&quot;</span><br />
<span class="co2">#include &quot;CArea.h&quot;</span><br />
<span class="co2">#include &lt;vector&gt;</span></p>
<p>using namespace std;</p>
<p>class CBlock : public CEntity <span class="br0">&#123;</span><br />
&nbsp; &nbsp; public:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> vector&lt;CBlock*&gt; BlockList;<br />
&nbsp; &nbsp; &nbsp; &nbsp; bool OnHomeTile;<br />
&nbsp; &nbsp; &nbsp; &nbsp; CBlock<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> CheckForHome<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnMove<span class="br0">&#40;</span><span class="kw4">int</span>, <span class="kw4">int</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;</p>
<p><span class="co2">#endif // CBLOCK_H_INCLUDED</span><br />
&nbsp;</div>
<p>And&#8230;</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;CBlock.h&quot;</span></p>
<p>vector&lt;CBlock*&gt; CBlock::<span class="me2">BlockList</span>;</p>
<p>CBlock::<span class="me2">CBlock</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; OnHomeTile = <span class="kw2">false</span>;<br />
&nbsp; &nbsp; SurfEntity = <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; X = Y = <span class="nu0">0</span>.0f;<br />
&nbsp; &nbsp; Width = Height = <span class="nu0">32</span>;<br />
&nbsp; &nbsp; AnimState = <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CBlock::<span class="me2">CheckForHome</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CArea::<span class="me2">AreaControl</span>.<span class="me1">MapList</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">TypeOfTileAt</span><span class="br0">&#40;</span>X, Y<span class="br0">&#41;</span> == <span class="nu0">3</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; OnHomeTile = <span class="kw2">true</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; OnHomeTile = <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CBlock::<span class="me2">OnMove</span><span class="br0">&#40;</span><span class="kw4">int</span> MoveX, <span class="kw4">int</span> MoveY<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; X += MoveX;<br />
&nbsp; &nbsp; Y += MoveY;<br />
<span class="br0">&#125;</span></p>
<p>&nbsp;</p></div>
<p>
After the class definition, we have &#8221; : public CEntity.&#8221; This is what tells the compiler that this new class extends and inherits the attributes and methods of the CEntity class. This class, much like the CEntity class, has its own vector of CBlocks. Sure, it makes sense to just use the CEntity::EntityList vector in its place, but we&#8217;re going to need a vector of just CBlocks (not including the CEntity that will be CPlayer).</p>
<p>Next, CBlock has an attribute that says whether or not it&#8217;s located on its &#8216;home&#8217; tile. The constructor, CBlock(), sets that value to false, and the rest of the values which it inherits from its parent class, CEntity, are set to their default values, as well. The next function, CheckForHome(), sets the OnHomeTile boolean value to true, if the TypeID of the tile under the block is TILE_TYPE_HOMEOFBLOCK. Otherwise, it&#8217;s false. There isn&#8217;t a return statement because this function just deals with CBlock&#8217;s personal variables. The final function, OnMove, is very simple. It takes in two integer variables, MoveX and MoveY, and increments the block&#8217;s X and the block&#8217;s Y by those amounts, respectively. (Remember, even though the class didn&#8217;t set an X or a Y variable, CBlock inherits those two from CEntity, so they&#8217;re allowed to be manipulated. And they exist.)</p>
<p>Next, we need to implement a player, in kinda the same way.</p>
<p>CPlayer, a child of CEntity, will inherit every one of its attributes and methods, and we will define our own and maybe even override the inherited methods. Make two new files, CPlayer.cpp and CPlayer.h, and open up CPlayer.h.</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef CPLAYER_H_INCLUDED</span><br />
<span class="co2">#define CPLAYER_H_INCLUDED</span><br />
<span class="co2">#include &quot;CEntity.h&quot;</span><br />
<span class="co2">#include &quot;CBlock.h&quot;</span><br />
<span class="co2">#include &quot;CArea.h&quot;</span></p>
<p><span class="kw4">typedef</span> <span class="kw2">enum</span> <span class="br0">&#123;</span>YES = <span class="nu0">0</span>, NO, BLOCK<span class="br0">&#125;</span>;</p>
<p>class CPlayer : public CEntity <span class="br0">&#123;</span><br />
&nbsp; &nbsp; public:<br />
&nbsp; &nbsp; &nbsp; &nbsp; CPlayer<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnMove<span class="br0">&#40;</span><span class="kw4">int</span> MoveX, <span class="kw4">int</span> MoveY<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> CanPlayerMoveLeft<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> CanPlayerMoveUp<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> CanPlayerMoveRight<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> CanPlayerMoveDown<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;</p>
<p><span class="co2">#endif CPLAYER_H_INCLUDED</span><br />
&nbsp;</div>
<p>Then, open CPlayer.cpp and let&#8217;s define the functions.</p>
<div class="dean_ch" style="white-space: wrap;">
<p><span class="co2">#include &quot;CPlayer.h&quot;</span></p>
<p>CPlayer::<span class="me2">CPlayer</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; SurfEntity = <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; X = Y = <span class="nu0">0</span>.0f;<br />
&nbsp; &nbsp; Width = Height = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; AnimState = <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CPlayer::<span class="me2">OnMove</span><span class="br0">&#40;</span><span class="kw4">int</span> MoveX, <span class="kw4">int</span> MoveY<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; X += MoveX;<br />
&nbsp; &nbsp; Y += MoveY;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">int</span> CPlayer::<span class="me2">CanPlayerMoveLeft</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CArea::<span class="me2">AreaControl</span>.<span class="me1">MapList</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">TypeOfTileAt</span><span class="br0">&#40;</span>X &#8211; <span class="nu0">32</span>, Y<span class="br0">&#41;</span> == <span class="nu0">2</span><span class="br0">&#41;</span> <span class="kw1">return</span> NO;</p>
<p>&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; CBlock::<span class="me2">BlockList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;X == X &#8211; <span class="nu0">32</span> &amp;&amp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;Y == Y<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CArea::<span class="me2">AreaControl</span>.<span class="me1">MapList</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">TypeOfTileAt</span><span class="br0">&#40;</span>X &#8211; <span class="nu0">64</span>, Y<span class="br0">&#41;</span> == <span class="nu0">2</span><span class="br0">&#41;</span> <span class="kw1">return</span> NO;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> k = <span class="nu0">0</span>; k &lt; CBlock::<span class="me2">BlockList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; k++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>k<span class="br0">&#93;</span>-&gt;Y == Y &amp;&amp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>k<span class="br0">&#93;</span>-&gt;X == X &#8211; <span class="nu0">64</span><span class="br0">&#41;</span> <span class="kw1">return</span> NO;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> BLOCK;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> YES;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">int</span> CPlayer::<span class="me2">CanPlayerMoveUp</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CArea::<span class="me2">AreaControl</span>.<span class="me1">MapList</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">TypeOfTileAt</span><span class="br0">&#40;</span>X, Y &#8211; <span class="nu0">32</span><span class="br0">&#41;</span> == <span class="nu0">2</span><span class="br0">&#41;</span> <span class="kw1">return</span> NO;</p>
<p>&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; CBlock::<span class="me2">BlockList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;Y == Y &#8211; <span class="nu0">32</span> &amp;&amp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;X == X<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CArea::<span class="me2">AreaControl</span>.<span class="me1">MapList</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">TypeOfTileAt</span><span class="br0">&#40;</span>X, Y &#8211; <span class="nu0">64</span><span class="br0">&#41;</span> == <span class="nu0">2</span><span class="br0">&#41;</span> <span class="kw1">return</span> NO;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> k = <span class="nu0">0</span>; k &lt; CBlock::<span class="me2">BlockList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; k++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>k<span class="br0">&#93;</span>-&gt;Y == Y &#8211; <span class="nu0">64</span> &amp;&amp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>k<span class="br0">&#93;</span>-&gt;X == X<span class="br0">&#41;</span> <span class="kw1">return</span> NO;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> BLOCK;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> YES;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">int</span> CPlayer::<span class="me2">CanPlayerMoveRight</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CArea::<span class="me2">AreaControl</span>.<span class="me1">MapList</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">TypeOfTileAt</span><span class="br0">&#40;</span>X + <span class="nu0">32</span>, Y<span class="br0">&#41;</span> == <span class="nu0">2</span><span class="br0">&#41;</span> <span class="kw1">return</span> NO;</p>
<p>&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; CBlock::<span class="me2">BlockList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;X == X + <span class="nu0">32</span> &amp;&amp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;Y == Y<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CArea::<span class="me2">AreaControl</span>.<span class="me1">MapList</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">TypeOfTileAt</span><span class="br0">&#40;</span>X + <span class="nu0">64</span>, Y<span class="br0">&#41;</span> == <span class="nu0">2</span><span class="br0">&#41;</span> <span class="kw1">return</span> NO;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> k = <span class="nu0">0</span>; k &lt; CBlock::<span class="me2">BlockList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; k++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>k<span class="br0">&#93;</span>-&gt;Y == Y &amp;&amp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>k<span class="br0">&#93;</span>-&gt;X == X + <span class="nu0">64</span><span class="br0">&#41;</span> <span class="kw1">return</span> NO;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> BLOCK;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> YES;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">int</span> CPlayer::<span class="me2">CanPlayerMoveDown</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CArea::<span class="me2">AreaControl</span>.<span class="me1">MapList</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">TypeOfTileAt</span><span class="br0">&#40;</span>X, Y + <span class="nu0">32</span><span class="br0">&#41;</span> == <span class="nu0">2</span><span class="br0">&#41;</span> <span class="kw1">return</span> NO;</p>
<p>&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; CBlock::<span class="me2">BlockList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;Y == Y + <span class="nu0">32</span> &amp;&amp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;X == X<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CArea::<span class="me2">AreaControl</span>.<span class="me1">MapList</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">TypeOfTileAt</span><span class="br0">&#40;</span>X, Y + <span class="nu0">64</span><span class="br0">&#41;</span> == <span class="nu0">2</span><span class="br0">&#41;</span> <span class="kw1">return</span> NO;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> k = <span class="nu0">0</span>; k &lt; CBlock::<span class="me2">BlockList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; k++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>k<span class="br0">&#93;</span>-&gt;Y == Y + <span class="nu0">64</span> &amp;&amp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>k<span class="br0">&#93;</span>-&gt;X == X<span class="br0">&#41;</span> <span class="kw1">return</span> NO;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> BLOCK;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> YES;<br />
<span class="br0">&#125;</span></p>
<p>&nbsp;</p></div>
<p>A little explanation. Just like with CBlock, &#8221; : public CEntity&#8221; is to extend the CEntity class.</p>
<p>In the CPlayer class, we&#8217;re defining five new functions, OnMove and the four &#8220;can he move in a certain direction&#8221; functions. OnMove is simple: two integers are passed, and the CPlayer&#8217;s X and Y coordinates increment by exactly that much. (Remember, CPlayer has the X and Y attributes, even though they weren&#8217;t defined in CPlayer.h, because he INHERITED them from CEntity.) Here&#8217;s where it gets a little trickier. Those four other functions are the collision detection functions. They check whether the player can move left, up, right, or down, and return what the result of the check was. So let&#8217;s examine CanPlayerMoveLeft() closely.</p>
<p>First, look at the top of CPlayer.h. The typedef enum statement, like others before, makes YES equal to 0, NO equal to 1, and BLOCK equal to 2; this is because it&#8217;s much easier to remember YES, NO, and BLOCK, than it is to remember that 0 is the same thing as YES, etc.</p>
<p>The function first checks if the TypeID of the tile to the left of the player is TILE_TYPE_BLOCK. If so, then the function returns NO, meaning the player cannot move left (because a wall is blocking his movement). Then, the function checks if there&#8217;s a block there. It does this by looping through every one of the CBlocks in the static BlockList (which are automatically added when the CBlocks are loaded&#8230;we&#8217;ll get to that a bit later). Every time it loops, it checks the X and Y coordinates of the block, and if a block is to the left of the player, then the function returns BLOCK, which will tell the program that the player has a block to the left of him. There are two caveats, though. First, if there is a block to the left of the player, but there is <i>also</i> a TILE_TYPE_BLOCK (i.e. a wall) to the left of that block, the player cannot move, and the function returns NO. Similarly, second, if there are two blocks to the left of him, the player can&#8217;t move (he&#8217;s not THAT strong!), and the function returns NO. Otherwise, it returns BLOCK. However, if NONE of those are true, then the function returns a simple YES, because the player has a free spot to his left.</p>
<p>That repeats for each direction. The purpose of this function is so that, when the OnKeyDown() function is called (in CApp), before moving the character we test if he <i>can</i> move. That said, let&#8217;s move on to the implementation of these functions.</p>
<p>We need a way to load the blocks. Just like with the maps and areas, we&#8217;re going to have a directory next to your exe called blocks, with (so far) one file in it: 1.blocks. Make that file, position it accordingly in the directory tree, and open it. Our first level will have blocks at these coordinates:</p>
<p>(160, 128)<br />
(160, 192)<br />
(224, 160)<br />
(224, 192)<br />
(160, 288)<br />
(64, 288)</p>
<p>Make two more new files called CBlockControl.h and CBlockControl.cpp, and open up the header.</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef CBLOCKCONTROL_H_INCLUDED</span><br />
<span class="co2">#define CBLOCKCONTROL_H_INCLUDED</span><br />
<span class="co2">#include &quot;CBlock.h&quot;</span><br />
<span class="co2">#include &lt;vector&gt;</span></p>
<p>using namespace std;</p>
<p>class CBlockControl <span class="br0">&#123;</span><br />
&nbsp; &nbsp; public:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> vector&lt;CBlock&gt; BlockList;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> bool LoadBlocksFromFile<span class="br0">&#40;</span><span class="kw4">char</span>*<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;</p>
<p><span class="co2">#endif // CBLOCKCONTROL_H_INCLUDED</span><br />
&nbsp;</div>
<p>And&#8230;</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;CBlockControl.h&quot;</span></p>
<p>vector&lt;CBlock&gt; CBlockControl::<span class="me2">BlockList</span>;</p>
<p>bool CBlockControl::<span class="me2">LoadBlocksFromFile</span><span class="br0">&#40;</span><span class="kw4">char</span>* File<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; FILE* FileHandle = fopen<span class="br0">&#40;</span>File, <span class="st0">&quot;r&quot;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>FileHandle == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw4">int</span> BlockCount;</p>
<p>&nbsp; &nbsp; fscanf<span class="br0">&#40;</span>FileHandle, <span class="st0">&quot;%d<span class="es0">\n</span>&quot;</span>, &amp;BlockCount<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; BlockCount; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CBlock TmpBlock;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> X, Y;<br />
&nbsp; &nbsp; &nbsp; &nbsp; fscanf<span class="br0">&#40;</span>FileHandle, <span class="st0">&quot;%d &quot;</span>, &amp;X<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; fscanf<span class="br0">&#40;</span>FileHandle, <span class="st0">&quot;%d<span class="es0">\n</span>&quot;</span>, &amp;Y<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; TmpBlock.<span class="me1">X</span> = X;<br />
&nbsp; &nbsp; &nbsp; &nbsp; TmpBlock.<span class="me1">Y</span> = Y;<br />
&nbsp; &nbsp; &nbsp; &nbsp; TmpBlock.<span class="me1">OnLoad</span><span class="br0">&#40;</span><span class="st0">&quot;gfx/block.png&quot;</span>, <span class="nu0">32</span>, <span class="nu0">32</span>, <span class="nu0">1</span>, <span class="kw2">false</span>, <span class="nu0">64</span>, <span class="nu0">64</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; CBlockControl::<span class="me2">BlockList</span>.<span class="me1">push_back</span><span class="br0">&#40;</span>TmpBlock<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; fclose<span class="br0">&#40;</span>FileHandle<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>This is a class that will load every one of the blocks and their locations from a text file (namely, blocks/x.blocks, where x is the level number). When the static function is called, it takes in a char array. As we&#8217;ve done before with Tim&#8217;s tutorials, it reads that file. That file contains a number (in level one&#8217;s case, 6), followed by a next-line/return character. That number is stored in the integer BlockCount. Then, the function loops through every one of the blocks in the file (with the for loop), and loads their respective X and Y coordinates. Inside the for loop, a TmpBlock (TeMPoraryBLOCK) is created and its X and Y coordinates (attributes set by CEntity, and inherited by the CBlock class, remember) are set as the values in the X and Y integers in the for loop. Then, the TmpBlock is inserted into CBlockControl&#8217;s static vector of CBlocks (CBlockControl::BlockList).</p>
<p>So, it seems that now we have everything needed to actually implement everything we&#8217;ve just written; to bring it all together and make a level. Well, first we have to accomodate for one slight change. There is no longer a CCamera. We don&#8217;t need one as the map can&#8217;t get bigger than the one level. So we have to change something in CArea. Remember the function CArea::OnRender(SDL_Surface* SurfDisplay, int CameraX, int CameraY)? Well since we don&#8217;t need a camera anymore, we don&#8217;t need that function anymore. But don&#8217;t toss it! Who knows, we might later need the function for any additions you decide to make. So let&#8217;s make a new function:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> CArea::<span class="me2">OnRender</span><span class="br0">&#40;</span>SDL_Surface* SurfDisplay<span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>
Add the prototype to the class definition (make sure it&#8217;s public), and write the function in CArea.cpp:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> CArea::<span class="me2">OnRender</span><span class="br0">&#40;</span>SDL_Surface* SurfDisplay<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; MapList<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="me1">OnRender</span><span class="br0">&#40;</span>SurfDisplay, <span class="nu0">0</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>We now have two functions with the same name, but they have different parameters, which is allowed. It does the same thing, except there&#8217;s one map to render so there&#8217;s no need to figure out which is the first map to render. Duh.</p>
<p>Finally, open up CApp. We&#8217;re gonna put this thing together. In CApp.h, add the following things:</p>
<div class="dean_ch" style="white-space: wrap;">
private:<br />
&nbsp; &nbsp; SDL_Surface* SurfBackground;<br />
&nbsp; &nbsp; CPlayer ActionJackson;<br />
&nbsp; &nbsp; <span class="kw4">int</span> Moves;<br />
public:<br />
&nbsp; &nbsp; <span class="kw4">void</span> OnKeyDown<span class="br0">&#40;</span>SDLKey, SDLMod, Uint16<span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>Remember, this isn&#8217;t the whole thing; this is just what you need to add in the appropriate places. I think you already have the new function, but make sure it&#8217;s there, in any case.</p>
<p>So then, in CApp.cpp&#8230; In the constructor, CApp::CApp(), add statements that define Moves as 0, and SurfBackground as NULL (like SurfDisplay). In CApp::OnInit(), we need to almost completely rewrite it:</p>
<div class="dean_ch" style="white-space: wrap;">
bool CApp::<span class="me2">OnInit</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>SDL_Init<span class="br0">&#40;</span>SDL_INIT_EVERYTHING<span class="br0">&#41;</span> &lt; <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>SurfDisplay = SDL_SetVideoMode<span class="br0">&#40;</span>WWIDTH, WHEIGHT, <span class="nu0">32</span>, SDL_HWSURFACE | SDL_DOUBLEBUF<span class="br0">&#41;</span><span class="br0">&#41;</span> == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span>SurfBackground = CSurface::<span class="me2">OnLoad</span><span class="br0">&#40;</span><span class="st0">&quot;gfx/background.png&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CArea::<span class="me2">AreaControl</span>.<span class="me1">OnLoad</span><span class="br0">&#40;</span><span class="st0">&quot;maps/1.area&quot;</span><span class="br0">&#41;</span> == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ActionJackson.<span class="me1">OnLoad</span><span class="br0">&#40;</span><span class="st0">&quot;gfx/actionjackson.png&quot;</span>, <span class="nu0">32</span>, <span class="nu0">32</span>, <span class="nu0">1</span>, <span class="kw2">false</span>, <span class="nu0">64</span>, <span class="nu0">64</span>, <span class="nu0">0</span><span class="br0">&#41;</span> == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; CEntity::<span class="me2">EntityList</span>.<span class="me1">push_back</span><span class="br0">&#40;</span>&amp;ActionJackson<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CBlockControl::<span class="me2">LoadBlocksFromFile</span><span class="br0">&#40;</span><span class="st0">&quot;blocks/1.blocks&quot;</span><span class="br0">&#41;</span> == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; CBlockControl::<span class="me2">BlockList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CBlock::<span class="me2">BlockList</span>.<span class="me1">push_back</span><span class="br0">&#40;</span>&amp;CBlockControl::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; CEntity::<span class="me2">EntityList</span>.<span class="me1">push_back</span><span class="br0">&#40;</span>&amp;CBlockControl::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; ActionJackson.<span class="me1">X</span> = <span class="nu0">352</span>;<br />
&nbsp; &nbsp; ActionJackson.<span class="me1">Y</span> = <span class="nu0">320</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>
Let&#8217;s talk about this. The first two if&#8217;s start SDL, like we know already. The third is just something I thought would look nice. I have this cool red graphic that I made, and I put it in gfx, and called it background.png. This statement uses our CSurface function OnLoad and puts it on SurfBackground. Next, an area is loaded. I&#8217;ll get to what&#8217;s in that area file in a second. The next statement loads the player. Remember, CPlayer inherits everything from CEntity, and since CEntity had an OnLoad function that loaded the entity from an image file, so does CPlayer. And thus, ActionJackon (which we declared in the class definition) has it. NOTE: MY PARAMETERS MAY BE DIFFERENT FROM YOURS, SO CHANGE THEM AS IS NECESSARY. THERE&#8217;S NO NEED FOR TRANSPARENCY, AT LEAST NOT YET, SO JUST REMEMBER THAT.</p>
<p>ActionJackson is pushed back in the static EntityList vector, and then CBlockControl loads all the blocks from a file. Remember, it&#8217;s static, so we can run it without having declared an object/instance of CBlockControl. Then, like I promised WAAAAAY back, CBlock&#8217;s static BlockList vector would get those blocks. And, like we need to do and like we did for ActionJackson, we need to push the blocks back in EntityList, too. Finally, we just need to set initial X and Y coordinates for ActionJackson, and that&#8217;s all for OnInit().</p>
<p>Go to OnRender(). Rewrite it as this:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> CApp::<span class="me2">OnRender</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; CSurface::<span class="me2">OnDraw</span><span class="br0">&#40;</span>SurfDisplay, SurfBackground, <span class="nu0">0</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; CArea::<span class="me2">AreaControl</span>.<span class="me1">OnRender</span><span class="br0">&#40;</span>SurfDisplay<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; CEntity::<span class="me2">EntityList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!CEntity::<span class="me2">EntityList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="kw1">continue</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; CEntity::<span class="me2">EntityList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;OnRender<span class="br0">&#40;</span>SurfDisplay<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; SDL_Flip<span class="br0">&#40;</span>SurfDisplay<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Since we loaded a background to SurfBackground, we have to draw SurfBackground on SurfDisplay. And this MUST be the first render statement because otherwise, the background will be drawn OVER the other things. Also, the new function we created for CArea is called, taking only the filename and no camera coordinates (since we no longer need a camera).</p>
<p>Finally, the meat of the game. Go to CApp::OnKeyDown(SDLKey sym, SDLMod mod, Uint16 unicode). Erase all that stuff involving camera movement, and rewrite the function as this:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> CApp::<span class="me2">OnKeyDown</span><span class="br0">&#40;</span>SDLKey sym, SDLMod mod, Uint16 unicode<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">switch</span><span class="br0">&#40;</span>sym<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> SDLK_UP:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ActionJackson.<span class="me1">CanPlayerMoveUp</span><span class="br0">&#40;</span><span class="br0">&#41;</span> == BLOCK<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; CBlock::<span class="me2">BlockList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;X == ActionJackson.<span class="me1">X</span> &amp;&amp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;Y == ActionJackson.<span class="me1">Y</span> &#8211; <span class="nu0">32</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;OnMove<span class="br0">&#40;</span><span class="nu0">0</span>, <span class="nu0">-32</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ActionJackson.<span class="me1">OnMove</span><span class="br0">&#40;</span><span class="nu0">0</span>, <span class="nu0">-32</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Moves++;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ActionJackson.<span class="me1">CanPlayerMoveUp</span><span class="br0">&#40;</span><span class="br0">&#41;</span> == YES<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ActionJackson.<span class="me1">OnMove</span><span class="br0">&#40;</span><span class="nu0">0</span>, <span class="nu0">-32</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Moves++;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> SDLK_DOWN:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ActionJackson.<span class="me1">CanPlayerMoveDown</span><span class="br0">&#40;</span><span class="br0">&#41;</span> == BLOCK<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; CBlock::<span class="me2">BlockList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;X == ActionJackson.<span class="me1">X</span> &amp;&amp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;Y == ActionJackson.<span class="me1">Y</span> + <span class="nu0">32</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;OnMove<span class="br0">&#40;</span><span class="nu0">0</span>, <span class="nu0">32</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ActionJackson.<span class="me1">OnMove</span><span class="br0">&#40;</span><span class="nu0">0</span>, <span class="nu0">32</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Moves++;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ActionJackson.<span class="me1">CanPlayerMoveDown</span><span class="br0">&#40;</span><span class="br0">&#41;</span> == YES<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ActionJackson.<span class="me1">OnMove</span><span class="br0">&#40;</span><span class="nu0">0</span>, <span class="nu0">32</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Moves++;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> SDLK_LEFT:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ActionJackson.<span class="me1">CanPlayerMoveLeft</span><span class="br0">&#40;</span><span class="br0">&#41;</span> == BLOCK<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; CBlock::<span class="me2">BlockList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;X == ActionJackson.<span class="me1">X</span> &#8211; <span class="nu0">32</span> &amp;&amp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;Y == ActionJackson.<span class="me1">Y</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;OnMove<span class="br0">&#40;</span><span class="nu0">-32</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ActionJackson.<span class="me1">OnMove</span><span class="br0">&#40;</span><span class="nu0">-32</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Moves++;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ActionJackson.<span class="me1">CanPlayerMoveLeft</span><span class="br0">&#40;</span><span class="br0">&#41;</span> == YES<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ActionJackson.<span class="me1">OnMove</span><span class="br0">&#40;</span><span class="nu0">-32</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Moves++;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> SDLK_RIGHT:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ActionJackson.<span class="me1">CanPlayerMoveRight</span><span class="br0">&#40;</span><span class="br0">&#41;</span> == BLOCK<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; CBlock::<span class="me2">BlockList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;X == ActionJackson.<span class="me1">X</span> + <span class="nu0">32</span> &amp;&amp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;Y == ActionJackson.<span class="me1">Y</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;OnMove<span class="br0">&#40;</span><span class="nu0">32</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ActionJackson.<span class="me1">OnMove</span><span class="br0">&#40;</span><span class="nu0">32</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Moves++;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ActionJackson.<span class="me1">CanPlayerMoveRight</span><span class="br0">&#40;</span><span class="br0">&#41;</span> == YES<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ActionJackson.<span class="me1">OnMove</span><span class="br0">&#40;</span><span class="nu0">32</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Moves++;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> SDLK_ESCAPE:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Running = <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">break</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">default</span>: <span class="kw2">break</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p>&nbsp;</p></div>
<p>WOW. Let&#8217;s go through that bunch of code. The same switch statement remains as before, but the inside is different. Let&#8217;s take just the case of SDLK_UP. If the UP key is pressed: First, the function checks if the player can move, and that is done by calling the CanPlayerMove&#8230;() function and checking its return value. If there is a block (i.e. if CanPlayerMove&#8230;() returns BLOCK), then a for loop is run. For every block in CBlock&#8217;s static BlockList vector, there&#8217;s an if statement that checks if that block is the block that is next to the player. Otherwise, this function could just move any random block up, and that would obviously not be good. So this just figures out which block is next to the player. Once that&#8217;s figured out, that block moves up, and the for loop continues. It&#8217;s not going to return to the same block again, so it just keeps running until it&#8217;s out of options. Then, ActionJackson moves up, sort of &#8220;following&#8221; the block. And the Move count increments up by one.</p>
<p>If ActionJackson.CanPlayerMove&#8230;() doesn&#8217;t return BLOCK, none of that happens. The next if statement checks if that function returned YES. In this case, ActionJackson very simply moves up, not disturbing anything else, and the Move count increments up by one. Finally, if CanPlayerMove&#8230;() returns NO, nothing happens, so when up is pressed and the player can&#8217;t move up, he DOESN&#8217;T.</p>
<p>This repeats for every arrow key. There we go! The game works! Now let&#8217;s just make a use for CBlock&#8217;s boolean attribute, OnHomeTile. Go to CApp::OnLoop(), and rewrite it as this:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> CApp::<span class="me2">OnLoop</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; CEntity::<span class="me2">EntityList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!CEntity::<span class="me2">EntityList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="kw1">continue</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; CEntity::<span class="me2">EntityList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;OnLoop<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; bool BlocksAreHome = <span class="kw2">true</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; CBlock::<span class="me2">BlockList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;CheckForHome<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>BlocksAreHome &amp;&amp; !CBlock::<span class="me2">BlockList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;OnHomeTile<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BlocksAreHome = <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span> <span class="kw1">continue</span>; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>BlocksAreHome<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Running = <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>After the existing first for loop, a new boolean value is created. By default, BlocksAreHome is set to true, but that changes immediately if it isn&#8217;t true. The next for loop runs through every block in CBlock&#8217;s BlockList vector. Each of the blocks the loop runs through calls its CheckForHome() function, and accordingly sets its OnHomeTile boolean to true/false. Then, the block in the for loop is checked to be on its home tile with the if statement. If it&#8217;s not on its home tile, BlocksAreHome is set to false. Otherwise, the for loop continues, leaving BlocksAreHome true. Finally, after the for loop, if BlocksAreHome is true, Running is set to false, and the game ends. This is just all I&#8217;ve written for the end of the level; feel free to add your own end-of-game stuff.</p>
<p>Now the game is perfect. All you need to do is make the area, map, blocks, and graphics files. Thankfully, they&#8217;re all packaged below. Also, in Define.h, set TILE_SIZE to 32, MAP_WIDTH to 20, and MAP_HEIGHT to 15.</p>
<p>The directory tree should be as follows (numbered by sublevel):<br />
1. Sokoban (directory)<br />
2. blocks (directory) gfx (directory), maps (directory), tilesets (directory).</p>
<p>In the blocks directory, put the files in the following .zip archive:<br />
<a href="http://www.mediafire.com/?msz2niyjnwu">MediaFire &#8211; blocks.zip</a></p>
<p>In the gfx directory, put the files in the following .zip archive:<br />
<a href="http://www.mediafire.com/?7dgzy0mezlm">MediaFire &#8211; gfx.zip</a></p>
<p>In the maps directory, put the files in the following .zip archive:<br />
<a href="http://www.mediafire.com/?3obxzxmmnxm">MediaFire &#8211; maps.zip</a></p>
<p>In the tilesets directory, put the files in the following .zip archive:<br />
<a href="http://www.mediafire.com/?mmkniwielhy">MediaFire &#8211; tilesets.zip</a></p>
<p>And, should you need to refer to it, here are the full source files (with a few commented-out changes; ignore those):</p>
<p><b>SDL Sokoban &#8211; Tutorial Files:</b><br />
<a href="http://www.mediafire.com/?5em139mmljm">MediaFire &#8211; Sokoban.zip</a><br/><br />
<b>Linux:</b> <a href="../tutorials/sokoban.tar.gz">Tar</a> (Thanks Gaten)</p>
<p><font size=1>COPYRIGHT:<br />
Copyright 2008 Arseniy Banayev</p>
<p>This may be not be reproduced under any circumstances except for personal, private use. It may not be placed on any web site or otherwise distributed publicly without advance written permission. Use of this guide on any other web site or as a part of any public display is strictly prohibited, and a violation of copyright. This guide is only to be used on SDLTutorials.com, and only by its host, Tim Jones. If found anywhere else, the proper web law enforcement authorities will be notified for violating copyright.</p>
<p>All trademarks and copyrights contained in this document are owned by their respective trademark and copyright holders.</p>
<p>If you have any questions, comments, or misinformation concerning this guide, please leave comments or, in the rarest case, email me at <a href="mailto:xboteb13@gmail.com">xboteb13@gmail.com</a>. Any electronic mail that I judge to be spam before opening the contents will be deleted automatically. Any malicious software attached to the electronic mail will not only be ignored and pointless, thanks to <a href="http://www.ubuntu.com">Ubuntu</a>&#8217;s security, but will be promptly reported to the appropriate law enforcement authorities and legal partners.</p>
<p>DISCLAIMER:<br />
I will not be held responsible for any damages, reversible or irreversible, to your operating system, personal files, applications, or the physical computer itself, brought upon as a result of compiling and executing the given code or opening the provided files in the above packages.</font></p>
]]></content:encoded>
			<wfw:commentRss>http://www.sdltutorials.com/sdl-sokoban/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>SDL SoundBank</title>
		<link>http://www.sdltutorials.com/sdl-soundbank/</link>
		<comments>http://www.sdltutorials.com/sdl-soundbank/#comments</comments>
		<pubDate>Fri, 11 Apr 2008 12:59:50 +0000</pubDate>
		<dc:creator>Tim Jones</dc:creator>
				<category><![CDATA[SDL Tutorials]]></category>
		<category><![CDATA[C++ tutorials]]></category>
		<category><![CDATA[game tutorials]]></category>

		<guid isPermaLink="false">http://www.sdltutorials.com/sdl-soundbank/</guid>
		<description><![CDATA[In this side tutorial we are going to be adding a soundbank that will load all of our sounds, and then we call play them via an ID whenever we want. This tutorial will only deal with sounds, not music, and mind you it&#8217;s a very basic tutorial that gets the job done. There is [...]]]></description>
			<content:encoded><![CDATA[<p>In this side tutorial we are going to be adding a soundbank that will load all of our sounds, and then we call play them via an ID whenever we want. This tutorial will only deal with sounds, not music, and mind you it&#8217;s a very basic tutorial that gets the job done. There is much that can be added to this class, for channels, groups and such, but we&#8217;re dealing with basics here. We&#8217;ll base this tutorial off of my <a href="http://www.sdltutorials.com/sdl-events/">SDL Events</a> tutorial. So use those project files if you need something to work off of.</p>
<p>The first thing you need to do is download SDL mixer from the <a href="http://www.libsdl.org">SDL website</a>. It&#8217;s also included in the SDL library I provide on my website. Be sure to put the include files in the same directory as your SDL include files, and your lib files in the same directory as your SDL lib files to make things easier.</p>
<p><span id="more-36"></span><br />
Start by opening your project, and going under the linker settings. Add SDL_mixer after SDLmain, something like:</p>
<p>mingw32<br />
SDLmain<br />
SDL_mixer<br />
SDL</p>
<p>If you don&#8217;t remember where to find all these settings, hope on over to the first tutorial <a href="http://www.sdltutorials.com/sdl-tutorial-basics/">SDL Tutorial Basics</a> to get a refresher on linking. If you have a .lib file, instead of a .a library file, use the browse button to find the library file that way.</p>
<p>Just a little side note here about sounds. SDL_mixer treats any sound in memory as a chunk. This chunk basically contains the frequency data. What&#8217;s nice about SDL_mixer is that it takes this data and sends it to the audio output, meaning it has taken care of all the hard work. So all that we have to do is load our data, from a WAV file for instance, and then send it to SDL_mixer to be played.</p>
<p>First, create two new files, CSoundBank.h and CSoundBank.cpp. Open up the header file first:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef _CSOUNDBANK_H_</span><br />
&nbsp; &nbsp; <span class="co2">#define _CSOUNDBANK_H_</span></p>
<p><span class="co2">#include &lt;SDL.h&gt;</span><br />
<span class="co2">#include &lt;SDL_mixer.h&gt;</span><br />
<span class="co2">#include &lt;vector&gt;</span></p>
<p><span class="kw2">class</span> CSoundBank <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> CSoundBank &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SoundControl;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; std::<span class="me2">vector</span>&lt;Mix_Chunk*&gt; &nbsp; &nbsp; SoundList;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; CSoundBank<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> OnLoad<span class="br0">&#40;</span><span class="kw4">char</span>* <span class="kw4">File</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnCleanup<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> Play<span class="br0">&#40;</span><span class="kw4">int</span> ID<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;</p>
<p><span class="co2">#endif</span><br />
&nbsp;</div>
<p>We have a static control object first, this lets us add sounds and play sounds from anywhere in our program. Think of this as your master control for adding/playing sounds. We then have our SoundList, this is a list of SDL mixer sounds. Now, a Mix_Chunk object contains the information needed to play a sound. What we will do later on is load a wav file into a Mix_Chunk object. Think of it as the sound equivalent to SDL_Surface. Then we have some basic functions for loading, cleanup up, and playing a sound. Simple enough.</p>
<p>Next, open up CSoundBank.cpp:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;CSoundBank.h&quot;</span></p>
<p>CSoundBank CSoundBank::<span class="me2">SoundControl</span>;</p>
<p>CSoundBank::<span class="me2">CSoundBank</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">int</span> CSoundBank::<span class="me2">OnLoad</span><span class="br0">&#40;</span><span class="kw4">char</span>* <span class="kw4">File</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; Mix_Chunk* TempSound = <span class="kw2">NULL</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span><span class="br0">&#40;</span>TempSound = Mix_LoadWAV<span class="br0">&#40;</span><span class="kw4">File</span><span class="br0">&#41;</span><span class="br0">&#41;</span> == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">-1</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; SoundList.<span class="me1">push_back</span><span class="br0">&#40;</span>TempSound<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span>SoundList.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span> &#8211; <span class="nu0">1</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CSoundBank::<span class="me2">OnCleanup</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>;i &lt; SoundList.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Mix_FreeChunk<span class="br0">&#40;</span>SoundList<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; SoundList.<span class="me1">clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CSoundBank::<span class="me2">Play</span><span class="br0">&#40;</span><span class="kw4">int</span> ID<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>ID &lt; <span class="nu0">0</span> || ID &gt;= SoundList.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">return</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>SoundList<span class="br0">&#91;</span>ID<span class="br0">&#93;</span> == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="kw1">return</span>;</p>
<p>&nbsp; &nbsp; Mix_PlayChannel<span class="br0">&#40;</span><span class="nu0">-1</span>, SoundList<span class="br0">&#91;</span>ID<span class="br0">&#93;</span>, <span class="nu0">0</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>This is also pretty straight forward. We have our static control, our empty constructor, and then our loading function. We basically take the filename of the sound to be loaded, and try to load it via Mix_LoadWAV into the Mix_Chunk object. Notice I am making a temporary object first, and then throwing it into the list. At the very end of the function, I return the ID of the last inserted sound. So, for instance, say I loaded SoundA and SoundB:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">int</span> SoundA = CSoundBank::<span class="me2">SoundControl</span>.<span class="me1">OnLoad</span><span class="br0">&#40;</span><span class="st0">&quot;sounda.wav&quot;</span><span class="br0">&#41;</span>;<br />
<span class="kw4">int</span> SoundB = CSoundBank::<span class="me2">SoundControl</span>.<span class="me1">OnLoad</span><span class="br0">&#40;</span><span class="st0">&quot;soundb.wav&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>The ID for playing this sounds later would be returned by the OnLoad function.</p>
<p>Okay, next we have our cleanup function which goes through the list and frees the sound chunks. Simple enough, just like SDL_FreeSurface.</p>
<p>Lastly, we have our Play function that actually plays the sound. We pass an ID (the one we got returned from the Load function) first. We do a little boundary check to make sure the ID is valid, and then actually try to play the sound. The Mix_PlayChannel takes three arguments:</p>
<p>The first specifies which channel to play the sound on, -1 means use the first available.<br />
The second specifies which sound chunk to play.<br />
The last specifies how many times to play this sound (loop). -1 would be infinite.</p>
<p>We haven&#8217;t done much with channels in this class, but the class is easily changeable to add that functionality. Basically, a channel allows you to set certain settings to certain sounds. For instance, you can set volume or panning on the first channel, so any sounds played on that channel would be affected.</p>
<p>So lets do a little test now. Open up CApp.h and add the header file, and add some variables and functions to the class:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;CSoundBank.h&quot;</span></p>
<p><span class="co1">//&#8230;</span></p>
<p><span class="kw2">class</span> CApp <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> SoundA;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> SoundB;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">//&#8230; other code</span></p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnKeyDown<span class="br0">&#40;</span>SDLKey sym, SDLMod mod, Uint16 unicode<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;<br />
&nbsp;</div>
<p>Now, open up CApp_Init.cpp so we can load some sounds:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">if</span><span class="br0">&#40;</span><span class="br0">&#40;</span>SoundA = CSoundBank::<span class="me2">SoundControl</span>.<span class="me1">OnLoad</span><span class="br0">&#40;</span><span class="st0">&quot;sounda.wav&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> == <span class="nu0">-1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw1">if</span><span class="br0">&#40;</span><span class="br0">&#40;</span>SoundB = CSoundBank::<span class="me2">SoundControl</span>.<span class="me1">OnLoad</span><span class="br0">&#40;</span><span class="st0">&quot;soundb.wav&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> == <span class="nu0">-1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Now, to make sounds when we press a key, open up CApp_OnEvent.cpp and add the function:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> CApp::<span class="me2">OnKeyDown</span><span class="br0">&#40;</span>SDLKey sym, SDLMod mod, Uint16 unicode<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>sym == SDLK_1<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CSoundBank::<span class="me2">SoundControl</span>.<span class="me1">Play</span><span class="br0">&#40;</span>SoundA<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>sym == SDLK_2<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; CSoundBank::<span class="me2">SoundControl</span>.<span class="me1">Play</span><span class="br0">&#40;</span>SoundB<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>We aren&#8217;t done yet, we have to do a little bit to start SDL_mixer. This is just like starting up SDL, but instead we need to start up SDL_mixer to access sounds. Open up CApp_Init.cpp and add the following somewhere after SDL_Init:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">if</span><span class="br0">&#40;</span>Mix_OpenAudio<span class="br0">&#40;</span><span class="nu0">44100</span>, MIX_DEFAULT_FORMAT, <span class="nu0">2</span>, <span class="nu0">4096</span><span class="br0">&#41;</span> &lt; <span class="nu0">0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Mix_OpenAudio basically Inits SDL_mixer. This function takes 4 arguments. The first is used to specify the frequency, 44100 is usually a good number. But depending on your wav files, you may have to change this. Another common number is 22050. I won&#8217;t get into detail about frequencies and such, just leave it alone unless you really need to change it. The next is the format, again, it&#8217;s best to leave it unless you know much about audio (it&#8217;s basically the size of the samples used, 8bit or 16bit). The next is the number of channels, 1 = mono, 2 = stereo. Note, these channels are different than the other channels I was talking about before. The other channels are &#8220;mixing channels,&#8221; basically streams that I can push audio through. These channels though, are the number of audio outputs. Think of it like the number of speakers that you might have. 2 speakers, 2 channels. The last number is used to set the size of the samples (in bytes). Again, unless you really know what you are doing, it&#8217;s best to leave these numbers alone.</p>
<p>To tidy things up, we need to make sure we stop the SDL_mixer service when we are done, as well as freeing any sounds we may have loaded. So open up CApp_OnCleanup.cpp and add the following:</p>
<div class="dean_ch" style="white-space: wrap;">
CSoundBank::<span class="me2">SoundControl</span>.<span class="me1">OnCleanup</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>Mix_CloseAudio<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>And we are done! Try compiling, and pressing the 1 and 2 keys to here some sounds. If you need some WAV files, download the project files below to grab them.</p>
<p><b>SDL SoundBank &#8211; Tutorial Files:</b><br />
<b>Win32:</b> <a href="../tutorials/sdl-soundbank.zip">Zip</a>, <a href="../tutorials/sdl-soundbank.rar">Rar</a><br />
<b>Linux:</b> <a href="../tutorials/sdl-soundbank.tar.gz">Tar</a> (Thanks Gaten)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sdltutorials.com/sdl-soundbank/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>SDL Maps</title>
		<link>http://www.sdltutorials.com/sdl-maps/</link>
		<comments>http://www.sdltutorials.com/sdl-maps/#comments</comments>
		<pubDate>Sat, 15 Mar 2008 22:35:52 +0000</pubDate>
		<dc:creator>Tim Jones</dc:creator>
				<category><![CDATA[SDL Tutorials]]></category>
		<category><![CDATA[C++ tutorials]]></category>
		<category><![CDATA[game tutorials]]></category>

		<guid isPermaLink="false">http://www.sdltutorials.com/sdl-maps/</guid>
		<description><![CDATA[As I stated in the last lesson, we&#8217;re going to be looking at making a Map class that will be tile based. In addition to the maps, we&#8217;ll be creating Areas that enhouse many Maps. While we could create one giant map, it&#8217;s far easier to manage many smaller maps, and also opens the possibility [...]]]></description>
			<content:encoded><![CDATA[<p>As I stated in the last lesson, we&#8217;re going to be looking at making a Map class that will be tile based. In addition to the maps, we&#8217;ll be creating Areas that enhouse many Maps. While we could create one giant map, it&#8217;s far easier to manage many smaller maps, and also opens the possibility of tiling maps as well. By the way, head on over to the <a href="http://www.sdltutorials.com/sdl-image/">SDL Image tutorial</a> if you haven&#8217;t already done so, we will be making the switch over to SDL Image and stop using SDL_LoadBMP. No more chatter, lets get started.</p>
<p><span id="more-35"></span></p>
<p><br/></p>
<div style="padding: 5px; border: 1px #990033 solid; background-color: ##FFE1E1;">
<b>Known Bug:</b> The camera settings for this tutorial are backwards, and are reversed in the SDL Collision tutorial (and following). Changes are not put in place yet, to get the fixes view the SDL Collision tutorial.
</div>
<p><br/></p>
<p>We&#8217;re going to need several files in the beginning, Define.h, CArea.h, CArea.cpp, CMap.h, CMap.cpp, CTile.h, and CTile.cpp. So create these blank files. What we are going to do is have one Area object, this Area object will have many children Map objects in a vector (like the Entities in a vector). Within each of these Map objects, they will have a vector of each individual tile. So basically, we have a bunch of tiles that make up a map, and a bunch of maps make up an area.</p>
<p><center><img src="../tutorials/7-area.png" alt=""/></center></p>
<p>Lets start by opening up Define.h. This file is going to hold some constant values, as defines, that will define things like map width and height, screen width and height, and tile size. These are going to be some values that we will be using throughout making our Maps and such. Add the following below to define.h.</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef _DEFINE_H_</span><br />
&nbsp; &nbsp; <span class="co2">#define _DEFINE_H_</span></p>
<p><span class="co2">#define MAP_WIDTH&nbsp; &nbsp;40</span><br />
<span class="co2">#define MAP_HEIGHT&nbsp; 40</span></p>
<p><span class="co2">#define TILE_SIZE&nbsp; &nbsp;16</span></p>
<p><span class="co2">#define WWIDTH&nbsp; &nbsp; &nbsp; 640</span><br />
<span class="co2">#define&nbsp;WHEIGHT&nbsp;&nbsp; &nbsp; 480</span></p>
<p><span class="co2">#endif</span><br />
&nbsp;</div>
<p>We&#8217;ll get back to what these values mean later, but WWIDTH and WHEIGHT are the values set in SDL_SetVideoMode. So open up CApp_Init and change that function call to the following:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">if</span><span class="br0">&#40;</span><span class="br0">&#40;</span>Surf_Display = SDL_SetVideoMode<span class="br0">&#40;</span>WWIDTH, WHEIGHT, <span class="nu0">32</span>, SDL_HWSURFACE | SDL_DOUBLEBUF<span class="br0">&#41;</span><span class="br0">&#41;</span> == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Simple enough. Next, open up CTile.h. This class is going to define a single tile on a map. In gaming terms, a tile is basically a single square graphic that we draw to the screen. Remember the animation tutorial, each frame of Yoshi could be thought of as a tile. So when I say we have a map made up of many tiles, we are taking these tiles and repeating them in a grid sequence.</p>
<p>And since we have a single graphic containg all of our tiles, we only have to load one graphic, and not several for each tile. Each tile then needs some properties. The most obvious is which graphical tile to use. Take a look at an example tileset below:</p>
<p><center><img src="../tutorials/7-tileset.png" alt=""/></center></p>
<p>You&#8217;ll notice that the very top left has an ID of 0, and going to the left it increments in 1s.  This is called the Tile ID. By using the ID, and the size of each tile (TILE_SIZE), we can know which tile to draw to the screen. The next important thing is TypeID. This determines what type of tile it is. Some examples might be, invisible (don&#8217;t draw a tile), block (like a wall), or ground (player can walk on it). You can define whatever TypeIDs you want, but these are the most basic (other examples might be water, fire, ice, etc&#8230;). That&#8217;s basically it, this Tile class only has two members (for now, later on it will contain information for animated tiles). So lets push this class together inside of CTile.h:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef _CTILE_H_</span><br />
&nbsp; &nbsp; <span class="co2">#define _CTILE_H_</span></p>
<p><span class="co2">#include &quot;Define.h&quot;</span></p>
<p><span class="kw2">enum</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; TILE_TYPE_NONE = <span class="nu0">0</span>,</p>
<p>&nbsp; &nbsp; TILE_TYPE_NORMAL,<br />
&nbsp; &nbsp; TILE_TYPE_BLOCK<br />
<span class="br0">&#125;</span>;</p>
<p><span class="kw2">class</span> CTile <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> &nbsp; &nbsp; TileID;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> &nbsp; &nbsp; <span class="kw2">TypeID</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; CTile<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;</p>
<p><span class="co2">#endif</span></div>
<p>Notice the enum used. This lets us assign or check the TypeID, and know what it is at the same time. So if I did TypeID == TILE_TYPE_BLOCK, I would be able to notice in my code that I am checking for a block type of tile. TypeID == 2 isn&#8217;t as easy to interpret. If you never used enums, think of them like const variables. The value never changes. Also, the starting value defines the rest, notice I have = 0 on TILE_TYPE_NONE. From there the rest of the variables would automatically be assigned values in increments of 1.</p>
<p>Now, lets open up CTile.cpp and finish the code:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;CTile.h&quot;</span></p>
<p>CTile::<span class="me2">CTile</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; TileID = <span class="nu0">0</span>;<br />
&nbsp; &nbsp; <span class="kw2">TypeID</span> = TILE_TYPE_NONE;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Pretty straight forward. Next, lets look at making some maps. The first thing we need to consider is that our maps will be text files. So we need to come up with a file format, that way we can easily edit our maps outside of our code. And possibly later you could create a map editor.</p>
<p>Each map is going to have a width and height, defining the number of tiles. So a map of 10&#215;10, would have 100 tiles in it. We are going to make all of our maps the same width and height, so we don&#8217;t have to define that within the map files (MAP_WIDTH and MAP_HEIGHT). The part that we do need to add though is the TileID and TypeID for each individual tile. We are going to use the file format that I came up with, as it is relatively simple. Take a look at the 5&#215;5 map example below:</p>
<p>0:0 0:0 0:0 0:0 0:0<br />
1:0 1:0 1:0 0:0 0:0<br />
1:0 1:0 1:0 0:0 0:0<br />
1:0 1:0 1:0 0:0 0:0<br />
1:0 1:0 1:0 0:0 0:0</p>
<p>Each tile within the file would consist of 0:0, effectively being the TileID:TypeID. A space would be the deliminator between the tiles. A concept rendering if this map may look like this:</p>
<p><center><img src="../tutorials/7-map.png" alt=""/></center></p>
<p>For this tutorial we will be using 40&#215;40 maps, since that is a pretty decent size. And instead of printing an example out for you to copy, click on this link here:</p>
<p><a href="../tutorials/1.map">Example Map</a></p>
<p>First create a folder in the same directory as your exe called maps. This folder is where all your maps will be. Save that map as 1.map. Also, make another folder called tilesets in the same directory as your exe, and save the tileset above as 1.png.</p>
<p>Now that we have a file format for our maps, lets start designing the class that will render this thing. Open up CMap.h:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef _CMAP_H_</span><br />
&nbsp; &nbsp; <span class="co2">#define _CMAP_H_</span></p>
<p><span class="co2">#include &lt;SDL.h&gt;</span><br />
<span class="co2">#include &lt;vector&gt;</span></p>
<p><span class="co2">#include &quot;CTile.h&quot;</span><br />
<span class="co2">#include &quot;CSurface.h&quot;</span></p>
<p><span class="kw2">class</span> CMap <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_Surface* Surf_Tileset;</p>
<p>&nbsp; &nbsp; <span class="kw2">private</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; std::<span class="me2">vector</span>&lt;CTile&gt; TileList;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; CMap<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">bool</span> OnLoad<span class="br0">&#40;</span><span class="kw4">char</span>* <span class="kw4">File</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnRender<span class="br0">&#40;</span>SDL_Surface* Surf_Display, <span class="kw4">int</span> MapX, <span class="kw4">int</span> MapY<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;</p>
<p><span class="co2">#endif</span><br />
&nbsp;</div>
<p>A few of the basic things are here, OnLoad and OnRender. OnLoad does what you expect, loads a map from a file, and populates the TileList. The OnRender also does what you expect, properly puts each tile on the screen and draws them using the Surf_Tileset. Lets define what these functions do, now open up CMap.cpp:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;CMap.h&quot;</span></p>
<p>CMap::<span class="me2">CMap</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; Surf_Tileset = <span class="kw2">NULL</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">bool</span> CMap::<span class="me2">OnLoad</span><span class="br0">&#40;</span><span class="kw4">char</span>* <span class="kw4">File</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; TileList.<span class="me1">clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw4">FILE</span>* FileHandle = <span class="kw3">fopen</span><span class="br0">&#40;</span><span class="kw4">File</span>, <span class="st0">&quot;r&quot;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>FileHandle == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> Y = <span class="nu0">0</span>;Y &lt; MAP_HEIGHT;Y++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> X = <span class="nu0">0</span>;X &lt; MAP_WIDTH;X++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CTile tempTile;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">fscanf</span><span class="br0">&#40;</span>FileHandle, <span class="st0">&quot;%d:%d &quot;</span>, &amp;tempTile.<span class="me1">TileID</span>, &amp;tempTile.<span class="kw2">TypeID</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TileList.<span class="me1">push_back</span><span class="br0">&#40;</span>tempTile<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">fscanf</span><span class="br0">&#40;</span>FileHandle, <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw3">fclose</span><span class="br0">&#40;</span>FileHandle<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CMap::<span class="me2">OnRender</span><span class="br0">&#40;</span>SDL_Surface* Surf_Display, <span class="kw4">int</span> MapX, <span class="kw4">int</span> MapY<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>Surf_Tileset == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="kw1">return</span>;</p>
<p>&nbsp; &nbsp; <span class="kw4">int</span> TilesetWidth &nbsp;= Surf_Tileset-&gt;w / TILE_SIZE;<br />
&nbsp; &nbsp; <span class="kw4">int</span> TilesetHeight = Surf_Tileset-&gt;h / TILE_SIZE;</p>
<p>&nbsp; &nbsp; <span class="kw4">int</span> ID = <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> Y = <span class="nu0">0</span>;Y &lt; MAP_HEIGHT;Y++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> X = <span class="nu0">0</span>;X &lt; MAP_WIDTH;X++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>TileList<span class="br0">&#91;</span>ID<span class="br0">&#93;</span>.<span class="kw2">TypeID</span> == TILE_TYPE_NONE<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ID++;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">continue</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> tX = MapX + <span class="br0">&#40;</span>X * TILE_SIZE<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> tY = MapY + <span class="br0">&#40;</span>Y * TILE_SIZE<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> TilesetX = <span class="br0">&#40;</span>TileList<span class="br0">&#91;</span>ID<span class="br0">&#93;</span>.<span class="me1">TileID</span> % TilesetWidth<span class="br0">&#41;</span> * TILE_SIZE;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> TilesetY = <span class="br0">&#40;</span>TileList<span class="br0">&#91;</span>ID<span class="br0">&#93;</span>.<span class="me1">TileID</span> / TilesetWidth<span class="br0">&#41;</span> * TILE_SIZE;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CSurface::<span class="me2">OnDraw</span><span class="br0">&#40;</span>Surf_Display, Surf_Tileset, tX, tY, TilesetX, TilesetY, TILE_SIZE, TILE_SIZE<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ID++;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p><br/></p>
<div style="padding: 5px; border: 1px #990033 solid; background-color: ##FFE1E1;">
<b>Bug Fix:</b> There was a bug in the continue within the loop, we should be incrementing the ID before continuing. Thanks Zakalwe for helping find this bug!<br />
<br/><br />
<b>Bug Fix:</b> We should been dividing by TilesetWidth for TilesetY, otherwise it will not correctly grab the correct Y coordinate unless the Tileset is square. Thanks Anime for helping find this bug!</div>
<p><br/></p>
<p>Lets start at the top. The constructor sets the Tileset to NULL, obviously. Next we have the OnLoad function. First, we are clearing out any old tiles, that way if we load twice, it won&#8217;t have double the amount of tiles, effectively loading a new map. We then open up a FileHandle, and try to open the requested map file. Now, we go through the map file and grab each tile. This is accomplished by using the two loops. The outer loop is the Y axis loop, going from the top row to the bottom row of the map file. The inner loop is the X axis loop, going from the left most tile, to the right most tile. Pay attention to how this loop works, because it is also used below in the OnRender function. It basically goes from the top left tile, to the bottom right tile, 1 tile at a time. Inside of those loops we create a temporary tile, and load the file information into it. We then push that into our TileList, effectively saving the tile. We close the filehandle, and we are done.</p>
<p>Next, we have the function to render a map. Notice the MapX and MapY arguments. These tell use where to render this map on the screen. This is useful later on for moving maps around. First in the function we check for a valid tileset, because we are going to access this tileset directly and don&#8217;t want to cause a crash. We then grab the TilesetWidth and TilesetHeight in Tiles. This is important, because we need to know how many tiles a tileset contains, not its actual width and height. That way we can match up a TileID to a tileset. So, a Tileset with a Width and Height, in tiles, of 2&#215;2, would have 4 tiles on it, but in reality it would be 32&#215;32 pixels. So, a TileID of 0 would match the first tile, a TileID of 1 would be the next, and so on. TileIDs repeat on the next row, from left to right.</p>
<p>Okay, next we have that same loop again, going through each tile (Please note that these X and Y coordinates here in the loop are also in number of tiles, they aren&#8217;t actual pixels). This time, however, we have an ID variable. This ID is incremented by one each loop, and will allow us to grab each tile in the map. So, first we check to see if this Tile should even be drawn, by checking the TypeID. If it is TILE_TYPE_NONE, we skip over it with continue. After that we figure out where to draw this tile on the screen. This is done by taking the MapX and MapY (effectively offset coordinates, because they offset a map from 0, 0 to somewhere, which makes it seem like a map is moving), and taking the X and Y coordinates in the loop. We have to convert these X and Y coordinates back to pixel coordinates, which is done by multiplying it by the size of a tile.</p>
<p>After that, we do something with the Tileset. What we are doing is calculating where on the Tileset to grab the appropriate tile. This is by grabing the TileID of the tile first, and then converting that to a Tile coordinate. A little bit of explanation here. We have our 2&#215;2 tileset, and a TileID of 1. Figuring out X, we would get 1 % 2, which would be 1 still. We when multiply that by the TILE_SIZE, and get 16. That is the correct X coordinate for the Tile. Same with the Y, we put 1 / 2, which is 0.5. Since this an integer operation, the .5 is automatically dropped. Thus we are left with 0. Which is also the correct row. Now, say we had a TileID of 2. 2 % 2 = 0, and 2 / 2 = 1. See how the X repeats in a pattern? 0, 1, 0, 1&#8230; And notice how Y increases every time it goes past the Tileset Width? 0, 0, 1, 1. I hope this is clear, as it is somewhat hard to explain.</p>
<p>Next, we actually draw the tile to the screen using the coordinates we just calculated, and then increase the ID to go to the next tile. A little side note here, we could, for the sake of speed, create an OnRender_Cache function that would perform this same operation, but would draw to a Surface defined in the CMap class. Something like SDL_Surface* Surf_Map. Then, the OnRender function would render the Surf_Map only, and not perform any operations. But also take note that that method does not necessarely work later on when we want to animate tiles.</p>
<p>Okay, cool! I know that is quite a bit to take in at once, but don&#8217;t fret! It&#8217;s really not too bad once you get the hang of it. I want to say that right now we could create Map objects and render maps just fine. This would be ideal for games like Mario and Megaman, as they are just one big map. But for games like Zelda and Metroid, it won&#8217;t work too well. That is where Areas come in. Just like maps having file formats, each area will have its own file and file format. Each area is going to have a tileset to load, the size of the area, and the maps that are to be loaded in each area. Here is the area we are going to be using below:</p>
<p>./tilesets/1.png<br />
3<br />
./maps/1.map ./maps/1.map ./maps/1.map<br />
./maps/1.map ./maps/1.map ./maps/1.map<br />
./maps/1.map ./maps/1.map ./maps/1.map </p>
<p>Save this into a file called 1.area, and save it in your maps directory. Just like maps, this area will tile maps. I won&#8217;t get into detail because I think you all have the point by now.</p>
<p>Open up CArea.h and lets begin:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef _CAREA_H_</span><br />
&nbsp; &nbsp; <span class="co2">#define _CAREA_H_</span></p>
<p><span class="co2">#include &quot;CMap.h&quot;</span></p>
<p><span class="kw2">class</span> CArea <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> CArea &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;AreaControl;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; std::<span class="me2">vector</span>&lt;CMap&gt; &nbsp; &nbsp; &nbsp; MapList;</p>
<p>&nbsp; &nbsp; <span class="kw2">private</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AreaSize;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; SDL_Surface*&nbsp; &nbsp; &nbsp; &nbsp; Surf_Tileset;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; CArea<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">bool</span> &nbsp; &nbsp;OnLoad<span class="br0">&#40;</span><span class="kw4">char</span>* <span class="kw4">File</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> &nbsp; &nbsp;OnRender<span class="br0">&#40;</span>SDL_Surface* Surf_Display, <span class="kw4">int</span> CameraX, <span class="kw4">int</span> CameraY<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> &nbsp; &nbsp;OnCleanup<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;</p>
<p><span class="co2">#endif</span><br />
&nbsp;</div>
<p>This class is going to similar to the Map class in some ways, but different in others. Similarly, we have MapList that will hold our maps, just like the Map class had a list of tiles. Also, as have a Load function and Render function. Now the differences, we have a static AreaControl, much like Entities have a static control. This will allow us to manipulate an Area from any class by using this object. Next, we have the AreaSize which is the number of maps. We are going to assume that areas will always be square, so an AreaSize of 3, would be a 3&#215;3 area. If you wanted to, and I don&#8217;t think it&#8217;s necessary, you would have AreaWidth and AreaHeight. Next, we have a surface for the Tileset. You probably noticed that within the CMap class we never actually loaded a tileset. That&#8217;s because the Area is going to do it for us, and then pass that pointer to the CMap class. That way each map doesn&#8217;t load a tileset for itself, but effectively all maps share the same tileset. Again, if you wanted each Map to have its own tileset you can easily modify the class to do so.</p>
<p>Okay, now open up the CArea.cpp class:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;CArea.h&quot;</span></p>
<p>CArea CArea::<span class="me2">AreaControl</span>;</p>
<p>CArea::<span class="me2">CArea</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; AreaSize = <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">bool</span> CArea::<span class="me2">OnLoad</span><span class="br0">&#40;</span><span class="kw4">char</span>* <span class="kw4">File</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; MapList.<span class="me1">clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw4">FILE</span>* FileHandle = <span class="kw3">fopen</span><span class="br0">&#40;</span><span class="kw4">File</span>, <span class="st0">&quot;r&quot;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>FileHandle == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw4">char</span> TilesetFile<span class="br0">&#91;</span><span class="nu0">255</span><span class="br0">&#93;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw3">fscanf</span><span class="br0">&#40;</span>FileHandle, <span class="st0">&quot;%s<span class="es0">\n</span>&quot;</span>, TilesetFile<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span><span class="br0">&#40;</span>Surf_Tileset = CSurface::<span class="me2">OnLoad</span><span class="br0">&#40;</span>TilesetFile<span class="br0">&#41;</span><span class="br0">&#41;</span> == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">fclose</span><span class="br0">&#40;</span>FileHandle<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw3">fscanf</span><span class="br0">&#40;</span>FileHandle, <span class="st0">&quot;%d<span class="es0">\n</span>&quot;</span>, &amp;AreaSize<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> X = <span class="nu0">0</span>;X &lt; AreaSize;X++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> Y = <span class="nu0">0</span>;Y &lt; AreaSize;Y++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">char</span> MapFile<span class="br0">&#91;</span><span class="nu0">255</span><span class="br0">&#93;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">fscanf</span><span class="br0">&#40;</span>FileHandle, <span class="st0">&quot;%s &quot;</span>, MapFile<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CMap tempMap;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>tempMap.<span class="me1">OnLoad</span><span class="br0">&#40;</span>MapFile<span class="br0">&#41;</span> == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">fclose</span><span class="br0">&#40;</span>FileHandle<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tempMap.<span class="me1">Surf_Tileset</span> = Surf_Tileset;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MapList.<span class="me1">push_back</span><span class="br0">&#40;</span>tempMap<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">fscanf</span><span class="br0">&#40;</span>FileHandle, <span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw3">fclose</span><span class="br0">&#40;</span>FileHandle<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CArea::<span class="me2">OnRender</span><span class="br0">&#40;</span>SDL_Surface* Surf_Display, <span class="kw4">int</span> CameraX, <span class="kw4">int</span> CameraY<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">int</span> MapWidth &nbsp;= MAP_WIDTH * TILE_SIZE;<br />
&nbsp; &nbsp; <span class="kw4">int</span> MapHeight = MAP_HEIGHT * TILE_SIZE;</p>
<p>&nbsp; &nbsp; <span class="kw4">int</span> FirstID = -CameraX / MapWidth;<br />
&nbsp; &nbsp; &nbsp; &nbsp; FirstID = FirstID + <span class="br0">&#40;</span><span class="br0">&#40;</span>-CameraY / MapHeight<span class="br0">&#41;</span> * AreaSize<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>;i &lt; <span class="nu0">4</span>;i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> ID = FirstID + <span class="br0">&#40;</span><span class="br0">&#40;</span>i / <span class="nu0">2</span><span class="br0">&#41;</span> * AreaSize<span class="br0">&#41;</span> + <span class="br0">&#40;</span>i % <span class="nu0">2</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>ID &lt; <span class="nu0">0</span> || ID &gt;= MapList.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">continue</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> X = <span class="br0">&#40;</span><span class="br0">&#40;</span>ID % AreaSize<span class="br0">&#41;</span> * MapWidth<span class="br0">&#41;</span> + CameraX;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> Y = <span class="br0">&#40;</span><span class="br0">&#40;</span>ID / AreaSize<span class="br0">&#41;</span> * MapHeight<span class="br0">&#41;</span> + CameraY;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; MapList<span class="br0">&#91;</span>ID<span class="br0">&#93;</span>.<span class="me1">OnRender</span><span class="br0">&#40;</span>Surf_Display, X, Y<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CArea::<span class="me2">OnCleanup</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>Surf_Tileset<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_FreeSurface<span class="br0">&#40;</span>Surf_Tileset<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; MapList.<span class="me1">clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Quickly, going from the top, we declare the static object, and then set the AreaSize to 0. Then we have our Load function. It works just like the Load function within CMap, except there are a few differences. We have to load tileset first. We try to load this tileset into the surface, and if it fails return false. We then load the size of the Area. Okay, after that we have two loops, just like maps, that will go through and grab each map filename. It will then create a map object, load the map, set the tileset to be used, and then push it into the list. Pretty simply and straight forward.</p>
<p>Next, we have the Render function. We calculate the actual Map width and height, in pixels, first. This will let us find the first map to render. Some explanation first of what I am trying to do. Since an area can be of any size, like 100&#215;100 maps, we don&#8217;t want to go through all the trouble and render every single map. We only want to render the maps that are visible in the screen area. For our size of a screen, 640&#215;480, only a possible 4 maps can be visible at one time (like standing at the corner of 4 maps). So what we have to do is calculate the first Map ID to grab. This is going to the first map to render. From the first ID, we know the next 3 maps to render. The one to the right of the first map, the one at the bottom of the first map, and the one at the bottom right of the first map. How is that accomplished? Look at the image below:</p>
<p><center><img src="../tutorials/7-area-camera.png" alt=""/></center></p>
<p>We have a guy, the circle, in the very center of the screen, represented by the red square. The other squares are each Map, and we have a Camera position of -700, -700. Why negative? Think about it, the screen itself never really moves, everything else does. So, for something to move up, it must increase its Y in the negative direction. Same with the X coordinate. So, to get to the 4th map, we have to move the area in the negative direction. Now, notice the grayed out maps, these are maps not visible within the players view, so they shouldn&#8217;t be rendered. To figure out the First ID, which is 4 in this case, we need to use the specified Camera coordinates. We translate those Camera coordinates into Map coordinates. So, taking -(-700) / 640 (which is 40 * 16, remember the MapWidth calculation done above) we get 1 (dropping the decimal because its an integer operation). This is the X coordinate in Maps, but we aren&#8217;t done. We then calculate the Y coordinate in Maps the same way -(-700) / 640, but we multiply that by the AreaSize. That&#8217;s because we are grabbing the ID. So, it would become 1 * 3, which is 3, and adding that to the first calculation of 1, we get 4. And what do you know, the First ID on the map!</p>
<p>Okay, so we go through each of the four maps now. Since I did a regular loop of i < 4, we need to figure out how to add that to the First ID, to actually figure out each of the four Map IDs. This is done by taking the First ID as an offset first. We then take i, our position in the loop, divide by two and multiply by the area size. What does this do? Much like the Map class, it creates a pattern, 0, 0, 1, 1. Same with the last operation i % 2, it creates a pattern of  0, 1, 0, 1. This then gives us the correct pattern of, 4, 5, 7, 8. Which are the correct map to render.</p>
<p>We do a little check to make sure the ID is good, since the ID may not exist. And now the last calculation (yes, I know, a lot of complex calculations). It works just like the way we calculated which tile to grab on the tileset. It's turning an ID into actual pixel coordinates, and then offsetting those coordinates by the camera (making it seem like it moved). We then finally render the map, passing the coordinates of where to draw it.</p>
<p>Lastly, we have our cleanup function that frees the surface and clears the maps.</p>
<p>What a load! I hope all of the various calculations don't get you confused. There are really only two basic things we are trying to do, turn pixel coordinates into grid based coordinates. Such as with tiles, and with the maps. The other thing was turning those grid based coordinates back and forth into IDs. </p>
<p>Okay, we are not quite done yet, still a little bit to do (now you see why this tutorial took so long to complete!). You may have noticed that I called the arguments on the Render function on the CArea class CameraX and CameraY. We are going to need to make a camera class that defines the viewing area. This is what we are going to manipulate to move around on a map!</p>
<p>So create two new files, CCamera.cpp and CCamera.h. Open up the header file first:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef _CCAMERA_H_</span><br />
&nbsp; &nbsp; <span class="co2">#define _CCAMERA_H_</span></p>
<p><span class="co2">#include &lt;SDL.h&gt;</span></p>
<p><span class="co2">#include &quot;Define.h&quot;</span></p>
<p><span class="kw2">enum</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; TARGET_MODE_NORMAL = <span class="nu0">0</span>,<br />
&nbsp; &nbsp; TARGET_MODE_CENTER<br />
<span class="br0">&#125;</span>;</p>
<p><span class="kw2">class</span> CCamera <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> CCamera CameraControl;</p>
<p>&nbsp; &nbsp; <span class="kw2">private</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> X;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> Y;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span>* TargetX;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span>* TargetY;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> TargetMode;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; CCamera<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> OnMove<span class="br0">&#40;</span><span class="kw4">int</span> MoveX, <span class="kw4">int</span> MoveY<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> GetX<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> GetY<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> SetPos<span class="br0">&#40;</span><span class="kw4">int</span> X, <span class="kw4">int</span> Y<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">void</span> SetTarget<span class="br0">&#40;</span><span class="kw4">int</span>* X, <span class="kw4">int</span>* Y<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;</p>
<p><span class="co2">#endif</span><br />
&nbsp;</div>
<p>First, we have a control member object, just like area. Then we have the coordinates of where the camera is. An extra thing I threw in, was the ability to target something. For example, in a Megaman game the camera would target Megaman himself. That way, when Megaman moves the camera would automatically update. So we have two pointers for X and Y coordinates. If these are null, the camera will automatically revert to the cameras position. Next, we have a target mode, which, for now, is either normal (the camera will position to the top left of the target) or center (will center the camera to the target). Pretty simply I think.</p>
<p>We then have a few functions, the first is the OnMove, which will increase the X and Y of the camera by MoveX and MoveY. So OnMove(0, -1) would move the camera to the left one pixel. We then have Get functions for the coordinates, and the ability to set the coordinates and set a target.</p>
<p>Okay, now open up CCamera.cpp:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;CCamera.h&quot;</span></p>
<p>CCamera CCamera::<span class="me2">CameraControl</span>;</p>
<p>CCamera::<span class="me2">CCamera</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; X = Y = <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; TargetX = TargetY = <span class="kw2">NULL</span>;</p>
<p>&nbsp; &nbsp; TargetMode = TARGET_MODE_NORMAL;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CCamera::<span class="me2">OnMove</span><span class="br0">&#40;</span><span class="kw4">int</span> MoveX, <span class="kw4">int</span> MoveY<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; X += MoveX;<br />
&nbsp; &nbsp; Y += MoveY;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">int</span> CCamera::<span class="me2">GetX</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>TargetX != <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>TargetMode == TARGET_MODE_CENTER<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> *TargetX &#8211; <span class="br0">&#40;</span>WWIDTH / <span class="nu0">2</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> *TargetX;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> X;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">int</span> CCamera::<span class="me2">GetY</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>TargetY != <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>TargetMode == TARGET_MODE_CENTER<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> *TargetY &#8211; <span class="br0">&#40;</span>WHEIGHT / <span class="nu0">2</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> *TargetY;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> Y;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CCamera::<span class="me2">SetPos</span><span class="br0">&#40;</span><span class="kw4">int</span> X, <span class="kw4">int</span> Y<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; this-&gt;X = X;<br />
&nbsp; &nbsp; this-&gt;Y = Y;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CCamera::<span class="me2">SetTarget</span><span class="br0">&#40;</span><span class="kw4">int</span>* X, <span class="kw4">int</span>* Y<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; TargetX = X;<br />
&nbsp; &nbsp; TargetY = Y;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>From top to bottom, like usual, we have are static member first. We then have the constructor defaulting some variables. The OnMove function will increase the X and Y, like I said before. We then have GetX. It will check to see if we have a valid target, and if so return the targets coordinates as the camera coordinates, otherwise return the camera x. For centering mode, we take the screen width and divide by two to find the center of the screen, and then subtract it from the target coordinates. This will center the camera to the target. We then have the SetPos and SetTarget functions, which are self-explanatory.</p>
<p>So lets put all this junk together! Open up CApp.h and modify it to include the new header files:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;Define.h&quot;</span></p>
<p><span class="co2">#include &quot;CArea.h&quot;</span><br />
<span class="co2">#include &quot;CCamera.h&quot;</span><br />
&nbsp;</div>
<p>Also, add a new function prototype:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> OnKeyDown<span class="br0">&#40;</span>SDLKey sym, SDLMod mod, Uint16 unicode<span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>We are going to checking that event for move our map around with the keyboard. So, open up CApp_OnEvent.cpp and add the function:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw4">void</span> CApp::<span class="me2">OnKeyDown</span><span class="br0">&#40;</span>SDLKey sym, SDLMod mod, Uint16 unicode<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">switch</span><span class="br0">&#40;</span>sym<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> SDLK_UP: &nbsp; &nbsp;CCamera::<span class="me2">CameraControl</span>.<span class="me1">OnMove</span><span class="br0">&#40;</span> <span class="nu0">0</span>, &nbsp;<span class="nu0">5</span><span class="br0">&#41;</span>; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> SDLK_DOWN: &nbsp;CCamera::<span class="me2">CameraControl</span>.<span class="me1">OnMove</span><span class="br0">&#40;</span> <span class="nu0">0</span>, <span class="nu0">-5</span><span class="br0">&#41;</span>; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> SDLK_LEFT: &nbsp;CCamera::<span class="me2">CameraControl</span>.<span class="me1">OnMove</span><span class="br0">&#40;</span> <span class="nu0">5</span>, &nbsp;<span class="nu0">0</span><span class="br0">&#41;</span>; <span class="kw2">break</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> SDLK_RIGHT: CCamera::<span class="me2">CameraControl</span>.<span class="me1">OnMove</span><span class="br0">&#40;</span><span class="nu0">-5</span>, &nbsp;<span class="nu0">0</span><span class="br0">&#41;</span>; <span class="kw2">break</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">default</span>: <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>We check the SDL keys, and according to the key move the camera around. Next, open up CApp_OnCleanup.cpp and add the cleanup function for the Area:</p>
<div class="dean_ch" style="white-space: wrap;">
CArea::<span class="me2">AreaControl</span>.<span class="me1">OnCleanup</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>Open up CApp_OnRender.cpp and add the Render call too:</p>
<div class="dean_ch" style="white-space: wrap;">
CArea::<span class="me2">AreaControl</span>.<span class="me1">OnRender</span><span class="br0">&#40;</span>Surf_Display, CCamera::<span class="me2">CameraControl</span>.<span class="me1">GetX</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, CCamera::<span class="me2">CameraControl</span>.<span class="me1">GetY</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>Notice that we are passing the Camera coordinates to the OnRender. And lastly, open up CApp_OnInit.cpp:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">if</span><span class="br0">&#40;</span>CArea::<span class="me2">AreaControl</span>.<span class="me1">OnLoad</span><span class="br0">&#40;</span><span class="st0">&quot;./maps/1.area&quot;</span><span class="br0">&#41;</span> == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="br0">&#125;</span></p>
<p>SDL_EnableKeyRepeat<span class="br0">&#40;</span><span class="nu0">1</span>, SDL_DEFAULT_REPEAT_INTERVAL / <span class="nu0">3</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>SDL_EnableKeyRepeat call sets the keyboard repeat count. So if we hold down a key it will keep calling the event above. And we are done! Compile the code and try it out. I hope it all works as expected, this was a very lengthy tutorial. Please check out the tutorial files below if you are having a bit of trouble. And please let me know if for some reason I left some important code out.</p>
<p><b>SDL Maps &#8211; Tutorial Files:</b><br />
<b>Win32:</b> <a href="../tutorials/sdl-maps.zip">Zip</a>, <a href="../tutorials/sdl-maps.rar">Rar</a><br />
<b>Linux:</b> <a href="../tutorials/sdl-maps.tar.gz">Tar</a> (Thanks Gaten), <a href="../tutorials/sdl-maps-compiled.tar.gz">Binary</a> (Thanks Thomas)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sdltutorials.com/sdl-maps/feed/</wfw:commentRss>
		<slash:comments>75</slash:comments>
		</item>
		<item>
		<title>SDL Image</title>
		<link>http://www.sdltutorials.com/sdl-image/</link>
		<comments>http://www.sdltutorials.com/sdl-image/#comments</comments>
		<pubDate>Fri, 14 Mar 2008 11:46:03 +0000</pubDate>
		<dc:creator>Tim Jones</dc:creator>
				<category><![CDATA[SDL Tutorials]]></category>
		<category><![CDATA[C++ tutorials]]></category>
		<category><![CDATA[game tutorials]]></category>

		<guid isPermaLink="false">http://www.sdltutorials.com/sdl-image/</guid>
		<description><![CDATA[This side tutorial is rather simple, short, and sweet. I am going to show you how to stop using those pesky bitmap (BMP) files that are too big and don&#8217;t support alpha transparency, and to start using other file formats for you surfaces (I personally like PNG). If you have not read my SDL Coordinates [...]]]></description>
			<content:encoded><![CDATA[<p>This side tutorial is rather simple, short, and sweet. I am going to show you how to stop using those pesky bitmap (BMP) files that are too big and don&#8217;t support alpha transparency, and to start using other file formats for you surfaces (I personally like PNG). If you have not read my <a href="http://www.sdltutorials.com/sdl-coordinates-and-blitting/">SDL Coordinates and Bliting</a> tutorial, I encourage you to do so now. We will be building off of that tutorial, modifying the OnLoad function of the CSurface class.</p>
<p>The first thing you need to do is download SDL_image, the latest version, from the main <a href="http://www.libsdl.org">SDL website</a>. You can also download this library from the &#8220;Libraries&#8221; section of this website, under SDL. If you don&#8217;t want to worry about finding all these libraries, the SDL package I provide is good for most SDL beginners, as it provides SDL_image, and some other useful libraries. Be sure to put the include files in the same directory as your SDL include files, and your lib files in the same directory as your SDL lib files to make things easier.</p>
<p><span id="more-34"></span><br />
Start by opening your project, and going under the linker settings. Add SDL_image after SDLmain, something like:</p>
<p>mingw32<br />
SDLmain<br />
SDL_image<br />
SDL</p>
<p>If you don&#8217;t remember where to find all these settings, hope on over to the first tutorial <a href="http://www.sdltutorials.com/sdl-tutorial-basics/">SDL Tutorial Basics</a> to get a refresher on linking.</p>
<p>First, open up CSurface.h, so that we can include an extra header file:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#ifndef _CSURFACE_H_</span><br />
&nbsp; &nbsp; <span class="co2">#define _CSURFACE_H_</span></p>
<p><span class="co2">#include &lt;SDL.h&gt;</span><br />
<span class="co2">#include &lt;SDL_image.h&gt;</span><br />
&nbsp;</div>
<p>Once that is all done, open up CSurface.cpp and look for the OnLoad function. Currently, this is what our code looks like:</p>
<div class="dean_ch" style="white-space: wrap;">
SDL_Surface* CSurface::<span class="me2">OnLoad</span><span class="br0">&#40;</span><span class="kw4">char</span>* <span class="kw4">File</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_Surface* Surf_Temp = <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; SDL_Surface* Surf_Return = <span class="kw2">NULL</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span><span class="br0">&#40;</span>Surf_Temp = SDL_LoadBMP<span class="br0">&#40;</span><span class="kw4">File</span><span class="br0">&#41;</span><span class="br0">&#41;</span> == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; Surf_Return = SDL_DisplayFormat<span class="br0">&#40;</span>Surf_Temp<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; SDL_FreeSurface<span class="br0">&#40;</span>Surf_Temp<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> Surf_Return;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>There are two changes to make here, the first is changing SDL_LoadBMP to IMG_Load. The second is changing SDL_DisplayFormat to SDL_DisplayFormatAlpha. Remember I said BMPs don&#8217;t support alpha layers? Well, PNGs do! And if you are wanting to keep that alpha layer you&#8217;ll need to use SDL_DisplayFormatAlpha instead of SDL_DisplayFormat. So, our code should look like this now:</p>
<div class="dean_ch" style="white-space: wrap;">
SDL_Surface* CSurface::<span class="me2">OnLoad</span><span class="br0">&#40;</span><span class="kw4">char</span>* <span class="kw4">File</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; SDL_Surface* Surf_Temp = <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; SDL_Surface* Surf_Return = <span class="kw2">NULL</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span><span class="br0">&#40;</span>Surf_Temp = IMG_Load<span class="br0">&#40;</span><span class="kw4">File</span><span class="br0">&#41;</span><span class="br0">&#41;</span> == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">NULL</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; Surf_Return = SDL_DisplayFormatAlpha<span class="br0">&#40;</span>Surf_Temp<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; SDL_FreeSurface<span class="br0">&#40;</span>Surf_Temp<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> Surf_Return;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Finally, don&#8217;t forget to change the filename that the Test Surface is trying to load in CApp_OnInit.cpp:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">if</span><span class="br0">&#40;</span><span class="br0">&#40;</span>Surf_Test = CSurface::<span class="me2">OnLoad</span><span class="br0">&#40;</span><span class="st0">&quot;myimage.png&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>And we are done! I told you it would be short. Try compiling, and trying out different file formats. Some common formats supported by SDL_image are:</p>
<p>BMP (Go figure)<br />
GIF<br />
PNG<br />
JPG<br />
PCX<br />
TIF<br />
and others&#8230;</p>
<p>Please note that there are additional DLL files associated with SDL image that are needed now (about 5 of them). So be sure to include those with your project. You can download these DLL files here, <a href="http://www.libsdl.org/projects/SDL_image/">http://www.libsdl.org/projects/SDL_image/</a> under Binary -> Win32 -> and the Win32 zip (not the VC8). Also, the DLL files are also included in the project files below.</p>
<p>This tutorial inspired by Blommis. <img src='http://www.sdltutorials.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><b>SDL Image &#8211; Tutorial Files:</b><br />
<b>Win32:</b> <a href="../tutorials/sdl-image.zip">Zip</a>, <a href="../tutorials/sdl-image.rar">Rar</a><br />
<b>Linux:</b> <a href="../tutorials/sdl-image.tar.gz">Tar</a> (Thanks Gaten), <a href="../tutorials/sdl-image-compiled.tar.gz">Binary</a> (Thanks Thomas)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sdltutorials.com/sdl-image/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>SDL Entities</title>
		<link>http://www.sdltutorials.com/sdl-entities/</link>
		<comments>http://www.sdltutorials.com/sdl-entities/#comments</comments>
		<pubDate>Fri, 22 Feb 2008 13:27:20 +0000</pubDate>
		<dc:creator>Tim Jones</dc:creator>
				<category><![CDATA[SDL Tutorials]]></category>
		<category><![CDATA[sdl]]></category>
		<category><![CDATA[sdl entities]]></category>

		<guid isPermaLink="false">http://www.sdltutorials.com/sdl-entities/</guid>
		<description><![CDATA[In this new tutorial, as I had promised before, we are going to take our hand at creating entities. Entities, for all gaming purposes, are anything that can be interacted with in any way, shape, or form. Some examples might be a monster or a treasure chest that you can open. In this sense, practically [...]]]></description>
			<content:encoded><![CDATA[<p>In this new tutorial, as I had promised before, we are going to take our hand at creating entities. Entities, for all gaming purposes, are anything that can be interacted with in any way, shape, or form. Some examples might be a monster or a treasure chest that you can open. In this sense, practically everything within the game that moves is an Entity. A rock that is part of a map, which never moves, is not an entity. But if you wanted that rock to move for whatever reason, then we&#8217;d make it an Entity. This tutorial will be split into 3 different tutorials. The first, this one you are reading, will deal with a basic Entity class structure. The next tutorial will veer off slightly to build a Map class via a tileset. Then, the last tutorial, which is what a lot of people have trouble with, will deal with Entity to Map collision, and Entity to Entity Collision. </p>
<p><span id="more-29"></span></p>
<p><b>Update:</b><br />
- Fixed class below to have a virtual destructor. <i>(Thanks Andras!)</i></p>
<p>Lets get started by creating two new files called CEntity.cpp and CEntity.h. Open up the header file and add the following:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &lt;vector&gt;</span></p>
<p><span class="co2">#include &quot;CAnimation.h&quot;</span><br />
<span class="co2">#include &quot;CSurface.h&quot;</span></p>
<p><span class="kw2">class</span> CEntity <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">static</span> std::<span class="me2">vector</span>&lt;CEntity*&gt; &nbsp; &nbsp;EntityList;</p>
<p>&nbsp; &nbsp; <span class="kw2">protected</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; CAnimation &nbsp; &nbsp; &nbsp;Anim_Control;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; SDL_Surface* &nbsp; &nbsp;Surf_Entity;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; X;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">float</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Y;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Width;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Height;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AnimState;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; CEntity<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">virtual</span> ~CEntity<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; <span class="kw2">public</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">bool</span> OnLoad<span class="br0">&#40;</span><span class="kw4">char</span>* <span class="kw4">File</span>, <span class="kw4">int</span> Width, <span class="kw4">int</span> Height, <span class="kw4">int</span> MaxFrames<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> OnLoop<span class="br0">&#40;</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> OnRender<span class="br0">&#40;</span>SDL_Surface* Surf_Display<span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> OnCleanup<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span>;<br />
&nbsp;</div>
<p>Now, open up the cpp file and add the following:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;CEntity.h&quot;</span></p>
<p>std::<span class="me2">vector</span>&lt;CEntity*&gt; CEntity::<span class="me2">EntityList</span>;</p>
<p>CEntity::<span class="me2">CEntity</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; Surf_Entity = <span class="kw2">NULL</span>;</p>
<p>&nbsp; &nbsp; X = Y = <span class="nu0">0</span>.0f;</p>
<p>&nbsp; &nbsp; Width = Height = <span class="nu0">0</span>;</p>
<p>&nbsp; &nbsp; AnimState = <span class="nu0">0</span>;<br />
<span class="br0">&#125;</span></p>
<p>CEntity::~CEntity<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">bool</span> CEntity::<span class="me2">OnLoad</span><span class="br0">&#40;</span><span class="kw4">char</span>* <span class="kw4">File</span>, <span class="kw4">int</span> Width, <span class="kw4">int</span> Height, <span class="kw4">int</span> MaxFrames<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span><span class="br0">&#40;</span>Surf_Entity = CSurface::<span class="me2">OnLoad</span><span class="br0">&#40;</span><span class="kw4">File</span><span class="br0">&#41;</span><span class="br0">&#41;</span> == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; CSurface::<span class="me2">Transparent</span><span class="br0">&#40;</span>Surf_Entity, <span class="nu0">255</span>, <span class="nu0">0</span>, <span class="nu0">255</span><span class="br0">&#41;</span>;</p>
<p>&nbsp; &nbsp; this-&gt;Width = Width;<br />
&nbsp; &nbsp; this-&gt;Height = Height;</p>
<p>&nbsp; &nbsp; Anim_Control.<span class="me1">MaxFrames</span> = MaxFrames;</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">true</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CEntity::<span class="me2">OnLoop</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; Anim_Control.<span class="me1">OnAnimate</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CEntity::<span class="me2">OnRender</span><span class="br0">&#40;</span>SDL_Surface* Surf_Display<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>Surf_Entity == <span class="kw2">NULL</span> || Surf_Display == <span class="kw2">NULL</span><span class="br0">&#41;</span> <span class="kw1">return</span>;</p>
<p>&nbsp; &nbsp; CSurface::<span class="me2">OnDraw</span><span class="br0">&#40;</span>Surf_Display, Surf_Entity, X, Y, AnimState * Width, Anim_Control.<span class="me1">GetCurrentFrame</span><span class="br0">&#40;</span><span class="br0">&#41;</span> * Height, Width, Height<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw4">void</span> CEntity::<span class="me2">OnCleanup</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>Surf_Entity<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; SDL_FreeSurface<span class="br0">&#40;</span>Surf_Entity<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; Surf_Entity = <span class="kw2">NULL</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Okay, now for some basic explanation. What we are doing here is encapsulating the basic 5 components I mentioned within the first lesson (excluding Events, which will be handled in a later lesson). This allows us to handle Entities within the game much more easily, rather than clumping them together with everything else in the game within the main CApp class. This will also be the way we handle other things as well. The first thing you may notice is a static vector called EntityList. This vector will hold all of our entities, easily accessible through CEntity::EntityList, because it&#8217;s declared as a static. I should make a special note here: we declare this EntityList within CEntity because it prevents from circular dependencies later on. An example of this is trying to get a Map to communicate with Entities, and Entities to get to communicate with the Map. Such as CMap declaring a CEntity member, and CEntity declaring a CMap member. It would cause problems on the compile level.</p>
<p>So this vector contains all of our Entities within the game. Notice that each member of the vector is a pointer. This is because later on we are going to inherit this CEntity class for Entity specific classes. So, for example, if we were going to make a Megaman game, we would have a CMegaMan class inheriting the CEntity class. And, via polymorphism, we can store that CMegaMan class within the EntityList. This is the very reason why we declared the functions above as virtuals, and certain members as protected.</p>
<p>Next, we have basic information about the Entity, common to all Entities, coordinates, dimensions, and a surface for its image. Next, we have a loading function that basically takes a filename, and loads the image. By default, we have it setting a transparent color. I&#8217;d like to step aside here for a moment to let you all know that certain things I do aren&#8217;t set in stone. You can, and are encourage, to take this code and modify to your liking. You may want more parameters on your OnLoad function, or you may want less. You may not want a default transparent color, who knows. I encourage you to test different things. Don&#8217;t worry, my code will still be here if you mess things up.</p>
<p>Next, we have a basic OnLoop function that handles basic calculations. Right now we are only calculating Animation. Also please note that we have only set the MaxFrames for the Animation, and left the defaults in place. Next, we have the OnRender function. Instead of making it render to the display only, I&#8217;ve allowed a parameter to specify where to render this entity. This could be any surface you want. So you could, if you wanted, render one entity onto another.</p>
<p>Lastly, we have an OnCleanup function that restores memory and all that stuff.</p>
<p>Like I mentioned in the beginning, this is a basic Entity class structure, it basically doesn&#8217;t do much yet, but don&#8217;t fret, it soon will in coming lessons. So lets get it working. Open up CApp.h and add the header file to the top, and declare two Entities:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co2">#include &quot;CEntity.h&quot;</span></p>
<p>
<span class="co1">//&#8230;</span></p>
<p><span class="kw2">private</span>:<br />
&nbsp; &nbsp; CEntity &nbsp; &nbsp; &nbsp; &nbsp; Entity1;<br />
&nbsp; &nbsp; CEntity &nbsp; &nbsp; &nbsp; &nbsp; Entity2;<br />
&nbsp;</div>
<p>Now, lets load these two Entities. Open up CApp_OnInit.cpp and add the following:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">if</span><span class="br0">&#40;</span>Entity1.<span class="me1">OnLoad</span><span class="br0">&#40;</span><span class="st0">&quot;./entity1.bmp&quot;</span>, <span class="nu0">64</span>, <span class="nu0">64</span>, <span class="nu0">8</span><span class="br0">&#41;</span> == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="br0">&#125;</span></p>
<p><span class="kw1">if</span><span class="br0">&#40;</span>Entity2.<span class="me1">OnLoad</span><span class="br0">&#40;</span><span class="st0">&quot;./entity2.bmp&quot;</span>, <span class="nu0">64</span>, <span class="nu0">64</span>, <span class="nu0">8</span><span class="br0">&#41;</span> == <span class="kw2">false</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;<br />
<span class="br0">&#125;</span></p>
<p>Entity2.<span class="me1">X</span> = <span class="nu0">100</span>;</p>
<p>CEntity::<span class="me2">EntityList</span>.<span class="me1">push_back</span><span class="br0">&#40;</span>&amp;Entity1<span class="br0">&#41;</span>;<br />
CEntity::<span class="me2">EntityList</span>.<span class="me1">push_back</span><span class="br0">&#40;</span>&amp;Entity2<span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>Now, depending on the images you use, you need to set the values appropriately on the OnLoad function. I&#8217;ve reused the yoshi image from the previous lesson, and if you still need it:</p>
<p><img src="../wp-content/uploads/yoshi.bmp"/></p>
<p>Now, remember how I stated we are basically encapsulating the basic functions of a game within the Entity class? We have to call those functions now in the respective CApp functions. So, open up CApp_OnLoop.cpp and add the following:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>;i &lt; CEntity::<span class="me2">EntityList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>!CEntity::<span class="me2">EntityList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="kw1">continue</span>;</p>
<p>&nbsp; &nbsp; CEntity::<span class="me2">EntityList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;OnLoop<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>We are basically running through each Entity in our vector, and calling the OnLoop function. Simple enough! (And we&#8217;re doing an error checking so we don&#8217;t call any NULL pointers). Now, lets do the same things in CApp_OnRender.cpp: </p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>;i &lt; CEntity::<span class="me2">EntityList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>!CEntity::<span class="me2">EntityList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="kw1">continue</span>;</p>
<p>&nbsp; &nbsp; CEntity::<span class="me2">EntityList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;OnRender<span class="br0">&#40;</span>Surf_Display<span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>And the same thing in CApp_OnCleanup.cpp:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>;i &lt; CEntity::<span class="me2">EntityList</span>.<span class="me1">size</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;i++<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span><span class="br0">&#40;</span>!CEntity::<span class="me2">EntityList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="kw1">continue</span>;</p>
<p>&nbsp; &nbsp; CEntity::<span class="me2">EntityList</span><span class="br0">&#91;</span>i<span class="br0">&#93;</span>-&gt;OnCleanup<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span></p>
<p>CEntity::<span class="me2">EntityList</span>.<span class="me1">clear</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp;</div>
<p>Note that I added the clear function call, which clears out the vector to nothing. Basically a reset.</p>
<p>Great, now try getting this thing to compile. You should see two yoshis running together on the screen. In the next lesson we&#8217;re going to looking at making Maps, and creating a basic file format for our Maps.</p>
<p><b>SDL Entities &#8211; Tutorial Files:</b><br />
<b>Win32:</b> <a href="../tutorials/sdl-entities.zip">Zip</a>, <a href="../tutorials/sdl-entities.rar">Rar</a><br />
<b>Linux:</b> <a href="../tutorials/sdl-entities.tar.gz">Tar</a> (Thanks Gaten)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.sdltutorials.com/sdl-entities/feed/</wfw:commentRss>
		<slash:comments>63</slash:comments>
		</item>
	</channel>
</rss>
