Enemy motion path
BlitzMax Forums/BlitzMax Programming/Enemy motion path
| ||
Hi, I am just playing about with a side scrolling shooter and am working on the motion paths of the enemies. I can get them to travel in a wave motion from Right to Left using COSINE, and I can get them to track towards the player ship based on its position on the screen. But how would I go about doing a more complex motion path? One of the things I wanted to do was have an enemy appear on the right of the screen, travel straight across for a short distance, then do a complete circle back in roughly in the middle of the screen, and finish by heading toward the player ship. Any tips would be much appreciated |
| ||
didnt someone just release a path spline editor? |
| ||
This i belive |
| ||
One way to create paths is to record them. You could write a simple path creator that allows you to draw the path with the mouse. Alternatively, you could used a list that contains instructions on how to move the object and simply process it sequentially. i.e. Move 200,200 'move in a straight line to 200,200 Circle 250 ' move in a circle with a radius of 250 (using current position as the starting point. Move 900,300 ' move in a straight line to 900,300 exit 'move to the nearest edge and then remove the enemy |
| ||
Great - thanks for the quick responses guys. This path spline editor looks to be just the ticket! - I should pay more attention to what gets posted on the site ;) And Perturbatio, thanks for your tips too. |
| ||
Check this out.. Made by SCOUSE (not me)Type vec2d Field x#,Y# Method set(xx#,yy#) x=xx Y=yy End Method Method add(v:vec2d) x:+ v.x Y:+ v.Y End Method Method sub(v:vec2d) x:- v.x Y:- v.Y End Method Method mulS(f#) x:* f Y:* f End Method Method negate() x= -x Y= -Y End Method Method Copy(s:vec2d) x=s.x Y=s.Y End Method Method mag:Float(v:vec2d) Local xx#,yy# xx=v.x - x yy=v.Y - Y Return sqr(xx*xx + yy*yy) End Method End Type Type cSpline Global cSplineList:TList Field pnt:vec2d[] Field segLen:Float[] 'the length of each segment Field segPerc:Float[] 'What percentage of the overall length, this segment takes up Field totalLength:Float Field outMulti:Float Field inMulti:Float Field link:TLink Method New() If not cSplineList Then cSplineList = CreateList() link = ListAddLast(cSplineList,Self) End Method Function Create:cSpline(pntCount = 4) If pntCount<4 Then pntCount = 4 Local c:cSpline = New cSpline c.pnt = New vec2d[pntCount] For Local i:Int = 0 To pntCount-1 c.pnt[i] = New vec2d Next 'segments are always the pointcount - 3 ' 1....2----3----4----5----6....7 <7 points, 4 segments c.segLen = New Float[pntCount-3] c.segPerc = New Float[pntCount-3] c.outMulti = 0.5 c.inMulti = 0.5 Return c End Function 'Adds a point to this curve. Default index of '-1 will add the point to the end Method AddPoint(x:Float, Y:Float, index:Int = -1) If index > pnt.length Then index = -1 If index = -1 pnt = pnt[..pnt.length+1] pnt[pnt.length-1] = New vec2d pnt[pnt.length-1].set(x,Y) segPerc = segPerc[..segPerc.length+1] segLen = segLen[..segLen.length+1] Else End If UpdateCurve() End Method 'Makes a cSpline appear closed Method Close(mergeEnds:Byte = False) If pnt.length < 6 Return If mergeEnds 'average the start and end points Local v:vec2d = New vec2d v.Copy(pnt[pnt.length-2]) v.sub(pnt[1]) v.mulS(.5) pnt[1].x:+ v.x pnt[1].Y:+ v.Y pnt[pnt.length-2].x:- v.x pnt[pnt.length-2].Y:- v.Y End If pnt[pnt.length-2].Copy(pnt[1]) pnt[pnt.length-1].Copy(pnt[2]) pnt[0].Copy(pnt[pnt.length-3]) UpdateCurve() End Method Method DrawCurve(steps:Int = 100) SetScale 1,1 SetLineWidth 1 Local i:Int,j:Int Local s:Float Local t:Float = 1.0 / steps Local Loop:Float Local sX:Float = 0, sY:Float = 0 Local lX:Float = 0, lY:Float = 0 lX = pnt[1].x lY = pnt[1].Y For i = 0 To pnt.length-4 While Loop <= 1.0 For j = 0 To 3 sX:+ interp(j,Loop) * pnt[i+j].x sY:+ interp(j,Loop) * pnt[i+j].Y Next DrawLine lX,lY,sX,sY lX = sX lY = sY sX = 0 sY = 0 Loop:+ t Wend Loop = 0 Next End Method Method UpdateCurve(steps:Int=500) Local i:Int,j:Int Local cLen:Float = 0 Local t:Float = 1.0 / steps Local delta:Float = 0 Local lastX#=0,lastY#=0 Local tX#=0,tY#=0 Local sX#=0,sY#=0 totalLength = 0 For i = 0 To pnt.length-4 lastX = pnt[i+1].x lastY = pnt[i+1].Y While delta < 1.0 'get the position at point 'delta' For j = 0 To 3 sX:+ interp(j,delta) * pnt[i+j].x sY:+ interp(j,delta) * pnt[i+j].Y Next tX = sX - lastX tY = sY - lastY 'Add the length of this step cLen:+ sqr(tX*tX + tY*tY) 'Record last position lastX = sX lastY = sY sX = 0 sY = 0 delta:+ t Wend segLen[i] = cLen totalLength:+ cLen cLen = 0 delta = 0 Next 'Update segment percentages For i = 0 To segLen.length-1 segPerc[i] = segLen[i] / totalLength Next End Method Method GetHeading:Float(Pos:Float) Local ahead:Float Local ax:Float,ay:Float Local bx:Float,by:Float Local angle:Float If Pos < .99 ahead = Pos + .01 Else ahead = Pos - .01 End If Local a:vec2d = GetPosition(Pos) Local b:vec2d = GetPosition(ahead) a.sub(b) angle = ATan2(-a.x,a.Y) If Pos < .99 Return angle Else Return angle+180 End If End Method Method PlotCurve(steps:Int = 100) SetColor 0,255,0 SetScale 1,1 Local p:vec2d Local d:Float = 0 Local stp:Float = 1.0 / steps While d <= 1.0 p = GetPosition(d) DrawOval p.x-1,p.Y-1,2,2 d:+ stp Wend SetColor 255,255,255 End Method Method GetPosition:vec2d(tPerc:Float) If tPerc>1 Then tPerc = 1 If tPerc<0 Then tPerc = 0 Local p:vec2d = New vec2d Local i:Int,j:Int Local tempTotal:Float = 0 Local tempPerc:Float = 0 'find which segment the target percentage is in For i = 0 To segPerc.length-1 tempTotal:+ segPerc[i] If tPerc = tempTotal p.x = pnt[i+1].x p.Y = pnt[i+1].Y Return p Else If tPerc < tempTotal Exit End If tempPerc:+ segPerc[i] Next ' i = the segment in which the target percentage falls into 'transform the target 'global' percentage, into a local segment percentage Local getPerc# = (tPerc - tempPerc) * (1.0 / segPerc[i]) For j = 0 To 3 p.x:+ interp(j,getPerc) * pnt[i+j].x p.Y:+ interp(j,getPerc) * pnt[i+j].Y Next posSeg = i+1 Return p End Method Method interp:Float(i:Int, t:Float) Select i Case 0 Return ( (-t+2) * t - 1) * t * .5 Case 1 Return (( (3*t-5) *t) * t + 2) * .5 Case 2 Return ( (-3*t+4) * t + 1) * t * .5 Case 3 Return ( (t-1) * t^2) * .5 Default Return 0 End Select End Method End Type '----------------------------------------------------------------------------------- MAIN PROGRAM Global cpm#=.5,pm#=.5 'Create a curve with 7 points (first and last are always ghost control points only!) Local c:cSpline = cSpline.Create(7) c.pnt[0].set(100,200) c.pnt[1].set(200,400) c.pnt[2].set(300,200) c.pnt[3].set(400,400) c.pnt[4].set(500,200) c.pnt[5].set(600,400) c.pnt[6].set(700,200) c.UpdateCurve() Graphics 800,600,0 'make a sprite Local player:TImage = CreateImage(32,32,1,DYNAMICIMAGE|MASKEDIMAGE) SetImageHandle player,16,16 DrawOval 0,0,32,32 SetLineWidth 3 SetColor 255,0,0 DrawLine 16,0,10,6 DrawLine 16,0,22,6 DrawLine 10,6,22,6 GrabImage player,0,0,0 SetColor 255,255,255 Local curPoint=0 Local Pos:vec2d = New vec2d Local playerPos# = 0 Local time% Local doPlot:Byte = False, doCurve:Byte = True Local Last:vec2d = New vec2d Last.Copy(c.pnt[1]) Global posSeg:Int = 0 While not KeyHit(KEY_ESCAPE) Cls If KeyDown(KEY_1) curPoint = 0 If KeyDown(KEY_2) curPoint = 1 If KeyDown(KEY_3) curPoint = 2 If KeyDown(KEY_4) curPoint = 3 If KeyDown(KEY_5) curPoint = 4 If KeyDown(KEY_6) curPoint = 5 If KeyDown(KEY_7) curPoint = 6 If KeyDown(KEY_8) curPoint = 7 If KeyDown(KEY_9) curPoint = 8 If KeyDown(KEY_0) curPoint = 9 'curve multiplier adjustment If KeyDown(KEY_LEFT) c.outMulti:+ .01 If KeyDown(KEY_RIGHT) c.outMulti:- .01 If KeyDown(KEY_UP) c.inMulti:- .01 If KeyDown(KEY_DOWN) c.inMulti:+ .01 If KeyHit(KEY_SPACE) Then c.Close(True) If KeyHit(KEY_P) Then doPlot = not doPlot If KeyHit(KEY_C) Then doCurve = not doCurve If MouseDown(1) c.pnt[curPoint].set(MouseX(),MouseY()) c.UpdateCurve() End If If MouseHit(2) c.AddPoint(MouseX(),MouseY()) End If Local n:Int For n = 0 To c.pnt.length-1 If n=curPoint SetScale 6,6 SetColor 100,100,100 DrawOval c.pnt[n].x - 7,c.pnt[n].Y - 7,3,3 End If If n=0 or n=c.pnt.length-1 SetColor 0,255,0 Else SetColor 255,0,0 End If SetScale 3,3 DrawOval c.pnt[n].x - 2,c.pnt[n].Y - 2,2,2 SetScale 1,1 SetColor 255,255,255 DrawText "p"+(n+1),c.pnt[n].x,c.pnt[n].Y+2 Next SetColor 255,255,255 SetScale 1,1 DrawText "Press 1,2,3,4,5,6 or 7 to select point, 'p' & 'c' toggle plot/curve drawing",0,0 DrawText "Current move point: "+(curPoint+1),0,20 DrawText "Approx length of curve: "+c.totalLength,0,40 'For Local i:Int = 0 To c.segPerc.length-1 ' DrawText "Segment percentage "+(i+1)+" = : "+c.segPerc[i],0,80+(i*14) 'Next Pos = c.GetPosition(playerPos) DrawText Int(100*playerpos)+"%",Pos.x,Pos.Y+20 SetRotation c.GetHeading(playerpos) DrawImage player,Pos.x,Pos.Y SetRotation 0 If doCurve Then c.DrawCurve(10) '10 lines per segment If doPlot Then c.PlotCurve(50) Flip FlushMem playerPos:+ .005'.0025 If playerPos > 1.0 Then playerPos = 0 Wend copy paste all that and you'll have the coolest spline ever. only problem is I cannot comprehend his code (its seems to be way too complex) any chance someone can make a much simpler version of the "cspline?" so I can disect it and add this to my editor? |