GLib (compact sprite library)
Post by David Williams on May 13th, 2016, 06:22am
Code:
DEFFNGetGLIBVer:="0.07"
DEFPROCInitGLIB(RETURN v{}):`v=@vdu%:LOCALS%,Z%:DIMv{a%,w%,h%}
v.a%=FN`cds:v.w%=`v!208:v.h%=`v!212:Z%=FN`ga(4096,TRUE):S%=FN`ga(2048,TRUE)
$S%="608B5C2424C703FFFFFFFF8B7C24383B7C24280F8DC70000008B74243C3B74242C0F8DB9"
$S%+="0000008B4C24308B54243483F9007D03F7D99083FA007D03F7DA90F7D93BF90F8E970000"
$S%+="00F7DA3BF20F8E8D000000F7D9F7DAC70300000000C7430400000000C7430800000000C7"
$S%+="430C00000000894B10895314897B1889731C8BEF03E93B6C24287E0E2B6C2428296B10C7"
$S%+="4304FFFFFFFF83FF007D14297B0C017B10C7431800000000C74304FFFFFFFF8BEE03EA3B"
$S%+="6C242C7E0E2B6C242C296B14C74304FFFFFFFF83FE007D14297308017314C7431C000000"
$S%+="00C74304FFFFFFFF61C21C0060":gClip=FN`m(S%,0)
$S%="608B6C24248B4424288B7D008B4D040FAF4D08FCF3AB61C2080000":Clr=FN`m(S%,0)
$S%="608BEC81EC800000008B75248BC4FF7538FF7534FF7530FF752CFF7608FF760450E8F6FE"
$S%+="FFFFF70424FFFFFFFF0F855A0000008B552C89542434C1642434020FAF5424080354240C"
$S%+="C1E2020355288B7E04897C2438C1642438020FAF7C241C037C2418C1E702033E8B5C2410"
$S%+="33C98B048A85C0740389048F83C1013BCB7CEF03542434037C2438FF4C241475DF81C480"
$S%+="00000061C2180060":Plot=FN`m(S%,33)
$S%="608BEC81EC800000008B75248BC4FF7538FF7534FF7530FF752CFF7608FF760450E85FFE"
$S%+="FFFFF70424FFFFFFFF0F85570000008B552C89542434C1642434020FAF5424080354240C"
$S%+="C1E2020355288B7E04897C2438C1642438020FAF7C241C037C2418C1E702033E8BF28B5C"
$S%+="24108B4424348B5424388B6C241456578BCBFCF3A55F5E03F003FA4D7FF081C480000000"
$S%+="61C218008B":BPlot=FN`m(S%,33)
$S%="608BEC83EC409BDBE39BD93C24668B04246625FFF3660D000C66890424D92C248B553483"
$S%+="FA000F8E480100008B7D3883FF000F8E3C0100006800000100DB0424DB452CDA7534D8C9"
$S%+="DB5C2404DB4530DA7538DEC9DB5C240883C4048B45248B5D3CF7DA3BDA0F8E090100003B"
$S%+="58040F8D000100008B4D40F7DF3BCF0F8EF30000003B48080F8DEA000000F7DAF7DF895C"
$S%+="2408894C240C89542410897C2414C744241800000000C744241C000000008B7004C1E602"
$S%+="8974242083FB007D10C744240800000000015C2410295C241C8B50042B55343BDA7E0B8B"
$S%+="70042B7424088974241083F9007D10C744240C00000000014C2414294C24188B50082B55"
$S%+="383BCA7E0B8B70082B74240C897424148B74240C0FAF700403742408C1E60203308B5D28"
$S%+="33FF8BCF034C24180FAF4C2404C1E9100FAF4D2CC1E102575055538B4424108B6C242C03"
$S%+="D98B7C24204F8BD703D50FAFD0C1EA108B1493F7C2FFFFFF0074038914BE4F7DE55B5D58"
$S%+="5F03742420473B7C24147CAE83C44061C220008B":PlotScaled=FN`m(S%,0)
$S%="608BEC81EC800000008B75248BC4FF7538FF7534FF7530FF752CFF7608FF760450E85FFE"
$S%+="FFFFF70424FFFFFFFF0F85610000008B552C89542434C1642434020FAF5424080354240C"
$S%+="C1E2020355288B7E04897C2438C1642438020FAF7C241C037C2418C1E702033E8B5C2410"
$S%+="33C98B048A85C0740AD12C8F81248F7F7F7F7F83C1013BCB7CE803542434037C2438FF4C"
$S%+="241475D881C48000000061C2180060":PlotShadow=FN`m(S%,33)
$S%="608BEC81EC800000008B75248BC4FF7538FF7534FF7530FF752CFF7608FF760450E8C1FD"
$S%+="FFFFF70424FFFFFFFF0F856E0000008B552C89542434C1642434020FAF5424080354240C"
$S%+="C1E2020355288B7E04897C2438C1642438020FAF7C241C037C2418C1E702033E8B5C2410"
$S%+="33C98B048A85C074178B348F25FEFEFE0081E6FEFEFE00D1E8D1EE03C689048F83C1013B"
$S%+="CB7CDB03542434037C2438FF4C241475CB81C48000000061C2180060"
PlotAvg=FN`m(S%,33)
$S%="8B7424048B4C24088B5E048B54240C3BCB73133B5608730E8B060FAFD38B7C241003D189"
$S%+="3C90C2100000":PlotPixel=FN`m(S%,0)
$S%="8B6C24048B45008B5D048B4D088B5424088B7C240C8B742410E81B00000083C201E81300"
$S%+="000083C701E80B00000083EA01E803000000C21000603BD3730C3BF973080FAFFB03FA89"
$S%+="34B861C300":PlotPoint=FN`m(S%,0)
$S%="33C08B6C24048B7C24083B7D0473178B74240C3B7508730E0FAF7504037424088B7D008B"
$S%+="04B7C20C0000":ReadPixel=FN`m(S%,0)
$S%="8B6C24048B7C24083B7D0473418B74240C3B750873380FAF7504037424088B7D0033C00F"
$S%+="B644B7028B5C241089030FB644B7018B5C241489030FB604B78B5C241889030FB644B703"
$S%+="8B5C241C8903C21C0000":ReadRGBA=FN`m(S%,0)
$S%="608BEC81EC800000008B75248BC4FF7538FF7534FF7530FF752CFF7608FF760450E85FFE"
$S%+="FFFFF70424FFFFFFFF0F85670000008B552C89542434C1642434020FAF5424080354240C"
$S%+="C1E2020355288B7E04897C2438C1642438020FAF7C241C037C2418C1E702033E8B5C2410"
$S%+="8B753CC1E61833C98B048A85C0740A25FFFFFF000BC689048F83C1013BCB7CE803542434"
$S%+="037C2438FF4C241475D881C48000000061C21C0060":PlotSetAlpha=FN`m(S%,33)
$S%="608BEC81EC800000008B75248BC4FF7538FF7534FF7530FF752CFF7608FF760450E8BBFD"
$S%+="FFFFF70424FFFFFFFF0F85720000008B552C89542434C1642434020FAF5424080354240C"
$S%+="C1E2020355288B7E04897C2438C1642438020FAF7C241C037C2418C1E702033E8B5C2410"
$S%+="518B4D3C83C118BE01000000D3E65933C98B048A85C0740C0BC681248F000000FF09048F"
$S%+="83C1013BCB7CE603542434037C2438FF4C241475D681C48000000061C21C0060"
PlotSetAlphaBit=FN`m(S%,33)
$S%="608BEC81EC800000008B75248BC4FF7538FF7534FF7530FF752CFF7608FF760450E80CFD"
$S%+="FFFFF70424FFFFFFFF0F855F0000008B552C89542434C1642434020FAF5424080354240C"
$S%+="C1E2020355288B7E04897C2438C1642438020FAF7C241C037C2418C1E702033E8B5C2410"
$S%+="33F633C98B048A85C074060B348F89048F83C1013BCB7CEC03542434037C2438FF4C2414"
$S%+="75DC81C480000000C1EE188BC68944241C61C2180060"
PlotGetAlphaBits=FN`m(S%,33)
$S%="608BEC81EC800000008B75248BC4FF7538FF7534FF7530FF752CFF7608FF760450E85FFE"
$S%+="FFFFF70424FFFFFFFF0F85690000008B552C89542434C1642434020FAF5424080354240C"
$S%+="C1E2020355288B7E04897C2438C1642438020FAF7C241C037C2418C1E702033E8B5C2410"
$S%+="33C98B048AA9000000FF740F3D000000FF722725FFFFFF0089048F83C1013BCB7CE00354"
$S%+="2434037C2438FF4C241475D081C48000000061C218008BF0C1EE180FB66C8A020FB6448F"
$S%+="022BE80FAFEEC1FD0803C588448F020FB66C8A010FB6448F012BE80FAFEEC1FD0803C588"
$S%+="448F010FB62C8A0FB6048F2BE80FAFEEC1FD0803C588048FC6448F030083C1013BCB0F8C"
$S%+="6EFFFFFF03542434037C2438FF4C24140F855AFFFFFF81C48000000061C2180060"
PlotAlphaBlend=FN`m(S%,33)
Z%=FN`ga(4096,TRUE)
ENDPROC
DEFPROCDisplay(W%):PRIVATEI%:IFI%=0 I%=FN`s("InvalidateRect")
SYSI%,@hwnd%,0,0:IFW%PROC`w
*REFRESH
ENDPROC
DEFFNLoadImg(p$,A%):LOCALK%,X%,Y%,W%,H%,M%:X%=0:Y%=0:K%=FN`l(p$,X%,Y%,0)
IFK%=0ERROR100,"LoadImg failed"
A%=FN`g(K%,A%,W%,H%):SYS"DeleteObject",K%:SYS"RtlMoveMemory",A%,A%+54,4*W%*H%
=A%
DEFPROCCleanup:PROC`n(3,0):ENDPROC
DEFFN`m(S%,O%):LOCALA%,I%:A%=FN`ga(LEN$S%,TRUE):FORI%=0TOLEN$S%DIV2-1
A%?I%=EVAL("&"+MID$($S%,2*I%+1,2)):NEXT
IFO%>0PROC`d(A%,O%,gClip)
=A%
DEFFN`cds:LOCALA%,B%,H%,O%:DIMB%19:!B%=44:B%!4=`v!208:B%!8=`v!212:B%!12=&200001
SYS"CreateDIBSection",@memhdc%,B%,0,^A%,0,0TOH%:IFH%=0ERROR100,"`cds failed"
SYS"SelectObject",@memhdc%,H%TOO%:SYS"DeleteObject",O%:CLS:=A%
DEFPROC`w:PRIVATEB%,G%,I%,S%,W%:LOCALL%,P%,T%:IFS%=0 S%=FN`s("Sleep")
IFB%=0SYS"timeBeginPeriod",1:B%=1
IFI%=0PROC`7(I%,G%)
L%=0:P%=^T%:REPEAT:L%=T%:SYSS%,1:SYSG%,I%,P%:UNTILT%<L%:ENDPROC
DEFPROC`7(RETURN I%,RETURN G%):LOCALD%,E%,J%,K%,L%
SYS"LoadLibrary","DDRAW.DLL"TOD%:IFD%=0 ERROR100,"`7 failed"
SYS"GetProcAddress",D%,"DirectDrawCreateEx"TOE%:DIMJ%19,L%95:J%=J%+3AND-4
L%=L%+3AND-4:!J%=&15E65EC0:J%!4=&11D23B9C:J%!8=&60002FB9:J%!12=&5BEA9797
SYSE%,0,^K%,J%,0:L%=!K%:I%=K%:G%=L%!64
ENDPROC
DEFFN`l(f$,RETURN X%,RETURN Y%,R%)
LOCALi{},b{},x%,y%,H%,C%,P%,O%,Q%,T%
DIMi{a%,b%,c%,d%},T% LOCAL 513
i.a%=&7BF80980:i.b%=&101ABF32:i.c%=&AA00BB8B:i.d%=&AB0C3000
SYS"MultiByteToWideChar",0,0,f$,-1,T%,256
SYS"LoadLibrary","OLEAUT32.DLL"TOO%
SYS"GetProcAddress",O%,"OleLoadPicturePath"TOQ%:IFQ%=0 THEN=0
SYSQ%,T%,0,0,0,i{},^P%:IFP%=0 THEN=0
SYS!(!P%+12),P%,^H%:IFH%=0 THEN=0
DIMb{T%,W%,H%,B%,P{l&,h&},p{l&,h&},s%}:SYS"GetObject",H%,DIM(b{}),b{}
x%=b.W%:y%=b.H%:IFX%=0 X%=x%
IFY%=0 Y%=y%
IFR%THEN
IFX%/Y%>x%/y% X%=Y%*x%/y%ELSEY%=X%*y%/x%
ENDIF
SYS"CopyImage",H%,0,X%,Y%,0TOC%:SYS"DeleteObject",H%:SYS!(!P%+8),P%:=C%
DEFFN`g(h%,RETURN D%,RETURN W%,RETURN H%):LOCALB%,S%,R%:DIMB%LOCAL26
B%=B%+3AND-4:SYS"GetObject",h%,24,B%TOR%
IFR%=0 ERROR100,"GetObject failed"
W%=B%!4:H%=B%!8:S%=54+4*W%*H%:IFD%=0DIMD% S%+7:D%=D%+7AND-8
IFD%=-1D%=FN`ga(54+4*W%*H%,TRUE)
$$D%=STRING$(53,CHR$0)
!D%=19778:D%!2=S%:D%!10=54:D%!14=40:D%!18=W%:D%!22=H%:D%!26=&200001
SYS"GetDIBits",@memhdc%,h%,0,H%,D%+54,D%+14,0TOR%
IFR%<>H% ERROR100,"GetDIBits failed"
=D%
DEFPROC`n(O%,V%):LOCALi,m:m=1000:PRIVATED%
IFD%=0THEN
D%=FN`ga(4*m,FALSE):IFD%=0 ERROR100,"GlobalAlloc failed"
FORi=0TOm-1:D%!(4*i)=0:NEXT
ENDIF
CASEO%OF
WHEN1:i=0:WHILED%!(4*i)<>0ANDi<m:i+=1:ENDWHILE
IFi>=m ERROR100,"Obj list full"
D%!(4*i)=V%
WHEN2:i=0:WHILED%!(4*i)<>V%ANDi<m:i+=1:ENDWHILE
IFi<m SYS"GlobalFree",V%:D%!(4*i)=0
WHEN3:FORi=0TOm-1
IFD%!(4*i)<>0SYS"GlobalFree",D%!(4*i):D%!(4*i)=0
NEXT:SYS"GlobalFree",D%:D%=0
ENDCASE
ENDPROC
DEFFN`s(f$):LOCALP%:DIMP%LOCAL5:[OPT 0:call f$:]:=P%!-4+P%
DEFPROC`d(B%,O%,C%):LOCALD%,P%:D%=C%-B%-O%-5:P%=B%+O%+1:!P%=D%:ENDPROC
DEFFN`ga(S%,F%):LOCALA%:SYS"GlobalAlloc",64,S%TOA%:IFF%PROC`n(1,A%)
=A%
DEF FNGrab(v{},A%,X%,Y%,W%,H%)
LOCALB%,D%,L%,I%,O%
IFA%=-1A%=FN`ga(4*W%*H%,TRUE)
D%=A%
FOR L%=Y% TO Y%+H%-1
B%=v.a%+4*(L%*v.w%+X%):FORI%=B%TOB%+4*W%-1STEP4:!D%=!I%:D%+=4:NEXT
NEXT
=A%
DEFPROCFWS:LOCALW%:SYS"GetWindowLong",@hwnd%,-16TOW%
SYS "SetWindowLong",@hwnd%,-16,W%AND&FFFAFFFF
ENDPROC
Re: GLib (compact sprite library)
Post by David Williams on May 13th, 2016, 06:26am
This program ("Wavey Starfish") demonstrates GLib's PlotScaled routine. Copy and paste the following code into the BB4W IDE, then tack-on the GLib library from the first post in this thread (or INSTALL it, if you prefer).
Code:
REM "Wavey Starfish"
REM Requires GLIB 0.06 (or later)
MODE 8 : OFF
ON ERROR OSCLI"REFRESH ON":ON:CLS:REPORT:PRINT " at line ";ERL:END
REM If GLIB is an external library file (GLIB.BBC) then
REM include the following line:
REM INSTALL @lib$ + "GLIB"
PROCInitGLIB( g{} )
ON CLOSE PROC`n(3,0):QUIT
sprSz% = 64
nSpokes% = 10
maxSprSz% = sprSz%
minSprSz% = 4
maxR% = 300
minR% = 50
cx% = g.w% / 2
cy% = g.h% / 2
REM Draw a ball on the screen:
GCOL 1
FOR R% = sprSz%/2-1 TO 1 STEP -1
i = 1-(R%/(sprSz%/2))^4
COLOUR 1, 255*i, 100*i, 255*i
CIRCLE FILL sprSz%, sprSz%, 2*R%
NEXT R%
REM Copy the ball into a sprite/bitmap:
ballSpr% = FNGrab(g{}, -1, 0, 0, sprSz%, sprSz%)
TIME = 0
*REFRESH OFF
REPEAT
SYS Clr, g{}, &204060 : REM dark blue background
FOR R% = minR% TO maxR% STEP 25
f = (R%-minR%)/(maxR%-minR%)
sz% = minSprSz% + maxSprSz%*(1-f)
angleInc = 100*f*SIN(TIME/150)
FOR I% = 0 TO nSpokes%-1
i = 100*SIN(TIME/250)
angle = I%*(360/nSpokes%) + angleInc + i
X% = cx% + R%*SINRAD(angle)
Y% = cy% + R%*COSRAD(angle)
SYS PlotScaled, g{}, ballSpr%, sprSz%, sprSz%, sz%, sz%, \
\ X%-sz%/2, Y%-sz%/2
NEXT I%
NEXT R%
PROCDisplay(TRUE)
UNTIL FALSE
PROC`n(3,0) : REM free memory
END
Re: GLib (compact sprite library)
Post by DDRM on May 13th, 2016, 11:30am
Hi David,
Ooh, looks like that (particularly the library bit) will repay a bit of study! Are you in the market for providing a bit of documentation for the library functions?
Are your sprites 32 bit bitmaps, with black set to transparent?
Best wishes,
D
Re: GLib (compact sprite library)
Post by David Williams on May 13th, 2016, 11:58am
on May 13th, 2016, 11:30am, DDRM wrote:Ooh, looks like that (particularly the library bit) will repay a bit of study! Are you in the market for providing a bit of documentation for the library functions? |
|
If anyone is wondering why the GLib code is so cryptic (certainly cryptic enough to cause me problems!), it's because it was originally designed so that it could be employed within the limitations of the Trial version of 'BBC BASIC for Windows' (I can't, off-hand, remember what the memory limitations were). This meant making it as compact as possible, and necessitated the use of short or single-character variable names and functions, and pre-assembled machine code.
I will shortly put up some documentation for it, including some commented example programs.
There's some routines I'd like to add (actually, there's quite a few routines I'd like to add but they would bloat the library, and I won't be able to fit the whole thing into one post!). I like being able to fit it all in one post. (Last time I checked, I only had 34 free characters available! (some more trimming to do, then...))
Quote:Are your sprites 32 bit bitmaps, with black set to transparent? |
|
Yes, 32bpp (ARGB) bitmaps, although any bitmap header data is ignored (which is why you must specify the height and width of the sprite you wish to plot, and the start address of the sprite's pixel data).
Black pixels are assumed to be transparent by some of the plotting routines. I will document which plotters ignore black pixels, and which ones don't.
David.
--
Re: GLib (compact sprite library)
Post by David Williams on May 15th, 2016, 11:07am
The program listed below will have to function as the rather perfunctory GLib documentation for the time being. It was written in a hurry, sorry. There ought to be enough information in there to put some sprites/bitmaps on the screen (which is GLib's purpose), but I'm willing to respond to any technical questions anyone may have regarding GLib.
Code:
REM GLib examples
REM Glossary
REM ========
REM
REM bmAddr ... bitmap address (memory address of ARGB32 bitmap image)
REM bmW ... bitmap width (in pixels)
REM bmH ... bitmap height (in pixels)
REM ARGB32 ... 32-bit pixel colour format used by GLib.
REM Each pixel in an ARGB32 bitmap image takes up 4 bytes (32 bits per pixel).
REM A = 8-bit alpha value (only used by PlotAlphaBlend); range 0 to 255
REM R = 8-bit red component (range 0 to 255)
REM G = 8-bit green component (range 0 to 255)
REM B = 8-bit blue component (range 0 to 255)
REM In hexadecimal, ARGB32 has the form &AARRGGBB
REM Examples:
REM White &00FFFFFF
REM Orange &00FF8000
REM Green &0000FF00
REM Blue with 50% alpha &7F0000FF
REM If GLib is an external file (i.e. in BB4W's standard LIB folder),
REM then include the following line:
INSTALL @lib$ + "GLIB"
REM If not, then tack the GLib library on to the end of this program.
REM It's good practice to call PROCCleanup upon closing the program,
REM or if an error is trapped:
ON CLOSE PROCCleanup : QUIT
ON ERROR PROCCleanup : CLS : REPORT : PRINT " at line "; ERL : END
REM Fix program window size (a 'built-in' GLib subroutine):
PROCFWS
REM Set up a 640x512 program window:
MODE 8 : OFF
WinW% = @vdu%!208
WinH% = @vdu%!212
REM Initialise GLib (GLib subroutine):
PROCInitGLIB( g{} )
REM The structure returned by PROCInitGLIB has three members:
REM
REM a% ... the 'screen' or 'frame buffer' address (currently a DIB section)
REM w% ... screen/frame buffer width
REM h% ... screen/frame buffer height
REM Load 512x512 JPEG image from BB4W's 'GRAPHICS' folder:
path$ = LEFT$( @lib$, LEN@lib$-4 ) + "EXAMPLES\GRAPHICS\"
file$ = path$ + "WORLD.JPG"
worldImg% = FNLoadImg(file$, -1)
REM FNLoadImg automatically loads the JPEG image, and converts it to
REM the required raw ARGB32 pixel format required by GLib.
REM The parameter specified as -1 in this case tells FNLoadImg to allocate
REM the memory required to hold the ARGB32 bitmap. Otherwise, you must
REM specify the address at which the ARGB32 bitmap will be placed, having
REM reserved the memory block (of sufficient size!) yourself.
REM Create a sprite (a colourful spiral) by drawing it on the screen
REM using BB4W's native graphics commands, then 'grab' it as a sprite/bitmap:
DIM spiral{ a%, w%, h% }
r = 0
FOR angle = 0 TO 1000
GCOL RND(15)
x = WinW% + r*SINRAD(angle)
y = WinH% + r*COSRAD(angle)
CIRCLE FILL x, y, 8
r += 0.1
NEXT angle
PROCgetMinMaxRect( g{}, minX%, minY%, maxX%, maxY% )
spiral.w% = maxX% - minX%
spiral.h% = maxY% - minY%
spiral.a% = FNGrab( g{}, -1, minX%, minY%, spiral.w%, spiral.h% )
REM Create another sprite, but this time one with an alpha mask.
REM When plotted with PlotAlphaBlend, this sprite will appear as a fuzzy red blob.
CLS
DIM ball{ a%, w%, h% }
GCOL 1 : CIRCLE FILL 200, 200, 80
PROCgetMinMaxRect( g{}, minX%, minY%, maxX%, maxY% )
ball.w% = maxX% - minX%
ball.h% = maxY% - minY%
ball.a% = FNGrab( g{}, -1, minX%, minY%, ball.w%, ball.h% )
m = SQR((ball.w%/2)^2 + (ball.h%/2)^2)
FOR Y% = 0 TO ball.h%-1
FOR X% = 0 TO ball.w%-1
d = SQR((X%-ball.w%/2)^2 + (Y%-ball.h%/2)^2)
ball.a%?(4*(Y%*ball.w%+X%) + 3) = 255*(1 - d/m)^2
NEXT
NEXT
REM Now actually draw stuff...
REM Clear the program window (fill it with dark blue).
REM Clr takes parameters g{}, ARGB32
SYS Clr, g{}, &000040
REM Plot the 512x512 'world' image at coordinates x=30, y=20.
REM BPlot takes parameters g{}, bmAddr, bmW, bmH, x, y
REM BPlot is well-suited to drawing background images. It's very fast.
REM All pixels (including black ones) in the bitmap image are plotted.
SYS BPlot, g{}, worldImg%, 512, 512, 30, 20
REM Use PlotPixel to draw 1000 randomly coloured pixels in the lower half of the window.
REM PlotPixel takes parameters g{}, x, y, ARGB32
FOR I% = 1 TO 1000
SYS PlotPixel, g{}, RND(WinW%), RND(WinH%/2), RND(&FFFFFF)
NEXT I%
REM Draw 1000 randomly coloured points in the upper half of the window.
REM A point is a 2x2 square block of pixels.
REM PlotPoint takes parameters g{}, x, y, ARGB32
FOR I% = 1 TO 1000
SYS PlotPoint, g{}, RND(WinW%), WinH%/2+RND(WinH%/2), RND(&FFFFFF)
NEXT I%
REM Draw 10 randomly positioned spiral sprites (the one we created earlier).
REM Plot takes the same parameters as BPlot - g{}, bmAddr, bmW, bmH, x, y
REM Black pixels are not plotted (i.e. they are assumed to be transparent)
FOR I% = 1 TO 10
SYS Plot, g{}, spiral.a%, spiral.w%, spiral.h%, RND(WinW%), RND(WinH%)
NEXT I%
REM Draw 10 randomly positioned, colour-averaged spiral sprites using PlotAvg.
REM PlotAvg takes parameters g{}, bmAddr, bmW, bmH, x, y
REM Black pixels are not plotted (i.e. they are considered to be transparent)
FOR I% = 1 TO 10
SYS PlotAvg, g{}, spiral.a%, spiral.w%, spiral.h%, RND(WinW%), RND(WinH%)
NEXT I%
REM Draw the spiral sprite stretched horizontally and vertically to varying extents.
REM PlotScaled takes parameters g{}, bmAddr, bmW, bmH, newW, newH, x, y
REM Black pixels are not plotted.
FOR I% = 1 TO 10
newW% = RND(300)
newH% = RND(300)
SYS PlotScaled, g{}, spiral.a%, spiral.w%, spiral.h%, newW%, newH%, RND(WinW%), RND(WinH%)
NEXT I%
REM Draw alpha-blended sprites.
REM PlotAlphaBlend takes parameters g{}, bmAddr, bmW, bmH, x, y
REM Black pixels in the sprite are processed by this routine.
FOR I% = 1 TO 10
SYS PlotAlphaBlend, g{}, ball.a%, ball.w%, ball.h%, RND(WinW%), RND(WinH%)
NEXT I%
REM Draw translucent shadows (actually 'silhouettes' of the spiral sprite).
REM PlotShadow takes parameters g{}, bmAddr, bmW, bmH, x, y
REM Black pixels are not plotted.
FOR I% = 1 TO 20
SYS PlotShadow, g{}, spiral.a%, spiral.w%, spiral.h%, RND(WinW%), RND(WinH%)
NEXT I%
REM Update the program window:
PROCDisplay(FALSE)
PROCCleanup
END
DEF PROCgetMinMaxRect(v{}, RETURN minX%, RETURN minY%, RETURN maxX%, RETURN maxY%)
LOCAL A%, B%, H%, W%, X%, Y%
minX% = 100000000
minY% = 100000000
maxX% = -100000000
maxY% = -100000000
A% = v.a%
W% = v.w%
H% = v.h%
FOR Y% = 0 TO H%-1
B% = A% + 4*Y%*W%
FOR X% = 0 TO W%-1
IF B%!(4*X%) THEN
IF X% < minX% THEN
minX% = X%
ENDIF
IF X% > maxX% THEN
maxX% = X%
ENDIF
IF Y% < minY% THEN
minY% = Y%
ENDIF
IF Y% > maxY% THEN
maxY% = Y%
ENDIF
ENDIF
NEXT
NEXT
ENDPROC
Re: GLib (compact sprite library)
Post by David Williams on May 15th, 2016, 12:40pm
If GLib isn't installed in your BB4W LIB folder, then either do that, or append the library (from the first post in this thread) to the end of this program:
Code:
REM "Ring of Balls"
REM Requires GLIB 0.07 (or later)
REM If GLib is in BB4W's LIB folder, then include the following line:
INSTALL @lib$ + "GLIB"
REM Otherwise, append the GLib library to the end of this program.
PROCFWS : REM Fix Window Size
MODE 8 : REM 640x512
OFF
nBalls% = 16
REM Get window width and height:
winW% = @vdu%!208
winH% = @vdu%!212
PROCInitGLIB( g{} )
ON ERROR OSCLI"REFRESH ON":ON:PROCCleanup:REPORT:PRINT ERL:END
ON CLOSE PROCCleanup:QUIT
REM Create a 32bpp bitmap of dimensions winW% by 10*winH%:
bgW% = winW%
bgH% = 10 * winH%
PRINT "Generating colourful ";bgW%;"x";bgH%;" bitmap..."
bg% = FN`ga( 4*bgW%*bgH%, TRUE )
I% = bg%
k = 3*PI/(bgW%-1)
FOR Y% = 0 TO bgH%-1
yf = 16*PI*Y%/(bgH%-1)
sin_yf = SIN(yf)
sin_yf_2 = SIN(yf/2)
FOR X% = 0 TO bgW%-1
xf = k*X%
blue& = 128 + 64*(sin_yf+COS(xf))
red& = 128 + 64*(sin_yf_2+SIN(xf+yf))
!I% = blue& + &10000*red&
I% += 4
NEXT
NEXT
REM Create a green ball sprite:
DIM ball{a%, w%, h%}
CLS
GCOL 15
FOR R% = 64 TO 1 STEP -1
r = 1 - R%/64
COLOUR 15, r*10, r*255, r*100
CIRCLE FILL winW%, winH%, R%
NEXT R%
PROCgetMinMaxRect( g{}, minX%, minY%, maxX%, maxY% )
ball.w% = maxX% - minX% + 1
ball.h% = maxY% - minY% + 1
ball.a% = FNGrab( g{}, -1, minX%, minY%, ball.w%, ball.h% )
h% = bgH% - winH%
TIME = 0
*REFRESH OFF
REPEAT
t = TIME / 120
REM Draw the moving background image:
y% = -0.5*(h% + h%*SIN(TIME/350))
SYS BPlot, g{}, bg%, bgW%, bgH%, 0, y%
REM Draw the ring of balls
REM Draw ball shadows:
FOR I% = 0 TO nBalls%-1
angle = 2*PI*I%/(nBalls%-1) + t
x% = winW%/2 + 200*SIN(angle) - ball.w%/2
y% = winH%/2 + 200*COS(angle) - ball.h%/2
SYS PlotShadow, g{}, ball.a%, ball.w%, ball.h%, x%-24, y%-32
NEXT I%
REM Draw the balls proper:
FOR I% = 0 TO nBalls%-1
angle = 2*PI*I%/(nBalls%-1) + t
x% = winW%/2 + 200*SIN(angle) - ball.w%/2
y% = winH%/2 + 200*COS(angle) - ball.h%/2
SYS Plot, g{}, ball.a%, ball.w%, ball.h%, x%, y%
NEXT I%
REM Update the program window
REM (with VSync synchronisation):
PROCDisplay( TRUE )
UNTIL FALSE
END
:
:
:
:
DEF PROCgetMinMaxRect(v{}, RETURN minX%, RETURN minY%, RETURN maxX%, RETURN maxY%)
LOCAL A%, B%, H%, W%, X%, Y%
minX% = 100000000
minY% = 100000000
maxX% = -100000000
maxY% = -100000000
A% = v.a%
W% = v.w%
H% = v.h%
FOR Y% = 0 TO H%-1
B% = A% + 4*Y%*W%
FOR X% = 0 TO W%-1
IF B%!(4*X%) THEN
IF X% < minX% THEN
minX% = X%
ENDIF
IF X% > maxX% THEN
maxX% = X%
ENDIF
IF Y% < minY% THEN
minY% = Y%
ENDIF
IF Y% > maxY% THEN
maxY% = Y%
ENDIF
ENDIF
NEXT
NEXT
ENDPROC
Re: GLib (compact sprite library)
Post by David Williams on May 18th, 2016, 09:49am
Code:
REM Thick antialiased lines using GDI+.
REM Here, GLib is used in conjunction with GDI+.
REM Fairly consistent 60 fps for 60 lines on my laptop.
REM
REM This program calls GdipDrawLine directly, and performs
REM 'inline' conversion to 4-byte floats in order to reduce
REM overheads.
nLines% = 30
*ESC OFF
REM If you don't yet have GLib installed in the BB4W's LIB folder,
REM either append GLib to the end of this program, or install it
REM in the LIB folder.
INSTALL @lib$ + "GLIB"
PROCInitGLIB( g{} )
INSTALL @lib$ + "GDIPLIB"
PROCFWS : REM Fix Window Size
MODE 8 : OFF
ON ERROR PROCCleanup : REPORT : PRINT ERL : END
ON CLOSE PROCCleanup : QUIT
SetBoundsRect = FN`s("SetBoundsRect")
GetBoundsRect = FN`s("GetBoundsRect")
OffsetRect = FN`s("OffsetRect")
InvalidateRect = FN`s("InvalidateRect")
GetTickCount = FN`s("GetTickCount")
REM The following bit of assembler code
REM is the work of RTR:
DIM f4% 10
P% = f4%
[OPT 2
mov esi,[ebp+2]:mov edi,[ebp+7]
fld qword [esi]:fstp dword [edi]
ret
]
f32# = 0.0 : pf32% = ^f32# + 4 : !pf32% = &3FF00000
PROC_gdipinit
ON ERROR PROCCleanup : PROC_gdipexit : REPORT : PRINT ERL : END
ON CLOSE PROCCleanup : PROC_gdipexit : QUIT
DIM rc{l%,t%,r%,b%}
yellowPen% = FN_gdipcreatepen(&FFFFFF00, 2+&200, 2)
greenPen% = FN_gdipcreatepen(&FF00FF00, 2+&200, 4)
bluePen% = FN_gdipcreatepen(&FF0080FF, 2+&200, 8)
orangePen% = FN_gdipcreatepen(&FFFF8000, 2+&200, 6)
gdipGfxPtr% = FN_gdipg
SYS SetBoundsRect, @memhdc%, 0, 5
SYS GetBoundsRect, @memhdc%, rc{}, 0
DIM line{( nLines%-1 ) x1, y1, x2, y2, dx1, dx2, dy1, dy2, pen%}
ScrW% = @vdu%!208
ScrH% = @vdu%!212
FOR I% = 0 TO nLines%-1
line{(I%)}.x1 = RND( @vdu%!208 )
line{(I%)}.y1 = RND( @vdu%!212 )
line{(I%)}.x2 = RND( @vdu%!208 )
line{(I%)}.y2 = RND( @vdu%!212 )
line{(I%)}.dx1 = 2*RND(1)*SGN(RND(1)-0.5)
line{(I%)}.dx2 = 2*RND(1)*SGN(RND(1)-0.5)
line{(I%)}.dy1 = 2*RND(1)*SGN(RND(1)-0.5)
line{(I%)}.dy2 = 2*RND(1)*SGN(RND(1)-0.5)
CASE RND(4) OF
WHEN 1 : line{(I%)}.pen% = yellowPen%
WHEN 2 : line{(I%)}.pen% = greenPen%
WHEN 3 : line{(I%)}.pen% = bluePen%
WHEN 4 : line{(I%)}.pen% = orangePen%
ENDCASE
NEXT I%
REM Line endpoints variables:
x1% = 0 : y1% = 0 : x2% = 0 : y2% = 0
frame% = 0
frameRate% = 0
*REFRESH OFF
SYS GetTickCount TO time0%
REPEAT
SYS Clr, g{}, 0
FOR I% = 0 TO nLines%-1
f64# = line{(I%)}.x1 : f64# *= f32# : CALL f4%,f64#,x1%
f64# = line{(I%)}.y1 : f64# *= f32# : CALL f4%,f64#,y1%
f64# = line{(I%)}.x2 : f64# *= f32# : CALL f4%,f64#,x2%
f64# = line{(I%)}.y2 : f64# *= f32# : CALL f4%,f64#,y2%
SYS `GdipDrawLine`, gdipGfxPtr%, line{(I%)}.pen%, x1%, y1%, x2%, y2%, @memhdc%
line{(I%)}.x1 += line{(I%)}.dx1
line{(I%)}.y1 += line{(I%)}.dy1
line{(I%)}.x2 += line{(I%)}.dx2
line{(I%)}.y2 += line{(I%)}.dy2
IF line{(I%)}.x1 < 0 OR line{(I%)}.x1 >= ScrW% line{(I%)}.dx1 *= -1
IF line{(I%)}.x2 < 0 OR line{(I%)}.x2 >= ScrW% line{(I%)}.dx2 *= -1
IF line{(I%)}.y1 < 0 OR line{(I%)}.y1 >= ScrH% line{(I%)}.dy1 *= -1
IF line{(I%)}.y2 < 0 OR line{(I%)}.y2 >= ScrH% line{(I%)}.dy2 *= -1
NEXT I%
PRINT TAB(2,1);frameRate%;" fps"
PROCDisplay(TRUE)
frame% += 1
SYS GetTickCount TO time1%
IF time1%-time0% >= 1000 THEN
frameRate% = frame%
frame% = 0
SYS GetTickCount TO time0%
ENDIF
UNTIL FALSE
END
Re: GLib (compact sprite library)
Post by David Williams on May 22nd, 2016, 08:59am
An unfinished/buggy "Asteroids"-style game:
http://pastebin.com/86rn3bnU
(Scroll down to the bottom of the Pastebin window to the section titled "RAW Paste Data", then click somewhere inside that box and press CTRL+A to select all the code, followed by CTRL+C to copy it into the Windows clipboard, then within the BB4W IDE press CTRL+V to paste in the program listing. Or do it your own way!)
This was never meant to be a game (and really isn't much of a game at all). It was supposed to be a GLib/GDI+ demo with a couple of random 'asteroids' moving across the screen, but then one thing led to another. It's basically is just a demo, not a proper game.
Use the left/right arrow keys to spin around, and use the 'up' arrow key to thrust, and space bar to fire. From level 4 onwards, thicker (and generally faster) asteroids appear which take more hits to destroy.
60 fps on all three of my machines.
For possibly improved performance (if the animation gets jittery), compile the program and then run it.
David.
--
Re: GLib (compact sprite library)
Post by DDRM on May 22nd, 2016, 3:14pm
Handsome, but difficult!

D
Re: GLib (compact sprite library)
Post by David Williams on Jun 19th, 2016, 3:14pm
Here's a little demo of GLib's capabilities (a work-in-progress game that I had started, but probably won't finish). Nothing much happens yet, sadly.
Use the arrow keys to move around.
Copy and paste the code from Pastebin into the BB4W IDE. The GLib library is already appended at the end of the program, so it doesn't need to reside in BB4W's LIB folder.
http://pastebin.com/Ag9eH66e
(Scroll down to the section titled 'RAW Paste Data' and then left-click somewhere inside the window, press CTRL A to select all the code, then CTRL C to copy it to the clipboard, and then press CTRL V inside the BB4W IDE to paste it.)
The scrolling is very smooth on my desktop PC, but on my laptop it's a bit jerky. I don't know why. Background processes most likely to blame. The program uses less than 15% CPU on my machines.
David.
Re: GLib (compact sprite library)
Post by David Williams on Jun 26th, 2016, 09:11am
Code: REM Fern 3D
REM Requires GLib to run
*ESC OFF
*FLOAT 64
INSTALL @lib$ + "GLIB"
PROCFWS : MODE 8 : OFF
PROCInitGLIB( g{} )
ON ERROR PROCCleanup : REPORT : END
ON CLOSE PROCCleanup : QUIT
P% = PlotPixel
Q% = PlotPoint
R% = ReadPixel
G% = g{}
nPts% = FNgetFernPoints( 12345678, FALSE )
DIM p(nPts%-1,2), q(nPts%-1,2), m(2,2)
dummy% = FNgetFernPoints( 12345678, TRUE )
minX = 10000000
maxX = -minX
minY = 10000000
maxY = -minY
FOR I% = 0 TO nPts%-1
IF p(I%,0) < minX THEN minX = p(I%,0)
IF p(I%,0) > maxX THEN maxX = p(I%,0)
IF p(I%,1) < minY THEN minY = p(I%,1)
IF p(I%,1) > maxY THEN maxY = p(I%,1)
NEXT I%
FOR I% = 0 TO nPts%-1
p(I%,0) -= (maxX - minX)/2
p(I%,1) -= (maxY - minY)/2
p(I%,2) = 250
NEXT I%
*REFRESH OFF
REPEAT
T% = TIME
A = T%/122
B = T%/176
C = T%/312
D = 2*PI*SIN(T%/520)
E = 3*PI*COS(T%/720)
sA = SIN(A)
cA = COS(A)
sB = SIN(B)
cB = COS(B)
sC = SIN(C)
cC = COS(C)
m() = (cB*cC), -cB*sC, sB, cA*sC+sA*sB*cC, cA*cC-sA*sB*sC, -sA*cB, sA*sC-cA*sB*cC, sA*cC+cA*sB*sC, cA*cB
q() = p().m()
SYS Clr, G%, &000040
FOR I% = 0 TO nPts%-1
SYS Q%, G%, 320+q(I%,0), 256+q(I%,1), &E020
NEXT
PROCDisplay(TRUE)
UNTIL FALSE
END
DEF FNgetFernPoints( rndseed%, store_coords% )
LOCAL A%, C%, I%, S%, r, x, y, newx, newy
S% = RND(-ABS(rndseed%))
C% = 0
x = 0
y = 0
SYS Clr, g{}, 0
FOR I% = 1 TO 80000
r = RND(1)
CASE TRUE OF
WHEN r<=0.1 A=0: B=0: C=0: D=0.16: E=0: F=0
WHEN r>0.1 AND r<=0.86 A=.85: B=.04: C=-.04: D=.85: E=0: F=1.6
WHEN r>0.86 AND r<=0.93 A=.2: B=-.26: C=.23: D=.22: E=0: F=1.6
WHEN r>0.93 A=-.15: B =.28: C=.26: D=.24: E=0: F=.44
ENDCASE
newx=A*x+B*y+E
newy=C*x+D*y+F
x=newx
y=newy
SYS R%, G%, 300+48*x, 16+48*y TO A%
IF A% = 0 THEN
IF store_coords% THEN
SYS P%, G%, 300+48*x, 16+48*y, &E020
p(C%,0) = 48*x
p(C%,1) = 48*y
p(C%,2) = 0
ELSE
SYS P%, G%, 300+48*x, 16+48*y, &E020
ENDIF
C% += 1
ENDIF
NEXT
= C%
Re: GLib (compact sprite library)
Post by David Williams on Jun 27th, 2016, 06:23am
This one's slightly different:
(Reminder: Obtain the GLib library from the first post in this thread and either append it to the end of this program (remove the INSTALL statement in that case), or put it in the usual place (BB4W's LIB folder)).
Code: REM Fern 3D
REM Requires GLib to run
*ESC OFF
*FLOAT 64
INSTALL @lib$ + "GLIB" : REM remove this line if GLib library is appended to end of this program
PROCFWS : MODE 8 : OFF
PROCInitGLIB( g{} )
ON ERROR PROCCleanup : REPORT : END
ON CLOSE PROCCleanup : QUIT
P% = PlotPixel
Q% = PlotPoint
R% = ReadPixel
G% = g{}
REM Create colour-graduated background bitmap:
WinW% = @vdu%!208
WinH% = @vdu%!212
bg% = FN`ga(4*WinW%*WinH%, 1)
FOR Y% = 0 TO WinH%-1
A% = 4*Y%*WinW%
f = 1 - Y%/(WinH%-1)
C% = INT(255*0.5*f) + &100*INT(255*0.15*f) + &10000*INT(255*0.075*f)
FOR I% = bg%+A% TO bg%+A%+4*WinW%-1 STEP 4
!I% = C%
NEXT I%
NEXT Y%
nPts% = FNgetFernPoints( 12345678, FALSE )
DIM p(nPts%-1,2), q(nPts%-1,2), m(2,2)
dummy% = FNgetFernPoints( 12345678, TRUE )
minX = 10000000
maxX = -minX
minY = 10000000
maxY = -minY
FOR I% = 0 TO nPts%-1
IF p(I%,0) < minX THEN minX = p(I%,0)
IF p(I%,0) > maxX THEN maxX = p(I%,0)
IF p(I%,1) < minY THEN minY = p(I%,1)
IF p(I%,1) > maxY THEN maxY = p(I%,1)
NEXT I%
dx_max = maxX - minX
dy_max = maxY - minY
cx = dx_max/2
cy = dy_max/2
d_max = SQR(cx^2 + cy^2)
FOR I% = 0 TO nPts%-1
x = p(I%,0)
y = p(I%,1)
p(I%,2) = 100 + 100*SQR((x-cx)^2 + (y-cy)^2)/d_max
p(I%,0) -= cx
p(I%,1) -= cy
NEXT I%
k = 255 * 1/700
*REFRESH OFF
REPEAT
T% = TIME
A = T%/122
B = T%/176
C = T%/312
D = 2*PI*SIN(T%/520)
E = 3*PI*COS(T%/720)
sA = SIN(A)
cA = COS(A)
sB = SIN(B)
cB = COS(B)
sC = SIN(C)
cC = COS(C)
m() = (cB*cC), -cB*sC, sB, cA*sC+sA*sB*cC, cA*cC-sA*sB*sC, -sA*cB, sA*sC-cA*sB*cC, sA*cC+cA*sB*sC, cA*cB
q() = p().m()
REMSYS Clr, G%, &000040
SYS BPlot, G%, bg%, WinW%, WinH%, 0, 0
FOR I% = 0 TO nPts%-1
SYS Q%, G%, 320+q(I%,0), 256+q(I%,1), &100*INT(255-k*(350+q(I%,2)))
NEXT
PROCDisplay(TRUE)
UNTIL FALSE
END
DEF FNgetFernPoints( rndseed%, store_coords% )
LOCAL A%, C%, I%, S%, r, x, y, newx, newy
S% = RND(-ABS(rndseed%))
C% = 0
x = 0
y = 0
SYS Clr, g{}, 0
FOR I% = 1 TO 80000
r = RND(1)
CASE TRUE OF
WHEN r<=0.1 A=0: B=0: C=0: D=0.16: E=0: F=0
WHEN r>0.1 AND r<=0.86 A=.85: B=.04: C=-.04: D=.85: E=0: F=1.6
WHEN r>0.86 AND r<=0.93 A=.2: B=-.26: C=.23: D=.22: E=0: F=1.6
WHEN r>0.93 A=-.15: B =.28: C=.26: D=.24: E=0: F=.44
ENDCASE
newx=A*x+B*y+E
newy=C*x+D*y+F
x=newx
y=newy
SYS R%, G%, 300+48*x, 16+48*y TO A%
IF A% = 0 THEN
IF store_coords% THEN
SYS P%, G%, 300+48*x, 16+48*y, &E020
p(C%,0) = 48*x
p(C%,1) = 48*y
p(C%,2) = 0
ELSE
SYS P%, G%, 300+48*x, 16+48*y, &E020
ENDIF
C% += 1
ENDIF
NEXT
= C%
Re: GLib (compact sprite library)
Post by DDRM on Jun 28th, 2016, 08:44am
Hi David,
I get a fail with PROCFWS: where/what is it? It doesn't seem too critical, because simply deleting it results in a working program. 
I like the way you make the fern flat and then map in the z coordinate by distance, and the nice use of matrix multiplication to the rotation mapping all at once - those matrix functions are blindingly fast, aren't they? A great feature of BB4W.
If you scaled the z mappings in your matrix m() by one of your rotation angles, could you make it "blow in the breeze"?
Best wishes,
D
Re: GLib (compact sprite library)
Post by David Williams on Jun 28th, 2016, 10:34am
on Jun 28th, 2016, 08:44am, DDRM wrote:I get a fail with PROCFWS: where/what is it? It doesn't seem too critical, because simply deleting it results in a working program. ;D |
|
That was a subroutine I added to a more recent version of GLib than the one you may have in your LIB folder. Version 0.07 is the latest version, and the library code is listed in the first post of this thread. 'FWS' stands for 'Fix Window Size'. The reason for the cryptic name is in keeping with GLib's original need to be usable with the old, memory-limited trial version of BB4W.
Quote:If you scaled the z mappings in your matrix m() by one of your rotation angles, could you make it "blow in the breeze"? |
|
That's a nice idea, but with 18,907 points to 'process', the frame rate would probably take quite a hit! I may give it a try nevertheless, even if I need to resort to assembler code for speed.
I've included a slightly more efficient version of the program below (it uses a colour table, and hexadecimal constants in the point-plotting loop because the interpreter converts them to binary slightly faster than base 10).
David.
--
Code:
REM Fern 3D (v3)
REM Requires GLib to run
*ESC OFF
*FLOAT 64
INSTALL @lib$ + "GLIB" : REM remove this line if GLib library is appended to end of this program
PROCFWS : MODE 8 : OFF
PROCInitGLIB( g{} )
ON ERROR PROCCleanup : REPORT : END
ON CLOSE PROCCleanup : QUIT
P% = PlotPixel
Q% = PlotPoint
R% = ReadPixel
G% = g{}
REM Create colour-graduated background bitmap:
WinW% = @vdu%!208
WinH% = @vdu%!212
bg% = FN`ga(4*WinW%*WinH%, 1)
FOR Y% = 0 TO WinH%-1
A% = 4*Y%*WinW%
f = 1 - Y%/(WinH%-1)
C% = INT(255*0.5*f) + &100*INT(255*0.15*f) + &10000*INT(255*0.075*f)
FOR I% = bg%+A% TO bg%+A%+4*WinW%-1 STEP 4
!I% = C%
NEXT I%
NEXT Y%
nPts% = FNgetFernPoints( 12345678, FALSE )
DIM p(nPts%-1,2), q(nPts%-1,2), m(2,2)
dummy% = FNgetFernPoints( 12345678, TRUE )
minX = 10000000
maxX = -minX
minY = 10000000
maxY = -minY
FOR I% = 0 TO nPts%-1
IF p(I%,0) < minX THEN minX = p(I%,0)
IF p(I%,0) > maxX THEN maxX = p(I%,0)
IF p(I%,1) < minY THEN minY = p(I%,1)
IF p(I%,1) > maxY THEN maxY = p(I%,1)
NEXT I%
dx_max = maxX - minX
dy_max = maxY - minY
cx = dx_max/2
cy = dy_max/2
d_max = SQR(cx^2 + cy^2)
FOR I% = 0 TO nPts%-1
x = p(I%,0)
y = p(I%,1)
p(I%,2) = 50 + 150*SQR((x-cx)^2 + (y-cy)^2)/d_max
p(I%,0) -= cx
p(I%,1) -= cy
NEXT I%
k = 1/700
DIM C%( 700 )
FOR I% = 0 TO 700
C%(I%) = &100*INT(255*k*I%) + INT(64*k*I%)
NEXT I%
*REFRESH OFF
REPEAT
T% = TIME
A = T%/122
B = T%/176
C = T%/312
D = 2*PI*SIN(T%/520)
E = 3*PI*COS(T%/720)
sA = SIN(A)
cA = COS(A)
sB = SIN(B)
cB = COS(B)
sC = SIN(C)
cC = COS(C)
m() = cB*cC, -cB*sC, sB, cA*sC+sA*sB*cC, cA*cC-sA*sB*sC, -sA*cB, sA*sC-cA*sB*cC, sA*cC+cA*sB*sC, cA*cB
q() = p().m()
SYS BPlot, G%, bg%, WinW%, WinH%, 0, 0
FOR I% = 0 TO nPts%-1
SYS Q%, G%, &140+q(I%,0), &100+q(I%,1), C%(&15E+q(I%,2))
NEXT
PROCDisplay(TRUE)
UNTIL FALSE
END
DEF FNgetFernPoints( rndseed%, store_coords% )
LOCAL A%, C%, I%, S%, r, x, y, newx, newy
S% = RND(-ABS(rndseed%))
C% = 0
x = 0
y = 0
SYS Clr, g{}, 0
FOR I% = 1 TO 80000
r = RND(1)
CASE TRUE OF
WHEN r<=0.1 A=0: B=0: C=0: D=0.16: E=0: F=0
WHEN r>0.1 AND r<=0.86 A=.85: B=.04: C=-.04: D=.85: E=0: F=1.6
WHEN r>0.86 AND r<=0.93 A=.2: B=-.26: C=.23: D=.22: E=0: F=1.6
WHEN r>0.93 A=-.15: B =.28: C=.26: D=.24: E=0: F=.44
ENDCASE
newx=A*x+B*y+E
newy=C*x+D*y+F
x=newx
y=newy
SYS R%, G%, 300+48*x, 16+48*y TO A%
IF A% = 0 THEN
IF store_coords% THEN
SYS P%, G%, 300+48*x, 16+48*y, &E020
p(C%,0) = 48*x
p(C%,1) = 48*y
p(C%,2) = 0
ELSE
SYS P%, G%, 300+48*x, 16+48*y, &E020
ENDIF
C% += 1
ENDIF
NEXT
= C%
Re: GLib (compact sprite library)
Post by DDRM on Jun 28th, 2016, 11:09am
Hi David,
Aha! I now have the updated version (007, I think. I'll be careful not to offend it!), and the problem has gone away.
The point of my "waving" suggestion was that I think you could do it by altering the contents of the m matrix, so there should be essentially 0 time cost. I may be misunderstanding how it works, though, I haven't worked through it carefully. You might need an intermediate array equivalent to p and q, to hold the "blown" XYZ data (i.e with the z coordinates transformed by Cos(angle)), but even that should be fast.
OK, I had a go:
Code:
REM Near the top: probably a sledgehammer! Make space for extra array
HIMEM=LOMEM+4E7
.
REM With the other array declarations (included)
DIM p(nPts%-1,2), q(nPts%-1,2), m(2,2),dt(nPts%-1,2)
.
REM Highjacking your mapping section
m()=1,0,0,0,1,0,0,0,cA
dt()=p().m()
m() = cB*cC, -cB*sC, sB, cA*sC+sA*sB*cC, cA*cC-sA*sB*sC, -sA*cB, sA*sC-cA*sB*cC, sA*cC+cA*sB*sC, cA*cB
q() = dt().m()
Best wishes,
D
Re: GLib (compact sprite library)
Post by David Williams on Jun 28th, 2016, 3:01pm
David, that's efficient and works well! And there's me thinking (or perhaps not thinking) I'd need to do it via a loop.
You probably noticed that darker points (in this case, a point is a 2x2 block of pixels) sometimes overwrite lighter ones, when ideally the points should be plotted in order from dark to light according to their Z co-ordinates. One could sort them (very CPU-expensive given the number of points), or one could write an assembler routine which reads a background pixel and only overwrites it with a new one if the new one is lighter (depending on how 'lightness' is defined!). Doing it in BASIC would really slow things down, I think.
Regards,
David.
--
Re: GLib (compact sprite library)
Post by David Williams on Sep 19th, 2016, 11:09am
Over at the 'BBC BASIC (SDL)' forum, Michael asks the question,
Quote:The bigger question to ask you Richard, is how is a sprite image held in memory and quickly placed on the screen? |
|
This is exactly what the compact library 'GLib' is for. The library code is posted in the first post of this thread. It plots 32bpp (4 bytes per pixel) sprites, and it's pretty fast (for a software-based renderer).
I've bundled up most of the GLib example programs that I had posted to this thread into a Zip folder containing compiled EXEs and souce code.
Download:
https://drive.google.com/open?id=0B3j5sIQi9SskVnlJdmZuYWI3cTQ
David.
--
Re: GLib (compact sprite library)
Post by David Williams on Sep 19th, 2016, 11:31am
on Sep 19th, 2016, 11:09am, David Williams wrote:Over at the 'BBC BASIC (SDL)' forum, Michael asks the question,
This is exactly what the compact library 'GLib' is for. The library code is posted in the first post of this thread. It plots 32bpp (4 bytes per pixel) sprites, and it's pretty fast (for a software-based renderer).
I've bundled up most of the GLib example programs that I had posted to this thread into a Zip folder containing compiled EXEs and source code.
Download:
https://drive.google.com/open?id=0B3j5sIQi9SskVnlJdmZuYWI3cTQ
David. -- |
|
Re: GLib (compact sprite library)
Post by michael on Sep 19th, 2016, 11:37pm
I see.. I looked over "Wavey Starfish" and I think I will be able to make it work for the animation overlays..
( what is the status of GLib? is it Open Source or Public Domain or what?)
I am currently working with a DIB section Ric shown me to adapt to my BMPtoCode output code..
The only huge leap is getting all the colors right and then its just a matter of converting my conditional statements to produce the proper hexadecimal value.
Your work is pretty cool. I will definitely tinker with it to see if I can adapt it to my code toon parts tools.
After a certain point, the data base will become too large to post, but hopefully, should allow a person to construct animations easily and control them with commands in code.
Here is an output code image that I would need to modify :
The colors in this program were extracted from windows paint color values on a 256 color BMP file format except for the bottom right color on the default colors.
So if a person were to convert this programs color controls and plotting controls, toon creation work could be more effective.
AND once that was done, I could modify BMPtoCode to automatically generate the code needed for any Code image.
And each image would function like a customizable BBC Basic command in a future library.
**** BMPtoCODE created this entire program from a 256 color BMP image. And the data statements are compressed image data
This cant be compressed any more.. It took me at least a month to work out the compression in LBB.
Code: VDU 22,8
VDU 23,23,1|
OFF:VDU 5:COLOUR 0:CLG
PROC_image(100,500)
WAIT 0:END
DEF PROC_image(h,v)
LOCAL DATA
u=0:r=0:g=0:b=0:a=0:c=0:t=0
ost$=""
READ x,y:REPEAT
READ nst$,t
IF nst$="0" THEN r=0:g=0:b=0 :REM 'black 0 0 0
IF nst$="1" THEN r=192:g=128:b=64:REM ' brown 192 128 64
IF nst$="2" THEN r=64:g=64:b=192 :REM'dark blue 64 64 192
IF nst$="3" THEN r=128:g=128:b=128:REM' dark grey 128 128 128
IF nst$="4" THEN r=128:g=0:b=0:REM'dark red 128 0 0
IF nst$="5" THEN r=224:g=192:b=0 :REM'dark yellow 224 192 0
IF nst$="6" THEN r=128:g=160:b=192:REM'flat blue 128 160 192
IF nst$="7" THEN r=32:g=192:b=64 :REM'green 32 192 64
IF nst$="8" THEN r=166:g=202:b=240:REM'light blue 166 202 240
IF nst$="9" THEN r=192:g=192:b=192:REM 'light gray 192 192 192
IF nst$="a" THEN r=192:g=224:b=0:REM 'light green 192 224 0
IF nst$="b" THEN r=224:g=32:b=64:REM'light red 224 32 64
IF nst$="c" THEN r=0:g=160:b=192 :REM'medblue 0 160 192
IF nst$="d" THEN r=224:g=128:b=64 :REM 'orange 224 128 64
IF nst$="e" THEN r=224:g=160:b=192:REM'pink 224 160 192
IF nst$="f" THEN r=160:g=64:b=192:REM'purple 160 64 192
IF nst$="g" THEN r=192:g=220:b=192:REM'tan 192 220 192
IF nst$="h" THEN r=255:g=255:b=255:REM'white 255 255 255
IF nst$="i" THEN r=255:g=255:b=0:REM'yellow 255 255 0
COLOUR 0,r,g,b:GCOL 0
FOR u=0 TO t
a=a+1: MOVE h+c,v-a:DRAW h+c,v-a:IF a>x THEN c=c+1:a=0
NEXT u
UNTIL nst$="100000"
MOVE 0,0
DATA 161,161
DATA 0,9471,3,1,0,159,3,1,0,157,h,3,0,157,h,3,0,155,h,7,0,153,h,7,0,151,h,11,0,149,h,11,0,147,h,13,3,1,0,145,h
DATA 13,3,1,0,143,h,15,0,145,h,15,0,145,g,1,h,15,0,143,g,1,h,15,0,143,h,17,0,143,h,17,0,141,h,21,0,139,h,21,0,139
DATA h,21,0,139,h,21,0,137,h,25,0,135,h,25,0,135,h,27,0,133,h,27,0,133,h,27,3,1,0,131,h,27,3,1,0,129,3,1,h,29,0
DATA 129,3,1,h,29,0,129,g,1,h,29,0,129,g,1,h,29,0,129,h,31,0,129,h,31,0,129,h,31,0,129,h,31,0,129,h,13,9,1,0,1
DATA h,11,0,131,h,13,9,1,0,1,h,11,0,131,h,11,0,5,9,1,h,7,0,133,h,11,0,5,9,1,h,7,0,133,h,9,3,1,0,7,h
DATA 5,0,135,h,9,3,1,0,7,h,5,0,139,h,7,0,5,g,1,h,3,0,141,h,7,0,5,g,1,h,3,0,145,g,1,h,7,g,1,0,149
DATA g,1,h,7,g,1,100000,0
ENDPROC
And here is the current project... extracting the colors and matching them to my custom colors in my output code file:
Any suggestions would help..
It has been just experimentation / trial and error to get the current colors I have posted here..
White found (updated on edit)
If you look at the previous code you will see the colors I need .. (its good to be close to the colors that I made, otherwise the image wont be right.
There seems to be a problem with this program. Seems the graphics draws and screen size are not always the same.. When I run it multiple times the image is not always the same.
Code: REM The 3rd and 4th components of the VDU 23,22 statement must be the same as bmi.Header.Width% and bmi.Header.Height%
VDU 23,22,1024;640;16,16,16,0
DIM BITMAPINFOHEADER{Size%, Width%, Height%, Planes{l&,h&}, BitCount{l&,h&}, Compression%, SizeImage%, XPelsPerMeter%, YPelsPerMeter%, ClrUsed%, ClrImportant%}
DIM bmi{Header{} = BITMAPINFOHEADER{}}
bmi.Header.Size% = DIM(BITMAPINFOHEADER{})
bmi.Header.Width% = 1024
bmi.Header.Height% = 640
bmi.Header.Planes.l& = 1
bmi.Header.BitCount.l& = 32
SYS "CreateDIBSection", @memhdc%, bmi{}, 0, ^bits%, 0, 0 TO hbitmap%
IF hbitmap%=0 ERROR 100, "Couldn't create DIBSection"
SYS "SelectObject", @memhdc%, hbitmap% TO oldhbm%
SYS "DeleteObject", oldhbm%
SYS "InvalidateRect", @hwnd%, 0, 0
REM The code to this point sets the screen size in pixels and creates bitmap to the same size
REM To access the bitmap you need to use bit% :-
REM Each pixel is four bytes
REM You can access one at a time with "bits%?(X,Y)=8_bit_number"
REM Or all four bytes at the same time "bits%!(X,Y)=&aaRRGGBB
REM when setting X and Y remember they are pixel coordinates not graphics coordinates
X=100
Y=100
bits%?( ( X + ( Y * bmi.Header.Width% ) ) * 4 ) = 255 : REM Will put a blue dot at 100,100
X=110
bits%!( ( X + ( Y * bmi.Header.Width% ) ) * 4 ) =&FF0000
X=115
bits%!( ( X + ( Y * bmi.Header.Width% ) ) * 4 ) = &00FF00FF : REM Will put a magenta dot at 110,100
FOR loop = 300 TO 500
bits%!( ( loop + ( loop * bmi.Header.Width% ) ) * 4 ) = &400040 :REM DARK PURPLE
bits%!( ( loop +8+ ( loop * bmi.Header.Width% ) ) * 4 ) = &FF0000 :REM RED
bits%!( ( loop +15+ ( loop * bmi.Header.Width% ) ) * 4 ) = &F36E2D7 :REM CYAN
bits%!( ( loop +16+ ( loop * bmi.Header.Width% ) ) * 4 ) = &F36E2D7 :REM CYAN
bits%!( ( loop +25+ ( loop * bmi.Header.Width% ) ) * 4 ) = &0011E6380C :REM orange
bits%!( ( loop +35+ ( loop * bmi.Header.Width% ) ) * 4 ) = &00BEFA717 :REM yellow
bits%!( ( loop +45+ ( loop * bmi.Header.Width% ) ) * 4 ) = &00F360BFF :REM blue
bits%!( ( loop +55+ ( loop * bmi.Header.Width% ) ) * 4 ) = &00F36E23C :REM green
bits%!( ( loop +65+ ( loop * bmi.Header.Width% ) ) * 4 ) = &005F9C57C :REM TAN
bits%!( ( loop +80+ ( loop * bmi.Header.Width% ) ) * 4 ) = &65497 :REM light blue
bits%!( ( loop +90+ ( loop * bmi.Header.Width% ) ) * 4 ) = &654951 :REM Greyish purple?
bits%!( ( loop +91+ ( loop * bmi.Header.Width% ) ) * 4 ) = &654951 :REM greyish purple?
bits%!( ( loop +92+ ( loop * bmi.Header.Width% ) ) * 4 ) = &654951 :REM greyish purple?
bits%!( ( loop +93+ ( loop * bmi.Header.Width% ) ) * 4 ) = &654951 :REM greyish purple?
bits%!( ( loop +99+ ( loop * bmi.Header.Width% ) ) * 4 ) = &6549 :REM grass green
bits%!( ( loop +109+ ( loop * bmi.Header.Width% ) ) * 4 ) = &65 :REM ? dark blue
bits%!( ( loop +129+ ( loop * bmi.Header.Width% ) ) * 4 ) = &12632256:REM purple
bits%!( ( loop +149+ ( loop * bmi.Header.Width% ) ) * 4 ) = &167777215 :REM Dark yellow
bits%!( ( loop +159+ ( loop * bmi.Header.Width% ) ) * 4 ) = &167777:REM dark cyan
bits%!( ( loop +169+ ( loop * bmi.Header.Width% ) ) * 4 ) = &167772111:REM dark red
bits%!( ( loop +179+ ( loop * bmi.Header.Width% ) ) * 4 ) = &FFFFFF: REM BRIGHT WHITE BMPtoCODE
bits%!( ( loop +189+ ( loop * bmi.Header.Width% ) ) * 4 ) = &C0CFD0: REM GRAY? BMPtoCODE
bits%!( ( loop +199+ ( loop * bmi.Header.Width% ) ) * 4 ) = &C0C0C0: REM Light GRAY BMPtoCODE
bits%!( ( loop +209+ ( loop * bmi.Header.Width% ) ) * 4 ) = &A0013BF: REM RED BMPtocode? NOPE!! its blue
NEXT
bits%!( ( X + ( Y * bmi.Header.Width% ) ) * 4 ) = &400040 :REM DARK PURPLE
REM The reason for the "* bmi.Header.Width%" is to move the "Y" position up the screen by the correct displacement
REM and the "*4" is because each position on the bit map is four pixels
REM A simple line
REM After you have finished accessing the bit map a "*REFRESH" is needed to update the screen
*REFRESH
Re: GLib (compact sprite library)
Post by David Williams on Sep 21st, 2016, 11:48am
The programs linked-to below work with BB4W and BBCSDL. I get a rather inconsistent 60 to 70 fps on my Core i7 desktop PC with either BB4W and BBCSDL, and the same with BB4W on my Celeron-based laptop (duo core), but not with BBCSDL which returns roughly 30 fps. In this case, omitting the "WAIT 1" statement still isn't enough to raise the average frame rate beyond 50 fps. I have taken steps to ensure that the alpha channel of the 640x480 32bpp bitmap rendered via OSCLI "MDISPLAY ..." is totally clear so that SDL isn't attempting to alpha-blend anything. Furthermore, I have ensured that the address of the start of the bitmap pixel data (i.e. address of the first pixel in the background bitmap) is 'DWORD aligned' (i.e. divisible by 4). This certainly speeds up rendering with BB4W, because usually the pixel data of a 32bpp BMP is misaligned by 2 bytes (header size is 54 bytes, when ideally it ought to be 56!).
Links:
http://pastebin.com/FVRKZNN6
Scroll down to the 'RAW Paste Data' section, press CTRL+A to select all the code, then copy and paste into the BB4W/BBCSDL IDE.
Also, I've just added this (alpha-blended sprites over a colourful background):
http://pastebin.com/aTmyEpVd
Bonus: here's that "wavey starfish" again, compatible with BBCSDL:
http://pastebin.com/EfdUetEL
David.
--
Re: GLib (compact sprite library)
Post by David Williams on Sep 24th, 2016, 9:28pm
Here's another little demo (and definitely the last in the series) which works with both BB4W and BBCSDL. It is not a game as such, although you can use the Z and X keys to move your space ship, and press Enter to fire at the descending aliens.
http://pastebin.com/CWJKMLP4
The program is self-contained. You don't need to install GLib beforehand.
It also runs independent of frame rate.
When run under BBCSDL, I found that I have to clear the entire alpha channel of the 640x480 graphics 'surface' bitmap before calling *MDISPLAY. This is annoying and inefficient. But why is the alpha channel used in the first place? I use it here for fast and easy collision detection, not for alpha blending.
David.
--
Re: GLib (compact sprite library)
Post by DDRM on Sep 26th, 2016, 2:18pm
Hi David,
Ooh, that's an intriguing throw-away! How are you using it for collision detection?
D
Re: GLib (compact sprite library)
Post by David Williams on Sep 26th, 2016, 3:54pm
on Sep 26th, 2016, 2:18pm, DDRM wrote:Ooh, that's an intriguing throw-away! How are you using it for collision detection? |
|
The 'alien' sprites are plotted using the routine PlotSetAlpha which, apart from merely plotting a sprite, also sets the 'invisible' and normally redundant alpha byte of all overwritten background pixels to a specified value in the range 0 to 255. This value is different for each individual alien, and is in fact the alien's index in the alien{()} structure array. Actually, the indices run from 1 up to the maximum number of aliens that may be plotted (which can't exceed 255) because writing alpha values of zero isn't terribly useful in this scheme. So once we've plotted all the aliens, and the initially-clean alpha channel of the background/surface bitmap has been scribbled all over, when it comes to plotting our missiles/plasma bolts, those are plotted using PlotGetAlphaBits. This routine plots the missile sprites but also reads the background alpha bytes (of all pixels overwritten by the missile sprite) and returns the cumulative alpha value which, if there is no collision, should be zero. If it's nonzero, then a collision of the missile with one of the aliens has taken place. But which alien? The nonzero alpha value will be the actual index of the alien we've just collided with.
I'm pretty sure that I used this collision detection method with my game 'Alien Eliminator':
https://www.youtube.com/watch?v=lgPWQKjLaaw
And with other games, too.
With BB4W, drawing the background/surface bitmap using *MDISPLAY is relatively fast irrespective of the state of the bitmap's alpha channel (whether it is completely clear, or contains nonzero alpha values), because it doesn't attempt to do any alpha blending. But with BBCSDL and *MDISPLAY, the bitmap is 'automatically' scanned for nonzero alpha values prior to rendering. If the alpha channel is clear then the bitmap is drawn fast-ish (not as fast as with BB4W), but if there is so much as one nonzero alpha value, then SDL will alpha blend the entire bitmap (or at least I think that's the case; it certainly seems to be). This is why I clear the alpha channel (when run under BBCSDL) before calling *MDISPLAY. I don't know how SDL is doing the (here unwanted) alpha channel pre-scanning, but I hope it's not using the CPU to do it!
David.
--
Re: GLib (compact sprite library)
Post by DDRM on Sep 27th, 2016, 12:55pm
Hi David,
OK, that's a cute and clever idea, but now I'm struggling a bit... So all the bits where you encode the string $S% as hex to (spaces defined by) variables like PlotGetAlphaBits are essentially pre-assembled functions, which you can then call using SYS, as if they were system commands? Sneaky, if opaque!
So that's kind of like Michael's BMPtoCode idea? 
With regard to the use of alpha channel values, Richard posted something on the cross-platform forum in another context that suggests that this is a "feature" of SDL rather than BB4SDL:
"What SDL does is to scan all the alpha bytes; if any of them are non-zero it (sensibly) assumes that you are using the alpha channel and applies it throughout. If none of the alpha bytes are non-zero it ignores the alpha channel entirely."
... so I wouldn't hold your breath for a version which doesn't behave that way...
Best wishes,
D
Re: GLib (compact sprite library)
Post by David Williams on Sep 27th, 2016, 1:52pm
on Sep 27th, 2016, 12:55pm, DDRM wrote:OK, that's a cute and clever idea, but now I'm struggling a bit... So all the bits where you encode the string $S% as hex to (spaces defined by) variables like PlotGetAlphaBits are essentially pre-assembled functions, which you can then call using SYS, as if they were system commands? Sneaky, if opaque! |
|
The intention behind GLib is that it be compact enough to be usable with the pre-v6 trial version of BB4W. So, yes, instead of memory-consuming assembly language, I use strings of pre-assembled machine code to save some space (although each byte of machine code requires 2 bytes for its ASCII representation). I suppose I could've used DATA statements instead which might have saved yet more space, but using strings seemed more convenient to me. I know that it was possible to circumvent (perhaps to a limited extent) the 8K (or was it 12K?) limit of the pre-v6 trial version of BB4W, but I'm not clever enough to figure out how to do it!
Incidentally, the more extensive GLib2 library is DLL-based (uses even less memory than GLib). I wrote it while I was learning C. I found that I was able to write graphics functions sometimes in a matter of minutes (literally!) rather than hours. I know that compiled C can be slower than hand-coded assembler code, but not always, and it depends on the competence of the programmer. Since a C compiler understands the CPU architecture better than most human programmers, and knows how to schedule sequences of instructions for efficient execution, compiled C can be faster. Some of my C-based graphics routines are faster than their largely equivalent assembly language versions, even though they're based on the same algorithms, and this is likely due to the C compiler sequencing (pipelining) the instructions in a more efficient way than I ever possibly could.
Quote:So that's kind of like Michael's BMPtoCode idea? |
|
Hmm.. perhaps, in a sense? Just to be sure, those machine code routines don't encode any image/sprite information.
Quote:With regard to the use of alpha channel values, Richard posted something on the cross-platform forum in another context that suggests that this is a "feature" of SDL rather than BB4SDL: |
|
I was aware of this, but if there is a way the 'pre-scanning' could be suppressed then it could save some (or rather a lot!) of CPU cycles. For a while, I did wonder why large (e.g. 640x4800 32bpp) BMP images took so long to render via *MDISPLAY (under BBCSDL). SDL was pre-scanning over 3 million pixels, even though for my particular application it wasn't necessary as no alpha blending was taking place.
I won't be able to develop one myself, but an SDL-based graphics library (which uses accelerated SDL graphics surfaces and rendering operations) is highly desirable. (GLib and GfxLib is mostly all CPU-intensive software-based rendering.) Such a library would ideally include an image loader (with appropriate conversion where necessary), and a function for synchronising graphics rendering with screen/monitor's refresh. I gather, from a brief Google search, that VBlank synchronisation is difficult or impossible with SDL in 'windowed mode'.
David.
--
Re: GLib (compact sprite library)
Post by David Williams on Sep 27th, 2016, 7:35pm
Just another experiment with frame rate-independent animation. I'm probably doing this wrong!
Use the Up/Down arrow keys to increase/decrease the number of sprites displayed. The frame rate will drop as the number of sprites increases, but the speed of the sprites should be roughly constant. The frame rate and number of objects are displayed in the window's title bar.
Works with BB4W and BBCSDL:
Code: *ESC OFF
NumSprTypes% = 20
MaxObjs% = 2000
M% = 3
HIMEM = LOMEM + M%*&100000
HIMEM = (HIMEM + 3) AND -4
BB4W% = (INKEY(-256) == &57)
IF BB4W% THEN
GetTicks$ = "GetTickCount"
SetWindowText$ = "SetWindowText"
ELSE
GetTicks$ = "SDL_GetTicks"
SetWindowText$ = "SDL_SetWindowTitle"
ENDIF
ScrW% = 640
ScrH% = 480
VDU 23,22,ScrW%;ScrH%;8,16,16,0 : OFF
TmpBMPBuf% = FNmalloc(4*128*128)
REM Create a 640x480 32bpp 'surface' bitmap:
DIM bmp{a%,w%,h%}
bmp.w%=ScrW%
bmp.h%=ScrH%
bmp.a%=FNcreateBMP32(bmp.w%,bmp.h%)
PROCInitGLIB(g{},bmp.w%,bmp.h%)
g.a%=bmp.a%+54
DIM spr{(NumSprTypes%-1) a%, sz%}
DIM obj{(MaxObjs%-1) type%, x, y, dx, dy}
*REFRESH OFF
GCOL 15
FOR I%=0 TO NumSprTypes%-1
spr{(I%)}.sz% = 4*(8+RND(10))
CLS
col1% = RND(64)+&100*RND(64)+&10000*RND(64)
col2% = (32+RND(255-32))+&100*(32+RND(255-32))+&10000*(32+RND(255-32))
FOR r%=spr{(I%)}.sz%/2-1 TO 1 STEP -1
f=1-r%/(spr{(I%)}.sz%/2-1)
PROClerpRGB(col1%,col2%,f,R%,G%,B%)
COLOUR 15,R%,G%,B%
CIRCLE FILL spr{(I%)}.sz%, spr{(I%)}.sz%, 2*r%
NEXT r%
file$ = @tmp$ + "spr" + STR$I%
OSCLI "GSAVE """+file$+""" "+STR$0+","+STR$0+","+STR$(2*spr{(I%)}.sz%)+","+STR$(2*spr{(I%)}.sz%)
NEXT I%
CLS : OSCLI "REFRESH" : OSCLI "REFRESH ON"
FOR I%=0 TO NumSprTypes%-1
PRINT I%
file$ = @tmp$ + "spr" + STR$I% + ".BMP"
spr{(I%)}.a% = FNLoadBMP(file$,TmpBMPBuf%,4*128*128)
NEXT I%
FOR I%=0 TO MaxObjs%-1
obj{(I%)}.type% = RND(NumSprTypes%)-1
obj{(I%)}.x = 32+RND(ScrW%-64)
obj{(I%)}.y = 32+RND(ScrH%-64)
obj{(I%)}.dx = 0.05 * SGN(RND(1)-0.5) * (0.25 + 3.75*RND(1))
obj{(I%)}.dy = 0.05 * SGN(RND(1)-0.5) * (0.25 + 3.75*RND(1))
NEXT I%
G% = g{}
NumObjs% = 1
flushKbBuf% = 0
frames% = 0
frameRate% = 0
SYS GetTicks$ TO time0%
REPEAT
SYS GetTicks$ TO t1%
SYS Clr,g{},&A0D0
P% = PlotShadow
FOR I%=0 TO NumObjs%-1
t%=obj{(I%)}.type%
a%=spr{(t%)}.a%
sz%=spr{(t%)}.sz%
SYS P%,G%,a%,sz%,sz%,obj{(I%)}.x-16,obj{(I%)}.y-16
NEXT
P% = Plot
FOR I%=0 TO NumObjs%-1
t%=obj{(I%)}.type%
a%=spr{(t%)}.a%
sz%=spr{(t%)}.sz%
SYS P%,G%,a%,sz%,sz%,obj{(I%)}.x,obj{(I%)}.y
NEXT
OSCLI "MDISPLAY "+STR$~bmp.a%
WAIT 1
SYS GetTicks$ TO t2%
dt%=t2%-t1%
FOR I%=0 TO NumObjs%-1
obj{(I%)}.x+=dt%*obj{(I%)}.dx
obj{(I%)}.y+=dt%*obj{(I%)}.dy
IF obj{(I%)}.x<-32 THEN
obj{(I%)}.dx*=-1
obj{(I%)}.x+=obj{(I%)}.dx
ENDIF
IF obj{(I%)}.x>ScrW%-32 THEN
obj{(I%)}.dx*=-1
obj{(I%)}.x+=obj{(I%)}.dx
ENDIF
IF obj{(I%)}.y<-32 THEN
obj{(I%)}.dy*=-1
obj{(I%)}.y+=obj{(I%)}.dy
ENDIF
IF obj{(I%)}.y>ScrH%-32 THEN
obj{(I%)}.dy*=-1
obj{(I%)}.y+=obj{(I%)}.dy
ENDIF
NEXT
IF INKEY-58 THEN
NumObjs%+=1
IF NumObjs%=MaxObjs% NumObjs%=MaxObjs%
ENDIF
IF INKEY-42 THEN
NumObjs%-=1
IF NumObjs%<1 NumObjs%=1
ENDIF
frames% += 1
SYS GetTicks$ TO time1%
IF time1%-time0% >= 1000 THEN
frameRate% = frames%
frames% = 0
SYS SetWindowText$, @hwnd%, STR$frameRate% + " fps | "+STR$NumObjs%+" objects"
SYS GetTicks$ TO time0%
ENDIF
IF flushKbBuf% > 0 THEN
flushKbBuf% -= 1
ELSE
*FX 21, 0
flushKbBuf% = 250
ENDIF
UNTIL FALSE
END
DEF PROClerpRGB( rgb1%, rgb2%, f, RETURN r%, RETURN g%, RETURN b% )
LOCAL r1%, g1%, b1%, r2%, g2%, b2%
r1% = (rgb1% AND &FF0000) >> 16
g1% = (rgb1% AND &FF00) >> 8
b1% = rgb1% AND &FF
r2% = (rgb2% AND &FF0000) >> 16
g2% = (rgb2% AND &FF00) >> 8
b2% = rgb2% AND &FF
r% = r1% + f*(r2%-r1%)
g% = g1% + f*(g2%-g1%)
b% = b1% + f*(b2%-b1%)
ENDPROC
DEF FNcreateBMP32( W%, H% )
LOCAL A%, S%
S% = 54 + 4*W%*H% + 6
DIM A% S%-1
A% = ((A% + 3) AND -4) + 2
A%?0 = ASC"B"
A%?1 = ASC"M"
A%!2 = 54 + 4*W%*H%
A%!6 = 0
A%!10 = 54
A%!14 = 40
A%!18 = W%
A%!22 = H%
A%?26 = 1
A%?28 = 32
A%!30 = 0
A%!34 = 4*W%*H%
A%!38 = 0
A%!42 = 0
A%!46 = 0
A%!50 = 0
= A%
DEF FNLoadBMP( file$, buf%, bufSz% )
LOCAL A%, B%, F%, W%, H%, I%, S%
F% = OPENIN( file$ )
IF F% = 0 THEN ERROR 0, "Can't find file " + file$
S% = EXT#F%
CLOSE#F%
OSCLI "LOAD """ + file$ + """ " + STR$~buf%
IF buf%?0<>ASC"B" OR buf%?1<>ASC"M" THEN
ERROR 0, file$ + " isn't a BMP file"
ENDIF
IF buf%?28 <> 24 AND buf%?28 <> 32 THEN
ERROR 0, "BMP file has invalid colour depth (must be 24 or 32)"
ENDIF
W% = buf%!18
IF (W% AND 3) <> 0 THEN ERROR 0, "BMP image width must be a multiple of 4"
H% = buf%!22
REM if H% is negative then sprite is "upside down" !
S% = 4 * W%*ABS(H%)
DIM B% S%+7
B% = (B% + 7) AND -8
A% = buf% + buf%!10
IF SGN(H%) = 1 THEN
IF buf%?28 = 24 THEN
FOR I% = B% TO B%+S%-1 STEP 4
!I% = ?A% OR &100*A%?1 OR &10000*A%?2
A% += 3
NEXT
ENDIF
ENDIF
IF SGN(H%)=-1 THEN
H%=ABS(H%)
IF buf%?28=24 THEN
A%+=3*W%*(H%-1)
FOR Y%=0 TO H%-1
Z%=A%
FOR I%=B%+4*W%*Y% TO B%+4*(W%*Y% +(W%-1))-1 STEP 4
!I%=?Z% OR &100*Z%?1 OR &10000*Z%?2
Z%+=3
NEXT
A%-=3*W%
NEXT
ENDIF
ENDIF
= B%
REM ============================================================================
DEFPROCInitGLIB(RETURN v{},W%,H%):LOCALS%,Z%:DIMv{a%,w%,h%}
v.w%=W%
v.h%=H%
Z%=FNmalloc(4096)
S%=FNmalloc(2048)
$S%="608B5C2424C703FFFFFFFF8B7C24383B7C24280F8DC70000008B74243C3B74242C0F8DB9"
$S%+="0000008B4C24308B54243483F9007D03F7D99083FA007D03F7DA90F7D93BF90F8E970000"
$S%+="00F7DA3BF20F8E8D000000F7D9F7DAC70300000000C7430400000000C7430800000000C7"
$S%+="430C00000000894B10895314897B1889731C8BEF03E93B6C24287E0E2B6C2428296B10C7"
$S%+="4304FFFFFFFF83FF007D14297B0C017B10C7431800000000C74304FFFFFFFF8BEE03EA3B"
$S%+="6C242C7E0E2B6C242C296B14C74304FFFFFFFF83FE007D14297308017314C7431C000000"
$S%+="00C74304FFFFFFFF61C21C0060":gClip=FN`m(S%,0)
$S%="608B6C24248B4424288B7D008B4D040FAF4D08FCF3AB61C2080000":Clr=FN`m(S%,0)
$S%="608BEC81EC800000008B75248BC4FF7538FF7534FF7530FF752CFF7608FF760450E8F6FE"
$S%+="FFFFF70424FFFFFFFF0F855A0000008B552C89542434C1642434020FAF5424080354240C"
$S%+="C1E2020355288B7E04897C2438C1642438020FAF7C241C037C2418C1E702033E8B5C2410"
$S%+="33C98B048A85C0740389048F83C1013BCB7CEF03542434037C2438FF4C241475DF81C480"
$S%+="00000061C2180060":Plot=FN`m(S%,33)
$S%="608BEC81EC800000008B75248BC4FF7538FF7534FF7530FF752CFF7608FF760450E85FFE"
$S%+="FFFFF70424FFFFFFFF0F85610000008B552C89542434C1642434020FAF5424080354240C"
$S%+="C1E2020355288B7E04897C2438C1642438020FAF7C241C037C2418C1E702033E8B5C2410"
$S%+="33C98B048A85C0740AD12C8F81248F7F7F7F7F83C1013BCB7CE803542434037C2438FF4C"
$S%+="241475D881C48000000061C2180060":PlotShadow=FN`m(S%,33)
Z%=FNmalloc(4096)
ENDPROC
DEFFN`m(S%,O%)
LOCALA%,I%:A%=FNmalloc(LEN$S%):FORI%=0TOLEN$S%DIV2-1
A%?I%=EVAL("&"+MID$($S%,2*I%+1,2)):NEXT
IFO%>0PROC`d(A%,O%,gClip)
=A%
DEFPROC`d(B%,O%,C%):LOCALD%,P%:D%=C%-B%-O%-5:P%=B%+O%+1:!P%=D%:ENDPROC
DEFFNmalloc(N%):LOCALA%:DIM A% N%+7:A%=(A%+7) AND -8:=A%
REM ============================================================================
Re: GLib (compact sprite library)
Post by David Williams on Nov 23rd, 2016, 04:55am
Anyone that has seen the latest version of GLib (0.24 beta - used by the 'Snowfall 3' demo) may have noticed that it has grown quite at lot in size, and therefore it can no longer be described as being a 'compact' library! It now stands at around 54 Kb, which I don't believe is excessive given the amount of functionality it provides. There is always the temptation to keep on adding new functions (a mistake I made with GfxLib). I will add several more useful ones, and stop there, I think.
The library incorporates a lot of Richard's work that he had kindly contributed to GfxLib and the Programmer's Reference, and he will be duly credited in the next release. For instance, the 'Snowfall 3' demo uses his MMX-based PlotRotateScaleRTR and BoxBlur routines.
Things to do:
1) Tidy up the library (drastically)
2) Write the documentation
3) Release the stable version
All by the end of this month, hopefully.
David.
--
Re: GLib (compact sprite library)
Post by David Williams on Nov 30th, 2016, 11:53pm
GLIB's documentation is starting to take shape:
http://www.proggies.uk/glib/glibdocs.html
I hope to have it all completed by the end of the weekend (before I run out of enthusiasm and energy!).
Re: GLib (compact sprite library)
Post by David Williams on Dec 1st, 2016, 03:33am
An old program modified for use with GLib. It downloads the latest version of GLib, and a BMP image, and stuffs them in a Windows temporary folder.
Copy, paste, run...
Code: REM "Vector balls 4"
REM Original GfxLib-based version created 16-Jan-2012
REM Modified for GLib on 01-Dec-2016
REM Uses 'PlotRotateScaleRTR' to draw the ball objects
*ESC OFF
*FLOAT 64
PROCurldownload( "http://www.proggies.uk/glib/GLIB.bbc", @tmp$+"glib_bbc.BBC" )
INSTALL @tmp$ + "glib_bbc"
PROCglib_FixWindowSize : MODE 8 : OFF
PROCglib_Init(g{}, glib{})
ON CLOSE PROCglib_Cleanup : QUIT
ON ERROR PROCglib_Cleanup : OSCLI "REFRESH ON" : ON : REPORT : PRINT " at line "; ERL : END
INSTALL @lib$+"SORTLIB" : sort% = FN_sortinit(1,0)
DIM g2{} = g{}
ballTypes% = 6 : DIM bmAddrTbl%( ballTypes%-1 )
REM bmAddrTbl%(0) = FNglib_LoadImg( @dir$+"blueball_128x128x24.BMP", -1 )
bmAddrTbl%(0) = FNLoadImgFromNet( "http://www.proggies.uk/temp/", "blueball_128x128x24.bmp" )
g2.w% = 128
g2.h% = 128
FOR I% = 1 TO ballTypes%-1
bmAddrTbl%(I%) = FNglib_CopyBitmap( glib{}, bmAddrTbl%(0), 128, 128, -1 )
g2.a% = bmAddrTbl%(I%)
SYS glib.PlotShuffleRGB%, g2{}, bmAddrTbl%(I%), 128, 128, 0, 0, I%
NEXT I%
_PREMULTIPLY = &1
_INVERT = &8
_3MRPASS = 3<<4
_2MBBPASS = 2<<6
ctrl% = _PREMULTIPLY + _INVERT + _3MRPASS + _2MBBPASS
FOR I% = 0 TO ballTypes%-1
PROCglib_CreateAlphaMask( g{}, glib{}, bmAddrTbl%(I%), 128, 128, 0, ctrl% )
NEXT I%
N% = 50
DIM bmAddr%( N%-1 ), bmAddr2%( N%-1 )
DIM x%(N%-1), y%(N%-1), z%(N%-1)
DIM x2%(N%-1), y2%(N%-1), z2%(N%-1)
minDist% = 100
R% = RND(-12345)
FOR I%=0 TO N%-1
REPEAT
valid% = TRUE
x%=-400+RND(2*400 - 1)
y%=-400+RND(2*400 - 1)
z%=-400+RND(2*400 - 1)
IF I%=0 THEN
x%(0) = x%
y%(0) = y%
z%(0) = z%
ELSE
FOR J%=0 TO I%
d% = SQR( (x%-x%(J%))^2 + (y%-y%(J%))^2 + (z%-z%(J%))^2 )
IF d% < minDist% THEN
valid% = FALSE
J% = I%
ENDIF
NEXT J%
ENDIF
UNTIL valid%
x%(I%) = x%
y%(I%) = y%
z%(I%) = z%
bmAddr%(I%) = bmAddrTbl%( RND(ballTypes%)-1 )
NEXT I%
a#=0
b#=0
c#=0
*REFRESH OFF
REPEAT
T% = TIME
bgCol% = &10000*INT(255*ABSSINRAD(T%/4.5)) + \
\ &100*INT(255*ABSSINRAD(T%/6.7)) + \
\ INT(255*ABSCOSRAD(T%/6.83))
SYS glib.Clr%, g{}, bgCol%
cosa# = COSa#
cosb# = COSb#
cosc# = COSc#
sina# = SINa#
sinb# = SINb#
sinc# = SINc#
FOR I%=0 TO N%-1
x# = x%(I%)
y# = y%(I%)
z# = z%(I%)
x1# = x#*cosa# - y#*sina#
y1# = x#*sina# + y#*cosa#
z1# = z#
y2# = y1#*cosb# - z1#*sinb#
z2# = y1#*sinb# + z1#*cosb#
x2# = x1#
z3# = z2#*cosc# - x2#*sinc#
x3# = z2#*sinc# + x2#*cosc#
y3# = y2#
x2%(I%) = x3#
y2%(I%) = y3#
z2%(I%) = z3#
NEXT I%
bmAddr2%() = bmAddr%()
C%=N% : CALL sort%, z2%(0), x2%(0), y2%(0), bmAddr2%(0)
FOR I%=0 TO N%-1
d# = 1/(&3E8+z2%(I%))
x = &140 + &2A8 * x2%(I%) * d#
y = &100 + &2A8 * y2%(I%) * d#
scale% = &10000*300/(z2%(I%)+650)
SYS glib.PlotRotateScaleRTR%, g{}, bmAddr2%(I%), 128, 128, 16*x, 16*y, 0, scale%
NEXT
a# += 0.019151
b# += 0.016316
c# += 0.012194
IF a# > 2*PI THEN a# -= 2*PI
IF b# > 2*PI THEN b# -= 2*PI
IF c# > 2*PI THEN c# -= 2*PI
PROCglib_Display
UNTIL FALSE
DEFFNLoadImgFromNet(url$,file$):LOCALA%,F%:F%=OPENIN(@tmp$+file$)
IF F%=0 PROCurldownload(url$+file$,@tmp$+file$)
CLOSE#F%
A%=FNglib_LoadImg(@tmp$+file$,0)
=A%
DEFPROCurldownload(url$,file$)
LOCALurlmon%,res%
SYS"LoadLibrary","urlmon.dll"TOurlmon%
SYS"GetProcAddress",urlmon%,"URLDownloadToFileA"TO`URLDownloadToFile`
SYS`URLDownloadToFile`,0,url$,file$,0,0TOres%
SYS"FreeLibrary",urlmon%
IFres%ERROR100,"Couldn't download "+url$
ENDPROC
Re: GLib (compact sprite library)
Post by DDRM on Dec 1st, 2016, 07:45am
Brilliant - that's really encouraging. It's very hard to use someone else's programming tools without a clear understanding of the required format etc.
Thanks!
D
Re: GLib (compact sprite library)
Post by sveinioslo on Dec 1st, 2016, 7:49pm
Quote:GLIB's documentation is starting to take shape: |
|
Thank you, been waiting for this.
Svein
Re: GLib (compact sprite library)
Post by michael on Dec 3rd, 2016, 12:55am
WOW! That is an amazing 3D ball animation. Or at least it looks 3D..
Re: GLib (compact sprite library)
Post by David Williams on Dec 20th, 2016, 02:16am
Added a new routine to GLIB which stretches (scales) a bitmap, with the transparency level of each plotted pixel determined by that pixel's 'brightness' (actually its averaged RGB value). The darker a pixel is, the more transparent it is when plotted. Finally, a global transparency value is applied to each pixel so that the bitmap as a whole can be 'faded' into the background if so desired. This routine is perhaps useful for e.g. fireball/explosion effects.
Here's a quick demo of the new routine (it's nothing exciting of course):
http://www.proggies.uk/temp/test_plotscaleblend2.zip
I recommend that you extract the EXE file from the Zip folder before running it.
David.
--