REBOL

 

Pongo Game - Source Code

Arkanoid style block game.
Author: Kurt (Age 13)
File size: 8K
Return to index

 

REBOL [
    Title: "Pongo"
    Author: "Kurt & Dad"
    Version: 2.0.0
    Date: 4-April-2003 ;Last: 4-Mar-2001
]

;-- Create the Tile Images
;   This starts by making a single tile face, then creating 5 other tiles
;   based on that first tile, each with a different amount of "glow".
the-tile: layout [
    tile: box 50x20 edge [color: gray effect: 'bevel size: 2x2]
]
tiles: []     ; This list holds each of the new glow images.
glow-count: 5 ; The number of glow images to create.
repeat n glow-count [
    tile/effect: compose [gradient 0x1 255.255.255 (100.100.100 / glow-count * n)]
    append tiles to-image tile
]
tile-image: first tiles

;-- Create the Ball Image
ball-face: make face [
    edge: para: font: none
    size: 25x25
    color: silver
    effect: [gradmul 1x1 255.255.255 0.0.0 oval 0.0.0]
]

;-- Create the Paddle Image
paddle: make face [
    edge: make edge [size: 4x4 color: gray effect: 'bevel]
    effect: [grid 4 4]
    size: 80x18
    color: white
]

;-- Tile Map:
;   A simple character map is used to layout the tiles on the screen.
;   Different letters indicate diffent color tiles. You can change
;   this map to create different levels.
level: 1
tile-maps: [
; Level 1
{
yyy  yyy
y y  y y
yyy  yyy

   bb  
   bb
  mmmm

  rrrr
 rr  rr
  rrrr
}
; Level 2
{
rrrrrrrr
bb yy bb
r r  r r
bb gg bb
  r  r

s s  s s

 r    r
}
; Level 3
{
   gg
   gg
  gllg
  gllg
 gllllg
 gllllg
 gllllg
gllllllg
gllllllg
gllllllg
llllllll
   mm
   mm
   mm
   mm
}
]

;-- Color key:
;   This is what maps a letter to a specific color:
colors: reduce [
    #"r" red
    #"g" green
    #"b" blue
    #"y" yellow
    #"s" silver
    #"p" purple
    #"m" brown
    #"l" leaf
    #"?" 0
]

;-- Main window:
;   This inclues the title for the game, the score field,
;   and the playfield where the tiles go.
main: layout [
    vh2 "Kurt's Pongo Game"
    scorefield: text bold gold "Press mouse button to start."
    playfield: box 400x400 black
]
main/effect: [gradient 0x-1 180.180.180 80.80.80] ; window background
playfield/pane: [] ; holds the tiles, paddle, and ball.
random/seed: now ; set randomness

;-- Layout Tiles:
;   Layout the actual tiles according to the map above.
tile-count: 0
layout-tiles: does [
    x: 0  ; the horizontal postion of next tile
    y: 2  ; the vertical position of next tile
    clear playfield/pane
    tile-map: pick tile-maps level
    foreach char tile-map [
        ; For each character in the tile map...
        either char = newline [
            ; End of line. Move to next vertical position.
            x: 0
            y: y + tile-image/size/y
        ][
            ; User the letter (rgbysp...) to get the color:
            color-value: select colors char
            if color-value [
                ; Add new tile face to the playfield:
                tile-count: tile-count + 1
                append playfield/pane make face [
                    color: either color-value = 0 [random 255.255.255][color-value]
                    offset: as-pair x y
                    size: tile-image/size
                    image: tile-image
                    effect: reduce ['colorize color]
                    edge: para: font: none
                ]
            ]
            ; Move to next horizontal position:
            x: x + tile-image/size/x
        ]
    ]
    ; Reverse it so we detect collision with lower tile first:
    reverse playfield/pane
    ; Add the Paddle and Ball to the Playfield:
    insert playfield/pane paddle
    insert playfield/pane ball
    max-y: y + tile-image/size/y  ; put the paddle after this
]

;-- Special functions:

hit-tile?: func [x y] [
    ; Given a position, tell us what tile we hit.
    ; Return NONE if we did not hit a tile.
    foreach tile next next playfield/pane [
        if all [
            tile/offset/y + tile/size/y > y
            tile/offset/x - ball/size/x < x
            tile/offset/x + tile/size/x > x
        ][return tile]
    ]
    none 
]

set-glow: func [glow-level] [
    ; Set the glow level for each tile in the playfield.
    ; (Skip first two faces: the paddle and the ball)
    foreach face next next playfield/pane [
        face/image: pick tiles glow-level
    ]
]

bump-score: does [
    ; Bump up the score:
    score: score + 1
    scorefield/text: reform [
        "Level:" level
        "  Score:" score
        ;either score > high-score [" NEW HIGH SCORE!!!"][""]
    ]
]

game-over: has [comments str note percent] [
    ; Tell user that the game is over.
    str: reform ["GAME OVER! Score:" score "- "]
    percent: score / tile-count * 100
    comments: [
        20 "You need practice."
        40 "Keep working at it!"
        60 "That's a good score!"
        80 "Wow! That's amazing!"
    ]
    note: "I bow to you, master pongo player."
    foreach [num msg] comments [
        if percent < num [note: msg break] ;>
    ]
    alert append str note
    reset-game
]

start-level: does [
    layout-tiles
    ;-- Set the Ball and Paddle Positions:
    paddle/offset: playfield/size - 200x40
    ball/offset: paddle/offset - paddle/size - 6
    bx: ball/offset/x ; Ball X position
    by: ball/offset/y ; Ball Y position
    dx: 0   ; Delta X - how much to move horizontally each time
    dy: -15 ; Delta Y - how much to move vertically each time
    bs: ball/size/x ; Ball size (for both x and y)
    glow: 0  ; tile glow
    ;-- Set the Speed and Display the Window:
    ball/rate: 30
    started: off
    won-level: false
]

;-- Make the Ball Face:
;   And set it to move as time goes by.
ball: make face [
    size: 25x25
    color: black
    image: to-image ball-face
    feel: make feel [
        engage: func [face act event] [
            ; Each time we get a "time" action:
            if act = 'time [
                if not started [exit]
                move-ball
                show ball
            ]
        ]
    ]
    edge: para: font: none
]

;-- Ball Movement Code:
;   This is the hard stuff, where we compute the next position
;   for the ball as it bounces around the playfield.

do reset-game: does [
    score: 0 ; total score
    level: 1
    past-paddle: false
    start-level
]

move-ball: does [
    ; Move the ball to the next position:
    bx: bx + dx
    by: by + dy

    ; If it hit the right side, bounce it back:
    if bx + bs >= playfield/size/x [dx: negate dx]
    ; If it hit the left side, bounce it back:
    if bx < 0 [dx: abs dx] ;>

    ; If the tiles are glowing, bump them to next glow level:
    if glow > 0 [
        glow: glow - 1
        if glow > 0 [set-glow glow]
    ]

    ; Is the ball in the tile area?
    if by < max-y [ ;>
        ; If ball hit a tile, remove it and bump the score:
        either tile: hit-tile? bx by [
            remove find playfield/pane tile
            bump-score
            if 2 >= length? playfield/pane [won-level: true]
            glow: glow-count
            set-glow glow
            by: tile/offset/y + tile/size/y - 5
            dy: abs dy
        ][
            if by < 0 [dy: abs dy] ;>
        ]
    ]

    ; Is the ball moving past the paddle (game over):
    either past-paddle [
        ; Is the ball off the screen?
        if by > playfield/size/y [
            ball/rate: none
            ball/offset: as-pair bx by
            show ball
            game-over
        ]
    ][
        ; Did the ball hit the paddle?
        if by + ball/size/y >= paddle/offset/y [
            either all [
                ; Check if ball is in paddle's position:
                not past-paddle
                bx + bs - 3 > paddle/offset/x
                bx + 2 < (paddle/offset/x + paddle/size/x) ;>
            ][
                ; It hit the paddle. Bounce it off the paddle, giving it
                ; a little extra speed each time.
                dy: min 50 dy * 20 / 19
                dy: negate dy
                ; Make edges of the paddle deflect the ball slightly:
                dx: bx - paddle/offset/x - (paddle/size/x / 2) / 10 + dx
                by: paddle/offset/y - paddle/size/y - 5
                if won-level [
                    alert "You made it to the next level!"
                    level: level + 1
                    start-level
                ]
            ][
                ; Past the paddle. Game over, pal.
                past-paddle: true
            ]
        ]
    ]
    ball/offset: as-pair bx by
    show [playfield scorefield]
]

start-level
view/new center-face main

;-- Detect Mouse Movement and Move Paddle:
main/feel/detect: func [face event] [
    if event/type = 'move [
        paddle/offset/x: event/offset/x - 70
        show paddle
    ]
    if event/type = 'down [started: true]
    event
]
show ball
do-events