REBOL [ Title: "Pongo" Author: "Kurt & Dad" Version: 2.0.0 Date: 4-April-2003 ;Last: 4-Mar-2001 Needs: [view 1.2.8] ] ;-- 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 quit ] start-level: does [ layout-tiles ;-- Set the Ball and Paddle Positions: paddle/offset: playfield/size - 200x40 ball/offset: paddle/offset - paddle/size 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. score: 0 ; total score level: 1 past-paddle: false 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