So in my previous post about multi-platform programming, I mentioned that I was planning on doing a small game to practice/test my theory on multi-platform programming. That game is called Stick Man Trampoline!
To start off, I wanted to keep the gameplay simple. I wanted the actual implementation to be basic, so that I could easily test how it worked on multiple platforms. I decided to take the old game Breakout, and simplify it.
So, we start off with the paddle, and a "ball" that will bounce on it. In Breakout, the skill comes from controlling the ball in different ways to hit and destroy all the bricks. As the amount of bricks get reduced, you have to aim in different directions to hit the remainders. With my game, I wanted there to be one target or goal, and the entire level is focused on reaching that goal. I decided to put a hole in the roof, and make that the target. Hitting the walls, floor, or anywhere on the roof that isn't the hole results in a loss.
Next step is how you control, or work towards this goal. I knew I wanted to give the player a level of control as to which direction (left or right) they can fling their character, so the further from the center of the trampoline the character hits, the more 'in that direction' they'll fly as they go up. This is cumulative, so if you've hit the left edge twice, you'll have to hit the right edge twice to equal it out to 'straight up'. The other option was to reset the horizontal movement each time you hit the tramp, giving the player more control. I decided this was too forgiving, however, and wanted the player to have to think about every jump. The last part is how long it takes to get to the goal. Basically, there's a set number of 'jumps' it takes to get to the roof, and you have that many 'jumps' to get the character oriented correctly to make it through the hole.
Next step is how difficulty increases across levels. One way to vary difficulty is to affect the goal. I decided to randomly place the hole in the roof, to give some variance to each level. On top of this, as you progress in levels, the hole will get smaller.
Next, I wanted to make the game a little more intense with each level, so as the level increases so does the amount of horizontal motion you get from the trampoline. As levels progress, the player has to be more careful about where they place the tramp. A slight nudge in one direction early on, becomes a mistake that will fling you straight into the wall in later levels.
The last area of gameplay I wanted to vary with difficulty was the number of jumps required to reach the top. There were two options here, each of which would change the feel of the game. First, was to decrease the amount of jumps with each level. This would create a sense of urgency, and focus the player on small, discrete movements of the trampoline. The other option, is to increase the required number of jumps. This would give the player more time to line up to the hole, but also allow more room for mistakes. I decided to go with the second option, favoring the thought of the player frantically trying to fix an erratic 'bad jump' before they hit the roof.
Well, I feel like that explains all the mechanics that went into Stick Man Trampoline. My next post will be going more into the graphical elements of the game, focusing on making it "Juicy".
Thursday, September 26, 2013
Sunday, September 8, 2013
Code Snippet : An Exercise with Multiplatform Programming
So today I'm going to address an issue I ran into while creating Snake Hunt.
Snake Hunt was built in Monogame, an open-source framework that wraps around XNA. The reasons I chose to use Monogame are because it's simple and Monogame promises to be incredibly multi-platform. With this in mind, and the thought that after programming once I'll be able to release on pretty much every device, I jumped into making Snake Hunt.
So Monogame isn't the whole game, just part of it. The remaining parts can easily be programmed for each platform, but the problem comes with how the game refers to it. Since every platform works differently, the game would need to reference different code for each platform you're building for. At this point that means you'd need a separate copy of the code for each platform, and then change each copy to work on that platform. The problem with this is it causes a LARGE amount of duplicated code, and whenever you change something in your game, you have to change it in multiple places.
The solution to this is to use something called an interface. An interface is a programming construct which defines different methods, and then allows other 'classes' to implement it, promising that those implementations will also have those methods. We can then take the game code, and refer to just the interface, which would have methods like "PerformInAppPurchase" or "ActivateApps" etc. Then, in each platforms project, we use the same game code, but just pass in that platforms specific implementation of the interface. What we end up with is the game referring to each platform in the same way, keeping one copy of the code, and each platform handling their own specific stuff. Like this:
Snake Hunt was built in Monogame, an open-source framework that wraps around XNA. The reasons I chose to use Monogame are because it's simple and Monogame promises to be incredibly multi-platform. With this in mind, and the thought that after programming once I'll be able to release on pretty much every device, I jumped into making Snake Hunt.
Visual Studio Monogame Templates
So I threw together a Windows Store Project, and started coding assuming I could worry about the other platforms later. See, this is how I perceived Monogame worked:
So, I finished the game, had it running perfectly, and decided to try other platforms. First thing I realized was the project I was using was designed to build only to Windows 8. Fair enough! So I made a new Windows Phone project. Now I needed the code to be moved over. . . so I just made copies of all the files and tried to build the project and I got a boat-load of missing reference exceptions.
See Monogame isn't a 100% wrapper around anything you could write, it simply wraps around the XNA framework. Though the majority of what's written in a game would be within that framework, there are certain things that aren't, that would still be platform specific. An example of this would be in app purchases and ads, which are handled differently on every platform. A more accurate diagram of this follows:
So Monogame isn't the whole game, just part of it. The remaining parts can easily be programmed for each platform, but the problem comes with how the game refers to it. Since every platform works differently, the game would need to reference different code for each platform you're building for. At this point that means you'd need a separate copy of the code for each platform, and then change each copy to work on that platform. The problem with this is it causes a LARGE amount of duplicated code, and whenever you change something in your game, you have to change it in multiple places.
The solution to this is to use something called an interface. An interface is a programming construct which defines different methods, and then allows other 'classes' to implement it, promising that those implementations will also have those methods. We can then take the game code, and refer to just the interface, which would have methods like "PerformInAppPurchase" or "ActivateApps" etc. Then, in each platforms project, we use the same game code, but just pass in that platforms specific implementation of the interface. What we end up with is the game referring to each platform in the same way, keeping one copy of the code, and each platform handling their own specific stuff. Like this:
So, with these realizations, I'm starting work on another project. I'll post more information later, but the goal of this project is to put this design to the test. It'll be a simple game, with basic gameplay and art, but will (hopefully) work on any of the platforms Monogame supports.
Project Setup
Even with these discoveries, I was still having trouble keeping the code base shared between so many different projects. Everytime I made a new class, I had to copy it as a link to all the other projects. In searching for a solution to this, I discovered this magical chunk of xml:
<Compile Include="..\MonoGUI\CStudios\**\*.*"> <Link>%(RecursiveDir)%(FileName)</Link> </Compile>
EDIT: Working with this a little further, it turns out that using this with Content needs to be done a little differently. Assuming that you've made a WindowsPhoneXNAContent project (the only type that works in Visual Studio 2012), you'd use the following:
<ItemGroup>
<Content Include="..\ContentProject\ContentProject\bin\Windows Phone\Debug\Content\**\*.*">
<Link>Content\%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
Where "ContentProject" would be the name of the Content Project you made.
The problem I was having was that the .xnb was being cut off of the extension, which stopped the ContentManager from loading it. Using %(Extension) fixes this.
END EDIT
Used in conjunction with the following project layout:
Basically, we start off with a "Library" project. Create a folder within that, where we put all the source code for the game. It doesn't matter what platform we put as the build target, since that project will never really be built. From there, we make a project for each platform, and place the chunk of xml within the project file (Replacing MonoGUI with the Library project name, and CStudios with the folder that contains the source).
From this point on, every project now contains a "Link" to all files in the library project. Not only will the sub projects automatically add any files you add to the library, but it keeps them up to date. By setting them as a "Link" Visual Studio doesn't copy them into the local project, but instead keeps a reference to them. When changed in the library project, the sub projects immediately have that update.
There are other files that remain local to only certain platform-specific projects, such as entry points (each platform launches the game differently, but they should all call something in the library code to do so), and the "Platform Specific" interface implementation I referred to earlier.
Hopefully this helps someone figure out how to do multi-platform programming! I'll be putting another post up soon about my next game, that will be implementing this style.
Sunday, August 11, 2013
Showcase : Snake Hunt
Snake Hunt is a modern take on the classic game Snake. I made it as an exercise in gameplay and design. I wanted to take a classic game that everyone knows, and upgrade the gameplay, all while keeping the same feel and general idea behind it.
I updated the movement beyond the traditional four directions, put in support for various control schemes, and added several new gameplay mechanics. The mice now move, and get faster as you get larger. This requires you to change your strategy as time progress, from chasing down the closest, to 'trapping' the slowest. This is possible, since you can now wrap over yourself. To add a level of difficulty I've added randomly spawning obstacles, as well as a constantly decreasing food bar. If you hit one of these obstacles or the walls, or if you go too long without eating, that's game over!
Snake Hunt was made over 8 weeks, in my spare time, while interning at Microsoft. I'd wake up at 5:30 every morning to get as much coding in as possible before work, and as soon as I got back home I'd be back to work.
It was my first professional-esque attempt at using the XNA/Monogame framework, and I learned a lot, including a lot of things I'd do differently code and design-wise.
Snake Hunt has been released in the Windows 8 Store, and can be found at the following link:
http://apps.microsoft.com/windows/app/snake-hunt/86c230bb-9ac4-4db6-ac16-868d30653713
Here's a short trailer:
You can follow the development of the game here:
An Issue Of Control
The Hunt Begins
A Level Of Difficulty
I updated the movement beyond the traditional four directions, put in support for various control schemes, and added several new gameplay mechanics. The mice now move, and get faster as you get larger. This requires you to change your strategy as time progress, from chasing down the closest, to 'trapping' the slowest. This is possible, since you can now wrap over yourself. To add a level of difficulty I've added randomly spawning obstacles, as well as a constantly decreasing food bar. If you hit one of these obstacles or the walls, or if you go too long without eating, that's game over!
Snake Hunt was made over 8 weeks, in my spare time, while interning at Microsoft. I'd wake up at 5:30 every morning to get as much coding in as possible before work, and as soon as I got back home I'd be back to work.
It was my first professional-esque attempt at using the XNA/Monogame framework, and I learned a lot, including a lot of things I'd do differently code and design-wise.
Snake Hunt has been released in the Windows 8 Store, and can be found at the following link:
http://apps.microsoft.com/windows/app/snake-hunt/86c230bb-9ac4-4db6-ac16-868d30653713
Here's a short trailer:
You can follow the development of the game here:
An Issue Of Control
The Hunt Begins
A Level Of Difficulty
Sunday, July 28, 2013
Snake : A level of difficulty
Last post we rounded out how hunting the mice would work, and mentioned at the end some problems caused with the changes we've made from the classic version of Snake. Let's compare these changes now:
Classic: Food was immobile, there would only be one at a time, hitting yourself causes you to lose.
New: Food moves, as the game progress there will be more which can be chased off if too difficult to get, and you can go over your own body.
We've made the game more exciting by adding a chase element to getting the food and making the mice have variable statistics. We've also added a level of strategy by allowing you to use your body to trap the mice. On the other hand, we've removed almost every level of difficulty. The only loss condition is hitting the wall, which you can easily avoid. If a mouse is too fast for you to catch, you can chase it off and wait for a respawn.
So there's two things we now need to fix. We need to add a level of difficulty within the game map itself, and a level of risk to choosing whether or not to chase a mouse off and wait for a respawn.
Fix 1) There are now randomly spawning obstacles on the map field (rocks and bushes). Keeping with the theme of randomness, the position and size is randomized, as well as when they pop up. This allows the play area to evolve as the game progresses, and creates a level of risk. As the game continues, the players movement is more restricted, but at the same point they can push mice into the obstacles, giving a high-risk method of trapping them.
Fix 2) There is now a hunger bar that is constantly decreasing. If it reaches the bottom, the player will lose, and the only way to fill it is to eat mice! This will push the player into taking more risk in catching mice, in order to keep their hunger bar topped off.
Fix 3) Less of a fix and more of an added feature, there are now three difficulty settings. Playing on a higher difficulty simply ups the speed of the game, allowing a higher challenge for those who like reflex-based games.
Classic: Food was immobile, there would only be one at a time, hitting yourself causes you to lose.
New: Food moves, as the game progress there will be more which can be chased off if too difficult to get, and you can go over your own body.
We've made the game more exciting by adding a chase element to getting the food and making the mice have variable statistics. We've also added a level of strategy by allowing you to use your body to trap the mice. On the other hand, we've removed almost every level of difficulty. The only loss condition is hitting the wall, which you can easily avoid. If a mouse is too fast for you to catch, you can chase it off and wait for a respawn.
So there's two things we now need to fix. We need to add a level of difficulty within the game map itself, and a level of risk to choosing whether or not to chase a mouse off and wait for a respawn.
Fix 1) There are now randomly spawning obstacles on the map field (rocks and bushes). Keeping with the theme of randomness, the position and size is randomized, as well as when they pop up. This allows the play area to evolve as the game progresses, and creates a level of risk. As the game continues, the players movement is more restricted, but at the same point they can push mice into the obstacles, giving a high-risk method of trapping them.
Fix 2) There is now a hunger bar that is constantly decreasing. If it reaches the bottom, the player will lose, and the only way to fill it is to eat mice! This will push the player into taking more risk in catching mice, in order to keep their hunger bar topped off.
Fix 3) Less of a fix and more of an added feature, there are now three difficulty settings. Playing on a higher difficulty simply ups the speed of the game, allowing a higher challenge for those who like reflex-based games.
So gameplay-wise, we're pretty much done. All that's left is a bunch of polishing and gui work. Once that's done, I'll do a showcase piece as well as a postmortem discussing some of the programming issues I ran into, and how that's going to inspire my next few projects.
Friday, July 26, 2013
Showcase : House Wives vs Zombies
House Wives vs Zombies is set in the 1950's, where a sudden zombie virus has spread through your city. The virus however, only affects men, so it's up to you to take your mighty rolling pin in hand, beat those misogynist zombies, and save the remaining men in the city (though we didn't get around to finishing that last part).
Controls:
Esc: Quit
WASD: Move
1: Switch to Rolling Pin (Default weapon)
2: Switch to pistol
Mouse: Change facing
Left Mouse Button: Fire weapon
Team:
One programmer/Lead designer (Myself)
Three artists
Two composers
Everyone helped with designing and input
It's a game I threw together with a few people for the Iamagamer game jam, with the theme of "Strong Female Protagonists". We weren't able to participate that week, so we held our own mini-jam the week after. Though we had good intentions, a bunch of things came up, and we ended up only spending around 16 hours on the project. Despite this, I'm proud of the work we got done in the short period of time, and though rough, I feel like the finished product is a good proof-of-concept.
Here's a link to the download if you want to give it a go. (Just run the installer, you can uninstall it once you're done). Postmortem coming later.
https://dl.dropboxusercontent.com/u/85698531/HouseWifeVsZombies.zip
Controls:
Esc: Quit
WASD: Move
1: Switch to Rolling Pin (Default weapon)
2: Switch to pistol
Mouse: Change facing
Left Mouse Button: Fire weapon
Team:
One programmer/Lead designer (Myself)
Three artists
Two composers
Everyone helped with designing and input
It's a game I threw together with a few people for the Iamagamer game jam, with the theme of "Strong Female Protagonists". We weren't able to participate that week, so we held our own mini-jam the week after. Though we had good intentions, a bunch of things came up, and we ended up only spending around 16 hours on the project. Despite this, I'm proud of the work we got done in the short period of time, and though rough, I feel like the finished product is a good proof-of-concept.
Here's a link to the download if you want to give it a go. (Just run the installer, you can uninstall it once you're done). Postmortem coming later.
https://dl.dropboxusercontent.com/u/85698531/HouseWifeVsZombies.zip
Wednesday, July 17, 2013
Snake : The Hunt Begins
So, last post we discussed the controls of the snake game. In response to the post, I received a comment on how to improve the (rather terrible) controller support. Basically, instead of limiting the controls to four general directions, I've changed it so that the 'target angle' of the snake is whatever angle the thumb pad is currently facing. Brilliant and simple!
Moving on, I've finished implementing the AI of the mice/food. "AI? Why would completely immobile pellets of food need AI?" You ask? Well, I felt keeping the food immobile would be a waste of such a fun movement mechanic. So, the mice move, giving a level of difficulty to the chase.
Each mouse has a list of attributes, being: Speed, RunSpeedMultiplier, AwarenessDistance, AwarenessDropMultiplier, WalkTime, PauseTime.
So, I wanted the natural behavior of the mouse to be 'skittish', so they alternate between two states. They will first choose a random direction, and move at their Speed in that direction. They will move this way until their WalkTime is up, and will then not move for . . well, the duration of their PauseTime. Once that runs up, they'll choose another random direction and repeat the process.
Their behavior changes, however, if the head of the snake gets within a distance less than their "AwarenessDistance". They immediately move at their Speed times the RunSpeedMultiplier (which will always make them run faster) in a direction directly away from the snake head. Their direction will constantly update, so they're always running directly away from you. They will continue like this, until they reach a distance away from you equal to their AwarenessDistance times the DropMultiplier, or are chased out of the map (Mice who are being chased can escape the map. If they notice a snake is there, they're going to get out of there!).
Now, the values of all these attributes are randomized per mouse, so when mice spawn (more spawn the longer your body is) you'll get fast and slow ones, some stupid (won't run until you're on top of them) or smart (see you coming miles away), which provides an interesting twist to each game. On top of this, the values scale with the length of the snake, the longer you are, the faster the mice will be. At the beginning you're much faster than the mice, and can easily out-maneuver them, however as time progresses, it get's impossible to catch them by just chasing. This brings to light another gameplay element I'm quite proud of.
As seen in the picture from the last post, I've made it so the snake doesn't collide with himself. This allows you, as you get longer, to trap the mice. They run directly away from your head . . . so if you loop around before going in to strike them, you can catch them in the curves of your body.
Cool! And to demonstrate this, I've made a video! You'll see the three stages of the game here, the beginning, when you easily catch mice, the mid-game, where they're getting hard to chase down but you're not quite long enough to wrap around them, and the late-game, where strategy and planning are needed to capture those tasty mice.
Moving on, I've finished implementing the AI of the mice/food. "AI? Why would completely immobile pellets of food need AI?" You ask? Well, I felt keeping the food immobile would be a waste of such a fun movement mechanic. So, the mice move, giving a level of difficulty to the chase.
Each mouse has a list of attributes, being: Speed, RunSpeedMultiplier, AwarenessDistance, AwarenessDropMultiplier, WalkTime, PauseTime.
So, I wanted the natural behavior of the mouse to be 'skittish', so they alternate between two states. They will first choose a random direction, and move at their Speed in that direction. They will move this way until their WalkTime is up, and will then not move for . . well, the duration of their PauseTime. Once that runs up, they'll choose another random direction and repeat the process.
Their behavior changes, however, if the head of the snake gets within a distance less than their "AwarenessDistance". They immediately move at their Speed times the RunSpeedMultiplier (which will always make them run faster) in a direction directly away from the snake head. Their direction will constantly update, so they're always running directly away from you. They will continue like this, until they reach a distance away from you equal to their AwarenessDistance times the DropMultiplier, or are chased out of the map (Mice who are being chased can escape the map. If they notice a snake is there, they're going to get out of there!).
Now, the values of all these attributes are randomized per mouse, so when mice spawn (more spawn the longer your body is) you'll get fast and slow ones, some stupid (won't run until you're on top of them) or smart (see you coming miles away), which provides an interesting twist to each game. On top of this, the values scale with the length of the snake, the longer you are, the faster the mice will be. At the beginning you're much faster than the mice, and can easily out-maneuver them, however as time progresses, it get's impossible to catch them by just chasing. This brings to light another gameplay element I'm quite proud of.
As seen in the picture from the last post, I've made it so the snake doesn't collide with himself. This allows you, as you get longer, to trap the mice. They run directly away from your head . . . so if you loop around before going in to strike them, you can catch them in the curves of your body.
Cool! And to demonstrate this, I've made a video! You'll see the three stages of the game here, the beginning, when you easily catch mice, the mid-game, where they're getting hard to chase down but you're not quite long enough to wrap around them, and the late-game, where strategy and planning are needed to capture those tasty mice.
First thing you might notice, is not terrible graphics! Thanks to Erika for doing the art.
Another interesting thing to note, is that at almost every stage of the game, mice were still smart/lucky enough to escape, leaving an element of difficulty at all points.
However, the issue still stands that, as is, it's pretty much impossible to lose. The only obstacles are the walls which, honestly, can be easily avoided. Mice respawn when chased out of the map, so you'll always be able to get bigger. There's some level of challenge to chasing the mice, but outside of that it gets boring. I already have two more mechanics designed to fix this, but that'll have to wait for another time!
Sunday, June 30, 2013
Code Snippet : Angle Facings
So, simple enough concept: "I have an entity facing a certain direction. I want to turn him to face a target direction. I want him to turn on the shortest angle possible".
-0 degrees is straight right, and the range of angles is 180 (counter clockwise) -> -180 (clockwise)
Despite this being what I consider a simple and common problem, I struggled greatly to find somewhere that adequately described the solution. So here's how I handled it!
Things to note:
-Angles are in degrees (Most math libraries use radians, but I find degrees easier to assign initial values to, so we'll assume all Math functions we use take and return degrees)
-0 degrees is straight right, and the range of angles is 180 (counter clockwise) -> -180 (clockwise)
First of all, you'll need a helpful function called WrapAngle. Monogame has this by default in the MathHelper class, but in essence it does the following:
Alright, so whenever we modify an angle, we need to feed it through WrapAngle.
Next step, is to get our compared value. facingAngle is your current facing, and targetAngle is . . . well, the angle you're turning towards.
We now use this, along with the turningSpeed of the entity to update the facing position. We do a quick check to make sure this direction is actually the shortest.
Aaaaand done! Put this in your update loop, and your entity will always turn to a given angle, taking the shortest
public float WrapAngle(float angle)
{
while (angle > 180)
{
angle -= 360;
}
while (angle < -180)
{
angle += 360;
}
return angle;
}
Alright, so whenever we modify an angle, we need to feed it through WrapAngle.
Next step, is to get our compared value. facingAngle is your current facing, and targetAngle is . . . well, the angle you're turning towards.
float compareAngle = WrapAngle(targetAngle - facingAngle);
We now use this, along with the turningSpeed of the entity to update the facing position. We do a quick check to make sure this direction is actually the shortest.
facingAngle = facingAngle + Math.Min(turningSpeed, Math.Max(-turningSpeed, compareAngle));
Aaaaand done! Put this in your update loop, and your entity will always turn to a given angle, taking the shortest
Subscribe to:
Posts (Atom)






