follow path
BlitzMax Forums/BlitzMax Beginners Area/follow path
| ||
Hi ! In my game i want add satellites (red) to the player ship (white). (LMB to create a satellite). My problem : Red satellites don't follow exatly the player movement (see the white twist, cord, tie up (sorry for bad english : Systran translation ;-)) |
| ||
have a look at scotts flocking stuff in the tutorials |
| ||
scott code seems to be interesting but i've some difficulties to understand and adapt it to my purpose ! my satellite are not ennemies, just virtual ships at side of player ship. When it move they follow the player (Gradius). Is there an easier method to do this ? |
| ||
I havent had chance to look at scotts code in a little while, but I'm firly sure you can use it extend the behaviour so the satellites will fly around while staying seperated from you and each other... Scott is busy writing a tutorial I'm recon that once its finished I'm sure you'll see how to easly use it in your project rather than having to adapt it... |
| ||
You could do something like this:Local ddx# = joyx-s.x Local ddy# = joyy-s.y Local dist# = Sqr(ddx*ddx + ddy*ddy)+0.001 If dist > 150 ' too far away - move closer s.x = s.x + ddx/dist s.y = s.y + ddy/dist ElseIf dist < 64 ' too close - move away s.x = s.x - ddx/dist s.y = s.y - ddy/dist EndIf |
| ||
You could look at spring forces and simple create a virtual spring between the satellites and the ship, this way they would follow. A spring is simply a direction force which holds the following formula: Force = (PosShip - PosSatellite)(PosShip - PosSatellite) * k where k is the spring constant. After that you can simply apply this force vektor to the satellite. This means your satellite need a virtual weight (you can use this as a second constant to make different satellite type to react with different speeds while you keep k constant for all satellites) because accelerationSatellite = force / WeightSatellite then speedSatellite = speedSatellite + accelerationSatellite Note: speed, acceleration, position, force are all 2D vectors if you want to do it in 2D or 3D vectors if you do it in 3D |
| ||
Here is a small sample using scotts spritebeviors.Strict Import sas.spritebehaviors Graphics 800,600 Parameters.SeparationWeight= 8 Parameters.AlignmentWeight= 4 Parameters.CohesionWeight= 10 Parameters.ObstacleAvoidanceWeight=10 Parameters.WallAvoidanceWeight= 99 Parameters.WanderWeight = 50 Parameters.SeekWeight=5 Parameters.FleeWeight=1 Parameters.ArriveWeight=1 Parameters.PursuitWeight=1 Parameters.OffsetPursuitWeight=1 Parameters.InterposeWeight=1 Parameters.HideWeight=1 Parameters.EvadeWeight= 0.01 Parameters.FollowPathWeight=0.05 Parameters.ViewDistance = 25 Global colrad:Double = 32 Global world:GameWorld = GameWorld.Create(GraphicsWidth(),GraphicsHeight()) Delta.Start() Local Leader:Sprite = Sprite.CreateForSteering(Null, world, CreateVector(MouseX(),MouseY()), Rand(0,359), CreateVector(0,0), 1, 4, 4, 180, .5) Leader.SetCollisionRadius(colrad) Leader.GetSteering().ObstacleAvoidanceOn() ' Turn on the flocking behaviors Leader.SetWorldWrap(True) ' allow the prites to wrap from on side to the other of the screen world.AddVehicle(Leader) Local ld = 40 Local ax, ay ax = MouseX()- ld ay = MouseY()- ld While Not KeyDown(KEY_ESCAPE) Cls SetColor 255,255,255 Leader.SetPosition(MouseX(),MouseY()) If MouseDown(1) Then Local s1:sprite = Sprite.CreateForSteering(Null, world, CreateVector(ax,ay), Rand(0,359), CreateVector(0,0), 1, 4, 4, 180, .5) s1.SetCollisionRadius(colrad) s1.GetSteering().ObstacleAvoidanceOn() ' Turn on the flocking behaviors s1.GetSteering().FlockingOn() ' Turn on the flocking behaviors s1.GetSteering().SeekOn(Leader) s1.SetWorldWrap(True) ' allow the prites to wrap from on side to the other of the screen world.AddVehicle(s1) ax = MouseX()- ld ay = MouseY()- ld ld = ld + 20 FlushMouse() End If world.Update(Delta.Time()) ' update the agents world.Render() ' render the world Flip Delta.update() Wend You need to have the sas.spritebehaviors module installed from his side and build it. |
| ||
@all : many Thanks for your answers. @Dreamora : where is my error ? k and Weight values ? |
| ||
No, it was an error on my side, because I missed 2 things: 1. You need to define a length in which the spring does not push or pull 2. I gave you the formula for the spring energy, not force Here is the working one, sorry for making headache Strict Graphics 800,600 Global jposx Global jposy Global Satellites_list:TList = CreateList() Type TSatellite Field x# Field y# Field SpeedX# Field SpeedY# Function Create:TSatellite (x:Int, y:Int) Local n:TSatellite = New TSatellite n.x# = x n.y# = y ListAddLast Satellites_list, n Return n End Function Function Update() Local Weight# = 5.0 Local k# = 0.01 Local spring_neutral_length# = 8.0 For Local s:TSatellite = EachIn Satellites_list Local dx# = s.x - Float(jposx) Local dy# = s.y - Float(jposy) Local ForceX# = (spring_neutral_length-dx) * k Local ForceY# = (spring_neutral_length-dy) * k Local AccelerationX# = Float(ForceX# / Weight#) Local AccelerationY# = Float(ForceY# / Weight#) s.SpeedX# = s.SpeedX# + AccelerationX# s.SpeedY# = s.SpeedY# + AccelerationY# s.x# = s.x# + s.SpeedX# s.y# = s.y# + s.SpeedY# DebugLog s.x DebugLog s.y SetColor 255,0,0 DrawOval s.x,s.y, 20,20 Next End Function End Type While Not KeyDown(KEY_ESCAPE) Cls jposx = MouseX() jposy = MouseY() SetColor 255,255,255 DrawOval MouseX(), MouseY(), 10,10 TSatellite.Update() If MouseDown(1) Then Local s1:TSatellite = TSatellite.Create (MouseX()+10, MouseY()+10) FlushMouse() End If Flip Wend |
| ||
awesome dreamora. Is there a method to avoid the 'spring effect'. Imagine that the link between the player and the satellite is a rigid stick ! |