Page 1 of 1

Black hole - how to speed up?

Posted: Thu Jul 04, 2013 1:24 pm
by em_uk
Hi,

I finally think I have gotten my head around how vectors work and have managed to borrow some math calculations to do things like find angle, distance, direction and movement required. I have cobbled this "black hole simulator!" together.

How would I go about making this faster? Is it the use of circle? Should I be using pointers to speed things up? Sprites?

Code: Select all

;black hole - em_uk
;math codes borrowed from pb forums
;

#RAD = 0.0175
max=1000
Structure XY
  X.f
  Y.f
EndStructure

Structure T_PINGPONG
  min.i
  max.i
  counter.i
  direction.i
  delay.i
  inc.i
  val.i
EndStructure

Structure sVector
  c.XY
  angle.f
EndStructure

Structure player
  direction.sVector
  speed.f
  type.l
  state.l
  color.i
EndStructure

;Define pl1.player
Dim pl1.player(max)
Define pl2.player

Procedure addMovement( *V.sVector, speed.f )
  *V\c\x + Cos( *V\angle * #RAD ) * speed
  *V\c\y + Sin( *V\angle * #RAD ) * speed
EndProcedure

Procedure.f findangle(x1.f,y1.f,x2.f,y2.f) 
  
  Protected a.f,b.f,c.f,angle.f
  a.f = x1-x2 
  b.f = y2-y1 
  c.f = Sqr(a*a+b*b) 
  angle.f = ACos(a/c)*57.29577 
  If y1 < y2 
    angle=360.0-angle
  EndIf 
  
  ProcedureReturn angle.f
EndProcedure

Procedure.i PingPong (*p.T_PINGPONG)
  
  If *p\val>*p\delay
    If *p\direction = 0
      *p\direction = *p\inc
      *p\counter = *p\min
    Else
      *p\counter + *p\direction   
      If *p\counter =< *p\min 
        *p\direction = 0
      ElseIf *p\counter >= *p\max
        *p\direction = -*p\direction
      EndIf
      *p\val=0
    EndIf   
  Else
    *p\val + 1
  EndIf
  
  ProcedureReturn *p\counter
EndProcedure

Define PP1.T_PINGPONG 
Define PP2.T_PINGPONG 
Define PP3.T_PINGPONG 

pp1\min=0
pp1\max=699
pp1\delay=0
pp1\inc=1
pp1\delay=5

pp2\min=10
pp2\max=500
pp2\inc=12

pp3\min=20
pp3\max=20
pp3\inc=1
pp3\delay=250

For a = 0 To max
  
  pl1(a)\direction\c\x = Random(749)
  pl1(a)\direction\c\y = Random(599)
  pl1(a)\speed = Random(4,1)
  pl1(a)\state = PingPong(@pp3)
  pl1(a)\type=Random(5,1)
  If  pl1(a)\type>2
    r=100:g=100:b=100
  Else
    r=255:g=255:b=255
  EndIf
  
  pl1(a)\color=RGB(Random(r,1),g,Random(b,1))
Next

pl2\direction\c\x = 400
pl2\direction\c\y = 300

InitSprite() : InitKeyboard()

OpenWindow(0,0,0,800,600,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(0),0,0,800,600)
;OpenScreen(800,600,32,"")

Repeat
  
  If IsWindow(0)
    event=WindowEvent()
  EndIf
  
  StartDrawing(ScreenOutput())
  
  
  For a = 0 To max
    
    pl1(a)\direction\angle=findangle(pl2\direction\c\x,pl2\direction\c\y,pl1(a)\direction\c\x,pl1(a)\direction\c\y)
    
    addMovement(@pl1(a)\direction,pl1(a)\speed)
    
    If pl1(a)\direction\c\y>299 And pl1(a)\direction\c\y<301 Or pl1(a)\direction\c\x>400 And pl1(a)\direction\c\x<401;pl1(a)\type=0
      
      num=Random(4,1)
      If num=1
        pl1(a)\direction\c\x = -20 + Random(800)
        pl1(a)\direction\c\y = 0
        
      ElseIf num = 2
        pl1(a)\direction\c\x = -20+Random(800)
        pl1(a)\direction\c\y = 600
        
      ElseIf num = 3     
        pl1(a)\direction\c\x = 0
        pl1(a)\direction\c\y = -20 + Random(600)
        
      ElseIf num = 4
        pl1(a)\direction\c\x = 800
        pl1(a)\direction\c\y = -20 + Random(600)
        
      EndIf
      
      pl1(a)\type=Random(2,1)
      If  pl1(a)\type<2
        r=100:g=100:b=100
      Else
        r=255:g=255:b=255
      EndIf
      
      pl1(a)\color=RGB(Random(r,1),g,Random(b,1))
      
    EndIf
    
    Circle(pl1(a)\direction\c\x,pl1(a)\direction\c\y,pl1(a)\type,Pl1(a)\color)
    
  Next
  
  StopDrawing()
  
  pl2\direction\c\X=PingPong(@PP1)
  
  ExamineKeyboard()
  If event=#PB_Event_CloseWindow Or KeyboardPushed(#PB_Key_Escape)
    quit=1
  EndIf
  Delay(1)
  FlipBuffers()
  ClearScreen(#Black)
Until quit

Re: Black hole - how to speed up?

Posted: Thu Jul 04, 2013 2:17 pm
by Michael Vogel
The circle routine needs a lot of time, to see the difference, just change the "circle line" to...

Code: Select all

Box(pl1(a)\direction\c\x,pl1(a)\direction\c\y,pl1(a)\type,pl1(a)\type,Pl1(a)\color)
You could generate sprites or images in different sizes during at the beginning and then draw the appopriate image instead of drawing a circle.

But if you just need a quick and dirty solution, you could try use round boxes as well:

Code: Select all

		size=pl1(a)\type
		corner=size>>1
		RoundBox(pl1(a)\direction\c\x,pl1(a)\direction\c\y,size,size,corner,corner,Pl1(a)\color)

Re: Black hole - how to speed up?

Posted: Thu Jul 04, 2013 8:26 pm
by BasicallyPure
em_uk wrote:How would I go about making this faster? Is it the use of circle? Should I be using pointers to speed things up? Sprites?
What do you mean by faster? More efficient code or speed up the animation.

Michael's suggestion is a good one to improve the code efficiency and reduce cpu load.
Here are some others that might help some.
1. keep track of the angles in radians instead of degrees so you don't have to keep converting back and forth.
make a constant like this: #PIx2 = #PI * 2 and use that instead of 360. Remove the #Rad multiplication and
the *57.29577 multiplication.
2. use macros instead of procedures for addMovement() and findAngle(). Procedure calls are slower.
possibly like this:

Code: Select all

Macro addMovement()
   pl1(a)\direction\c\X + Cos(pl1(a)\direction\angle ) * pl1(a)\speed
   pl1(a)\direction\c\Y + Sin(pl1(a)\direction\angle ) * pl1(a)\speed
EndMacro

Code: Select all

#PIx2 = #PI * 2
Macro findAngle()
   u.f = pl2\direction\c\x - pl1(a)\direction\c\x
   v.f = pl1(a)\direction\c\y - pl2\direction\c\y
   angle.f = ACos(u / Sqr(u*u+v*v))
   If pl2\direction\c\y < pl1(a)\direction\c\y
      angle = #PIx2 - angle
   EndIf
   pl1(a)\direction\angle = angle
EndMacro
3. you don't need delay(1) in your loop. There is a delay intrinsic with FlipBuffers().
try removing the delay(1) and you will see the cpu load does not increase.

The animation speed will still be 60 frames/second even with the improved code efficiency so you won't
notice any speed increase unless your computer could not complete all calculations in your animation
loop in time to draw the next frame.

Re: Black hole - how to speed up?

Posted: Fri Jul 05, 2013 2:43 am
by em_uk
Sorry, "faster" was the wrong choice of word, "efficient" was intended.

I'm just breaking the ice with these type of calculations. I've borrowed some from other sources and built on that. I wanted the Procedures to be reusable in code I write in the future, so having it modular rather than hard coded variable macros seemed the more sensible approach however, obviously if it I am trying to get the best performance out of the code then macros are the way to go.

I've amended my code to now use radians rather the having to recalculate and convert.

Much appreciated for the input! :) I'm having a lot of fun with vectors and the trig that goes with it. When I was putting this together last night, I didn't think I would succeed after many failed attempts!

:lol:

Re: Black hole - how to speed up?

Posted: Fri Jul 05, 2013 3:16 am
by buddymatkona
Nice looking black hole effect. :)

If you keep expanding this idea, how about taking advantage of threads?
Let Main handle the display. Meanwhile Thread1 can calculate orbital position vectors for stars in a cluster. At the same time, Thread2 could add an inward spiral componet for each star toward the (approaching?) black hole.
With a master/slave setup, Main would signal others to do all the calculations in shared memory for Frame(i+1) before drawing Frame(i). Only if CPU usage per thread is high would you need a multi-core to get help from threads.

Re: Black hole - how to speed up?

Posted: Fri Jul 05, 2013 4:45 pm
by em_uk
Interesting idea!

I'm afraid my linear trig knowledge is far from complete, I could implement the threads but I will have to study some more math to get the right effect.

I would suppose as the star approaches the center/target point when it hits a certain value to then have its x & y axes affected by a sin/cos calculation?

Re: Black hole - how to speed up?

Posted: Fri Jul 05, 2013 5:14 pm
by wilbert
For the angle, you can use ATan2

Code: Select all

Procedure.f findangle(x1.f,y1.f,x2.f,y2.f) 
  ProcedureReturn ATan2(x2-x1, y2-y1) * 57.29577 + 180
EndProcedure

Re: Black hole - how to speed up?

Posted: Sat Jul 06, 2013 1:39 pm
by said
nice demo em_uk :lol:
Mr Wilbert, your tips are very valuable ... thanks :)

Re: Black hole - how to speed up?

Posted: Mon Jul 08, 2013 1:20 am
by em_uk
Indeed, did not Atan2 could do that. Thanks wilbert!

:lol: :lol:

Re: Black hole - how to speed up?

Posted: Mon Jul 08, 2013 12:32 pm
by em_uk
Ok ATan2 doesn't give the same results.

The outer part of the screen, the stars fly in, then the second half (inner part) they seem to buzz around....