Phil Hassey - game dev blog
Phil Hassey as Snidely Whiplash
"You can't buy awesomeness.
You're born that way."

VisualC++ 2008 for gcc / SDL people

January 14th, 2010

I’ve had to port a project to VC 2008 from my usual mingw setup.  Here’s what I did.  This covers quite a few things, in particular where to find common GCC settings in VC land.

Setting up the project
  1. New project
  2. Type: win32
  3. Template: Win32 console if you want a console.  Or just Win32 Project if you don’t want the console to pop up.
  4. Choose a name for your project
  5. The solution name is the folder everything gets put in.  In VC, you can have several projects within a single solution.
  6. On App settings, I choose Windows application, Empty project

Adding the source files

  1. I right click on my project name and Add>New filter, and use that to bundle a few different sets of source files together
  2. This is done so that VC will compile the files, but keep in mind that the separations don’t seem to mean anything to VC.  It’s just for your visual convenience.
  3. Note that if there are two files with the same base name “dostuff.c” and “dostuff.cc” this will cause VC to choke during compilation as it will create two .obj files with the same name and fail during linking.
  4. VC doesn’t support C99 so any C99 files will have to be Right Click > Properties > C/C++ > Advanced > Compile as > C++ Code

Note: a Project can have a number Configurations (Debug, Release ..) If you are targeting a certain distribution site with some special requirements you can add more Configurations via Solution > Properties > Configuration Manager >

Compilation Options

Adding some project compile time options (mainly -D and -I equivalents for specific defines and include folders.)  Keep in mind which Configuration you are modifying at all times.  You can also switch to “All Configurations” for global changes.

  1. (GCC -I)  To add in include folders, Project > Configuration Properties > C/C++ > General > Additional Include Directories > … I found with include folders you often need to stack on a few ../../’s to get it to point at what you want it to point at.  (In my project I’ve got my VC project separate from all my source code, so everything is up and over a few folders.)
  2. (GCC -D)  To add in defines, Project > Configuration Properties > C/C++ > Preprocessor > Preprocessor Definitions > .. I often add a few of these to tell the code what build we’re doing.  (iPhone vs, Windows, vs Linux, etc)
  3. (GCC -W)  Although warnings might be useful .. They made it impossible to see the errors.  You can turn down the warnings from level 3 to 1 in Project > Configuration Properties > C/C++ > General > Warning Level >
  4. (GCC -l)  Linked libraries are probably going to be needed.  Again in my project I’ve often got a few ../../’s in the paths.  Here’s where you add this stuff: Project > Configuration Properties > Linker > Input > Additional Dependencies >
  5. .. an alternate way is to add #pragma comment(lib,”MyLib.lib”) into your main.cpp.  By doing this you can refer to a lib right within your source if you prefer.
  6. For whatever reason, you may need to exclude some libs from being compiled into your project.  (If you see errors like “_tolower already defined in MSVCRTD.lib, etc).  You can exclude a lib in Project > Configuration Properties > Linker > Input > Ignore Specific Library > .. (in my case, I had to add msvcrt.lib and libcmt.lib)
  7. For my project I needed to expand the size of my stack, due to having excessive amounts of static data compiled into the project.  You can do this via Project > Config Properties > Linker > System > Stack (Reserve&Commit) Size > .. I changed them both to 4000000 and things worked.

Final packaging

I found that running right from VC didn’t always work. (Maybe I should find out why, but I haven’t.)  But I can run from the command-line.  Before doing so, I needed to:

  1. Copy in required dlls from SDL, etc
  2. Copy in game data files
  3. Copy in the VC Runtime files from: C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT
  4. For a release build I’m sure to build against SDLmain_nostdio.lib so that the game won’t crash Vista/Win7 where writing out stdout.txt and stderr.txt may result in some kind of fail.

Saving to Your_Favorite_Version_Control_System

  1. You may leave out all your ‘Debug’ folders or other Configuration folders, those seem to only contain generated files.
  2. You may leave out the .ncb and the .COMPUTER.username.blah file, they seem to be used by VC for stuff that can be regenerated, etc.

Hopefully this will be helpful to anyone who does the same thing.  Between you and me, I found the install of VC 2008 to be pretty nice in comparison to trying to install mingw, which tends to require considerable muscling.  Also, since everyone provides their libs as MSVC libs, building against those vendor libs is not only easy, but possible.  (With mingw, many MSVC C++ libs are unusable due to binary incompatibility.)

-Phil

P.S. Adding an Icon to your Project

This is pretty easy.  Add a Project.rc to your project.  The Project.rc should include this line:

IDI_PROJECT       ICON         “path/to/icon256.ico”

You can create an Icon with IconFX .

P.S.S. Creating a windows Installer

I’ve used Innosetup in the past.  It seems to work.

P.S.S.S. Dealing with LPCTSTR conversions

If your whole project is using C-strings, you can go into Project > Properties > Configuration Properties > General > Character Set > and change it to “Not Set” so that VC will no longer try and use Unicode strings to some of its functions (like ShellExecute.)

P.S.S.S.S. Dealing with conflicting .obj files

If you get a linking error about a bunch of undefined symbols and you have say “game.c” and “game.cpp” in your project, they are both being compiled down to “game.obj” .. To set one of them to compile to a different filename, say “mygame.obj”, you need to Right Click > C/C++ > Output Files > Object File Name > “$(IntDir)\mygame.obj”

Alternately, you can just rename some of your source files so there are no name conflicts by default.

xkcd “Self-Description” solved with python+pygame

January 13th, 2010

Well, something about this xkcd comic drew me in …

The 3rd panel reminded me of a study I did in college on iterated function system fractals.  These fractals are known for creating ferns, trees, and the Sierpinski triangle.  There are a number of ways of creating these fractals, but one of them is called (something like) the reducing photo copier method.  Where you can start with ANY starting image on your photo copier, and just shrink the images, make a few copies, position them on the copier, and repeat.  Eventually your image converges towards the fern / triangle / whatever if you are precise.  (This can be done with a ‘Real Life’ photo copier for simple IFS like the Sierpinski triangle.)

So as a way to avoid work that I’m supposed to be doing this evening, I figured I’d see how “accurate” this comic was.  Here’s my pygame code that checks it out.  If you run main.py it will start with an image (the xkcd logo) and each time you press a key it will do an iteration of re-creating the comic.  You can see it flashing between the current iteration and the original strip.  After about 4-5 iterations the images converge (pretty closely.)

The most interesting bit was trying different starting images and seeing how long it took to converge.  Starting with all black  it takes 6 iterations.  Starting with all white takes 5 iterations.  And starting with the xkcd logo takes 4 iterations.  The logo probably goes the quickest because it has some black and white in it (like this image) so it converges faster.  (You can edit main.py towards the bottom page to try these different starting points.)

So .. there ya go!  Enjoy!

-Phil

Is None more like 0 or -1 ?

January 7th, 2010

In tinypyC++ every variable is a certain type.  In some cases I may have an int x = None;  But I’m not sure what that should mean?

What’s the most pythonic? Here’s some anecdotal evidence:

>>> None,None==None,None==-1,None==0,None==1,None==False,None==True,bool(None)
(None, True, False, False, False, False, False, False)
>>> -1,-1==None,-1==-1,-1==0,-1==1,-1==False,-1==True,bool(-1)
(-1, False, True, False, False, False, False, True)
>>> 0,0==None,0==-1,0==0,0==1,0==False,0==True,bool(0)
(0, False, False, True, False, True, False, False)
>>> 1,1==None,1==-1,1==0,1==1,1==False,1==True,bool(1)
(1, False, False, False, True, False, True, True)

So .. you can see -1 gets 4/7.  0 also gets 4/7.  (1 gets a mere 3/7, so it’s out.)

Anyone care to tilt the scales to -1 or 0?

Exceptions and various compilation option speeds

January 6th, 2010

So after some discussion yesterday with a few folks about Exceptions in C++, I decided to add a compilation flag to disable the use of exceptions in tinypyC++.  The claim given to me was around these few items: 1. Exceptions slow your code down.  2. Exceptions aren’t cross-platform (in some cases).  3. Exceptions can easily add in memory-leaks.

I can’t argue with #2, although it’s not completely relevant for the platforms I’m targeting right now.  #3, with the way tinypyC++ does reference counting, I wouldn’t be surprised if this could happen.  #1, I figured might be true, but I wanted to know how real #1 actually was.  So here are my results:

g++ flags ms
(none) 894
-g 891
-O3 414
-DTP_NO_THROW -fno-exceptions 894
-g -DTP_NO_THROW -fno-exceptions 878
-O3 -DTP_NO_THROW -fno-exceptions 378

In the first test I’m rendering a Julia fractal for 20 frames and averaging the time it takes to render. In the second test (below) I’m doing the same test, but I did one code optimization to remove a new/delete that was happening for each pixel – by reusing the coordinates object.

g++ flags ms
(none) 293
-g 290
-O3 153
-DTP_NO_THROW -fno-exceptions 304
-g -DTP_NO_THROW -fno-exceptions 303
-O3 -DTP_NO_THROW -fno-exceptions 112

I found it interesting that in the 2nd test case I did, removing exceptions actually increased the time it took to render the fractal!  Not quite sure why .. hmmm.  (I tried it a few times and kept getting similar results too.)

What is clear in the second test is that the compiler is able to optimize the code much more aggressively.  I guess Exceptions choke up the optimizer.  In all cases it seems that adding on the -g flag seems to make the code run slightly faster, surprisingly enough!  (-g adds in debugger info.)  In all cases, the optimizer was able to roughly double the speed of the program, and when I disable exceptions it is able to throw in even more speed.

-Phil

Seahorse Adventures – Loading TGAs (and more)

January 5th, 2010

Here’s a screenshot.  This is my Ubuntu desktop of my work on a new iPhone game.  Take a look at it nice and big.  Below I’ll explain all of what is going on …

bsa_dev1

In short, I’m working on porting my pyweek#3 team entry to the iPhone.  Here’s the details:

  • Top left, you see Kate, my text editor.  You’ll notice I’ve got -what appears- to be python.  But that’s actually tinypyC++ code!  My converter still has some rough edges, but it’s starting to get pretty good.  If you weren’t looking to closely you might mistake that for ordinary python code!  (In fact, it should be 100% python parser friendly.)  You can see how I have to use a touch of annotation to make it all go.  But for the most part, the types get inferred.  (The C++ outputted is about 2x as long, so I’m saving a ton of keystrokes!)
  • Top right, you see the level being painted.  It isn’t all working yet, but those are the basic tiles.  Interesting bit about loading the level, when I created this game I used my own level editor and library I made with pygame.  To save on disk and time I save all the levels to .tga files.  Since I’m targeting the iPhone I need an easy way to read the data from .tga files.  I don’t have SDL_image available, so a friend pointed me towards this great site.  It appears to have some awesome bits of code, including very simple and easy to use image loader that can load tga/png/jpg/etc.  I think it has the most painless interface I’ve ever seen for a C-based image-loader.
  • Bottom right you can see me working on tinypyC++.  As I’m working on BSA, I’m always finding new bugs in it.  Lately most of the bugs have been of the “add more graceful error handling” nature.  tinypy will point out what line (and character) an error happened on, but with a bit of extra work I’m able to add in some coherent error messages to tell the user what is going on.  In this case it was to inform the user of an undefined module name.
  • Bottom left you can see the startup of the game.  I’m using irrKlang for all my  game audio now.  It is not open source, but it’s “free” to use for free games, and the price is quite reasonable for commercial projects.  irrKlang is not portable to the iPhone yet, so I have to have a separate driver for my iPhone audio.

And that’s it for today’s report!

-Phil

New Year’s Python meme

January 4th, 2010
Hmmn, better late than never, ‘eh?
  1. What’s the coolest Python application, framework or library you have discovered in 2009 ?
    pygame – I’ve used it for ages, but I rediscovered it this year for a new use.  Now-a-days I use it for processing images (creating batches of icons, creating texture atlases, etc)
  2. What new programming technique did you learn in 2009?
    I’ve used databases for _ages_ in web development.  This year a friend suggested I could use databases to store data for games and 1. avoid recompiling 2. avoid parsing 3. use a nice database frontend to manage it.  I’ve only experimented with it briefly, but it seems like a pretty keen technique 🙂
  3. What’s the name of the open source project you contributed the most in 2009? What did you do?
    I was a bit of an open-source waste-of-space this year.  But in the last two weeks of the year I began doing work on my tinypyC++ converter.  So far I’ve used it to put one game on the App Store.
  4. What was the Python blog or website you read the most in 2009?
    Planet Python.  Thanks everyone 🙂
  5. What are the three top things you want to learn in 2010 ?
    How to do game PR.  How to present at conferences.  How to not go crazy.

Over the course of 2009 I used python much less than in 2005-2008.  This year (with the help of tinypyC++) I hope to be using (something like) python again.  C++ just isn’t nearly as fun!  I don’t plan on attending PyCon this year, though I wish I could.  There’s just a limit to how many conferences I can attend.  If anyone is at GDC, catch up with me!  I’ll be speaking at the iPhone Summit about multi-player network testing.  I always gotta thank the python community for introducing me to the magic of testing.  It’s what makes network code and mad projects like tinypy possible.

-Phil

How to run your Xcode universal binary under Rosetta on an Intel Mac

December 29th, 2009

Here’s the trick. First, build your universal binary, let’s say under Debug mode. Then from a terminal …

cd build/Debug
/usr/bin/arch -arch ppc MyApp.app/Contents/MacOS/MyApp

This will launch your app using the Rosetta PPC emulator. This way you can test your Universal binaries from an i386 system 🙂

I’m doing it this way, because for some reason the ‘Right Click on Your App > Get Info > General > Open using Rosetta’ checkbox is grayed out. Oh well!

-Phil

P.S. Another technique is to go into Project > Edit Project Settings > Build > check ‘Build Active Architecture Only’ .. Then you can change your active Arch to PPC and the build will only include PPC and will run.  Just be sure to uncheck the box before you send a build to your users.

Elephants! is free on the App Store!

December 23rd, 2009

My gift to you: A totally FREE iPhone game! I made this game several years ago with some other way-cool game-dev friends. In “Elephants!” you save the giraffes while jumping on a rolled up squirrel! More fun than a barrel of pigeons! For Christmas this year I figured I’d port it over to the iPhone for you 🙂 Check it out!

From the dev side, yeah, this is my first attempt at “python” on the iPhone. Even though it’s actually restricted tinypy code. Here’s a sample of game code so you get the idea of what’s behind this game. All this code is converted by tinypy into C++ code so I can compile it with Xcode for the iPhone:

def elephant_new(g:Level,pos:List(int))->Sprite:
    s = Sprite('elephant',pygame.Rect(43-14,8,28,48))
    s.rect.set_centerx(pos[0])
    s.rect.set_bottom(pos[1])
    
    g.sprites.append(s)
    
    s.ball = ball_new(g,(int(s.rect.get_centerx()),int(s.rect.get_bottom())))
    s.suit = ElephantSuit()
    s.vy = 0
    s.vx = 0
    s.jump = 0 
    s.facing = 'e'
    s.score = 0
    s.z = 1
    s.state = 'live'
    s.name = 'elephant'
    
    return s

Merry Christmas – Free game from Galcon.com – Elephants!

December 23rd, 2009

Our gift to you: A totally FREE iPhone game! I made this game several years ago with some other way-cool game-dev friends. In “Elephants!” you save the giraffes while jumping on a rolled up squirrel! More fun than a barrel of pigeons! For Christmas this year I figured I’d port it over to the iPhone for you :) Check it out!

Elephants! First python + pygame game submitted to App Store :)

December 19th, 2009

So, I managed to submit a “python” app to the App Store — “Elephants!” Here’s a few crazy things I had to work out to get things going:

  • I found that ObjC doesn’t care much for C++ objects that do their own reference counting.  To have a “Game” object at all, I had to use a pointer to my object instead of using my reference counting object.  It seems that during some of the “magic” of ObjC it copies objects without calling any of the C++ copying methods, so reference counting gets killed.
  • I ported a basic subset of pygame to tinypyC++ and made it work under openGL.  I don’t have this available in my tinypyC++ repository because it takes a good deal of prep-work to use (isn’t out-of-the-box) so it wouldn’t be generally useful to anyone yet.
  • I was able to get pause on call / resume working by saving the game state to a text file.  Since tab-separated files are so easy to create and parse in python this seemed to be the easiest route to getting the project done.
  • I learned a ton about C++ templates.  I still haven’t even touched the tip of the iceberg, and I’m not sure I want to, but at least I’m getting the basics down and that seems to be enough for me to stumble through this project with.

You can check out my current progress at svn://www.imitationpickles.org/tinypy/branches/tinypy2 (in the tinypy/example folder you can check out a julia fractal demo.  It also includes a mini pygame module that depends on SDL not OpenGL, so it actually works out-of-the-box.)

Here are some things I’ve been adding this week in preparation for my next project:

  • I’ve added “weak pointers” .. Since reference counting has the problem of cyclic references never getting collected, I had to do this for some use-cases.  In tinypyC++ weak pointers are just normal pointers, and if the object is collected, the pointer will be invalid, so be careful.  They are created by doing stuff like “x = ptr(GameData())”
  • I’ve added more C style types.  I’ve got uint16, cstr, Array, etc.  This all makes it possible for me to have a different kind of object – a struct in tinypyC++.  The struct is meant to be a C oriented type that can be saved directly to disk.  In Elephants I serialized via saving CSV data.  In the future, if I keep all the game state in C struct type data, I can just use a single simple line like “open(‘data.txt’,’wb’).write(struct_dump(game_data)”
  • I found that STL extensions include a “hash_map” which turns out to be about 2x as fast as the normal “map”.  I’m using that now.

I’m not entirely sure how useful this project is going to be for anyone else, or even for me for that matter.  But I think after my next game project I’ll have a much better feel for what the situation is.  TinypyC++ has some real tradeoffs in terms of being a bit of a hybrid of C++ and of python.  It doesn’t offer the full power of either language.  But I’m doing my best to capture a middle ground between them that will make my life easier.