Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Space shootemup movement paths
#1
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


Attached Files
.txt   rndmov.txt (Size: 4.79 KB / Downloads: 15)
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)