Code archives/Graphics/2D Sprites with Movement and Animation scripting
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| Being able to define paths and movement for different sprites that operate independant of each other can be a pain to code. SAM makes it simple to define different paths and animations for sprites and then play those movements and animations back. It includes some simple single letter commands: A - Animate (A Repeat,Frame,Delay,Frame,Delay,......) L - Label L # (Used for Jumps/gotos, it defines a label) J - Jump # (Jumps to a label) M - Move (M Xpoints,YPoints,XSpeed,YSpeed) ETC see code for more. | |||||
' IMPLEMENTATION of types and support functions
' set some local vars for use
Local RVal:Int=0
Local A:Int=0
' Define Paths for use by SAM
Local Square:String="A 1,1,100,2,100,3,100:L 1:M 150,0,.5,0:M 0,150,0,.5:M 150,0,-.5,0:M 0,150,0,-.5:J 1"
Local Triangle:String="A 1,5,50,4,50,3,50,2,50,1,50:L 1:M 150,150,.5,.5:M 150,0,-.5,0:M 150,150,.5,-.5:J 1"
' setup the graphics
Graphics 800,600,,0
HideMouse
' Load Anim images
RVal=IMGs_Add("3232.png",32,32)
SeedRnd MilliSecs()
' Make 4 sprites that move in Square path and 4 that move in triangle path
For A=1 To 8
' Create a Bob/Sprite
RVal=BOB_Add(1,Rnd()*GraphicsWidth(),Rnd()*GraphicsHeight(),Rnd()*20,Rnd()+.1,.Rnd()+.1)
' Now try out SAM
If A>4 Then
SAM_calc(Triangle,,RVAL)
Else
SAM_calc(Square,,RVAL)
End If
Next
' MAIN LOOP
Repeat
Cls
SAM_UpdateAll()
Flip
Until KeyHit (KEY_ESCAPE)
' END OF IMPLEMENTATION
'===============================
' The junk that makes this work
'===============================
'===================================
' IMAGES DEFINED HERE
'===================================
Global IMG:t_IMG[] ' Images
Global IMGCount:Int=-1
' stuff needed to work
Global AIMAGE:tImage[] ' Anim Images
Global AIMAGECount:Int=-1
Type t_IMG
Field ImagePTR:tImage Ptr ' Pointer to a blitz image type
Field FrameNum:Int ' Frame Number
Field Width:Int ' Somewhat redundant, but too damn convenient
Field Height:Int
Method Draw(X:Int,Y:Int)
DrawImage(ImagePTR[0],X,Y,FrameNum)
End Method
End Type
'==============================================
' IMG_ADD
'----------------------------------------------
' Defines an image and returns the image number
'----------------------------------------------
Function IMG_Add:Int(mImagePTR:tImage Ptr,mFrameNum:Int,mFrameWidth:Int,mFrameHeight:Int)
Local A:Int
IMGCount=IMGCount+1
IMG = IMG[..IMGCount+1]
IMG[IMGCount]=New t_IMG
IMG[IMGCount].ImagePTR=mImagePTR
IMG[IMGCount].FrameNum=mFrameNum
IMG[IMGCount].Width=mFrameWidth
IMG[IMGCount].Height=mFrameHeight
End Function
Function IMGs_Add:Int(FileName:String,FrameWidth:Int,FrameHeight:Int)
Local AnImage:tImage
Local AnimImage:tImage
Local iFrame:Int,FramesTotal:Int
AnImage=LoadImage(FileName)
FramesTotal = (ImageWidth(AnImage)/FrameWidth) * (ImageHeight(AnImage)/FrameHeight)
AIMAGECount = AIMAGECount + 1
AIMAGE=AIMAGE[..AIMAGECount+1]
' AIMAGE[AIMAGECount]
AIMAGE[AIMAGECount]=LoadAnimImage(FileName,FrameWidth,FrameHeight,0,FramesTotal)
For iFrame=0 To FramesTotal
IMG_Add(Varptr AIMAGE[0],iFrame,FrameWidth,FrameHeight)
Next
Return FramesTotal
End Function
'========================================
' BOBS DEFINED HERE
'========================================
Global BOB:t_BOB[] ' Images
Global BOBCount:Int=-1
Type t_BOB
Global MPS:Float=60 ' Moves Per Second
Global Delta:Float
Global LastDelta:Float
Global MyTimer:Float
Field Active:Int=1 ' Are we Active?
Field X:Float=0 ' Current X Position
Field Y:Float=0 ' Current Y Position
Field LastX:Float=0 ' Last X Position
Field LastY:Float=0 ' Last Y Position
Field CountX:Float=0 ' Number of X Movements since last reset
Field CountY:Float=0 ' Number of Y movements since last reset
Field IMGNum:Int=0 ' Image Number from IMG (IMAGES.BMX)
Field SX:Float=0 ' X Speed
Field SY:Float=0 ' Y Speed
Field WrapAround:Int=1 ' 1 - WrapAround 0 - No Checking
Field WrapBehaviour:Int=0 ' 0-Go to other side, 1 = Bounce
Function Width:Int(BobNum)
Return IMG[BOB[BOBNum].IMGNum].Width
End Function
Function Height:Int(BobNum)
Return IMG[BOB[BOBNum].IMGNum].Height
End Function
End Type
Function BOB_Add(iCount:Int=1,X:Float=0,Y:Float=0,IMGNum:Int=0,SX:Float=0,SY:Float=0,sSAM:String="")
Local A:Int
For A=0 To iCount-1
BOBCount = BOBCount+1
BOB = BOB[..BOBCount+1]
BOB[BOBCount]=New t_BOB
BOB[BOBCount].X = X
BOB[BOBCount].Y = Y
BOB[BOBCount].LastX = X
BOB[BOBCount].LastY = Y
BOB[BOBCount].IMGNum = IMGNum
BOB[BOBCount].SX = SX
BOB[BOBCount].SY = SY
Next
Return BOBCount
End Function
Function BOB_Update()
Local A:Int
If BOBCount=-1 Then Return -1
If BOB[0].MyTimer>0 Then
BOB[0].Delta = (MilliSecs()/5)-BOB[0].MyTimer
Else
BOB[0].Delta = 0 ' dont move till we have a delta
End If
BOB[0].MyTimer = MilliSecs()/5
If Abs(BOB[0].Delta-BOB[0].LastDelta)>1 Then
BOB[0].LastDelta=BOB[0].Delta
Else
BOB[0].Delta=BOB[0].LastDelta
End If
'Print BOB[0].Delta
For A=0 To BOBCount
If BOB[A].Active=1 Then
' Save X , Y
BOB[A].LastX = BOB[A].X
BOB[A].LastY = BOB[A].Y
' Update position
BOB[A].X = BOB[A].X + (BOB[A].SX * BOB[A].Delta)
BOB[A].Y = BOB[A].Y + (BOB[A].SY * BOB[A].Delta)
' counters/Used alot For SAM
BOB[A].CountX = BOB[A].CountX + (BOB[A].SX * BOB[A].Delta)
BOB[A].CountY = BOB[A].CountY + (BOB[A].SY * BOB[A].Delta)
' Zones
'SetZone(A,BOB_X#(A),BOB_Y#(A),ImageWidth(IB_IMAGE( BOB_I(A) ) ),ImageHeight(IB_IMAGE( BOB_I(A) ) ))
' If wrap
If BOB[A].WrapAround=1 Then
If BOB[A].WrapBehaviour=0 Then
If BOB[A].X+BOB[A].Width(A)<0 Then BOB[A].X = GraphicsWidth()
If BOB[A].X>GraphicsWidth() Then BOB[A].X = BOB[A].Width(A)*-1
If BOB[A].Y+BOB[A].Height(A)<0 Then BOB[A].Y = GraphicsHeight()
If BOB[A].Y>GraphicsHeight() Then BOB[A].Y = BOB[A].Height(A)*-1
Else
If BOB[A].X<0 Then
BOB[A].SX = Abs(BOB[A].SX)
End If
If BOB[A].X+BOB[A].Width(A)>GraphicsWidth() Then
BOB[A].SX = Abs(BOB[A].SX) * -1
End If
If BOB[A].Y<0 Then
BOB[A].SY = Abs(BOB[A].SY)
End If
If BOB[A].Y+BOB[A].Height(A)>GraphicsHeight() Then
BOB[A].SY = Abs(BOB[A].SY) * -1
End If
End If
End If
End If
Next
End Function
Function BOB_Draw()
Local A:Int
If BOBCount=-1 Then Return -1
For A=0 To BOBCount
IMG[BOB[A].IMGNum].Draw(BOB[A].X,BOB[A].Y)
Next
End Function
Function BOB_ResetCounts(BobNum:Int)
BOB[BobNum].CountX=0
BOB[BobNum].CountY=0
End Function
'================================================
' SAM DEFINED HERE
'================================================
' COMMANDS , Seperator :
' M X,Y,Steps
' Goto (char) - goes To a label (char):
' stuff needed to work
Global SAM:t_Sam[] ' Sam
Global SAMCount:Int=-1
Type t_Sam
Global BufferSize:Int=1024 ' amount To buffer each time in bytes
Field Bank:TBank ' Handle to Bank
Field BankOff:Int=0 ' Offset into Bank
Field EXE:Int=0 ' Offset of current execution
Field BOBnum:Int=0 ' Bob number to use
Field ANIM:Int=0 ' Offset of current animation
Field ANIMDelay:Int=0 ' countdown till next anim
Field ANIMDelayType:Byte=0 ' 0 is time (100=1 second)
End Type
Function SAM_add()
Local A:Int
SAMCount=SAMCount+1
SAM = SAM[..SAMCount+1]
SAM[SAMCount]=New t_SAM
Return SAMCount
End Function
'=========================================================
' Bank Layout
'=========================================================
' Byte 0 - CMD
' Command Structure:
' 1 - [Label] (Byte:1:Int:4) 5 - The Int is the label number, although For now only (0-255) supported
' Part of move command
' 2 - [Set X,Y speed] (Byte:1:Float:4:Float:4) 9
' 3 - [Reset XY counters] (Byte:1) 1
' 4 - [Wait Counters] (Byte:1:Float:4:Float:4) 9
' 5 - [Jump To Label] (Byte:1:Int 4) 5 - the Int is offset of the label
' 6 - [Go] (Byte:1:Float:4:Float:4) 9
' 7 - [Image] (Byte:1:Int:4) 5
' 8 - [ANIM] [Short:2:Int:4] 6 [short:2] [int:4] 6
'SAM_calc("L 1:M 10,10,1,1:M -10,-10,-1,-1:J 1",0)
' SAM Commands
'==============
' L # ; Label - See jump - followed by number of label (0-255)
' ex: L 1
'
' M PX,PY,SX,SY ; Move - moves bobs - PixelsToMoveX,PixelsToMoveY,#SpeedX,#SpeedY
' ex: M 100,100,.1,.1
'
' G X,Y ; Go - moves bob directly To spot - X,Y
'
' I # ; Image - Sets Image of bob
'
' J # ; Jump - jump/Goto To a label (see L command)
'
' A REPEAT,Frame,Delay,Frame,Delay,Frame,Delay
' ex: J 1
'==================
Function SAM_Update()
Local A:Int
If SAMCount=-1 Then Return -1
For A=0 To SAMCount
SAM_Run(A)
Next
End Function
Function SAM_UpdateAll()
SAM_Update()
BOB_Update()
BOB_Draw()
End Function
Function SAM_Run(A:Int)
Local X:Float,Y:Float,CheckX:Float,CheckY:Float,iNum:Int,T:Int
Local Z:Int
' okay execute current command
#SAM_RUNNEXT
If SAM[A].EXE>=SAM[A].BankOff Then Return 0
Select PeekByte(SAM[A].Bank,SAM[A].EXE)
Case 1 ' label
' 0 (1 2 3 4)
' we just skip labels when we encounter them
SAM[A].EXE=SAM[A].EXE+5
Goto SAM_RUNNEXT
Case 2 ' set speed
' 0 (1 2 3 4) (5 6 7 8)
BOB[SAM[A].BobNum].SX = PeekFloat(SAM[A].Bank,SAM[A].EXE+1)
BOB[SAM[A].BobNum].SY = PeekFloat(SAM[A].Bank,SAM[A].EXE+5)
SAM[A].EXE=SAM[A].EXE+9
Goto SAM_RUNNEXT
Case 3 ' reset counts
' 0
BOB_resetcounts(SAM[A].BOBnum)
SAM[A].EXE=SAM[A].EXE+1
Goto SAM_RUNNEXT
Case 4 ' wait counters
' T = Meets Tests
' 0 (1 2 3 4) (5 6 7 8)
' Check X,Y
CheckX = PeekFloat(SAM[A].Bank,SAM[A].EXE+1)
CheckY = PeekFloat(SAM[A].Bank,SAM[A].EXE+5)
T=0
If Abs(BOB[SAM[A].BOBnum].countX ) >= CheckX Then
T=T+1
If BOB[SAM[A].BobNum].SX<>0 Then 'First time
BOB[SAM[A].BobNum].SX=0 ' stop X speed
CheckX = CheckX - Abs(BOB[SAM[A].BOBnum].countX )
'BOB[SAM[A].BobNum].X = BOB[SAM[A].BobNum].X + CheckX
End If
' set X exactly
' 100 110
End If
If Abs(BOB[SAM[A].BOBnum].countY ) >= CheckY Then
T=T+1
If BOB[SAM[A].BobNum].SY<>0 Then ' First time
BOB[SAM[A].BobNum].SY=0 ' stop X speed
CheckY = CheckY - Abs(BOB[SAM[A].BOBnum].countX )
'BOB[SAM[A].BobNum].Y = BOB[SAM[A].BobNum].Y + CheckY
End If
End If
' If both tests met Then go To Next command
If T=2 Then
SAM[A].EXE=SAM[A].EXE+9
Goto SAM_RUNNEXT
End If
Case 5 ' Jump
iNum=PeekInt(SAM[A].Bank,SAM[A].EXE+1) ' get offset
SAM[A].EXE=iNum
Goto SAM_RUNNEXT
Case 6 ' Go
X=PeekFloat(SAM[A].Bank,SAM[A].EXE+1)
Y=PeekFloat(SAM[A].Bank,SAM[A].EXE+5)
BOB[SAM[A].Bobnum].X=X
BOB[SAM[A].Bobnum].Y=Y
SAM[A].EXE=SAM[A].EXE+9
Case 7 ' Image
iNum=PeekInt(SAM[A].Bank,SAM[A].EXE+1) ' get Image
BOB[SAM[A].Bobnum].IMGnum = iNum
SAM[A].EXE=SAM[A].EXE+5
Case 8 ' Anim
' Field ANIM:Int=0 ' Offset of current animation
' Field ANIMDelay:Int=0 ' countdown till next anim
' read frame
' read delay
' jump spot
Z = PeekInt(SAM[A].Bank,SAM[A].EXE+1)
' get first frame and delay
iNum = Int(PeekShort(SAM[A].Bank,SAM[A].EXE+5))
SAM[A].AnimDelay= PeekInt(SAM[A].Bank,SAM[A].EXE+7)
If SAM[A].AnimDelayType=0 Then
SAM[A].AnimDelay=MilliSecs() + (SAM[A].AnimDelay*10)
End If
SAM[A].ANIM = SAM[A].EXE + 11
' set bob frame
BOB[SAM[A].Bobnum].IMGnum = iNum
' jump ahead
SAM[A].EXE = Z
' iNum = Int(PeekShort(SAM[A].Bank,SAM[A].EXE+1))
' SAM[A].AnimDelay= PeekInt(SAM[A].Bank,SAM[A].EXE+3)
' save next offset
' SAM[A].ANIM=SAM[A].EXE+7
' set first frame
' BOB[SAM[A].Bobnum].IMGnum = iNum
' move exe spot
' need to store stepover spot, or read shorts till 65330
' short , int
' read until we get a short over 65529
End Select
' do any animation
If Not SAM[A].AnimDelay=0 Then
If SAM[A].AnimDelayType=0 Then ' 100=1 second
If SAM[A].AnimDelay<MilliSecs() Then
#SAM_RepeatFrame
' get frame and delay
iNum = Int(PeekShort(SAM[A].Bank,SAM[A].ANIM))
If iNum<65530 Then
SAM[A].AnimDelay= MilliSecs() + (PeekInt(SAM[A].Bank,SAM[A].ANIM+2)*10)
SAM[A].ANIM = SAM[A].ANIM + 6
' ' set bob frame
BOB[SAM[A].Bobnum].IMGnum = iNum
Else
If iNum=65530 Then
SAM[A].AnimDelay=0
Else
SAM[A].ANIM=PeekInt(SAM[A].Bank,SAM[A].ANIM+2)
Goto SAM_RepeatFrame
End If
End If ' iNum < 65530 (Signifies end of frames)
End If ' Anim Delay has run out <1
End If ' Delay Type 0 (100=1 second)
End If
End Function
'========================================================
' Okay, typically For movement there are two types..
' 1. Path
' Follow a predefined path, but we want this To happen at a standard pace.
' A. Set Speed
'
' 2. Constant
' IMPORTANT: Uses Global sARRAY For label calcs
Function SAM_Calc(TXT:String,iChan:Int=-1,iBob:Int)
Local CMD:String
Local A:Int,B:Int,C:Int
Local TMP:String
Local LBL:String
Local iNum:Int=0
' dim Global array
Local sArray:Int[255] ' label use
If iChan=-1 Then
iChan=SAM_add()
End If
' Set bob
SAM[iChan].BOBnum = iBOB
' first create bank
If Not SAM[iChan].Bank=Null Then
SAM[iChan].Bank=Null
End If
SAM[iChan].Bank=CreateBank(SAM[iChan].BufferSize)
SAM[iChan].BankOff=0
SAM[iChan].EXE=0
A=1
' Upper Case
TXT=Upper(TXT)
' remove all spaces
TXT=Replace(TXT," ","")
' get CMD
Repeat
' get End of cmd
B=Instr(TXT,":",A)
If B<1 Then B=Len(TXT)+1
B = B - A
' If no more Then Exit
If B<1 Then Exit
' get command
CMD=Mid(TXT,A,B)
'TMP$=TMP$ + CMD$ + "+"
Select Mid(CMD,1,1)
Case "I" ' Image
SAM_CheckBankSize(iChan,5)
iNum=Int(Mid(CMD,2))
' place into bank
PokeByte SAM[iChan].Bank,SAM[iChan].BankOff,7 '@
' 0
PokeInt SAM[iChan].Bank,SAM[iChan].BankOff+1,iNum
' 1 2 3 4
SAM[iChan].BankOff = SAM[iChan].BankOff + 5
Case "J" ' JUMP
SAM_CheckBankSize(iChan,5)
iNum=Int(Mid(CMD,2))
' place into bank
PokeByte SAM[iChan].Bank,SAM[iChan].BankOff,5 '@
' 0 (Place actaul offset instead of label pointer)
PokeInt SAM[iChan].Bank,SAM[iChan].BankOff+1,sArray[iNum]
' 1 2 3 4
SAM[iChan].BankOff = SAM[iChan].BankOff + 5
Case "L" ' LABEL
SAM_CheckBankSize(iChan,5)
' Get label Number into integer
iNum=Int(Mid(CMD,2))
' place into bank
PokeByte SAM[iChan].Bank,SAM[iChan].BankOff,1 '@
' 0
PokeInt SAM[iChan].Bank,SAM[iChan].BankOff+1,iNum
' 1 2 3 4
SAM[iChan].BankOff = SAM[iChan].BankOff + 5
' SAVE OFFSET For jumps
sArray[iNum]=SAM[iChan].BankOff
Case "M" ' MOVE
SAM_CheckBankSize(iChan,20)
' first we do a set speed command
PokeByte SAM[iChan].Bank,SAM[iChan].BankOff,2 ' @
' 0
PokeFloat SAM[iChan].Bank,SAM[iChan].BankOff+1,Float(GET_TOKEN(CMD,3))
' 1 2 3 4
PokeFloat SAM[iChan].Bank,SAM[iChan].BankOff+5,Float(GET_TOKEN(CMD,4))
' 5 6 7 8
' reset counters
PokeByte SAM[iChan].Bank,SAM[iChan].BankOff+9,3 '@
' 9
' Wait counters
PokeByte SAM[iChan].Bank,SAM[iChan].BankOff+10,4 '@
' 10
PokeFloat SAM[iChan].Bank,SAM[iChan].BankOff+11,Float(Mid(GET_TOKEN(CMD,1),2))
' 11 12 13 14
PokeFloat SAM[iChan].Bank,SAM[iChan].BankOff+15,Float(GET_TOKEN(CMD,2))
' 15 16 17 18
SAM[iChan].BankOff = SAM[iChan].BankOff + 19
' Print GET_TOKEN$(CMD$,1) +"-"
' Print GET_TOKEN$(CMD$,2) +"-"
' Print GET_TOKEN$(CMD$,3) +"-"
' Print GET_TOKEN$(CMD$,4) +"-"
' Print "Blarg"
Case "G" ' Go
SAM_CheckBankSize(iChan,9)
' GO
PokeByte SAM[iChan].Bank,SAM[iChan].BankOff,6 '@
' 0
PokeFloat SAM[iChan].Bank,SAM[iChan].BankOff+1,Float(Mid(GET_TOKEN(CMD,1),2))
' 1 2 3 4
PokeFloat SAM[iChan].Bank,SAM[iChan].BankOff+5,Float(GET_TOKEN(CMD,2))
' 5 6 7 8
SAM[iChan].BankOff = SAM[iChan].BankOff + 9
Case "A" ' Anim
Local aRepeat:Short=0
Local iFrame:Int=1
Local iBankStart:Int
SAM_CheckBankSize(iChan,7) ' byte+ one anim
' Anim Define
PokeByte SAM[iChan].Bank,SAM[iChan].BankOff,8 '@
' 0
' Int (jump ahead)
PokeInt SAM[iChan].Bank,SAM[iChan].BankOff+1,0 ' this will be repoked at end with end position
' 1 2 3 4 x
' save whether to repeat
aRepeat=Short(Mid(GET_TOKEN(CMD,1),2))
' up offset before loop
SAM[iChan].BankOff = SAM[iChan].BankOff + 5
iBankStart = SAM[iChan].BankOff
' Frame,Delay
While Len(GET_TOKEN(CMD,2*iFrame))>0
' check we have space for a short (0-65535) 2 Bytes and a long 8 bytes
SAM_CheckBankSize(iChan,6)
' frame
PokeShort SAM[iChan].Bank,SAM[iChan].BankOff,Short(GET_TOKEN(CMD,2*iFrame))
' 0 1
' delay
PokeInt SAM[iChan].Bank,SAM[iChan].BankOff+2,Int(GET_TOKEN(CMD,2*iFrame+1))
' 2 3 4 5
SAM[iChan].BankOff = SAM[iChan].BankOff + 6
iFrame = iFrame + 1
Wend
' to signify end we use either 65530 (No repeat) or 65531 (Repeat)
aRepeat=aRepeat+65530
PokeShort SAM[iChan].Bank,SAM[iChan].BankOff,Short(aRepeat)
' 0 1
' and poke int no matter what for start pos
PokeInt SAM[iChan].Bank,SAM[iChan].BankOff+2,Int(iBankStart)
' 2 3 4 5
SAM[iChan].BankOff = SAM[iChan].BankOff + 6
' reset jump spot at beginning
PokeInt SAM[iChan].Bank,iBankStart-4,SAM[iChan].BankOff ' repoking
End Select
A=A+B+1
Forever
Return iChan
' Print TMP$
' Text 10,10,TMP$
End Function
' checks For enough free space, If Not it resizes
Function SAM_CheckBankSize(iBank,iNeeded)
If iNeeded+SAM[iBank].BankOff>BankSize(SAM[iBank].Bank) Then
ResizeBank SAM[iBank].Bank,BankSize(SAM[iBank].Bank)+SAM[iBank].BufferSize
End If
End Function
Function GET_TOKEN:String(TXT:String,iNum:Int,sDelim:String=",")
Local A:Int,B:Int=0,C:Int
B=0
If TXT="" Then
Return ""
End If
If Instr(TXT,",")<1 Then
Return TXT
End If
If iNum=0 Then
Return Mid(TXT,1,Instr(TXT,sDelim)-1)
End If
C=1
For A=1 To Len(TXT)
If Mid(TXT,A,1)=sDelim Then
B=B+1
If B=iNum Then
Return Mid(TXT,C,A - C)
Else
C=A+1
End If
End If
Next
B=B+1
If B=iNum Then
Return Mid(TXT,C,A - C)
End If
Return ""
End Function |
Comments
| ||
| IMPORTANT: Requires a 320x320 image with 32x32 frames called 3232.png to work.. Can be downloaded at: http://www45.brinkster.com/QuickSetup/default.htm Please note while it may look like alot of code, the only important parts are between the implementation and end implementation remarks. The rest should be thrown into an Import statement. Also the BOB and IMAGE part could be used seperately without using SAM, but SAM requires the other two. |
| ||
| I like it ! its like Amal in Amos (Amiga) But what is with collisions? Greetings Duncki |
Code Archives Forum