Glowballs demo

Discussions related to graphics (2D and 3D), animation and games programming
p_m21987
Posts: 177
Joined: Mon 02 Apr 2018, 21:51

Glowballs demo

Post by p_m21987 »

Hello,

I haven't done much BASIC programming for a while, so for fun, today I adapted one of my JohnsonScript demos for BBCSDL.
Here's the original JohnsonScript code: https://github.com/TheGoldenManDenis/Jo ... glowballs3
(JohnsonScript is my own simple programming language I made myself, with an interpreter written in C and support for graphics through Xlib)

And here's the BBCSDL version:

Code: Select all

   10 numballs%=10 -1
   20 step%=16
   30 res%=500
   40 wh% =    res%-res%MODstep%
   50 VDU 23,22,wh%;wh%;8,16,16,0
   60 GCOL 4
   70 REMGCOL128+15
   80 *refresh off
   90 OFF
  100 res%=res%*2
  110 step%=step%*2
  120
  130 DIM balls{(numballs%)x,y,r,c&(4),xmo,ymo}
  140 FORI%=0TOnumballs%
  150   balls{(I%)}.x=RND(res%)
  160   balls{(I%)}.y=RND(res%)
  170   balls{(I%)}.r=res%/2+RND(res%/2)
  180   balls{(I%)}.c&(0)=RND(256)
  190   balls{(I%)}.c&(1)=RND(256)
  200   balls{(I%)}.c&(2)=RND(256)
  210   balls{(I%)}.xmo=(RND(1000)/1000-0.5)*2*12
  220   balls{(I%)}.ymo=(RND(1000)/1000-0.5)*2*12
  230 NEXT
  240
  250 REPEAT
  260
  270   CLG
  280   MOUSEX%,Y%,B%:IFB%THENGOTO140
  290
  300   REM move balls
  310   FORI%=0TOnumballs%
  320     PROCmoveandlimit(balls{(I%)}.x, balls{(I%)}.xmo)
  330     PROCmoveandlimit(balls{(I%)}.y, balls{(I%)}.ymo)
  340   NEXT
  350
  360   REM render balls
  370   FORI%=0 TO res% STEP step%
  380     FORJ%=0TOres%STEPstep%
  390       col%=0
  400       FOR K%=0 TO numballs%
  410         C%=FNglowballc( balls{(K%)}, I%,J% )
  420         IF C% THEN col%=FNadd_col(col%,C%)
  430       NEXT
  440       IFcol%THEN
  450         COLOUR4,col%>>16,col%>>8,col%
  460         RECTANGLEFILL J%,I%,step%
  470       ENDIF
  480     NEXT
  490   NEXT
  500
  510   *refresh
  520
  530 UNTILFALSE
  540
  550 DEF FNadd_col(a%,b%)
  560 LOCAL out%
  570 out%=?(^a%) + ?(^b%): IFout%>255: ?(^a%)=255ELSE?(^a%)=out%
  580 out%=?(^a%+1) + ?(^b%+1): IFout%>255: ?(^a%+1)=255ELSE?(^a%+1)=out%
  590 out%=?(^a%+2) + ?(^b%+2): IFout%>255: ?(^a%+2)=255ELSE?(^a%+2)=out%
  600 =a%
  610
  620 DEF FNglowballc( b{},xx,yy )
  630 LOCAL r,d,out,o%
  640 r = b{}.r * 0.5
  650 d = FNdist(b{}.x, b{}.y, xx,yy)
  660 IF d>r:=0
  670 out=1-d/r
  680 = ((b{}.c&(0)*out)<<16) OR ((b{}.c&(1)*out)<<8) OR ((b{}.c&(2)*out))
  690
  700 DEF FNdist(x,y,xx,yy)
  710 =SQR( (x-xx)^2 + (y-yy)^2 )
  720
  730 DEFPROCmoveandlimit(RETURN xy, RETURN mo)
  740 xy += mo
  750 IF xy>res% xy=res%: mo=-mo
  760 IF xy<0 xy=0: mo=-mo
  770 ENDPROC
It's pretty slow, so I'm wondering if anyone has suggestions on how to optimise the code.

Here's a video I recorded of the JohnsonScript version (it looks the same as the BBCSDL one) https://www.youtube.com/watch?v=EJ7Q6qNTnTs

PM
RichardRussell

Re: Glowballs demo

Post by RichardRussell »

p_m21987 wrote: Sat 14 Mar 2020, 15:26 It's pretty slow, so I'm wondering if anyone has suggestions on how to optimise the code.
Have you profiled it? I did, and it's apparent that the most time-consuming part is FNdist(). There are a couple of obvious optimisations there:
  • FNdist() involves a square root, but as you only actually use that value after you have compared it with r it would be better to compare the square of the distance with r^2 and only calculate the square root after you have ascertained that d^2 <= r^2.
  • FNdist() is only called from one place. Since function calls are expensive, it would be better to inline it.
So in code terms the changes amount to:

Code: Select all

  650 d = (b.x-xx)^2 + (b.y-yy)^2
  660 IF d>r*r:=0
  670 out=1-SQRd/r
I'd also suggest you run the Cross Reference utility because that would have alerted you to the fact that o% in FNglowballc() is never used so making it LOCAL just wastes time. You could also usefully delete {} where it's superfluous, so for example replace b{}.c&(0) with b.c&(0)

There's a fair bit of conversion going on between individual 8-bit R,G,B colour components and their 24-bit composite RGB representation. I suspect that some improvement in performance could be achieved by avoiding these conversions by working with separate R,G,B throughout.

As for jumping out of a loop with GOTO, may you be forgiven! It's a memory leak too so doubly awful:

Code: Select all

  280   MOUSEX%,Y%,B%:IFB%THENGOTO140
p_m21987
Posts: 177
Joined: Mon 02 Apr 2018, 21:51

Re: Glowballs demo

Post by p_m21987 »

RichardRussell wrote: Sun 15 Mar 2020, 00:27 Have you profiled it?
Ah I hadn't done that yet.
Thanks very much for the suggestions, especially the very nice detailed explanation about FNdist.

And also thank you for reminding me about the cross reference utility, I have to admit that I had forgotten to use it. I need to remember to do that more often.
RichardRussell wrote: Sun 15 Mar 2020, 00:27 As for jumping out of a loop with GOTO, may you be forgiven! It's a memory leak too so doubly awful
Hahahah! Ohhhh my god -- yeah, that was definitely a programming sin. I'll replace that with something more sensible, perhaps moving lines 140 to 230 into a procedure and then replacing the GOTO with a call to the procedure.

Maybe it would be interesting to explain why that part of the program is like that.
With my language JohnsonScript and its interpreter, while/endwhile are essentially just jumps to a certain position in the program (with some extra logic for checking loop conditions). This means that while/endwhile MUST be evenly balanced unlike in BASIC.
But as it doesn't use the stack to keep track of whether or not you are in a loop, you can safely jump out of a loop using 'goto' without leaking memory.
I didn't do a very thorough job of adapting it into BASIC (as I'm sure you can tell) so that part of the program has that memory leak as a result of its legacy/origins as a JohnsonScript program.

Anyway, thanks again Richard, I appreciate the reply and I'm glad to see you active on the forums again.

PM
RichardRussell

Re: Glowballs demo

Post by RichardRussell »

p_m21987 wrote: Sun 15 Mar 2020, 23:14perhaps moving lines 140 to 230 into a procedure and then replacing the GOTO with a call to the procedure.
Another possibility would be to put a REPEAT just before line 140, because that's where you want to jump back to:

Code: Select all

  135 REPEAT
  140   FORI%=0TOnumballs%
  150     balls{(I%)}.x=RND(res%)
then your 'main loop' can exit when the mouse button is pressed (or the touchscreen is tapped):

Code: Select all

  510     *refresh
  520     MOUSE X%,Y%,B%
  530   UNTIL B%
  535 UNTIL FALSE
That's probably how I would do it.
RichardRussell

Re: Glowballs demo

Post by RichardRussell »

p_m21987 wrote: Sun 15 Mar 2020, 23:14I'm glad to see you active on the forums again.
Only for a short time. The current 'everybody being moderated' situation is not sustainable, and the time it is taking for posts to be approved is getting longer and longer as their number rises. I don't know of any other comparable forum that operates a similar regime. The only option is going to be for me to leave again so that the moderation can be switched off, but I want to get the release of BB4W v6.13a out of the way before I do that.
p_m21987
Posts: 177
Joined: Mon 02 Apr 2018, 21:51

Re: Glowballs demo

Post by p_m21987 »

Richard is the greatest