A Platformer Template with Level Editor (in-progress)

Started by RootBound, Fri 11/04/2025 19:48:07

Previous topic - Next topic

RootBound

So I've noticed that people often ask if it's possible to make platformers with AGS, and they get the same answer: Yes it is, here's an example, and no, we don't support tile-based drawing of rooms.

I'm trying to expand that answer to: Yes it is, and here's a working game template, and yes, the template lets you draw tile-based room backgrounds.

So far the code has been full of hurdles, but I've made great progress today, so I wanted to announce the existence of this endeavor.

For now, enjoy the results:

They/them. Here are some of my games:

brushfe


Rik_Vargard


RootBound

Layer support enabled.  :)  Now I need to implement very silly things like actually being able to scroll around the room. (laugh)

They/them. Here are some of my games:


Matti

Nice work!

In case you don't know, abstauber also made a tile-based platformer engine a long time ago. I never really tried it out though and the links seem to be dead.

abstauber

Nice work indeed, this also caught my attention and it looks pretty good  (nod)

Btw. dkh also did a tile based game in 2007 with an ASCII art text file serving as a tile map.
https://www.adventuregamestudio.co.uk/play/game/933/

oh, and here's a screenshot of my tile editor (based on DKH's work).


Unfortunately I never managed to finish it, the last showstopper was implementing at somewhat acceptable pathfinding. But if it's on github, in case you're curious:
https://github.com/dkrey/ags_krokus

RootBound

@abstauber that's incredible. It looks far more advanced and comprehensive than my method.

At the moment what I have looks like this to the end-user:

-Import all tile sprites into the AGS editor
-Set room size using regular AGS room editor
-Designate tile sets in script (e.g. sprites 1-16 belong to tile set A, and so on)
-Run the "game" (level editor)
-Use level editor to place tiles on grids (supports up to 4 layers, after that it gets very slow)
-Export each layer as a .pcx (alternative is .bmp, those are the only two AGS export formats)
-Choose a specific layer to export as a walkable area mask (tiles will not be walkable, everything else will--this is required by my platformer game template I'm making)
-Convert .pcx files to .png using outside program (AGS cannot import .pcx). I don't like this step, but the alternative is exporting as .bmp, which is space-inefficient.
-Import each tile layer as an object in the room
-Import walkable area mask (which should match the "normal" ground tile layer).
-Place objects in the room using normal AGS room editor (room object limit is 256, which is tricky if you want, for example, 100 coins to collect plus lots of other interactive objects--I'd prefer to generate these with overlays in script, but haven't figured out a way to make that work)
-Set a single hotspot for all objects of a given type, so that interactions can be handled in script modules.
-Everything else (character movement like falling, collisions etc) is handled in script (part of my platformer game template-in-progress)

So I wouldn't call it an "engine" and maybe more of a "tool" to use within the AGS editor.

I don't currently feel like it's robust enough for a general end-user, but it does work.

What are the end-user steps involved in your system? Can the user import sprites without using the AGS editor? Are files exported at all? I'm really curious how you handled it (and I admit your code is slightly above my comprehension).

Thanks very much!
They/them. Here are some of my games:

Crimson Wizard

#8
Quote from: RootBound on Mon 05/05/2025 16:27:59-Export each layer as a .pcx (alternative is .bmp, those are the only two AGS export formats)
-Choose a specific layer to export as a walkable area mask (tiles will not be walkable, everything else will--this is required by my platformer game template I'm making)
-Convert .pcx files to .png using outside program (AGS cannot import .pcx). I don't like this step, but the alternative is exporting as .bmp, which is space-inefficient.
-Import each tile layer as an object in the room
-Import walkable area mask (which should match the "normal" ground tile layer).

I did not realize that the purpose of this is to export room images with intent to reimport them back.
Usually, with the level editor, one would expect it to save a level as a data (either in binary, or a textual format) that may be loaded in game and have level imagery recreated at runtime from the same tiles. This way:
* the workflow will speed up significantly;
* you may also have unlimited number of levels in the same room;
* you may edit the level and test run it right away from the same game.

On another hand, if you prefer to have levels as series of images that may be imported in the AGS room editor, then there are existing tools that let create such "levels". For example, there's a Tiled level editor, which, I assume, may be used for that purpose.

EDIT: Of course, none of the above excuses AGS from not supporting loading and saving PNGs at runtime, that is something that should have been added years ago, but still is not. Also, Editor could let import PCX files, since AGS engine saves these.

RootBound

@Crimson Wizard you make good points. I'll have to consider whether to try to rewrite my current system to accomplish this.
They/them. Here are some of my games:

abstauber

Don't worry, I also need to re-understand the code every time I work on it. I wrote it more than a decade ago, back when AGS didn't support dynamic arrays.

AGS is actually able to import PCX files, at least at runtime ;)
https://adventuregamestudio.github.io/ags-manual/DynamicSprite.html#dynamicspritecreatefromfile


The way I implemented the tile engine (and I had lots of inspirations from DKH) is that I ignore most room functions and just draw on its surface.

In an external tile editor you need to create a tile map and export the tiles in a long row of tiles / tile strip.
Everything else can be done in the ingame editor, map size, walkable tiles, harmful tiles and so on.

For tile animations a view can be assigned for each level and a loop can then be assigned to a tile.

The work flow can be this:
* Import a tileset
* If you want moving platforms, also import platform sprites

* Run the game
* Enter the editor room
* Create a new level
* set the map dimensions, sprite slots and view
* click through the tiles and mark them as either as solid, ramp, hostile and so on
* Draw the level, place enemies, set items, waypoints and so on.
* Save the level
* Close the game
* Create a room and tell it to load the level, you just created
* Let the player character start in the room and see if it works.
* From there on you can edit the level in game by going the editors room and switching back the level's rooms.

RootBound

Fascinating. Can't imagine how you did this without dynamic arrays.
Quote from: abstauber on Today at 07:39:56* Save the level
* Close the game
* Create a room and tell it to load the level, you just created
So when you save the level and load the level, where is the data being saved, and how is it being loaded?
They/them. Here are some of my games:

abstauber

Since you can only read/write to these directories, $INSTALLDIR$, $SAVEGAMEDIR$ and $APPDATADIR$ (not even sure about INSTALLDIR) I chose to store my files in $SAVEGAMEDIR while they are still in development and I would have shipped the level in $INSTALLDIR.

The level files are custom binary files, created by the editor.
TENG::load_map and TENG::save_map can be found here:
https://github.com/dkrey/ags_krokus/blob/main/TENG.asc

They consist mostly of simple looped file writes like this:

Code: ags
  //Save BG Tiles
  j=0; 
  index = 0;
  file.WriteInt(bg_tile_cnt);
  while ( j < num_tiles_y ) {
    i = 0;
    while ( i < num_tiles_x ) {
      if (tile[index].tileno[0]>0) {
        file.WriteInt(index);
        file.WriteInt(tile[index].mirrored_x[0]);
        file.WriteInt(tile[index].mirrored_y[0]);
        file.WriteInt(tile[index].tileno[0]);
      }
      index ++;
      i++;
    } 
    j++;
  }  

SMF spam blocked by CleanTalk