Tuesday, January 31, 2012

New Backgrounds

Hey!

It's been a while since my last update, but rest assured we're working hard on getting this game out.

Here are the new backgrounds for World 1
The basic idea is that he's running towards the city

So, with each level it gets a little closer

Almost there!

Be sure to check them out in-game in the latest version.

Sunday, January 29, 2012

Enemies

I haven't posted about game mechanics in a bit, so I guess I'll talk about how I implemented enemies! This will also contain a modification I made to my asset system, as well as another one that I would like to make in the future. So here we go!

An instance of the Enemy class is created for almost everything in the game that has the potential to kill the player. The exceptions to this are doors and light gates (implemented with another class called Static) and the spikes that line the edges of some levels.

Now in order to create a single Enemy class that can represent any type of enemy, I had to use a lot of switch statements. For the non programmers out there, a switch statement lets you define several different cases and execute a different block of code depending on which case fits. For my purposes, I could check which type of enemy a particular instance of the Enemy class is and make sure it behaves correctly.


//Conditional x collision depending on enemy type
    if(type==SLIME){
     if(assets.getBg().checkCollisionX(collision, yPos) || assets.getBg().checkGap(collision, yPos+spriteHeight)){
      collided=true;
     }
    }else if(type==STINGER){
     if(assets.getBg().checkCollisionX(collision, yPos) || assets.getBg().checkCollisionX(collision, yPos+spriteHeight-assets.getBg().tileSize) || (xPos<=xBoundL && xSpeed<0) || (xPos>=xBoundR&&xSpeed>0)){
      collided=true;
     }
I again use a switch statement to define different hitboxes depending on the type of enemy
public Rect getLoc(){
  if(type==STINGER){
   return new Rect(xPos+40,yPos+40,xPos+spriteWidth-20,yPos+spriteHeight-25);
  }else if(type==LIGHT_TRAP){
   return new Rect(xPos,yPos+15,xPos+spriteWidth,yPos+spriteHeight);
  }else{
   return new Rect(xPos,yPos,xPos+spriteWidth,yPos+spriteHeight);
  }
 }


This setup makes it very simple for me to add new enemies in. I simply need to add cases defining it's hitbox and movement pattern and I'm set!

Another consideration I  needed to make was how I manage the bitmaps containing spritesheets for these enemies. My original implementation had all of the enemy sprite sheets aliased correctly such that each sheet was loaded once per type of enemy. However, whenever an enemy switched directions or was flipped from on to off, the change was handled within the enemy class. This meant that eventually, every enemy instance would have it's own sprite sheet. Terribly inefficient, and unavoidable as long as sprite sheet changes are handled by the enemy itself.

To fix this, I modified my Assets structure (yet again) to contain a bitmap manager for the Enemy class. A data structure was built that stores two sprite sheets per enemy type, labeled by the enemy's type name. The reason I stored two per enemy is that if we have some slimes facing left and some facing right, they can't be read off of the same sheet! Whenever an Enemy is created, it checks the data structure to see if it's bitmaps are loaded in and loads them if needed. When a switch is flipped, the two bitmaps for that enemy are overwritten with the new versions. This way, I can have 2 slimes or 200 slimes in a level with virtually the same memory footprint!

In the future, I'd like to move ALL bitmap allocations into the Assets class. Right now the Player sets up its own bitmaps, the Background sets up a bitmap, etc. A much more elegant and less bug-prone setup would be for the Assets instance created for a level to have a single data structure with all of the bitmaps used for the level. It can then pass every single asset a reference to it's bitmaps, and requires much less work when I want to clean out all of the bitmaps before loading a new level.

Saturday, January 28, 2012

VERSION 0.1 UPDATE

Hey!

So, apparently the game didn't work on phones with different screen sizes...

We fixed that!

It also works on Tablets now!

Download Off-Switch V0.1

Instructions:
  1. Download Offswitch.apk
  2. Email the file to whichever email you have linked to your phone
  3. Open the email on your phone, click install (May have to confirm that you want to allow untrusted apps)
  4. Enjoy!

Feel free to post any suggestions/critiques/bug reports either as comments on this post or emailed to martywalkeranimation@gmail.com (Art/level design) or cjalbert@umd.edu (programming/bugs).

Known Issues

  • Standing inside/slightly under the thin platforms
  • Light gates misbehave a bit when turned off and back on
  • Shadow's head may pass through blocks when hit from the side
FAQ

1. Q: Why won't this run on my device? 
    A: If it doesn't install at all, it's possible that your phone is running on an older version of Android. To make multitouch work correctly, the app supports Android 2.2 and later. 

2. Q: Why can't I save my game?
    A: Saved games aren't in yet.. However, if you hit your phones menu button, there's a skip level button to help you get back to where you left off. No cheating!

3. Q: Can I play on my PC?
    A: Unfortunately, no. The only way to run android apps on a PC is with the AVD Emulator, which is build into the SDK and more for debugging than anything. It lags TERRIBLY.

4. Q: Are you going to make an iPhone version?
    A: Short answer: No. Long answer.. The Android API is built on java, and the iOS API uses Objective C. This means essentially rewriting all of my code. On top of that, my understanding is that Apple charges a 100 dollar developer license fee to write apps, along with requiring the programmer to have an iMac and an iOS device for testing. Finally, apps can't be installed on phones unless approved by Apple, so I wouldn't be able to send you a development version anyways!

Friday, January 27, 2012

Alpha demo now available!

With great excitement and mild exhaustion, I'm happy to announce that we now have an alpha version of Off-Switch available to play! This demo contains all of world one except for the boss fight. So download it, find bugs, show it off to your friends, and have a merry time!

Download Off-Switch V0.1

Instructions:
  1. Download Offswitch.apk
  2. Email the file to whichever email you have linked to your phone
  3. Open the email on your phone, click install (May have to confirm that you want to allow untrusted apps)
  4. Enjoy!

Feel free to post any suggestions/critiques/bug reports either as comments on this post or emailed to martywalkeranimation@gmail.com (Art/level design) or cjalbert@umd.edu (programming/bugs).

Known Issues

  • Standing inside/slightly under the thin platforms
  • Light gates misbehave a bit when turned off and back on
  • Shadow's head may pass through blocks when hit from the side
FAQ

1. Q: Why won't this run on my device?
    A: If it doesn't install at all, it's possible that your phone is running on an older version of Android. To make multitouch work correctly, the app supports Android 2.2 and later. On the other hand, if you play on a tablet or phone with a screen larger than 480x800, there's a scaling issue that I'm working on fixing. Hold tight!

2. Q: Why can't I save my game?
    A: Saved games aren't in yet.. However, if you hit your phones menu button, there's a skip level button to help you get back to where you left off. No cheating!

3. Q: Can I play on my PC?
    A: Unfortunately, no. The only way to run android apps on a PC is with the AVD Emulator, which is build into the SDK and more for debugging than anything. It lags TERRIBLY.

4. Q: Are you going to make an iPhone version?
    A: Short answer: No. Long answer.. The Android API is built on java, and the iOS API uses Objective C. This means essentially rewriting all of my code. On top of that, my understanding is that Apple charges a 100 dollar developer license fee to write apps, along with requiring the programmer to have an iMac and an iOS device for testing. Finally, apps can't be installed on phones unless approved by Apple, so I wouldn't be able to send you a development version anyways!


Wednesday, January 25, 2012

Act 1, Scene 1

We'll be releasing a demo of world 1 in by the end of the week, so I wanted to do at least the intro cut-scene done first.

I've changed the story a bit from what I had originally envisioned. Originally it was going to be this big story where Silhouette (Shadow Jones' girlfriend for those new to the blog) gets possessed along with all of the other creatures, so Jones chases after her and spends the whole game trying to snap her out of it - fighting the bosses whenever they got in his way.

 I made this cut-scene as a stand-in for the first demo, but I think I'm going to go with it. The first story is big and kinda cool, but at the end of the day it's a generic "save the princess" story.

Plus this one's funnier


...and people don't have to tap through 20 panels of story to get to the game.

We'll see where we end up.

Sunday, January 22, 2012

Progress 1/23/2012

So I noticed that while we have many informative posts describing different elements of the game, there's really no indication of how far along things currently are. So I figured I'd give a quick update on the current state of Offswitch, along with some stats.

As of now, all of the framework is in place for a simple platformer. The tiling system is in place, so levels of any size can be quickly created and loaded into the game. There are currently 3 enemies (light traps, slimes, and stingers), one player type (default), and 2 statics (doors and levers). Levers are functional, flipping enemies from their light state to their shadow state. Enemies are also killable, though no transformations exist in game yet.

The things I'm working on now (in order of priority):
  • Stinger transformation (allows player to fly, but removes ability to flip levers)
  • Parallax gradients (Gradient in background moves with player, but at a different speed relative to the level)
  • Pause/resume states (Currently, player will restart at beginning of level if app loses focus)
  • Slight bug fixes
Also, we will soon be talking about how to implement boss fights. We are hoping to have a demo available once world one (levels 1-1 to 1-3 and boss fight) is completed. The demo should feature the flying transformation and near-final versions of all world 1 levels.

Now for some fun stats!
  • Assets: 83 (levels, sprite sheets, etc.)
  • Assets in game: 34 images, 3 level files
  • Classes: 12
  • Lines of code: 3,272
  • Project size:  4.25 MB
  • Application size: 1.05 MB
  • Revisions: ~350
  • Number of times the word "Offswitch" appears in source code: 85
  • Start date: Dec 23, 2011 (1 month old today!)
  • Most revised class: Player.java (Collision is hard!)

Levels

This is kind of a fun one to talk about. The level system is the subject of the single largest and most complicated overhaul I had to make in the course of this project! It was a tedious and terrifying process, but the results are awesome. I'll start with the old system.

In our original level system, the Background object mentioned in a previous post held a Bitmap. This Bitmap was essentially the entire level. Here's what one looks like
As a fun aside, here's the image Marty would give me to place the enemies and such.

The player and enemies would actually refer to this bitmap in memory, looking up pixel positions to see if they were black. This is how collision was managed, and it wasn't a very good way for a few reasons. First off, we were limited to black platforms/walls/etc and nothing else that was a part of the background layer could be black. However, it lead to a MUCH more significant issue. Memory management.

Alright, this is going to require a hardcore digression so skip this paragraph if you aren't interested in how memory is managed. Image files on a computer can be saved in several formats: GIF, JPEG, BMP, etc. However, this file extension only refers to how the image is compressed to store on a hard drive. While actually working with the picture (viewing it or manipulating it, for example), it is expanded and stored in RAM, which I'll refer to as memory here. The images size in memory has nothing to do with what format it's saved as; in fact, it's pretty simple to figure out it's size. Multiply the number of pixels by the bit depth (typically 32) and divide it by 8 bits in a byte to get the number of bytes. One megabyte is a million bytes (sort of), so the rather small level depicted above is 1600*1966 pixels, or about 12.5 MB. On Android, these images are stored in an area of memory called the native heap which is as small as 24MB on some devices and has no problem crashing your app if you try to go past that. Since I'm also loading player sprites, enemies, and all sorts of other fun images, this level crashed phones.

So I made a new system, that didn't suck. In the new system, I used tiles. Each tile is loaded only once, and a level file is loaded in that is used to create a massive data structure describing what kind of tile goes where. We only needed to load around 20 or 30 different 32x32 pixel tiles into memory, and we could create massive levels! This was stress tested with a 200x200 tile level, which ran perfectly but was absolutely miserable to navigate (thanks Alex Mateik..) In this fancy new system, levels are made like this.


Marty loads in a tile set, creates a level, and sends me the tile set and .tmx file produced. The level is parsed out using a nice little chunk of code called TMXLoader (Thanks David Iserovich) and I create a bitmap of what the player can currently see. The bitmap is constantly recreated, and all of our memory issues are solved!

Collision is also a bit easier in this system. Rather than checking pixels, I can look up what tile the player is entering and decide if it is a collision tile or not. To determine what tile number each type of tile is, I open up the .tmx file in a text editor and I am greeted by something like this.
Slightly eye-melting, I admit. However, squint your eyes and you should see a level amidst these numbers! 0 is a transparent tile (or lack of tile), 1 is a solid block, 2 is a platform, and all of the other numbers are pieces of the curved cliff edges. With this, I can decide what tiles should cause the player to react in what ways, and keep the player from randomly falling through floors! Well..sometimes.

Saturday, January 21, 2012

Polishing the Transform Animation

I spent a lot of today finishing up that transform animation. It gave me more trouble than a lot of the others because I had started the first pass straight ahead on 1's, 2's and 4's without much of a plan. The result I got was basically good, but needed a lot of polish

Here's what I had started with:
It's not the worst thing in the world, but there are parts that could be clarified. The idea of the transform was that his arms would pop into wings and pull him up. As a friend pointed out to me, it really isn't clear that his arms are what's changing. It almost just looks like wings are popping out of his back.

The reason is that the initial antic pose for his arm was all scrunched up like so:
Which I think could have been kind of fun....if anyone could see it...

The fact that I followed that with a vague smear didn't help much.

Fixing it was a simple matter of making a bigger deal out of his arm before it changed
I made the arm pose a little cleaner and had it slow in to the anticipation so that it stays around that pose for an extra frame before popping off. I also replaced the vague smear with a clearer morphing pose.

Here it is animated:
The next real issue is that the spacing's a bit of a mess. Since I did a lot of it straight ahead I hadn't planned for proper slow ins and outs, so his bounce is a little mushy. I went over the whole thing and pushed his up and down extremes a little further, while cleaning up the overall arc a bit. 
The differences are subtle, but there. From there it was mostly clean-up.
I cleaned up the body and arms first as they're the main action. The legs are all follow through, and the face is largely secondary, so I threw them inside of symbols to be dealt with later.
Then I dealt with them.

...guess that's it...

'Till next time.

Friday, January 20, 2012

Transformations

One of the hardest things we've had to come up with from the design side is how the transformations are going to look. We've had a lot of cool ideas, but they had to be scrapped simply because there are too many variables to account for. We needed an animation that would work no matter what state the player/enemy sprites are in and no matter which direction they were facing.

 Here's the idea I think we'll end up going with:
When the player kills the enemy it'll swoop down and compress into a little ball that hovers over to the player.
Once it hits the player he transforms into his new state with his new abilities (unless it's a slime...those don't give him powers. It just hits him and disappears).

Here's the first pass at the roughs for his transformation. I'll fix a few things then clean it up tomorrow:
It's a nice, simple solution that separates both animations, and should help them transition smoothly from any state.

Thursday, January 19, 2012

Asset Management

In today's episode of offswitch development nonsense, I'm going to talk about the asset management system I made! Rather, I'm going to talk about the old system and how terrible it was before describing the new system and how much better it is! This post will have pictures instead of code, so that's exciting.

When I say asset, I'm referring to elements of the game: backgrounds/gradients, buttons, enemies, statics (doors, levers, etc), and the player. Just to clarify, background and gradient are kind of misleading names.. the gradient object I refer to is the scene painted behind the level, and the background object is the platforms and walls of the actual level. I should REALLY get around to renaming those things before I get called out on it.

So I'll explain the old system. For fellow java programmers out there, I created an Asset object with some generic methods/variables, then made all six of the game objects I listed extend Asset. My "Asset Management System" was just an Asset array. Since all of the different things extended Asset, I could throw them all into the array. In English, this is the equivalent to dumping everything into a large box. Whenever I needed to access an objects, I had to go digging through the box and check what each thing was. And just about everything in the box needed to access just about everything else in the box. If the player needed to access the background to check for collision, It had to search through the box to find the background and then check the pixel needed. This led to a lot of weird dependencies and channels of communication between all of the different objects. I drew a picture, both to illustrate the unnecessary complexity of this system and to demonstrate why Marty is doing ALL of the drawings.


It doesn't take a programmer to tell that this system redefines terrible. So I decided to rip it all out and redesign it!

The new system creates an Asset object, which is a custom data structure containing all of the individual objects and a few methods for them to interact. Each object is given a handle to the Asset object, so if they need to talk to each other they can trace up to the Asset and access the object they need. This is both entirely more efficient and WAY easier to understand, as the following picture demonstrates.


Way better, right?

Silhouette

Here are some concepts for Shadow Jones' girlfriend Silhouette. She gets possessed along with the other creatures when the light demons attack, which is what drives Jones to take action in the first place. He spends the whole game chasing after her and trying to snap her out of it.


She's been the easiest of any character to design so far. I figured out the look I wanted pretty quick, I just need to lock down the a bit before doing any in-game drawings.

That's it for now. I'm off to work some more.

Wednesday, January 18, 2012

So, How's the Game Work?

Ah, day 3 of the production blog. I suppose it's time to explain how the game actually works.

The basic premise is "Light Demons have invaded Shadowland and possessed all of the creatures. It's up to you to stop them!" (I'll go more into the story once I get the cut-scenes drawn out for you.)

It's sort of your basic platformer. All the enemies are these glowing light creatures:

(Well, in game they glow...the glow doesn't export well into an animated gif)

Somewhere in the level each enemy has a lightswitch. When you turn it off they become shadow versions of themselves
At which point they're harmless and you can merge with them to use their abilities to solve puzzles and get around obstacles. (You can only flip one switch at a time, though. Once you deactivate one, it reactivates all the others.)


For instance if you wanted to get to the ledge in the upper left:

You'd kill the little flying dude, and fly up there.

That's an easy example...

Eventually it'd get a bit harder...you'd have to dodge spikes and stuff...

Should be fun...

Here's hoping

Tuesday, January 17, 2012

Controls

To start things off from the programming side, I'm going to post some of my favorite code: the controls! Implementing good, functional multi-touch controls was harder than I had anticipated, as there are a lot of things we take for granted when playing video games. For example, what happens if I slide my finger off of the button before lifting it from the screen? How about if I slide my finger from the right button to the left? I'll talk about how I dealt with some of these cases, but first let me show you the code!
 @SuppressWarnings("unchecked")
 public boolean onTouchEvent(MotionEvent event){
  //Binds the key to a hashmap so we can watch for it to lift, then proceed to call doKeyUp/Down

  int actionCode = event.getActionMasked();
  switch (actionCode){
  case(MotionEvent.ACTION_DOWN):
  case(MotionEvent.ACTION_POINTER_DOWN):
   if(event.getPointerCount()==4){
    mAssets.getPlayer().invincible=!mAssets.getPlayer().invincible;
   }
  if(thread.getCurrentState()==STATE_PAUSE){
   thread.unpause();
   return true;
  }else if(thread.getCurrentState()==STATE_WIN){
   level=0;
   thread.doStart();
  }else if(thread.getCurrentState()!=STATE_RUNNING && level==0){
   level=1;
   thread.doStart();
  }


  for(int i = 0; i < event.getPointerCount(); i++){
   if( event.getActionIndex()!=i){
    //This pointer has not gone down, or the button is already bound to something
   }else if (event.getX(i)>10 && event.getX(i)<100 && event.getY(i)>380 && event.getY(i)<470 && mPointers.containsValue(Button.BUTTON_LEFT)==false) {
    //Left button
    mPointers.put(event.getPointerId(i),Button.BUTTON_LEFT);
    onKeyDown(Button.BUTTON_LEFT);

    //Right button
   } else if (event.getX(i)>110 && event.getX(i)<200 && event.getY(i)>380 && event.getY(i)<470&& mPointers.containsValue(Button.BUTTON_RIGHT)==false) {
    mPointers.put(event.getPointerId(i),Button.BUTTON_RIGHT);
    onKeyDown(Button.BUTTON_RIGHT);

    //A button
   } else if (event.getX(i)>600 && event.getX(i)<690 && event.getY(i)>380 && event.getY(i)<470&& mPointers.containsValue(Button.BUTTON_A)==false) {
    mPointers.put(event.getPointerId(i),Button.BUTTON_A);
    onKeyDown(Button.BUTTON_A);

    //B button
   } else if (event.getX(i)>700 && event.getX(i)<790 && event.getY(i)>380 && event.getY(i)<470&& mPointers.containsValue(Button.BUTTON_B)==false) {
    mPointers.put(event.getPointerId(i),Button.BUTTON_B);
    onKeyDown(Button.BUTTON_B);
   }
  }

  break;
  case (MotionEvent.ACTION_UP):
  case (MotionEvent.ACTION_POINTER_UP):

   for(int i = 0; i < event.getPointerCount(); i++){
    if(event.getActionIndex()==i && mPointers.containsKey(event.getPointerId(i))){
     onKeyUp((Integer)mPointers.get(event.getPointerId(i)));
     mPointers.remove(event.getPointerId(i));
    }
   }
  break;
  
  case (MotionEvent.ACTION_MOVE):
   for(int i=0;i110 && event.getX(i)<200 && event.getY(i)>380 && event.getY(i)<470 && mPointers.containsValue(Button.BUTTON_RIGHT)==false){
      onKeyUp(Button.BUTTON_LEFT);
      mPointers.remove(event.getPointerId(i));
      mPointers.put(event.getPointerId(i),Button.BUTTON_RIGHT);
      onKeyDown(Button.BUTTON_RIGHT);
     }else if((Integer)mPointers.get(event.getPointerId(i))==Button.BUTTON_RIGHT && event.getX(i)>10 && event.getX(i)<100 && event.getY(i)>380 && event.getY(i)<470 && mPointers.containsValue(Button.BUTTON_LEFT)==false){
      onKeyUp(Button.BUTTON_RIGHT);
      mPointers.remove(event.getPointerId(i));
      mPointers.put(event.getPointerId(i),Button.BUTTON_LEFT);
      onKeyDown(Button.BUTTON_LEFT);
     }
    }
   }
  break;

  }

  return true;
 }
A lot to process, I know. I'll explain some of the more interesting parts for you. First off, button binding!

When implementing game controls, the natural first thought is to set a button to "pressed" when you put your finger on it and "unpressed" when you lift your finger. However, this leaves one major problem. If your finger is not on the button still when you lift it, it won't be lifted! An additional problem I ran into was that it's easy to get your fingers mixed up when programming multi-touch. If you aren't careful, lifting your left thumb may cause the button under your right thumb to lift.. which I claimed made the game more interesting, but was shot down in the end.

I fixed both of these problems with one Hashmap, a fairly basic java structure that stores data using a key in the same way the post office uses your address to determine which house to bring your mail to. So after the first bit of code with all the STATE garbage (all that does is start the game if it isn't started when I touch anywhere on screen), I have a nicely labeled block of code for every button that checks to see if the finger went down on top of one of the buttons. If so, it binds the pointer ID of that finger (guaranteed not to change, where the pointer INDEX can change whenever it feels like it) to the button it is pressing. This way, when the finger is lifted I don't even have to care where it is at the time. I just look up what button it was bound to, lift the button, and unbind it. Fun, right?

The next bit of code worth talking about is the block under ACTION_MOVE, which is what I call the d-pad sliding code. You may not think about it, but gamers typically slide their thumb between the left and right buttons of the d-pad on a controller to quickly switch directions. Initially my code required the player to lift their thumb from the left button before pressing right and vice-versa, which felt a bit clunky. To fix that, I check if a finger that is bound to the left button hovers over the right button or if a finger bound to right hovers over left, and unbind/rebind the finger appropriately. This small addition makes a HUGE difference to gameplay.

Finally, you might be wondering what happens when I call that doKeyDown thing. What I'm doing there is sending a signal to the actual game thread, which then does two things. The first thing it does is talk to the Button class, telling it to redraw the button as a depressed button (slightly greyed out version) to give the player some feedback that their button press was received. The second thing it does is update a variable in the Player class telling the player that the button is pressed. I've considered moving this variable outside of the Player, but it seems to be fine there for now since the player is the only thing that has to read in a button press and respond to it.

Anyways, this was a bit lengthy but I hope it offers some insight into what it takes to develop controls for a touch screen game. Next time I'll talk about something more headache inducing, like collision!

Designing Shadow Jones

So, I guess I'll start off with the development of the main character, Shadow Jones, the Shadow from Shadowland.

Funny enough, he started out as a magician:
It was an idea for a short film I had a couple years ago about a sort of magic duel between a magician and a sorcerer. Not the greatest idea in the world, but I wanted it to be in a cool, silhouettey style.

Anyway, eventually I canned it in favor of what became The Mighty Hunter

After TMH I was back to trying to find an idea for my next short and started doodling that magician again.

If you look across those pages from right to left you can almost see him change from the magician to the shadow. I eventually simplified his slicked back hair into just that little swoosh in the back, and dropped the sleeves and pants in favor of simple arms and legs.


Eventually it became a story about a little shadow who's wandering around one day when he finds a little glowing light bulb. He reaches out to touch it and the light burns his hand off. Once the light bulb has a taste for shadow flesh it starts chasing him around and stuff. Then the shadow...

dies...

or something...

I never really worked out the story 100%...



It was becoming little more than an extended chase scene, so I was about to scrap it. Then I figured it'd make a cool game, so I suggested it to Cody.

Now that's what it is...

Here are some sprites of him in a couple of the forms he takes in the game:


PhotobucketPhotobucketPhotobucket


Monday, January 16, 2012

Intro time

Hey everyone, looks like it's my turn to introduce myself. My name is Cody, and I'm handling the programming side of Offswitch. That basically translates to Marty saying, "Can we do this?" to which I sigh and grudgingly respond, "Yeah, probably..it'll be hard though.."

Anyways, the goal of this whole project for me has been to learn how to program a video game. I desperately want to go into the video game industry, and figured an internship would be easier to land if I managed to come up with a functional game to show off. Now I'm realizing that though the finished product will prove that I've learned a thing or two, there is much more story in the journey than in the destination. With that motivation, I'm going to be breaking down various aspects of the game and explaining how they are implemented, the history and various redesigns, and even go over planned improvements.

On that note, if you aren't at all interested in programming you may want to stick to Marty's posts! Mine may at times reach a pretty high level of nerd talk. Planned posts at this point include controls, the physics system and main game loop, my asset management system, collision, the level rendering (currently being revamped into a tiling system!), and some of the more advanced mechanics such as enemy states and player transformation. Hopefully I can provide some insight into the various mechanics that need to be considered when programming a game, as well as give other programmers a chance to learn from my mistakes.

Oh.. since Marty's intro had lots of nice pictures, I suppose I should give you some source code to ponder. Check it out: the main loop!


//Main game loop
  @Override
  public void run() {
   // start tracing to "/sdcard/calc.trace"
   //Debug.startMethodTracing("calc");
   while (mRun) {

    if(!updateFlag){
     Canvas c = null;
     try {
      c = mSurfaceHolder.lockCanvas(null);
      synchronized (mSurfaceHolder) {
       updatePhysics();
       doDraw(c);
      }
     } finally {
      // do this in a finally so that if an exception is thrown
      // during the above, we don't leave the Surface in an
      // inconsistent state
      if (c != null) {
       mSurfaceHolder.unlockCanvasAndPost(c);
      }
     }
     //Satisfy flag conditions
     if(restartFlag){
      restartFlag=false;
      doStart();
     }
     if(winFlag){
      winFlag=false;
      level++;
      doStart();
     }
    }
   }
   // stop tracing
   // Debug.stopMethodTracing();
   Log.w(this.getClass().getName(), "Thread exited");
  }

Pilot

Oh hey, I didn't see you there.

Welcome to the production blog of Off-switch, a cool mobile game my buddy Cody and I are making. It's a puzzle platformer about this little shadow dude who's home has been invaded by light demons.

I'm doing all the art so I'll be posting neat stuff like:

Concept Art:































Sprites:











And Level Design:














Hope the whole thing ends up being interesting. We'll probably post links to beta versions and stuff as we get them, so stay tuned.

-Marty