An example of using bezier curves for enemy movements in a (space) shooter.
Code:
' ==============================================================================
' Random paths.
' ==============================================================================
import "Keycodes.lib"
import "Speed.lib"
' Array of enemies.
enemies?[32]
' Clear all enemies.
for i = 0 to sizeof(enemies) - 1
_ClearEnemy enemies[i]
next
' Active curve that spawning enemies will inherit.
activeCurve?
_CreateEnemyCurve activeCurve
' Curve will change every five seconds.
curveChangeTimer = 5*60
' Two enemies will spawn every second.
enemySpawnTimer = 0
' Turn off automatic redraw.
set redraw off
' ------------------------------------------------------------------------------
' Game loop.
' ------------------------------------------------------------------------------
do
' Update ---------------------------------------------------------------------
' Create new curve?
curveChangeTimer = curveChangeTimer - 1
if curveChangeTimer <= 0
' Set timer to 5*60 ticks (5 seconds)
curveChangeTimer = 5*60
_CreateEnemyCurve activeCurve
endif
' Spawn a new enemy?
enemySpawnTimer = enemySpawnTimer - 1
if enemySpawnTimer <= 0
' Set timer to 30 ticks (half a second).
enemySpawnTimer = 1*30
' Find an inactive enemy.
for i = 0 to sizeof(enemies) - 1
if not enemies[i].act then break
next
' Did we find an empty spot?
if i < sizeof(enemies)
_ClearEnemy enemies[i]
enemies[i].act = true
_CopyCurve enemies[i], activeCurve
endif
endif
' Update enemies.
for i = 0 to sizeof(enemies) - 1
' Only update enemy if it's active.
if enemies[i].act then _UpdateEnemy enemies[i]
next
' Draw -----------------------------------------------------------------------
' Clear screen.
set color 0, 0, 0
cls
' Draw enemies.
set color 255, 255, 255
for i = 0 to sizeof(enemies) - 1
if enemies[i].act then _DrawEnemy enemies[i]
next
redraw
_SPD_HoldFrame 60
until keydown(VK_ESC, true)
' ==============================================================================
' Clear enemy.
' ==============================================================================
procedure ClearEnemy(&enemy?)
' Active flag.
enemy.act = false
' Bezier curve control points.
enemy.x0# = 0.0
enemy.y0# = 0.0
enemy.x1# = 0.0
enemy.y1# = 0.0
enemy.x2# = 0.0
enemy.y2# = 0.0
enemy.x3# = 0.0
enemy.y3# = 0.0
' Bezier curve param, [0..1]
enemy.p# = 0.0
' Parameter speed for curve
enemy.spd# = 0.005
' Actual position.
enemy.x = 0
enemy.y = 0
endproc
' ==============================================================================
' Update enemy.
' ==============================================================================
procedure UpdateEnemy(&enemy?)
' Increase curve parameter.
enemy.p# = enemy.p# + enemy.spd#
' Inactivate if end of curve has been reached.
if enemy.p# > 1.0
enemy.act = false
endif
' Evaluate position.
ip# = (1.0 - enemy.p#)
b0# = ip*ip*ip
b1# = 3.0*ip*ip*enemy.p#
b2# = 3.0*ip*enemy.p#*enemy.p#
b3# = enemy.p#*enemy.p#*enemy.p#
enemy.x = int(b0*enemy.x0# + b1*enemy.x1# + b2*enemy.x2# + b3*enemy.x3#) - 16
enemy.y = int(b0*enemy.y0# + b1*enemy.y1# + b2*enemy.y2# + b3*enemy.y3#) - 16
endproc
' ==============================================================================
' Draw enemy.
' ==============================================================================
procedure DrawEnemy(&enemy?)
draw rect enemy.x, enemy.y, 32, 32, true
endproc
' ==============================================================================
' Create enemy curve.
' ==============================================================================
procedure CreateEnemyCurve(&c?)
' Start at upper, left or right edge of the screen.
r = rnd(3)
if r = 0
' On Linux, you can skip 'float' and use rnd(640.0)
c.x0# = float(rnd(640))
c.y0# = -16.0
elseif r = 1
c.x0# = -16.0
c.y0# = float(rnd(480))
else
c.x0# = 656.0
c.y0# = float(rnd(480))
endif
' End at any screen edge.
r = rnd(4)
if r = 0
c.x3# = float(rnd(640))
c.y3# = -16.0
elseif r = 1
c.x3# = float(rnd(640))
c.y3# = 496.0
elseif r = 2
c.x3# = -16.0
c.y3# = float(rnd(480))
else
c.x3# = 656.0
c.y3# = float(rnd(480))
endif
' Completely random middle control points.
c.x1# = float(rnd(640))
c.y1# = float(rnd(480))
c.x2# = float(rnd(640))
c.y2# = float(rnd(480))
endproc
' ==============================================================================
' Copy curve.
' ==============================================================================
procedure CopyCurve(&dst?, &src?)
dst.x0# = src.x0#
dst.y0# = src.y0#
dst.x1# = src.x1#
dst.y1# = src.y1#
dst.x2# = src.x2#
dst.y2# = src.y2#
dst.x3# = src.x3#
dst.y3# = src.y3#
endproc