$Id: MAP_HACKERS_GUIDE,v 1.6 2006/09/21 03:18:27 gmcnutt Exp $ MAP HACKER'S GUIDE TO NAZGHUL/HAXIMA "The map is not the territory." --Alfred Korzybski INTRODUCTION So you want to modify Haxima? Or maybe you find Haxima pathetic and know you can do better. Then you've come to the right place. The Haxima scripts will give you lots of examples on how to do things, if you can figure them out. Since you're a smart guy I'm sure you can, but an explanation here or there might speed things up. Here you'll find a discussion of the principles of how to build a game like Haxima with the nazghul engine. This manual is still in its infancy. If you don't find what you're looking for feel free to email requests or suggestions to nazghul-devel@lists.sourceforge.net Happy hacking! CONCEPTS COMPOSITE SPRITE First, see SPRITE. A composite sprite is a sprite made up of layers of other sprites. GOB Scheme data associated with a kernel data structure. The kernel never accesses this data, it is meant to be used by scripts to customize or augment these data structures. Objects, object types and astral bodies all optionally have gobs. OBJECT Something which exists on the map and is not part of the scenery. OBJECT TYPE Read-only data associated with and shared by a class of objects. A type is a kernel data structure which describes attributes that are common to an entire class of objects. For example, all short swords have the same sprite and basic attributes, and all sword objects refer to the sword object type to provide these attributes. In fact, simple objects like short swords may be implemented in the kernel as little more than an object type and a location. There are several classes of object type: a generic base class, an arms type, a vehicle type, and a field type. Every object type class has a fixed set of attributes. These can be extended by the script, however, by attaching a gob to the object type. SPRITE An animation sequence which shows an object. Every visible object has a sprite. Sprites can be composed of other sprites, see COMPOSITE SPRITE. SPRITE SET Usually sprite images are collected into files with lots of images in them. A sprite set refers to the file and stores information like how big the images are, how many are in the file, etc. Sprites refer to sprite sets. Different sprites can share some of the same images, although few ever do. TAG A name given to a kernel data structure so that it can be referred to by a scheme variable. Tags are important because they can be used when saving a game to allow objects to refer to one another when the game is reloaded. QUICK START: HOW TO CHANGE A MAP Start haxima with the -d option: $ haxima -d Start a game, then invoke the terrain editor using the Ctrl-T command. Like a paint program, terrain editing has the concept of a current "brush", which is a terrain type. The following keybindings are in effect: Arrow keys - move the cursor [0-9]-Arrow - jump the cursor Space/Enter - change the terrain under the cursor PgUp/PgDn - scroll the available terrain list to change the brush Home/End - jump to the top or bottom of the available terrain list C - copy; set the terrain under the cursor as the brush F - terrain fill (uses the 4-neighbor algorithm) ESC - abort eddit mode Ctrl-[0-9] - save the brush in a "quick access" terrain slot [0-9] - load the brush with the quick access terrain slot "Quick Access" slots start as all walls. Palette.scm holds the list of terrain types. When you are done editing, save the game like you normally would. Your changes will be there the next time you start the game. If you want your changes to be part of a game started from "Start New Game" the current process involves modifying some Scheme files. To add your changes to the "Start New Game" scripts you need to find your changes in the file you saved and copy-and-paste them into the proper startup .scm file. In general, you must find the name of the place which is using the map and search for it in the .scm files, then replace the starting map with your own. KERNEL API This section documents the kernel calls available to scripts. The document format is moduled after the UNIX man pages, which, like so many things in UNIX, have served well enough over the last 30-odd years to be worth emulating. ---------------------------------------------------------------------------- NAME kern-sprite-apply-matrix - apply a color conversion matrix to a sprite SYNOPSIS (kern-sprite-apply-matrix ) DESCRIPTION The purpose of this is to alter the colors of a sprite. The idea is you create one sprite, probably in grayscale, and use this procedure to make different colored variations of it. This works by applying the matrix to the sprite, resulting in a linear remapping of the sprite colors to another set of colors. The matrix is in the form: (list (list ) (list ) (list ) (list )) This matrix is applied to the red, green and blue components of each pixel in the sprite like this: r = R * c00 + G * c01 + B * c02 + k1 g = R * c10 + G * c11 + B * c12 + k2 b = R * c20 + G * c21 + B * c22 + k3 Where r, g and b are the result and R, G and B are the original values for the pixel. The result for a component will be clamped to [0, 255]. The underlying image is copied before being modified. This means that if the sprite is a clone of another sprite, the other sprite will not be modified. RETURNS The modified sprite. If something is wrong with the arguments it returns the original, unmodified sprite. EXAMPLES This applies an identity matrix, which does nothing: (kern-sprite-apply-matrix ksprite '((1 0 0) (0 1 0) (0 0 1) (0 0 0))) This matrix will convert a grayscale image to blue: 0 0 0 0 0 0 0 0 1 0 0 0 This will swap red and blue: 0 0 1 0 1 0 1 0 0 0 0 0 This will lighten every pixel by a fixed offset: 1 0 0 0 1 0 0 0 1 64 64 64 This will darken every pixel by a scale factor: 0.5 0 0 0 0.5 0 0 0 0.5 0 0 0 ---------------------------------------------------------------------------- NAME kern-sprite-blit-over - blit one sprite over another one SYNOPSIS (kern-sprite-blit-over ) DESCRIPTION The images of the destination sprite will be copied and then modified by the blit, so you don't have to worry about other sprites that refer to the same images. The two sprites should have the same number of frames and the same dimensions or the results are not defined. The modification will not be saved with the game, so it needs to be redone at load time. Blitting over uses more memory than decorating sprites because it makes an extra copy of all the sprite frames. It is faster, though, because it only blits all the sprite components once when it is created, instead of every time it is rendered. Blitting is also preferrable for composite weapon sprites, because composite sprite building does not have good support for recursively composite sprites. Unreadying composite weapon sprites will strip them down to their bare sprite. But weapon sprites built via blitting over do not have this problem, because stripping down a blitted-over sprite has no effect. RETURNS The modified destination sprite. EXAMPLES (define s_fancy_shield (kern-sprite-blit-over s_shield s_emblem)) ---------------------------------------------------------------------------- NAME kern-sprite-clone - copy a sprite SYNOPSIS (kern-sprite-clone ) DESCRIPTION Use this when you want to make a modified version of a sprite but still want to keep the original intact. You can assign the clone its own tag and henceforth refer to the tag as a scheme variable, or you can pass in nil and just use the return value. RETURNS The cloned sprite, or nil if 'original' was a bad arg or a memory allocation failure prevented creation of the clone. EXAMPLES ;; Clone grass and turn it brown to make dirt (kern-sprite-clone s_grass 's_dirt) (kern-sprite-apply-matrix s_dirt green-to-brown-matrix) ---------------------------------------------------------------------------- NAME kern-type-set/get-gob - associate scheme data with an object type SYNOPSIS (kern-type-set-gob ) (kern-type-get-gob ) DESCRIPTION kern-type-set-gob associates 'cell' with the object type 'ktype', so that it can later be found by scripts via kern-type-get-gob. 'ktype' must be the result of a call to kern-mk-obj-type. The purpose is to add game-specific information to a kernel data structure so that closures called from the kernel can find it. This information is not visible to the kernel. Unlike the gobs attached to objects, gobs attached to object types are not written to the save-game file. For that matter, object types are not written, either, and must be reloaded for every game. ---------------------------------------------------------------------------- NAME kern-sprite-strip-decorations - remove all decorations from a base sprite SYNOPSIS (kern-sprite-strip-decorations ) DESCRIPTION Remove all decorations from and discard them (see sprite_append_decoration()). Useful for rebuilding decorated sprites from scratch. This does not remove layers built via kern-sprite-blit-over. RETURNS The base sprite. EXAMPLES ;; Make a ship with sails. (define s_ship (kern-sprite-append-decorations (list s_ship s_sails))) ;; Nah, changed my mind. (define s_ship (kern-sprite-strip-decorations s_ship)) ---------------------------------------------------------------------------- NAME - SYNOPSIS () DESCRIPTION RETURNS EXAMPLES