Phil Hassey - game dev blog
Phil Hassey as Rambo
".. I've been there,
I know what it's like,
and I'll do it again if I have to."

Archive for the 'development' Category

Turkey Tomahawk Turbo

Sunday, December 1st, 2013

I’m pleased to announce Turkey Tomahawk Turbo!

I made it for the Charity Game Jam this year!

So check it out Windows or Mac or Linux! And now on the Web!

Have fun!
-Phil

SDL2 Tips, Tricks, and Workarounds

Tuesday, November 5th, 2013

It only took me about 3 days to get my framework working with all my targets: Windows, Mac, Linux, iOS and Android. I took an extra day to write my own simple mixer for WAV and OGG audio. And there might have been another day in there for other cleanup / fixes. So maybe 1 week total.

You can get SDL2 here. If you’ve used SDL before, you’ll find that it’s pretty similar, only it seems to work better, and now it’s got slick iOS and Android support.

You will want to follow the SDL 1.2 to 2.0 Migration Guide. And then for Android and iOS, read the README-android.txt and README-ios.txt as included in the source zip. I’m just writing up some tips here to help you along the way. I’m writing this with OpenGLES 1.1 in mind.

SDL2 for Windows, Mac, Linux

– Initializing your Window must be done in the right order. Basically, I call SDL_CreateWindow first, then SDL_GL_CreateContext. If SDL_CreateWindow fails with my preferred settings, I chose more fail-safe settings. After setting the mode I use SDL_GetWindowSize and SDL_GetWindowFlags to see if I got what I wanted. If things aren’t quite right, I use SDL_SetWindowFullscreen and SDL_SetWindowSize to try and request them again. (I always go out of fullscreen, set size, (maybe go into fullscreen), then set size again.

– As of SDL 2.0.1, Mac Retina displays do not work consistently. There is a flag for this “SDL_WINDOW_ALLOW_HIGHDPI” but I’ve found that if you ever change mode, or do anything, things seem to fall apart. If you aren’t messing around much, it might just work well enough for you.

– glu doesn’t seem to work anymore. So I had to switch over to using glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP,GL_TRUE); to generate my mipmaps. I examine the glGetString(GL_VERSION)) to make sure it’s >= 1.4 before doing that. And if I’m not on a new enough GL, I just don’t use mipmaps at all.

– Use stb_image to load your images. (I didn’t do that just for SDL2, but it’s a great tip!)

SDL2 for Android

I can’t believe how smoothly this went. (Recall, 2 months for NDK, 1 week for Marmalade .. this port took 1 DAY!!!)

– Follow README.android for the details.

– in AndroidManfiest.xml in the “activity” tag add android:configChanges=”orientation” , keeps your app from crashing. You may use other orientation tags to keep it in a single orientation, or whatever.

– If you use sockets, be sure to add these permissions “android.permission.INTERNET”

– Use SDL_rwops to read your own data files (which you have placed in the “assets” folder of your Android project.)

– If you want to use SDL2_mixer, you may need to edit SDL2_mixer/Android.mk and disable a few things.

– If you are using single touch, your mouse SDL code might work already, otherwise add support for SDL_FINGER* events (and filter out the touch events from your mouse code if (e.motion.which == SDL_TOUCH_MOUSEID) { break; }

– Be sure to call SDL_SetTextInputRect before SDL_StartTextInput if you are using key input. SDL_SetTextInputRect let’s you specify where on the screen the text is appearing so that SDL2 can shift the screen to keep the virtual keyboard from overlapping it.

– On suspend / resume I had to pause my audio.

SDL2 for iOS

– Follow README.ios for the details.

– SDL_SetTextInputRect doesn’t work. So you’ll need to capture UIKeyboardWillShowNotification and shift your screen to keep the virtual keyboard from overlapping it on your own.

– Unlike in Android, the orientation won’t change between portrait and landscape UNLESS you add SDL_WINDOW_RESIZABLE to your SDL_CreateWindow flags.

– Even though I added in SDL_iPhoneSetAnimationCallback, I got crashes when suspending my app. I also had to use SDL_SetEventFilter to capture SDL_APP_WILLENTERBACKGROUND and SDL_APP_DIDENTERFOREGROUND to set a flag to tell my callback to start / stop doing its thing.

Custom Mixer?

You might be able to use SDL2_mixer on all platforms. I did try it out for Android, and got it working pretty easily. However, I decided to write up my own mixer using SDL2 to stream the output. (This ended up only taking a few hours, and it keeps me from having to have SDL2_mixer as an additional dependency on all platforms.)

I used SDL_LoadWAV to load wav files and stb_vorbis to load and stream ogg files.

Good luck!
-Phil

Getting ENet to work with Marmalade

Thursday, August 8th, 2013

Through a bit of Googling and whatnot, I got in touch with Joe Delgado who was able to provide a patch to fix ENet to work with Marmalade. These are modifications to unix.c. When I am making a Marmalade build of my games, I always have PLATFORM_MARMALADE defined. So you can replace that with whatever you do.

After the #ifdef __APPLE__ segment, add this to set up the correct defines, etc.

#ifdef PLATFORM_MARMALADE
#define SOMAXCONN 128
#undef HAS_POLL
#undef HAS_MSGHDR_FLAGS
#undef HAS_FCNTL
#include <sys/select.h>
#include <sys/uio.h>
#define HAS_SOCKLEN_T
#endif

In enet_socket_send, it turns out the Marmalade sendmsg is broken. So I replace:

    msgHdr.msg_iov = (struct iovec *) buffers;
    msgHdr.msg_iovlen = bufferCount;
    sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);

With

#ifdef PLATFORM_MARMALADE
    // concatenates buffers together

    ENetBuffer * newBuffers;
    char* d;
    int i, totalSize;

    newBuffers = (ENetBuffer*)malloc(sizeof(ENetBuffer));
    totalSize = 0;
    for (i=0;i<bufferCount;i++) {
        totalSize += (buffers+i)->dataLength;
    }

    newBuffers->data = malloc(totalSize);
    newBuffers->dataLength = totalSize;
    d = (char*)newBuffers->data;
    for (i=0;i<bufferCount;i++) {
        memcpy(d, (buffers+i)->data, (buffers+i)->dataLength);
        d += (buffers+i)->dataLength;
    }

    msgHdr.msg_iov = (struct iovec *) newBuffers;
    msgHdr.msg_iovlen = totalSize;

    sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);

    free(newBuffers->data);
    free(newBuffers);

#else

    msgHdr.msg_iov = (struct iovec *) buffers;
    msgHdr.msg_iovlen = bufferCount;
    sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);

#endif

And that seems to get ENet working 100% with Marmalade. I applied this patch to ENet 1.3.6 … The original patch was written for ENet 1.3.3, and I suspect it would work for the latest version of ENet. I built this with Marmalade 6.3.2. I’ve passed on a request to the Marmalade team to fix sendmsg so that the larger chunk of the code would no longer be necessary.

-Phil

Dynamite Jack: Component Object model

Friday, April 20th, 2012

I’m gonna dig into some of the tech behind Dynamite Jack, so hold onto your seats.

So, a lot of devs are into Component Object game design. That article is by a friend of mine who goes into a good overview of a lot about the model. Anyway, you could probably spend all day reading the resources he links to. The short version (as I see it): Ideal Component Object game design is like a Normalized Database. It basically means, it’s kind of a chore to get it working but it’s super flexible and powerful.

I thought that was interesting. So I went to a talk at 360iDev by Gareth Jenkins. He demonstrated how to do component architecture with real concrete examples, which really helped me get my head around the idea. But the most profound bit of the talk was the end, where I remember him saying something like:

“It doesn’t matter HOW you do this, as long as you DO IT.”

That was super freeing for me. The idea that it didn’t matter how hacky I did it, but it would still give me all the benefits was very helpful. So here’s how I do the component object model in Dynamite Jack:

struct Entity {
  bool active;
  bool has_player;
  bool has_guard;
  bool has_light;
  bool has_position;

  int player_state;
  int player_cartridges;

  int guard_state;

  float light_angle;
  float light_radius;
  float light_degrees;

  float position_x;
  float position_y;
};

#define MAX_ENTITIES 64
Entity entities[MAX_ENTITIES];

Now, you’ll see the cool bit is that I have access to all data without creating anything, so no free / delete needed. The simple bit is activating a feature is just a matter of setting “has_light” to on or off. That’s how I actually turn on and off the player’s flashlight in the game.

In the game code, I just loop through all the items and dispatch to various functions for each component type.

void sys_loop() {
  LOOP_ENTITIES() {
    if (e.has_player) { player_loop(e); }
    if (e.has_guard) { guard_loop(e); }
    if (e.has_light) { light_loop(e); }
    if (e.has_position) { position_loop(e); }
  }
}

And I have a similar function for handling events, and painting the screen. It made it really great for prototyping the game and changing features. The “cave trolls” in the game (see at the start of the trailer) had their AI replaced quite a few times, and being able to just hack new things on and change things around without breaking my other entities was really nice!

One of the other nice things about having it explicitly in code, as opposed to “registering” things magically, is that I can see exactly in my code what order the components are being run in, so if something depends on something else, I can be sure they are in the right order.

Dynamite Jack has 20 different “components” but they all lie in the same big structure. Another cool one is having an “action” component, which doesn’t even exist in the game, it’s just a timer to trigger some future event. With everything being an Entity, it just gets it’s own loop called, and is able to do whatever.

So, yeah, my method gives me only a single Class, as many components as I like, and the flexibility to mix and match stuff. The power to toggle components on and off. And a fixed amount of memory used. So easy “save to file” style serialization of the game state.

Anyway, that’s the tech for the day. I definitely recommend component systems, it makes it SO EASY to try new things with your game, and be able to tweak them until they work “just right”.

-Phil

P.S. If you’re looking for the code on how to do this, it’s all in this post. It really can be THAT SIMPLE 🙂

How to create and play IVF / VP8 / WebM / libvpx video in OpenGL

Thursday, February 2nd, 2012

Disclaimer: this tutorial covers how to render IVF / VP8 / libvpx video in an OpenGL libSDL / SDL window. IVF video only includes video, not audio. For game developers, it’s trivial to play audio via their own audio system. So you’ll have two files per movie “movie.ivf” and “movie.ogg” or whatever. As an exercise to the reader, you could easily jam both into a single file if you really wanted to.

The Problem We’re Trying To Solve

So you’re an indie game developer and you want to show a clip of video in your commercial cross-platform (PC/Mac/Linux/other?) game! Obviously you want a patent-free open source unrestricted license to do it.

Wait, can’t I go commercial?

Better than that, you could just use the built-in codecs on a platform! I’d suggest this if you are targeting a single platform, iPhone / iOS for example.

Otherwise, you’ll be using Bink, a commercial solution at $8500 / platform. I emailed about their “indie licenses” and never heard back.

The Open Source Options I didn’t like much

Here’s what we have for patent free open source codecs .. and their various problems.

Xiph Theora – Probably the best known codec. To get it working you have to have libogg, libvorbis, and libtheora all built for your target platforms. To me, that seemed like a lot to ask. Also, the libtheora API is a MONSTER. playtheora is a SDL example (similar to this one) that covers some of that ugliness, so I’d recommend checking that out if you want to use theora.

Dirac / Schroedinger – the BBC funded codec. I couldn’t get this one to build. It doesn’t seem to be all that popular.

Motion Jpeg – This isn’t so much of a codec as an idea. Make your own movie file with a ton of .jpg’s in it. I tried this. The files get really huge really fast. I wouldn’t recommend this.

Motion JPEG 2000 – This implementation was also pretty confusing. I couldn’t find where to start. And, yeah, this isn’t all that popular either.

libvpx .. why I chose it

WebM / libvpx – Backed by google this is a new contendor on the block. The thing that sold me was the sample encoder which was pretty simple. It also depends on nothing. Also, building it on OS X and Linux was trivial. Also they offer a pre-built Windows binary. Also, they just had their 1.0.0 release a few days ago.

So, yeah, having a supported, up and coming, easy to build codec was key to me.

How to encode for IVF / libvpx

Since it’s a new codec, not much supports it right now. I used a fresh build of ffmpeg under linux that I built with this configure command:

./configure --enable-encoders --enable-libvpx

Then I was able to use ffmpeg to encode ivf files pretty easily:

ffmpeg -i Untitled.mov -vcodec libvpx -b 1000k -s 1024x512 movie.ivf

Note: we’re not dealing with WebM files. WebM files are container files that also contain audio. Again, you’ll have to store your audio separately, or create your own container file, or figure out what WebM is on your own time.

So .. what’s the bottom line? Do we get any code?

Yes! I created a libSDL player that plays back the video at max speed possible and it converts the YUV data to RGB data and loads it as a texture. Here are the functions I provide:

void playvpx_init(Vpxdata *data, const char *_fname) ;

Just init your Vpxdata with a filename “movie.ivf” .. It’ll try and get libvpx up and running for you.

bool playvpx_loop(Vpxdata *data) ;

Call this once per frame to have it decode a frame of video. It will return false once it has run out of frames. If you want to mess with the libvpx YUV data yourself, it’s data->img. See the playvpx.cpp source or the libvpx example above to see what that structure provides. It’s pretty simple.

int playvpx_get_texture(Vpxdata *data) ;

Call this once per frame to have it convert the YUV data to RGB and upload the texture to OpenGL. It will return 0 on failure or a OpenGL texture ID on success. I convert on your CPU, so it’s not super fast, but it should work fine on modern computers. If anyone cares to provide a Shader version of this function, or provide a SIMD / MMX / SSE version .. well, that would be faster!

void playvpx_deinit(Vpxdata *data) ;

Call this function when you’re done to cleanup.

Conclusion and Source Code

Okay, here’s playvpx for you to check out. It’s a C-style API, but I’m sure I use some minor C++ in there. Probably wouldn’t be hard to make it C-only if you require C for your project.

Oh, and I include the libvpx binary for Windows, OS X, and Linux. So you may not have to build it for any platforms!

The code is licensed under the libvpx BSD-style license. My code here is a gutted version of their sample_decoder.c, so .. that seems to make most sense to me.

Tough decisions, interesting beginnings

Wednesday, September 28th, 2011

So, if you’ve been following this blog for a while (like a year) you might recall last year’s “October Challenge” game called “Stealth Target” that I attempted to release as a paid beta game, which I then issued refunds for and then made a few vague efforts to revive and .. well ..

I mean, it looks, sort of okay. Those dynamic lights are neat stuff, man I learned a ton about OpenGL and tricks doing this game. The trouble is, since it is a 3D rendered game, when you stick it next to shots of (links to any recent Unity game on touchArcade left as an exercise to the reader) it looks awful. “Why is this dev even bothering?” Coupled with the fact that the interface was a bit kludgy using a mouse and at least twice as bad using touch, it just wasn’t a great fit for, well, anything sadly. To finish the project it would take me at least 3-4 more months of serious work and I don’t expect that I would be happy with the final result, so I had to kill it.

.. But I had written some keen code. And I still liked the game concept. So I thought about it a bit more. I had made another game a ton of years ago called Escape from Anathema Mines. It was a similar “dodge the guards” type of game with an overhead visual aesthetic that actually worked pretty well.

I thought it over and decided that with some of the GL experience I had acquired while working on Stealth Target, and by going in the direction of the overhead view that worked so well in that game, I could re-mix the two games together and create something new and exciting and simple enough that I could get it done. After just a few days of work I’ve already got a OpenGL / HD playable of Escape from Anathema Mines.

I’m going to extend the game with some of the bomb concepts from Stealth Target and maybe top it off with some other wacky features. This game is much easier to work on for the primary reason: it isn’t in 3D. Not being in 3D just makes rendering and working on it so much easier. One thing that also helped getting this up and running quickly was being able to reuse a ton of the code / algorithms that I had already written for Stealth Target.

I also been learning about the Object Component model over the past year and I’m using this game as my first attempt at it. I went to a talk at 360iDev (check it out) and got a very nice overview of the model. But the BIGGEST point he made that worked for me was when he said, “It doesn’t really matter how you do this, as long as it works for you. You won’t make a perfect model, so just make one that gets the job done and don’t feel bad about it.” Which was really liberating for me, I’ve always felt it was supposed to be some perfectly coded model, and being allowed by someone to just “get the job done” really helped. I was able to use the things I learned in his talk to help my code without having to do weird stuff that wouldn’t work with my style of coding. I have everything in a single structure named Entity. Really simple, but the thing I also do is have a bunch of bools like “has_light” “has_position” and then more members like “position_x, position_y, light_a” and so on. That way everything is always there (very C) but it’s component oriented (I can test if a component is there and take action on it if it is.)

Here’s the level editor, which is actually is very similar to the one for Stealth Target, only .. since the game is actually an overhead game, it was a ton easier to get working.

So, yeah. I’m enjoying doing this project. It’s actually my “hobby project” which means I’m only allowing myself to work on it during off-hours. I will probably attempt to monetize it somehow, but my main goal with this project is to satisfy my need to get these game ideas out the door and see how they come out. I’ve got my main work hours dedicated to some of the other commercial projects I’m working on this year.

Which I should talk about more soon. A lot more.

-Phil

From 0 to iCade in 3 hours 16 minutes

Tuesday, August 30th, 2011

Hey,

1. The Arrival and Assembly (30 min)

So my iCade arrived at 2:58pm today. It took me 30 minutes to unbox the parts and put the whole thing together with a hex-screwdriver. The completed item looks 110% win!!! There are tons of detailed unboxing guides on the internet, so I’ll just give you a shot of mine:

2. Testing it out with GAMES (30 min)

I had to check it out with a real game, so I went to the definitive touchArcade post on the subject. I realized I already had several of those titles on my iPad, so I dove right in with Velocispider which was totally awesome on the iCade!! I can only hope more devs add support! 30 minutes elapsed “fun time”.

3. Downloading the iCade SDK (1 min)

The “official” SDK is sort of useless, it’s just a manual telling us what we already knew. The great bit is there is an Open Source SDK (MIT) that is ready to go! I downloaded and unzipped that and began adding it into my project. 1 minute.

4. Being stupid (2 hours)

I then proceeded to brilliantly comment out the two lines of code that make the iCade code work. And then spend 2 hours realizing it. /facepalm

5. The iCade Integration (15 min)

Once I fixed my error, the integration took approximately 15 minutes. The bulk of the code was just a switch statement that converted the iCade SDK events to my own internal framework events. I already had keyboard support, so it was no trouble at all.

- (void)setState:(BOOL)state forButton:(iCadeState)button {
    int v = 0; unsigned char c;
    switch(button) {
        case iCadeButtonA: v=KEY_a; c='a'; break;
        case iCadeButtonB: v=KEY_b; c='b'; break;
        case iCadeButtonC: v=KEY_c; c='c'; break;
        case iCadeButtonD: v=KEY_d; c='d'; break;
        case iCadeButtonE: v=KEY_e; c='e'; break;
        case iCadeButtonF: v=KEY_f; c='f'; break;
        case iCadeButtonG: v=KEY_g; c='g'; break;
        case iCadeButtonH: v=KEY_h; c='h'; break;
        case iCadeJoystickUp: v=KEY_UP; c=0; break;
        case iCadeJoystickRight: v=KEY_RIGHT; c=0; break;
        case iCadeJoystickDown: v=KEY_DOWN; c=0; break;
        case iCadeJoystickLeft: v=KEY_LEFT; c=0; break;
    }
    Event e;
    e.v = v;
    e.c = c;
    e.type = state?EVT_KEYDOWN:EVT_KEYUP;
    game_event(e);
}

I also had to go ahead and add Universal (iPad) support to the game, this didn’t take too long as my framework has smarts for doing that pretty easily.

6. In conclusion …

I’ve submitted my update to the App Store, so hopefully it’ll be in your hands within a week.

In conclusion, integrating iCade into your iOS game only takes 15 minutes, unless you’re as stupid as I am. I encourage all devs who have appropriate games to do this so that I can play more games on my iCade!!! Go GO GO GO!

-Phil

tinypy2 musings

Thursday, June 2nd, 2011

So, my mind has been poking away at the idea of making a “tinypy2” that would be a bit less like python, so probably even more confusing for end users. Being only one sentence into my proposal here, and it already sounds bad. Well, here goes:

-1 All objects would be assigned and passed by value instead of by reference
=0 There would be a dictionary of global variables
+1 The VM state could be saved to readable JSON
+1 The VM state could be loaded from JSON
=0 The VM would be written in C++
+1 The VM would have super-easy interoperability with C++ code
-1 The VM would be on the slow side

Tallying up the pros and cons, we get to a +1 for this idea. I don’t suppose there’s much way for anyone to comment on if this sounds like a good idea or not, but thos are some of the thoughts going around in my head right now. It seems like it would be an interesting rudimentary scripting language. The load / save of VM state and C++ interoperability are the key points.

#badideas ??

-Phil

The Galcon Office 2011 Edition

Thursday, June 2nd, 2011

So, hey, we recently (3 months ago) moved to “the goat ranch” and I finally got around to decorating my office. Since moving in, I’ve released one game and I’ve got three (or so) in the works. So a lot of stuff is going to be happening here this year!

Everything in that picture has got some sort of anecdote behind it, so if you’re curious about anything, just ask 🙂

-Phil

Invasion of the Blobs & dev toolkit in the works

Friday, May 20th, 2011

Hey,

A few weeks ago I entered the Ludum Dare game development contest and whipped together a fun game about defending off invading blobs using a spray can.

I spent another week getting it polished up so it works on a ton of platforms. The game is “The Invasion of the Blobs” (iBLOBS for short). You can get it here. It’s available on iPhone/iPad, Android, PC, Linux, Mac, and pretty soon the Mac App Store.

The reason for the porting frenzy with this game is I’m working towards releasing an open source C++ toolkit for supporting all these platforms (and maybe a few more). This is my first game release with this kit. It uses code from all my recent games, but it finally puts that code into a clean and organized re-usable structure. This is going to be super helpful for reducing bugs and improving game code across each platform.

Anyway, I hope you enjoy iBLOBS. It’s totally free, so you might as well give it a whirl. If you want to help out, please post a message here if there are any crashes or support issues on any platform, I want to get those ironed out best I can 🙂

Have fun!
-Phil

UPDATE: The Android port has been giving quite a few people trouble. If you are a dev with the Android dev kit, please do an “adb logcat” and post the results here, that would be a huge help!

UPDATE2: The Android build is so broken I took it down.