Click here to Skip to main content
15,885,216 members
Articles / Multimedia / GDI+
Article

Tile Editor Control

Rate me:
Please Sign up or sign in to vote.
4.88/5 (20 votes)
29 May 2008CPOL3 min read 80.2K   3.4K   70   5
A control to edit maps or small pictures in tile form.

screen1.png

Introduction

The TileEditor control edits a grid of tiles. It can be used to quickly create fast editors of tile based games. It supports 2D grids with multiple layers, and can paint relatively fast using GDI.

The current version supports editing of small and medium maps, mutliple selections of tiles, copy and pasting of tiles and multiple undo and redo actions.

Background

Frequently, I have needed a Tile Editing control so I can quickly make editors to edit maps for Tile Based games. None were around at the time, so I decided to create my own. The control is a quick painting tile editor, letting you create editors of many kinds quickly and easily.

History

  • 2.0 (27th May 08)
    • Added selection of tiles.
    • Added copying and pasting of tiles.
    • Added undo and redo actions

Using the Control

Painting the map

The TileEditor control can be used like any other control. The map and tile sizes are simple properties which you can change in design time and runtime. To add spacing between the tiles, you can set the TileSpacing property to the number of pixels you want between the tiles. To draw the tiles, there is an event called PaintTile which is passed a TileEventArgs instance which contains the location of the tile that is being drawn and the PaintEventArgs instance. You can then paint anything you like; the following example is from the demo which paints the tile image inverted if selected or normally if not selected.

C#
private void TileEditor_PaintTile(object sender, TileEventArgs e)
{
    int tile = TileEditor[e.Location];
    Bitmap b = (Bitmap)GetTileImage(tile).Clone();

    if (e.Selected) {
        e.PaintArgs.Graphics.DrawImage(TileEditor.InvertBitmap(b),
            e.PaintArgs.ClipRectangle, new Rectangle(0, 0, 32, 32), GraphicsUnit.Pixel);
    } else {
        e.PaintArgs.Graphics.DrawImage(b,
            e.PaintArgs.ClipRectangle, new Rectangle(0, 0, 32, 32), GraphicsUnit.Pixel);
    }
}

Editing the Map

To edit the map, you will need to add the MouseDown event. This is passed the MouseTileEventArgs instance, which includes the location of the tile that was clicked. You can add code to change the tile in any way; in the demo, there are two selected tiles (one for the left mouse click and one for the right). If shift is held down, it will edit the bottom layer instead of the top layer. For continuous editing when dragging, you will need to do the same code in the MouseMove event. To make it more efficient, you can record the last tile the mouse is on, and only edit the tile if the last tile is different from the current tile. An example is as follows:

C#
private void TileEditor_MouseDown(object sender, MouseTileEventArgs e)
{
    TilePoint pt = e.Location;
    if (ShiftDown)
        pt.Z = 0;
    else
        pt.Z = 1;
    if (e.MouseArgs.Button == MouseButtons.Left)
        TileEditor.SetTile(pt, LeftTile);
    else if (e.MouseArgs.Button == MouseButtons.Right)
        TileEditor.SetTile(pt, RightTile);
}

TilePoint LastMouse;
private void TileEditor_MouseMove(object sender, MouseTileEventArgs e)
{
    TilePoint pt = e.Location;
    if (ShiftDown)
        pt.Z = 0;
    else
        pt.Z = 1;
    if (pt != LastMouse) {
        if (e.MouseArgs.Button == MouseButtons.Left) {
            TileEditor.SetTile(pt, LeftTile);
        } else if (e.MouseArgs.Button == MouseButtons.Right) {
            TileEditor.SetTile(pt, RightTile);
        }
        LastMouse = pt;
        RefreshSelectedTiles();
    }
}

bool ShiftDown;
private void Editor_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Shift)
        ShiftDown = true;
}

private void Editor_KeyUp(object sender, KeyEventArgs e)
{
    ShiftDown = false;
}

Obtaining Different Zoom Levels

screen2.png

Zoom levels can easily be done by just changing the tile size. When drawing in the PaintTile event, it should automatically resize the image or drawing to the size of the tile. It will repaint the whole map when the tile size is changed, so this could take a few seconds.

C#
private void x32ToolStripMenuItem_Click(object sender, EventArgs e)
{
    TileEditor.TileSize = new Size(32, 32);
}

private void x16ToolStripMenuItem_Click(object sender, EventArgs e)
{
    TileEditor.TileSize = new Size(16, 16);
}

Undo and Redo

Undo and Redo actions can now be easily achieved by calling a few functions. Undos are done in groups of saved tiles, you can create groups and add tiles to them with their saved values and then add the group to the Undo stack. The TileEditor control has several functions for adding tiles to its own UndoGroup which can then be added to the stack instead of creating your own group.

C#
//Apply and clear the undo group if any tiles were in it already
TileEditor.ApplyAndClearUndoGroup();
//Add the selected tiles to the group
TileEditor.AddSelectionToUndoGroup();
//Other functions to add tiles to the group
TileEditor.AddTilesToUndoGroup(new Rectangle(0, 0, 5, 5));
TileEditor.AddTileToUndoGroup(new UndoTile(5, 3, 0, 2));
//Apply the group
TileEditor.ApplyAndClearUndoGroup();

In the demo the group is cleared when the mouse down event is called for the tile editor control and is applied in the mouse up event. Tiles are then added to it in the MouseMove event.

Selecting, Copy and Paste

To activate selection for the control do TileEditor.AllowSelect = true;. Remember to unselect all the tiles when setting it to false. TileEditor.UnselectAll();

You can use the selected flag passed in the PaintEventArgs for the paint tile event to draw a different image or an inverted image to show it is selected. You can retrieve the selected tiles by doing TileEditor.SelectedTiles which returns a list of TilePoints. To copy the selected tiles do TileEditor.CopySelectedTiles();. The following code pastes the tiles after adding the tiles that are to be overwritten to the UndoStack.

C#
private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
{
    //Apply and clear the undo group
    TileEditor.ApplyAndClearUndoGroup();

    //Add the pasting area to the undo group and apply it
    TileEditor.AddTilesToUndoGroup(TileEditor.PastingSelectionArea);
    TileEditor.ApplyAndClearUndoGroup();

    //Paste tiles
    TileEditor.PasteSelectedTiles();
}

Known Bugs

  • Large maps. At the moment, an image of the whole map is stored so that the control can achieve fast painting, so you may get an 'Out of Memory' error if the image is too large.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United Kingdom United Kingdom
Ted John started programming at an early age using Visual Basic and HTML. As he gained more experience, he starting writing utilities for his favourite video games.

In his spare time he currently writes program for fun in mostly VB.NET, C# and C++. He also runs a website in PHP and a wiki.

He also enjoys playing strategy games such as popular Tycoon games and Populous: The Beginning (his favourite game).

Comments and Discussions

 
GeneralMy vote of 5 Pin
cyberhead28-Nov-19 7:04
cyberhead28-Nov-19 7:04 
GeneralThis Control is exactly what I want, thank you for sharing Pin
Li Shu10-Jan-10 23:13
Li Shu10-Jan-10 23:13 
Generalnice work Pin
serioux24-Jul-09 6:08
serioux24-Jul-09 6:08 
GeneralI like this Pin
Sacha Barber13-May-08 21:30
Sacha Barber13-May-08 21:30 
General[Message Removed] Pin
Mojtaba Vali13-May-08 19:48
Mojtaba Vali13-May-08 19:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.