Homing example

Share your advanced PureBasic knowledge/code with the community.
techjunkie
Addict
Addict
Posts: 1126
Joined: Wed Oct 15, 2003 12:40 am
Location: Sweden
Contact:

Homing example

Post by techjunkie »

Code updated For 5.20+

I just had to convert a cool "homing example" by Jeppe Nielsen from BlitzBasic to PureBasic.

It isn't perfect in any way! I did a fast conversion and it can improved in a 1000 ways.

but here it is...

Code: Select all

; Homing example, by Jeppe Nielsen 2003
;
; Original code from BlitzBasic Community
; http://www.blitzbasic.com
;
; Converted from BlitzBasic to PureBasic by Techjunkie 2004

Global playerx.l
Global playery.l
Global distance.f
Global fcolor.l

distance = 100

Structure enemy
  x.l
  y.l
  vx.f
  vy.f
  ax.f
  ay.f
  vmax.f
  amax.f
EndStructure

Global e.enemy
Global Dim e.enemy(1000)

Global enemy_count.l
enemy_count = 0

Procedure enemynew(x.f, y.f, vmax.f, amax.f)
  
  e(enemy_count)\x = x
  e(enemy_count)\y = y
  
  e(enemy_count)\vmax = vmax
  e(enemy_count)\amax = amax
  
  enemy_count + 1
  
EndProcedure

Procedure enemyupdate()
  
  For i = 0 To enemy_count
    
    dx.f = (playerx - e(i)\x)
    dy.f = (playery - e(i)\y)
    
    l.f = Sqr(dx.f * dx.f + dy.f * dy.f)
    
    dx.f =( dx.f / l.f) * e(i)\amax
    dy.f = (dy.f / l.f) * e(i)\amax
    
    ;if close enough escape target
    If l.f <= distance.f
      dx.f = -dx.f
      dy.f = -dy.f
    EndIf
    
    ;check against all other enemies, to avoid them
    dxx.f = 0
    dyy.f = 0
    co = 0
    
    For j = 0 To enemy_count
      If j <> i 
        dex.f = (e(i)\x - e(j)\x)
        dey.f = (e(i)\y - e(j)\y)
        
        l.f = Sqr(dex.f * dex.f + dey.f * dey.f)
        
        dxx.f = dxx.f + (dex.f / l.f) * e(i)\amax
        dyy.f = dyy.f + (dey.f / l.f) * e(i)\amax
        
        co + 1
      EndIf
    Next
    
    dxx.f = dxx.f / co
    dyy.f = dyy.f / co
    
    dx.f = (dx.f + dxx.f) / 2.0
    dy.f = (dy.f + dyy.f) / 2.0
    
    e(i)\ax = e(i)\ax + dx.f
    e(i)\ay = e(i)\ay + dy.f
    
    acc.f = Sqr(e(i)\ax * e(i)\ax + e(i)\ay * e(i)\ay)
    
    ;Check if current acceleration is more than allowed
    If acc.f > e(i)\amax
      e(i)\ax = (e(i)\ax / acc.f) * e(i)\amax
      e(i)\ay = (e(i)\ay / acc.f) * e(i)\amax
    EndIf
    
    e(i)\vx = e(i)\vx + e(i)\ax
    e(i)\vy = e(i)\vy + e(i)\ay
    
    vel.f = Sqr(e(i)\vx * e(i)\vx + e(i)\vy * e(i)\vy)
    
    ;Check if current velocity is more than allowed
    If vel.f > e(i)\vmax
      e(i)\vx = (e(i)\vx / vel.f) * e(i)\vmax
      e(i)\vy = (e(i)\vy / vel.f) * e(i)\vmax
    EndIf
    
    ; add velocity to position
    e(i)\x = e(i)\x + e(i)\vx
    e(i)\y = e(i)\y + e(i)\vy
    
  Next
EndProcedure

If InitMouse() = 0 Or InitSprite() = 0 Or InitKeyboard() = 0
  MessageRequester("Error", "Can't open DirectX", 0)
  End
EndIf

If (OpenScreen(800, 600, 16, "Homing Example") = 0)
  MessageRequester("Error", "Impossible to open a 800*600 16 bit screen",0)
  End
EndIf

;create ten enemies at random locations
For i = 1 To 10   
  enemynew(Random(800.0), Random(600.0), (4.0*Random(1000)/1000) + 0.5, (0.08*Random(1000)/1000) + 0.02)
Next

;     BackColor(RGB(0, 0, 0))
click = 0
fcolor = RGB(255,255,255)

Repeat
  FlipBuffers()
  ClearScreen(RGB(0,0,0))
  
  ExamineKeyboard()
  ExamineMouse()     
  
  StartDrawing(ScreenOutput())
  DrawingMode(2|4)
  text.s = "Enemies = " + Str(enemy_count)
  ;         Locate(10,10)
  ;         DrawText(text)
  ;         Locate(10,30)
  ;         DrawText("Move player with mouse")
  ;         Locate(10,50)
  ;         DrawText("LMB - Resize allowed distance to player")
  ;         Locate(10,70)
  ;         DrawText("RMB - Add enemies")
  ;         Locate(10,90)
  ;         DrawText("ESC - Quit")
  StopDrawing()
  
  If click = 0
    playerx = MouseX()
    playery = MouseY()
  EndIf
  
  If (MouseButton(1) And click = 0)
    click = 1
    clickx = MouseX()
    clicky = MouseY()
  EndIf
  
  If (MouseButton(1) And click = 1)
    dx = (MouseX() - clickx)
    dy = (MouseY() - clicky)
    
    distance = Sqr(dx * dx + dy * dy)
  EndIf
  
  If (MouseButton(1) = 0 And click = 1)
    click = 0
  EndIf
  
  If (MouseButton(2))
    If (enemy_count < 1000)
      enemynew(Random(800.0), Random(600.0), 2.5, (0.08 * Random(1000)/1000) + 0.02)
    EndIf
  EndIf
  
  enemyupdate()
  
  StartDrawing(ScreenOutput())
  DrawingMode(2|4)
  For i = 0 To enemy_count
    Box(e(i)\x - 3, e(i)\y - 3, 6, 6, fcolor)
  Next
  Box(playerx - distance, playery - distance, 10, 10, fcolor)
  Circle(playerx - distance , playery - distance, distance * 2, fcolor) 
  StopDrawing()
  
Until KeyboardPushed(#PB_Key_Escape)
End


Image
(\__/)
(='.'=) This is Bunny. Copy and paste Bunny into your
(")_(") signature to help him gain world domination.
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Post by Dare2 »

Neat. :)

Next .. BOIDs!
merendo
Enthusiast
Enthusiast
Posts: 449
Joined: Sat Apr 26, 2003 7:24 pm
Location: Germany
Contact:

Post by merendo »

And... umm... what is this supposed to be? :roll:
The truth is never confined to a single number - especially scientific truth!
techjunkie
Addict
Addict
Posts: 1126
Joined: Wed Oct 15, 2003 12:40 am
Location: Sweden
Contact:

Post by techjunkie »

merendo wrote:And... umm... what is this supposed to be? :roll:
Have you run it?

It is an example of homing physics that allow "enemies" to chase player, with velocity and acceleration.

Can be used in games for example.
Image
(\__/)
(='.'=) This is Bunny. Copy and paste Bunny into your
(")_(") signature to help him gain world domination.
merendo
Enthusiast
Enthusiast
Posts: 449
Joined: Sat Apr 26, 2003 7:24 pm
Location: Germany
Contact:

Post by merendo »

Yes, sure i have run it :)

However, i thought the whole source was a little game of itself. Well, well....
The truth is never confined to a single number - especially scientific truth!
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

It could be called "Spermatozoid simulation" :P
Num3
PureBasic Expert
PureBasic Expert
Posts: 2812
Joined: Fri Apr 25, 2003 4:51 pm
Location: Portugal, Lisbon
Contact:

Post by Num3 »

Psychophanta wrote:It could be called "Spermatozoid simulation" :P
:mrgreen:

The big square kind of looks like Fred....

It's a mob going wild trying to catch him :!:
techjunkie
Addict
Addict
Posts: 1126
Joined: Wed Oct 15, 2003 12:40 am
Location: Sweden
Contact:

Post by techjunkie »

Psychophanta wrote:It could be called "Spermatozoid simulation" :P
*LOL*

Hmmmm... Interesting idea... I've made a version with sprites... Just change the boxes to something "else"...

:lol:
Image
(\__/)
(='.'=) This is Bunny. Copy and paste Bunny into your
(")_(") signature to help him gain world domination.
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Post by Dare2 »

lol. :)
techjunkie
Addict
Addict
Posts: 1126
Joined: Wed Oct 15, 2003 12:40 am
Location: Sweden
Contact:

Post by techjunkie »

Converted to PB4.x.

Code: Select all

; Homing example, by Jeppe Nielsen 2003 
; 
; Original code from BlitzBasic Community 
; http://www.blitzbasic.com 
; 
; Converted from BlitzBasic to PureBasic by Techjunkie 2004
; Converted from PureBasic 3.x to 4.x 2006-08-30

Global playerx.l 
Global playery.l 
Global distance.f 
Global fcolor.l 

distance = 100 

Structure enemy 
  x.l 
  y.l 
  vx.f 
  vy.f 
  ax.f 
  ay.f 
  vmax.f 
  amax.f 
EndStructure 

Global e.enemy 
Global Dim e.enemy(1000) 

Global enemy_count.l 
enemy_count = 0 

Procedure enemynew(x.f, y.f, vmax.f, amax.f) 

  e(enemy_count)\x = x 
  e(enemy_count)\y = y 

  e(enemy_count)\vmax = vmax 
  e(enemy_count)\amax = amax 

  enemy_count + 1 
  
EndProcedure 

Procedure enemyupdate() 

  For i = 0 To enemy_count 

    dx.f = (playerx - e(i)\x) 
    dy.f = (playery - e(i)\y) 

    l.f = Sqr(dx.f * dx.f + dy.f * dy.f) 

    dx.f = (dx.f / l.f) * e(i)\amax 
    dy.f = (dy.f / l.f) * e(i)\amax 

;if close enough escape target 
    If l.f <= distance.f 
      dx.f = -dx.f 
      dy.f = -dy.f 
    EndIf 

;check against all other enemies, to avoid them 
    dxx.f = 0 
    dyy.f = 0 
    co = 0 

    For j = 0 To enemy_count 
      If j <> i  
        dex.f = (e(i)\x - e(j)\x) 
        dey.f = (e(i)\y - e(j)\y) 
  
        l.f = Sqr(dex.f * dex.f + dey.f * dey.f) 
  
        dxx.f = dxx.f + (dex.f / l.f) * e(i)\amax 
        dyy.f = dyy.f + (dey.f / l.f) * e(i)\amax 
  
        co + 1 
      EndIf 
    Next 

    dxx.f = dxx.f / co 
    dyy.f = dyy.f / co 

    dx.f = (dx.f + dxx.f) / 2.0 
    dy.f = (dy.f + dyy.f) / 2.0 

    e(i)\ax = e(i)\ax + dx.f 
    e(i)\ay = e(i)\ay + dy.f 

    acc.f = Sqr(e(i)\ax * e(i)\ax + e(i)\ay * e(i)\ay) 

;Check if current acceleration is more than allowed 
    If acc.f > e(i)\amax 
      e(i)\ax = (e(i)\ax / acc.f) * e(i)\amax 
      e(i)\ay = (e(i)\ay / acc.f) * e(i)\amax 
    EndIf 

    e(i)\vx = e(i)\vx + e(i)\ax 
    e(i)\vy = e(i)\vy + e(i)\ay 

    vel.f = Sqr(e(i)\vx * e(i)\vx + e(i)\vy * e(i)\vy) 

;Check if current velocity is more than allowed 
    If vel.f > e(i)\vmax 
      e(i)\vx = (e(i)\vx / vel.f) * e(i)\vmax 
      e(i)\vy = (e(i)\vy / vel.f) * e(i)\vmax 
    EndIf 

; add velocity to position 
    e(i)\x = e(i)\x + e(i)\vx 
    e(i)\y = e(i)\y + e(i)\vy 

  Next 
EndProcedure 

If InitMouse() = 0 Or InitSprite() = 0 Or InitKeyboard() = 0 
  MessageRequester("Error", "Can't open DirectX", 0) 
  End 
EndIf 

If (OpenScreen(800, 600, 16, "Homing Example") = 0) 
  MessageRequester("Error", "Impossible to open a 800*600 16 bit screen",0) 
  End 
EndIf 

;create ten enemies at random locations 
For i = 1 To 10    
  enemynew(Random(800.0), Random(600.0), (4.0*Random(1000)/1000) + 0.5, (0.08*Random(1000)/1000) + 0.02) 
Next 

click = 0 
fcolor = RGB(255,255,255) 

Repeat 
  FlipBuffers() 
  ClearScreen(RGB(0,0,0)) 
  
  ExamineKeyboard() 
  ExamineMouse()      
  
  StartDrawing(ScreenOutput()) 
    DrawingMode(2|4)
    BackColor(RGB(0,0,0))  
    text.s = "Enemies = " + Str(enemy_count) 
    DrawText(10,10,text, fcolor) 
    DrawText(10,30,"Move player with mouse", fcolor) 
    DrawText(10,50,"LMB - Resize allowed distance to player", fcolor) 
    DrawText(10,70,"RMB - Add enemies", fcolor) 
    DrawText(10,90,"ESC - Quit", fcolor) 
  StopDrawing() 

  If click = 0 
    playerx = MouseX() 
    playery = MouseY() 
  EndIf 

  If (MouseButton(1) And click = 0) 
    click = 1 
    clickx = MouseX() 
    clicky = MouseY() 
  EndIf 

  If (MouseButton(1) And click = 1) 
    dx = (MouseX() - clickx) 
    dy = (MouseY() - clicky) 
  
    distance = Sqr(dx * dx + dy * dy) 
  EndIf 

  If (MouseButton(1) = 0 And click = 1) 
    click = 0 
  EndIf 

  If (MouseButton(2)) 
    If (enemy_count < 1000) 
      enemynew(Random(800.0), Random(600.0), 2.5, (0.08 * Random(1000)/1000) + 0.02) 
    EndIf 
  EndIf 

  enemyupdate() 
  
  StartDrawing(ScreenOutput()) 
    DrawingMode(2|4) 
    For i = 0 To enemy_count 
      Box(e(i)\x - 3, e(i)\y - 3, 6, 6, fcolor) 
    Next 
    Box(playerx - distance, playery - distance, 10, 10, fcolor) 
    Circle(playerx - distance , playery - distance, distance * 2, fcolor)  
  StopDrawing() 

Until KeyboardPushed(#PB_Key_Escape) 
End 
Image
(\__/)
(='.'=) This is Bunny. Copy and paste Bunny into your
(")_(") signature to help him gain world domination.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

That works excellently techjunkie, thanks for sharing it. It can form the basis for many game ideas.
BERESHEIT
techjunkie
Addict
Addict
Posts: 1126
Joined: Wed Oct 15, 2003 12:40 am
Location: Sweden
Contact:

Post by techjunkie »

netmaestro wrote:That works excellently techjunkie, thanks for sharing it. It can form the basis for many game ideas.
Thanks! :D It's rather cool, but thank Jeppe Nielsen too. He's done a lot of cool stuff in BlitzBasic. I'm about to convert more examples.
Image
(\__/)
(='.'=) This is Bunny. Copy and paste Bunny into your
(")_(") signature to help him gain world domination.
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

Thanks - this is neat. Maybe I can use it to get my son interested in programming games instead of just playing them :)

cheers
Post Reply