Archive for the 'Java' Category

48h Global Game Jam 2012: Run Or Gun

Last weekend I participated in the GGJ12 48 hour Game Jam.  It was my first game jam ever so I didn’t know what to expect. I knew It looked like a lot of fun and a lot of hard work rolled into one weekend but I didn’t expect was the amount of motivation that I would feel after it.  Motivation that is helping me push through some of the background coding that GunCore needs.

Needless to say, I was unprepared. Before the theme was released everyone was showing off their already partially completed games, code foundations that had everything already working but the levels, half completed projects brought in for the jam, frameworks and engines that did most of the game making process for them; GameMaker etc.  But with a pretty much blank slate Matt and I picked up a solo artist and got the help of a floater sound producer and got to work.

Team Lazorun:

Orun Irunmale – Programmer
Matt Lazaridis – Game Designer / Level Editor
Marko Hadzi Nikolov – Artist
Ryan Henwood – Music / Sound

GGJ Theme: Ouroboros

The theme was a image of an ouroboros to be interpreted any way we wanted it to. Matt was the man with the plan who decided to make a 2 player game where your efforts to win come back to haunt you later on down the road, causing some form of strategy to be used to come out ahead. With that idea I began coding and having Matt as my peer programmer made the process go smoothly. While I rushed to build the gameState engine to coordinate the different game modes, graphics engine for drawing all of our objects, collision, keyboard and mouse inputs and a simple hardcoded level editor, Matt continuously tested and tweaked my code to help perfect timings, variables and algorithms, coordinate with our artist and sound guy, remind me of the game mechanics that I should be focusing on and also the occasional, “Good Job, man”.

With really, no time to spare, we completed our game, Run Or Gun.  The video below shows it in action and it can be downloaded from the Global Game Jam site or directly through this link.

After it’s all said and done I find myself looking for the next jam. I now understand why it is so fun to make a game with the, “get er done”, philosophy. I didn’t have to worry about my cohesion or coupling, my data structure decisions or design. I just got to build. Like lego without instructions. Felt good.

Advertisements

Letting Others Play My Game

GunCore is my first game. Every mistake I’ve ever made in game development, I’ve made on GunCore. Despite my follies, through thick and thin, each month the game continues to grow and it’s finally able to be played outside of my Eclipse IDE.

I made a build a week ago and send it to 5 friends to give it a quick test.  Naturally, it was a disaster. The game is too early in development to be sent to someone without me beside them guiding them away from the incomplete sections.  As I answered my friends questions I realize that my prototype/feature priority needed to be changed. I need to focus more on patching the holes in my prototypes to allow the player to experience and critique the gameplay experience rather than the being lost in incomplete game states.

Since than I’ve been doing just that.  I’ve been cleaning up old test levels, rebalancing player and enemy attributes and temporarily removing all unnecessary, incomplete features.  My goal is to get an alpha build ready and start the play test phase of development.  GunCore is still far from alpha ready but at least it’s heading in the right direction.

New Test-Level Gameplay Video

Just in time for Screenshot Saturday 38.

This level uses the snap-to-grid feature to allow levels to feel more consistant with my old art. Also the new ImagePool class lets me fill the screen with many similar images with little performance difference. Now I don’t feel guilty with flooding the screen and building things out of objects for aesthetics and not just gameplay. I still consider a lot of the gameplay still in early development but here is a test level where timing the melee slash and enemy reload is the key to staying alive.

I whipped up these enemies last night while playing hours of DOOM on my iphone, dancing around imps with dual stick controls.  I liked in DOOM how an enemy’s corpse sticks around to remind you, on return trips, how hard you own (and that you’ve been there before) so  I added corpses to my new enemy monster.  They add the atmosphere I’m looking for but I’m not sure if they’re a final version feature.

Check out the video to see what I’m talking about.

ImagePool Singleton Class

While working on GunCore, Matt and I have been wearing many hats; The designer, programmer, marketing strategist, artist, sound designer, webmaster, and blogger. Because of this rush, I’ve been neglecting some of my code where I’m just programming and not software engineering and I regret it every time I have to modify them.

I’ve been applying to new graduate software eng jobs lately and it really was the excuse I needed to spend more time with the software eng textbooks I refused to sell.  I have been wanting to iterate through some of GunCores code anyway and now I can practice what I’m reading and make GunCore more efficient at the same time.

To start off I’d like to share my ImagePool Singleton Class, its implementation, problems I faced and am still facing and most importantly, the things I think I’m doing correctly but might not be.

Previously in my game each instance of a game object had all of the images associated with it. When an enemy class was created, its image would be loaded and stored in memory. This way, 10 monsters with 20 images for their animation each, will be 200 images in memory; all of which are copies of just 20 unique images.

At first I was just going to declare all of the game’s images at the initialization of the application and make every game object just point to the image they want to display. Now the same image won’t be repeated in memory but as levels and especially chapters change, lots of images will never be used again or will never be used at all.  This looks like a job for a Object Pool.

I wanted to be able to:

  • Store all images in one place
  • Have the ability to dynamically add images
  • Check for and eliminate copies
  • Remove images that haven’t been used recently
  • Provide global access to the entire application

An Object Pool design pattern allows me to encapsulate all the images, check for expiry and copies and a Singleton design pattern enforces the one and only instance of the pool that I will need, as well as global access through out the application.

Here is the implementation that I’m working on. I’m at the point where it’s working, I don’t have any crashes, but I do have some concerns.

//Singleton Object Pool for storing images.
public class ImagePool {

	private static ImagePool instance = null;
	private static HashMap<String, ImageHolder> imageMap = new HashMap<String, ImageHolder>();
	private static int mapSize = 0;
	private static final int expiryCutOff = 1000;
	private static int expireTimer = 0;
	private static int checkTimer = 0;
	private static int checkRate = (int) expiryCutOff / 10;

	private ImagePool() {

	}

	private static class ImagePoolHolder {
		public static final ImagePool instance = new ImagePool();
	}

	public static ImagePool getInstance() {
		return ImagePoolHolder.instance;
	}

	// Returns the image to the string imageName is referencing
	// with rotation and brightness attributes
	public static Image getImage(String imageName, int rot, float darkness) {
		String image = imageName;
		// Force the rotation angle to 0-360
		rot = rot % 360;
		if (rot < 0) {
			rot = 360 + rot % 360;
		}
		// Create unique key for each unique image
		String imageID = imageName.concat("" + rot + "" + darkness);
		// Add new images or update old ones.
		if (!(imageMap.containsKey(imageID))) {
			ImageHolder imageHolder = new ImageHolder(initImage(
					ImagePool.class.getResource(image).getPath(), darkness,
					rot, Color.RED), expireTimer);
			imageMap.put(imageID, imageHolder);
			mapSize++;
			System.out.println("ADDING   imageCount: " + mapSize
					+ " imageID: " + imageID);
		} else {
			imageMap.get(imageID).updateFrames(expireTimer);
		}

		return imageMap.get(imageID).getImage();
	}

	// Called externally every frame. In case of slow computers,
	// using real time will expire objects early so using frames instead
	public static void checkExpiry() {
		expireTimer++;
		checkTimer++;
		// Because this method will be called every frame, the checkRate allows
		// control of the checkExpiry frequency.
		// Currently set to 1/10 of the expire time.
		if (checkTimer > checkRate) {
			checkTimer = 0;
			Set<String> set = imageMap.keySet();
			Iterator<String> iter = set.iterator();
			ArrayList<String> keyList = new ArrayList<String>();
			// add all expired keys into the keyList.
			for (int i = 0; i < set.size(); i++) {
				String s = iter.next().toString();
				if (imageMap.containsKey(s)) {
					if (expireTimer - expiryCutOff > imageMap.get(s)
							.getFrames()) {
						keyList.add(s);
					}
				}
			}
			// Remove all images that have expired keys that are in
			// the keyList
			for (int i = 0; i < keyList.size(); i++) {
				if (imageMap.containsKey(keyList.get(i))) {
					imageMap.remove(keyList.get(i));
					mapSize--;
					System.out.println("REMOVING imageCount: " + mapSize
							+ " imageID: " + keyList.get(i));
				}
			}
		}
	}
}

^ ImagePool Class Source. Edit: I changed the Singleton structure to be more thread safe using the Bill Pugh design.

Let me break it down.

I start with a HashMap called imageMap. I needed a data structure with unique keys and because of the high amount of insertions and deletions, as images expire and are remade, a hashMap seems slightly better then its ordered brethren, the linkedHashMap.

Each unique image needs a unique key and hashMaps always have unique keys so I can check for similar images by checking if the key exists or not.  For a key I decided to use a String that holds the image’s path + rotation degree + brightness which are all the variables to defining a unique image.  Any other image modifiers will have to be done in the art phase and become a separate PNG or I’ll just have to concatenate another variable onto the String. For GunCore, I don’t expect to.

The values for the HashMap imageMap are images but I had to wrap them in a class with an expiry date to track images which have not been requested recently for removal. The ImageHolder class wraps the images.

//ImageHolder Class is created in line 37 of the ImagePool
//Wraps an image with an expiry date so that old images can be removed
public class ImageHolder {

	private Image image;
	private int expireFrames;

	public ImageHolder(Image i, int e) {
		image = i;
		expireFrames = e;
	}

	public Image getImage() {
		return image;
	}

	public int getFrames() {
		return expireFrames;
	}

	public void updateFrames(int f) {
		expireFrames = f;
	}

}

^ ImageHolder Class Source

Every object can be drawn by calling ImagePool like this:

//Global classes can call for an image like this
g2d.drawImage(
	ImagePool.getInstance().getImage(f.getImageName(), f.getRotation(), F.getBrightness()),
(int) f.getX(), (int) f.getY(), this);

^ Game Class Draw Method

Every time getImage is called with a path, rotation and brightness the HashMap checks the key and then either finds it, updates the expiry date and returns the image associated with it’s key, or doesn’t find it and creates it, stores it and returns it.  The goal is to minimise the creating and storing parts.

	public static Image getImage(String imageName, int rot, float darkness) {
		String image = imageName;
		// Force the rotation angle to 0-360
		rot = rot % 360;
		if (rot < 0) {
			rot = 360 + rot % 360;
		}
		// Create unique key for each unique image
		String imageID = imageName.concat("" + rot + "" + darkness);
		// Add new images or update old ones.
		if (!(imageMap.containsKey(imageID))) {
			ImageHolder imageHolder = new ImageHolder(initImage(
					ImagePool.class.getResource(image).getPath(), darkness,
					rot, Color.RED), expireTimer);
			imageMap.put(imageID, imageHolder);
			mapSize++;
			System.out.println("ADDING   imageCount: " + mapSize
					+ " imageID: " + imageID);
		} else {
			imageMap.get(imageID).updateFrames(expireTimer);
		}

		return imageMap.get(imageID).getImage();
	}

^ ImagePool Class Source

Now that I have the expiry date updating I need a method to check them all and remove the expired ones. The expiry date timer does not use real time to expire images.  For fun I tried to run this game on my netbook which looks like it’s running at about 10 frames a second. If I used real time, that slow computer would be even slower as recently used but infrequently used images are expired and replaced over and over again.  If instead I use a frame counter, slower computers will hold the images for the length of gameplay I intended.

I decided to encapsulate this expiry frame counter in the imagePool class, calling checkExpiry every frame and making it only really check the HashMap for expired images a fraction of those times. Alternately, I could just not call checkExpiry every frame and decide when to in the already crowded main game loop’s class. The first way allows me to stay on one page of code and not bounce around so I choose it.

Currently the rate of checking for expired images is 1/10 of the time allowed before an image expires. This seems to be a fair assumption for now. The real rate would be the optimization of performance and memory management. A challenge for another day.

	public static void checkExpiry() {
		expireTimer++;
		checkTimer++;
		// Because this method will be called every frame, the checkRate allows
		// control of the checkExpiry frequency.
		// Currently set to 1/10 of the expire time.
		if (checkTimer > checkRate) {
			checkTimer = 0;

^ ImagePool Class Source

The checkExpiry method iterates through the whole hashMap and stores all expired keys into an arrayList and then deletes all the keys in the arrayList out of the hashMap.  When I tried to delete the keys from the hashMap on the fly I was having null pointer errors as I assume were caused by removing images while iterating through.

</span>
<pre>// add all expired keys into the keyList.
			for (int i = 0; i < set.size(); i++) {
				String s = iter.next().toString();
				if (imageMap.containsKey(s)) {
					if (expireTimer - expiryCutOff > imageMap.get(s)
							.getFrames()) {
						keyList.add(s);
					}
				}
			}
			// Remove all images that have expired keys that are in
			// the keyList
			for (int i = 0; i < keyList.size(); i++) {
				if (imageMap.containsKey(keyList.get(i))) {
					imageMap.remove(keyList.get(i));
					mapSize--;
					System.out.println("REMOVING imageCount: " + mapSize
							+ " imageID: " + keyList.get(i));
				}
			}

^ ImagePool Class Source

I’ve noticed that if I load a level and immediately load a different one, both level’s images will fill up the hashMap and zero frames of expiry time will pass.  After about 10 levels I can fill up the hashMap and cause a full heap error.

To combat this I clear the hashMap of all images before every level load but a level with to many different images being requested at the same time could still crash the game.  Maybe I’ll add a max size to the hashMap to catch overflow.

As the game runs I get a list of added and removed images as they are requested (and are not available) and expire.

Printout of ImagePool actions

That’s my first attempt at an ImagePool. The game is currently using it without any noticeable problems and levels with large amounts of the same wall run smoother. I’m new to posting code publicly and have to admit it’s a little humbling but there is always more to learn, so any feedback at all is appreciated.

My First Game

This is GunCore (working title). It’s a Megaman/Contra inspired  2D platformer that my friend and I have been working on for some time.

I programmed the game in Java, drew the art with pencil and paper and used Gimp for color. It’s all placeholder art but I admit it is nice to see my poor drawings come to life on the screen.

Were still prototyping and brainstorming so the game isn’t close to ready and this is my first game so I dont really know what I’m doing, but the game is already fun. I must be on the right track.

I wanted to start this blog after I did a two person play test and learned a great deal from watching someone, other then me, play my game for the first time. It showed me how important, in early development, it is to get others opinions. Though the game is far away from public beta this blog will be a place to publicly post design decisions and features in hope to get some constructive feedback.

Right now I just wanted to give you a peek at what I’ve been working on. As I get more organized I’ll have a lot more info available.


Follow the dev on Twitter.

Error: Twitter did not respond. Please wait a few minutes and refresh this page.

About Me

Orun Irunmale
I'm Orun, an indie game developer. This is my development blog for all my software escapades.

RSS oruncode RSS

  • New Site & New Blog January 25, 2013
    All my blogging and game projects will be on our new site.  Come check it out. This is my last post here at oruncode.  Lazorun.com  Lazorun.com/blog
    oruncode
  • My Ludum Dare #23 Game April 25, 2012
    Made in just 48 hours, The Last Ride Home is a driving game that will test your reaction timing and your persistance as you try to drive through as many levels as possible. Here is a gameplay video. The game can be played in the Chrome Browser. You can play it now here is a link […]
    oruncode
  • March is my Month of JavaScript March 21, 2012
    March is turning out to be the month of JavaScript for me. Ever since I was asked to copy this game for a job interview a few weeks ago, I’ve been enjoying making anything I can think of with JS and HTML5 canvas. This was my first JS project. It’s an image matching game. I jacked […]
    oruncode