NaaLaa

Full Version: Looking for a space shooter game written old NaaLaa
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi there! I’m looking for an old NaaLaa (probably v4 or before) game. If I’m not wrong, there was a 2D space shooter written in NaaLaa that I used to play around 2011 or 2010. It was a typical space shooter with bugs/space ships flying around, shooting and all that. I don’t remember whether it came bundled with NaaLaa or if someone shared a link on the old forum.

Sad note: I used to have old versions of NaaLaa and some programs on my old HDD. I tried connecting it to my Linux machine, and idiot me tried to recover the partition… now it’s all gone ?
This one ?

Code:
rem ==================================================================
rem Blastemroids
rem
rem Enemy and player sprites by Ari Feldman, other sprites by Marcus.
rem ==================================================================

visible:
    vNextFrameTime
    vFrameHold

visible:
    rem Enemy data.
    CEL_SIZE = 20
    GRID_WIDTH = 12
    GRID_HEIGHT = 6
    vEnemies[GRID_WIDTH][GRID_HEIGHT][7]
    ENEMY_TYPE = 0
    ENEMY_STATE = 1
    ENEMY_STAMINA = 2
    ENEMY_X = 3
    ENEMY_Y = 4
    ENEMY_BASE_FRAME = 5
    ENEMY_FRAME = 6
    vEnemiesF#[GRID_WIDTH][GRID_HEIGHT][5]
    ENEMY_X1 = 0
    ENEMY_Y1 = 1
    ENEMY_X2 = 2
    ENEMY_Y2 = 3
    ENEMY_PARAM = 4
    vNextAttackTimer
    vEnemyCount
    vGridMotionAngle# = 0.0
    vGridOffsetY

    rem Enemy bullets.
    MAX_ENEMY_BULLETS = 8
    vEnemyBullets[MAX_ENEMY_BULLETS][2]
    BULLET_ACTIVE = 0
    BULLET_FRAME = 1
    vEnemyBulletsF#[MAX_ENEMY_BULLETS][4]
    BULLET_X = 0
    BULLET_Y = 1
    BULLET_DX = 2
    BULLET_DY = 3
    vEnemyBulletCounter
    vEnemyBulletTimer = 400

    rem Player.
    vPlayerX
    vPlayerY
    vPlayerBulletType
    vPlayerBulletX
    vPlayerBulletY
    vPlayerShield
    vScore = 0
    vLevel = 1
    vLives = 3
    vGameOver = false
    vGameOverTimer = 0

    rem Explosions.
    MAX_EXPLOSIONS = 8
    vExplosions[MAX_EXPLOSIONS][4]
    EXP_FRAME = 0
    EXP_FRAME_COUNTER = 1
    EXP_X = 2
    EXP_Y = 3
    vExplosionCounter = 0

    rem Other.
    vScroll = 0
    vCentiCounter = 0

    rem Images.
    BACKGROUND_IMAGE = 0
    PLAYER_IMAGE = 1
    PLAYER_BULLETS_IMAGE = 2
    EXPLOSION_IMAGE = 3
    LOGO_IMAGE = 4
    GAME_OVER_IMAGE = 5
    ENEMY_BULLET_IMAGE = 10
    ENEMY_IMAGE_BASE = 10

    rem Sound.
    EXPLOSION_SOUND = 0
    ENEMY_HIT_SOUND = 1
    BULLET_SOUND = 2

hidden:

rem Init window.
set window 0, 0, 320, 240, true, true
set color 0, 0, 0
cls

rem Load.
proc Load
set redraw off


rem Init.
proc InitPlayer
proc InitEnemies 24 + vLevel*2
proc InitExplosions

play music 0

rem ==================================================================
rem Main loop.
rem ==================================================================
proc InitFrameHold 60
do
    rem Maintain constant speed.
    proc HoldFrame

    vCentiCounter = (vCentiCounter + 1)%100
    vScroll = (vScroll + 1)%240
    vGridMotionAngle = vGridMotionAngle + 0.5

    rem Init new level if all enemies are gone.
    if vEnemyCount = 0
        vLevel = vLevel + 1
        proc InitEnemies 24 + vLevel*2
    endif

    rem Update.
    proc UpdatePlayer
    proc UpdateEnemies
    proc UpdateEnemyBullets
    proc UpdateExplosions
    if vGameOver
        vGameOverTimer = vGameOverTimer - 1
        if vGameOverTimer = 0
            vGameOver = false
            vLevel = 0
            vScore = 0
            vEnemyCount = 0
            proc InitPlayer
        endif
    endif
    
    rem Draw.
    set color 255, 255, 255
    draw image BACKGROUND_IMAGE, 0, vScroll
    draw image BACKGROUND_IMAGE, 0, vScroll - 240
    proc DrawEnemies
    proc DrawEnemyBullets
    proc DrawPlayer
    proc DrawExplosions
    proc DrawScoreEtc
    if vGameOver
        set color 0, 0, 0, 128
        cls
        set color 255, 255, 255
        draw image GAME_OVER_IMAGE, (width(primary) - width(GAME_OVER_IMAGE))/2, 100
        set caret width(primary)/2, 140
    endif

    redraw
until keydown(27) or not running()

stop music 0

end

rem ==================================================================
rem Load data.
rem ==================================================================
procedure Load()
    rem create font 0, "impact", 16
    rem save font 0, "data/impact16.txt", "data/impact16.bmp"
    if javac()
        load font 0, "data/impact16.txt", "data/impact16.png"
    else
        load font 0, "data/impact16.txt", "data/impact16.bmp"
    endif

    set color 255, 255, 255

    load image LOGO_IMAGE, "data/logo.bmp"
    draw image LOGO_IMAGE, 160 - width(LOGO_IMAGE)/2, 60

    set caret 160, 100
    center "Use cursor keys to control your ship."
    center "Press space bar to shoot."
    center
    center "Loading . . ."
    wait 1000

    if javac()
        load music 0, "data/bgmusic.aif"
    else
        load music 0, "data/bgmusic.it"
    endif

    load image GAME_OVER_IMAGE, "data/gameover.bmp"
    set image colorkey GAME_OVER_IMAGE, 0, 0, 0

    create image BACKGROUND_IMAGE, 320, 240
    set image BACKGROUND_IMAGE
    set color 0, 0, 0
    cls
    for i = 0 to 199
        set color 255, 255, 255, rnd(256)
        draw pixel rnd(320), rnd(240)
    next
    set image primary

    load image PLAYER_IMAGE, "data/player.bmp"
    set image colorkey PLAYER_IMAGE, 0, 0 ,0
    set image grid PLAYER_IMAGE, 2, 1

    load image PLAYER_BULLETS_IMAGE, "data/player_bullets.bmp"
    set image colorkey PLAYER_BULLETS_IMAGE, 0, 0, 0

    load image EXPLOSION_IMAGE, "data/explosion.bmp"
    set image colorkey EXPLOSION_IMAGE, 0, 0, 0
    set image grid EXPLOSION_IMAGE, 8, 1

    load image ENEMY_IMAGE_BASE + 1, "data/enemy_0.bmp"
    load image ENEMY_IMAGE_BASE + 2, "data/enemy_1.bmp"
    load image ENEMY_IMAGE_BASE + 3, "data/enemy_2.bmp"
    set image colorkey ENEMY_IMAGE_BASE + 1, 0, 0 ,0
    set image colorkey ENEMY_IMAGE_BASE + 2, 0, 0 ,0
    set image colorkey ENEMY_IMAGE_BASE + 3, 0, 0 ,0
    set image grid ENEMY_IMAGE_BASE + 1, 12, 1
    set image grid ENEMY_IMAGE_BASE + 2, 12, 1
    set image grid ENEMY_IMAGE_BASE + 3, 12, 1

    load image ENEMY_BULLET_IMAGE, "data/enemy_bullet.bmp"
    set image colorkey ENEMY_BULLET_IMAGE, 0, 0, 0
    set image grid ENEMY_BULLET_IMAGE, 2, 1

    load sound EXPLOSION_SOUND, "data/explosion.wav"
    load sound ENEMY_HIT_SOUND, "data/enemy_hit.wav"
    load sound BULLET_SOUND, "data/bullet.wav"
    
    set color 255, 255, 0
    center
    center "Click to start game!"
    wait mousebutton

endproc

rem ==================================================================
rem Init player.
rem ==================================================================
procedure InitPlayer()
    vLives = 3
    vPlayerX = 160 - width(PLAYER_IMAGE)/2
    vPlayerY = 250
    vPlayerShield = 200
    vPlayerBulletType = 0
    vGameOver = false
endproc

rem ==================================================================
rem Update player.
rem ==================================================================
procedure UpdatePlayer()
    if vGameOver then return;
    if keydown(37) then vPlayerX = vPlayerX - 2
    if keydown(39) then vPlayerX = vPlayerX + 2
    if vPlayerY > 210 then vPlayerY = vPlayerY - 1
    if vPlayerX < 0 then vPlayerX = 0
    if vPlayerX > 320 - width(PLAYER_IMAGE) then vPlayerX = 320 - width(PLAYER_IMAGE)
    if keydown(" ") and vPlayerBulletType = 0
        vPlayerBulletType = 1
        vPlayerBulletX = vPlayerX
        vPlayerBulletY = vPlayerY + 8
        play sound BULLET_SOUND
    endif
    if vPlayerShield > 0 then vPlayerShield = vPlayerShield - 1

    if vPlayerBulletType > 0
        vPlayerBulletY = vPlayerBulletY - 4
        if vPlayerBulletY < -height(PLAYER_BULLETS_IMAGE) then vPlayerBulletType = 0
    endif
endproc

rem ==================================================================
rem Draw player
rem ==================================================================
procedure DrawPlayer()
    if vGameOver then return
    if vPlayerShield = 0 or vCentiCounter%8 < 4 then draw image PLAYER_IMAGE, vPlayerX, vPlayerY, (vCentiCounter%10)/5
    if vPlayerBulletType > 0
        draw image PLAYER_BULLETS_IMAGE, vPlayerBulletX, vPlayerBulletY
    endif
endproc

rem ==================================================================
rem Lose a life.
rem ==================================================================
procedure LoseLife()
    if vPlayerShield = 0
        proc AddExplosion vPlayerX + width(PLAYER_IMAGE)/2, vPlayerY + height(PLAYER_IMAGE)/2
        vLives = vLives - 1
        vPlayerY = 250
        vPlayerX = 160 - width(PLAYER_IMAGE)/2
        vPlayerShield = 200
        if vLives < 0
            vGameOver = true
            vGameOverTimer = 300
        endif
    endif
endproc

rem ==================================================================
rem Draw score etc.
rem ==================================================================
procedure DrawScoreEtc()
    set color 255, 255, 255
    set caret 4, 4
    write "Level:   "
    set color 128, 255, 255
    write vLevel
    set caret 64, 4
    set color 255, 255, 255
    write "Score:   "
    set color 255, 255, 128
    write vScore

    set color 255, 255, 255
    for i = 0 to vLives - 1
        draw image PLAYER_IMAGE, 320 - (i + 1)*(width(PLAYER_IMAGE) + 4), 4, 0
    next
endproc

rem ==================================================================
rem Init explosions.
rem ==================================================================
procedure InitExplosions()
    vExplosionCounter = 0
    for i = 0 to MAX_EXPLOSIONS - 1
        vExplosions[i][EXP_FRAME] = -1
    next
endproc

rem ==================================================================
rem Add an explosion at (x, y).
rem ==================================================================
procedure AddExplosion(x, y)
    vExplosions[vExplosionCounter][EXP_FRAME] = 0
    vExplosions[vExplosionCounter][EXP_FRAME_COUNTER] = 0
    vExplosions[vExplosionCounter][EXP_X] = x - width(EXPLOSION_IMAGE)/2
    vExplosions[vExplosionCounter][EXP_Y] = y - height(EXPLOSION_IMAGE)/2
    vExplosionCounter = (vExplosionCounter + 1)%MAX_EXPLOSIONS
    play sound EXPLOSION_SOUND
endproc

rem ==================================================================
rem Update explosions.
rem ==================================================================
procedure UpdateExplosions()
    for i = 0 to MAX_EXPLOSIONS - 1
        if vExplosions[i][EXP_FRAME] >= 0
            vExplosions[i][EXP_FRAME_COUNTER] = (vExplosions[i][EXP_FRAME_COUNTER] + 1)%4
            if vExplosions[i][EXP_FRAME_COUNTER] = 0
                vExplosions[i][EXP_FRAME] = vExplosions[i][EXP_FRAME] + 1
                if vExplosions[i][EXP_FRAME] = 8 then vExplosions[i][EXP_FRAME] = -1
            endif
        endif
    next
endproc

rem ==================================================================
rem Draw explosions.
rem ==================================================================
procedure DrawExplosions()
    for i = 0 to MAX_EXPLOSIONS - 1
        if vExplosions[i][EXP_FRAME] >= 0
            draw image EXPLOSION_IMAGE, vExplosions[i][EXP_X], vExplosions[i][EXP_Y], vExplosions[i][EXP_FRAME]
        endif
    next
endproc

rem ==================================================================
rem Init enemies.
rem ==================================================================
procedure InitEnemies(count)
    vNextAttackTimer = 400

    rem Clear.
    for y = 0 to GRID_HEIGHT - 1
        for x = 0 to GRID_WIDTH - 1
            vEnemies[x][y][ENEMY_TYPE] = 0
        next
    next
    
    rem Add enemies.
    count = min(count, GRID_WIDTH*GRID_HEIGHT)/2
    for i = 0 to count - 1
        do
            x = rnd(GRID_WIDTH/2)
            y = rnd(GRID_HEIGHT)
        until vEnemies[x][y][ENEMY_TYPE] = 0
        type = rnd(3) + 1
        vEnemies[x][y][ENEMY_TYPE] = type
        vEnemies[x][y][ENEMY_STAMINA] = type
        vEnemies[x][y][ENEMY_STATE] = 0
        vEnemies[x][y][ENEMY_BASE_FRAME] = 0
        vEnemies[x][y][ENEMY_FRAME] = rnd(60)
        vEnemies[GRID_WIDTH - 1 - x][y][ENEMY_TYPE] = type
        vEnemies[GRID_WIDTH - 1 - x][y][ENEMY_STAMINA] = type
        vEnemies[GRID_WIDTH - 1 - x][y][ENEMY_STATE] = 0
        vEnemies[GRID_WIDTH - 1 - x][y][ENEMY_BASE_FRAME] = 0
        vEnemies[GRID_WIDTH - 1 - x][y][ENEMY_FRAME] = rnd(60)
    next

    vEnemyCount = count*2

    vEnemyBulletCounter = 0
    for i = 0 to MAX_ENEMY_BULLETS - 1
        vEnemyBullets[i][BULLET_ACTIVE] = 0
    next
    vGridOffsetY = -200
endproc

rem ==================================================================
rem Add an enemy bullet moving from (x, y) to player's position.
rem ==================================================================
procedure AddEnemyBullet(x, y)
    vEnemyBullets[vEnemyBulletCounter][BULLET_ACTIVE] = true
    vEnemyBullets[vEnemyBulletCounter][BULLET_FRAME] = 0
    vEnemyBulletsF[vEnemyBulletCounter][BULLET_X] = float(x)
    vEnemyBulletsF[vEnemyBulletCounter][BULLET_Y] = float(y)
    dx# = float(vPlayerX) - float(x)
    dy# = float(vPlayerY) - float(y)
    k# = 1.0/sqr(dx*dx + dy*dy)
    vEnemyBulletsF[vEnemyBulletCounter][BULLET_DX] = dx*k*2.0
    vEnemyBulletsF[vEnemyBulletCounter][BULLET_DY] = dy*k*2.0
    vEnemyBulletCounter = (vEnemyBulletCounter + 1)%MAX_ENEMY_BULLETS
endproc

rem ==================================================================
rem Update enemy bullets.
rem ==================================================================
procedure UpdateEnemyBullets()
    for i = 0 to MAX_ENEMY_BULLETS - 1
        if vEnemyBullets[i][BULLET_ACTIVE]
            vEnemyBullets[i][BULLET_FRAME] = (vEnemyBullets[i][BULLET_FRAME] + 1)%20
            vEnemyBulletsF[i][BULLET_X] = vEnemyBulletsF[i][BULLET_X] + vEnemyBulletsF[i][BULLET_DX]
            vEnemyBulletsF[i][BULLET_Y] = vEnemyBulletsF[i][BULLET_Y] + vEnemyBulletsF[i][BULLET_DY]
            if not vGameOver
                if ImageCol(ENEMY_BULLET_IMAGE, int(vEnemyBulletsF[i][BULLET_X]), int(vEnemyBulletsF[i][BULLET_Y]), PLAYER_IMAGE, vPlayerX, vPlayerY)
                    vEnemyBullets[i][BULLET_ACTIVE] = false
                    proc LoseLife
                endif
            endif
        endif
    next
endproc

rem ==================================================================
rem Draw enemy bullets.
rem ==================================================================
procedure DrawEnemyBullets()
    for i = 0 to MAX_ENEMY_BULLETS - 1
        if vEnemyBullets[i][BULLET_ACTIVE]
            draw image ENEMY_BULLET_IMAGE, int(vEnemyBulletsF[i][BULLET_X]), int(vEnemyBulletsF[i][BULLET_Y]), vEnemyBullets[i][BULLET_FRAME]/10
        endif
    next
endproc

rem ==================================================================
rem Return the x coordinate of an enemy at grid position (x, y).
rem ==================================================================
function GridX(x, y)
    return (320 - GRID_WIDTH*CEL_SIZE)/2 + x*CEL_SIZE + int(cos(vGridMotionAngle + float(y*24))*24.0)
endfunc

rem ==================================================================
rem Return the y coordinate of an enemy at a certain grid y.
rem ==================================================================
function GridY(y)
    return 24 + y*CEL_SIZE + vGridOffsetY
endfunc

rem ==================================================================
rem Update enemies.
rem ==================================================================
procedure UpdateEnemies()
    if vGridOffsetY < 0 then vGridOffsetY = vGridOffsetY + 1
    vEnemyBulletTimer = vEnemyBulletTimer - 1
    rem Update enemy attacks.
    vNextAttackTimer = vNextAttackTimer - 1
    if vNextAttackTimer <= 0
        rem Look for enemies that can attack and add them to a list.
        attackers[GRID_WIDTH*GRID_HEIGHT]
        count = 0
        for y = 0 to GRID_HEIGHT - 1
            for x = 0 to GRID_WIDTH - 1
                if vEnemies[x][y][ENEMY_TYPE] > 0 and vEnemies[x][y][ENEMY_STATE] = 0
                    rem Add enemy to list of possible attackers. Convert its position
                    rem in the grid to an index.
                    attackers[count] = y*GRID_WIDTH + x
                    count = count + 1
                endif
            next    
        next
        rem Any one interested?
        if count > 0
            rem Get any enemy from the list.
            enemy = attackers[rnd(count)]
            rem Convert its position back to the 2D grid.
            x = enemy%GRID_WIDTH
            y = enemy/GRID_WIDTH
            rem Init its attack curve.
            vEnemies[x][y][ENEMY_STATE] = 1
            vEnemiesF[x][y][ENEMY_PARAM] = 0.0
            vEnemiesF[x][y][ENEMY_X1] = float(rnd(320))
            vEnemiesF[x][y][ENEMY_X2] = float(rnd(320))
            vEnemiesF[x][y][ENEMY_Y1] = 400.0
            vEnemiesF[x][y][ENEMY_Y2] = float(GridY(y) - 100)
            rem Wait some until next attack.
            vNextAttackTimer = max(200 + rnd(100) - vLevel*50, 50)
        else
            vNextAttackTimer = 50
        endif
    endif

    rem Move enemies.
    for y = 0 to GRID_HEIGHT - 1
        for x = 0 to GRID_WIDTH - 1
            if vEnemies[x][y][ENEMY_TYPE] > 0
                vEnemies[x][y][ENEMY_FRAME] = (vEnemies[x][y][ENEMY_FRAME] + 1)%60
                gx = GridX(x, y)
                gy = GridY(y)
                rem Is it attacking?
                if vEnemies[x][y][ENEMY_STATE] = 1
                    rem Shoot?
                    prm# = vEnemiesF[x][y][ENEMY_PARAM]
                    if vEnemyBulletTimer <= 0 and ((prm > 0.05 and prm < 0.1) or prm > 0.75)
                        vEnemyBulletTimer = 50 + rnd(100)
                        proc AddEnemyBullet vEnemies[x][y][ENEMY_X], vEnemies[x][y][ENEMY_Y]
                    endif
                    rem Update position.
                    vEnemiesF[x][y][ENEMY_PARAM] = vEnemiesF[x][y][ENEMY_PARAM] + 0.0025
                    rem Back at where it started?
                    if vEnemiesF[x][y][ENEMY_PARAM] >= 1.0
                        vEnemies[x][y][ENEMY_STATE] = 0
                        vEnemies[x][y][ENEMY_X] = gx + 2
                        vEnemies[x][y][ENEMY_Y] = gy + 6
                        vEnemies[x][y][ENEMY_BASE_FRAME] = 0
                    else
                        p[] = FlyingEnemyPos(vEnemiesF[x][y][ENEMY_PARAM], float(gx), float(gy), vEnemiesF[x][y][ENEMY_X1], vEnemiesF[x][y][ENEMY_Y1], vEnemiesF[x][y][ENEMY_X2], vEnemiesF[x][y][ENEMY_Y2])
                        vEnemies[x][y][ENEMY_X] = p[0] + 4
                        vEnemies[x][y][ENEMY_Y] = p[1] + 6
                        vEnemies[x][y][ENEMY_BASE_FRAME] = FlyingEnemyDir(vEnemiesF[x][y][ENEMY_PARAM], float(gx), float(gy), vEnemiesF[x][y][ENEMY_X1], vEnemiesF[x][y][ENEMY_Y1], vEnemiesF[x][y][ENEMY_X2], vEnemiesF[x][y][ENEMY_Y2])
                    endif
                else
                    vEnemies[x][y][ENEMY_X] = gx + 2
                    vEnemies[x][y][ENEMY_Y] = gy + 6
                endif

                if ImageCol(vEnemies[x][y][ENEMY_TYPE] + ENEMY_IMAGE_BASE, vEnemies[x][y][ENEMY_X], vEnemies[x][y][ENEMY_Y], PLAYER_IMAGE, vPlayerX, vPlayerY)
                    proc LoseLife
                endif

                rem Hit by player bullet?
                if vPlayerBulletType > 0
                    if ImageCol(vEnemies[x][y][ENEMY_TYPE] + ENEMY_IMAGE_BASE, vEnemies[x][y][ENEMY_X], vEnemies[x][y][ENEMY_Y], PLAYER_BULLETS_IMAGE, vPlayerBulletX, vPlayerBulletY)
                        vPlayerBulletType = 0
                        vEnemies[x][y][ENEMY_STAMINA] = vEnemies[x][y][ENEMY_STAMINA] - 1
                        if vEnemies[x][y][ENEMY_STAMINA] = 0
                            img = ENEMY_IMAGE_BASE + vEnemies[x][y][ENEMY_TYPE]
                            proc AddExplosion vEnemies[x][y][ENEMY_X] + width(img)/2, vEnemies[x][y][ENEMY_Y] + height(img)/2
                            if vEnemies[x][y][ENEMY_STATE] = 1
                                vScore = vScore + 20*vEnemies[x][y][ENEMY_TYPE]
                            else
                                vScore = vScore + 10*vEnemies[x][y][ENEMY_TYPE]
                            endif
                            vEnemies[x][y][ENEMY_TYPE] = 0
                            vEnemyCount = vEnemyCount - 1
                        else
                            play sound ENEMY_HIT_SOUND
                        endif
                    endif
                endif

            endif
        next
    next
endproc

rem ==================================================================
rem Return true if two image at specific locations intersect.
rem ==================================================================
function ImageCol(img0, x0, y0, img1, x1, y1)
    if x0 + width(img0) < x1 then return false
    if y0 + height(img0) < y1 then return false
    if x1 + width(img1) < x0 then return false
    if y1 + height(img1) < y0 then return false
    return true
endfunc

rem ==================================================================
rem Calculate position for an attacking enemy. It's a special case of
rem a cubic bezier curve, where the start and end point are the same.
rem ==================================================================
function FlyingEnemyPos[](param#, x#, y#, x1#, y1#, x2#, y2#)
    param = max#(param, 0.0)
    param = min#(param, 1.0)
    b0# = 1.0 - param
    b0 = b0*b0*b0
    b1# = 1.0 - param
    b1 = b1*b1
    b1 = b1*3.0*param
    b2# = 3.0*(1.0 - param)*param*param
    b3# = param*param*param
    return [int(b0*x + b1*x1 + b2*x2 + b3*x), int(b0*y + b1*y1 + b2*y2 + b3*y)]
endfunc

rem ==================================================================
rem Return direction for enemy (a base frame for its image grid).
rem Think I've messed up the code a little here ... never mind.
rem ==================================================================
function FlyingEnemyDir(param#, x#, y#, x1#, y1#, x2#, y2#)
    b0# = 1.0 - param
    b0 = -3.0*b0*b0
    b1# = 1.0 - param
    b1 = 3.0*b1 - 6.0*param*b1
    b2# = 6.0*param*(1.0 - param) - 3.0*param*param
    b3# = 3.0*param*param
    dx# = b0*x + b1*x1 + b2*x2 + b3*x
    dy# = b0*y + b1*y1 + b2*y2 + b3*y
    k# = 1.0/sqr(dx*dx + dy*dy)
    dx = dx*k
    dy = dy*k
    
    if dy <= 0.0
        if abs#(dx) < 0.25
            ret = 0
        else
            if dx < 0.0
                ret = 8
            else
                ret = 10
            endif
        endif
    else
        if abs#(dx) < 0.25
            ret = 2
        else
            if dx < 0.0
                ret = 6
            else
                ret = 4
            endif
        endif
    endif
    return ret
endproc

rem ==================================================================
rem Draw enemies.
rem ==================================================================
procedure DrawEnemies()
    for y = 0 to GRID_HEIGHT - 1
        for x = 0 to GRID_WIDTH - 1
            if vEnemies[x][y][ENEMY_TYPE] > 0
                set color 255, 255, 255
                draw image ENEMY_IMAGE_BASE + vEnemies[x][y][ENEMY_TYPE], vEnemies[x][y][ENEMY_X], vEnemies[x][y][ENEMY_Y], vEnemies[x][y][ENEMY_BASE_FRAME] + vEnemies[x][y][ENEMY_FRAME]/30
            endif
        next
    next
endproc

rem ==================================================================
rem Init frame hold
rem ==================================================================
procedure InitFrameHold(speed)
    vNextFrameTime = time()
    vFrameHold = 1000/speed
endproc

rem ==================================================================
rem Hold frame to maintain constant speed.
rem ==================================================================
procedure HoldFrame()
    while time() < vNextFrameTime; wait 1; wend
    vNextFrameTime = vNextFrameTime + vFrameHold
endproc
I think Blastemroids was one of the first games I wrote in naalaa Smile
(02-12-2026, 08:44 AM)1micha.elok Wrote: [ -> ]This one ?

Code:
rem ==================================================================
rem Blastemroids
rem
rem Enemy and player sprites by Ari Feldman, other sprites by Marcus.
rem ==================================================================

visible:
    vNextFrameTime
    vFrameHold

visible:
    rem Enemy data.
    CEL_SIZE = 20
    GRID_WIDTH = 12
    GRID_HEIGHT = 6
    vEnemies[GRID_WIDTH][GRID_HEIGHT][7]
    ENEMY_TYPE = 0
    ENEMY_STATE = 1
    ENEMY_STAMINA = 2
    ENEMY_X = 3
    ENEMY_Y = 4
    ENEMY_BASE_FRAME = 5
    ENEMY_FRAME = 6
    vEnemiesF#[GRID_WIDTH][GRID_HEIGHT][5]
    ENEMY_X1 = 0
    ENEMY_Y1 = 1
    ENEMY_X2 = 2
    ENEMY_Y2 = 3
    ENEMY_PARAM = 4
    vNextAttackTimer
    vEnemyCount
    vGridMotionAngle# = 0.0
    vGridOffsetY

    rem Enemy bullets.
    MAX_ENEMY_BULLETS = 8
    vEnemyBullets[MAX_ENEMY_BULLETS][2]
    BULLET_ACTIVE = 0
    BULLET_FRAME = 1
    vEnemyBulletsF#[MAX_ENEMY_BULLETS][4]
    BULLET_X = 0
    BULLET_Y = 1
    BULLET_DX = 2
    BULLET_DY = 3
    vEnemyBulletCounter
    vEnemyBulletTimer = 400

    rem Player.
    vPlayerX
    vPlayerY
    vPlayerBulletType
    vPlayerBulletX
    vPlayerBulletY
    vPlayerShield
    vScore = 0
    vLevel = 1
    vLives = 3
    vGameOver = false
    vGameOverTimer = 0

    rem Explosions.
    MAX_EXPLOSIONS = 8
    vExplosions[MAX_EXPLOSIONS][4]
    EXP_FRAME = 0
    EXP_FRAME_COUNTER = 1
    EXP_X = 2
    EXP_Y = 3
    vExplosionCounter = 0

    rem Other.
    vScroll = 0
    vCentiCounter = 0

    rem Images.
    BACKGROUND_IMAGE = 0
    PLAYER_IMAGE = 1
    PLAYER_BULLETS_IMAGE = 2
    EXPLOSION_IMAGE = 3
    LOGO_IMAGE = 4
    GAME_OVER_IMAGE = 5
    ENEMY_BULLET_IMAGE = 10
    ENEMY_IMAGE_BASE = 10

    rem Sound.
    EXPLOSION_SOUND = 0
    ENEMY_HIT_SOUND = 1
    BULLET_SOUND = 2

hidden:

rem Init window.
set window 0, 0, 320, 240, true, true
set color 0, 0, 0
cls

rem Load.
proc Load
set redraw off


rem Init.
proc InitPlayer
proc InitEnemies 24 + vLevel*2
proc InitExplosions

play music 0

rem ==================================================================
rem Main loop.
rem ==================================================================
proc InitFrameHold 60
do
    rem Maintain constant speed.
    proc HoldFrame

    vCentiCounter = (vCentiCounter + 1)%100
    vScroll = (vScroll + 1)%240
    vGridMotionAngle = vGridMotionAngle + 0.5

    rem Init new level if all enemies are gone.
    if vEnemyCount = 0
        vLevel = vLevel + 1
        proc InitEnemies 24 + vLevel*2
    endif

    rem Update.
    proc UpdatePlayer
    proc UpdateEnemies
    proc UpdateEnemyBullets
    proc UpdateExplosions
    if vGameOver
        vGameOverTimer = vGameOverTimer - 1
        if vGameOverTimer = 0
            vGameOver = false
            vLevel = 0
            vScore = 0
            vEnemyCount = 0
            proc InitPlayer
        endif
    endif
    
    rem Draw.
    set color 255, 255, 255
    draw image BACKGROUND_IMAGE, 0, vScroll
    draw image BACKGROUND_IMAGE, 0, vScroll - 240
    proc DrawEnemies
    proc DrawEnemyBullets
    proc DrawPlayer
    proc DrawExplosions
    proc DrawScoreEtc
    if vGameOver
        set color 0, 0, 0, 128
        cls
        set color 255, 255, 255
        draw image GAME_OVER_IMAGE, (width(primary) - width(GAME_OVER_IMAGE))/2, 100
        set caret width(primary)/2, 140
    endif

    redraw
until keydown(27) or not running()

stop music 0

end

rem ==================================================================
rem Load data.
rem ==================================================================
procedure Load()
    rem create font 0, "impact", 16
    rem save font 0, "data/impact16.txt", "data/impact16.bmp"
    if javac()
        load font 0, "data/impact16.txt", "data/impact16.png"
    else
        load font 0, "data/impact16.txt", "data/impact16.bmp"
    endif

    set color 255, 255, 255

    load image LOGO_IMAGE, "data/logo.bmp"
    draw image LOGO_IMAGE, 160 - width(LOGO_IMAGE)/2, 60

    set caret 160, 100
    center "Use cursor keys to control your ship."
    center "Press space bar to shoot."
    center
    center "Loading . . ."
    wait 1000

    if javac()
        load music 0, "data/bgmusic.aif"
    else
        load music 0, "data/bgmusic.it"
    endif

    load image GAME_OVER_IMAGE, "data/gameover.bmp"
    set image colorkey GAME_OVER_IMAGE, 0, 0, 0

    create image BACKGROUND_IMAGE, 320, 240
    set image BACKGROUND_IMAGE
    set color 0, 0, 0
    cls
    for i = 0 to 199
        set color 255, 255, 255, rnd(256)
        draw pixel rnd(320), rnd(240)
    next
    set image primary

    load image PLAYER_IMAGE, "data/player.bmp"
    set image colorkey PLAYER_IMAGE, 0, 0 ,0
    set image grid PLAYER_IMAGE, 2, 1

    load image PLAYER_BULLETS_IMAGE, "data/player_bullets.bmp"
    set image colorkey PLAYER_BULLETS_IMAGE, 0, 0, 0

    load image EXPLOSION_IMAGE, "data/explosion.bmp"
    set image colorkey EXPLOSION_IMAGE, 0, 0, 0
    set image grid EXPLOSION_IMAGE, 8, 1

    load image ENEMY_IMAGE_BASE + 1, "data/enemy_0.bmp"
    load image ENEMY_IMAGE_BASE + 2, "data/enemy_1.bmp"
    load image ENEMY_IMAGE_BASE + 3, "data/enemy_2.bmp"
    set image colorkey ENEMY_IMAGE_BASE + 1, 0, 0 ,0
    set image colorkey ENEMY_IMAGE_BASE + 2, 0, 0 ,0
    set image colorkey ENEMY_IMAGE_BASE + 3, 0, 0 ,0
    set image grid ENEMY_IMAGE_BASE + 1, 12, 1
    set image grid ENEMY_IMAGE_BASE + 2, 12, 1
    set image grid ENEMY_IMAGE_BASE + 3, 12, 1

    load image ENEMY_BULLET_IMAGE, "data/enemy_bullet.bmp"
    set image colorkey ENEMY_BULLET_IMAGE, 0, 0, 0
    set image grid ENEMY_BULLET_IMAGE, 2, 1

    load sound EXPLOSION_SOUND, "data/explosion.wav"
    load sound ENEMY_HIT_SOUND, "data/enemy_hit.wav"
    load sound BULLET_SOUND, "data/bullet.wav"
    
    set color 255, 255, 0
    center
    center "Click to start game!"
    wait mousebutton

endproc

rem ==================================================================
rem Init player.
rem ==================================================================
procedure InitPlayer()
    vLives = 3
    vPlayerX = 160 - width(PLAYER_IMAGE)/2
    vPlayerY = 250
    vPlayerShield = 200
    vPlayerBulletType = 0
    vGameOver = false
endproc

rem ==================================================================
rem Update player.
rem ==================================================================
procedure UpdatePlayer()
    if vGameOver then return;
    if keydown(37) then vPlayerX = vPlayerX - 2
    if keydown(39) then vPlayerX = vPlayerX + 2
    if vPlayerY > 210 then vPlayerY = vPlayerY - 1
    if vPlayerX < 0 then vPlayerX = 0
    if vPlayerX > 320 - width(PLAYER_IMAGE) then vPlayerX = 320 - width(PLAYER_IMAGE)
    if keydown(" ") and vPlayerBulletType = 0
        vPlayerBulletType = 1
        vPlayerBulletX = vPlayerX
        vPlayerBulletY = vPlayerY + 8
        play sound BULLET_SOUND
    endif
    if vPlayerShield > 0 then vPlayerShield = vPlayerShield - 1

    if vPlayerBulletType > 0
        vPlayerBulletY = vPlayerBulletY - 4
        if vPlayerBulletY < -height(PLAYER_BULLETS_IMAGE) then vPlayerBulletType = 0
    endif
endproc

rem ==================================================================
rem Draw player
rem ==================================================================
procedure DrawPlayer()
    if vGameOver then return
    if vPlayerShield = 0 or vCentiCounter%8 < 4 then draw image PLAYER_IMAGE, vPlayerX, vPlayerY, (vCentiCounter%10)/5
    if vPlayerBulletType > 0
        draw image PLAYER_BULLETS_IMAGE, vPlayerBulletX, vPlayerBulletY
    endif
endproc

rem ==================================================================
rem Lose a life.
rem ==================================================================
procedure LoseLife()
    if vPlayerShield = 0
        proc AddExplosion vPlayerX + width(PLAYER_IMAGE)/2, vPlayerY + height(PLAYER_IMAGE)/2
        vLives = vLives - 1
        vPlayerY = 250
        vPlayerX = 160 - width(PLAYER_IMAGE)/2
        vPlayerShield = 200
        if vLives < 0
            vGameOver = true
            vGameOverTimer = 300
        endif
    endif
endproc

rem ==================================================================
rem Draw score etc.
rem ==================================================================
procedure DrawScoreEtc()
    set color 255, 255, 255
    set caret 4, 4
    write "Level:   "
    set color 128, 255, 255
    write vLevel
    set caret 64, 4
    set color 255, 255, 255
    write "Score:   "
    set color 255, 255, 128
    write vScore

    set color 255, 255, 255
    for i = 0 to vLives - 1
        draw image PLAYER_IMAGE, 320 - (i + 1)*(width(PLAYER_IMAGE) + 4), 4, 0
    next
endproc

rem ==================================================================
rem Init explosions.
rem ==================================================================
procedure InitExplosions()
    vExplosionCounter = 0
    for i = 0 to MAX_EXPLOSIONS - 1
        vExplosions[i][EXP_FRAME] = -1
    next
endproc

rem ==================================================================
rem Add an explosion at (x, y).
rem ==================================================================
procedure AddExplosion(x, y)
    vExplosions[vExplosionCounter][EXP_FRAME] = 0
    vExplosions[vExplosionCounter][EXP_FRAME_COUNTER] = 0
    vExplosions[vExplosionCounter][EXP_X] = x - width(EXPLOSION_IMAGE)/2
    vExplosions[vExplosionCounter][EXP_Y] = y - height(EXPLOSION_IMAGE)/2
    vExplosionCounter = (vExplosionCounter + 1)%MAX_EXPLOSIONS
    play sound EXPLOSION_SOUND
endproc

rem ==================================================================
rem Update explosions.
rem ==================================================================
procedure UpdateExplosions()
    for i = 0 to MAX_EXPLOSIONS - 1
        if vExplosions[i][EXP_FRAME] >= 0
            vExplosions[i][EXP_FRAME_COUNTER] = (vExplosions[i][EXP_FRAME_COUNTER] + 1)%4
            if vExplosions[i][EXP_FRAME_COUNTER] = 0
                vExplosions[i][EXP_FRAME] = vExplosions[i][EXP_FRAME] + 1
                if vExplosions[i][EXP_FRAME] = 8 then vExplosions[i][EXP_FRAME] = -1
            endif
        endif
    next
endproc

rem ==================================================================
rem Draw explosions.
rem ==================================================================
procedure DrawExplosions()
    for i = 0 to MAX_EXPLOSIONS - 1
        if vExplosions[i][EXP_FRAME] >= 0
            draw image EXPLOSION_IMAGE, vExplosions[i][EXP_X], vExplosions[i][EXP_Y], vExplosions[i][EXP_FRAME]
        endif
    next
endproc

rem ==================================================================
rem Init enemies.
rem ==================================================================
procedure InitEnemies(count)
    vNextAttackTimer = 400

    rem Clear.
    for y = 0 to GRID_HEIGHT - 1
        for x = 0 to GRID_WIDTH - 1
            vEnemies[x][y][ENEMY_TYPE] = 0
        next
    next
    
    rem Add enemies.
    count = min(count, GRID_WIDTH*GRID_HEIGHT)/2
    for i = 0 to count - 1
        do
            x = rnd(GRID_WIDTH/2)
            y = rnd(GRID_HEIGHT)
        until vEnemies[x][y][ENEMY_TYPE] = 0
        type = rnd(3) + 1
        vEnemies[x][y][ENEMY_TYPE] = type
        vEnemies[x][y][ENEMY_STAMINA] = type
        vEnemies[x][y][ENEMY_STATE] = 0
        vEnemies[x][y][ENEMY_BASE_FRAME] = 0
        vEnemies[x][y][ENEMY_FRAME] = rnd(60)
        vEnemies[GRID_WIDTH - 1 - x][y][ENEMY_TYPE] = type
        vEnemies[GRID_WIDTH - 1 - x][y][ENEMY_STAMINA] = type
        vEnemies[GRID_WIDTH - 1 - x][y][ENEMY_STATE] = 0
        vEnemies[GRID_WIDTH - 1 - x][y][ENEMY_BASE_FRAME] = 0
        vEnemies[GRID_WIDTH - 1 - x][y][ENEMY_FRAME] = rnd(60)
    next

    vEnemyCount = count*2

    vEnemyBulletCounter = 0
    for i = 0 to MAX_ENEMY_BULLETS - 1
        vEnemyBullets[i][BULLET_ACTIVE] = 0
    next
    vGridOffsetY = -200
endproc

rem ==================================================================
rem Add an enemy bullet moving from (x, y) to player's position.
rem ==================================================================
procedure AddEnemyBullet(x, y)
    vEnemyBullets[vEnemyBulletCounter][BULLET_ACTIVE] = true
    vEnemyBullets[vEnemyBulletCounter][BULLET_FRAME] = 0
    vEnemyBulletsF[vEnemyBulletCounter][BULLET_X] = float(x)
    vEnemyBulletsF[vEnemyBulletCounter][BULLET_Y] = float(y)
    dx# = float(vPlayerX) - float(x)
    dy# = float(vPlayerY) - float(y)
    k# = 1.0/sqr(dx*dx + dy*dy)
    vEnemyBulletsF[vEnemyBulletCounter][BULLET_DX] = dx*k*2.0
    vEnemyBulletsF[vEnemyBulletCounter][BULLET_DY] = dy*k*2.0
    vEnemyBulletCounter = (vEnemyBulletCounter + 1)%MAX_ENEMY_BULLETS
endproc

rem ==================================================================
rem Update enemy bullets.
rem ==================================================================
procedure UpdateEnemyBullets()
    for i = 0 to MAX_ENEMY_BULLETS - 1
        if vEnemyBullets[i][BULLET_ACTIVE]
            vEnemyBullets[i][BULLET_FRAME] = (vEnemyBullets[i][BULLET_FRAME] + 1)%20
            vEnemyBulletsF[i][BULLET_X] = vEnemyBulletsF[i][BULLET_X] + vEnemyBulletsF[i][BULLET_DX]
            vEnemyBulletsF[i][BULLET_Y] = vEnemyBulletsF[i][BULLET_Y] + vEnemyBulletsF[i][BULLET_DY]
            if not vGameOver
                if ImageCol(ENEMY_BULLET_IMAGE, int(vEnemyBulletsF[i][BULLET_X]), int(vEnemyBulletsF[i][BULLET_Y]), PLAYER_IMAGE, vPlayerX, vPlayerY)
                    vEnemyBullets[i][BULLET_ACTIVE] = false
                    proc LoseLife
                endif
            endif
        endif
    next
endproc

rem ==================================================================
rem Draw enemy bullets.
rem ==================================================================
procedure DrawEnemyBullets()
    for i = 0 to MAX_ENEMY_BULLETS - 1
        if vEnemyBullets[i][BULLET_ACTIVE]
            draw image ENEMY_BULLET_IMAGE, int(vEnemyBulletsF[i][BULLET_X]), int(vEnemyBulletsF[i][BULLET_Y]), vEnemyBullets[i][BULLET_FRAME]/10
        endif
    next
endproc

rem ==================================================================
rem Return the x coordinate of an enemy at grid position (x, y).
rem ==================================================================
function GridX(x, y)
    return (320 - GRID_WIDTH*CEL_SIZE)/2 + x*CEL_SIZE + int(cos(vGridMotionAngle + float(y*24))*24.0)
endfunc

rem ==================================================================
rem Return the y coordinate of an enemy at a certain grid y.
rem ==================================================================
function GridY(y)
    return 24 + y*CEL_SIZE + vGridOffsetY
endfunc

rem ==================================================================
rem Update enemies.
rem ==================================================================
procedure UpdateEnemies()
    if vGridOffsetY < 0 then vGridOffsetY = vGridOffsetY + 1
    vEnemyBulletTimer = vEnemyBulletTimer - 1
    rem Update enemy attacks.
    vNextAttackTimer = vNextAttackTimer - 1
    if vNextAttackTimer <= 0
        rem Look for enemies that can attack and add them to a list.
        attackers[GRID_WIDTH*GRID_HEIGHT]
        count = 0
        for y = 0 to GRID_HEIGHT - 1
            for x = 0 to GRID_WIDTH - 1
                if vEnemies[x][y][ENEMY_TYPE] > 0 and vEnemies[x][y][ENEMY_STATE] = 0
                    rem Add enemy to list of possible attackers. Convert its position
                    rem in the grid to an index.
                    attackers[count] = y*GRID_WIDTH + x
                    count = count + 1
                endif
            next    
        next
        rem Any one interested?
        if count > 0
            rem Get any enemy from the list.
            enemy = attackers[rnd(count)]
            rem Convert its position back to the 2D grid.
            x = enemy%GRID_WIDTH
            y = enemy/GRID_WIDTH
            rem Init its attack curve.
            vEnemies[x][y][ENEMY_STATE] = 1
            vEnemiesF[x][y][ENEMY_PARAM] = 0.0
            vEnemiesF[x][y][ENEMY_X1] = float(rnd(320))
            vEnemiesF[x][y][ENEMY_X2] = float(rnd(320))
            vEnemiesF[x][y][ENEMY_Y1] = 400.0
            vEnemiesF[x][y][ENEMY_Y2] = float(GridY(y) - 100)
            rem Wait some until next attack.
            vNextAttackTimer = max(200 + rnd(100) - vLevel*50, 50)
        else
            vNextAttackTimer = 50
        endif
    endif

    rem Move enemies.
    for y = 0 to GRID_HEIGHT - 1
        for x = 0 to GRID_WIDTH - 1
            if vEnemies[x][y][ENEMY_TYPE] > 0
                vEnemies[x][y][ENEMY_FRAME] = (vEnemies[x][y][ENEMY_FRAME] + 1)%60
                gx = GridX(x, y)
                gy = GridY(y)
                rem Is it attacking?
                if vEnemies[x][y][ENEMY_STATE] = 1
                    rem Shoot?
                    prm# = vEnemiesF[x][y][ENEMY_PARAM]
                    if vEnemyBulletTimer <= 0 and ((prm > 0.05 and prm < 0.1) or prm > 0.75)
                        vEnemyBulletTimer = 50 + rnd(100)
                        proc AddEnemyBullet vEnemies[x][y][ENEMY_X], vEnemies[x][y][ENEMY_Y]
                    endif
                    rem Update position.
                    vEnemiesF[x][y][ENEMY_PARAM] = vEnemiesF[x][y][ENEMY_PARAM] + 0.0025
                    rem Back at where it started?
                    if vEnemiesF[x][y][ENEMY_PARAM] >= 1.0
                        vEnemies[x][y][ENEMY_STATE] = 0
                        vEnemies[x][y][ENEMY_X] = gx + 2
                        vEnemies[x][y][ENEMY_Y] = gy + 6
                        vEnemies[x][y][ENEMY_BASE_FRAME] = 0
                    else
                        p[] = FlyingEnemyPos(vEnemiesF[x][y][ENEMY_PARAM], float(gx), float(gy), vEnemiesF[x][y][ENEMY_X1], vEnemiesF[x][y][ENEMY_Y1], vEnemiesF[x][y][ENEMY_X2], vEnemiesF[x][y][ENEMY_Y2])
                        vEnemies[x][y][ENEMY_X] = p[0] + 4
                        vEnemies[x][y][ENEMY_Y] = p[1] + 6
                        vEnemies[x][y][ENEMY_BASE_FRAME] = FlyingEnemyDir(vEnemiesF[x][y][ENEMY_PARAM], float(gx), float(gy), vEnemiesF[x][y][ENEMY_X1], vEnemiesF[x][y][ENEMY_Y1], vEnemiesF[x][y][ENEMY_X2], vEnemiesF[x][y][ENEMY_Y2])
                    endif
                else
                    vEnemies[x][y][ENEMY_X] = gx + 2
                    vEnemies[x][y][ENEMY_Y] = gy + 6
                endif

                if ImageCol(vEnemies[x][y][ENEMY_TYPE] + ENEMY_IMAGE_BASE, vEnemies[x][y][ENEMY_X], vEnemies[x][y][ENEMY_Y], PLAYER_IMAGE, vPlayerX, vPlayerY)
                    proc LoseLife
                endif

                rem Hit by player bullet?
                if vPlayerBulletType > 0
                    if ImageCol(vEnemies[x][y][ENEMY_TYPE] + ENEMY_IMAGE_BASE, vEnemies[x][y][ENEMY_X], vEnemies[x][y][ENEMY_Y], PLAYER_BULLETS_IMAGE, vPlayerBulletX, vPlayerBulletY)
                        vPlayerBulletType = 0
                        vEnemies[x][y][ENEMY_STAMINA] = vEnemies[x][y][ENEMY_STAMINA] - 1
                        if vEnemies[x][y][ENEMY_STAMINA] = 0
                            img = ENEMY_IMAGE_BASE + vEnemies[x][y][ENEMY_TYPE]
                            proc AddExplosion vEnemies[x][y][ENEMY_X] + width(img)/2, vEnemies[x][y][ENEMY_Y] + height(img)/2
                            if vEnemies[x][y][ENEMY_STATE] = 1
                                vScore = vScore + 20*vEnemies[x][y][ENEMY_TYPE]
                            else
                                vScore = vScore + 10*vEnemies[x][y][ENEMY_TYPE]
                            endif
                            vEnemies[x][y][ENEMY_TYPE] = 0
                            vEnemyCount = vEnemyCount - 1
                        else
                            play sound ENEMY_HIT_SOUND
                        endif
                    endif
                endif

            endif
        next
    next
endproc

rem ==================================================================
rem Return true if two image at specific locations intersect.
rem ==================================================================
function ImageCol(img0, x0, y0, img1, x1, y1)
    if x0 + width(img0) < x1 then return false
    if y0 + height(img0) < y1 then return false
    if x1 + width(img1) < x0 then return false
    if y1 + height(img1) < y0 then return false
    return true
endfunc

rem ==================================================================
rem Calculate position for an attacking enemy. It's a special case of
rem a cubic bezier curve, where the start and end point are the same.
rem ==================================================================
function FlyingEnemyPos[](param#, x#, y#, x1#, y1#, x2#, y2#)
    param = max#(param, 0.0)
    param = min#(param, 1.0)
    b0# = 1.0 - param
    b0 = b0*b0*b0
    b1# = 1.0 - param
    b1 = b1*b1
    b1 = b1*3.0*param
    b2# = 3.0*(1.0 - param)*param*param
    b3# = param*param*param
    return [int(b0*x + b1*x1 + b2*x2 + b3*x), int(b0*y + b1*y1 + b2*y2 + b3*y)]
endfunc

rem ==================================================================
rem Return direction for enemy (a base frame for its image grid).
rem Think I've messed up the code a little here ... never mind.
rem ==================================================================
function FlyingEnemyDir(param#, x#, y#, x1#, y1#, x2#, y2#)
    b0# = 1.0 - param
    b0 = -3.0*b0*b0
    b1# = 1.0 - param
    b1 = 3.0*b1 - 6.0*param*b1
    b2# = 6.0*param*(1.0 - param) - 3.0*param*param
    b3# = 3.0*param*param
    dx# = b0*x + b1*x1 + b2*x2 + b3*x
    dy# = b0*y + b1*y1 + b2*y2 + b3*y
    k# = 1.0/sqr(dx*dx + dy*dy)
    dx = dx*k
    dy = dy*k
    
    if dy <= 0.0
        if abs#(dx) < 0.25
            ret = 0
        else
            if dx < 0.0
                ret = 8
            else
                ret = 10
            endif
        endif
    else
        if abs#(dx) < 0.25
            ret = 2
        else
            if dx < 0.0
                ret = 6
            else
                ret = 4
            endif
        endif
    endif
    return ret
endproc

rem ==================================================================
rem Draw enemies.
rem ==================================================================
procedure DrawEnemies()
    for y = 0 to GRID_HEIGHT - 1
        for x = 0 to GRID_WIDTH - 1
            if vEnemies[x][y][ENEMY_TYPE] > 0
                set color 255, 255, 255
                draw image ENEMY_IMAGE_BASE + vEnemies[x][y][ENEMY_TYPE], vEnemies[x][y][ENEMY_X], vEnemies[x][y][ENEMY_Y], vEnemies[x][y][ENEMY_BASE_FRAME] + vEnemies[x][y][ENEMY_FRAME]/30
            endif
        next
    next
endproc

rem ==================================================================
rem Init frame hold
rem ==================================================================
procedure InitFrameHold(speed)
    vNextFrameTime = time()
    vFrameHold = 1000/speed
endproc

rem ==================================================================
rem Hold frame to maintain constant speed.
rem ==================================================================
procedure HoldFrame()
    while time() < vNextFrameTime; wait 1; wend
    vNextFrameTime = vNextFrameTime + vFrameHold
endproc

Ohh nice. I think so

(02-12-2026, 05:42 PM)Marcus Wrote: [ -> ]I think Blastemroids was one of the first games I wrote in naalaa Smile

Hey Marcus, do you happen to have a copy of this game? Just asking out of pure nostalgia.
I'll have a look at a backup drive tomorrow!
Hi, sorry to butt in, but I can see that this was included in the N6 distribution in the examples folder (examples/games). If you no longer have N6 installed, it can still be downloaded from Naalaa.com home page.
Hope this helps......

Edit - I just tried running the program here, and found that I had to change the lines with "set image colorkey" in, replacing "0,0,0" with "true" in each case. Not sure why (perhaps I have an older version), but it seems to run fine with those changes.
(02-13-2026, 05:05 PM)kevin Wrote: [ -> ]Hi, sorry to butt in, but I can see that this was included in the N6 distribution in the examples folder (examples/games). If you no longer have N6 installed, it can still be downloaded from Naalaa.com home page.
Hope this helps......

Edit - I just tried running the program here, and found that I had to change the lines with "set image colorkey" in, replacing "0,0,0" with "true" in each case. Not sure why (perhaps I have an older version), but it seems to run fine with those changes.

Is it?

[Image: froc-froccoli.gif]

let me check

Yessssss! This is the one ?. Thanks everyone.

[Image: Screenshot-2026-02-13-233745.png]

Absolute Nostalgia. I remember my college days.
I think that i tried this shooter
looking great!!!