[Completed] [Level Editor] A few questions on concepts I'm not sure of.

EDIT: Maybe a bit of break is all I needed. :cranky: It’s futile continuing to think without taking some rest. Thus, I’m also modifying some parts of the questions.

I have somewhat created a level editor for my Pokémon Walking project.

This is all just a basic setup for creating a new area. I’m fed up with myself having to use Paint.NET to draw almost completely transparent data onto bitmaps, so I decided to create my own custom level editor.

The top part of the editor is the main toolbar for creating, saving, and opening a game area.
On the left of the editor is the Tiles Selection Panel, where all the tiles are stacked together neatly. I can choose what tiles I wanted by clicking on the tiles.
In the center is the Editor Canvas, where it is showing a white BufferedImage bitmap in the center. I can pan the bitmap around by dragging it with my right mouse button.

Now, the problems I am having are issues and “writer’s blocks” all jumbled up together the moment I notice them. I’ll list the things I know of after I had taken a break from tinkering the editor out below:

  • Apparently, panning is good. It’s great for moving around the map in an intuitive way. One sure thing, is that it adds complexity to a simple algorithm:
y * imageWidth + x = pixel located at (x, y)

Therefore, I just need to know how to tweak that algorithm above so that it works even after panning the whole canvas.

[list][li]I need to do some way of easily sorting all the messy data, into neat arrays. Then I can use that new data to create tile IDs so that the editor knows what I’m drawing.

  • Saving/Loading area map is for saving/loading files. That’ll do.

  • I am left with “how to draw tiles onto the white bitmap?” problem. Other than writing the RGB color to the raster, I have no other alternate methods of doing this. Any suggestions?

This is all I can think of. Now, I need help on the first and the last bullet-point issues I’m having. If anyone can tell me what I need to do, I’ll be grateful for your help.[/list]

For your first question, imageWidth means how many tiles you have in a row of the whole image? Why don’t you set it to a rather large number and cut it down when saving?

I’m sorry? If I were to set [icode]imageWidth[/icode] to a large number, I wouldn’t be able to obtain the pixel within the image. I need the pixel (and surrounding pixels) in order for me to draw different tiles onto that image. Large number for that would also become ArrayIndexOutOfBoundsException, which I’m sure that’s not good. One last thing is, how does a large number for [icode]imageWidth[/icode] can be worked for panning/moving the image around in an editor? I just don’t know the answer to that question.

In other words, in the picture shown in the first post, I want to have the tiles on the left of the editors be drawn like a brush in MS Paint onto the white image in the drawing area. I need to use that algorithm in order for me to pinpoint where I can draw. That algorithm is based on BufferedImage.getRGB(), where it returns a 1D-array of pixel colors. (integers) But because of panning, I can’t get the absolute pixel location within the bitmap itself.

For point 4 I would probably use a BufferedImage to contain the white canvas, then draw the tiles (also BufferedImages) to that canvas (perhaps do continuously rendering loop or just whenever things change).
http://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html

For your formula:

y * imageWidth + x = pixel located at (x, y)

Do you really need to use this formula? Sounds like you store things in a 1D-array or something. However, it seems ot me that using a BufferedImage or a 2D array would be much easier.

i still cant help thinking that it would be easier to use a tile map system, rather than the map being a big image… its so much easier to alter and work with in general, especially for a 2d grid based game like this!

(Assuming you really can’t use Paint.NET)
You should separate your map representation from rendering. Have a [icode]tiles[][][/icode] of an applicable type (integer, better yet: an enum), we don’t care about performance or anything as this is the level editor (really a [][] isn’t much worse than a [] for raw performance, at least in small maps). Use a [icode]Map<Point,?>[/icode] instead if the maps are of arbitrary size or shape, and you don’t want to be limited while creating a level. (Replace ? with the relevant type like I said before)

Then, come render time, simply walk through your data structure, and render the BufferedImage associated with that tile at the tile’s location. Location in this case (top-down screen-coordinates) is a function of world-coordinates (stored in the data structure, i.e. Map<Point,?>), tile width in pixels, and the “camera” (allows panning, etc. like you wanted).

Example:


List<BufferedImage> tileIDs; // initialized elsewhere, could also use a Tile class with a getImage() method or something
Map<Point, Integer> tiles; // initialized elsewhere, Point is the location, Integer is the "tileID"

Point camera; // used for storing the panning offset

...

//now, in the editor-panel; either have tiles and tileIDs in this class or somehow give access to tiles & tileIDs, maybe pass them in, whatever.

private BufferedImage buffer; // for double buffering

public void paint(Graphics g) {
    Graphics bg = buffer.getGraphics();
    for(Map.Entry<Point, Integer> tile: tiles) {
        int x = tile.getKey().x * TILE_WIDTH + camera.x;
        int y = tile.getKey().y * TILE_HEIGHT + camera.y;     // note that TILE_WIDTH and TILE_HEIGHT are identical for square tiles, migtht just call em TILE_SIZE
        if(x < -TILE_WIDTH || x > getWidth() || y < -TILE_HEIGHT || y > getHeight()) // cull tiles we can't see
            continue;
        BufferedImage tileImage = tileIDs.get(tile.getValue());
        bg.drawImage(tileImage, x, y, TILE_WIDTH, TILE_HEIGHT, null);
    }
    bg.dispose();
    g.drawImage(buffer, 0, 0, getWidth(), getHeight(), null); // may use different scaling, etc.
}

Note that this isn’t the most performant method, the actual game might need something faster. (Might; don’t prematurely optimize)

Okay, okay, I am getting somewhere now.

I use 1D array over 2D array is because I’m lazy to type another for loop. It is a lame excuse, but that is what I feel right now. It is flexible as a 2D array, so it complements on not having to convert a 1D to a 2D from BufferedImage. Just trivial things.

Going to complete this right now, and let you know what I did later.

EDIT: The link below provides the completed level editor, with all the info formatted and cleaned up.