QB CULT MAGAZINE
Vol. 3 Iss. 3 - December 2003

Puzzle Effect Explained

By Relsoft <vic_viperph@yahoo.com>

Do you remember the time you first installed windows? Or the countless times you reinstalled it? Have you ever wondered how to do those nice "swipe" effects? Well, fret no more as your good 'ol Genso Sanzo is here to teach you how. ;*)

An algo you thought you could never use in any GFX code you make will become your friend...

Defint a-z
Dim A(0 to 50)
For i=0 to 50
	A(i)=i
next i

For i=0 to 50
	b=(int(rnd*51))
	swap a(i), a(b)
next i

'Print it


For i=0 to 50
	print a(i)
next i

All this code does is make an array of random numbers from 0 to 50 with an all unique entry. This same algo will be what we will use to make the effect.

First thing you need is a way to have a virtual page in the screen mode we would use. Since we are using SCREEN 13, we either have to use a LIB or a nice routine made by Plasma357. It's called SETVIDEOSEG. SetVideoSeg allows us to use Virtual Pages in Screen 13 without any libs.

With the virtual page problem out of the way, we can start to make the swipe itself. The general ago for this is actually simple...

[Pseudo code]
1. Set up a texture on your hidden virtual page
2. DIM an array of coordinates for the entire screen in any stepsize you want
3. Dim an imagearray to use for GET/PUT
   (Enough size for the stepsize you want)
4. Use the unique random number algo above to rearrange the array's elements
5. Read the array(i) sequentially from top to bottom
    ie.  x1=array(i,0)     'x
	 y1=array(i,1)	   'y
	 SetVideoSEG, LAYER	'Get from Layer
	 Get(x1,y1)-(x1+stepsize,y1,stepsize),Image()
	 SetVideoSeg  &ha000    'Set Draw to screen
	 Put(x1,y1),Image()
6. Set some delay here
7. Check to see if I=MaxEmements of array
   Return to step 5 if less or equal;
   End if greater than;
[End Pseudo code]

Here's the whole effect if you want:

''Example File for doing the "puzzle" effect you see when installing
''Windows 9x
''Relsoft 2003
''SetvideoSeg by Plasma357(teh pirate)
DECLARE SUB SwipePuzzle (StepSize%)
DECLARE SUB SetVIDEOSeg (Segment%)
DEFINT A-Z

'Set up our buffer using setvideoseg
'setvideoseg allows us to use virtual pages in screen 13
REDIM SHARED Vpage(32009)            'our buffer
Vpage(6) = 2560                      'Width 320*8
Vpage(7) = 200                       'Height
DIM SHARED LAYER
LAYER = VARSEG(Vpage(0)) + 1         'Buffer Seg(Ask Plasma)

RANDOMIZE TIMER

CLS
SCREEN 13                           'VGA 320*200*256

PRINT "Press Eny Key to Generate texture"
C$ = INPUT$(1)                      'Wait for key

SetVIDEOSeg LAYER                   'Set Draw to Buffer
'Grey Scale the Palette
 FOR I = 0 TO 255
  OUT &H3C8, I
  OUT &H3C9, I \ 4
  OUT &H3C9, I \ 4
  OUT &H3C9, I \ 4
 NEXT I

FOR y = 0 TO 199                    'generate our texture
FOR x = 0 TO 319                    'use any BMP you want
    PSET (x, y), (x XOR y)          'if you have one.
NEXT x
NEXT y

StepSize = 2                        '2*2 block size to generate
                                    'each frame

SwipePuzzle (StepSize)              'do the Magic

C$ = INPUT$(1)
CLS
SCREEN 0
WIDTH 80
END

SUB SetVIDEOSeg (Segment) STATIC

DEF SEG

IF VideoAddrOff& = 0 THEN ' First time the sub is called

' We need to find the location of b$AddrC, which holds the graphics
' offset (b$OffC) and segment (b$SegC). Since b$AddrC is in the default
' segment, we can find it by setting it to a certain value, and then
' searching for that value.

SCREEN 13 ' Set b$SegC to A000 (00A0 in memory)
PSET (160, 100), 0 ' Set b$OffC to 7DA0 (not needed in the IDE)

FOR Offset& = 0 TO 32764 ' Search for b$AddrC, which is
IF PEEK(Offset&) = &HA0 THEN ' in the default segment and
IF PEEK(Offset& + 1) = &H7D THEN ' should have a value of
IF PEEK(Offset& + 2) = &H0 THEN ' A0 7D 00 A0.
IF PEEK(Offset& + 3) = &HA0 THEN
VideoAddrOff& = Offset& + 2 ' If we found it, record the
EXIT FOR ' offset of b$SegC and quit
END IF ' looking. (Oddly, changing
END IF ' the b$OffC doesn't seem to
END IF ' do anything, so this is why
END IF ' this sub only changes b$SegC)
NEXT

END IF

' Change b$SegC to the specified Segment

POKE VideoAddrOff&, Segment AND &HFF
POKE VideoAddrOff& + 1, (Segment AND &HFF00&) \ &H100


END SUB

SUB SwipePuzzle (StepSize) STATIC

STP = StepSize
Xmax& = 319             'Max dimensions of our screen
Ymax& = 199
DIM PC((Xmax& * Ymax&) \ STP, 1)    '0=x,1=y
                                    'Pc(i,0)=x
                                    'Pc(i,1)=y
DIM Image(((STP * STP) + 4) \ 2)    'our temp array to GET/PUT

'Initialize array
I = 0
FOR y = 0 TO 199 STEP STP
        FOR x = 0 TO 319 STEP STP
        PC(I, 0) = x
        PC(I, 1) = y
        I = I + 1
        NEXT x
NEXT y


'Randomize Array
'makes sure no reacuuring values
FOR II = 0 TO I
        J = INT(RND * I)
        SWAP PC(II, 0), PC(J, 0)
        SWAP PC(II, 1), PC(J, 1)
NEXT II

'do the puzzle
FOR J = 0 TO I
        SetVIDEOSeg LAYER           'get from buffer
        GET (PC(J, 0), PC(J, 1))-(PC(J, 0) + STP - 1, PC(J, 1) + STP - 1), Image(0)
        SetVIDEOSeg &HA000          'put to screen
        PUT (PC(J, 0), PC(J, 1)), Image(0)
        IF J MOD 60 = 0 THEN        'nice delay routine
            WAIT &H3DA, 8
            WAIT &H3DA, 8, 8
        END IF
NEXT J

ERASE PC                            'conserve memory
ERASE Image

END SUB

I'll try to contribute to every issue of this mag. So if you want any effect explained, send me an email at <vic_viperph@yahoo.com> and I'll try to make an article about it(assuming I know about what you want to ask.)

Relsoft 2003

<Editors Note: Relsoft has already written two articles, one on Plasmas and the other on Metaballs; both will be appearing in the next issue>