Loading Maps from www.mapeditor.de.vu - Fausti - 01-14-2005
I'm developing a clone for an old DOS Game (www.gameofrobot.de) with freebasic, and because of my lazyness I use a free mapeditor from (www.mapeditor.de.vu). Perhaps some of you know it, therefor I post my loadmap code snippet. Some things could be done better/easier, I know And it's far from being complete. But it serves me well.
Code: TYPE MAP_HEADER
blocks AS UINTEGER
layers AS UINTEGER
images AS UINTEGER
geoms AS UINTEGER
tilesets AS UINTEGER
anims AS UINTEGER
basis AS UINTEGER
daten AS UINTEGER
meta AS UINTEGER
END TYPE
TYPE MAP_TILESET
MaskR AS UINTEGER
MaskG AS UINTEGER
MaskB AS UINTEGER
FrameB AS UINTEGER
FrameH AS UINTEGER
Anims AS UINTEGER
Frames AS UINTEGER
FileName AS STRING * 12
END TYPE
TYPE MAP_ANIMATION
Frames AS UINTEGER
StartFrame AS UINTEGER
Modus AS UINTEGER
Frame(256) AS UINTEGER
Zeit(256) AS UINTEGER
END TYPE
TYPE MAP_LAYER
Visible AS UINTEGER
Name AS STRING * 12
BDatenTiefe AS UINTEGER
BDatenSize AS UINTEGER
BDaten AS STRING
DatenTiefe AS UINTEGER
DatenSize AS UINTEGER
Daten AS STRING
MDatenTiefe AS UINTEGER
MDatenSize AS UINTEGER
MDaten AS STRING
END TYPE
TYPE MAP_TYPE
Header AS MAP_HEADER
BlockSize(256) AS UINTEGER
TileSet(256) AS MAP_TILESET
Animation(256) AS MAP_ANIMATION
Layer(256) AS MAP_LAYER
END TYPE
SUB Map_Load(fname$)
DIM tString AS STRING
DIM nChar AS UINTEGER
DIM tChar AS STRING * 1
DIM tByte AS STRING * 1
DIM tMap AS MAP_TYPE
DIM aB_Tileset
DIM aB_Animation
DIM aB_Background
DIM aB_Layer
aB_Layer = -1
DIM aFrame
DIM aBLOCK, lBType, aBType
DIM nBeg, nCount, nCalc
DIM nValue AS UINTEGER
OPEN fname$ FOR BINARY AS #1
' HEADER
tString = STRING(64, " "): GET #1,, tString
nBeg = 28: nCount = 2: GOSUB Str2UInt: tMap.Header.blocks = nValue
nBeg = 30: nCount = 2: GOSUB Str2UInt: tMap.Header.layers = nValue
nBeg = 32: nCount = 2: GOSUB Str2UInt: tMap.Header.images = nValue
nBeg = 34: nCount = 2: GOSUB Str2UInt: tMap.Header.geoms = nValue
nBeg = 36: nCount = 2: GOSUB Str2UInt: tMap.Header.tilesets = nValue
nBeg = 38: nCount = 2: GOSUB Str2UInt: tMap.Header.anims = nValue
nBeg = 40: nCount = 2: GOSUB Str2UInt: tMap.Header.basis = nValue
nBeg = 42: nCount = 2: GOSUB Str2UInt: tMap.Header.daten = nValue
nBeg = 44: nCount = 2: GOSUB Str2UInt: tMap.Header.meta = nValue
' TABLE
tString = STRING(tMap.Header.blocks * 4, " "): GET #1,, tString
FOR i = 0 TO tMap.Header.blocks - 1
nBeg = (i * 4): nCount = 4: GOSUB Str2UInt: tMap.BlockSize(i) = nValue
NEXT
' BLOCKS
FOR aBLOCK = 0 TO tMap.Header.blocks - 1
GET #1,, tChar: aBType = ASC(tChar)
SEEK #1, (SEEK(1)-1)
SELECT CASE aBType
CASE 100 'TILESET
tString = STRING(26, " "): GET #1,, tString
nBeg = 1: nCount = 1: GOSUB Str2UInt: tMap.TileSet(aB_Tileset).MaskR = nValue
nBeg = 2: nCount = 1: GOSUB Str2UInt: tMap.TileSet(aB_Tileset).MaskG = nValue
nBeg = 3: nCount = 1: GOSUB Str2UInt: tMap.TileSet(aB_Tileset).MaskB = nValue
nBeg = 4: nCount = 2: GOSUB Str2UInt: tMap.TileSet(aB_Tileset).FrameB = nValue
nBeg = 6: nCount = 2: GOSUB Str2UInt: tMap.TileSet(aB_Tileset).FrameH = nValue
nBeg = 10: nCount = 2: GOSUB Str2UInt: tMap.TileSet(aB_Tileset).Anims = nValue
nBeg = 12: nCount = 2: GOSUB Str2UInt: tMap.TileSet(aB_Tileset).Frames = nValue
tMap.TileSet(aB_Tileset).FileName = MID$(tString, 15, 12)
aB_Tileset = aB_Tileset + 1
CASE 101 'ANIMATION
tString = STRING(13, " "): GET #1,, tString
nBeg = 1: nCount = 2: GOSUB Str2UInt: tMap.Animation(aB_Animation).Frames = nValue
nBeg = 3: nCount = 2: GOSUB Str2UInt: tMap.Animation(aB_Animation).StartFrame = nValue
nBeg = 5: nCount = 2: GOSUB Str2UInt: tMap.Animation(aB_Animation).Modus = nValue
FOR aFrame = 0 TO tMap.Animation(aB_Animation).Frames - 1
tString = STRING(4, " "): GET #1,, tString
nBeg = 0: nCount = 2: GOSUB Str2UInt: tMap.Animation(aB_Animation).Frame(aFrame) = nValue
nBeg = 2: nCount = 2: GOSUB Str2UInt: tMap.Animation(aB_Animation).Zeit(aFrame) = nValue
NEXT
aB_Animation = aB_Animation + 1
CASE 0 'BACKGROUND
tString = STRING(36, " "): GET #1,, tString
CASE 1 'LAYER RECTANGLE
aB_Layer = aB_Layer + 1
tString = STRING(35, " "): GET #1,, tString
nBeg = 1: nCount = 1: GOSUB Str2UInt: tMap.Layer(aB_Layer).Visible = nValue
tMap.Layer(aB_Layer).Name = MID$(tString, 3, 12)
CASE 102 'BASEDATA
tString = STRING(8, " "): GET #1,, tString
nBeg = 1: nCount = 1: GOSUB Str2UInt: tMap.Layer(aB_Layer).BDatenTiefe = nValue
nBeg = 2: nCount = 4: GOSUB Str2UInt: tMap.Layer(aB_Layer).BDatenSize = nValue
tString = STRING(tMap.Layer(aB_Layer).BDatenSize, " ")
GET #1,, tString
tMap.Layer(aB_Layer).BDaten = tString
CASE 103 'MAPDATA
tString = STRING(8, " "): GET #1,, tString
nBeg = 1: nCount = 1: GOSUB Str2UInt: tMap.Layer(aB_Layer).DatenTiefe = nValue
nBeg = 2: nCount = 4: GOSUB Str2UInt: tMap.Layer(aB_Layer).DatenSize = nValue
tMap.Layer(aB_Layer).Daten = STRING(tMap.Layer(aB_Layer).DatenSize, " ")
GET #1,, tMap.Layer(aB_Layer).Daten
CASE 104 'METADATA
tString = STRING(8, " "): GET #1,, tString
nBeg = 1: nCount = 1: GOSUB Str2UInt: tMap.Layer(aB_Layer).MDatenTiefe = nValue
nBeg = 2: nCount = 4: GOSUB Str2UInt: tMap.Layer(aB_Layer).MDatenSize = nValue
tMap.Layer(aB_Layer).MDaten = STRING(tMap.Layer(aB_Layer).MDatenSize, " ")
GET #1,, tMap.Layer(aB_Layer).MDaten
CASE ELSE 'UNKNOWN
PRINT "Unbekannter Block ("+STR$(aBType)+") gefunden!"
END SELECT
NEXT
CLOSE 1
EXIT SUB
Str2UInt:
nCalc = 1
nValue = 0
REM FOR i = (nCount - 1) TO 0 STEP -1
FOR j = 0 TO (nCount - 1)
nChar = ASC(MID$(tString, nBeg + j+1, 1))
nValue = nValue + (nChar * nCalc)
nCalc = nCalc * 256
NEXT
RETURN
END SUB
For a better understanding of my code, you should read the manual of the mapeditor. Included with the editor is sourcecode for handling the mapfiles with blitzbasic.
Greetings
Fausti
P.S. Hope my english is understandable With mapeditor 1.4 it doesn't go. I'm using 1.1. But I'll update the source...
Loading Maps from www.mapeditor.de.vu - Blitz - 01-14-2005
Christ, ever heard of sub routines?
Loading Maps from www.mapeditor.de.vu - Fausti - 01-14-2005
Quote:Christ, ever heard of sub routines?
Yes I know them But I've written this snippet in 30min. It's not beatiful, bugfree nor optimized. It's only intension was to help me load a map for testing.
Loading Maps from www.mapeditor.de.vu - Blitz - 01-14-2005
Sure, but 5 mins, 30 min, or 30 days. Why are you using gosub? Using sub/functions does take any more time to do then using gosub.
Nah, it's not really any of my buisness. Good luck.
Loading Maps from www.mapeditor.de.vu - Fausti - 01-14-2005
Quote:Sure, but 5 mins, 30 min, or 30 days. Why are you using gosub? Using sub/functions does take any more time to do then using gosub.
Nah, it's not really any of my buisness. Good luck.
I've seen no basic source for 7 years. Today (better yesterday) I found freebasic and it sounds interesting, so I'll give it a try. In my QB times, I used a lot of gosubs, so I've used it here, too
The point is, I'm sure the label "Str2UInt" isn't necessary nor a Str2UInt sub or function is. I should use the right types for my vars, then I don't need to read the data as a string and converting these string to an uint. But I'm learning *lol*
Loading Maps from www.mapeditor.de.vu - Fausti - 01-14-2005
I've fixed the problem with loading maps from v1.4 and changed the Str2UInt gosub procedure into a nice function *lol*
Code: TYPE MAP_HEADER
blocks AS UINTEGER
layers AS UINTEGER
images AS UINTEGER
geoms AS UINTEGER
tilesets AS UINTEGER
anims AS UINTEGER
basis AS UINTEGER
daten AS UINTEGER
meta AS UINTEGER
sdaten AS UINTEGER
END TYPE
TYPE MAP_TILESET
MaskR AS UINTEGER
MaskG AS UINTEGER
MaskB AS UINTEGER
FrameB AS UINTEGER
FrameH AS UINTEGER
Anims AS UINTEGER
Frames AS UINTEGER
FileName AS STRING * 12
END TYPE
TYPE MAP_ANIMATION
Frames AS UINTEGER
StartFrame AS UINTEGER
Modus AS UINTEGER
SDaten AS UINTEGER
Frame(256) AS UINTEGER
Zeit(256) AS UINTEGER
END TYPE
TYPE MAP_LAYER
Visible AS UINTEGER
Name AS STRING * 12
BDatenTiefe AS UINTEGER
BDatenSize AS UINTEGER
BDaten AS STRING
DatenTiefe AS UINTEGER
DatenSize AS UINTEGER
Daten AS STRING
MDatenTiefe AS UINTEGER
MDatenSize AS UINTEGER
MDaten AS STRING
END TYPE
TYPE MAP_TYPE
Header AS MAP_HEADER
BlockSize(256) AS UINTEGER
TileSet(256) AS MAP_TILESET
Animation(256) AS MAP_ANIMATION
Layer(256) AS MAP_LAYER
END TYPE
FUNCTION Str2UInt(s$, start, count) AS UINTEGER
DIM nCalc: nCalc = 1
DIM nValue: nValue = 0
DIM nChar
FOR i = 0 TO (count - 1)
nChar = ASC(MID$(s$, start + i+1, 1))
nValue = nValue + (nChar * nCalc)
nCalc = nCalc * 256
NEXT
Str2UInt = nValue
END FUNCTION
SUB Map_Load(m, fname$)
DIM tString AS STRING
DIM nChar AS UINTEGER
DIM tChar AS STRING * 1
DIM tByte AS STRING * 1
DIM tMap AS MAP_TYPE
DIM aB_Tileset
DIM aB_Animation
DIM aB_Background
DIM aB_Layer
aB_Layer = -1
DIM aFrame
DIM nX, nY
DIM aBLOCK, lBType, aBType
DIM nBeg, nCount, nCalc
DIM nValue AS UINTEGER
OPEN fname$ FOR BINARY AS #1
' HEADER
tString = STRING(64, " "): GET #1,, tString
tMap.Header.blocks = Str2UInt(tString, 28, 2)
tMap.Header.layers = Str2UInt(tString, 30, 2)
tMap.Header.images = Str2UInt(tString, 32, 2)
tMap.Header.geoms = Str2UInt(tString, 34, 2)
tMap.Header.tilesets = Str2UInt(tString, 36, 2)
tMap.Header.anims = Str2UInt(tString, 38, 2)
tMap.Header.basis = Str2UInt(tString, 40, 2)
tMap.Header.daten = Str2UInt(tString, 42, 2)
tMap.Header.meta = Str2UInt(tString, 44, 2)
tMap.Header.sdaten = Str2UInt(tString, 48, 2)
' TABLE
tString = STRING(tMap.Header.blocks * 4, " "): GET #1,, tString
FOR i = 0 TO tMap.Header.blocks - 1
tMap.BlockSize(i) = Str2UInt(tString, (i*4), 4)
NEXT
' BLOECKE
FOR aBLOCK = 0 TO tMap.Header.blocks - 1
GET #1,, tChar: aBType = ASC(tChar)
SEEK #1, (SEEK(1)-1)
SELECT CASE aBType
CASE 100
tString = STRING(26, " "): GET #1,, tString
tMap.TileSet(aB_Tileset).MaskR = Str2UInt(tString, 1, 1)
tMap.TileSet(aB_Tileset).MaskG = Str2UInt(tString, 2, 1)
tMap.TileSet(aB_Tileset).MaskB = Str2UInt(tString, 3, 1)
tMap.TileSet(aB_Tileset).FrameB = Str2UInt(tString, 4, 2)
tMap.TileSet(aB_Tileset).FrameH = Str2UInt(tString, 6, 2)
tMap.TileSet(aB_Tileset).Anims = Str2UInt(tString, 10, 2)
tMap.TileSet(aB_Tileset).Frames = Str2UInt(tString, 12, 2)
tMap.TileSet(aB_Tileset).FileName = MID$(tString, 15, 12)
aB_Tileset = aB_Tileset + 1
CASE 101
tString = STRING(13, " "): GET #1,, tString
tMap.Animation(aB_Animation).Frames = Str2UInt(tString, 1, 2)
tMap.Animation(aB_Animation).StartFrame = Str2UInt(tString, 3, 2)
tMap.Animation(aB_Animation).Modus = Str2UInt(tString, 5, 1)
tMap.Animation(aB_Animation).SDaten = Str2UInt(tString, 6, 1)
FOR aFrame = 0 TO tMap.Animation(aB_Animation).Frames - 1
tString = STRING(4, " "): GET #1,, tString
tMap.Animation(aB_Animation).Frame(aFrame) = Str2UInt(tString, 0, 2)
tMap.Animation(aB_Animation).Zeit(aFrame) = Str2UInt(tString, 2, 2)
NEXT
aB_Animation = aB_Animation + 1
CASE 0
tString = STRING(36, " "): GET #1,, tString
CASE 1
aB_Layer = aB_Layer + 1
tString = STRING(36, " "): GET #1,, tString
tMap.Layer(aB_Layer).Visible = Str2UInt(tString, 1, 1)
tMap.Layer(aB_Layer).Name = MID$(tString, 3, 12)
CASE 102
tString = STRING(8, " "): GET #1,, tString
tMap.Layer(aB_Layer).BDatenTiefe = Str2UInt(tString, 1, 1)
tMap.Layer(aB_Layer).BDatenSize = Str2UInt(tString, 2, 4)
tString = STRING(tMap.Layer(aB_Layer).BDatenSize, " ")
GET #1,, tString
tMap.Layer(aB_Layer).BDaten = tString
CASE 103
tString = STRING(8, " "): GET #1,, tString
tMap.Layer(aB_Layer).DatenTiefe = Str2UInt(tString, 1, 1)
tMap.Layer(aB_Layer).DatenSize = Str2UInt(tString, 2, 4)
tMap.Layer(aB_Layer).Daten = STRING(tMap.Layer(aB_Layer).DatenSize, " ")
GET #1,, tMap.Layer(aB_Layer).Daten
CASE 104
tString = STRING(8, " "): GET #1,, tString
tMap.Layer(aB_Layer).MDatenTiefe = Str2UInt(tString, 1, 1)
tMap.Layer(aB_Layer).MDatenSize = Str2UInt(tString, 2, 4)
tMap.Layer(aB_Layer).MDaten = STRING(tMap.Layer(aB_Layer).MDatenSize, " ")
GET #1,, tMap.Layer(aB_Layer).MDaten
CASE 105
tString = STRING(4, " "): GET #1,, tString
' More to do...
CASE ELSE
END SELECT
NEXT
CLOSE 1
END SUB
Greetings
Fausti
Loading Maps from www.mapeditor.de.vu - v3cz0r - 01-14-2005
Cool but, couldn't you use VAL()? It converts strings to integer/fpoint numbers, it's an intrinsic function.
In 7 years i would forget about it too ;)
Loading Maps from www.mapeditor.de.vu - Fausti - 01-16-2005
Quote:Cool but, couldn't you use VAL()? It converts strings to integer/fpoint numbers, it's an intrinsic function.
In 7 years i would forget about it too
I'll use VAL() in the next version, thanks!
You've done a really good work with freebasic!
I'll try to rewrite some of my projects and tests from D in basic. So, you'll have some more examples to include into the freebasic package.
The SDL_BUTTON_RIGHT const seems to be invalid. It should be 3 not 4. But I'm using the libsdl.dll.a for 1.2.8. So, it could be my fault
Loading Maps from www.mapeditor.de.vu - Fausti - 01-16-2005
I can't use VAL() because the strings I read from the Mapfile aren't strings with
numbers in it. The number 65535 isn't like "65535" in the string, it's represented as
Chr$(255)+Chr$(255) to save space. I think it could be possible to read them like this:
Dim val16 as ushort
Get #1,, val16
But if the Mapfile's spec changes in the future, it's easier to change the parameters
of my conversion function, than to change all types.
Would it be possible to add something like:
Code: '$resicon: "icon.ico"
And while compiling, fbc would create the .rc file, compile it and appends the corresponding
object file to the linking process. It would make the process of compiling an executable with
icon under windows easier. Ok, it would be a windows-only feature (or is linux able to include
icon data in the executables?), but for someone without knowledge of resource files and linking
them into an executable, it would be a very nice feature.
I think I've found two bugs in the last cvs version of fbc.
1.
Code: Sub Map_Load(m, fname$)
...
End Sub
Sub LoadAllMaps()
Map_Load(0, "szene1.map")
Map_Load(1, "szene2.map")
End Sub
While compiling I get something like:
Code: ...expected ')' found ','...
He points to the Map_Load(0, "szene1.map"). With beta 10, it's all ok.
2.
I've told you already, that I think the SDL_BUTTON_RIGHT should be 3 not 4. So, I changed
sdlmouse.bi.
Compiling with beta 10 is ok. But the strange thing happens while compiling with
the cvs version. Fbc said the compiling process was successful. But while running my game,
the right button doesn't react, because sdl returns a 4 for the right button.
So, I changed SDL_BUTTON_RIGHT in sdlmouse.bi back to 4 and recompiled. Now, the same problem,
but sdl returns a 3 for the right mouse button. Perhaps I should use only stable versions
MFG
Fausti
Loading Maps from www.mapeditor.de.vu - v3cz0r - 01-16-2005
Yeah, ()'s are not allowed anymore when calling SUB's (not FUNCTION's) as it's in QB, 'cause they would break if you do say: mysub (myarg1 + exp) or expr, myarg2 etc.. So ()'s won't be optional on SUB's, blame M$ for not make them obrigatory with SUB's.
SDL headers will be exchanged on next release, the new headers have:
Code: #define SDL_BUTTON_LEFT 1
#define SDL_BUTTON_MIDDLE 2
#define SDL_BUTTON_RIGHT 3
#define SDL_BUTTON_WHEELUP 4
#define SDL_BUTTON_WHEELDOWN 5
|