GRAFISCHE SCROLL
Als oud Amiga-gebruiker probeer ik AmigaBASIC programma's om te zetten naar PowerBASIC. Hierbij kom je regelmatig voor problemen te staan als het gaat om grafische effecten van statements die niet bestaan in PowerBASIC. In een Duits Amiga-tijdschrift uit 1988 vond ik een soort 3D boter-kaas-en-eieren spel met
een interessant grafisch effect. De PowerBASIC code bestaat uit het tekenen van de borden, dan een
wacht-loop en test op ingedrukte toets en daarna het effect. Wordt de s-toets ingedrukt dan wordt de SUB SCROLL gebruikt. Bij elke andere toets wordt code doorlopen die tot een minimum beperkt is om dit effect te bereiken en bovendien met het gele kader het gebied toont waarbinnen alles zich afspeelt. Het scherm toont vier boven elkaar geplaatste speelborden met elk 4*4 vakken. Door het perspectief zijn de borden vertekend tot ruiten. Toets-indruk aktiveert het effect waarbij de speelborden in het beeldscherm lijken te schuiven. Van elk bord blijft tenslotte alleen de rode voor- en zijkant zichtbaar. Dit effect wordt bereikt door het gebruik van het SCROLL-statement, onbekend in PowerBASIC. Hiervoor heb ik dus vervangende code moeten maken, waarvan ik zeker NIET wil beweren dat deze net zo werkt als het AmigaBASIC statement.

Nu dan een beschrijving van de 'scroll' code. Zoals de naam al aangeeft gaat het om een 'scroll' effect, en wel binnen een opgegeven rechthoek over een bepaald aantal pixels en in elke mogelijke richting. De uiteindelijke 'scroll' richting is de resultante van de horizontale en verticale richting opgegeven met de pixel-waarde  (positief of negatief). M.a.w.: SCROLL lbx,lby,rox,roy,delta_x,delta_y De rechthoek wordt beschreven door (lbx,lby)-(rox,roy), dwz door de coordinaten van linker bovenhoek en rechter onderhoek. De 'scroll' richting wordt bepaald door het aantal pixels van delta_x (horizontaal) en delta_y (verticaal); een positieve waarde geeft een richting naar resp. rechts en omlaag, een negatieve naar resp. links en omhoog.

 lbx,lby                                H
 -- +--------------------------------+
-dy |                                |
 -- |----------------------------+   |  SCROLL lbx,lby,rox,roy,+dx,-dy
    |                          h |   |
    |                            |   |
    |                            |   |
    |                            |   |
    |                            |   |
    |                            |   |
    |                            |   |
    |                            |   |
    +--------------------------------+ rox,roy
                                     |+dx|

Bovenstaande figuur kan de werking van een 'scroll' richting rechts omhoog verduidelijken; rechts omdat dx positief is, omhoog omdat dy negatief is. Het doel is om de kleine rechthoek, zo te verplaatsen dat hoekpunt h samenvalt met hoekpunt H. Hierdoor wordt aan boven- en rechterkant van de afbeelding een klein deel  afgesneden en door de verplaatsing onstaat een schijnbare beweging. De kleine rechthoek wordt in een buffer gezet mbv:  GET (lbx,lby+ABS(dy))-(rox-ABS(dx),roy),ScrollBuf De grote rechthoek wordt geschoond door deze te vullen met de 'BackGround' kleur. De kleine rechthoek wordt van de buffer op zijn nieuwe plaats  gezet mbv:  PUT (lbx+ABS(dx),lby),ScrollBuf Door deze bewerking een aantal keren te herhalen ontstaat het bedoelde effect.

Grafische bewerkingen worden sterk beinvloed door de rekenkracht van de CPU en de mogelijkheden van de grafische kaart. Dit effect oogt soepel met deze code onder DOS, op een 33 MHz VESA systeem met een IntelDX4 OverDrive Proc.(100 MHz) en een Diamond Speedstar PRO (VLB) VGA-kaart. Versnelling is natuurlijk te verwezenlijken door de code van SCROLL niet in een SUB te vatten en berekeningen zoveel mogelijk buiten de binnenste FOR-loop te houden; zie de ELSE-tak als de s-toets NIET wordt ingedrukt. Voor vertraging kan DELAY worden gebruikt.

'scroll.bas

' SCROLL zoals in AMIGA-Basic
' Auteur: Herman H. Dalman, maart 1999.
'
$OPTION CNTLBREAK
%Red=6: %Yellow=7: %White=1: %LiBlue=4: %Grey=2: %BlueGreen=3: %Green=8
%DaRed=5
%BG=%BlueGreen 'BackGround kleur
'
%lox=60: %loy=43 'Oorsprong coordinaat (linkonder) v.bovenste bord
%BordSp=50 'Afstand vh ene bord tot andere
%BordDikte=5
%BordBr=320 'Bord-breedte; richting --
%BordHo=40 'Bord-hoogte; richting |
%BordLen=200 'Bord-lengte; richting /
%VakkenBr=4: %VakkenLen=4 'Vakken per breedte en lengte
%VakLen=%BordLen/%VakkenLen: %VakBr=%BordBr/%VakkenBr
%VakHo=%BordHo/%VakkenLen
%Borden=4
%BordVakken=%VakkenLen*%VakkenBr
DEFINT a-z
'
SBufSize=4+CEIL(%BordBr/8)*4*(%BordHo+%BordDikte) 'Max.grootte ScrollBuf
DIM ScrollBuf(SBufSize) AS SHARED INTEGER
'
SCREEN 9 '8 en 12 kan ook!
PALETTE %Red,52
PALETTE %Yellow,54
PALETTE %White,63
PALETTE %LiBlue,59
PALETTE %Grey,56
PALETTE %BlueGreen,35
PALETTE %Green,34
PALETTE %DaRed,4
'
COLOR %Grey,%BG: CLS
FOR i=0 TO %Borden-1 'Teken speelborden
 j=i*%BordSp
 PSET (%lox,%loy+j),%White 'Maak bovenkant speelbord (=witte ruit)
 DRAW "C"+STR$(%White)+ _
 "M+"+STR$(%BordBr)+",0 M+"+STR$(%BordLen)+",-"+STR$(%BordHo)+ _
 " M-"+STR$(%BordBr)+",0 M-"+STR$(%BordLen)+",+"+STR$(%BordHo)
 PAINT STEP(15,-2),%Grey,%White 'vul ruit met kleur
 LINE (%lox,%loy+j)-STEP(%BordBr+2,%BordDikte),%Red,BF 'rode voorkant
 DRAW "C"+STR$(%DaRed)+ _ 'rechter zykant
 "M+"+STR$(%BordLen-2)+",-"+STR$(%BordHo)+" M+0,-"+STR$(%BordDikte) _+
 " M-"+STR$(%BordLen-2)+","+STR$(%BordHo)+" M+0,+"+STR$(%BordDikte)
 PAINT STEP(+4,-2),%DaRed 'vul zykant met kleur
 FOR y=0 TO %VakkenLen 'wit ruitpatroon op bovenkant
   LINE (%lox+y*%VakLen,%loy+j-y*%VakHo)-STEP(%BordBr,0),%White 'Hor.
   LINE (%lox+y*%VakBr,%loy+j)-STEP(%BordLen,-%BordHo),%White
 NEXT y
NEXT i
t$=""
DO:	IF INSTAT THEN t$=INKEY$
LOOP WHILE t$=""
' Effect verdwynende speelborden
delta_y=-2: delta_x=8 'Omhoog & Rechts
jb=0
IF t$="s" THEN
	FOR j=0 TO %Borden-1
 		FOR i=1 TO %BordHo/ABS(delta_y)
  		SCROLL %lox,%loy-%BordHo+jb, _
     		%lox+%BordLen+%BordBr,%loy+%BordDikte+jb,delta_x,delta_y
	  NEXT i
		INCR jb,%BordSp
	NEXT j
ELSE
	x2=%lox+%BordLen+%BordBr
	FOR j=0 TO 3
		y1=%loy-%BordHo+jb: y2=%loy+%BordDikte+jb
	 	LINE (%lox-1,y1-1)-(x2+1,y2+1),%yellow,B:DELAY 1
		FOR i=1 TO 20
			GET (%lox,y1+2)-(x2-8,y2),ScrollBuf
	  	LINE (%lox,y1)-(x2,y2),%BG,BF
  		PUT (%lox+8,y1),ScrollBuf,PSET
	  NEXT i
		INCR jb,%BordSp
	NEXT j
END IF
'
END

SUB SCROLL (BYVAL lbx,BYVAL lby,BYVAL rox,BYVAL roy,BYVAL dx,BYVAL dy)
'Verplaatst een rechthoekig scherm-deel in elke mogelyke richting.
' (lbx,lby)-(rox,roy) is de rechthoek, waarbinnen de inhoud wordt verplaatst.
' dx is aantal pixels van de verplaatsing in horizontale richting;
' naar rechts by positieve waarden, naar links by negatieve.
' dy is aantal pixels van de verplaatsing in verticale richting;
' omlaag by positieve waarden, omhoog bij negatieve.
LOCAL gx1,gx2,px,gy1,gy2,py
'%BG=BackGround kleur
'ScrollBuf=buffer voor opslaan van te verplaatsen rechthoek
	IF dy < 0 THEN gy1=ABS(dy) ELSE gy2=-dy: py=dy
  IF dx < 0 THEN gx1=ABS(dx) ELSE gx2=-dx: px=dx
	GET (lbx+gx1,lby+gy1)-(rox+gx2,roy+gy2),ScrollBuf
  LINE (lbx,lby)-(rox,roy),%BG,BF
  PUT (lbx+px,lby+py),ScrollBuf,PSET
END SUB

