Object movement question

BlitzPlus Forums/BlitzPlus Programming/Object movement question

Valgar(Posted 2004) [#1]
Hi to all.
I'm making some movement function (i call them when i whant the alien in my game move...);now i have some basic movement (like straight direction[easy to code],zig-zag[easy to code,it's basically two straight direction at once :P] but if i want to implement some complex movement (like clockwise move)or some path movement.....what's the best way to do this?
I ear of precalculated table and so on....but i don't figured out how to do it yet :(
Is also difficult to make some sort of line movement like this?(in precalculated path,like i draw a line and they follow that line)
Example:follow this path from O to X

O------------
\ |---------|
\ | |
\ | |
---------- |
|
|
|
|----------------|
|
|
X

Thanks


Mr Brine(Posted 2004) [#2]
Hi

To move something in a circular motion, try somat like this:

; ----------------------------------------------------------

Graphics 640, 480, 32, 2

Global x#, y#, t#

Repeat

Cls
x = 100 * Sin(t)
y = 100 * Cos(t)
Text 320 + x, 240 + y, "@"
Flip
t = t + 1

Until MouseHit(1) = True

; ----------------------------------------------------------

to change the direction and speed of the rotation adjust the code:

t = t + 1


to change the shape of the circle motion adjust the '100 *' bit of code:

x = 100 * Sin(t)
y = 100 * Cos(t)


Hope this helps

Mr Brine


Mr Brine(Posted 2004) [#3]
Hi Again

this code moves things along a line, click any where in the window and the "@" symbol will move their. escape quits

Notes:

- SQR function is pretty processor intensive.
- to change the speed of the movement alter the speed parameter of the calcgradient function, in the program loop.


;---------------------------------------------------------------------

Graphics 640, 480, 32, 2


Type gradient

Field sx#, sy#
Field fx#, fy#
Field xg#, yg#

End Type



Global g.Gradient = New Gradient



Function CalcGradient(fx, fy, speed#)

Local xd#, yd#
Local length#

g\fx = fx
g\fy = fy

xd = fx - g\sx
yd = fy - g\sy

length = Sqr(Float(xd * xd + yd * yd))

g\xg = xd / length * speed
g\yg = yd / length * speed

End Function



Function AddGradient()

g\sx = g\sx + g\xg
g\sy = g\sy + g\yg

End Function



Repeat

Cls

If(MouseHit(1) = True)

CalcGradient(MouseX(), MouseY(), 1)

Else

Text g\sx, g\sy, "@"
AddGradient()

End If

Flip

Until KeyHit(1) = True



;---------------------------------------------------------------------


hope this helps also

Mr Brine


Valgar(Posted 2004) [#4]
Thanks

Yes,for circular movements only works(but i see that flicker too much....the object make jump instead of pixel movement..)
Here's the code of your suggestion:

Graphics 640, 480, 32, 2
player=LoadImage("jet6.TGA")
Global x#, y#, t#

Repeat

Cls
x = 100 * Sin(t)
y = 100 * Cos(t)
DrawImage player,50+x,200+y
Flip
t = t + 1

Until MouseHit(1) = True


if you run it do you understand what i'm saying (sorry for bad translation)


Valgar(Posted 2004) [#5]
I have made this code copying the Krylar code in tutorials...but don't work!
And i think it's related to types...and types variables but i don't know why,what and where :)
Here's the code:

(\code)
Graphics 640,480,32,1
SetBuffer BackBuffer()

giocatore=LoadImage("jet6.TGA")
Global nemico=LoadImage("alien1.TGA")
Global missile=LoadImage("missile.BMP")

frametimer=CreateTimer(60)

;inizio codice rotazione
Const iNumRotations=36

; next we need an array to hold the images
Dim ObjectFrames(iNumRotations)

; now we need two arrays so we can pre-computed our
; Sin/Cos tables...helps speed things up
Dim XSinTable#(iNumRotations)
Dim YCosTable#(iNumRotations)

; now actually call the function that pre-computes
PrecomputeSinCosTables()

; Load the Object and do the rotations
LoadObject("alien1.tga", iNumRotations)

; initialize the Object to point north
Global ObjectDir = 0

; This controls the Object so it doesn't shake about
; when it gets close to the target. You can adjust
; this, but it seems that .01 is working well.
Global Smoothness# = .02

; initialize the X,Y locations of the Object
Global X# = 400
Global Y# = 300

; initialize the Speed# used
Global Speed# = 4

Global XTarget# = 500
Global YTarget# = 450
;fine codice rotazione

MidHandle giocatore
MidHandle nemico
MidHandle missile
Global jetx,jety

Global nem.nemico

Type proiettile
Field posizioneX
Field posizioneY
Field durata
Field velocita
Field aspetto
Field potenza
End Type


Type nemico
Field movimento
Field velocita
Field vitalita
Field aspetto
Field potenza
Field esplosione
Field punteggio
Field posizioneX
Field posizioneY
Field utile
Field negativo
Field positivo
;aggiunte al type
Field XTarget#
Field YTarget#
Field ObjectDir
Field X#
Field Y#
;Field Speed#
;fine aggiunte al type
End Type

;main

Repeat
Cls
WaitTimer(frametimer)


If MouseHit(2)
crea_nemico(2,300,50,3,nemico,100)
EndIf
muovi_nemico()

jetx=MouseX()
jety=MouseY()

DrawImage giocatore,jetx,jety

If MouseHit(1) Then crea_proiettile()

muovi_proiettile()

VWait

Flip

Until KeyHit(1)=1

End

;end main




Function crea_proiettile()
bullet.proiettile=New proiettile
bullet\posizioneX=MouseX() ;the x position of missile creation is the mouse coords(the same coords of my jet of course)
bullet\posizioneY=bullet\posizioneY+MouseY()-45 ;the missile creation start a bit up to the jet(for simulating the launch-bay hehe)
bullet\velocita=5 ;the speed of the missile
bullet\durata=300 ;the starting value of the animation
End Function

Function muovi_proiettile()
For bullet.proiettile=Each proiettile
DrawImage missile,bullet\posizioneX,bullet\posizioneY
bullet\posizioneY=bullet\posizioneY-bullet\velocita ;this move the missile up
bullet\durata=bullet\durata-bullet\velocita ;this start the counter of the missile course
If bullet\durata=<0 Then Delete bullet
Next
End Function

Function crea_nemico(moto,partenzaX,partenzaY,velocita,immagine,vita)
nem.nemico=New nemico
nem\movimento=moto
nem\velocita=velocita
nem\vitalita=vita
nem\aspetto=immagine
nem\potenza=nem\potenza ;da aggiungere in seguito
nem\esplosione=nem\esplosione ;da aggiungere in seguito
nem\punteggio=nem\punteggio ;da aggiungere in seguito
nem\posizioneX=x#
nem\posizioneY=y#
nem\utile=partenzaX
nem\negativo=-velocita
nem\positivo=+velocita
;inizializzazione del nemico

nem\XTarget# = MouseX() ;quello che puntera il nemico
nem\YTarget# = MouseY() ;quello che puntera il nemico
nem\ObjectDir = AngleToTarget(nem\X#,nem\Y#,nem\XTarget#,nem\YTarget#, Speed#,CurrentObjectDir, iNumRotations,Smoothness#)
nem\X# = nem\X# + (xSinTable#(ObjectDir) * Speed#)
nem\Y# = nem\Y# + (yCosTable#(ObjectDir) * Speed#)

;fine inizializzazione


End Function

Function muovi_nemico()
For nem.nemico=Each nemico

CurrentDistance# = GetDistance#(X,Y,XTarget,YTarget)
If CurrentDistance < 1
nem\X# = nem\X# - (xSinTable#(ObjectDir) * Speed#)
nem\Y# = nem\Y# - (yCosTable#(ObjectDir) * Speed#)
Speed# = 0
nem\ObjectDir = CurrentObjectDir
Text 0,84,"Hit Target!"
Else
Speed# = 2
EndIf

DrawImage(ObjectFrames(ObjectDir),nem\X#,nem\Y#)
;DrawImage nem\aspetto,nem\posizioneX,nem\posizioneY
;If nem\movimento=1 Then moto_verticale()
;If nem\movimento=2 Then moto_sindes()
;If nem\movimento=3 Then moto_centrato()
If nem\vitalita=<0
Delete nem
Exit
EndIf
;If nem\posizioneY=>500
; Delete nem
; Exit
;EndIf
Next
End Function

Function moto_verticale()
nem\posizioneX=nem\posizioneX
nem\posizioneY=nem\posizioneY + nem\velocita
End Function

Function moto_sindes()
nem\posizioneY=nem\posizioneY + (nem\positivo / 2) ;movimento verso il basso a meta velocita
nem\posizioneX=nem\posizioneX+nem\velocita ;movimento verso destra inizio
If nem\posizioneX => nem\utile+100 ;se fa cento passi a sin cambia direzione
nem\posizioneX = nem\posizioneX - nem\velocita ;e va verso destra
nem\velocita = nem\negativo ;il movimento sara ora negativo!!!
EndIf

If nem\posizioneX <= nem\utile -100 ;se fa cento passi a destra cambia direzione
nem\posizioneX = nem\posizioneX + nem\velocita ;e va verso destra come all'inizio
nem\velocita = nem\positivo ;il movimento ora ritorna positivo!!!
EndIf
End Function

Function PrecomputeSinCosTables()
Local iAngle# = 0

; run through the full rotation cycle, and use Sin and Cos
; at 10-degree increments
Multiplyer = 360/iNumRotations
For iAngle = 0 To iNumRotations-1
xSinTable#(iAngle) = Sin(iAngle*Multiplyer)
yCosTable#(iAngle) = -Cos(iAngle*Multiplyer)
Next
End Function

Function AngleToTarget(X#, Y#, XTarget#, YTarget#,Speed#, ShipDir, Rotations,Smoothness#)

; Calculate what the next x,y position of the ship would be
; if it kept moving in its current direction
StraightX# = nem\X# + (xSinTable#(ShipDir) * Speed#)
StraightY# = nem\Y# + (yCosTable#(ShipDir) * Speed#)

; Calculate what the next x,y position of the ship would be
; if it turned one unit left and moved forward from there
LeftShipDir = ShipDir - 1
If LeftShipDir < 0
LeftShipDir = Rotations - 1
EndIf
LeftX# = nem\X# + (xSinTable#(LeftShipDir) * Speed#)
LeftY# = nem\Y# + (yCosTable#(LeftShipDir) * Speed#)

; Calculate what the next x,y position of the ship would be
; if it turned one unit right and moved forward from there
RightShipDir = ShipDir + 1
If RightShipDir > Rotations - 1
RightShipDir = 1
EndIf
RightX# = nem\X# + (xSinTable#(RightShipDir) * Speed#)
RightY# = nem\Y# + (yCosTable#(RightShipDir) * Speed#)

; using our above calculated projections, let's see what
; the distance is between the target and each projection
StraightDist# = GetDistance#(StraightX,StraightY,nem\XTarget,nem\YTarget)
LeftDist# = GetDistance#(LeftX,LeftY,nem\XTarget,nem\YTarget)
RightDist# = GetDistance#(RightX,RightY,XTarget,nem\YTarget)

; if the Left distance is less than the Straight and the
; Right distances, the the best direction to turn would
; be left. That will bring us closer to the target.
If LeftDist < StraightDist And LeftDist < RightDist
; see if there is enough of an angle to warrant
; changing the dir...if this was left out the ship
; will shake madly when it gets close to the target
If StraightDist - LeftDist > Smoothness
; change the ship dir accordingly
ShipDir = LeftShipDir
EndIf
EndIf

; if the Right distance is less than the Straight and the
; Left distances, the the best direction to turn would
; be Right.
If RightDist < StraightDist And RightDist < LeftDist
; see if there is enough of an angle to warrant
; changing the dir...if this was left out the ship
; will shake madly when it gets close to the target
If StraightDist - RightDist > Smoothness
; change the ship dir accordingly
ShipDir = RightShipDir
EndIf
EndIf

; return the appropriate direction
Return(ShipDir)
End Function

Function GetDistance#(XSource#,YSource#,XTarget#,YTarget#) ; find the difference between the source and target
XDist# = nem\XTarget - XSource
YDist#= nem\YTarget - YSource

; use a little math
TotalDist# = Sqr#((XDist * XDist) + (YDist * YDist))

; return the value
Return (TotalDist)
End Function

Function LoadObject(ObjectName$,Rotations)
; tell BB to handle the centering of our images
AutoMidHandle True

; Load the player image and point to it with "imgTemp"
imgTemp = LoadImage(ObjectName$)

; see if the image was loaded successfully
If imgTemp = 0
Text 100,100,"Invalid Image!"
Else
; set it's mask (transparent color)
MaskImage imgTemp,0,0,0

; now run through the loop and rotate the image
For iLoop=0 To Rotations-1

; first copy the original image into the current frame
ObjectFrames(iLoop)=CopyImage( imgTemp )

; rotate the frame the appropriate number of degrees
RotateImage ObjectFrames(iLoop), iLoop*360/Rotations
Next
EndIf
End Function

(\endcode)
Thanks.


Valgar(Posted 2004) [#6]
ps:your last example is what i'm thinking [but has the same jump movement of the previous example...sorry but don't know how to improve it!]


Valgar(Posted 2004) [#7]
ARGHHHHHHHHHHHH what an idiot that i'm!
I forgot to digit "setbuffer backbuffer()" so it's why your examples flicker!
Excuse for my hemm.....newbie error.
But i'm not able to understand why my code doesn't work...