Friday 17 July 2015

Painting the future

First things first, I currently have three open issues in the Github-page. 2 of them are trivial to fix, I'll probably start with them friday evening, but the memory leak will be slightly more interesting to solve. Were I leaking file handle or even naked pointers, they'd be easy to fix with a bit of macrology. No such luck though. I have a hunch I'm doing something incredibly stupid with STM. Memory-usage rises like hell when manipulating the state of the map. I thought STM-primitives carried their history all the time, but it seems I'm wrong. And I'm happy about that. In general case such behaviour would explode the already ridiculous RAM usage of JVM.

Sometimes I wonder if I romanticize the sixth-generation and older video game consoles a bit too much

Anyway, let's assume I'll get those bugs fixed on friday evening. That leaves me ˜48 hours to create new things. I should use them wisely.

First I have to parametrize hit-layer's tiles' size. I'm not certain, with the whopping 0 users this editor has, that 50px*50px isn't too big rectangle for controlling the places player can or cannot step on. I have a feeling though that it is. Thus, in the next version, hit-layer's tile-size can be anything, as long as (= h w).

In case I get really experimental, I'll parametrize the regular layers' tile-size too. It will have to be a different param though. (not= hitlayer-tile-w layer-tile-w) can be true.

Like I've spoken in the past, this map-editor will not be only a map-editor when I have realized my vision. I have this vision of a unity-like 2d-games editor with the added benefit of being Lisp all the way down, at least till you find pieces of crusty Java-machinery. So this editor will gain a possibility to load characters. They should probably be loaded as children of the Map-struct. These characters can be then moved and rotated around by either a script or a player. Animation subsystem should be easy to write.

The way I've imagined scripting to work will be different to Unity's kind. Scripts do not live in the file system. Instead they are in the same image as maps, characters, and other objects I haven't yet come up with. When editor loads an image (yes, henceforth the .memap-files editor produces are called images) it opens up an nrepl-server for scripting both the game and the engine. It also opens another server for my own protocol that dumps the image's script-files to the Emacs minor mode. This minor mode overrides find-file (C-x C-f) and save-buffer (C-x C-s) to communicate with this fileserver instead of operating system's.

Game is running in the background, rendering the scene, animations, scripts and updating AI and physics if I'll ever implement such luxury. User can edit maps and character-animations in the editor window. They can peek and poke the state of the game in REPL. On top of the game's namespaces, also editor's namespaces are open for customizing. Considering that by default Clojure's compiler (or whatever component Leiningen calls when uberjarring) keeps as much code inside a jar noncompiled as possible, it shouldn't be hard to provide the editor's sources too to Emacs through the aforementioned protocol. It should be a setting defaulted to off though, because unless user is sure to know what they want to create, they probably don't want to customize the editor.

So what am I to implement? Loading of animations (or static characters), decide what interesting properties I'm going to base my interpration of animations on (initial-frame-index, amount of sprites in a spritesheet, is-playing?, location and angle probably), and some sort of selection-rotating-and-moving tool for them. Some context-specific views on editor's sidebar would be nice too. Maybe a listbox where user could open certain frames to the pxart-editor? And replacing the animation sequence with another spritesheet without scrapping rest of the character's properties should be supported too.

Once characters can be loaded, scripted, and they can react and interact with the map, I'll probably have another go at game-design (instead of game-devtool-design). I'm a little on the fence on what I'll actually put into to game. Last October's spec on the game mechanics should be mostly applicable. Story will cause me most pain. On the other hand, the old, finnish manuscript found somewhere in merpg.webs.com is shit. On the other hand, it's my best finished game-manuscript (as opposed to a book-manuscript), and if Nintendo dares to save a princess in every other Zelda and Mario (a hyperbole, I know), I can use this as a source. I'll sell a better story to my next game then.

But, before I can take any stress of what I've written, I want to make a pxart-application (with possible dropbox-bindings) to Android! I've done it before, somewhere in Memapper's history you might even find the code for it, so it shouldn't be a long project. Hardest part will probably be finding how one commanded Android's 2D-rendering from Clojure again.

But now I'm off to sauna. Hack merrily!

Monday 13 July 2015

MEMAP-format

This is just a technical specification. If you're expecting war stories, this text might be a bit disappointment.

Specification for the memap-format

Files editor spits out are zip-files with a funny extension designed mostly to screw with prehistoric Windowses. Root of an example zip-file looks like this:

  • Map 0.memap
  • Map 1.memap
  • Map N.memap
  • initial.png
  • G__1312.png
  • G__4332.png
  • asdfgh.png

Where N means arbitrary number, and names of the pngs' aren't strongly defined. Editor creates sequential id-numbers for the inner memap-files, but upon loading they may be called anything. Only *.memap-extension is needed. As for *.pngs, only requirement for them that filename is a legal Clojure keyword

.png-files are tilesets, .memap-files contain the maps. For each .png an expression

(and (= (rem (width *png-image*) 50) 0)
     (= (rem (height *png-image*) 50) 0))

is true. I highly recommend to keep an initial.png - tileset in your file. Editor allows removing it, but skies will open and horrible things will happen if it is removed.

Each .memap-file has a clojure-map full of data. Example of this follows:

  ^{:tyyppi :map,
  :id :G__9092,
  :hit-layer ^{:tyyppi :layer...}
              [[true ...] 
               [true ...]
               ...], :zonetiles {}, 
  :name "Map 228E9"}
  [^{:tyyppi :layer, :name "New layer", :opacity 255, :visible? true}
    [;;Layer begins here
     [{:x 3, :y 1, :tileset :G__8862, :rotation 0} ...]
     ...]]

First we have a map of metadata. :tyyppi (:type in english) can be either :map or :layer. It's used in editor's multimethod-dispatching machinery. :id:s are just to ease seeking a map, and in future I might write an upgradeable format where maps are stored in a map instead of a seq, and :id:s are used keys there. Map's :hit-layer is a layer with all the ordinary metadata, and the interesting data comes next: a 2D vector of booleans. Editor/future game engine will query if player can step on a tile with the following function:

(get-in hit-layer [x y])

:name is the string visible in editor's Maps-listbox. The actual data this metadata describes is a vector of layers. Layer's metadata is in my opinion self-explanatory. All values editor cares of are present in the example above. Valid :opacity values are 0<=:opacity<=255

Layers are again 2D-vectors, where one queries tile located at (x,y) completely the same way as with hit-layer. Instead of booleans real layers consist of tile-structures.

Tile's 4 interesting values are :x, :y, :tileset and :rotation. :tileset is the key editor queries the tileset with, valid values are defined by the names of the png-files in your zip-file. :x and :y define which of the 50px*50px chunks in the aforementioned tileset tile is rendered with. The origin is, similar to most of the 2D-things, in the upper left corner. :rotation's valid values are 0<=:rotation<4. Tile is rendered in the angle of 90&dg;*:rotation.

Map's origin is also in the upper left corner

Upgrade-path

It's possible that this isn't the final format :D. In case I screw with the format of the map I'll change the inner .memap-files' extension to something else, .memapx or something, and write an upgrade procedure. If I add something else (like, for example, script files), I'll just dump them to a specific folder in the root of the .zip-package.

That's it

It's really not a complex format. Files are not exactly small, but structure is loose, with Clojure's reader-facilities made implementation unbelievably easy, and XML would've been twice bigger.

Anyway, are there details I've overlooked?

Sunday 12 July 2015

Initial release of MEMAPPER

It's released!

Wow,

Back in 2011 I incrementally developed five versions of this infamous tilemap editor and published them $deity knows where, probably in the initial F&C. Then I understood that spec was too simple, we needed a multilayered format. One which understood alpha channel and layer-transparencies Paint.NET-style. One which could rotate tiles in real-time. One which understood multiple maps per file, with multiple tilesets per file.

I created an interpration of this spec with Java. It was shit. I began a software-job, which negatively impacted the schedule. I spent most of 2012 trying to understand Linux and Lisps. April -13, I began with a new revision of clj-memapper. I hacked it till christmas and decided it was shit. I sulked until summer of '14. I hacked a better version in July, and for $deity knows why, left it rotting 80% ready for a year. Last weekend I decided that the image-thing I had tech-wanked over for two years would be the death of this thing. I wrote procedures that dump editor's state to disk and the inverse of that, plus fixed a few bugs, and released the damn thing.

Look!

It is released!

I repeat: the thing I've techwanked over for last four years is released. Feature-freeze of 2011 is finally implemented. Codebase doesn't suck. Everything is fine and underdocumented.

What's interesting is that if I do radical stuff like this more, this project called MERPG has a slight chance of shipping before my grandchildren roam the earth.

 What now?

If you have a project where you'd need tilemaps, with 50px*50px tiles, and actually understand clojure (enough to use the github-visible merpg.IO.out - functions) or are able to deduce the yet-undocumented file format (hint: editor produces zip-packages), please do give this thing a try. I'm certain there are ways to break the system, and I'd love to find them.

What next?

I'll need to document this thing. At least the file format, although one versed in Clojure (or EDN) can probably understand it easily. Do I have to create the documents that hold user's hand through the main use-cases?

After that I think a new blogpost will follow. There are some new techwankments I'd love to explore while waiting for the new story and any graphics to materialize.

Let me repeat:

MEMAPPER IS RELEASED. DOWNLOAD FROM GITHUB. 

It runs on Java, so it shouldn't matter which OS you run it on. Currently I've only tested it on Linux though, but I have no idea why it should refuse to run anywhere else. It needs at least a Java 6 JRE. I recommend the latest OpenJRE. As far as I know Oracle is still distributing ask-malware with their Windows-JRE.

Memapper is tested only on a powerful workstation. Due to Swing's software renderer and not-really-optimized code of mine Memapper might get high CPU Usage that drains laptop battery fast.

This is beta quality software. It doesn't implement Ctrl+Z - functionality (yet I hope) and might crash without a notice. If it does so, I'd love some sort of a report.