Code Example: 
"Pong", by Pieter-Bas IJdens

This example was submitted by Pieter-Bas IJdens, and is a Yabasic PS/2 adaptation of the classic "Pong" game made famous by Atari a long, long time ago, when even I myself was still in my pre-teens ... ;-) Thanks to Pieter-Bas for submitting this example, which is truly examplary in it's neatness. A tip for the beginner - 0 and 1 are frequently used instead of 'true' and 'false', but obviously 0 and 1 take up less space and save a lot of typing - knowing that should help you understand the code below a bit better still. 

rem Author: Pieter-Bas IJdens
rem spam@monad.freeserve.co.uk
rem 10 Feb 2001
rem
rem Legal stuff:
rem This code is specifically copyright free and may be used by anyone
rem for any purpose.

rem PADS: The number of pads. Usually a player would use
rem up, down. In one-pad mode TRI, X control the
rem right bat

PADS = 2

BAT_HEIGHT = 40
BAT_WIDTH = 8
BAT_SPEED = 10
BAT_OFFSET = 20

BALL_RADIUS = 6
BALL_SPEED = 11

XSIZE = 640
YSIZE = 512

main()

sub main()
    init()

    cont = 1

    wait_controller("Press any button to start.")

    while(cont = 1)
    
    draw_new_field()

        update_bat(left_bat(), "PORT1", 16, 64)
        if (PADS = 2) then
            update_bat(right_bat(), "PORT2", 16, 64)
        else
            update_bat(right_bat(), "PORT1", 4096, 16384)
        endif

        update_ball()
    
        pause 0.02
    wend
end sub

sub update_bat(bat(), addr$, up, down)
    local maxstep

    if (and(peek(addr$), down) > 0) then
        maxstep = YSIZE - (bat(2) + (bat(4) / 2))
        bat(2) = bat(2) + min(maxstep, BAT_SPEED)
    elsif (and(peek(addr$), up) > 0) then
        maxstep = bat(2) - (bat(4) / 2)
        bat(2) = bat(2) - min(maxstep, BAT_SPEED)
    endif
end sub

sub update_ball()
    b_newx = ball(1) + ball(5) * cos(ball(4))
    b_newy = ball(2) + ball(5) * sin(ball(4))
    b_newr = ball(3)
    b_newa = ball(4)
    b_news = ball(5)

    check_topbot_collission()
    check_bat_collission(left_bat())
    check_bat_collission(right_bat())
    check_leftright_collission()

    ball(1) = b_newx
    ball(2) = b_newy
    ball(3) = b_newr
    ball(4) = b_newa
    ball(5) = b_news
end sub

sub check_topbot_collission()
    local r, y_toomuch

    r = ball(3)

    if (b_newy < r) then
        b_newy = r + (r - b_newy)
        b_newa = (2 * pi) - b_newa
        beep
    endif

    if (b_newy > (YSIZE - r)) then
        y_toomuch = r + (b_newy - YSIZE)
        b_newy = YSIZE - (y_toomuch + r)
        b_newa = (2 * pi) - b_newa
        beep
    endif
end sub

sub check_leftright_collission()
    local r, reinit

    r = b_newr
    reinit = 0

    if (b_newx < r) then
        score(2) = score(2) + 2
        reinit = 1
        beep
    elsif (b_newx > (XSIZE - r)) then
        score(1) = score(1) + 1
        reinit = 1
        beep
    endif

    if (reinit = 1) then
        b_newx = XSIZE / 2
        b_newy = YSIZE / 2
        b_newa = random_angle()

        wait_controller("Press any button to start.")
    endif
end sub

sub check_bat_collission(bat())
    local a, b, x, y, rev, bx_n, bx_o
    local ignore, y_top, y_bot, too_much

    if (bat(1) > (XSIZE / 2)) then
        x = bat(1) - (bat(3) / 2)
        rev = -1
        bx_o = ball(1) + ball(3)
        bx_n = b_newx + b_newr
        if (bx_o >= bx_n) then
            ignore = 1
        elsif ((bx_o > x) or (bx_n < x)) then
            ignore = 1
        endif
    else
        x = bat(1) + (bat(3) / 2)
        rev = 1
        bx_o = ball(1) - ball(3)
        bx_n = b_newx - b_newr
        if (bx_o <= bx_n) then
            ignore = 1
        elsif ((bx_o < x) or (bx_n > x)) then
            ignore = 1
        endif
    endif

    if (ignore = 0) then
rem Let's give the players a bit of slack (b_newr / 2)

        y_top = bat(2) - (bat(4) / 2) - (b_newr / 2)
        y_bot = bat(2) + (bat(4) / 2) + (b_newr / 2)

        a = (ball(2) - b_newy) / (ball(1) - b_newx)
        b = b_newy - (a * b_newx)

        y = a * x + b 

        if (y >= y_top and y <= y_bot) then
            if (b_news > 2 * b_newr) then
                draw_the_ball(x + (rev * b_newr), y, b_newr)
            endif

            too_much = b_newx - (x + (rev * b_newr))
            b_newx = (x + (rev * b_newr)) - too_much

            b_newa = pi - b_newa
        endif
    endif
end sub

sub draw_new_field()
    buffer = 1 - buffer
    setdrawbuf buffer
    setrgb 0, 64, 127, 64
    clear window
    draw_bat(left_bat())
    draw_bat(right_bat())
    draw_ball()
    draw_score()
    setdispbuf buffer
end sub

sub draw_ball()
    draw_the_ball(ball(1), ball(2), ball(3))
end sub

sub draw_the_ball(x, y, r)
    setrgb 1, 127, 127, 127

    fill circle x, y, r
end sub

sub draw_bat(bat())
    local ltx, lty, rbx, rby

    ltx = bat(1) - (bat(3) / 2)
    lty = bat(2) - (bat(4) / 2)
    rbx = bat(1) + (bat(3) / 2)
    rby = bat(2) + (bat(4) / 2)

    setrgb 1, 127, 127, 127
    fill rectangle ltx, lty, rbx, rby
end sub

sub draw_score()
    setrgb 1, 0, 0, 0

    text 50, 20, str$(score(1)), "cc"
    text XSIZE - 50, 20, str$(score(1)), "cc"
end sub

sub init()
    init_structures()
    init_screen()
end sub

sub init_structures()
rem ball: x, y, radius, angle, speed
    dim ball(5)
    init_ball()

rem left_bat: x, y (center), width, height
    dim left_bat(4)
    left_bat(1) = BAT_OFFSET
    left_bat(2) = YSIZE / 2
    left_bat(3) = BAT_WIDTH
    left_bat(4) = BAT_HEIGHT

rem right_bat: x, y (center), width, height
    dim right_bat(4)
    right_bat(1) = XSIZE - BAT_OFFSET
    right_bat(2) = YSIZE / 2
    right_bat(3) = BAT_WIDTH
    right_bat(4) = BAT_HEIGHT

rem score: left, right
    dim score(2)
    score(1) = 0
    score(2) = 0
end sub

sub init_ball()
    ball(1) = XSIZE / 2
    ball(2) = YSIZE / 2
    ball(3) = BALL_RADIUS
    ball(4) = random_angle()
    ball(5) = BALL_SPEED
end sub

sub random_angle()
    local r

    r = ran() * 2 * pi

rem These angles keep the game interesting
    while (((r > 0.4 * pi) and (r < 0.6 * pi)) or ((r > 1.4 * pi) and (r < 1.6 * pi)))
        r = ran() * 2 * pi
    wend

    return r
end sub

sub init_screen(text$)
    open window XSIZE, YSIZE
    buffer = 0
    setdrawbuf buffer
    setrgb 0, 64, 127, 64
    clear window
end sub

sub wait_controller(text$)
    setrgb 1, 0, 0, 0

    text XSIZE / 2, YSIZE / 2, text$, "cc"

    while (or(peek("PORT1"), peek("PORT2")) = 0)
        pause 0.02
    wend
end sub

 

(c) 2001 Arwin van Arum

"Sony" and "Playstation 2" are registered trademarks owned by Sony Inc.

"Tekken" and "Bust-A-Groove" are registered trademarks and are owned by Namco.