Saturday, September 11, 2010

Side Scrolling Fun III: Sprites & Tiles


With the level editor complete, I added some code to read in a level file, allowing the player to roam free in a bigger world. The next step was to pretty things up a little by drawing each tile from an image (instead of a red, green, or blue square.)
Since the level could be, in principle quite large, it didn't make sense to draw the entire level each "tick," but to at the very least draw only what is visible on the screen at the time. Given that the blocks from the level file are already sorted by x-position, and since the levels are long but not tall, this wasn't too hard. I just searched through the array of "Squobs" until I got to the first one which had an x-component greater than the leftmost screen point minus the block width and marked that as the starting point. From there I kept going through the list until I got to the first brick which had an x-coordinate greater than the rightmost screen-point and marked that as the ending point and drew all of the blocks in between.
The next task was to draw the player as an animated sprite. Normally sprites are a collection of images which animate in sequence to make the appearance of moving. Since you don't necessarily want to make one animation frame per clock cycle, you can incorporate a frame rate by counting up each clock cycle to a certain number before flipping frames. For the purposes of making a character look like he's walking, I counted distance traveled instead of clock cycles. This makes it look a little (but not too much) more natural and keeps the character from walking on the spot when his velocity is little or zero.
In order to get the player to face the right way and to look like he's jumping when he's jumping, I gave the Sprite class a set of states:
  1. s: Standing and facing right
  2. S: Standing and facing left
  3. j: Jumping and facing right
  4. J: Jumping and facing left
  5. r: Running and facing right
  6. R: Running and facing left
... and each is sorted out in the code via a switch(state) statement.

Here is a screenshot of the code in action:


In order to circumvent Java's (admittedly necessary) security measures, all the files are loaded as URLs from the server where they reside. As a result, loading the level takes a really long time. However I couldn't convince Java to read files from a browser so until I find a better way, I'm stuck doing it this way.

The code can be found zipped here or directly here.

You can play the game here (all you need is a little patience.)

Thursday, September 9, 2010

Side Scrolling Fun II: The Level Editor

In the very basic side-scroller engine that I started, I needed obstacles for the character (or circle) to walk on. This was done by manually typing in the coordinates and dimensions of the obstacles directly in the code. This is ridiculous and should be done with a level-editor type program, so I decided to take a stab at one. I decided to try to learn the nice-looking Java Swing layout editor. To simplify things such as file i/o, I made a stand-alone program instead of an Applet. At first, learning Swing was a huge mistake since I spent hours trying to make things work. After a while I learned the basics: the main window is a JFrame, which contains a number of JPanels which can be addressed individually. The frame can have a menu, a toolbar, and a drawing area, among other things.

The main program, which contains a menu, a toolbar and a drawing area (MapPanel which extends JPanel) is MainFrame (extends JFrame.) This contains all the event listeners and handles the "save" and "open" operations. The MapPanel is a grid of characters, each of which determine a block of a given size on the map.

The map may be saved into a text file consisting of a header telling the size of the map etc, followed by a list of coordinates of block types sorted by x.

A typical file is: (level1.txt)

200,50,636
0,0,b
0,1,b
0,2,b
1,17,b
1,18,b
2,1,r
2,13,g
...

You can open saved files. The open function first check for a logical header and then attempts to read the blocks into an Array of type "MapPoint" which is just a container for data of form (int x,int y, char type). If anything goes wrong with any of the points, the map loader jumps ship and returns false. Only if every point makes sense and the number of points is consistent with the header file does the map get loaded on screen and the method returns true.


The final time consuming part was making the program behave like a normal program. For example, if the user has already saved the file and chosen a file location, a new file dialog menu shouldn't pop up when he saves again, it should just save - something I never really thought about. Also, if the user saves then exits, he shouldn't be asked to save again, but if a save is needed, a polite program would ask of he wants to save first. To this end, boolean values for were created to denote whether a filename has been selected yet and whether a save is required.

Other challenges were making the functional part of the program convenient to use. It would be very annoying to have to draw the map by clicking each block individually. To circumvent this, a click-drag feature was implemented by checking whether the user is holding the mouse down. Also, it is essential to clear mistakenly placed blocks and to know what type of block is currently selected. I found that the best way to show this was to have an outline of the current block type hover along with the mouse cursor. Finally, for the "big picture," the user can toggle a mini map on and off by pressing m. The end result looks like this:


This now allows me to continue along with the side-scroller engine and test it out on a few simple maps. The next iteration of this program (if it comes to be) will extend the functionality of the UI by adding features like "undo" and remembering the current file directory so the user doesn't have to constantly navigate there.

The program+source code can be found zipped here, or straight out the gate here.

Thanks to Java Swing, the end results doesn't look too bad and almost resembles a real program that one might find on the internet.