Black hole - how to speed up?

Just starting out? Need help? Post your questions and find answers here.
User avatar
em_uk
Enthusiast
Enthusiast
Posts: 366
Joined: Sun Aug 08, 2010 3:32 pm
Location: Manchester UK

Black hole - how to speed up?

Post 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
----

R Tape loading error, 0:1
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Black hole - how to speed up?

Post 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)
User avatar
BasicallyPure
Enthusiast
Enthusiast
Posts: 539
Joined: Thu Mar 24, 2011 12:40 am
Location: Iowa, USA

Re: Black hole - how to speed up?

Post 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.
BasicallyPure
Until you know everything you know nothing, all you have is what you believe.
User avatar
em_uk
Enthusiast
Enthusiast
Posts: 366
Joined: Sun Aug 08, 2010 3:32 pm
Location: Manchester UK

Re: Black hole - how to speed up?

Post 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:
----

R Tape loading error, 0:1
buddymatkona
Enthusiast
Enthusiast
Posts: 252
Joined: Mon Aug 16, 2010 4:29 am

Re: Black hole - how to speed up?

Post 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.
User avatar
em_uk
Enthusiast
Enthusiast
Posts: 366
Joined: Sun Aug 08, 2010 3:32 pm
Location: Manchester UK

Re: Black hole - how to speed up?

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

R Tape loading error, 0:1
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Black hole - how to speed up?

Post 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
Windows (x64)
Raspberry Pi OS (Arm64)
said
Enthusiast
Enthusiast
Posts: 342
Joined: Thu Apr 14, 2011 6:07 pm

Re: Black hole - how to speed up?

Post by said »

nice demo em_uk :lol:
Mr Wilbert, your tips are very valuable ... thanks :)
User avatar
em_uk
Enthusiast
Enthusiast
Posts: 366
Joined: Sun Aug 08, 2010 3:32 pm
Location: Manchester UK

Re: Black hole - how to speed up?

Post by em_uk »

Indeed, did not Atan2 could do that. Thanks wilbert!

:lol: :lol:
----

R Tape loading error, 0:1
User avatar
em_uk
Enthusiast
Enthusiast
Posts: 366
Joined: Sun Aug 08, 2010 3:32 pm
Location: Manchester UK

Re: Black hole - how to speed up?

Post 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....
----

R Tape loading error, 0:1
Post Reply