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