| |||
Views: 86,391,774![]() |
![]() ![]() ![]() ![]() |
03-29-23 05:33 PM![]() |
|
Guest: Register | Login |
0 users currently in ROM Hacking Archives | 1 guest |
Main - ROM Hacking Archives - Kawa's Map Editor Creation Tutorial | New thread | New reply |
Kawa |
| ||||||||
![]() ![]() CHIKKN NI A BAAZZKIT!!! 80's Cheerilee is best pony Level: 136 Posts: 1837/5344 EXP: 29958248 Next: 138667 Since: 02-20-07 From: The Netherlands Last post: 4104 days Last view: 2239 days |
Part 1First of all, we'll need a form with a tile selection area and a map editing area. Both should be able to scroll freely. The easiest way to do this is by having two AutoScroll-enabled Panels containing two AutoSizing PictureBoxes. Place the two Panels on a new Form, enable AutoScroll for both and position them nicely. Then, add a PictureBox in each, in the top-left corner and set to AutoSize. The tileset panel should be as wide as the tileset (128px in this example) plus some margin for the scroll bar but frankly, we can afford to play it loose for now. Interjection: I showed the draft for this tutorial to Cearn and he insists on using constants for tile sizes. I've decided to compromise -- this tutorial will use size constants, but I'm not updating the final source code archive. So whenever I say "128 pixels wide", that should be read as "eight times the tile size", id est "8 * 16". Now that the UI is in place, we can go over the code. Now, I like to use backbuffers, so we'll go with that. Define two Bitmap and two Graphics objects.
Next up is loading and displaying the tileset. We'll go with a slightly cut Advance Wars tileset, but anything goes, really. In this example, as announced before, the tileset should be 128px wide, most any height. This maps to eight tiles a row. There's some math involved here that we'll get to later. Also note that you can't pull a Graphics object from indexed Bitmaps, so don't just try that.
Now, to select a tile from the tileset, we must remember which tile index was selected. Add a CurrentTile variable to do this, and add the following event handler:
I hear you ask, "Kawa, when the hell are we getting to the mapping part?". Well, how 'bout right now? First of all, we'll need something to store the current map in. For readability's sake, we'll go with a 2D int array.
Next, we'll need something to draw the full map. This only has to happen under few circumstances, such as on load. For any subsequent change, drawing single tiles will suffice. We'll tackle both these tasks in one go.
You should have a black map now, since the Map array defaults to all zero, which is a black tile. So let's get to the fun part!
Hook this up to both the MouseMove and MouseDown events for mapPictureBox. Why both? Because if you only hook it to MouseMove, you have to jiggle the cursor every time you start drawing and if you only hook it to MouseDown, you can't do strokes. That's it. You now have a simple map editing system going. Next time, we'll tackle loading and saving, probably followed by loading the assets from ROM. Download the finished app for this part ____________________ Wife make lunch - Shampoo Opera - give it a spin Spare some of your free time? <GreyMaria> I walked around the Lake so many goddamn times that my sex drive was brutally murdered Kawa rocks ![]() |
Arbe |
| ||
![]() go away Level: 85 Posts: 1631/1788 EXP: 5796350 Next: 102190 Since: 02-23-07 Last post: 4575 days Last view: 1144 days |
I can hear the voices of 20 years worth of dead and gone rom hacking souls shouting "FINALLY" in the dark. Awesome that you're putting in the time. |
Xenesis |
| ||
![]() Level: 45 Posts: 235/416 EXP: 650688 Next: 9476 Since: 02-20-07 Last post: 3991 days Last view: 2699 days |
:o
:o :o Yes. ![]() *goes to attempt to do this himself as well* |
Arbe |
| ||
![]() go away Level: 85 Posts: 1636/1788 EXP: 5796350 Next: 102190 Since: 02-23-07 Last post: 4575 days Last view: 1144 days |
Suggestion this is moved to Rom Hacking at some point and maybe stickied? ![]() |
Kawa |
| ||
![]() ![]() CHIKKN NI A BAAZZKIT!!! 80's Cheerilee is best pony Level: 136 Posts: 1843/5344 EXP: 29958248 Next: 138667 Since: 02-20-07 From: The Netherlands Last post: 4104 days Last view: 2239 days |
I had the same idea.
So what should be in Part 2, people? ____________________ Wife make lunch - Shampoo Opera - give it a spin Spare some of your free time? <GreyMaria> I walked around the Lake so many goddamn times that my sex drive was brutally murdered Kawa rocks ![]() |
MathOnNapkins |
| ||
![]() ![]() Super Koopa Level: 61 Posts: 652/842 EXP: 1873810 Next: 2786 Since: 02-19-07 From: durff Last post: 4094 days Last view: 3617 days |
Undo / Redo would be boss. ____________________ Zelda Hacking Forum hobbies: delectatio morosa |
Kawa |
| ||
![]() ![]() CHIKKN NI A BAAZZKIT!!! 80's Cheerilee is best pony Level: 136 Posts: 1847/5344 EXP: 29958248 Next: 138667 Since: 02-20-07 From: The Netherlands Last post: 4104 days Last view: 2239 days |
I should do that for the OpenPoké map editor first so I know what to do. Redrawing the whole map takes some time, so I think keeping a list of changes per stroke would be a nice starting point. ____________________ Wife make lunch - Shampoo Opera - give it a spin Spare some of your free time? <GreyMaria> I walked around the Lake so many goddamn times that my sex drive was brutally murdered Kawa rocks ![]() |
Arbe |
| ||
![]() go away Level: 85 Posts: 1638/1788 EXP: 5796350 Next: 102190 Since: 02-23-07 Last post: 4575 days Last view: 1144 days |
RIBBON MENUS!! |
Kawa |
| ||
![]() ![]() CHIKKN NI A BAAZZKIT!!! 80's Cheerilee is best pony Level: 136 Posts: 1849/5344 EXP: 29958248 Next: 138667 Since: 02-20-07 From: The Netherlands Last post: 4104 days Last view: 2239 days |
Screw that, that's just an interface paradigm choice. A simple tutorial map editor wouldn't ever reach the point where menus and toolbars are insufficient. ____________________ Wife make lunch - Shampoo Opera - give it a spin Spare some of your free time? <GreyMaria> I walked around the Lake so many goddamn times that my sex drive was brutally murdered Kawa rocks ![]() |
Arbe |
| ||
![]() go away Level: 85 Posts: 1639/1788 EXP: 5796350 Next: 102190 Since: 02-23-07 Last post: 4575 days Last view: 1144 days |
wait hang on for some reason i thought we were suggesting shit for openpoke editor
uh, events? lol |
Kawa |
| ||
![]() ![]() CHIKKN NI A BAAZZKIT!!! 80's Cheerilee is best pony Level: 136 Posts: 1850/5344 EXP: 29958248 Next: 138667 Since: 02-20-07 From: The Netherlands Last post: 4104 days Last view: 2239 days |
Events are a good topic to cover at any rate, and I might go onto it in more detail later.
For now, here's a quickie take on it: Intermission -- Events
The graphics should run something like this: On load, redraw the entire map. After redrawing the entire map, call the event drawer. After drawing the events, call the final merger. The final merger simply blits the map and events to the final buffer in that order and calls picMap.Refresh() as before. On drawing a tile, blit that single tile to the map buffer as before, then call the merger. On moving an event, call the event drawer, which in turn calls the merger. The event drawer just iterates and draws rectangles or whatever. My fingers hurt now. ____________________ Wife make lunch - Shampoo Opera - give it a spin Spare some of your free time? <GreyMaria> I walked around the Lake so many goddamn times that my sex drive was brutally murdered Kawa rocks ![]() |
Bukkarooo |
| |||
![]() ![]() Fuzzy Son of a bitch, I'm sick of these dolphins... Level: 58 Posts: 406/778 EXP: 1576629 Next: 917 Since: 10-15-08 From: Florida Last post: 4790 days Last view: 4557 days |
|
Kawa |
| ||
![]() ![]() CHIKKN NI A BAAZZKIT!!! 80's Cheerilee is best pony Level: 136 Posts: 1851/5344 EXP: 29958248 Next: 138667 Since: 02-20-07 From: The Netherlands Last post: 4104 days Last view: 2239 days |
I've thought about undo buffers some more and decided on a hybrid approach. I'll implement it in the OpenPoké map editor, then write up Part 2 of the tutorial. Is that okay? ____________________ Wife make lunch - Shampoo Opera - give it a spin Spare some of your free time? <GreyMaria> I walked around the Lake so many goddamn times that my sex drive was brutally murdered Kawa rocks ![]() |
MathOnNapkins |
| ||
![]() ![]() Super Koopa Level: 61 Posts: 655/842 EXP: 1873810 Next: 2786 Since: 02-19-07 From: durff Last post: 4094 days Last view: 3617 days |
Fine by me :/. I'm doing some independent research of my own on the subject anyways. ____________________ Zelda Hacking Forum hobbies: delectatio morosa |
Kawa |
| |||||||
![]() ![]() CHIKKN NI A BAAZZKIT!!! 80's Cheerilee is best pony Level: 136 Posts: 1856/5344 EXP: 29958248 Next: 138667 Since: 02-20-07 From: The Netherlands Last post: 4104 days Last view: 2239 days |
Part 2 - Undo BuffersTo undo changes, we'll need something to track them in. Since redrawing the entire map can be slow (depending on the map's size ofcourse), we'll basically take screenshots of each operation, before and after. These will be part of each undo state. Not to be too wasteful, we'll not save copies of the entire map array.
This one's important, it gets extra spacing:
![]() Now, let's hook this system up.
____________________ Wife make lunch - Shampoo Opera - give it a spin Spare some of your free time? <GreyMaria> I walked around the Lake so many goddamn times that my sex drive was brutally murdered Kawa rocks ![]() |
DarkPhoenix |
| ||
![]() ![]() Micro-Goomba Level: 12 Posts: 14/19 EXP: 6301 Next: 1620 Since: 05-24-07 Last post: 4906 days Last view: 4893 days |
Just a thought - rather than using separate stacks for undo and redo, you could use a single list, with a pointer to the current position. FireFox 3's Forward/Back buttons provide a good visual of this approach.
For reference, since it wasn't mentioned, the book "Design Patterns" (or alternatively, the Wikipedia Article) has a collection of the industry standard solutions for common concepts like Undo/Redo, with diagrams and all that jazz. See "Command" and "Momento". |
Kawa |
| ||
![]() ![]() CHIKKN NI A BAAZZKIT!!! 80's Cheerilee is best pony Level: 136 Posts: 1871/5344 EXP: 29958248 Next: 138667 Since: 02-20-07 From: The Netherlands Last post: 4104 days Last view: 2239 days |
I just found the two stacks approach easier to implement on short notice. At least it works as designed, right? And it made sense when I visualized it while telling my friends about it.
I may look into that book/article later, it sounds like an interesting read. Also, not to drift off-topic but what makes Fx3's forward/back buttons different from other browsers'? If you could tell me that in a PM... ____________________ Wife make lunch - Shampoo Opera - give it a spin Spare some of your free time? <GreyMaria> I walked around the Lake so many goddamn times that my sex drive was brutally murdered Kawa rocks ![]() |
Kawa |
| |||
![]() ![]() CHIKKN NI A BAAZZKIT!!! 80's Cheerilee is best pony Level: 136 Posts: 1939/5344 EXP: 29958248 Next: 138667 Since: 02-20-07 From: The Netherlands Last post: 4104 days Last view: 2239 days |
Part 3 - File IOFor demonstration purposes, we'll go with seperate files instead of diving directly into ROMs. Just bear with me, okay?To load and save maps, add a menu bar or toolbar or what have you, with two options at the very least: Open and Save. Also add, from the Dialogs category, open and save dialog controls. In the click event for Open, put this:
This would mean that a map file in this demonstration is a series of only 32-bit values. As the comment implies, if we used a byte array for our map data we could just use File.ReadBytes(MapWidth * MapHeight) and call it a day.
Notice the new function "MakeBackbuffers"? This is it, basically:
Replace the part below "Map = new int[MapWidth, MapHeight];" in the form's constructor with a call to MakeBackbuffers as well. Saving is pretty much the exact opposite deal as with loading, with the added bonus that you don't need to redraw the map, since it hasn't changed. I'm leaving that as an exercise for the reader. How to speed up the first drawing of the mapYou may have noticed that when first loading a map, it may take a notable amount of time to draw it all. I sure did while working on the OpenPoké editor, and my current project.Believe it or not, replacing the DrawImage() call in the DrawFullMap function with a simple Get/SetPixel loop makes it much faster, and that's not even the limit!
Sample codehttp://acmlm.no-ip.org/uploader/get.php?id=1569 Does NOT include the optimization described just now, nor does it contain the undo/redo thing. I wrote it way before I came up with either of those. Consider it a challenge. ____________________ Wife make lunch - Shampoo Opera - give it a spin Spare some of your free time? <GreyMaria> I walked around the Lake so many goddamn times that my sex drive was brutally murdered Kawa rocks ![]() |
Coby |
| ||
![]() ![]() Red Paragoomba Level: 18 Posts: 52/53 EXP: 29569 Next: 328 Since: 02-28-07 From: Belgium Last post: 5034 days Last view: 3788 days |
Hey Kawa, remember me? ![]() I must congratulate you on this splendid tutorial (Jij gekke Hollander jij) This finally gives me an idea on how to start making level editors after all these years :p Anyhow, I'm trying to port your code to VB.net (because we didn't learn C# yet, I know OO-Java and it looks like the syntax is about the same but fuck it :p) because I thought it would be a nice way of flexing my vb skillz (although most of the code is the same, spare for the syntax difference). So, everything works fine up until now, just whenever I try to call the function drawTile(x,y,map(x,y)) VB gives a System.NullreferenceException. Note that when I just call drawTile(x,y,0) then it goes fine
That's how I declared the drawTile sub, and I just call it like
Don't mind the try-catch. Anyhow, do you (or anyone else) have any idea why it's going fubar on me? Am I missing something really stupid or am I doing something totally wrong? :o P.S. Sorry for just barging in like that after all these years :p P.P.S. For those who don't know or remember me, I used to own the ExGFX Workshop |
Kawa |
| ||
![]() ![]() CHIKKN NI A BAAZZKIT!!! 80's Cheerilee is best pony Level: 136 Posts: 1958/5344 EXP: 29958248 Next: 138667 Since: 02-20-07 From: The Netherlands Last post: 4104 days Last view: 2239 days |
You forgot to initialize map[,] . Make sure that you do Map = new int[MapWidth, MapHeight]; too.
That was from the C# code, just in case. I'll leave the VB translation to you. ____________________ Wife make lunch - Shampoo Opera - give it a spin Spare some of your free time? <GreyMaria> I walked around the Lake so many goddamn times that my sex drive was brutally murdered Kawa rocks ![]() |
Main - ROM Hacking Archives - Kawa's Map Editor Creation Tutorial | New thread | New reply |
© 2005-2023 Acmlm, blackhole89, Xkeeper et al. |
MySQL - queries: 57, rows: 85/86, time: 0.033 seconds. |