# Skins

You can change the sokoban visual elements (wall, box, goal, etc.) via a skin. With different skins YSokoban will look in a different way. Function keys F3 to F8 can be defined to use different skin for each key. YSokoban can automatically resize skin, but smaller skins doesn't look good when enlarged. It's better to have large skin and resize it down to smaller size. So all skins with size more than 40 pixels are considered resizable by default. Following keys control resizing:

key | action
--- | ---
* | toggles auto-resizing on/off.
= | switch auto-resizing off and set skin to it's default size.
# or ` | toggles auto-resizing algorithm (there are two possible algorithms it depends on skin which one is better).
- or [ | stop auto-resizing and use skin with one pixel less size than current
+ or ] | stop auto-resizing and use skin with one pixel greater size than current
S or A | Iterate over skins in skins folder (subfolder where YSokoban.exe is). A/S will iterate backward/forward on skins there.

## Skin options dialog

Activated via main menu -> Skins. It brings a dialog where one can define which skin (bmp or png file) to be used for every functional key. Usually skins are copied into folder where YSokoban resides.

Other options in this dialog has following meaning:

- Show grid in a level (Ctrl-Fx for opposite, where x is the func-key number)
  There is a description in a skin whether there is grid allowed.
  If grid is allowed for that skin then it will be displayed.
- Show dotted grid (uncheck to show lines)
  Grid consists of several pixels of some color (in default YSokoban skin, they are white) visually marking cells or it can be configured (with this option) to show lines instead of dots.

- Auto shrink size if level is smaller
  Will automatically reduce size of YSokoban window if level size is smaller than current widow.
  This options was used before support for resizeable skins. It has no effect if skin resizing is switched on.
- Auto enlarge size if level is bigger
  Will automatically enlarge size of YSokoban window if level size is bigger than current widow.
  This options was used before support for resizeable skins. It has no effect if skin resizing is switched on.
- Skin resizing buttons (*,=,+,-) have global effect (on all skins)
  If checked then auto-resizing (and selected skin size) will have effect on all skins, if not selected then all settings (regarding skin resizing) will have effect per skin (i.e. you can use different settings for different skins).
- Show unreachable cells as outside cells - will show unreachable internal cells in a same way as outside cells
- How to paint squares outside of the level:
  - Background - use specified background image (use browse button to select one)
    - Center - image will be centered
    - Tile - image will be used many times to cover the background
    - Stretch - image will be stretched
  - Use skin - will use skin image
  - Use skin color - will use defined color in skin
  - Use dialog color - will use color of a dialog box in Windows (i.e. usually gray)

Example: Show/Hide grid (try with default skin pressing F7 and ctrl-F7 to show/hide grid):

## Skin file description

Skins for YSokoban started as a simple BMP file. Intention was to keep them as simple as possible and preferably to have just one file, so that user should not take care for folders with files, keeping together several parts of a skin (if tiles are different images and/or if there are some special text file in addition to a bmp).

NOTE: the word "cell" and "tile" are used interchangeably in this file.

### Old skin format

What YSokoban needs is following:

- walls (all possible variants)
- man, on empty tile and on goal
- box, on empty tile and in place (on goal tile)

In YSokoban it is possible to select box or man and click on some tile and man will push box there (or will just go there). So YSokoban needs a way to mark selected object. Best thing is to have this animated. When level is completed then same animation is used for all objects.

All walls (at that moment) are represented by 16 possible tiles. So they occupy 4x4 tiles from image.

For animation YSokoban uses one row per object - man, man on goal, box, box on goal. This takes 4 more rows. First two rows are used for empty tile, man and box, on next row I have goal, man on goal, box on goal. Two unused tiles were used to put invalid selection for boxes.

(I think YSokoban still supports it, but does not scale it, i.e. it is not resizeable).

Later on I realize that there are some features I want to have, but it is not possible with this skin. This is:

- have a tile to put outside of level
- there are much more possible walls if we want to fill with flat walls large area of a level.

For example compare following level:

    ########
    #-.--$-#
    #-####-#
    #-####-#
    #-####-#
    #----@-#
    ########

whith old style skin (on the left) and with new one (on the right)

### New skin format

New skin format was designed to serve this needs, but it is not possible anymore to have all possible tiles (or should I say, it will be not nice to draw all of them). Instead we draw only building parts of a walls and combine them on the fly.

New skin format has same tiles as the old one, except walls (which were totally rearranged) and one tile for out of level was added.

To be more precise:

- row 1 (empty cells): floor/space, player, box, box not accessible
- row 2 (goal cells): goal only, player on goal, box on goal, box on goal not accessible.
- row 3 cross wall, horizontal wall, flat wall, outside tile
- row 4 vertical wall, single wall, unused tile, description tile
- row 5 .. 8 are animation frames (same as in old skin):
  - row 5 are the four animation frames for the player.
  - row 6 are the four animation frames for the player-on-goal.
  - row 7 are the four animation frames for a box.
  - row 8 are the four animation frames for a box-on-goal.

The animation frames are played from left to right.

Wall construction is done in the following way: Every wall tile consist of four parts (see skinExample above, building parts of skins are marked). When the program needs wall it creates it by using appropriate parts from given 5 wall cells. Normally this four parts are equal by size, but sometime they are not (because wall is shifted to the upper left part of a square and provides some shadow on the lower right part. So we need a way to specify how exactly it is divided - how large is left part and how large is upper part. For that purpose we use second empty square. If it is filled with same color - then by default program divides square in equal pieces. If there is some line starting from upper corner to the left then it's length is used to form the X size of leftmost piece and the length of vertical line is used to form the Y size of topmost piece.

The rest of this square is used to mark squares which could have grid marks inside. For more information, read the section "More information on the description tile" below.

Box in Row 4 column 3 is not used at all and in example, the author puts his name there.

The above level (shown with old skins), now looks better with new skin (because parts are marked you can see how they are constructed).

#### More information on the description tile

That's the tile on row 4, column 4, counting from left to right, top to bottom.

This tile should start with only one color for the entire tile. So, it can be colored white, black, red, or whatever. Just color the whole tile with the same solid color.

Other color can be added to this tile to describe two things:

##### To describe how to divide each of the wall tiles.

Draw a one-pixel line, with a different color than the tile, starting from the upper-left corner of this tile to the right. Draw another one-pixel line, same color as the horizontal line, starting from the upper-left corner of this tile straight down (a vertical line).

These two lines combined shows how to divide each of the five wall-tiles.

YSokoban's skin is setup this way because there are times in which you want to divide the wall-tile differently to allow shadow to show properly.

By default, (meaning if there is no horizontal or vertical line, the entire tile is just one solid color), YSokoban will divide the wall tiles into 4 equal parts.

##### To describe which tile to show grid and what color.

Please compare the files "skinExample1.png" and "skinExample1_without_net_mark.png" (download skins_description.zip from skins page on YSokoban site). Specifically, compare the right-most tile on row 4.

The two skin files are identical except that the one shows the grid-mark, one doesn't.

The grid-mark area in this tile is an 4x8 pixel rectangular area. Note that this 4x8 area is not part of the two lines that's used to describe the wall-tile division. If we assume the upper-left corner pixel of this tile is position (1,1). This 4x8 area starts at (2,2). Each pixel of this 4x8 area corresponds to one tile of the skin. (Note that the skin is a 4x8 tiles)

This 4x8 area also need to be the same color as those two lines that's used to describe the wall-tile division. Furthermore, this color is also used as the "grid" color.

skinExample1.png indicates that every tile will have a grid, and the color for the grid is a lighter gray than the floor.

skinExample1_without_net_mark.png indicates that there is no grid. So, if you press CTRL+N, doesn't show a grid.

Also, you don't have to mark every tile to show the grid. You can specify the grid for some tiles and leave some unmarked.

In the sf_100z_greenRed_gray.png skin, it shows that the tiles in row 3 and 4 doesn't have a gird. Load the skin into YSokoban and check out the result of the grid.

There is also a good reason for not having a grid-mark at all in the skin. Sometimes tiles are designed in such a way that there is no need for artificially added grid and/or such a grid will spoil the design. For such tiles we remove the grid. Usually this is either all tiles (because there is natural grid for them) or only walls (because grid over walls will spoil wall design). For example, look at the sf_100rg24.png skin, it has "grid" built-in already.

##### Special RGB marked skins

YSokoban prior to version 1.805 will always refuse to put grid outside of the level.

Since version 1.805 YSokoban will put grid even on cells outside of the level if appropriate pixel in grid definition is set. This means pixel for row 3, cell 4 (if we number rows and columns starting from 1).

All skins (already created) usually contain pixel there and this will result in showing it. In order to keep backward compatibility and still have this option YSokoban will consider this pixels only if skin has special mark. This special mark is one red, one green and one blue pixel in other 3 corners (as shown on the image).

Now outside cells will also respect grid pixels. Moreover grid in cell will be drawn using provided color.

Same as above, but additionally all border walls will be drawn using alternative wall cell

Same as the first one, but all internal walls will be drawn using alternative wall cell

Same as above, but alternate wall will be used only inside flat part of internal walls

The only unused cell is used for alternative wall cell. From the example above this is the cell with copyright in it which up to now is not used. So if alternative wall cell is needed then even this cell is used and the only place which remains for copyright and author name is actually the cell with this special RGB marks. This means all other pixels (not used for RGB, and wall mark) are still not used and author can put his name there. To name used pixels in RGB mark: first column, first row, upper left block of 4x8 pixels, plus all corners.

##### More technical details on how YSokoban process the description tile (right most tile on row 4):

YSokoban gets pixel 0,0 (I'm talking with relative coordinates inside this cell) and scans first row horizontally and first column vertically. When it gets pixel with different color (up to the end of cell) then this is X and Y length to be used for dividing walls, if X = Y = cell size (i.e., nothing defined) then YSokoban simply assumes that division shall happen at the middle (as it is usually). Then it scans all 4x8 pixels to get which cells are allowed to have grid (those which has same color are allowed). Which means that if you left this tile (4x4) empty, i.e. filled with one color, then this means - divide walls in the middle and all cells may have grid. The rest of cell is not used. This means that from entire cell we use topmost row, leftmost column and 4x8 pixels from 1,1 to 4,8. The rest is not used at all and could contain whatever we please (including another copyright image).

New special RGB mark is used like this: checks for red, green and blue color in other corners:

- 0, xsize-1 shall be green
- xsize-1, 0 shall be red
- xsize-1, xsize-1 shall be blue

If it is like this (pixel is consider red if R > G+B), then background color is used from xsize-2, xsize-2. All pixels used to check for grid are compared against this bg color, if pixel is different than background then it is considered set and color for net is the pixel color.

Thanks to Ming for suggestions and improvements.

Created with Ywiki