Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Loading Maps from www.mapeditor.de.vu
#1
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 Wink 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 Wink With mapeditor 1.4 it doesn't go. I'm using 1.1. But I'll update the source...
Reply
#2
Christ, ever heard of sub routines?
oship me and i will give you lots of guurrls and beeea
Reply
#3
Quote:Christ, ever heard of sub routines?

Yes I know them Smile 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.
Reply
#4
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.
oship me and i will give you lots of guurrls and beeea
Reply
#5
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 Smile

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*
Reply
#6
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
Reply
#7
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 ;)
Reply
#8
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 Wink

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 Wink
Reply
#9
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 Wink

MFG
Fausti
Reply
#10
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
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)