Advertisement

WPF - Presenting 2D sprites (2D map editor)

Started by November 23, 2015 06:58 PM
11 comments, last by Eiron 9 years ago

Hello!

I want to make a basic 2D map editor like this:

0f2f6da487.png

I can currently load images to a position on the canvas, without making use of any form of grid. At first I was looking to create a dynamic grid with variable amount rows/columns and bind the position (index) of each sprite to a grid column/row but I quickly figured that isn't what a grid is meant to do.

After looking further into this my best bet is to use a datagrid and I'm now wondering if this the best fit for the job, whether it will work and how to do this with a MVVM approach.

I want to dynamically set the size of each 'cell' (32x32, 64x64) at runtime (or maybe just for a new project)

I want every sprite to have a (bound) grid position.

I want to zoom in/out on the grid.

I want an overview of my loaded sprites in a container such as in the above example 'terrains'.

I want to draw with these terrains on a visible (solid..) line grid, with every sprite snapping into place.

I want to drag and drop (move) sprites within the datagrid and spawn click the selected sprite from the 'spritecontainer'.

I want a undo/redo option.

Is this all possible with a datagrid? Is a datagrid the way to go or are there better ways? How long will this take me? Are some points too ambitious? How should I approach this?

Thanks in advance!

It's possible, but there are tools that do most of this for free! Is there a reason you don't want to use one of these?

Check out tiled or tide! There are many more but these are the only ones I've used.

Advertisement

Yes indeed, I know, I was using Tiled as reference here :)

I'm doing this is purely for learning purposes.

Digging a bit deeper into this, it looks like a datagrid can't be an empty grid and is solely used for displaying existing data.

How should I create a grid, ready for displaying images at a certain index?

I think DataGrid is too heavyweight component for your case. For relatively small maps, say 20x20 or 30x30, that fit entirely on the screen, you might be better off using a Grid or UniformGrid layout component with some images in it. For large maps, say 1000x1000 tiles, I would go for another route: implement a custom control based on a Canvas with some UI virtualization, i.e. if we have 30x30 tiles visible on the screen out of a 1000x1000 tile map, create images for only the visible tiles and then implement some object pool to reuse the same images while scrolling.

I think UniformGrid is what I was looking for, thanks!

Advertisement

Digging further into this, it seems like a UniformGrid (kinda like a datagrid) only shows populated cells.

My issue is that cells are empty until filled. I need to find some way to bind (spawn) items to existing visible empty row/columns.

Since there is no UI component that can do exactly what you want "out of the box", you'll need to provide some glue code, of course. For example, here is some code how to initialize the layout whenever you create or open a new tile map:


private void InitLayout(int columns, int rows)
{
	var grid = new UniformGrid();

	grid.Columns = columns;
	grid.Rows = rows;

	for (int row = 0; row < rows; row++)
	{
		for (int column = 0; column < columns; column++)
		{
			var image = new Image();

			// Initialize image.Source from your view-model here.
			grid.Children.Add(image);
		}
	}

	Content = grid;
}

You can provide some events in your view-model to notify about changes of tile the map layout and the content of individual cells, and then handle these events accordingly in the view. The exact implementation depends on how you have structured your underlying view-model, so I am afraid I cannot give you more specific suggestions, unless you share some code.

I've incorporated some of your code into my application:

7542b1b47a.png

I create a grid of 8x8 with the first sprite extracted from a spritesheet. The UniformGrid just scales as it wishes sad.png

Edit: Since I initialized the entire grid anyway, I just added positions to the tiles and threw them in a canvas under scrollview. Works splendid!

If you have not specified any dimensions (Width and Height), the UniformGrid would stretch to fill its container, which is expected. Sorry, I have forgotten to put that in my example code. smile.png I am glad that you've decided to use a Canvas instead, however. That is a more flexible solution, provided you'd decide to add some sprites of different sizes later.

This topic is closed to new replies.

Advertisement