Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
AI Experiment
#1
I had asked Gemini to generate naalaa/n7 code before, but it failed pretty badly. But now I tried giving it some "training" code:

Code:
' A "game" where you pick up bouncing objects.

' Constants for screen size.
constant SCREEN_W = 320, SCREEN_H = 240

' Global variables (visible inside functions).
visible vPlayer, vBouncers

' Create window of size 320x240, not fullscreen, and upscaled by 2.
set window "A Game", SCREEN_W, SCREEN_H, false, 2
' Turn off automatic redraw, meaning we need to call 'redraw' to copy the backbuffer to the window.
set redraw off

' Set up player, start at center of screen.
vPlayer = [
        x: SCREEN_W/2 - 8, y: SCREEN_H/2 - 8,
        w: 16, h: 16,
        r: 255, g: 255, b: 255]
        
' Set up 100 bouncers, which are moving objects that the player can pick up.
vBouncers = []
for i = 1 to 100
    ' Size, direction and speed.
    side = 4 + rnd(20)
    moveAngle = rnd()*2*PI
    speed = 0.5 + rnd()*2.5
    ' Add object last in array.
    vBouncers[sizeof(vBouncers)] = [
            x: rnd(SCREEN_W - side), y: rnd(SCREEN_H - side),
            w: side, h: side,
            dx: cos(moveAngle)*speed, dy: sin(moveAngle)*speed,
            r: 64 + rnd(128), g: 64 + rnd(128), b: 64 + rnd(128)]
next

' Loop while escape key isn't pressed.
while not keydown(KEY_ESCAPE)
    ' Update sprites.
    UpdatePlayer()
    UpdateBouncers()
    
    ' Clear screen with black color.
    set color 0, 0, 0
    cls
    
    ' Draw sprites.
    DrawSprite(vPlayer)
    foreach b in vBouncers
        DrawSprite(b)
    next
    
    ' Display the number of bouncers that are left to pick up at the top of the screen.
    set caret SCREEN_W/2, 4
    set color 255, 255, 255    
    center "BOUNCERS: " + sizeof(vBouncers)

    ' Copy backbuffer to window.
    redraw
    ' Wait to cap fps at 60.
    fwait 60
wend

' Update player function.
function UpdatePlayer()
    ' Move with arrow keys.
    if keydown(KEY_LEFT) vPlayer.x = max(vPlayer.x - 1, 0)
    if keydown(KEY_RIGHT) vPlayer.x = min(vPlayer.x + 1, SCREEN_W - vPlayer.w)
    if keydown(KEY_UP) vPlayer.y = max(vPlayer.y - 1, 0)
    if keydown(KEY_DOWN) vPlayer.y = min(vPlayer.y + 1, SCREEN_H - vPlayer.h)
endfunc

' Update bouncers.
function UpdateBouncers()
    i = 0
    while i < sizeof(vBouncers)
        ' UpdateBouncer returns true if bouncer has not been picked up by player.
        if UpdateBouncer(vBouncers[i])
            i = i + 1
        else
            ' Free index i from vBouncers.
            free key vBouncers, i
        endif
    wend
endfunc

' Update bouncer, return 'false' if it should be removed because of collision with player.
function UpdateBouncer(b)
    ' Move.
    b.x = b.x + b.dx
    b.y = b.y + b.dy
    ' Bounce on screen borders.
    if b.x < 0
        b.x = 0
        b.dx = -b.dx
    elseif b.x > SCREEN_W - b.w
        b.x = SCREEN_W - b.w
        b.dx = -b.dx
    endif
    if b.y < 0
        b.y = 0
        b.dy = -b.dy
    elseif b.y > SCREEN_H - b.h
        b.y = SCREEN_H - b.h
        b.dy = -b.dy
    endif
    ' Return 'true' if not colliding with player.
    return not SpritesOverlap(vPlayer, b)
endfunc

' Return true if two sprites (any object with 'x', 'y', 'w' and 'h' fields) collide.
function SpritesOverlap(a, b)
    return a.x + a.w > b.x and a.x < b.x + b.w and a.y + a.h > b.y and a.y < b.y + b.h
endfunc

' Draw sprite (any object with 'x', 'y', 'w', 'h', 'r', 'g' and 'b' fields) as rectangle.
function DrawSprite(s)
    ' Set color and draw filled rectangle.
    set color s.r, s.g, s.b
    draw rect s.x, s.y, s.w, s.h, true
endfunc

, and asked it if it could generate other games in the same language. Gemini generated a shootemup and a platform "game", both without any errors:

Code:
' A simple "Shoot 'em up" game in Naalaa 7.
constant SCREEN_W = 320, SCREEN_H = 240

visible vPlayer, vBullets, vEnemies, vSpawnTimer

' Initialize the window
set window "Space Shooter", SCREEN_W, SCREEN_H, false, 2
set redraw off

' Set up player at the bottom of the screen
vPlayer = [
        x: SCREEN_W/2 - 8, y: SCREEN_H - 24,
        w: 16, h: 12,
        r: 0, g: 255, b: 255] ' Cyan player

vBullets = []
vEnemies = []
vSpawnTimer = 0

' Main game loop
while not keydown(KEY_ESCAPE)
    UpdatePlayer()
    UpdateBullets()
    UpdateEnemies()
    
    ' Clear screen with black color
    set color 0, 0, 0
    cls
    
    ' Draw all entities
    DrawSprite(vPlayer)
    
    foreach b in vBullets
        DrawSprite(b)
    next
    
    foreach e in vEnemies
        DrawSprite(e)
    next
    
    redraw
    fwait 60
wend

' ---- FUNCTIONS ----

function UpdatePlayer()
    ' Move left and right
    if keydown(KEY_LEFT) vPlayer.x = max(vPlayer.x - 2, 0)
    if keydown(KEY_RIGHT) vPlayer.x = min(vPlayer.x + 2, SCREEN_W - vPlayer.w)
    
    ' Shoot with SPACE (includes a slight delay so you cannot laser-spam too fast)
    if keydown(KEY_SPACE)
        if sizeof(vBullets) = 0 or vBullets[sizeof(vBullets)-1].y < vPlayer.y - 30
            ' Add a new bullet moving upwards (dy = -4)
            vBullets[sizeof(vBullets)] = [
                    x: vPlayer.x + vPlayer.w/2 - 2, y: vPlayer.y - 6,
                    w: 4, h: 6,
                    dy: -4,
                    r: 255, g: 255, b: 0] ' Yellow bullet
        endif
    endif
endfunc

function UpdateBullets()
    i = 0
    while i < sizeof(vBullets)
        ' Move bullet upwards
        vBullets[i].y = vBullets[i].y + vBullets[i].dy
        
        ' If the bullet leaves the top of the screen, remove it
        if vBullets[i].y < -vBullets[i].h
            free key vBullets, i
        else
            i = i + 1
        endif
    wend
endfunc

function UpdateEnemies()
    ' Spawn a new enemy every 45 frames (roughly every 0.75 seconds)
    vSpawnTimer = vSpawnTimer + 1
    if vSpawnTimer >= 45
        vSpawnTimer = 0
        vEnemies[sizeof(vEnemies)] = [
                x: rnd(SCREEN_W - 16), y: -16,
                w: 16, h: 16,
                dy: 1 + rnd()*1.5, ' Randomized downward speed
                r: 255, g: 64, b: 64] ' Red enemy
    endif

    ' Update and handle collisions for enemies
    i = 0
    while i < sizeof(vEnemies)
        vEnemies[i].y = vEnemies[i].y + vEnemies[i].dy
        
        enemyHit = false
        
        ' Check if this enemy collides with ANY bullet
        j = 0
        while j < sizeof(vBullets)
            if SpritesOverlap(vEnemies[i], vBullets[j])
                enemyHit = true
                free key vBullets, j ' Remove the bullet
                break ' Exit the bullet loop since the enemy is already hit
            else
                j = j + 1
            endif
        wend
        
        ' Handle enemy cleanup (on hit or if it moves off screen)
        if enemyHit
            free key vEnemies, i
        elseif vEnemies[i].y > SCREEN_H
            free key vEnemies, i ' Enemy passed the player
        else
            i = i + 1
        endif
    wend
endfunc

' Standard collision detection
function SpritesOverlap(a, b)
    return a.x + a.w > b.x and a.x < b.x + b.w and a.y + a.h > b.y and a.y < b.y + b.h
endfunc

' Standard rendering routine
function DrawSprite(s)
    set color s.r, s.g, s.b
    draw rect s.x, s.y, s.w, s.h, true
endfunc

Code:
' A simple platformer game in Naalaa 7.
constant SCREEN_W = 320, SCREEN_H = 240

visible vPlayer, vPlatforms

' Setup window
set window "Platformer", SCREEN_W, SCREEN_H, false, 2
set redraw off

' Player object (added dy for vertical velocity and onGround state)
vPlayer = [
        x: 40, y: 100,
        w: 12, h: 16,
        dy: 0.0,
        onGround: false,
        r: 0, g: 255, b: 0] ' Green player

' Array to hold all solid platforms
vPlatforms = []

' Level Design: Add floor and a few platforms
' Floor
vPlatforms[sizeof(vPlatforms)] = [x: 0, y: SCREEN_H - 16, w: SCREEN_W, h: 16, r: 128, g: 128, b: 128]
' Platform 1
vPlatforms[sizeof(vPlatforms)] = [x: 60, y: 160, w: 80, h: 10, r: 180, g: 100, b: 40]
' Platform 2
vPlatforms[sizeof(vPlatforms)] = [x: 180, y: 120, w: 80, h: 10, r: 180, g: 100, b: 40]

' Main game loop
while not keydown(KEY_ESCAPE)
    UpdatePlayer()
    
    ' Render
    set color 0, 0, 0
    cls
    
    ' Draw level and player
    foreach p in vPlatforms
        DrawSprite(p)
    next
    DrawSprite(vPlayer)
    
    redraw
    fwait 60
wend

' ---- FUNCTIONS ----

function UpdatePlayer()
    ' 1. Horizontal movement
    if keydown(KEY_LEFT) vPlayer.x = max(vPlayer.x - 2, 0)
    if keydown(KEY_RIGHT) vPlayer.x = min(vPlayer.x + 2, SCREEN_W - vPlayer.w)
    
    ' 2. Gravity (constantly pull the player down)
    vPlayer.dy = vPlayer.dy + 0.2
    
    ' Terminal velocity (don't fall infinitely fast)
    if vPlayer.dy > 6.0 vPlayer.dy = 6.0
    
    ' Apply vertical movement
    vPlayer.y = vPlayer.y + vPlayer.dy
    
    ' 3. Collision Detection with Platforms
    vPlayer.onGround = false
    
    foreach p in vPlatforms
        if SpritesOverlap(vPlayer, p)
            ' Check if player is falling down into the platform
            if vPlayer.dy > 0
                ' Snap player to the top of the platform
                vPlayer.y = p.y - vPlayer.h
                vPlayer.dy = 0
                vPlayer.onGround = true
            endif
        endif
    next
    
    ' 4. Jumping (Only allowed if standing on a solid surface)
    if keydown(KEY_UP) and vPlayer.onGround
        vPlayer.dy = -4.5 ' Negative velocity moves upwards
        vPlayer.onGround = false
    endif
endfunc

' Reusing your exact layout-logic for rendering and box-overlap
function SpritesOverlap(a, b)
    return a.x + a.w > b.x and a.x < b.x + b.w and a.y + a.h > b.y and a.y < b.y + b.h
endfunc

function DrawSprite(s)
    set color s.r, s.g, s.b
    draw rect s.x, s.y, s.w, s.h, true
endfunc

Then I asked if it could create a breakout game:

Code:
' A classic Breakout game in Naalaa 7.
constant SCREEN_W = 320, SCREEN_H = 240

visible vPaddle, vBall, vBricks

' Initialize window
set window "Breakout", SCREEN_W, SCREEN_H, false, 2
set redraw off

' Set up the player's paddle
vPaddle = [
        x: SCREEN_W/2 - 20, y: SCREEN_H - 20,
        w: 40, h: 8,
        r: 255, g: 255, b: 255] ' White paddle

' Set up the ball (with dx and dy for directional movement)
vBall = [
        x: SCREEN_W/2 - 3, y: SCREEN_H/2,
        w: 6, h: 6,
        dx: 1.5, dy: -1.5,
        r: 255, g: 255, b: 0] ' Yellow ball

' Set up a grid of bricks
vBricks = []
for row = 0 to 4
    for col = 0 to 9
        ' Calculate positions to make a nice grid
        vBricks[sizeof(vBricks)] = [
                x: 16 + col * 29, y: 30 + row * 12,
                w: 25, h: 8,
                r: 50 + row * 40, g: 255 - row * 40, b: 100 + col * 15]
    next
next

' Main game loop
while not keydown(KEY_ESCAPE) and sizeof(vBricks) > 0
    UpdatePaddle()
    UpdateBall()
    
    ' Clear screen with black color
    set color 0, 0, 0
    cls
    
    ' Draw all game elements
    DrawSprite(vPaddle)
    DrawSprite(vBall)
    foreach b in vBricks
        DrawSprite(b)
    next
    
    ' Display score / remaining bricks
    set caret 4, 4
    set color 255, 255, 255
    write "BRICKS LEFT: " + sizeof(vBricks)
    
    redraw
    fwait 60
    
    ' Game over check (if ball falls past the paddle)
    if vBall.y > SCREEN_H
        ' Optional: Reset ball position instead of closing instantly
        vBall.x = SCREEN_W/2 - 3
        vBall.y = SCREEN_H/2
        vBall.dy = -1.5
    endif
wend

' ---- FUNCTIONS ----

function UpdatePaddle()
    ' Move paddle left and right with boundaries
    if keydown(KEY_LEFT) vPaddle.x = max(vPaddle.x - 3, 0)
    if keydown(KEY_RIGHT) vPaddle.x = min(vPaddle.x + 3, SCREEN_W - vPaddle.w)
endfunc

function UpdateBall()
    ' Move the ball by its velocity vectors
    vBall.x = vBall.x + vBall.dx
    vBall.y = vBall.y + vBall.dy
    
    ' Bounce on left and right screen borders
    if vBall.x < 0
        vBall.x = 0
        vBall.dx = -vBall.dx
    elseif vBall.x > SCREEN_W - vBall.w
        vBall.x = SCREEN_W - vBall.w
        vBall.dx = -vBall.dx
    endif
    
    ' Bounce on the ceiling
    if vBall.y < 0
        vBall.y = 0
        vBall.dy = -vBall.dy
    endif
    
    ' Collision detection: Ball vs Paddle
    if SpritesOverlap(vBall, vPaddle)
        ' Always push the ball upwards when it hits the paddle
        vBall.y = vPaddle.y - vBall.h
        vBall.dy = -vBall.dy
        
        ' Dynamic angle modification based on where it hits the paddle
        ' (Hits the left side -> moves more left, hits right -> moves more right)
        paddleCenter = vPaddle.x + vPaddle.w / 2
        ballCenter = vBall.x + vBall.w / 2
        vBall.dx = (ballCenter - paddleCenter) / 5
    endif
    
    ' Collision detection: Ball vs Bricks
    i = 0
    while i < sizeof(vBricks)
        if SpritesOverlap(vBall, vBricks[i])
            ' Invert vertical speed upon impact
            vBall.dy = -vBall.dy
            
            ' Remove the destroyed brick
            free key vBricks, i
            
            ' Break out early so we don't process multiple bricks in one frame
            break
        else
            i = i + 1
        endif
    wend
endfunc

' Standard collision detection
function SpritesOverlap(a, b)
    return a.x + a.w > b.x and a.x < b.x + b.w and a.y + a.h > b.y and a.y < b.y + b.h
endfunc

' Standard rendering routine
function DrawSprite(s)
    set color s.r, s.g, s.b
    draw rect s.x, s.y, s.w, s.h, true
endfunc

So, if you want to use AI for generating n7 code, give it a training program to look at first Smile
Reply
#2
Am I impressed by the programs it generated? No, not really, haha Smile But I am impressed by the fact that it wrote functional n7 code from looking at the sample program I provided.
Reply
#3
I too have been experimenting with AI on a whole range of games with varying degrees of success. The one thing I did notice was, the AI accessed any online documentation to check for syntax. It would then make suggestions as to how to improve the game.

The whole concept is impressive but the amount of errors, even though a few, is reason enough not to rely on this concept until it is "more mature". Even though the results were not as "pretty" as hoped, It did create a very efficient piece of code. Using it to learn "how to" code properly is a big plus.

I have not tried Gemini. I use either ChatGPT, Copilot or Grok. By the way, AI does an excellent job cleaning up and enhancing old "black and white" photos (even adding colour).
Logic is the beginning of wisdom.

Live long and prosper.
Reply
#4
Yeah, and as I said, I wasn't impressed by the code, just by the fact that Gemini produced working n7 programs. Let me quote ... someone: "It's interesting how Al is constantly providing false information and incorrect statements about my area of expertise. Fortunately, it's very useful and always right about topics I know very little about."
Reply
#5
Hey in my company we have to use Claude and use SDD, speck development driven so AI can take over my job and we just need to do the specs and for that only a couple of users can do the job. It's inevitable I guess.
Reply
#6
well i tried and platformer code work
nice i will ask AI about trranslation...
Reply
#7
Here's another example where I gave gemini the 3d_text.n7 source code from the demo folder. I asked it to generate a function for creating a torus mesh using the s3d functions. Then I told it to "bake" some lighting into the mesh using one color per face. Sorry, I gave instructions in Swedish, so the comments are Swedish.

Code:
#win32

include "s3d.n7"

res = 480

set window "3D Torus", res*min(screenw()/screenh(), 2), res, true
set redraw off

S3D_SetView(primary, rad(90), 0.1, 50)

'mesh = Create3DTorus(20, 7.5, 16, 8, 128, 128, 128)
mesh = Create3DTorusWithLighting(20, 7.5, 16, 8, 255, 255, 255)

a = 0
do
    ay = (ay + 1)%360
    ax = (ax + 0.55)%360
  
    set color 0, 0, 0, 64
    cls
    S3D_Clear()
    S3D_Translate(0, 0, 4.5)
    S3D_Scale(0.1, 0.1, 0.1)
    S3D_RotateY(sin(rad(ay))*rad(65))
    S3D_RotateX(sin(rad(ax))*rad(22.5))
    S3D_RotateZ(sin(rad(ax*2))*rad(22.5))
    S3D_Mesh(mesh, 0)

    fwait 60    
    redraw
until keydown(KEY_ESCAPE)

' Create3DTorus
' -------------
' R: Stora radien (avstånd till rörets centrum)
' r: Lilla radien (rörets tjocklek)
' segmentsR: Antal segment runt stora cirkeln
' segmentsRor: Antal segment runt röret
function Create3DTorus(R, r, segmentsR, segmentsRor, rtop, gtop, btop)
    mesh = S3D_BeginMesh()
    S3D_Begin(S3D_QUADS)
    
    ' Vi sätter en grundfärg, du kan självklart lägga till texturering/gradienter här
    S3D_Color(rtop, gtop, btop)
    
    for i = 0 to segmentsR - 1
        phi1 = (i / segmentsR) * 2 * float(PI)
        phi2 = ((i + 1) / segmentsR) * 2 * float(PI)
        
        for j = 0 to segmentsRor - 1
            theta1 = (j / segmentsRor) * 2 * float(PI)
            theta2 = ((j + 1) / segmentsRor) * 2 * float(PI)
            
            ' Vertex 1
            x1 = (R + r * cos(theta1)) * cos(phi1)
            y1 = (R + r * cos(theta1)) * sin(phi1)
            z1 = r * sin(theta1)
            
            ' Vertex 2
            x2 = (R + r * cos(theta2)) * cos(phi1)
            y2 = (R + r * cos(theta2)) * sin(phi1)
            z2 = r * sin(theta2)
            
            ' Vertex 3
            x3 = (R + r * cos(theta2)) * cos(phi2)
            y3 = (R + r * cos(theta2)) * sin(phi2)
            z3 = r * sin(theta2)
            
            ' Vertex 4
            x4 = (R + r * cos(theta1)) * cos(phi2)
            y4 = (R + r * cos(theta1)) * sin(phi2)
            z4 = r * sin(theta1)
            
            ' Skicka till s3d
            S3D_Vertex(x1, y1, z1, 0, 0)
            S3D_Vertex(x2, y2, z2, 0, 0)
            S3D_Vertex(x3, y3, z3, 0, 0)
            S3D_Vertex(x4, y4, z4, 0, 0)
        next
    next
    
    S3D_End()
    S3D_EndMesh()
    
    return mesh
endfunc

' Create3DTorusWithLighting
' -------------------------
function Create3DTorusWithLighting(R, r, segmentsR, segmentsRor, baseR, baseG, baseB)
    mesh = S3D_BeginMesh()
    S3D_Begin(S3D_QUADS)
    
    ' Definiera en riktad ljuskälla ( directional light )
    ' Denna vektor pekar mot ljuset och bör vara normaliserad (längd 1)
    lx = 0.577
    ly = 0.577
    lz = -0.577 ' Negativt Z om kameran tittar i positiv Z-led
    
    ' Omgivningsljus (ambient) så att skuggsidan inte blir kolsvart
    ambient = 0.2
    
    for i = 0 to segmentsR - 1
        phi1 = (i / segmentsR) * 2 * float(PI)
        phi2 = ((i + 1) / segmentsR) * 2 * float(PI)
        
        for j = 0 to segmentsRor - 1
            theta1 = (j / segmentsRor) * 2 * float(PI)
            theta2 = ((j + 1) / segmentsRor) * 2 * float(PI)
            
            ' Beräkna de 4 hörnens positioner
            x1 = (R + r * cos(theta1)) * cos(phi1)
            y1 = (R + r * cos(theta1)) * sin(phi1)
            z1 = r * sin(theta1)
            
            x2 = (R + r * cos(theta2)) * cos(phi1)
            y2 = (R + r * cos(theta2)) * sin(phi1)
            z2 = r * sin(theta2)
            
            x3 = (R + r * cos(theta2)) * cos(phi2)
            y3 = (R + r * cos(theta2)) * sin(phi2)
            z3 = r * sin(theta2)
            
            x4 = (R + r * cos(theta1)) * cos(phi2)
            y4 = (R + r * cos(theta1)) * sin(phi2)
            z4 = r * sin(theta1)
            
            ' --- BAKAD LJUSSÄTTNING (Flat Shading) ---
            ' Vi räknar ut ytans mittpunkt för att få en approximativ normalvektor.
            ' För en torus pekar normalen från rörets centrum (cx, cy, cz) ut mot ytan.
            cx = R * cos((phi1 + phi2) / 2)
            cy = R * sin((phi1 + phi2) / 2)
            cz = 0
            
            mx = (x1 + x2 + x3 + x4) / 4
            my = (y1 + y2 + y3 + y4) / 4
            mz = (z1 + z2 + z3 + z4) / 4
            
            ' Normalvektorn (från rör-centrum till quad-mitt)
            nx = mx - cx
            ny = my - cy
            nz = mz - cz
            
            ' Normalisera normalen så den har längden 1
            length = sqr(nx*nx + ny*ny + nz*nz)
            if length > 0
                nx = nx / length
                ny = ny / length
                nz = nz / length
            endif
            
            ' Skalärprodukt (Dot Product) mellan normalen och ljusvektorn
            ' Ger ett värde mellan -1.0 och 1.0
            dot = nx*lx + ny*ly + nz*lz
            if dot < 0 then dot = 0 ' Klipp negativt ljus
            
            ' Slutgiltig ljusstyrka (ambient + diffust ljus)
            intensity = ambient + (1.0 - ambient) * dot
            if intensity > 1.0 then intensity = 1.0
            
            ' Applicera den bakade färgen på denna quad
            S3D_Color(baseR * intensity, baseG * intensity, baseB * intensity)
            
            ' Skicka vertexar till s3d
            S3D_Vertex(x1, y1, z1, 0, 0)
            S3D_Vertex(x2, y2, z2, 0, 0)
            S3D_Vertex(x3, y3, z3, 0, 0)
            S3D_Vertex(x4, y4, z4, 0, 0)
        next
    next
    
    S3D_End()
    S3D_EndMesh()
    
    return mesh
endfunc
Reply
#8
me  :  I don't know how to develop beat'em up game like Streets of Rage in Naalaa. Teach me.

Gemini   : 

To create a beat 'em up game like Streets of Rage in Naalaa, we need to implement a state machine to manage character animations (Idle, Walk, Punch, etc.) and a Z-axis layering system to simulate depth.

The following structure provides the core logic for your 1990s-style game. You would replace the placeholder image paths with your actual .png sprite sheets.

Code:
' Streets of Rage-style Engine Template
constant SCREEN_W = 640, SCREEN_H = 480
set window "Retro Brawl", SCREEN_W, SCREEN_H, false, 1
set redraw off

' Character State Constants
constant STATE_IDLE = 0, STATE_WALK = 1, STATE_PUNCH = 2, STATE_FALL = 3, STATE_DIE = 4

' Define Player Struct
visible vPlayer = [
    x: 100, y: 300, z: 0,
    hp: 100,
    state: STATE_IDLE,
    animFrame: 0,
    dir: 1 ' 1 for Right, -1 for Left
]

' Load Sprites (Assumes you have a folder of sprite strips)
' imgPlayer = loadimage("hero_strip.png")

while not keydown(KEY_ESCAPE)
    cls
   
    ' 1. Logic
    UpdatePlayer()
    UpdateEnemies()
   
    ' 2. Rendering (Sort by Y position for depth)
    ' This simulates the "Street" perspective where objects
    ' higher on the screen are further back.
    DrawBackground()
    DrawCharacters()
   
    ' 3. HUD
    DrawHUD()
   
    redraw
    fwait 60
wend

function UpdatePlayer()
    ' Movement logic with bounds
    if keydown(KEY_LEFT)
        vPlayer.x = vPlayer.x - 2
        vPlayer.dir = -1
        vPlayer.state = STATE_WALK
    elseif keydown(KEY_RIGHT)
        vPlayer.x = vPlayer.x + 2
        vPlayer.dir = 1
        vPlayer.state = STATE_WALK
    else
        vPlayer.state = STATE_IDLE
    endif
   
    ' Simplified Attack
    if keydown(KEY_A) then vPlayer.state = STATE_PUNCH
endfunc

function DrawCharacters()
    ' In a real game, sort a list of characters by Y coordinate
    ' to decide who draws in front of whom.
   
    ' Example: Draw current animation frame
    ' draw image imgPlayer, vPlayer.x, vPlayer.y, vPlayer.animFrame * 64, vPlayer.state * 64, 64, 64
endfunc

function DrawHUD()
    ' Strength/Health Bar
    set color 255, 0, 0
    draw rect 20, 20, vPlayer.hp * 2, 10, true
    set color 255, 255, 255
    center "PLAYER HP"
endfunc

Key Implementation Details for your Game

State Machine:
Use the vCharacter.state variable to drive the animation.
Create a mapping: State ID corresponds to a row in your sprite sheet (e.g., Row 0 = Idle, Row 1 = Walk, Row 2 = Punch).

Depth (Z-Axis):
In 90s brawlers, the Y coordinate is used for two things: movement and depth.
When sorting which character to draw first, compare their Y values. Higher Y values (closer to the bottom of the screen) should be drawn later (on top of others).

Level Progression:
Use a CurrentLevel variable. Create a function LoadLevel(levelNum) that switches backgrounds and spawns different enemy arrays.
Level 1: Street (simple enemies).
Level 2: Warehouse (crates/props).
Level 3: Factory (hazard pits).
Boss Level: High HP enemy object with a specialized AI_Boss() state function.

Strength/HP Indicators:
Draw the health bar using draw rect. Keep it separate from the sprite drawing so it stays fixed to the top of the screen (HUD).

Animation Timing:
Use a frame counter: vPlayer.animFrame = (vPlayer.animFrame + 1) % MaxFrames. Only update this every 5-10 frames (using mod) to prevent the animation from playing too fast.

Big Grin Big Grin Big Grin
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)