July #1GAM: Castaway Exhaustion, Meters, and Richer Experiences

Now that it is July, I’m continuing work on my One Game a Month project, Shipwrecked.

At the end of June, I was trying to create a new image to indicate that the player is either drowning or collapsed on the ground. I had a first try, but it didn’t read very well:

June #1GAM

That last frame is supposed to be the “collapsed on the ground due to exhaustion” image, but it didn’t look very different from the “facing up” image.

So I asked for help on Twitter and Google+, and I got some great suggestions:

July #1GAM - HelpfulTweets

Unfortunately, I ran out of time last month, but that’s when I created Dark Horse last Saturday and submitted that game for June.

So when I got back to work this month on Shipwrecked, I wanted to make it obvious to the player how dangerous it is to stay out in the water too long.

I created a few more frames of animation for drowning, which happens when you’re out of stamina and swimming. You can still swim, but you only have a few seconds of air left. If you run out of air, you die. Swimming has the Castaway bobbing in and out of the water, but drowning shows what little of his face that is above the water in anguish:

July #1GAM

And if you make it back to shore in time, here is the new “collapsed due to exhaustion” look, based on the feedback I received:

July #1GAM

I also added a stamina bar to the top right of the screen. If you are drowning, a second bar appears to give you an indication of how much air you have left. Both of these bars can be seen in the above screenshots.

When you stand still and aren’t swimming, you regain stamina slowly.

What I like about everything I just described is that it is a pretty simple system that provides a better play experience. It is slightly more complicated than what I had before. Originally, if you had no more stamina and were swimming, you instantly drowned. It was harsh, and you had little feedback.

Now, stamina informs whether or not you have the strength to swim. If you don’t, then you start drowning, but you still have time to get back to safety before you run out of air. Air becomes a secondary resource, and the player has more options. Do you risk swimming to that smaller island that may or may not be within swimming distance, or do you turn back? It’s up to you how conservative you want to play. What’s more, stamina doesn’t recover if you are moving, so if you have to keep running away from something chasing you, you are risking the danger of not being able to swim very long.

I’m reminded of a talk given by Chris Crawford in which he discusses the use of variable ranges rather than booleans to provide a larger experience. If you have an NPC in adventure game, you could have a boolean that represents whether or not the character is hostile towards the player, but wouldn’t it be possible to have a richer experience if there were any number of in-between states, such as indifferent? Or secondary states, such as confident or fearful?

While I’m pleased with the stamina and air supply systems, I still need to give the player some way of eating food and recovering from hunger. I could implement a simple system in which touching nearby food objects automatically consumes the food, but in keeping with the above ideas, wouldn’t it be a richer experience to have an inventory system and give the player the choice of when to eat? As a couple of examples, I can introduce the concepts of food spoilage and cooking.

At the same time, July 31st will be here before I know it. I can’t get carried away with feature creep before I have created the core of the game play.

June #1GAM Entry: Dark Horse

So despite my efforts, I wasn’t able to finish the game I’ve been working on all month for June’s One Game a Month project.

So I took a good chunk of Saturday to make an entirely different game instead.

I’ll continue working on Shipwrecked for July, but Dark Horse is a very simple racing game that I managed to get done in less than four hours.

Download Dark Horse for Linux 64-bit (362 kb tar.gz file)

It was originally a Zero Hour Game Jam project from last November that I never finished. It started out with a very simple rendering of a horse that can jump.

June #1GAM

I then added hurdles and birds as obstacles, a clock, and a previous best time to beat for the challenge:

June #1GAM

The still images don’t show the horses legs spinning in place, and when the horse jumps, it looks pretty frantic.

Hitting obstacles slows you down and prevents you from making your best time. You need to jump over the hurdles on the ground while avoiding the birds, which fly up and down in the air.

Each race has a random collection of obstacles. I thought about adding collectables to give the player more incentive to get in the air to make the birds a bit more dangerous, but then I thought about giving rewards for collecting all of the items, and unfortunately my game development time is up for this weekend.

Dark Horse is not polished, but it feels good to get this old project to a completed state.

And next month, I hope to deliver the ambitious Shipwrecked. I’ve already dedicated 23 hours to it, and another month might be enough. B-)

June #1GAM: Swimming and Boulders; Also, Is It Too Ambitious?

Last week, I posted a video of dancing coconut trees for my One Game a Month project for June.

I ran into some technical issues when loading and rendering the world and its objects in the right place, and so I didn’t get as much accomplished this weekend as I would have liked.

I still don’t have an inventory system, but I thought about adding a shark to the game, which means that the player should be able to enter the deep water for at least short periods of time before drowning.

June #1GAM

The Castaway, in his pampered past life, never learned how to swim.

I’ve also added rocks. I’ve been experimenting with making them look right. Above, they were large boulders, but they looked odd when the player was standing next to them. Below, they are a bit smaller width-wise, but I made them tall to avoid making it look like you could pick them up. It’s…odd.

June #1GAM

Still, now it is possible to have areas of the island that are impassable unless you take a more roundabout route.

As it stands, the game has day/night cycles, a large island to explore, two objects (coconut trees and boulders), water to swim in as well as wade through, and hunger.

But it still isn’t really a game.

Next up:

  • make the player die from hunger
  • give the player a new object that helps alleviate hunger
  • give the player a temporary mount of time to be in deep water before drowning

I would like some concept of fatigue, a way to create a shelter, weather effects such as rain, animals such as sharks and crabs, and an end goal. I worry that I can’t do it all by Monday, though. I’m half-tempted to churn out something simple for this month and continue working on this project next month.

June #1GAM: Half an Hour and a Lovely Bunch of Coconut Trees

Yesterday’s post about my June #1GAM mentioned my huge island to explore and new coconut tree sprites.

After just half an hour yesterday morning that I didn’t think I’d actually take advantage of, I have animated coconut trees:

I intend for the trees to animate when the Castaway shakes them in an attempt to knock down coconuts, but for now they dance in unison in a poor imitation of Super Mario World.

They aren’t pretty animations, but then I’m just making programmer art over here.

June #1GAM: A Huge Island with Coconut Trees

In my last One Game a Month project post, I mentioned that I had message routines and created tiles for an island.

At the time, I said the next steps were:

  • Add a map. A big one that spans more than a single screen.
  • Make the camera center on the Castaway as we explore the map.

Well, I did it. And I might have gotten a bit overambitious.

June #1GAM

Above is an image of my 1024×1024 map so far. Each pixel represents a tile, as it does for the maps of my first major game, Stop That Hero!. I find loading images and defining tiles by colors to be quick and easy.

But I’m starting to realize how much work it is to create such a large world. I wish I had time to figure out some procedural algorithm to generate an island for me. As it is, I’m plotting things by hand, and taking shortcuts as I get bored. You can see the mess of green swirls at the bottom left as an example.

In any case, I thought I should add some other elements to the island, so now there are coconut trees:

June #1GAM

I like the way they look when they are clustered together, even if the lack of variety makes them look more cookie-cutter than would be ideal.

I am finding a problem with rendering, however. Specifically with Z-ordering. There is no concept of an obstacle yet, so the Castaway can walk through trees. When he is above a tree and walking down, he’s behind it until his feet hit about halfway down the tree, then he pops in front of it.

I think it is because the render ordering is based on the top-left corner of a blitted image and not the hotspot location, which would be the bottom of the tree and the feet of the Castaway. When the Castaway’s feet get about halfway down the tree, his head is just below the top of the tree, so now the system thinks he is in front. Hopefully that’s what it is and can be easily fixed.

I did run into one problem with the map loading that I’d like to share here. The 1024×1024 map is split into 32×32 graticules (I refused to call them “chunks”). Each MapGraticule is split into 32×32 tiles.

When I loaded a graticule from the map, I did it by getting the pixel offset and then matching tiles to colors in each pixel in the 32×32 area of the image.

When I ran the game, however, I was confused why so many graticules appeared very similar. In fact, they looked the same. What gives?

My image loading code was fine. The problem was when I created the MapGraticule objects for the island map in the first place.

I did so like so:

for (int column = 0; column < WORLD_WIDTH; ++column)
   std::vector<MapGraticule*> graticules(WORLD_HEIGHT, new MapGraticule(graticuleWidth, graticuleHeight, DEFAULT_TILE));

For those of you unfamiliar with C++, the above code loops through each column in the world, creates a collection of pointers to MapGraticule objects, and adds it to the world map.

For those of you very familiar with C++, you see what I did wrong. I created a single MapGraticule object, but created a vector of pointers…that all point to that same object.

So when I was populating each graticule with the right tile data, I was actually overwriting the same object’s data. When I went to render the world, I was likewise getting the data to render from the same object instead of multiple objects like I expected.

It was a simple fix. I simply added a loop to go through each row and created a unique MapGraticule object for each coordinate:

for (int column = 0; column < width; ++column)
    std::vector<MapGraticule*> graticules;
    for (int row = 0; row < height; ++row)
       graticules.push_back(new MapGraticule(graticuleWidth, graticuleHeight, DEEP_WATER));

My next task is to give the player something to do other than explore the map.

Walking around is fun and all, but the people demand drama!

They want the player to pick things up. They want the player to put things down. They want the player to eat things.

Oh, the excitement!

And I might shrink the size of the island while I’m at it.

June #1GAM: Islands and Messages

The other day, I had merely a walking Castaway demo for Shipwrecked, my June One Game a Month project.

I spent a little more time on the controls than I thought I would. It didn’t feel right. I tried something simple at first:

if (an arrow key has been pressed since the last update)
velocity = 1.0
player.setDirection(the direction of the arrow key)
if (an arrow key has been released since the last update)
velocity = 0.0

It worked well enough. The Castaway moves at a constant speed until the key is released, then he comes to a complete halt.

The problem was that if you are switching directions periodically, sometimes the velocity drops to 0 even if you feel like you should keep moving.

So I changed it. Now, instead of checking for key release, I check the status of all four arrow keys. If none of them are currently pressed, THEN set the velocity to 0.0. Otherwise, allow the movement to continue.

It feels much better.

I’ve also added some message routines. Basically, if there is a message to display to the player, it will end up in a queue with a timer. When the message is visible, the timer ticks down to 0, and it removes the message from the queue for the next one. It took me all of 15 minutes to implement.

And instead of a giant purple emptiness, I added some tiles.

In this Shipwrecked message queue video demo, you can see all of the elements of the project in action, including being able to read a few lines in the Castaway’s diary:

I simply painted the tiles down using for-loops, so the Castaway could walk on water right now if I let him.

So the next big things to do:

  • Add a map. A big one that spans more than a single screen.
  • Make the camera center on the Castaway as we explore the map.
  • Give the player something to do other than explore the map.

My worry is that I’ll get to the end of the month without any game play. I still haven’t exactly figured out what actions the player has, nor what the ending looks like.

It’s partly because I’m worried that I’ll be too ambitious. For instance, if I implement the ability to get heat stroke, it means the player needs to be able to avoid it, which means finding or building shelter. Do I have time to implement the ability to collect resources and build a lean-to (as well as draw one that looks half-decent)?

These last few things have come together quickly. Maybe I’ll get lucky and won’t have to compromise entirely on the concept of a Castaway surviving on a desert island after a shipwreck.

June #1GAM: We’re Walking, Here!

Last time, I introduced the Castaway for my One Game a Month project for June. I’ve since created a few more poses and some basic walking animations.

Here’s a June #1GAM video demo I quickly put together:

Next up is giving the player direct control through the arrow keys, which means changing directions and needing to set the right frame when standing still.

And after that, I think I’ll add some basic text displays. I like the idea of tooltips and descriptions popping up when you are exploring the world. Maybe it will tell you if you’re getting hungry, similar to how NetHack does it. Or maybe I’ll be more direct than that. B-)

Soon after, I’ll create the world to explore, and I’m thinking about cutting back on line-of-sight since I might not have enough time to really play with it.

June #1GAM: We Need a Castaway

In my last post about my June project for One Game a Month, I talked about the general ideas I had, plus I created a mock-up.

Since then, I’ve thought about what kinds of tiles I’ll need. I’ve decided to set it on an island in an ocean, so it will have standard sand, rocks, water, and palm trees.

The game is called Shipwrecked, and we’re going to need a castaway. Here’s what I created during yesterday’s Game Dev Co-Op Hour:

June #1GAM castaway

I still need to provide left and right versions, plus walking animations, but I’ll keep them simple. I’m fairly pleased with my programmer art.

After that, the next task is to give this character a world to walk around in.

Then I can work on line-of-sight algorithms. I’ve been thinking about having the player’s vision deteriorate if he/she is too hungry or sick, so the edge of the fog might be closer than usual if the player is reckless.

I’m pretty excited. I hope my enthusiasm and productivity lasts. B-)

June #1GAM: I Think I’ll Do Line-Of-Sight

Four days into June, and I hadn’t thought about what to make for the One Game a Month challenge for June.

I searched online for interesting mechanics to play with, but nothing really jumped out at me. If you want to see some ridiculous concepts, try out the Game Idea Generator. B-)

At some point, I thought about the idea of being shipwrecked and needing to survive. Maybe you’re on an deserted island in the ocean. Maybe you’re on a deserted planet in the far reaches of space.

I liked it. The player has to deal with hunger, weather, injuries, disease, wildlife, environmental hazards, all while trying to survive. Maybe help is coming if you wait long enough? Maybe you need to explore the island and build something to find your own way to freedom? Maybe there are others in the same predicament?

I don’t know. But exploring sounded like it had to be a big part of this game. You’re stranded, and you don’t know where you are, so you better get a handle on your surroundings.

And since I decided to do a tile-based grid, it seems like a good opportunity to do line-of-sight fog of war.

I like the idea that the player can see his/her immediate surroundings but needs to explore to see more. I like the idea of multiple levels of fog. One tile away is visible. Two tiles away is a little foggy. Three tiles away is more foggy. Four tiles is opaque.

Below is a mock-up demonstrating experiments with some fog made in the GIMP to see how it might look with different levels.

June #1GAM Mock-up

I’m not sure I’m happy with it, as I want it to be more difficult to see what’s behind the fog. Maybe I can experiment with different ways to render or create fog. We’ll see.

I also have to think about explored areas vs areas the player is immediately able to see. I’m reminded of Fate of the Dragon‘s fog of war, which returned to opaque if you weren’t in an area after a period of time. I think I’ll follow the normal RTS convention of graying out explored areas you can’t currently see.

Perhaps I’ll use Zelda-like controls. I was thinking about using the mouse and doing click-to-move/interact for simplicity, but I wonder if there might be some advantages to using the keyboard in terms of how expressive the player can choose to be. Maybe there are good reasons to crawl, sit, rest, walk, run (which takes a lot of precious energy), swim, jump, climb, open inventory, use items.

But then again, I can probably do all of the above with the mouse as well as the keyboard. Spacebar can be used to toggle sitting/standing, CTRL+click could be used to crawl, while Shift+click could be used to run.

Either way, I’ll probably find that I won’t add all of this due to only having the rest of June to finish this game. B-)

May #1GAM Entry: Hungry Frogs

The updates have been coming in quickly towards the end of the month, but my May project for One Game a Month is finished.

Download Hungry Frogs for Linux 64-bit (352 kb tar.gz file)

May #1GAM

Rather, it is finished enough. You can control the frog by jumping and turning around. If you fall in the water, the frog slowly swims back to the nearest lily pad. Flies will move across the screen in a straight line from left to right, and you need to jump to eat them. If you miss half of them in a given round, the game is over. Otherwise, the flies move faster each round, making it more difficult to catch them.

I didn’t take many screenshots as I thought the rectangles made for an uninteresting still shot, but I did make videos to demonstrate progress of the game’s development.

First, getting the jumping physics to work:

Then, landing on lily pads and swimming when you fall in the water:

Then, some game play, with edible flies:

And the final version, with faster flies each round and a game over screen if you miss too many:

I moved the frog’s tongue down as I realized it looked strange at the top of the head and I wasn’t going to have time to replace the white rectangle with a nice animated frog image. I would have liked to have flies moving in fly-like ways instead of straight lines. I really appreciate how the developers of Frogs and Flies nailed it in the constraints of an Atari 2600’s memory and processing power.

I’m not sure I’m happy with how easy it is now. Originally it was difficult to catch flies, so I expanded the tongue’s collision detection to include the frog’s body as well as a space around the tongue. Now it might be too forgiving, although there’s a gap if the frog is moving fast enough that from one frame to the next the collision box goes around the fly’s location. I’d fix that next if I had more time.

I’ve never made a platformer before, and this project was a good start. I am pleased with the jumping physics, although I need to figure out a better way to determine the maximum heights of jumps.

All in all, it was a fun project to make, even if it is once again another project with scope cut drastically to make the deadline.