REBOL

Simple REBOL Game Programming For Young People

To get started, download and install REBOL/View from http://www.rebol.com/download-view.html (it takes just a few seconds). Once it's installed, run REBOL (Start -> Programs -> REBOL -> REBOL View), then click the "Console" Icon. Type "editor none" at the prompt - that will run REBOL's built in text editor. At this point, you are ready to start typing in REBOL programs. Copy/paste each example in this tutorial into the REBOL editor to see what the code does.

Every REBOL program must begin with the following header:

REBOL []

To create a program window (a "GUI"), use the following code:

REBOL []
view layout [size 600x440]

In the REBOL editor, save the above program code to a file, then press F5 on your keyboard to run it. If you save your program with a ".r" extension in the file name (i.e., "myprogram.r"), then you can also click your program's file icon, and it will run just like an ".exe" file.

To center a program window on your computer screen, use "center-face". Paste the following code into the REBOL text editor, then press the F5 key:

REBOL []
view center-face layout [size 600x440]

You can put a title in your program header, which will appear in the title bar of your program window. Paste the following code and press F5:

REBOL [title: "Game Demo"]
view center-face layout [size 600x440]

By default, REBOL program windows have gray backdrop. You can change that using the "backdrop" word (paste this code and press F5):

REBOL [title: "Game Demo"]
view center-face layout [size 600x440  backdrop white]

Here's how you add "widgets" (buttons, text fields, drop down lists, etc.) to your program window. Notice that everything in the window is between square brackets, and has been indented. Enclosed square brackets are called "blocks" in REBOL. Indentation is NOT required, but makes the code easier to read (paste this and press F5):

REBOL [title: "Game Demo"]
view center-face layout [
    size 600x440
    backdrop white
    btn "Click Me"
    field "Type Here"
    text-list data ["first" "second" "third"]
]

Here's how you make your widgets perform an action. The "alert" function is used to create a message box with text for the user to read. Notice that the word "value" holds the current/selected value in the widget (paste and press F5):

REBOL [title: "Game Demo"]
view center-face layout [
    size 600x440
    backdrop white
    btn "Click Me" [alert "Clicked"]
    field "Type Here" [alert value]
    text-list data ["first" "second" "third"] [alert value]
]

By default, REBOL puts widgets below one another in the program window. You can change that by using the "across" word. You can change back to the default behavior by using the word "below" (paste/F5):

REBOL []
view center-face layout [
    size 600x440
    backdrop white
    across
    btn white
    btn red
    btn blue
    below
    btn green
    btn orange
    btn purple
]

You can place your widgets at specified coordinate positions (XxY coordinates indicate X pixels over and Y pixels down) (paste/F5):

REBOL []
view layout [
    size 600x400
    at 200x250 btn "button 1"
    at 300x350 btn "button 2"
]

You can give any widget a LABEL by using a word of your choice, followed by a colon. You can change a labeled widget's position using the "/offset" refinement, followed by a colon. Whenever you make changes to a window's appearance (such as when moving a widget), you must use the "show" function to update the display. Notice the button widget below labeled "button1", and notice how clicking the other button changes button1's position (paste/F5):

REBOL []
view layout [
    size 600x400
    at 20x20 button1: btn "button 1" 
    at 100x20 btn "change button 1's position" [
        button1/offset: 300x250
        show button1
    ]
]

You can create a coordinate position from two separate numbers, using the "as-pair" function (paste/F5):

REBOL []
x-size: 600
y-size: 400
x-position: 20
y-position: 20
view layout [
    size (as-pair x-size y-size)
    at (as-pair x-position y-position) button1: btn "button 1"
]

You'll need random numbers often when making games. You can create them with the "random" function. To be sure that random numbers are properly generated, include the code "random/seed now/time" in your program (paste/F5):

REBOL []
random/seed now/time
x: random 500  ; generates a random number up to 500
y: random 300
size-x: 600
size-y: 400
view layout [
    size (as-pair size-x size-y)
    at (as-pair x y) button1: btn "button 1"
]

You can also create random pairs directly (i.e., without using as-pair). Just set the upper limit for the the X and Y numbers (i.e., "random 500x400") (paste/F5):

REBOL []
random/seed now/time
view layout [
    size 600x400
    at 20x20 button1: btn "button 1"
    at 100x20 btn "change button 1's position" [
        button1/offset: random 500x400
        show button1
    ]
]

You can set the text of any widget using the "/text" refinement. You'll need this to update text information on screen (i.e., for scores, lives left, etc.). To make sure text gets properly formatted, use the "form" function (paste/F5):

REBOL []
view layout [
    text1: text "This is a text widget"
    btn "Change the text widget's text" [
        text1/text: form "Changed!"
        show text1
    ]
]

Here is one way to check for user keystrokes. This is a great way to create game controls (paste/F5):

REBOL []
view center-face layout [
    size 600x440 
    text "Press an arrow key"
    key keycode [left]  [alert "You pressed the LEFT arrow key"]
    key keycode [right] [alert "You pressed the RIGHT arrow key"]
]

To create a repeating loop, just copy the line below that starts with the word "box", and the closing 3 square brackets, into your GUI code. Anything inside those brackets will be repeated continuously. This is a great way to create continuous motion and actions in a game (paste/F5):

REBOL []
view layout [
    size 600x440
    btn1: btn red
    box 0x0 rate 0 feel [engage: func [f a e] [if a = 'time [
        btn1/offset: btn1/offset + 2x2
        show btn1
    ]]]
]

You can check if any condition is true, and make decisions in your program, using the "if" function. Put the actions to be performed (if the condition is true) inside square brackets following the if test (paste/F5):

REBOL []
direction: "down"
view layout [
    size 600x440
    btn1: btn red
    box 0x0 rate 0 feel [engage: func [f a e] [if a = 'time [
        if btn1/offset/2 > 420  [direction: "up"]
        if btn1/offset/2 < 1    [direction: "down"]
        if direction = "down"   [btn1/offset: btn1/offset + 0x5]
        if direction = "up"     [btn1/offset: btn1/offset - 0x5]
        show btn1
    ]]]
]

Most games will involve testing for "collisions" - when graphics touch. Use REBOL's "within?" function to test if graphics share coordinate locations (i.e., are touching) (paste/F5):

REBOL []
direction: "down"
view layout [
    size 600x440
    btn1: btn red
    at 20x350 btn2: btn green
    box 0x0 rate 0 feel [engage: func [f a e] [if a = 'time [
        if btn1/offset/2 > 420  [direction: "up"]
        if btn1/offset/2 < 1    [direction: "down"]
        if direction = "down"   [btn1/offset: btn1/offset + 0x5]
        if direction = "up"     [btn1/offset: btn1/offset - 0x5]
        show btn1
        if (within? btn1/offset btn2/offset 1x1) [alert "Collision!"]
    ]]]
]

Here's a little game using much of what you've learned so far. Catch the falling pieces (paste/F5):

REBOL [title: "Catch Game"]    
alert "Arrow keys move left/right, up goes faster, down goes slower"
random/seed now/time   
speed: 11   score: 0
view center-face layout [
    size 600x440   backdrop white   across
    at 270x0 text "Score:"  t: text bold 100 (form score)
    at 280x20  y: btn 50x20 orange
    at 280x420 z: btn 50x20 blue
    key keycode [left]   [z/offset: z/offset - 10x0  show z]
    key keycode [right]  [z/offset: z/offset + 10x0  show z]
    key keycode [up]     [speed: speed + 1]
    key keycode [down]   [if speed > 1 [speed: speed - 1]]
    box 0x0 rate 0 feel [engage: func [f a e] [if a = 'time [
        y/offset: y/offset + (as-pair 0 speed)  show y
        if y/offset/2 > 440 [
            y/offset: as-pair (random 550) 20   show y
            score: score - 1
        ]
        if within? z/offset (y/offset - 50x0) 100x20 [
            y/offset: as-pair (random 550) 20   show y
            score: score + 1
        ]
        t/text: (form score)  show t
    ]]]
]

You can use the following short program to encode images, sounds, or any other types of files, so that they can be included directly in the code of your program (be sure to save this program to a separate file on your desktop - you will use it often):

REBOL [Title: "Binary Resource Embedder"]
system/options/binary-base: 64
uncompressed: read/binary to-file request-file/only
editor compress to-string uncompressed

Use the following "load to-binary decompress" code to load encoded files created by the program above. Assign each graphic a word label by using the colon symbol, and then display it in your program window using an "image" widget (paste/F5):

REBOL []
gun-man: load to-binary decompress 64#{
    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
}
view layout [
    size 600x400
    backdrop black
    image gun-man
]

Just as with images, you can use the "Binary Resource Embedder" program, provided earlier, to save sound files as code in your programs. You can play .wav sounds using the last line of following code (paste/F5):

REBOL []
my-sound: load to-binary decompress 64#{
    eJxtlHtMU1ccx6vGR3kWLMWpm5pskc2pi3MkqFNYJsh0oigV5KEULK2lpdDb9vbe
    9r56W1pogSKltBQqSGGAlYeimAlDkU1H1KgssrhBmFNhjAECHcZl2bVo1LjfyTm/
    nO/vdf45n9joyMjphTTaoQj2Tq4QWB1Io9HmUSt8Fc2z59GWUEp6KpB6k8pC3zJs
    7nzTvXbB/sdhmMdjcx5744q9SkHf1l4f/LLhq+K33jZnOI6/3gZBVAjq8Qj6Mkzl
    ek5KwBEpL11saGyrANhx4kKHzUBgmFKhUKKIAgBAlNRqNaSayiO1pEqeLeTzxZjJ
    nA+KAK2ByBaidle1XoGVnrLjx3kSlULEOSaBIBmkMZkL9Lo8owYUZYqyRLwMMVJo
    NqgkoL7MQoqOiXUVzpPl1a7OiyXS6K2RBxJiE1KgitrTteYyq0ktStgbE3MwTUha
    7BXFmDxHjpGITE5Unu++dLaupc2UFTLfd5PEZi8xObp7W/Ts8N3Jx3npXMjqarQA
    8XFHpJBUeAwscNRZ8wwF1a7auvIzVWRCwCL/XY6B4c5CWGYol+8LWfk52X63t1Ka
    mnw0Izk+XkCcbDpVKueKUdvpRofVfulms3TlIh8mODQ7fjpx2359ERTFZB3u+Gt2
    MH+zr8+mgwJMZ2/vajYeDt2aYr72U7eNUDf+es+yYQFzQcQvs+MTmQH0zaTTsued
    j/HHT2b6vloc6L0+71Z/hw2RykVHvt6bVtTZd+ecraCq3sT28fNnFD4bdQ/sWhwQ
    xHG14HH7iHtPpi6ELgn0CnFNTQybdwSviYLs39TYyqwN565cq+evoQctDvv+6cjT
    ns/ogQGH6r4tVwh0PWMjzq1egb5rqqfHJhq3+Pt9kOW61l2jh3TOG0Pt/BV01sL9
    A+7H/5xi+TGWpl/pq0cScxruP2qI8g70W2Zxj7ovb/cJYCS0D49dMXC5up4H13OC
    vFkLEodnhv8t8WUE+AsHn9w27totPj94XbXCZ6l31uj45MOkJUz65tbJiZGahJ1p
    rv6fcZYXa/7eodlHtLplXqyFkXenJ7qSwz4VNlxuTlrK8NvYNDPqrl9LDcq4Pzk5
    aIyNFpdftITSmfQP256NuH9jL2L6MhVDk2Mdiojt8WBZniB8bWha7f2JOyf2BLO2
    4b1jk301pAxAeFtWegfvbJgan36ofc/Hj7G/cuCPvlaYx04SZPCT4lKExvqLbRXg
    wS+jBZbv+vuuNhWDieuCAoN3EP0zU5PnOcu9vEO41Tdu9zp1AOc4N4PDPpSYlV/T
    dtaBcWJi+YbWH+/e7HAoD6zyZyyP0t9z//1nq2Cjj/8nKaXtP1ytOyHn8TkZ3DRu
    ugjWWU9WFqMivhCznunq6W42Z4Yt8wrYwGt++NR9x5K0/t33I0TFrZ1tTj3ATU7l
    iUFQli2SwFrTiaJ8jdZgrmpou+CqkOz+yD94XZK568Hvt5rwo3u+iEmR6IttZUYS
    yBRkyhFCDcnEmdkArMkvsTlqapx1VeWGnCNRYWHhidKi+pbW+tJ8pVwuQ3G1BoVz
    eOkcbg6caywoyMWVIKTEqf9ozNPrcrUYLMuRABBO6nUkppACAIzpqLQ8LYmpIBAE
    FRAEwbASwQmCwFSwgpIgJarW6inTUfUakiTVOAJTMkJoNCSuAmVSQCqHUdwTec4X
    tRrHVEpYqaKMIg9OqNVqAvcgh9RoczUkgSKeGMUlRKWkBqpQah6Gzkko/oJjOE7g
    L2FFAc2DM8zTjHoZDKsw4vlEDwyRF5xUKZVUj7lagsCxOfYR/wHwfuhW/AUAAA==
}

insert port: open sound:// my-sound wait port close port

Here's a version of the "Catch Game" above that replaces buttons with graphics, and adds a sound effect. You can create any game initially this way, simply using buttons, and later replace the buttons with more interesting graphic images, add sounds, etc. (paste/F5):

REBOL [title: "Feed The Gator"]
bird: load to-binary decompress 64#{
    eJzF2LuL4kAcwHG3shBURHDRRW3E+wuuPOEaC9lGC60EXyCClQjiM4qdzVWWVjYW
    iiA2Cj7wPOzEThALG7HYRixF737EU/bMTTLGzOQLgxCTyaeYxMTv77/0CravML7A
    +AbjDcaL4pXd/gO+/6m+jGu/n6vRaDAMY7fbTSaTzWa7zOn3+xm2zWbz5Pw8fSzF
    HTcajYLBoAIjn8/XbDalVV963J5KpXDIdwUCgV6vJ6tdhPour9crh/15+K1QKDSZ
    TER4t9ttsVhUsJcpnr3b7UoI/1wsFiuVSsw12HI+nz+fulAoVCoV7oF49sFgQAjO
    TaVSwRmPxyOQjUYjz54Oh0PIPh6PqcGhVqsluI/Vak2n08PhkNc+nU4pePGDlb5e
    r288tL3f78tt/ZtGo8lkMlwh2q5Wq4WnJZZSqYRreLnkWxYIuyyrJZFIZLPZxWLB
    48WwwzQ01ZFIBNMrZJ/NZtTUuVxOhBpt12q1FNSwLEWrEXZYbqTVtVrtSTXCbjab
    yanhuV4S9b/21Wp1OBzIwaPRaKfTkRDO2vP5PCHvrWQyKa36aj+dToTIHo+n3W6T
    UF/tl09425TEa7FYnE4nPCuRI3PskF6vF4F1u93lchmwu92Oghdhh3Q63UNwae8b
    j8a5RxoMBkx4vV6XhXzrf7+rOPBqtUofexfiWSwcDvPAKRtR8b43xePxO7XL5aJG
    Ewzvf4L9fg8v8fP5nDTnoT6WfwB19HCVxhQAAA==
}
alligator: load to-binary decompress 64#{
    eJxd0s1KW0EUB3C1K+lDuHVjXWSnkAvuXfgCBRG7bBeFlormPkKXQhuaN9BNxYUm
    UxF00UUWhUoIcRQXoYTkUm7T8Tof/845Z0o/5nL43XPmn+HmJmvrzx7N8KrHWoy1
    HGs71my8aC2mfVpzf25nAMQKaAe69zqZLbEu/8hWaf+31u+JlnM3NXtK6kt7xBrL
    OYVyTzSpNx0yQ3FA5iiekA3oV9Hg8had4x6yjHLefUKD9Ajk/RR4SvkN4Dnl5xEc
    9Y9lH1fgPAxCEF0yXCcn/+77/3VJL1Zt0Y7/nv9AxZa5rchuZi3ZUiXPc2VO2IEp
    k4aeF4PhS3Y0pPxP3JU0vwFYYwHyHGIrQp4Npa8ugSJa7ou3x0A3erEKT71/I3O/
    K3nnVxYMv78z7uHjL0YGmPei/sxq3EmPMply4O+D13Biwe8JL87RYJvicsewh40R
    +yHf7LDYYpuoXZMDv8p9L6g62beK8/1Ri/1itPTQnOsXb8XDrqgL+bwapr7kc3vw
    E+7Vw1eZhzXym/I75Ah2l1VY4bkWxxnekVOEC/J7Bj7nPkf6/4txRX8BGfoeSmYD
    AAA=
}
gulp-sound: load to-binary decompress 64#{
    eJxtlHtMU1ccx6vGR3kWLMWpm5pskc2pi3MkqFNYJsh0oigV5KEULK2lpdDb9vbe
    9r56W1pogSKltBQqSGGAlYeimAlDkU1H1KgssrhBmFNhjAECHcZl2bVo1LjfyTm/
    nO/vdf45n9joyMjphTTaoQj2Tq4QWB1Io9HmUSt8Fc2z59GWUEp6KpB6k8pC3zJs
    7nzTvXbB/sdhmMdjcx5744q9SkHf1l4f/LLhq+K33jZnOI6/3gZBVAjq8Qj6Mkzl
    ek5KwBEpL11saGyrANhx4kKHzUBgmFKhUKKIAgBAlNRqNaSayiO1pEqeLeTzxZjJ
    nA+KAK2ByBaidle1XoGVnrLjx3kSlULEOSaBIBmkMZkL9Lo8owYUZYqyRLwMMVJo
    NqgkoL7MQoqOiXUVzpPl1a7OiyXS6K2RBxJiE1KgitrTteYyq0ktStgbE3MwTUha
    7BXFmDxHjpGITE5Unu++dLaupc2UFTLfd5PEZi8xObp7W/Ts8N3Jx3npXMjqarQA
    8XFHpJBUeAwscNRZ8wwF1a7auvIzVWRCwCL/XY6B4c5CWGYol+8LWfk52X63t1Ka
    mnw0Izk+XkCcbDpVKueKUdvpRofVfulms3TlIh8mODQ7fjpx2359ERTFZB3u+Gt2
    MH+zr8+mgwJMZ2/vajYeDt2aYr72U7eNUDf+es+yYQFzQcQvs+MTmQH0zaTTsued
    j/HHT2b6vloc6L0+71Z/hw2RykVHvt6bVtTZd+ecraCq3sT28fNnFD4bdQ/sWhwQ
    xHG14HH7iHtPpi6ELgn0CnFNTQybdwSviYLs39TYyqwN565cq+evoQctDvv+6cjT
    ns/ogQGH6r4tVwh0PWMjzq1egb5rqqfHJhq3+Pt9kOW61l2jh3TOG0Pt/BV01sL9
    A+7H/5xi+TGWpl/pq0cScxruP2qI8g70W2Zxj7ovb/cJYCS0D49dMXC5up4H13OC
    vFkLEodnhv8t8WUE+AsHn9w27totPj94XbXCZ6l31uj45MOkJUz65tbJiZGahJ1p
    rv6fcZYXa/7eodlHtLplXqyFkXenJ7qSwz4VNlxuTlrK8NvYNDPqrl9LDcq4Pzk5
    aIyNFpdftITSmfQP256NuH9jL2L6MhVDk2Mdiojt8WBZniB8bWha7f2JOyf2BLO2
    4b1jk301pAxAeFtWegfvbJgan36ofc/Hj7G/cuCPvlaYx04SZPCT4lKExvqLbRXg
    wS+jBZbv+vuuNhWDieuCAoN3EP0zU5PnOcu9vEO41Tdu9zp1AOc4N4PDPpSYlV/T
    dtaBcWJi+YbWH+/e7HAoD6zyZyyP0t9z//1nq2Cjj/8nKaXtP1ytOyHn8TkZ3DRu
    ugjWWU9WFqMivhCznunq6W42Z4Yt8wrYwGt++NR9x5K0/t33I0TFrZ1tTj3ATU7l
    iUFQli2SwFrTiaJ8jdZgrmpou+CqkOz+yD94XZK568Hvt5rwo3u+iEmR6IttZUYS
    yBRkyhFCDcnEmdkArMkvsTlqapx1VeWGnCNRYWHhidKi+pbW+tJ8pVwuQ3G1BoVz
    eOkcbg6caywoyMWVIKTEqf9ozNPrcrUYLMuRABBO6nUkppACAIzpqLQ8LYmpIBAE
    FRAEwbASwQmCwFSwgpIgJarW6inTUfUakiTVOAJTMkJoNCSuAmVSQCqHUdwTec4X
    tRrHVEpYqaKMIg9OqNVqAvcgh9RoczUkgSKeGMUlRKWkBqpQah6Gzkko/oJjOE7g
    L2FFAc2DM8zTjHoZDKsw4vlEDwyRF5xUKZVUj7lagsCxOfYR/wHwfuhW/AUAAA==
}
alert "Arrow keys move left/right, up goes faster, down goes slower"
random/seed now/time   
speed: 9   score: 0
view center-face layout [
    size 600x440   backdrop white   across
    at 270x0 text "Score:"  t: text bold 100 (form score)
    at 280x20  y: image bird
    at 280x340 z: image alligator
    key keycode [left]   [z/offset: z/offset - 10x0  show z]
    key keycode [right]  [z/offset: z/offset + 10x0  show z]
    key keycode [up]     [speed: speed + 1]
    key keycode [down]   [if speed > 1 [speed: speed - 1]]
    box 0x0 rate 0 feel [engage: func [f a e] [if a = 'time [
        y/offset: y/offset + (as-pair 0 speed)  show y
        if y/offset/2 > 440 [
            y/offset: as-pair (random 550) 20   show y
            score: score - 1
        ]
        if within? z/offset (y/offset - 50x0) 100x20 [
            y/offset: as-pair (random 550) 20   show y
            score: score + 1
            insert port: open sound:// gulp-sound wait port close port
        ]
        t/text: (form score)  show t
    ]]]
]

This game contains some GUI layout parameters that make the widgets squeeze together, without any space in between ("origin 0x0" and "space 0x0"). It also uses the "style" word to define a completely new widget called "piece". Every time a "piece" widget is added to the GUI, it performs all the actions in the piece's style definition (in this example, "piece" is a 60x60 button that performs a number of offset calculations). You could make this program much more interesting by using images instead of buttons - give it a try if you really want to learn! (paste/F5):

REBOL [title: "Sliding Puzzle"]
view center-face layout [
    origin 0x0  space 0x0  across
    style piece button 60x60 [
        if not find [0x60 60x0 0x-60 -60x0] (face/offset - empty/offset) [
            exit
        ]
        temp: face/offset
        face/offset: empty/offset 
        empty/offset: temp
    ]
    piece "1"   piece "2"   piece "3"   piece "4" return
    piece "5"   piece "6"   piece "7"   piece "8" return
    piece "9"   piece "10"  piece "11"  piece "12" return
    piece "13"  piece "14"  piece "15"
    empty: piece 200.200.200 edge [size: 0]
]

This shooting game contains a text widget labeled "info". That widget displays text that is joined together ("concatenated) using the "rejoin" function. The entire game is also wrapped in square brackets, and labeled "game". When the screen needs to be refeshed, the entire GUI is simply "unview"ed, and the game code is done again (paste/F5):

REBOL [title: "Shooter"]
score: 0   speed: 10   lives: 5   fire: false   random/seed now/time
alert "[SPACE BAR: fire] | [Arrows: move left/right]"
do game: [
    view center-face layout [
        size 600x440
        backdrop black
        at 246x0 info: text tan rejoin ["Score: " score " Lives: " lives]
        at 280x440 x: box 2x20 yellow
        at (as-pair -50 (random 300) + 30) y: btn 50x20 orange
        at 280x420 z: btn 50x20 blue
        key keycode [right] [z/offset: z/offset + 10x0 show z]
        key keycode [left] [z/offset: z/offset + -10x0 show z]
        key keycode #" " [
            if fire = false [
                fire: true
                x/offset: as-pair (z/offset/1 + 25) 440
            ]
        ]
        box 0x0 rate speed feel [engage: func [f a e] [if a = 'time [
            if fire = true [x/offset: x/offset + 0x-30]
            if x/offset/2 < 0 [x/offset/2: 440  fire: false]
            show x
            y/offset: y/offset + as-pair 
                ((random 20) - 5) ((random 10) - 5)
            if y/offset/1 > 600 [
                lives: lives - 1
                if lives = 0 [
                    alert join "GAME OVER!!! Final Score: " score
                    quit
                ]
                alert "-1 Life!"   unview   do game
            ]
            show y
            if within? x/offset (y/offset - 5x5) 60x30 [
                alert "Ka-blammmm!!!"
                score: score + 1   speed: speed + 5  fire: false
                unview   do game
            ]
        ]]]
    ]
]

The following game of "Collect the Boxes" starts by setting some word labels ("variables"). The word "start-time" is set to hold the time at which the program was begun (you can always get the current time using "now/time"). Next, the "level" word is set to hold a number requested from the user. Then the word "gui" is set to hold a layout block of GUI widgets. Inside the repeating loop in the GUI, a "foreach" loop is used to perform several "if" calculations on each widget in the GUI (the list of current GUI widgets is held in "system/view/screen-face/pane/1/pane"). The first "if" in the foreach loop removes any boxes from the GUI which the player's piece is touching. The second "if" ends the game when all the small boxes have been removed from the GUI. Before actually viewing the GUI block, a collection of buttons is added to the block, using a "for" loop. The for loop repeats the number of times held in the "level" variable, each time appending a box with a random position and color. Finally, the player's piece (a 20x20 red button) is added to the GUI layout, and the window is shown using "view layout". Try to collect the boxes as quickly as possible!:

REBOL [Title: "Collect the Boxes"]
random/seed now
start-time: now/time
level: to-integer request-text/title/default "Number of Boxes?" "10"
gui: [
    size 600x440  backdrop white
    at -99x0 key keycode [up]    [p/offset: p/offset + 0x-10 show p]
    at -99x0 key keycode [down]  [p/offset: p/offset + 0x10  show p]
    at -99x0 key keycode [left]  [p/offset: p/offset + -10x0 show p]
    at -99x0 key keycode [right] [p/offset: p/offset + 10x0  show p]
    at -99x0 box rate 0 feel [engage: func [f a e][if a = 'time [
        foreach f system/view/screen-face/pane/1/pane [
            if  f <> p [
                if within? (f/offset + 10x10) p/offset 30x30 [
                    remove find system/view/screen-face/pane/1/pane f
                    show system/view/screen-face/pane/1/pane
                ]
            ]
            if (length? system/view/screen-face/pane/1/pane) < 8 [
                alert rejoin ["Your time: " now/time - start-time]
                quit
            ]
        ]
    ]]]
]
for counter 1 level 1 [
    append gui [at random 590x420 box 10x10 random 255.255.255]
]
append gui [p: btn red 20x20]
view center-face layout gui

This game uses REBOL's "draw" dialect. It's a bit beyond the scope of this tutorial, but a nice preview of things you can focus on learning next (paste/F5):

REBOL [title: "Little 3D Game"]
beep-sound: load to-binary decompress 64#{
eJwBUQKu/VJJRkZJAgAAV0FWRWZtdCAQAAAAAQABABErAAARKwAAAQAIAGRhdGEl
AgAA0d3f1cGadFQ+T2Z9jn1lSjM8T2uNsM/j7Midc05PWGh4eXVrXE5DQEZumsTn
4M2yk3hiVU9fcX+GcFU8KkNmj7rR3+HYroJbPUpfdoqAbldBP0ZWbpW62OvRrohk
WlleaHB2dW9bRzo1WYWy3OHbyrKObVNCVGp/jXpgRC48Vnievtfm6MCUaUVLWW1/
fXNkUkdCRlN7ps3r3cSkgm1fWFhmdH2AaVA6LElwnMja4dzNpHtXPUxje45/aVA5
PUtif6TG3uvMpHtXU1lkcnd2cGVURT0+ZJC84+HUvaGCZ1NIWm6AinVaQCtAX4Wu
yt3k37aJYEBKXXOHf3FdSEJET2KJsdPr1reUcGJbW2FsdXl2YUs5MFF7qdPe3tO+
mHNUP1Bnfo59ZEkyPFFukbTR5OvGm3BMTVlpent1aVpMQ0FJcZ3I6uHMsJB2YlZR
YXJ/hW5UOypEaJK90+Dg1qyBWjxKYHeLgG1WPz9HWXKYvNnr0KyFYVhZX2pydnVu
Wkc7N1yHtN3h2sivjGxTRFZrgI15X0MtPVh7osHZ5ua+kmdES1tvgn5zY1BGQ0hW
fqjO69vBoX9rXllaaHV9fmhPOi1Lcp/K2+DayaF4Vj1NY3uNfmhONjxLZIKnyODr
yqJ4VFFYZHN3dm5iUUM9QGaTv+Th0rqdf2VTSltvgIl0WT4rQGCIssze5N60iF8/
Sl10h39vW0ZBRFFljLPU69W1kG1gWlxiYHkWb1ECAAA=
}
alert {
   Try to click the bouncing REBOLs as many times as possible in
   30 seconds.  The speed increases with each click!
}
do game: [
   speaker: open sound://
   g: 12 i: 5 h: i * g j: negate h  x: y: z: w: sc: 0  v2: v1: 1  o: now
   img1: to-image layout [backcolor brown box red center logo.gif]
   img2: to-image layout [backcolor aqua box yellow center logo.gif]
   img3: to-image layout [backcolor green box tan center logo.gif]
   cube: [[h h j][h h h][h j j][h j h][j h j][j h h][j j j][j j h]]
   view center-face layout/tight [
      f: box white 550x550 rate 15 feel [engage: func [f a e] [
         if a = 'time [
            b: copy []  x: x + 3  y: y + 3  ; z: z + 3
            repeat n 8 [
               if w > 500 [v1: 0]   if w < 50 [v1: 1]
               either v1 = 1 [w: w + 1] [w: w - 1]
               if j > (g * i * 1.4) [v2: 0]   if j < 1 [v2: 1]
               either v2 = 1 [h: h - 1] [h: h + 1]  j: negate h
               p: reduce pick cube n 
               zx: p/1 * cosine z - (p/2 * sine z) - p/1
               zy: p/1 * sine z + (p/2 * cosine z) - p/2
               yx: (p/1 + zx * cosine y) - (p/3 * sine y) - p/1 - zx
               yz: (p/1 + zx * sine y) + (p/3 * cosine y) - p/3
               xy: (p/2 + zy * cosine x) - (p/3 + yz * sine x) - p/2 - zy
               append b as-pair (p/1 + yx + zx + w) (p/2 + zy + xy + w)
            ]
            f/effect: [draw [
               image img1 b/6 b/2 b/4 b/8
               image img2 b/6 b/5 b/1 b/2
               image img3 b/1 b/5 b/7 b/3 
            ]]
            show f
            if now/time - o/time > :00:20 [
               close speaker
               either true = request [
                  join "Time's Up! Final Score: " sc "Again" "Quit"
               ] [do game] [quit]
            ]
         ]
         if a = 'down [
            xblock: copy [] yblock: copy []
            repeat n 8 [
                append xblock first pick b n
                append yblock second pick b n
            ]
            if all [
                e/offset/1 >= first minimum-of xblock
                e/offset/1 <= first maximum-of xblock
                e/offset/2 >= first minimum-of yblock
                e/offset/2 <= first maximum-of yblock
            ][
               insert speaker beep-sound wait speaker
               sc: sc + 1
               t1/text: join "Score: " sc 
               show t1
               if (modulo sc 3) = 0 [f/rate: f/rate + 1]
               show f
            ]
         ]
      ]]
      at 200x0 t1: text brown "Click the bouncing REBOLs!"
   ]
]

There a number of additional games, and many more programming concepts and techniques explained in far greater detail, in the tutorial at http://re-bol.com. Read through that tutorial, and you'll learn to accomplish just about every other type of programming task you can imagine!

MakeDoc2 by REBOL - 25-May-2010