Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon
18. May 2012

 

 

You often hear people say things like “It’s memory management that makes C++ difficult”, this is patently false.  What makes C++ so incredibly difficult for new users ( and experienced ones! ) is the complexity.  Note, I didn’t say difficulty, I said complexity.

 

Today was one of those perfect examples, one of those experiences that I want to point at and say “THIS IS WHY YOU SHOULD LEARN WITH A DIFFERENT LANGUAGE!”.  Yes, that was shouting. 

 

 

Here’s the story.  Today I had a reader request guidance on how to make a release build of my C++ tutorial.  This was a really good request, so I put it together in tutorial form.  Something quickly dawned on me… I’ve never built this tutorial in release mode.  It was pretty obvious that I hadn’t because, well, it didn’t work!   Oops, my bad.

 

 

Let’s take a look at what happened, I want to see if you can guess what the problem is.  A gold star to whoever gets it before I reveal the answer at the end of this post.  That gold star offer applies to C++ veterans and new developers alike, this is a somewhat tricky one, especially considering the starting point!

 

 

So, I was building Pang 9 ( my Pong tutorial ) in release mode.  I downloaded the project files from here if you want to follow along at home.  I simply extracted the project, then I downloaded the full SFML 1.6 SDK, imported the Visual Studio 2008 project into Visual Studio 2010 and compiled the DLLs for multithreaded release mode, and copied those DLLs into my release directory.  Code compiles just fine under release, so then I run it ( within Visual Studio ) and:

 

 

image 

 

Uhoh… this can’t be good!  The offending line of code is right here:

 

sf::Music* SoundFileCache::GetSong(std::string soundName) const { std::map<std::string,sf::Music *>::iterator itr = _music.find(soundName); if(itr == _music.end()) { sf::Music * song = new sf::Music(); if(!song->OpenFromFile(soundName)) <----- EXCEPTION IS HERE { delete song; throw SoundNotFoundExeception( soundName + " was not found in call to SoundFileCache::GetSong"); } ..... SNIP ......

Well, there is a big bad pointer right above the line, that seems an obvious candidate doesn’t it?   Well don’t waste your time on that train of thought, the pointer isn’t the issue.  The .find call seems a likely candidate too, it isn’t though.

 

Hmm, lets start looking there, ill set a breakpoint and trace into the _music.find() call.  Oh yeah, this a release mode only bug, so our hands our tied on the debugging side of things… great.  Alright, lets take a closer look.

 

image

 

 

<Bad Ptr>.  Oooh, that’s not good.  Obviously I’ve done a bad allocation here somewhere, but that just doesn’t make sense, not with the way this data type works.  In fact, the only place these pointers are even allocated is in this actual method, and we haven’t even got to that code yet!

 

For some reason, our empty map ( it hasn’t been used yet, this is the first call ), is returning a Bad Ptr instead of working as expected.  This can’t be right?  But wait… that’s a red herring anyways, isn’t it, after all our exception has nothing to do with the Bad Ptr or the std::map at all, this is just the IDE sending us on a wild goose chase. We can literally boil it down to exactly two lines of code:

 

sf::Music * song = new sf::Music(); if(!song->OpenFromFile(soundName))

 

Now we are getting somewhere, we have isolated our reproduce case down to exactly a two line program!  Hmmm, both are just standard SFML calls.  Short of being out of memory, nothing here should be able to fail.  So then, what the hell is causing this problem???

 

 

// ANSWER TIME, got your guess yet?  Did you get it right and I owe you a gold star?  Let’s find out!

 

 

Well, long story short, it’s our SFML dlls built for Visual Studio 2010.  See, this is our first method call into any SFML DLL and it’s causing an explosion… but, why the heck is that???

 

 

Well, lets take a trip over to the SFML 1.6 project and check out how I built them.  All I did was download the SFML 1.6 project for Visual Studio 2008, delete all the examples and set my build mode to Release DLL and compiled everything.  Hidden between the various warnings was one very very very important but cryptic message:

 

image

 

A bunch of warnings as a side effect of the import process, and one extremely important warning… the ahah moment if you will:

 

Warning    8    warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library    C:\temp\t\SFML-1.6\build\vc2008\LINK    sfml-graphics

 

Say what?

 

 

Now here is the thing, with C++ libraries need to be IDENTICAL.  You link debug to debug, multithread to multithread, etc…  At the same time, you have to link Visual Studio 2010 binaries to Visual Studio 2010 binaries ( although not all versions are binary incompatible, VS 2005 and 2008 could share libraries I believe ), and this here is the source of all the trouble!

 

The sfml-graphics graphics library statically links to a lib called freetype, and this library isn’t compatible with Visual Studio 2010.  Download the newest version, extract it into the extlibs folder, recompile and PRESTO, problem solved.

 

 

 

So there you go, an unhandled exception in a call to open an audio file ended up actually being caused by a statically linked font library in a 3rd party graphics dll!

 

 

Still think it’s memory management that makes C++ tricky for beginners?  The biggest problem is, new developers run into this stuff almost immediately.  You need to conquer so much to get up and running with C++, the linker being one of the earliest and most daunting obstacles.  I honestly don’t expect anyone with a few months of programming experience to have been able to puzzle this one out.  It’s exactly these kinds of things that make people throw up their hands saying “Oh screw it, programming is too hard!”.  I don’t like a quitter, but frankly in this case… they are right!

 

 

Of course, this is by no means limited to C++.  I have had very similar experiences with Java where some XML file feeding another XML file feeding a code generator called by Maven puked out a message code like “Error, unknown problem”.  Thing is, with no other programming languages do you encounter this kind of problem until you are ready to deal with the complexity.  In C++, you start dealing with this crap on day 1.

 

So this, is one such reason why I say C++ isn’t a beginner friendly language!

General


18. May 2012

 

Someone on the PlayStation Suite forum recently asked if there was an implementation of the Box2D physics library that would work with PS Suite.  Initially Box2Dx looked encouraging, but in the end it relied on some unsafe ( as in the keyword ) code, plus it was quite a bit out of date.  In my searching though, I did stumble upon the Farseer XNA a prominent XNA physics library.  It depends on some XNA data types, but nicely, the library includes them!

 

So I set about trying to get FarSeer working with PlayStation Suite, which proved to be a fairly simple task.

 

First you need to create a PlayStation suite library, then copy across all of the code/folders from the archive.  Make sure it is FarSeer Physics Engine class you download, the other versions have dependencies that don’t work.  Now you have to make one very small code change.  You need to open DynamicTreeBroadPhase.cs and change internal struct Pair : … to public, like this:

 

public struct Pair : IComparable<Pair> //MJF made public

 

And that’s it.

 

Compile it as a PlayStation Suite library and add it as a reference to your project and you are off to the races.  You can download the DLL I compiled for PlayStation Suite right here if you don’t want to or can’t build it yourself.

 

Now, the reason I’m not really calling this a tutorial is, I haven’t bothered to actually take the time to figure out how to use FarSeer, I just modified their sample enough to verify it runs on the PlayStation Vita.  Due to the screwy decision to make the origin the bottom left, you need to alter their examples accordingly, but otherwise everything works fine.  Here is a sample of extremely poorly configured gravity.

 

using System; using System.Collections.Generic; using Sce.Pss.Core; using Sce.Pss.Core.Environment; using Sce.Pss.Core.Graphics; using Sce.Pss.Core.Input; using Sce.Pss.HighLevel.GameEngine2D; using Sce.Pss.HighLevel.GameEngine2D.Base; using FarseerPhysics.Common; using FarseerPhysics.Controllers; using FarseerPhysics.Dynamics; using FarseerPhysics.Factories; namespace FarTest { public class AppMain { private const float MeterInPixels = 64f; public static void Main() { Director.Initialize(); Scene scene = new Scene(); scene.Camera.SetViewFromViewport(); Vector2 midPoint = scene.Camera.CalcBounds().Center; // Create circle and ground sprites Texture2D texture = new Texture2D("/Application/circleSprite.png",false); TextureInfo ti = new TextureInfo(texture); SpriteUV sprite = new SpriteUV(ti); sprite.Quad.S = new Vector2(98,98); sprite.Position = new Vector2(midPoint.X - 98/2,Director.Instance.GL.Context.GetViewport().Height-98); Texture2D texture2 = new Texture2D("/Application/groundSprite.png",false); TextureInfo ti2 = new TextureInfo(texture); SpriteUV sprite2 = new SpriteUV(ti); sprite2.Quad.S = new Vector2(512,64); sprite2.Position = new Vector2(midPoint.X - 512/2,0); //Physics time World world = new World(new Microsoft.Xna.Framework.Vector2(0,-10)); Body circleBody = BodyFactory.CreateCircle(world,96f /2f,1f, new Microsoft.Xna.Framework.Vector2(sprite.Position.X,sprite.Position.Y)); circleBody.BodyType = BodyType.Dynamic; Body groundBody = BodyFactory.CreateRectangle(world,512f, 64f/2,1f, new Microsoft.Xna.Framework.Vector2(sprite2.Position.X,sprite2.Position.Y)); ; groundBody.IsStatic = true; groundBody.Restitution = 0.9f; groundBody.Friction = 0.4f; // Now update the sprite //circleBody.ApplyLinearImpulse(new Microsoft.Xna.Framework.Vector2(0,-50)); sprite.Schedule( (dt) => { sprite.Position = new Vector2(circleBody.Position.X,circleBody.Position.Y); world.Step(dt); }); scene.AddChild(sprite); scene.AddChild (sprite2); Director.Instance.RunWithScene(scene); } } }

 

 

And here are the results:

 

physics

 

 

The only real gotcha in the code is to make sure you use the Microsoft.Xna.Framework.Vector2 when calling FarSeer code and PSS’s Vector2 when dealing with PSS code.

 

 

Obviously, my ground is a bit bouncy, my gravity is a bit wonky, but it is a working physics simulation! Smile

General


18. May 2012

 

 

At the request of a reader I put together a guide on how to build your SFML 1.6 project in release mode, then how to package it for distribution.

 

It’s part of the main tutorial series, but can be accessed directly here.  If you are looking into how to distribute a release version of your SFML game, be sure to check it out

 

 

In doing so, I ran into a NASTY C++ related problem, which I will mention in a post shortly!

Programming


16. May 2012

 

 

image

 

 

If you are going to make your game require an always on internet connection, especially for the single player game, you damned well better have stable servers!

 

Diablo 3 have blown it pretty big time, and things don’t seem to be getting that much better.  On the bright side, in the face of all of these Error 37’s, D3 hasn’t really affected my productivity.

 

If anyone but Blizzard pulled this stunt, their game would be getting 0 star reviews and shamed into oblivion.  I am curious to see how Diablo ends up being reviewed.  The worst part is, Diablo 3 is a damned good game making suffering these annoyances worthwhile… just.

 

What *REALLY* pisses me off though… cache my damned password!  It’s annoying enough having to deal with these errors, but having to re-enter my password every time I hit an error 37, that’s just salt in the wound!  Blizzard, if you are listening to your fans, if you can’t fix your servers, at least cache the password field!

 

So, if you are here killing time between Diablo error messages, could I suggest a game programming tutorial or two… Winking smile

 

 

 

EDIT:  20 seconds later…

 

image

 

Why oh why did I complain… I angered the gods, who invoked their wrath in the form a hithero unheard of Error 33.  Battle.net is down for maintenance.  Please try again later (Error 33).

 

 

Blizzard, seriously, you screwed up big time.

 

 

I’m pretty tolerant of DRM, I understand the motivation behind it, but this DRM that supposedly isn’t DRM, well it’s about the worst I’ve dealt with since HoMM6.  Actually it’s worse, as I could still at least play HoMM offline during the outages.

 

I hope every other game developer out there is taking note of the Error 37’s and 33’s and realizing what a mistake always on internet connections for single player games is!  I won’t buy another one with this feature, that’s for sure.

 

 

Oh, and if you are here from Google looking for a way to fix Error 38’s, sadly you can’t.  That ball is completely in Blizzards court.  Until they fix their servers, increase capacity or implement an offline mode ( very very unlikely ) I am afraid to say these errors are going to be a fact of Diablo life.

Totally Off Topic


16. May 2012

 

I asked a few days back about how many people would be interested in an HTML5/RPG series.  Between comments and emails I’ve received, there appears to be a fair bit of interest and I’ve decided to go ahead with it.  As HTML gaming is somewhat new to me, I am not sure yet exactly the format the series will take.  I think it will be a hybrid between a blog and a tutorial series; combining musings with instruction, with the ever present caveat that “I might be doing something really stupid!”.

 

 

Anyways, one of those things I always hated about browser development was cross browser support.  As I do more and more research, it seems that Internet Explorer is still very unpleasant to support.  What I got to wondering was, just how many people actually use IE anymore, I surely don’t 99.9% of the time.  So I took a look at this sites statistics since the start of 2012:

 

image

 

I was rather shocked to  see a few things.  First, I’ve known Chromes popularity has been growing, but I had no idea it was to that degree.  I suppose I shouldn’t be shocked, I use Chrome almost exclusively.  What I found perhaps the next most shocking is that Safari is beating out Internet Explorer!  I know both benefit from being bundled with the OS, but given the 10 to 1 sales gap between Windows and Mac, you would figure IE would be much higher.

 

That said, all of these statistics are fairly meaningless, as the audience to a site like GameFromScratch are going to be much more technically savvy than most sites.

 

I mostly just found them interesting and to use it as an excuse to not officially support IE when developing my tutorials, at least until Windows 8 ships with the next version.

Totally Off Topic


AppGameKit Studio

See More Tutorials on DevGa.me!

Month List