DescriptionPlatformerer is a platformer engine I programmed a few years ago as part of a game I was planning to make. In classic SmileBASIC tradition, I ultimately decided to cancel the project, but that was after I made some decent progress on the core platformer programming. I've been meaning to upload it here for a while, as I figured that sharing it would be better than just leaving it on my system forever, and I've finally gotten around to doing it! Even though it isn't finished, I figured someone here might be interested in picking it up and using it for one of their own projects, which I would love to see happen! It has a decent amount of notation, but some areas of code are somewhat lacking in that, so I'm not sure how difficult that would be, but if you're interested, give it a shot!
Platformerer includes the following features:
Pixel perfect collision with 32x32 pixel sized tiles
Smooth scrolling on both the X and Y axis simultaneously
Collision checks for all space traveled between frames (If you move more than one pixel in a frame, you can't clip through tiles)
Support for map sizes of up to 1024x128 tiles
Solid tiles as well as tiles which can be passed through coming from the bottom, but not from the top
Smooth transition when walking up and down slopes
A camera system which focuses ahead of the direction the player is facing and stays in place vertically while the player is in the air
Separate layers for collision data and background tiles
Two small test levels used for testing what was implemented
Includes a level editor with basic functionality
As Platformerer was initially planned to be a fully fledged game, it also has a few other non-platforming related features including:
Save file system capable of saving which levels have been beaten, their times, collectables earned in each level, percent completion, and total play time. Program supports three files by default, but could easily be tweaked to support more.
Title screen which can display some info from the save files
World and level select screen
The ability to aim and shoot projectiles in a Shmup style.
As Platformerer is unfinished, it currently has a few issues that would need dealing with, including:
Falling or running out of bounds results in an out of range error
Spawn point is hard coded and currently cannot be changed on a per-level basis (Easy fix really)
If player falls below the camera bounds, the camera will still not follow until the player lands on a surface
Running off of ledges does not maintain player velocity, and so running off of a downward sloping ledge results in a sort of hop.
Steep slopes can be landed on rather than causing the player to slide down (This isn't a bug in the current version, I just never implemented this feature)
Level 1-2 has a misplaced BG tile that cannot be landed on. This is because there is actually no collision tile in this space.
Occasionally while editing and testing the program, you might start getting out of memory errors. I believe this may be somewhat related to using other programs (Such as the level editor) while working on the program. If this is occurring, going to browse projects and loading up another program should resolve the issue. Of course, if you have changes you want saved, make sure you save 'em first!
Level editor is pretty lacking in features and somewhat unstable
The download also comes with a couple other programs, LVLEDIT_V0.13 and TILELOAD. LVLEDIT is used to create and save level data, and TILELOAD is used to create the collision data for different tiles. It is not recommended you use TILELOAD unless you want to add or change tile collision data.
How it works
Okay, so here's a quick rundown of the major stuff going on in this program. It's been a while since I've worked on this, so I might be a bit off on some things, but overall I think I remember most of the major concepts.
First off, the scrolling. This uses a pretty basic concept that I'm sure a lot of people here know of. Basically, instead of loading all of the BG tiles into one massive set of BG tiles, I only use a small portion of the BG layer, just enough to cover the entire screen and the outside edges. Then depending on the camera position, I load the BG data into the small section of BG tiles, and slide the BG layer around small amounts depending on the precise position of the camera. This gives the illusion of scrolling across a massive screen, even though it's really not. Uncomment lines 542 and 543 to zoom out the BG layer and see this in action. This technique allows for maps larger than SmileBASICs tile limit, which makes it quite useful. I'm not going to go into much more detail on this though because like I said, it's a pretty well known trick and I'm sure there are some other people here who could explain it better than me!
Now for the collision. First off, the maps are saved as three dimensional arrays of numerical data. The maps consist of multiple 2-dimensional layers, each layer used for a different type of data (One for collision, one for background tiles, and a few more that can be used for anything else necessary [Spawn point, enemies placement, collectibles, etc.]). The collision layer stores values the represent different collision tiles, generated by the TILELOAD program. So for example, a tile with a simple, full square of collision would be saved as a 1. The game includes another three dimensional array, which contains multiple 2-dimensional 32x32 layers of data. This is the collision data for each tile. Combining this with the level data allows for pixel perfect collision. Basically, the player's position is first divided by 32. This determines which tile in the level the player is currently located in. Then, the remainder from this calculation is used to determine the player's position within the tile. This value is checked against the array of tile collision data to determine whether or not the player is colliding with anything. This collision check is also repeated multiple times per frame depending on how fast the player is moving, to make sure the player cannot clip through objects.
This area is a bit blurry for me (As I did a lot of experimenting and tweaking here), but I believe collision is not checked on all pixels surrounding the player, only necessary locations. This was done for optimization purposes. Besides stopping the player from moving through objects, collision checks are also made for things such as slopes. If the game detects that the ground is dropping, but only by one pixel, the player will get moved down one pixel, making for a smooth transition rather than the player going airborn. A similar principal applies for upward slopes, where it will move the player up one pixel rather than simply colliding. Other checks are done for things like the one way platforms. That's about all I can remember regarding the collision.InstructionsThe download includes three different programs. Below are instructions on how to use each. Note that, due to the unfinished nature of these programs, there's a general lack of polish
This is the main program. Starting it for the first time will present you with some prompts to create save files. Just press A to get through these. After this you will be presented with a logo and then the title screen. Press any button to bring up the file select. Select a file to bring up the options for that file. Only start, delete, and back work, the other options (Options and copy) were never implemented.
After starting the game, you will be presented with a World select screen. A few things to note about this screen:
D-Pad allows you to cycle through unlocked worlds (Worlds can be unlocked by marking levels as unlocked in the next screen. This really doesn't matter though as there are only two levels. You could add levels if you wanted, of course!)
A will select the currently displayed world and continue to that world's level select screen.
Y will bring up a series of prompts allowing you to customize the file play time (Seconds, minutes, and hours) and percentage of completion. This is used for debugging purposes. Note that these values must be set in order for the info to show on the title screen, and not the usual "New Game" text.
X will save the file. Make sure you do this after setting the game progress with Y!
Once you reach the level select screen, you can press B to go back to the world select, or A to select the level. When you select the level, you can either press A to play it, or B to debug it. The debug menu allows you to set parameters on the state of the level. Press A to change the values, and B to return to the previous screen. Most are bools, where 0 is false and 1 is true. The best time parameter will bring up a keyboard prompt allowing you to enter a value. Parameters you can set are, in order:
Mark a level as complete
Collectible 1 earned
Collectible 2 earned
Collectible 3 earned
Collectible 4 earned (The idea was that these would be like the four KONG letters of this game. This engine was highly inspired by the play style and movement of the DKC games!)
Set best time
This player has the best time for this level (Rather than it being the default best time, which would be a challenge for the player to beat).
Floppy 1 collected
Floppy 2 collected
Floppy 3 collected
Floppy 4 collected
Floppy 5 collected (More collectibles. There wouldn't have necessarily been five of these per level)
When you first start the game, only level 1-1 will be accessible. In order to be able to select level 1-2 and later, all previous levels must be marked as beaten through the debug screen. So to access level 1-2, select level 1-1, press B to access the debug menu, set "Did you beat it?" to 1, press B to return to the previous screen, and then press right on the D-pad to select level 1-2. Marking all the levels in a world as complete will unlock the next world on the world select screen. You can also save any info set in a level's debug screen by returning to the world select screen and then saving the file. Note that you must do this before playing the level, as there is no way to return to the menu once you load a level. This could probably be fixed very easily if desired.
Once you hit play, the selected level will be loaded. The controls are:
D-Pad: Move and aim
R: Aim diagonal up
L: Aim diagonal down
The character you control is a transparent orange square with two lines. The white pixel where the lines intersect is the point where collision is checked. You can run around levels and watch basic platformer stuff happen. WOW! In the top left you'll see three values. The top is your cooldown timer (You can only shoot when this is below 0. For some reason I never capped it so it continues to drop endlessly...), the next down is either your horizontal speed or the number of pixels you moved horizontally in the current frame (It's been a while since I worked on this so I'm not entirely sure which) and the third value is the same for vertical movement. There's really not much left to do at this point other than check out the code and see if you can find something useful, or use the level editor to create your own test levels. Note that if you wish to change your spawn point, you can do so at lines 569 and 570. Change the values assigned to PX and PY to change the horizontal and vertical positions respectively. You could also create conditional statements, setting spawn for each level individually, using the WSLCT and LSLCT variables to determine which level was load (World selected and level selected respectively).
Note: In order to best use this program I recommend loading it in the editor.
So this is a basic level editor I was creating alongside the game, as SmileTOOL's Map tool didn't offer all of the functionality I wanted. This editor was never intended to be user friendly, so if you wish to use it, there are some quirks you'll have to get used to.
Upon running the program, a basic default map is loaded with a few different tiles floating around. Note, that if you wish to load an existing map, you must
Edit line 33 to load the level data file you want. The name format for levels is "LVL_[WORLD NUMBER]_[LEVEL NUMBER]", so if you wanted to load level 3-2 (assuming it existed), you would need to change the file name to "LVL_3_2".
Once you have the desired level name set here, simply hold A when running the program to have it load the level (Note that the levels included with the download have all of their contents at the bottom, so you'll need to scroll all the way down to see them).
A quick guide of what each element of the editor is:
The top screen displays a wider view of the level. The red lines represent the portion of the screen being displayed on the bottom screen.
The top screen values are:
LYR: The layer currently being edited. 0 is for collision data, 1 is for BG tile data.
CX: The X position of the top screen camera.
CY: The Y position of the top screen camera.
The grid on the left side of the bottom screen can be touched to place tiles.
The tiles displayed on the right side of the touch screen can be tapped to be selected. The top left option always displays the currently selected tile, regardless of which page you are on. Tap this to set the currently selected tile to nothing.
The arrows at the bottom right of the tile selection section can be used to scroll through pages of tiles. Note that the last page contains some 16x16 pixel tiles that are unused and won't do anything in your level (In fact, they might produce an error if you try loading a level with these tiles in the game).
The two numbers on the bottom left of the bottom screen display the X and Y coordinates of the last placed tile respectively.
ROT on the bottom screen displays the current rotation value of the tiles you are placing. MIR displays the mirroring value. These values only apply to the tiles place-able when editing layer 1.
When editing layer 1, you will see both the BG tiles and the collision tiles so that you can easily make sure your BG tiles line up properly with the collision
Once you're in the editor, you'll start with the collision layer selected. By touching the grid on the bottom screen, you can place the currently selected tile (Displayed in the top left corner on the collision layer, meaning you won't see it in game, but you will still collide with it.) Select tiles with the icons shown on the right of the bottom screen. Note that yellow represents solid collision that cannot be passed through, while red represents collision that can be passed through from below, but not from above, meaning you can jump from underneath these tiles and then land on them. Press R to change to layer 1, which allows you to edit BG tile data. When doing this, you will still be shown the collision data so you can easily line your backgrounds up with the collision data. Press L to switch back to the collision layer.
When editing layer 1, A can be used to change the rotation value. X can be used to change the mirroring value. Note that this is not implemented for collision as it is simply not needed, as there is a collision tile for all of the basic tiles shapes I've included (Although upon further inspection I've found there is one collision tile type missing).
Pressing Y at any time will allow you to save the level. Make sure you use the name scheme "LVL_[WORLD NUMBER]_[LEVEL_NUMBER]" if you want to make it loadable by the game. Also note that if you back out of the save prompt the program will crash, so if you don't want to lose your current level design, be sure to save it as something!
TILELOAD is used to create the TILE data file that the game uses to load it's tile collision data. This program has three steps to it.
First it will go through the process of scanning the tiles drawn on graphic page 4, which are loaded from the "SP_BETATILES" file. As it scans this graphic, it loads the arrays for the different tile types with the collision data. Every empty pixel is a 0, every yellow pixel is a 1, and every red pixel is a 2 (Those numbers might be off). If you were to alter these sprites and then run this program, you would change the tile collision data. During this process, a graphical representation of what is currently being scanned is displayed. Holding A will slow the process down giving you a better idea of what's going on. Different BEEPs play depending on the color of the pixel currently being scanned. The value displayed in the center is the current tile value being scanned in. The number on the left is the color value of the pixel currently being scanned (I could be wrong on those last two sentences, however).
After it completes this process, a save prompt will be displayed. Save the file if you wish to overwrite the existing TILE file (I recommend making a backup of that first if you decide to mess with this program).
After this (whether you saved or not) you will be able to view the generated collision data graphically. Use left and right on the D-Pad to scroll through different tiles. Note that going below 0 or above 31 will crash the program.
As previously mentioned, you really only need to use this program if you want to add or alter tiles for collision.NotesIf you decide to use this for your own project, please be sure to remove my logo, but I also ask that you would still credit me!