Code archives/Miscellaneous/Mappy Routine
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| This is my first use of BlitzMax - a conversion of my Mappy plug-in (which was originally written for DBPro/GSDK and then for PureBasic). This was written for when I start my main game, and is a bit different from the other Mappy routines, as it allowed the adding, removing, copying and moving of layers. It can handle FMP05, FMP10 and (hopefully) FMP10RLE as well as FMA format. Unlike the previous versions, the intergrated graphics in a FMP file wont be extracted - this is because I dont have access to Windows bitmap format headers - this module was written on my iMac... This also means, that graphics needed by an FMP file will have to be 'manually' loaded. The code is in two parts - the main module, and the test program. Version 1.0.0.0 This is for BlitzMax | |||||
Const MAPPYERROR_INVALIDCOORD = 1
Const MAPPYERROR_OK = 0
Const MAPPYERROR_NOFILENAME = 2
Const MAPPYERROR_FILENOTFOUND = 3
Const MAPPYERROR_FILENOTOPENED = 4
Const MAPPYERROR_INVALIDHEADER = 5
Const MAPPYERROR_OUTOFMEM = 6
Const MAPPYERROR_INVALIDLAYER = 7
Const MAPPYERROR_UNKNOWNVERSION = 8
Const MAPPYERROR_TILENOTFOUND = 9
Const MAPPYERROR_LAYERNOTINUSE = 10
Const MAPPYERROR_MAPNOTLOADED = 11
Const MAPPYERROR_LAYERINUSE = 12
Const MAPPYERROR_UNKNOWNHEADER = 13
Const FMP05:Byte = 0
Const FMP10:Byte = 1
Const FMP10RLE:Byte = 2
Const FOREGROUND1 = 0
Const FOREGROUND2 = 1
Const FOREGROUND3 = 2
Type RGB
Field r:Byte
Field g:Byte
Field b:Byte
EndType
Type ANISTR
Field antype:Byte ' Type of anim, AN_?
Field andelay:Byte ' Frames To go before Next frame
Field ancount:Byte ' Counter, decs each frame, till 0, Then resets To andelay
Field anuser:Byte ' User info
Field ancuroff:Int ' Points To current offset in list
Field anstartoff:Int ' Points To start of blkstr offsets list, AFTER ref. blkstr offset */
Field anendoff:Int ' Points To End of blkstr offsets list
EndType
Type BLKSTR
Field bgoff:Int,fgoff:Int
Field fgoff2:Int,fgoff3:Int
Field user1:Int,user2:Int
Field user3:Short,user4:Short
Field user5:Byte
Field user6:Byte
Field user7:Byte
Field flags:Byte
EndType
Type TMappy
Const MAX_LAYERS = 8
Const HEADER_SIZE = 4
Const HEADER_AUTHOR$ = "ATHR"
Const HEADER_MAP$ = "MPHD"
Const HEADER_PALETTE$ = "CMAP"
Const HEADER_BLOCKGRFX$ = "BGFX"
Const HEADER_BODY$ = "BODY"
Const HEADER_LAYER$ = "LYR"
Const HEADER_ANIMATION$ = "ANDT"
Const HEADER_BLOCKDATA$ = "BKDT"
Const HEADER_EDITOR$ = "EDHD"
Const HEADER_EPHD$ = "EPHD"
Const MAPPY_HEADER1$ = "FORM"
Const MAPPY_HEADER2$ = "FMAP"
Const AN_END = 255 ' Animation types, AN_END = End of anims
Const AN_NONE = 0 ' No anim defined
Const AN_LOOPF = 1 ' Loops from start To End, Then jumps To start etc
Const AN_LOOPR = 2 ' As above, but from End To start
Const AN_ONCE = 3 ' Only plays once
Const AN_ONCEH = 4 ' Only plays once, but holds End frame
Const AN_PPFF = 5 ' Ping Pong start-End-start-End-start etc
Const AN_PPRR = 6 ' Ping Pong End-start-End-start-End etc
Const AN_PPRF = 7 ' Used internally by playback
Const AN_PPFR = 8 ' Used internally by playback
Const AN_ONCES = 9 ' * Used internally by playback
Const TILE_SIZE = 2
Field m_dMapType:Byte,m_dMapVersion:Short,m_dLSB:Byte
Field m_dMapWidth:Short,m_dMapHeight:Short,m_dMapDepth:Byte
Field m_dBlockWidth:Short,m_dBlockHeight:Short,m_dBlockSize:Short
Field m_dNumBlockStructs:Short,m_dNumBlockGFX:Short
Field m_dBlockGapX:Short,m_dBlockGapY:Short,m_dBlockStaggerX:Short,m_dBlockStaggerY:Short
Field m_dClipMask:Short
Field m_dTrans8:Byte,m_dTransRed:Byte,m_dTransGreen:Byte,m_dTransBlue:Byte
Field m_dNumAnimations:Int
Field m_dExtraByteSize:Int
Field m_dCpGraphicSize:Int,m_cpGraphics:TBank
Field m_dAuthorSize:Int
Field m_dTileSizeInBytes:Int,Mappy_FileSize:Int
Field m_dAuthor$
Global palette:RGB[256]
Global blockStructs:BLKSTR[]
Global layer:TBank[MAX_LAYERS]
Global extraBytesLayer:TBank[MAX_LAYERS]
Global animations:ANISTR[]
Field animationSeq:TBank
Function create:TMappy()
Local l:Int
m_dMapType=0
m_dMapVersion=0
m_dLSB=0
m_dMapWidth=0
m_dMapHeight=0
m_dMapDepth=0
m_dBlockWidth=0
m_dBlockHeight=0
m_dBlockSize=0
m_dNumBlockStructs=0
m_dNumBlockGFX=0
m_dBlockGapX=0
m_dBlockGapY=0
m_dBlockStaggerX=0
m_dBlockStaggerY=0
m_dClipMask=0
m_dTrans8=0
m_dTransRed=0
m_dTransGreen=0
m_dTransBlue=0
m_dNumAnimations=0
m_dExtraByteSize=0
m_dTileSizeInBytes=0
Mappy_FileSize=0
m_dAuthorSize=0
m_dAuthor$=""
versionHigh=0
versionLow=0
animations=Null
animationSeq=Null
For l=0 To 255
palette[l]=Null
Next
For l=0 To MAX_LAYERS-1
layer[l]=Null
extraBytesLayer[l]=Null
Next
blockStructs=Null
animations=Null
animationSeq=Null
Return New TMappy
EndFunction
Method loadMappyWord:Short(handle:TStream,order:Byte)
Local value:Short
Local temp:Byte[2]
temp[0]=ReadByte(handle)
temp[1]=ReadByte(handle)
If order
value=(Short(temp[1]) Shl 8)+Short(temp[0])
Else
value=(Short(temp[0]) Shl 8)+Short(temp[1])
EndIf
Return value
EndMethod
Method loadMappyHeader(handle:TStream,header:TBank)
PokeInt(header,0,ReadInt(handle))
EndMethod
Method swapByteOrder:Int(ThisLong:Int)
Local Hword:Int
Hword=((Thislong & 4294901760)/65536) & 65535
Thislong=((Thislong & 255)*16777216)+((Thislong & 65280)*256)+((Hword & 255)*256)+((Hword & 65280)/256)
Return Thislong
EndMethod
Method getMappySize:Int(handle:TStream,header:TBank)
Local temp:TBank
Local loop:Int
Local value:Int
' Read in the header
PokeInt(header,0,ReadInt(handle))
' Now we read in the size for this header
value=swapByteOrder(ReadInt(handle))
Return value
EndMethod
Method headerToString$(header:TBank)
Local loop:Int
Local text$
text$=""
For loop=0 To HEADER_SIZE-1
text$:+Chr$(PeekByte(header,loop))
Next
Return text$
EndMethod
Method mappySkipSection(handle:TStream,amount:Int)
SeekStream(handle,StreamPos(handle)+amount)
EndMethod
Method processPalette:Int(handle:TStream,ChunkSize:Int)
Local l:Int
Local i:Int
i=0
If m_dMapDepth<=8
For l=0 To (1 Shl m_dMapDepth)-1
palette[l]=New RGB
If palette[l]=Null
Return MAPPYERROR_OUYTOFMEM
EndIf
palette[l].r=ReadByte(handle)
palette[l].g=ReadByte(handle)
palette[l].b=ReadByte(handle)
i:+3
Next
EndIf
If i<>ChunkSize
mappySkipSection(handle,ChunkSize-l)
EndIf
Return MAPPYERROR_OK
EndMethod
Method MapHighTo8(handle:TStream,ChunkSize:Int)
mappySkipSection(handle,ChunkSize)
EndMethod
Method processBlockGraphics:Short(handle:TStream,ChunkSize:Int)
m_cpGraphics=CreateBank(ChunkSize)
If m_cpGraphics=Null Then Return MAPPYERROR_OUTOFMEM
m_cpGraphicSize=ChunkSize
Return MapHighTo8(handle,ChunkSize)
EndMethod
Method getMapHeader(handle:TStream,ChunkSize:Int)
Local temp:Short
Local i:Int
m_dMapVersion=(ReadByte(handle) Shl 8)+ReadByte(handle)
m_dLSB=ReadByte(handle)
m_dMapType=ReadByte(handle)
If m_dMapType<>FMP05 And m_dMapType<>FMP10 And m_dMapType<>FMP10RLE
Return MAPPYERROR_UNKNOWNVERSION
EndIf
i=4
m_dMapWidth=loadMappyWord(handle,m_dLSB)
m_dMapHeight=loadMappyWord(handle,m_dLSB)
temp=loadMappyWord(handle,m_dLSB)
temp=loadMappyWord(handle,m_dLSB)
i:+8
m_dBlockWidth=loadMappyWord(handle,m_dLSB)
m_dBlockHeight=loadMappyWord(handle,m_dLSB)
m_dMapDepth=loadMappyWord(handle,m_dLSB)
m_dBlockSize=loadMappyWord(handle,m_dLSB)
i:+8
m_dNumBlockStructs=loadMappyWord(handle,m_dLSB)
m_dNumBlockGFX=loadMappyWord(handle,m_dLSB)
i:+4
m_dTileSizeInBytes=m_dMapWidth*m_dMapHeight
Select m_dMapDepth
Case 15,16
m_dTileSizeInBytes:*2
Case 24
m_dTileSizeInBytes:*3
Case 32
m_dTileSizeInBytes:*4
EndSelect
If ChunkSize>24
m_dMapTrans8=ReadByte(handle)
m_dMapTransRed=ReadByte(handle)
m_dMapTransGreen=ReadByte(handle)
m_dMapTransBlue=ReadByte(handle)
i:+4
Else
m_dMapTrans8=0
m_dMapTransRed=255
m_dMapTransGreen=0
m_dMapTransBlue=255
EndIf
If ChunkSize>28
m_dBlockGapX=loadMappyWord(handle,m_dLSB)
i:+2
m_dBlockGapY=loadMappyWord(handle,m_dLSB)
i:+2
m_dBlockStaggerX=loadMappyWord(handle,m_dLSB)
i:+2
m_dBlockStaggerY=loadMappyWord(handle,m_dLSB)
i:+2
Else
m_dBlockGapX=m_dBlockWidth
m_dBlockGapY=m_dBlockHeight
m_dBlockStaggerX=0
m_dBlockStaggerY=0
EndIf
If ChunkSize>36
m_dClipMask=loadMappyWord(handle,m_dLSB)
Else
m_dClipMask=0
EndIf
Return MAPPYERROR_OK
EndMethod
Method allocateLayer:Int(layerLevel:Int,ChunkSize:Int,extraBytes:Int)
layer[layerLevel]=CreateBank(ChunkSize*TILE_SIZE)
If layer[layerLevel]=Null Then Return MAPPYERROR_OUTOFMEM
If extraBytes>0
extraBytesLayer[layerLevel]=CreateBank(ChunkSize*extraBytes)
If extraBytesLayer[layerLevel]=Null Then Return MAPPYERROR_OUTOFMEM
EndIf
Return MAPPYERROR_OK
EndMethod
Method getTileMapLayer:Int(handle:TStream,ChunkSize:Int,layerLevel:Int,extraBytes:Int)
Local status:Int
Local lp:Int
Local data:Short
Local rleCount:Int
status=allocateLayer(layerLevel,m_dMapWidth*m_dMapHeight,extraBytes)
If status=MAPPYERROR_OK
'Select doesn't seem to want to work with Byte variables
If m_dMapType=FMP05 Or m_dMapType=FMP10
lp=0
While lp<ChunkSize
data=ReadShort(handle)
If m_dMapType=FMP05
If data & 32768
data=((65536-data)/16) | 32768
Else
data:/m_dBlockSize
EndIf
EndIf
PokeShort(layer[layerLevel],lp,data)
lp:+SizeOf data
EndWhile
Else
While lp<ChunkSize
rleCount=ReadShort(handle)
If rleCount>0
While rleCount>0
data=ReadShort(handle)
PokeShort(layer[layerLevel],lp,data)
lp:+SizeOf data
relCount:-1
EndWhile
Else
If rleCount>32767
rel:-32767
data=ReadShort(handle)
While rleCount>0
PokeShort(layer[layerLevel],lp,data)
lp:+SizeOf data
relCount:-1
EndWhile
EndIf
EndIf
EndWhile
EndIf
EndIf
Return status
EndMethod
Method processBlockData:Int(handle:TStream,ChunkSize:Int)
Local loop:Int
blockStructs=New BLKSTR[m_dNumBlockStructs]
If blockStructs=Null Then Return MAPPYERROR_OUTOFMEM
For loop=0 To m_dNumBlockStructs-1
blockStructs[loop]=New BLKSTR
If blockStructs[loop]=Null Then Return MAPPYERROR_OUTOFMEM
blockStructs[loop].bgoff=ReadInt(handle)
blockStructs[loop].fgoff=ReadInt(handle)
blockStructs[loop].fgoff2=ReadInt(handle)
blockStructs[loop].fgoff3=ReadInt(handle)
blockStructs[loop].user1=ReadInt(handle)
blockStructs[loop].user2=ReadInt(handle)
blockStructs[loop].user3=ReadShort(handle)
blockStructs[loop].user4=ReadShort(handle)
blockStructs[loop].user5=ReadByte(handle)
blockStructs[loop].user6=ReadByte(handle)
blockstructs[loop].user7=ReadByte(handle)
blockStructs[loop].flags=ReadByte(handle)
Next
Return MAPPYERROR_OK
EndMethod
Method processAnimationData:Int(tempBuffer:TBank,ChunkSize:Int)
Local sequenceSize:Int
Local temp:Int
Local loop:Int
Local offset:Int
Local currentPos:Long
Local value:Int
'Count backwards to get the number of animations
m_dNumAnimations=0
sequenceSize=ChunkSize
temp=ChunkSize
Repeat
temp:-SizeOf ANISTR
sequenceSize:-SizeOf ANISTR
m_dNumAnimations:+1
Until PeekByte(tempBuffer,temp)=AN_END
animations=New ANISTR[m_dNumAnimations]
If animations=Null Then Return MAPPYERROR_OUTOFMEM
sequenceSize:/4
animationSeq=CreateBank(sequenceSize*SizeOf sequenceSize)
If animationSeq=Null Then Return MAPPYERROR_OUTOFMEM
offset=temp
For loop=0 To m_dNumAnimations-1
animations[loop]=New ANISTR
If animations[loop]=Null Then Return MAPPYERROR_OUTOFMEM
animations[loop].antype=PeekByte(tempBuffer,offset)
animations[loop].andelay=PeekByte(tempBuffer,offset+1)
animations[loop].ancount=PeekByte(tempBuffer,offset+2)
animations[loop].anuser=PeekByte(tempBuffer,offset+3)
animations[loop].ancuroff=PeekInt(tempBuffer,offset+4)
animations[loop].anstartoff=PeekInt(tempBuffer,offset+8)
animations[loop].anendoff=PeekInt(tempBuffer,offset+12)
If m_dMapType=FMP05
animations[loop].ancuroff:+ChunkSize
animations[loop].ancuroff:/4
animations[loop].anstartoff:+ChunkSize
animations[loop].anstartoff:/4
animations[loop].anendoff:+ChunkSize
animations[loop].anendoff:/4
EndIf
offset:+SizeOf ANISTR
Next
For loop=0 To sequenceSize-1
value=PeekInt(tempBuffer,loop*SizeOf sequenceSize)
If m_dMapType=FMP05
value:/m_dBlockSize
EndIf
PokeInt(animationSeq,loop*SizeOf sequenceSize,value)
Next
MapInitAnims()
Return MAPPYERROR_OK
EndMethod
Method MapInitAnims()
Local loop:Int
If m_dNumAnimations=0 Then Return
For loop=0 To m_dNumAnimations-1
Select animations[loop].antype
Case AN_PPFR
animations[loop].antype=AN_PPFF
Case AN_ONCES
animations[loop].antype=AN_ONCE
EndSelect
If animations[loop].antype=AN_LOOPR Or ..
animations[loop].antype=AN_PPRF Or ..
animations[loop].antype=AN_PPRR
If animations[loop].antype=AN_PPRF
animations[loop].antype=AN_PPRR
EndIf
animations[loop].ancuroff=animations[loop].anstartoff
If animations[loop].anstartoff<>animations[loop].anendoff
animations[loop].ancuroff=animations[loop].anendoff-1
EndIf
Else
animations[loop].ancuroff=animations[loop].anstartoff
EndIf
animations[loop].ancount=animations[loop].andelay
Next
EndMethod
Method processAnimation:Int(handle:TStream,ChunkSize:Int)
Local tempBuffer:TBank
Local loop:Int
tempBuffer=CreateBank(ChunkSize)
If tempBuffer=Null Then Return MAPPYERROR_OUTOFMEM
For loop=0 To ChunkSize-1
PokeByte(tempBuffer,loop,ReadByte(handle))
Next
loop=processAnimationData(tempBuffer,ChunkSize)
Return loop
EndMethod
Method loadMappyFile:Int(fileName$,extraBytes:Int)
Local handle:TStream
Local header1:TBank
Local header2:TBank
Local ChunkHeader:TBank
Local head1$
Local head2$
Local Chunk$
Local FilePosition:Int
Local DecodeFlag:Byte
Local ChunkSize:Int
Local result:Int
Local loop:Int
Local layer:Int
handle=OpenStream(fileName,True,False)
If handle=Null Then Return MAPPYERROR_FILENOTFOUND
header1=CreateBank(HEADER_SIZE)
header2=CreateBank(HEADER_SIZE)
ChunkHeader=CreateBank(HEADER_SIZE)
If header1=Null Or header2=Null Or ChunkHeader=Null
Return MAPPYERROR_OUTOFMEM
EndIf
m_dExtraByteSize=extraBytes
Mappy_FileSize=getMappySize(handle,header1)
loadMappyHeader(handle,header2)
head1$=headerToString(header1)
head2$=headerToString(header2)
If head1$=MAPPY_HEADER1$ And head2$=MAPPY_HEADER2$
FilePosition=12
Repeat
DecodeFlag=False
ChunkSize=getMappySize(handle,ChunkHeader)
FilePosition:+8
Chunk$=headerToString(ChunkHeader)
result=MAPPYERROR_OK
Select Chunk$
Case HEADER_AUTHOR$
m_dAuthorSize=ChunkSize
m_dAuthor$=""
For loop=1 To ChunkSize
m_dAuthor$:+Chr$(ReadByte(handle))
Next
Case HEADER_MAP$
getMapHeader(handle,ChunkSize)
Case HEADER_PALETTE$
processPalette(handle,ChunkSize)
Case HEADER_BLOCKGRFX$
processBlockGraphics(handle,ChunkSize)
Case HEADER_BODY$
result=getTileMapLayer(handle,ChunkSize,0,m_dExtraBytesSize)
Case HEADER_LAYER$
Case HEADER_ANIMATION$
result=processAnimation(handle,ChunkSize)
Case HEADER_BLOCKDATA$
result=processBlockData(handle,ChunkSize)
Case HEADER_EDITOR$
mappySkipSection(handle,ChunkSize)
Case HEADER_EPHD$
mappySkipSection(handle,ChunkSize)
Default
If Left$(Chunk$,Len(HEADER_LAYER$))=HEADER_LAYER$
layer=Asc(Right$(Chunk$,1))-Asc("0")
If layer>=0 And layer<MAX_LAYERS
result=getTileMapLayer(handle,ChunkSize,layer,m_dExtraBytesSize)
Else
result=MAPPYERROR_INVALIDLAYER
EndIf
Else
result=MAPPYERROR_UNKNOWNHEADER
EndIf
EndSelect
FilePosition:+ChunkSize
Until FilePosition>=Mappy_FileSize Or result<>MAPPYERROR_OK
Else
result=MAPPYERROR_INVALIDHEADER
EndIf
CloseStream(handle)
Return result
EndMethod
Method returnMappyFileSize:Int()
Return Mappy_FileSize
EndMethod
Method returnAuthorName$()
Return m_dAuthor$
EndMethod
Method returnMappyVersion:Short()
Return m_dMapVersion
EndMethod
Method returnMapWidth:Short()
Return m_dMapWidth
EndMethod
Method returnMapHeight:Short()
Return m_dMapHeight
EndMethod
Method returnMapDepth:Byte()
Return m_dMapDepth
EndMethod
Method returnMapType:Byte()
Return m_dMapType
EndMethod
Method returnBlockWidth:Short()
Return m_dBlockWidth
EndMethod
Method returnBlockHeight:Short()
Return m_dBlockHeight
EndMethod
Method returnBlockSize:Short()
Return m_dBlockSize
EndMethod
Method getPositionInLayer:Int(x:Short,y:Short)
Return (x*TILE_SIZE)+(y*m_dMapWidth*TILE_SIZE)
EndMethod
Method tileAtPosition:Int(layers:Short,x:Short,y:Short)
If (layers>=0 And layers<MAX_LAYERS) And (x>=0 And x<m_dMapWidth) And (y>=0 And y<m_dMapHeight)
If layer[layers]
Return Int(PeekShort(layer[layers],getPositionInLayer(x,y)) )
EndIf
EndIf
Return 0
EndMethod
Method writeTileAtPosition:Int(layers:Short,x:Short,y:Short,value:Short)
If (layers>=0 And layers<MAX_LAYERS) And (x>=0 And x<m_dMapWidth) And (y>=0 And y<m_dMapHeight)
If layer[layers]
PokeShort(layer[layers],getPositionInLayer(x,y),value)
Return True
EndIf
EndIf
Return False
EndMethod
Method returnBlockStructInfo(which:Int,store:Byte Ptr)
If which>=0 And which<m_dNumBlockStructs
MemCopy(store,blockStructs[which],SizeOf BLKSTR)
EndIf
EndMethod
Method returnNumberOfAnimations:Int()
Return m_dNumAnimations
EndMethod
Method returnNumberOfBlockStructs:Int()
Return m_dNumBlockStructs
EndMethod
Method returnNumberOfBlockGFX:Int()
Return m_dNumBlockGFX
EndMethod
Method returnClipMask:Short()
Return m_dClipMask
EndMethod
Method returnBackgroundOffset:Int(block:Int)
Local b:BLKSTR
b=New BLKSTR
returnBlockStructInfo(block,b)
Return b.bgoff/(m_dBlockWidth*m_dBlockHeight)
EndMethod
Method returnForegroundOffset:Int(block:Int,which:Short)
Local b:BLKSTR
Local index:Short
b=New BLKSTR
returnBlockStructInfo(block,b)
Select which
Case FOREGROUND1
index=b.fgoff
Case FOREGROUND2
index=b.fgoff2
Case FOREGROUND3
index=b.fgoff3
EndSelect
Return index/(m_dBlockWidth*m_dBlockHeight)
EndMethod
Method returnCurrentAnimationBlock:Int(block:Int)
Local a:ANISTR
Local temp:Int
a=New ANISTR
block=block & 32767
If getAnimation(m_dNumAnimations-block,a)
temp=PeekInt(animationSeq,a.ancuroff*SizeOf temp)
Return temp
Else
Return 0
EndIf
EndMethod
Method getAnimation:Short(block:Short,store:Byte Ptr)
If block>=0 And block<m_dNumAnimations
MemCopy(store,animations[block],SizeOf ANISTR)
Return True
Else
Return False
EndIf
EndMethod
Method addLayer:Int(layers:Int)
If layers>=0 And layers<MAX_LAYERS
If layer[layers] Then Return MAPPYERROR_LAYERINUSE
If dMapWidth>0 And m_dMapHeight>0
Return allocateLayer(layers,m_dMapWidth*m_dMapheight,m_dExtraBytes)
Else
Return MAPPYERROR_MAPNOTLOADED
EndIf
Else
Return MAPPYERROR_INVALIDLAYER
EndIf
EndMethod
Method deleteLayer:Int(layers:Int)
If layers>=0 And layers<MAX_LAYERS
If layer[layers]=Null
Return MAPPYERROR_LAYERNOTINUSE
Else
ResizeBank(layer[layers],0)
layer[layers]=Null
EndIf
Else
Return MAPPYERROR_INVALIDLAYER
EndIf
EndMethod
Method copyLayer:Int(fromLayer:Int,toLayer:Int)
Local status:Int
If fromlayer>=0 And fromLayer<MAX_LAYERS And toLayer>=0 And toLayer<MAX_LAYERS
If layer[fromLayer]=Null
Return MAPPYERROR_LAYERNOTINUSE
EndIf
If layer[toLayer]=Null
status=allocateLayer(toLayer,m_dMapWidth*m_dMapHeight,m_dExtraBytes)
If status<>MAPPERROR_OK
Return status
EndIf
EndIf
CopyBank( layer[fromLayer],0,layer[toLayer],0,BankSize(layer[fromlayer]))
Return MAPPYERROR_OK
Else
Return MAPPYERROR_INVALIDLAYER
EndIf
EndMethod
Method clearLayer:Int(layers:Int)
Local l:Int
If layers>=0 And layers<MAX_LAYERS
If layer[layers]=Null Then Return MAPPYERROR_LAYERNOTINUSE
For l=0 To BankSize(layer[layers])-1
PokeByte(layer[layers],l,0)
Next
Return MAPPYERROR_OK
Else
Return MAPPYERROR_INVALIDLAYER
EndIf
EndMethod
Method moveLayer:Int(fromLayers:Int,toLayer:Int)
If fromlayer>=0 And fromLayer<MAX_LAYERS And toLayer>=0 And toLayer<MAX_LAYERS
If layer[fromLayer]=Null
Return MAPPYERROR_LAYERNOTINUSE
EndIf
If layer[toLayer]=Null
status=allocateLayer(toLayer,m_dMapWidth*m_dMapHeight,m_dExtraBytes)
If status<>MAPPERROR_OK
Return status
EndIf
EndIf
CopyBank( layer[fromLayer],0,layer[toLayer],0,BankSize(layer[fromlayer]))
Return clearLayer(fromLayer)
Else
Return MAPPYERROR_INVALIDLAYER
EndIf
EndMethod
Method returnRGB(colour:Byte,store:Byte Ptr)
MemCopy(store,palette[colour],SizeOf RGB)
EndMethod
Method updateAnimations()
Local loop:Int
If m_dNumAnimations=0 Then Return
For loop=0 To m_dNumAnimations-1
If animations[loop].antype<>AN_NONE
animations[loop].ancount:-1
If animations[loop].ancount & 128
animations[loop].ancount=animations[loop].andelay
Select animations[loop].antype
Case AN_LOOPF
If animations[loop].anstartoff<>animations[loop].anendoff
animations[loop].ancuroff:+1
If animations[loop].ancuroff=animations[loop].anendoff
animations[loop].ancuroff=animations[loop].anstartoff
EndIf
EndIf
Case AN_LOOPR
If animations[loop].anstartoff<>animations[loop].anendoff
animations[loop].ancuroff:-1
If animations[loop].ancuroff=animations[loop].anstartoff-1
animations[loop].ancuroff=animations[loop].anendoff
EndIf
EndIf
Case AN_ONCE
If animations[loop].anstartoff<>animations[loop].anendoff
animations[loop].ancuroff:+1
If animations[loop].ancuroff=animations[loop].anendoff
animations[loop].antype=AN_ONCES
animations[loop].ancuroff=animations[loop].anendoff
EndIf
EndIf
Case AN_ONCEH
If animations[loop].anstartoff<>animations[loop].anendoff
If animations[loop].ancuroff<>animations[loop].anendoff-1
animations[loop].ancuroff:+1
EndIf
EndIf
Case AN_PPFF
If animations[loop].anstartoff<>animations[loop].anendoff
animations[loop].ancuroff:+1
If animations[loop].ancuroff=animations[loop].anendoff
animations[loop].ancuroff:-2
animations[loop].antype=AN_PPFR
If animations[loop].ancuroff<animations[loop].anstartoff
animations[loop].ancuroff:+1
EndIf
EndIf
EndIf
Case AN_PPFR
If animations[loop].anstartoff<>animations[loop].anendoff
animations[loop].ancuroff:-1
If animations[loop].ancuroff=animations[loop].anstartoff-1
animations[loop].ancuroff:+2
animations[loop].antype=AN_PPFF
If animations[loop].ancuroff>animations[loop].anendoff
animations[loop].ancuroff:-1
EndIf
EndIf
EndIf
Case AN_PPRR
If animations[loop].anstartoff<>animations[loop].anendoff
animations[loop].ancuroff:-1
If animations[loop].ancuroff=animations[loop].anstartoff-1
animations[loop].ancuroff:+2
animations[loop].antype=AN_PPRF
If animations[loop].ancuroff>animations[loop].anendoff
animations[loop].ancuroff:-1
EndIf
EndIf
EndIf
Case AN_PPRF
If animations[loop].anstartoff<>animations[loop].anendoff
animations[loop].ancuroff:-1
If animations[loop].ancuroff=animations[loop].anendoff
animations[loop].ancuroff:-2
animations[loop].antype=AN_PPRR
If animations[loop].ancuroff<animations[loop].anstartoff
animations[loop].ancuroff:+1
EndIf
EndIf
EndIf
EndSelect
EndIf
EndIf
Next
EndMethod
EndType
Strict
Import "TMappy.bmx"
Global mappy:TMappy=TMappy.create()
Local result
Local block:BLKSTR=New BLKSTR
Local rgbCol:RGB=New RGB
Global tileGraphics:TImage[81]
Local x:Int,y:Int,px:Int,py:Int
Local one$
Local a$
Local tile:Int
Local mapWidth,mapHeight,image:Short
Local blockWidth,blockHeight
Graphics 1024,768
For x=1 To 80
one$=String(x)
a$=Right$("000000"+one$,6)
Print a$
'tileGraphics[x]=New TImage
tileGraphics[x]=LoadImage("MappyGraphics\G"+a$+".PNG")
If tileGraphics[x]=Null
Print "File Not Found"
End
EndIf
Next
result=mappy.loadMappyFile("test.fmp",0)
Print result
If result<>MAPPYERROR_OK
WaitKey
End
EndIf
Print "Map Type:"
Print mappy.returnMapType()
If mappy.returnMapType()=FMP05
Print "FMP 05"
Else
If mappy.returnMapType()=FMP10
Print "FMP 10"
Else
If mappy.returnMapType()=FMP10RLE
Print "FMP 10RLE"
Else
Print "Unknown"
EndIf
EndIf
EndIf
Print "Mappy File Size:"
Print mappy.returnMappyFileSize()
Print "Mappy Author Name:"
Print mappy.returnAuthorName$()
Print "Mappy Version:"
Print mappy.returnMappyVersion()
Print "Mappy Width:"
Print mappy.returnMapWidth()
Print "Mappy Height:"
Print mappy.returnMapHeight()
Print "Map Depth:"
Print mappy.returnMapDepth()
Print "Block Width:"
Print mappy.returnBlockWidth()
Print "Block Height:"
Print mappy.returnBlockHeight()
Print "Block Size:"
Print mappy.returnBlockSize()
Print "Number Of Block Structures:"
Print mappy.returnNumberOfBlockStructs()
Print "Number Of Block GFX:"
Print mappy.returnNumberOfBlockGFX()
Print "Clip Mask:"
Print mappy.returnClipMask()
Print "Tile At Position 0,10,10:"
Print mappy.tileAtPosition(0,10,10)
Print "Tile At Position 0,0,0:"
Print mappy.tileAtPosition(0,0,0)
Print "Tile At Position 5,0,0:"
Print mappy.tileAtPosition(5,0,0)
Print "Write Tile At Position 0,10,10:"
Print mappy.writeTileAtPosition(0,10,10,7)
Print "Reading Tile:"
Print mappy.tileAtPosition(0,10,10)
Print "Getting block info for 1:"
mappy.returnBlockStructInfo(1,block)
Print "Flags:"
Print block.bgoff
Print block.fgoff
Print block.fgoff2
Print block.fgoff3
Print block.user1
Print block.user2
Print block.user3
Print block.flags
Print "Number of animations:"
Print mappy.returnNumberOfAnimations()
Print "Copying Layer:"
Print mappy.moveLayer(0,1)
Print "Getting RGB value:"
mappy.returnRGB(0,rgbCol)
Print "Red:"
Print rgbCol.r
Print "Green:"
Print rgbCol.g
Print "Blue:"
Print rgbCol.b
mapWidth=mappy.returnMapWidth()
mapHeight=mappy.returnMapHeight()
blockWidth=mappy.returnBlockWidth()
blockHeight=mappy.returnBlockHeight()
px=0
py=0
While Not KeyHit(KEY_ESCAPE)
Cls
If KeyHit(KEY_UP) And py>0 Then py=py-1
If KeyHit(KEY_DOWN) And py<mapHeight Then py=py+1
If KeyHit(KEY_LEFT) And px>0 Then px=px-1
If KeyHit(KEY_RIGHT) And px<mapWidth Then px=px+1
displayMap(px,py,100,100,blockWidth,blockHeight)
Flip
mappy.updateAnimations()
Wend
WaitKey
End
Function displayMap(x:Int,y:Int,maxX:Int,maxY:Int,blockWidth:Int,blockHeight:Int)
Local lx:Int
Local ly:Int
Local px:Int
Local py:Int
Local tile:Short
Local image:Int
For ly=0 To maxY
For lx=0 To maxX
px=x+lx
py=y+ly
tile=mappy.tileAtPosition(1,px,py)
If tile<>0
If tile & (1 Shl 15)
'Animate
tile=mappy.returnCurrentAnimationBlock(tile)
EndIf
image=mappy.returnBackgroundOffset(tile)
If image>0 And tileGraphics[image] Then DrawImage tileGraphics[image],lx*blockWidth,ly*blockHeight
image=mappy.returnForegroundOffset(tile,FOREGROUND1)
If image>0 And tileGraphics[image] Then DrawImage tileGraphics[image],lx*blockWidth,ly*blockHeight
EndIf
Next
Next
EndFunction |
Comments
None.
Code Archives Forum