BBC BASIC for Windows
« GLib (compact sprite library) »

Welcome Guest. Please Login or Register.
Apr 5th, 2018, 11:07pm



ATTENTION MEMBERS: Conforums will be closing it doors and discontinuing its service on April 15, 2018.
Ad-Free has been deactivated. Outstanding Ad-Free credits will be reimbursed to respective payment methods.

If you require a dump of the post on your message board, please come to the support board and request it.


Thank you Conforums members.

BBC BASIC for Windows Resources
Online BBC BASIC for Windows documentation
BBC BASIC for Windows Beginners' Tutorial
BBC BASIC Home Page
BBC BASIC on Rosetta Code
BBC BASIC discussion group
BBC BASIC for Windows Programmers' Reference

« Previous Topic | Next Topic »
Pages: 1 2 3  Notify Send Topic Print
 veryhotthread  Author  Topic: GLib (compact sprite library)  (Read 453 times)
DDRM
Administrator
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 321
xx Re: GLib (compact sprite library)
« Reply #12 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. grin

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
User IP Logged

David Williams
Developer

member is offline

Avatar

meh


PM

Gender: Male
Posts: 452
xx Re: GLib (compact sprite library)
« Reply #13 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%
 
User IP Logged

DDRM
Administrator
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 321
xx Re: GLib (compact sprite library)
« Reply #14 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
User IP Logged

David Williams
Developer

member is offline

Avatar

meh


PM

Gender: Male
Posts: 452
xx Re: GLib (compact sprite library)
« Reply #15 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.
--


User IP Logged

David Williams
Developer

member is offline

Avatar

meh


PM

Gender: Male
Posts: 452
xx Re: GLib (compact sprite library)
« Reply #16 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.
--
User IP Logged

David Williams
Developer

member is offline

Avatar

meh


PM

Gender: Male
Posts: 452
xx Re: GLib (compact sprite library)
« Reply #17 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.
--
User IP Logged

michael
Senior Member
ImageImageImageImage


member is offline

Avatar




PM


Posts: 335
xx Re: GLib (compact sprite library)
« Reply #18 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
 
« Last Edit: Sep 20th, 2016, 03:20am by michael » User IP Logged

I like making program generators and like reinventing the wheel
David Williams
Developer

member is offline

Avatar

meh


PM

Gender: Male
Posts: 452
xx Re: GLib (compact sprite library)
« Reply #19 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.
--
« Last Edit: Sep 21st, 2016, 12:23pm by David Williams » User IP Logged

David Williams
Developer

member is offline

Avatar

meh


PM

Gender: Male
Posts: 452
xx Re: GLib (compact sprite library)
« Reply #20 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.
--


User IP Logged

DDRM
Administrator
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 321
xx Re: GLib (compact sprite library)
« Reply #21 on: Sep 26th, 2016, 2:18pm »

Hi David,

Ooh, that's an intriguing throw-away! How are you using it for collision detection?

D
User IP Logged

David Williams
Developer

member is offline

Avatar

meh


PM

Gender: Male
Posts: 452
xx Re: GLib (compact sprite library)
« Reply #22 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.
--
User IP Logged

DDRM
Administrator
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 321
xx Re: GLib (compact sprite library)
« Reply #23 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! wink So that's kind of like Michael's BMPtoCode idea? wink

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
User IP Logged

David Williams
Developer

member is offline

Avatar

meh


PM

Gender: Male
Posts: 452
xx Re: GLib (compact sprite library)
« Reply #24 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! wink


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? wink


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.
--
User IP Logged

David Williams
Developer

member is offline

Avatar

meh


PM

Gender: Male
Posts: 452
xx Re: GLib (compact sprite library)
« Reply #25 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 ============================================================================
 
User IP Logged

David Williams
Developer

member is offline

Avatar

meh


PM

Gender: Male
Posts: 452
xx Re: GLib (compact sprite library)
« Reply #26 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.
--
User IP Logged

Pages: 1 2 3  Notify Send Topic Print
« Previous Topic | Next Topic »

| |

This forum powered for FREE by Conforums ©
Terms of Service | Privacy Policy | Conforums Support | Parental Controls