Scrolling Game Development Kit Forum
SGDK Version 1 => Help/FAQ => Topic started by: mr_c on 2006-01-22, 05:37:48 AM
-
I find the built-in map editor in SGDK very frustrating to use. Could someone please recommend an alternative which can generate maps I can easily import into SGDK?
I would like to use TileStudio (http://tilestudio.sourceforge.net) but as far as I can tell it doesn't output maps in the format requried by SGDK.
-
i don't believe there are any programs that make maps in a format sgdk will recognize.
-
Personally I can't think of that many map editors I like better. There is a script that adds controls which i personallly find quite benfitial (switching layers on the fly & show only they layer you ar working on). The only level editor I would even compaire to sgdk's is jazz jackrabbit 2 and thats game specific. What is it you find frustrating about sgdk's level editor?
It's been ages since I looked at tilestudio - around the time I got into sgdk... from what I remember whatever you were developing in would have to support tilestudio for the editor to be of any use but its still a decent gfx editor.
-
Can you be more specific about what's making it difficult for you? We might be able to provide some tips on how to work more easily.
There aren't any converters that I'm aware of that will import other formats into SGDK (nor am I aware of any other programs that can export directly to an SGDK-compatible format). But writing a script that imports a map probably wouldn't be too difficult. Before exploring that, though, tell us what you are missing in the SGDK map editor.
-
Can you be more specific about what's making it difficult for you?
-
having to use the arrows for map scrolling would be a bit of an inconvenience because in most cases the player is controlled by the arrows, and i usually don't want the player to get into contact with any of the other sprites, b/c if there is a collision defined it can screw up the game.
-
Well, I'm glad to see that 2 of the 3 problems with the current map editor are things I've fixed in SGDK2, and the other one is the easy one (and I probably will do it when I implement the copy feature for SGDK2). But of course you're interested in SGDK 1.x right now. The scrolling and copy problems could be easily solved with a design-time script. Seeing the tiles at design time would be a somewhat larger chore for a design time script.
So there are a couple formats you might be interested in. I'll start with the easy one. GameDev can export a project to an XML file, which should expose the format in an almost self-explanatory format readable in notepad. The trick there is to understand how base-64 encoding works for the tile data within the layer (generally the biggest blocks of code in the XML file). If you find a utility that can export the raw tile data from an existing map in an external editor (1 byte per tile with no data besides the tile values themselves) then I think you could take these steps to import a layer of tiles from an external source (of course you'll want to test this procedure before relying heavily on it):
- Create layers in your project that are exactly the right size to receive the layers you want to import (make sure the number of tile columns and rows match the layer you want to import).
- Export your project to XML
- Create your maps in the external application
- Export the external map data in raw binary form -- 1 byte per tile and no extra data (no width or height information)
- Run a utility that converts binary data to base-64 text. If you pass the binary file in, you should get a plain text output file. If you can't find any other utility, you might try one I wrote a while back that I think can do this: http://sourceforge.net/projects/bmrsa (http://sourceforge.net/projects/bmrsa)
- Open the base-64 file for the converted map (layer) data in a text editor and copy the whole text.
- Open the XML file in a text editor and find the block of text representing the layer tiles you want to import into. Replace the existing base-64 text with the text you copied.
- Save the XML file and import it back into GameDev.
- If it looks right, save the project back into GDP format (The map files will be overwritten with the new data).
Of course that's a manual process, and I suppose you're going to want to automate it. The Microsoft XML DOM objects are used to to the XML export/import in GameDev, and they automatically convert between binary and base64. But until I know more about what language(s) you want to use to automate this, I won't try to make a guess at what kind of sample code you'd want to see.
On the other hand, if you are going to be using a language that can interact with the Microsoft DOM objects, you might as well interact with the SGDK project directly (via COM) rather than using the XML objects. Then you don't even have to worry about the file format. You can just create a GameDev Engine object, tell it to load the project, locate the map, load the binary tile data, and copy it directly into the Data property of the layer and save the project.
I'll leave it up to you to let me know which of these solutions you want to explore more.
-
Some specs on the map file format would be really appreciated so I can write a conversion utility...
The things I find difficult about the built-in map editor are listed below. These aren't criticisms but simply things that don't fit my personal preferences:
1. The only major problem I have is not having both the map and the tiles on the same screen. It makes map-making very tiresome.
2. A small problem that could be solved easily is having to right-click and then choose the "copy" facility. A keyboard shortcut for this would be a huge improvement.
3. I would prefer it if the map didn't scroll when I move the mouse to the screen edge. I don't know about anyone else but I'd much rather use the keyboard for scrolling (which I know you can do but you can't de-activate mouse scrolling).
I might just have to get used to the map editor, SGDK is great in every other way and there's not really much competition...
A conversion utility would be possible, but probably not worth the effort. If you are really interested, SGDK is open source so you could probably just look at the .Save method of the Map class module (Map.mod) You don't even need VB 6 to do this as I believe .mod files are text based.
If all you're worried about is tile placement, all that is is a 2d byte array for every layer. you could possibly use a different utility to place tiles (make sure 2d grid is same size as layer) and if they are in the correct format, you could paste them into an xml file where the tile byte array is. If they aren't in correct format, a utility to reformat the array might be easier to make than a whole file conversion. This would take some pretty serious testing, but its worth a try.
Also, with a design time script, I think you could do 2 and 3 pretty easy, but 1 would be somewhat difficult and would probably be beyond the power of a design time script. I'd try to make the design time script for you, but I'm making leaps and bounds of progress on a game and don't want to lose momentum.
here is an example design time script: (edited from bluemonk's original creation distributed with SGDK)
' This is a generic map editing template script
' It connects to the map editor whenever it comes up.
' To customize the script to your own purpose, edit
' the second section (script number 1) in this file.
' ======== INITIAL STARTUP SCRIPT (Number 0) =========
Sub Project_OnEditMap(M)
Set HostObj.TempStorage = M
HostObj.StartScript=1
End Sub
HostObj.SinkObjectEvents ProjectObj, "Project"
HostObj.ConnectEventsNow()
#Split == MAP EDITING SCRIPT (Number 1) ============
Dim Rndm,totalclearcount
Dim MpEd
Set MpEd = HostObj.TempStorage
HostObj.TempStorage = Empty
Sub MapEd_OnEditInit()
Rndm=false
MpEd.DisplayMessage = "Map editing script connected, use" & vbCrLf & vbCrLf & "F-frame," & vbCrLf & "A-All" & vbCrLf & _
"C- Clear = " & vbCrLf & "4-left" & vbCrLf & "6-right" & vbCrLf & "8-up" & vbCrLf & "2-down"
End Sub
Sub MapEd_OnKeyPress(KeyAscii)
Dim TileWid, TileHgt
Dim Tmr, TmOut
'Dim Lyr0Dat, Lyr1Dat, Lyr2Dat,clear,totalclear
dim LyrDat, LyrBelowDat
Dim IntTemp
dim YStart, YEnd, XStart, XEnd, PerformScan, SolidityChange
'On Error Resume Next
'MpEd.disp.drawtext keyascii & " " & mped.editmode,20,20
If MpEd.EditMode >=9 Then Exit Sub
TmOut=8
HostObj.ScriptTimeOutSeconds = TmOut + .5
TileHgt = MpEd.theMap.MapLayer(0).TSDef.TileHeight
TileWid = MpEd.theMap.MapLayer(0).TSDef.TileWidth
'Set Lyr0Dat = MpEd.theMap.MapLayer(0).Data
'Set Lyr1Dat = MpEd.theMap.MapLayer(1).Data
'Set Lyr2Dat = MpEd.theMap.MapLayer(2).Data
set LyrDat = MpEd.theMap.MapLayer(MpEd.EditLayer).Data
clear=false
If KeyAscii = Asc("f") Then 'frame only
YStart = Int(MpEd.YOff / TileHgt)
YEnd = Int((MpEd.YOff+MpEd.theMap.ViewHeight) / TileHgt)- 1
XStart = Int(MpEd.XOff / TileWid)
XEnd = Int((MpEd.XOff+MpEd.theMap.ViewWidth) / TileWid)- 1
PerformScan = true
clear =false
'elseif keyascii = Asc("a") then 'all of layer
' YStart = 0
' YEnd = MpEd.theMap.MapLayer(0).Rows-2 '54
' Xstart = 0
' Xend = MpEd.theMap.MapLayer(0).Columns-1
' PerformScan = true
' clear =false
elseIf KeyAscii = Asc("c") Then 'clear
YStart = Int(MpEd.YOff / TileHgt)
YEnd = Int((MpEd.YOff+MpEd.theMap.ViewHeight) / TileHgt)- 1
XStart = Int(MpEd.XOff / TileWid)
XEnd = Int((MpEd.XOff+MpEd.theMap.ViewWidth) / TileWid)- 1
PerformScan = true
clear = true
elseif keyascii = asc("6") then
if MpEd.XOff+640<(MpEd.theMap.MapLayer(0).Columns-21)*32 then
MpEd.XOff=MpEd.XOff+640
else
MpEd.XOff=(MpEd.theMap.MapLayer(0).Columns-20)*32
end if
elseif keyascii = asc("4") then
if MpEd.XOff-640>0 then
MpEd.XOff=MpEd.XOff-640
else
MpEd.XOff=0
end if
elseif keyascii = asc("2") then
if MpEd.YOff+480<(MpEd.theMap.MapLayer(0).Rows-16)*32 then
MpEd.YOff=MpEd.YOff+480
else
MpEd.YOff=(MpEd.theMap.MapLayer(0).Rows-15)*32
end if
elseif keyascii = asc("8") then
if MpEd.YOff-480>0 then
MpEd.YOff=MpEd.YOff-480
else
MpEd.YOff=0
end if
else
PerformScan = false
end if
if PerformScan = true then
if clear=true then
For Y=ystart to yend
For X = xstart to xend
select case lyrdat.tilevalue(x,y)
case 25,222
lyrdat.tilevalue(x,y)=0
end select
next
next
else
For Y=ystart to yend
For X = xstart to xend
Select Case LyrDat.TileValue(X,Y)
Case 208,209,210,211,216,217,218,219 'draw cave faces from sides
'xend=0/0
select case lyrdat.tilevalue(x,y+1)
case 201, 220, 221, 228, 229,208,209,210,195,198,206,192,193,194
'nothing
case else
lyrdat.tilevalue(x,y+1)=lyrdat.tilevalue(x,y)+8
end select
case 1
select case left(MpEd.theMap.Name,3)
'case "Cav"
' lyrdat.tilevalue(x,y)=222
'case "Twn"
' lyrdat.tilevalue(x,y)=25
case "Cst"
lyrdat.tilevalue(x,y)=111
end select
case 0 'draw ground on blank tiles
select case left(MpEd.theMap.Name,3)
case "Cav"
lyrdat.tilevalue(x,y)=222
case "Twn"
lyrdat.tilevalue(x,y)=25
case "Cst"
lyrdat.tilevalue(x,y)=111
end select
Case Else
End Select
'If Err.Number <>0 Then Exit For
Next
'If Err.Number <>0 Then Exit For
Next
end if
'If Err.Number <> 0 Then MpEd.DisplayMessage = Err.Description
End If
' Tmr = Timer
'
' If Err.Number <> 0 Then MpEd.DisplayMessage = Err.Description
' If Timer-Tmr > TmOut Then MpEd.DisplayMessage = "Script Timeout at tile " & X & "," & Y
' HostObj.ScriptTimeOutSeconds = 2
' End If
End Sub
Sub MapEd_OnEditComplete()
HostObj.StartScript=0
End Sub
HostObj.SinkObjectEvents HostObj.AsObject(MpEd), "MapEd"
HostObj.ConnectEventsNow()
To link it, make a shortcut for the command insert this into the "Target" of the shortcuts properties:
"C:\Program Files\GameDev\gamedev.exe" "[.gdp full path]" /e "[script.vbs full path]"
(note im using the default gamdev.exe path, change as necessary)
-
lol, bluemonk put it better than me, but I think you get the point.
I never thought of linking to a project through COM, and importing all the data directly, and resaveing. This is probably BY FAR the easist method.
-
Thanks for your help bluemonkmn and cbass.
I think I'll try bluemonkmn's suggestion first and see if I can manually insert my map data into the XML. If it works then I won't bother automating the process, I only require one tilemap at this stage to produce a demo.
I'll report back with my results...
-
I decided to make the run-time script we have been talking about. just copy to your folder gamedev.exe is in ("c:\program files\gamedev")
From there, it will work for any project. Each time you load the map editor, the script will connect and display the message for its commands:
C - copy (also cancels copy and returns to tile placement, to the last tile you were using I might add, which is awesome :) )
T - Bring up menu and tile list (works just like right click now except that you dont have to hold down right click) you still have to use right click to select
S - Enables and disables scroll lock for the mouse
D - Deactivates and reactivates the script (clears message, disables all commands except D to reactive the script and disables scroll lock if activated.)
I haven't tried to make the script error out yet, but I plan on using it myself now as it does add some conviences to the map editor, so I should hopefully find any errors in it.
-
for some reason, it wont let me edit my post above.
Anyways, im relinking posting the script since I have fixed a few bugs. I tried to add a few more features (Axis lock and tile snap) but it seems to be impossible to do from script since the darn engine always overwrites any changes to the mouse position every frame. I guess we've lived without these features for this long and noone's seemed to complain, I guess we can live without em some more.
I thought of some other stuff like hotkey tile or tilematch selecting but that stuff can wait 8)
-
yea, after a short period it takes away the ability to edit or delete previous posts; i'm guessing its just this theme.
-
That's an administrative setting that I figured I'd take advantage of not long after Zorb edited one of his posts in order to claim he had said something he hadn't. So now you have (I think) 90 seconds to edit a post without getting tagged with "last edited" and some much longer period of time to edit it otherwise (can't remember what that's set to). The way I see it is, when something new gets added to a discussion (or changes), people want to know about it, so it's generally good to just add a new post with the new info.
-
for some reason, it wont let me edit my post above.
Anyways, im relinking posting the script since I have fixed a few bugs.