Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Blinky Bumpers
#1
BLINKY BUMPERS

Bumpers don't just watch the ball – they feel when it fails!
The whole machine has personality:
  Happy when you're playing well,
  Sad when you drain...
  and ready to cheer up the moment you hit ENTER to try again

Your score = how long you stay in play

Inspired by Kevin's Pinball
https://www.naalaa.com/forum/thread-129.html 

[Image: bvKY5.gif]

Code:
'============================================================
'BLINKY BUMPERS
'
'Bumpers don't just watch the ball – they feel when it fails!
'The whole machine has personality:
'  Happy when you're playing well,
'  Sad when you drain...
'  and ready to cheer up the moment you hit ENTER to try again
'
'Your score = how long you stay in play
'
'Inspired by Kevin's Pinball
'https://www.naalaa.com/forum/thread-129.html 
'============================================================

#win32
set window "Blinky Bumpers", 700, 600
set redraw off
randomize time()

' sfx.Noise(duration, freq, vol)
include "sfx.n7"
sfx = SFX()
sfx.SetSampleRate(8000)
visible sfxSound= sfx.Noise(0.01,261.6*10, 50)

'createfont(<font name>[, <bold>[, <italic>[, <underline>[, <smooth>]]]])
arial20 = createfont("arial", 20, true, false, false, true)
set font arial20

' Constants
constant MIN_DIST_SQ = 100     
constant MAX_PULL = 80
constant PLUNGER_X = 570
constant REST_Y = 410
constant DRAIN_Y = 495
constant ARC_CX = 350
constant ARC_CY = 350
constant ARC_R = 250
constant ARC_STEPS = 360
constant ANGLE_STEP = 0.0087 '= PI / ARC_STEPS
constant BUMPER_RADIUS = 50     
constant EYE_MAX_OFFSET = 25    
constant EYE_RADIUS = 20         
constant SMILE_DEPTH = 50       
constant SMILE_STEPS = 300      
constant FRAME_TIME = 0.01

' Ball state
visible x = PLUNGER_X
visible y = REST_Y
visible vx = 0
visible vy = 0
visible started = false
visible drained = false
visible score = 0             

' Plunger state
visible plungerY = REST_Y
visible spaceDown = false
visible prevSpaceDown = false

' Misc state
visible bumper4_happy = true
visible noseX = 350         


'------------
' Main loop
'------------
while not keydown(KEY_ESCAPE, true)
    prevSpaceDown = spaceDown
    spaceDown = keydown(KEY_SPACE)
   
    ' Restart
    if keydown(KEY_RETURN, true)
        randomize time()
        x = PLUNGER_X
        y = REST_Y
        vx = 0
        vy = 0
        started = false
        drained = false
        score = 0              ' Reset timer on restart
        plungerY = REST_Y
        bumper4_happy = true
        noseX = 350            ' Reset nose to center
    endif
   
    ' arrow keys
    if keydown(KEY_LEFT) then noseX = max(130, noseX - 4)
    if keydown(KEY_RIGHT) then noseX = min(570, noseX + 4)
    
    if not started
        plungerY = min(max(plungerY + spaceDown * 7 - 4, REST_Y), REST_Y + MAX_PULL)
        y = plungerY
       
        ' Launch on release
        if prevSpaceDown and not spaceDown and plungerY > REST_Y + 5
            vy = -(plungerY - REST_Y) * 0.15
            started = true
        endif
        x = PLUNGER_X
        vx = 0
    else
        if not drained
            ' Ball movement
            x = x + vx
            y = y + vy
           
            score = score + FRAME_TIME
           
            if y >= DRAIN_Y and vy > 0
                drained = true
                bumper4_happy = false
            endif
           
            if not drained
                handleCollisions()
            endif
        else
            vx = 0
            vy = 0
        endif
    endif
   
    ' Rendering
    set color 0,0,0; cls
    drawObstacles()
    drawEyes()       
    drawPlunger()
    drawBall()
   
    ' Infobox
    set color 255, 255, 255
    set caret width()/2,height()-20; center "Press SPACE BAR to launch"
    set caret width()/2,520; center "SCORE: " + int(score * 10)
    set caret 620,480 ; wln round((plungerY - REST_Y) / MAX_PULL * 100) + "%"
    if drained
        set caret 10,10
        wln "Here's a little secret..."
        wln "Use LEFT and RIGHT to move the nose...It's a paddle!"
        wln
        wln "ENTER to restart (and cheer up!)"
    endif
   
    redraw
    fwait 120
wend


'-----------
' Functions
'-----------
function drawBall()
    set color 255, 0, 0
    draw ellipse x, y, 10, 10, true
endfunc

function drawPlunger()
    set color 100, 100, 100
    draw rect PLUNGER_X - 10, REST_Y, 20, 85, true
    set color 255, 255, 255
    draw rect PLUNGER_X - 10, plungerY + 10, 20, 10, true
endfunc

function drawEyes()
    ' Left bumper eye (225, 250)
    dx = x - 225
    dy = y - 250
    dist = sqr(dx*dx + dy*dy)
    if dist > 0.1
        scale = EYE_MAX_OFFSET / dist
        if scale > 1 then scale = 1
        eye_x = 225 + dx * scale
        eye_y = 250 + dy * scale
    else
        eye_x = 225
        eye_y = 250
    endif
   
    set color 0, 0, 0
    draw ellipse eye_x, eye_y, EYE_RADIUS, EYE_RADIUS, true
   
    ' Right bumper eye (475, 250)
    dx = x - 475
    dy = y - 250
    dist = sqr(dx*dx + dy*dy)
    if dist > 0.1
        scale = EYE_MAX_OFFSET / dist
        if scale > 1 then scale = 1
        eye_x = 475 + dx * scale
        eye_y = 250 + dy * scale
    else
        eye_x = 475
        eye_y = 250
    endif
   
    set color 0, 0, 0
    draw ellipse eye_x, eye_y, EYE_RADIUS, EYE_RADIUS, true
endfunc

function collideWithCircle(ox, oy)
    dx = x - ox
    dy = y - oy
    if dx*dx + dy*dy >= MIN_DIST_SQ then return
   
    dist = sqr(dx*dx + dy*dy)
    if dist < 1 then dist = 1
   
    x = x + dx / dist * 5
    y = y + dy / dist * 5
   
    vx = dx / dist * 2.5
    vy = dy / dist * 2.5
   
   play sound sfxSound
endfunc

function handleCollisions()
    ' Top arc
    angle = 0
    for i = 0 to ARC_STEPS
        collideWithCircle(ARC_CX + ARC_R * cos(angle), ARC_CY - ARC_R * sin(angle))
        angle = angle + ANGLE_STEP
    next
   
    ' Side walls
    for j = 320 to 500 step 10
        collideWithCircle(100, j)
        collideWithCircle(600, j)
    next
   
    ' Bottom wall
    hit_bottom = false
    for i = 100 to 600 step 10
        dx = x - i
        dy = y - 500
        if dx*dx + dy*dy < MIN_DIST_SQ
            hit_bottom = true
        endif
        collideWithCircle(i, 500)
    next
    if hit_bottom
        drained = true
        bumper4_happy = false
    endif
   
    ' Bumper 1 (x=130)
    for j = 410 to 500 step 12
        collideWithCircle(130, j)
    next
   
    ' Bumper 2 (225, 250)
    for i = 0 to 360 step 30
        a = i * PI / 180
        collideWithCircle(225 + 40 * cos(a), 250 + 40 * sin(a))
    next
   
    ' Bumper 3 (475, 250)
    for i = 0 to 360 step 30
        a = i * PI / 180
        collideWithCircle(475 + 40 * cos(a), 250 + 40 * sin(a))
    next
   
    ' Bumper 4 - Mood Arc
    for i = 0 to SMILE_STEPS
        t = i / SMILE_STEPS
        arc_x = 225 + t * 250
       
        if bumper4_happy
            arc_y = 410 + SMILE_DEPTH * sin(t * PI)
        else
            arc_y = 410 - SMILE_DEPTH * sin(t * PI)
        endif
       
        collideWithCircle(arc_x, arc_y)
    next
   
    ' Bumper 5 - Nose
    for i = noseX - 30 to noseX + 30 step 10
        collideWithCircle(i, 350)
    next
   
endfunc

function drawObstacles()
    set color 255, 255, 255
   
    ' Top arc
    angle = 0
    for i = 0 to ARC_STEPS
        ox = ARC_CX + ARC_R * cos(angle)
        oy = ARC_CY - ARC_R * sin(angle)
        draw ellipse ox, oy, 4, 4, true 
        angle = angle + ANGLE_STEP
    next
   
    ' Bottom wall
    for i = 100 to 600
        draw ellipse i, 500, 4, 4, true
    next
   
    ' Side walls
    for j = 320 to 500
        draw ellipse 100, j, 4, 4, true
        draw ellipse 600, j, 4, 4, true
    next
   
    ' Bumpers
    for k = 410 to 500
        draw ellipse 130, k, 4, 4, true
    next
    draw ellipse 225,250,50,50,true
    draw ellipse 475,250,50,50,true
   
    ' Bumper 4 - Mood Arc
    for i = 0 to SMILE_STEPS
        t = i / SMILE_STEPS
        arc_x = 225 + t * 250
       
        if bumper4_happy
            arc_y = 410 + SMILE_DEPTH * sin(t * PI)
        else
            arc_y = 410 - SMILE_DEPTH * sin(t * PI)
        endif

       
        draw ellipse arc_x, arc_y, 6, 6, true
    next
   
    ' Bumper 5 - Nose
    for j = noseX - 30 to noseX + 30
        draw ellipse j, 350, 6, 6, true
    next
endfunc
Reply
#2
That's awesome - I'm looking forward to studying the code. I was really surprised when the ball went "into" the iris of the eye Smile
Great fun......thanks for sharing.
Reply
#3
Haha, this cheered me up Big Grin
Reply
#4
FLIPER ...cool
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)