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

Archive for the 'Uncategorized' Category

Galcon 3 Teaser Trailer

Friday, October 20th, 2023
Galcon 3

Wits & Wagers Halloween expansion

Saturday, November 2nd, 2013

Hey,

For Halloween Nan and I (well, mostly Nan, but I did come up with at least a few of the questions) came up with an expansion for the game Wits & Wagers!

You can download the pdf WitsAndWagers-Halloween. Print out page one, flip to back, print out page two. (Double check alignment, the pumpkin question should have the long answer on the back.)

-Phil

Goats in Utah!

Thursday, October 24th, 2013

A couple weeks ago Nan and I went on a goat vacation to Utah. It’s a super cool place to go hiking! Here’s three of my favorite pics from the trip:

Goblin Valley is totally amazing!

Spookey Canyon is super weird!

Cuzco says, “I’m the best!” while hiking on Escalante.

Petunia and Nubbin just hanging out on slot-canyon walls in Willis Creek.

Headin’ back.

Anyway it was a great time, we had a ton of fun. And the other day we bought a new goat hutch, it looked like a UFO in the back of our truck and a ton of people were staring while we spent the day in Pueblo driving around with it.

Goat hiking is fun!
-Phil

The 2011 Re-Cap: Five games in one year!

Friday, January 6th, 2012

Ahoy there! 2011 was a great year! Here’s a re-cap of the games I released and some final thoughts on ’em!

First of was The Invasion of the Blobs which was my Ludum Dare #20 entry! I had a blast making this game as part of the jam. I used this game as a way to work on my ports to Android, iOS, PC, Mac, Linux and distributed the game on all of them. I however, had to pull the Android version after a few hours because it was having so many technical problems. This caused me to decide to put further Android dev on hold for 18 months, until the platform has matured enough for me to be able to easily port things to it without going totally crazy. I’ll probably use Marmalade for future ports to Android. iBLOBS got around 25k downloads between the Mac and iOS app stores.

Next up was The Exterminator which was a game I made along with several teens to raise money to build a community outreach center. This project was a total blast, we spent two days working together on it, and then I spent a few more days spit shining the menus and adding in basic Game Center support. The release got a bit of coverage on 148Apps but no other iOS press that I know of. However, it did get some great local coverage in Colorado! This was pretty great, because, really, the game sold only a couple hundred copies, barely enough to cover the iOS dev fees. But it help raise awareness in Colorado and got at least one sizable non-profit interested in contributing a significant amount of money to the project (this is still in their approval process, so we don’t know for sure if that will come through or not.) Whatever the case was, it was a fun project, and it was a great excuse for me to buy an iCade ๐Ÿ˜‰

And then there was Chickon which was most definitely the most silly project I went into this year. I intended for this project to take a couple of weeks but it ended up taking about 6 months .. but I’d hardly call it really hard-serious work type 6 months. In the end, Chickon was an amazing PR success. touchArcade gave it 3 or 4 articles featuring all the goofy stunt videos I produced and reviewed it. The game has not seen a ton of in-app-purchases, but people who have played it have enjoyed it. I think this project was something of a success just for keeping my name in the ear of the press. At least they know I still exist! And I’m still doing something! I also tried a ton of different Galcon gameplay features in this game to see what worked and what didn’t. Since I am thinking about doing another Galcon sequel in the future, this game helped me eliminated about half a dozen really bad ideas ๐Ÿ™‚

And then I worked on my new game Anathema Mines. The beta mentioned above was a very limited private beta, though I may expand it more in the future. This game’s is explained a bit more here where I go into how it’s kind of the 4th rebirth of a game concept I’ve been working on for about six years now. I’m really happy with how it’s coming together and the next 2-3 months are going to be dedicated to finishing this game and giving it the best launch possible!

Lastly, I wrapped up the year having a blast creating Nobody Wants Kitty for Ludum Dare #22. The game is about a cat who nobody loves because it’s so ugly. The cat has to upgrade to being pretty over the course of the game. I had a fun time making this and I got to learn a bit more about creating flash games, which is really one of the best ways to prototype anything now-a-days!

Anyway, it’s been a great year! Thanks a ton for playing my games!

-Phil

Adding Retina / Multitasking support to my iOS apps

Tuesday, November 30th, 2010

Today I felt it was about time I got around to updating my Galcon apps with proper 4.x support now that everyone has it.

Adding retina is pretty easy. In EAGLView.m I had to add this snippet into initWithCoder:

	float scale = 1;
                
        if([[UIScreen mainScreen] respondsToSelector:
            NSSelectorFromString(@"scale")])
            {
             if([self respondsToSelector:
                  NSSelectorFromString(@"contentScaleFactor")])
                  {
                     scale = [[UIScreen mainScreen] scale];
                      self.contentScaleFactor = scale;
                 }
           }

Then in my code anywhere where the scale matters, I use that information to sort things out. I found that adding retina Icons, startup graphics, and other in-game graphics was as easy as adding an extra file: Icon.png becomes Icon@2x.png, my_game_stuff.png becomes my_game_stuff@2x.png, etc. It was pretty simple. Fonts were a bit more complex because I have different font data for each sized font, so I use the scale information I discovered earlier to ensure that I use entirely different font images, instead of using the @2x trick. The one goofy bit was importing to subversion. It doesn’t work, unless you put a trailing @ at the end of the filename, since subversion treats @ as the version identifier.

Doesn't work:
svn add Icon@2x.png

Works:
svn add Icon@2x.png@

Multitasking was even easier. In my AppDelegate.m I added these methods:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    game->save();

    Event e; e.type = EVT_SUSPEND;
    game->event(&e);
    [glView stopAnimation];
    
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    Event e; e.type = EVT_RESUME;
    game->event(&e);
    [glView startAnimation];
}

The first is called when the app is suspended, the second is called when the app resumes. The iOS handles saving / restoring all the texture data, so really I didn’t have to do anything. The only catch was I had to add in the glView stop/start calls to ensure that no GL calls were made while the app was suspending. The app will crash if any GL calls are made while in the background.

I do not do any background work to keep the network alive. This seems sensible because it makes it so the game will timeout after 30 seconds but you’ll still be connected if you get back sooner than that. Anything fancier could keep a player on the network indefinitely even if they are really gone. This gives the user at least a momentary opportunity to duck away and check something then resume playing.

-Phil

Android Day 3: Packaging, Assets, JNI, and OpenGL

Thursday, July 22nd, 2010

I considered using SDL for this port, however, I became concerned that none of the ports were quite ready for prime time. None of them have been really released as complete and stable packages, and there are enough weird things about Android that I think I’ll be better off doing the work directly myself. Galcon is an “OpenGLES” app in essence, so much of what SDL provides is unnecessary anyways. But if you are interested:

There is a summer of code project relating to this:

http://socghop.appspot.com/gsoc/student_project/show/google/gsoc2010/sdl/t127230762779
http://hg.libsdl.org/SDL-gsoc2010_android/summary

And there’s also another SDL port here:

http://www.anddev.org/code-snippets-for-android-f33/sdl-port-for-android-sdk-ndk-1-6-t9218.html

Step 1 – Using command line tools instead of the Eclipse IDE:

I also decided that avoiding Eclipse might be a good move. I’m sure there are those of you who would argue otherwise. But, err, I’m a CLI kind of guy, so we’ll see how it goes.

First I added ~/android/tools to my path, so that I wouldn’t have to keep typing in the whole path ๐Ÿ™‚

In my Galcon android folder, I ran this command:

$ android create project -t “android-4” -k com.igalcon.galcon -a Galcon -n Galcon -p .

Which created my other project files.

Then to create a debug build of Galcon:

$ ant debug

Then to install it onto my device:

$ adb devices

List of devices attached

emulator-5554 device

deviceid device

$ adb -s install bin/Galcon-debug.apk

And the app is installed, and I can run it. However, at this point I’ve just got a Hello World thing showing up, so I’ve got a long way to go until I’ve got Galcon appearing ๐Ÿ™‚

Step 2 – Including resources (graphics, audio) with your game:

There are a number of options as to how to bring data long for your game. A few are explained on this page:

http://developer.android.com/guide/topics/resources/providing-resources.html

I made a folder called “assets” and placed all my game assets in it. Instead of mp3s, I include ogg files. And instead of .wav, I include ogg files. On the Android handhelds, there is only 256 MB of internal storage. Many games just pack the binary and then download the data separately onto the users flash card. I deem that to be totally unawesome and will ship Galcon with all its data. But I will do my best to pack as little data into my binary as possible. By using oggs instead of mp3s and wavs, I’ve trimmed a couple MB off my data size.

UPDATE: App can request to be stored on the SD card! http://developer.android.com/guide/appendix/install-location.html

To do this, add android:installLocation=”preferExternal” to the manifest tag in AndroidManifest.xml .. And while you’re at it, add in <uses-sdk android:minSdkVersion=”4″ />ย to require OpenGLES 1.1 support. Also change target=android-8 in default.properties. ย This will give a warning since your minSdkVersion and your target aren’t the same. ย Just read that link above for more info.

If you save your files in “res” folders, some kind of Android magic kicks in and it seems you can’t reference anything by a String. You have to use Java IDs, which makes it really hard for C code to say “get me file X” .

Files saved in the assets/ directory are not given a resource ID, so you can’t reference them through theR class or from XML resources. Instead, you can query files in the assets/ directory like a normal file system and read raw data using AssetManager.

At this point, I’ve got a basic project building, and I’ve got assets included in my package. (I can tell this because my package is 3MB, not 200k like a empty Hello World example.) I think 3MB is an acceptable size.

Step 3 – Debugging the game:

Next I need to figure out how to get debugging working. I’m pretty sure I’m going to have bugs, so .. doing on-device debugging will be ideal. Again, if I were to take the wimp’s way out, I’d use Eclipse (I guess? for me actually, Eclipse seems like a greater learning curve..) but I’ll be using CLI methods to debug. I’ve edited Galcon.java and added a Divide by Zero bug, so I can see how it appears. And upon installing it, it crashes.

As a side note, to replace an app you’ve already installed, this command:

$ adb -s install -r bin/Galcon-debug.apk

Error that appears on my device: “Sorry! The application Galcon (process com.galcon.igalcon) has supped unexpectedly. Please try again.”

To debug:

$ adb -s logcat

And I get to see a lovely dump of errors as I have them:

E/AndroidRuntime( 1960): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.galcon.igalcon/com.galcon.igalcon.Galcon}: java.lang.ArithmeticException: divide by zero

Here’s a link to a page that talks more about adb, getting a shell on the device, and other fun goodies:

http://developer.android.com/guide/developing/tools/adb.html

Step 4 – Getting Java to call C functions:

Now I’m going to try and get Java to call out to the C / C++ code I built yesterday. At this point I’m going to send a thanks out to James Brown (Ancient Frog) who lent me a few lines of his attempt at an Android port. There are lots of tutorials and documentation on-line for JNI stuff, but seeing real code that is in the ballpark of what I want to do is a huge help. I’ll be posting a few snippets as I go in this blog, but if you do want to really learn about JNI, there is a ton of information.

First of all, in Galcon.java, in my Galcon class, I’ve sprinkled a handful of references to native functions:

public native void init();
public native void loop();
public native void paint();

In onCreate() I’ve added a call to init().

And then I created a myjni.cpp file which I filled with templates like this. I love all the ludicrous namespacing. I’m not sure who it is helping, but I’m pretty sure it isn’t me.

JNIEXPORT void JNICALL Java_com_galcon_igalcon_Galcon_loop(JNIEnv* env) { /* do stuff here */ }

After building and attempting to run I get this error from logcat:

W/dalvikvm( 2168): No implementation found for native Lcom/galcon/igalcon/Galcon;.init ()

I definitely need to add myjni.cpp to my jni/Android.mk and re-run ndk-build.

Tip: if you want to do some logging to the Android message log:

#include
#define MYLOG(msg) __android_log_write(ANDROID_LOG_ERROR,"MYLOG()",msg);

Seems to do the trick.

I’m still getting the error, so I think my .so isn’t being loaded. I add this before I call init to load the shared library:

System.loadLibrary("igalcon2");

I get a NEW error:

E/AndroidRuntime( 2255): java.lang.UnsatisfiedLinkError: Library igalcon2 not found

I guess libigalcon2.so isn’t being packaged. Gotta check into this. An unzip -v of the package reveals that libigalcon2.so is being included in the package. But I found this error in logcat:

W/dalvikvm( 2338): JNI_OnLoad returned bad version (0) in /data/data/com.galcon.igalcon/lib/libigalcon2.so 0x449e1260

I guess I need to make sure I’m returning the right version in my JNI_OnLoad function. This is my function:

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
  JNIEnv* env;
  if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
      MYLOG("JNI_OnLoad(): GetEnv failed");
      return -1;
  }
  return JNI_VERSION_1_4;
}

That seemed to work fine. So I’ve got JNI up and running and talking to my C code. I was able to get my various JNI functions calling my Galcon functions with no trouble.

Step 5 – Setting up an OpenGL context in Java:

logcat reveals that I’m getting a TON of OpenGLES errors similar to: “E/libEGL ( 2463): call to OpenGL ES API with no current context (logged once per thread)” .. This is pretty self explanatory. Time to figure this one out.

This page seems to reveal how to set up an OpenGL context:

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.html

And this seems to be how to set up and OpenGL renderer:

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/CubeRenderer.html

Sort of bodging those together got me pretty far. At least, I know my GLES code is being called and I’m not seeing errors.

Step 6 – Getting C to call a Java method (to load a texture):

I gotta get my texture images loading up so that my paint code is rendering something a bit more interesting to the screen. In this case instead of Java calling C, I need my C code calling Java code. So it’s like JNI in reverse. Or something. Here’s the documentation on doing just that:

http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jniref.html#call

You’ll note that no matter how we do this, we gotta have access to an “env” or something. I’m going to set up some kind of awful global variable that will be available to all my code so that I can use “env” to do stuff like this. I put this at the top of my JNI calls:

JNIEnv *_my_jnienv = 0;
void set_jnienv(JNIEnv *env) { _my_jnienv = env; }
JNIEnv *env *get_jnienv() { return _my_jnienv; }

And added set_jnienv(env); to the top of each call. Now in my other “driver” code I can call get_jnienv() to get it back.

Here’s my dummy load_texture method on the Java side:

    public static int load_texture(String fname) {
        Log.v("load_texture",fname);
        return 0;
    }

Here’s my C function that calls it:

int jni_load_texture(const char *s) {
    JNIEnv *env = get_jnienv();
    jclass cls = env->FindClass("com/galcon/igalcon/Galcon");
    jmethodID mid = env->GetStaticMethodID(cls,
	       "load_texture",
	       "(Ljava/lang/String;)I");
    // there could be some exception handling happening here, but there isn't
    jint ret;
    jstring mystr = env->NewStringUTF(s);
    ret = env->CallStaticIntMethod(cls, mid, mystr);
    return ret;
}

Pretty gruesome, but it seems to get the job done. Now if I can fill in my java load_texture method with something that works, I think I’ll have visuals! Here it is:

import android.graphics.BitmapFactory;
import android.graphics.Bitmap;
import android.content.res.AssetManager;
import android.opengl.GLUtils;
import android.opengl.GLES10;
import java.io.InputStream;
import java.io.IOException;

// gl is a GL10 instance, grabbed from within my renderer.  app is my Galcon Activity.

    public static int load_texture(String fname) {
        Log.v("load_texture",fname);

        AssetManager am = app.getAssets(); //new android.content.res.getAssets();

        try {
            InputStream stream = am.open(fname);
            Bitmap bitmap = BitmapFactory.decodeStream(stream);
            int[] textures = new int[1];
            gl.glGenTextures(1, textures, 0);
            int textureID = textures[0];
            gl.glBindTexture(GL10.GL_TEXTURE_2D, textureID);

            // no mipmaps
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);

            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

            return textureID;
        } catch(IOException e) {
//             Log.v("load_texture:open() fail");
            return 0;
        }
    }

Not trivial, but this saves me from having to decompress the files in C land. I currently don’t have any image decompression code that I use regularly so this works for me.

App Store pricing

Thursday, April 29th, 2010

Galcon Fusion is currently priced at $8 on the App Store. I originally had a longer post written, but I think this App Store user review says so much about the psychology of pricing and the values on the App Store that I really can’t think of anything to add to it.

“The price stinks, but it’s worth double!” – Jacques P.

Ludum Dare 2010 Keynote (starring Cuzco the Goat!!!)

Friday, April 23rd, 2010

See the Ludum Dare 2010 Keynote:

Inviting all python game-devs! Even if this notice is coming too late, we’ve got a compo coming in August, December, and mini-compos every month! Just check out the website and join the fun!

-Phil

Multi-hour AMX sketch

Friday, April 16th, 2010

Man, I’ve been having fun with this iPad ๐Ÿ™‚

IMG_0005

This image took a couple hours to draw. The AMX was much harder because I couldn’t just sloppy out whatever, I had to use straight lines and try to get it looking like the original. So being “less creative” is really quite a bit harder.

-Phil

48+ minute drawing “swamp”

Thursday, April 8th, 2010

Got a bit inspired by Monkey Island 2 swamps for this one …

IMG_0004

Again, iPad + Sketchbook Pro + Pogo Sketch Stylus = Fun!

-Phil