|
> |
| Home > Articles > Tutorials > Ruby Game Scripting System (RGSS) > RGSS For Dummies Tutorial 3: Control Flow
|
|
RGSS For Dummies Tutorial 3: Control Flow |
|
Author: RPG
Updated: September 04, 2007
|
|
Introduction
|
|
Our little variable and print programs were executed line by line; they weren't
interactive and just displayed some text on the screen. Real programs aren't
like that, they interact with users and other things to produce the desired
output. Ruby (and all high level languages) introduces some statements
(commands) that we can use to add interactivity to our scripts, mainly it
introduces conditional statements and loops. A conditional statement (or
expression) basically checks if a condition is met. If it is met, then some
commands will be executed, otherwise some other commands might be executed,. As
for loops, they allow you to execute a block of code over and over until a
condition is met. Loops and conditional statements are essential in programming,
if you don't learn them then you'll probably stay a worthless noob till the end
of time! ;)
|
|
Contents
|
|
1. Boolean Expressions
2. Important Note
3. Conditional Statements
3.1. if
3.2. unless
3.3. Ternary operator
4. Loops
4.1. while
4.2. until
4.3. Ranges
4.4. for
4.5. loop
4.6. break, next, retry, redo
4.7. Statement Modifiers
5. Conclusion
6. Summary
|
|
1. Boolean Expressions
|
|
A Boolean value is a value that can either be true or false. Think of a switch
that can be either on or off, or a path that only goes left and right; there's
no gray about Booleans, everything is black and white. You might be asked: "is u
alex???", thre are two valid answers for that question, either "lol yes im
alex!!!", or "no im not r u???". So if we had a Boolean variable called
is_u_alex?, (variables can't have spaces, so we use underscores) the value of
the variable could be true if you are Alex and false if you aren't. Makes no
sense, I know. Let's try something more simple, the mathematical statement "1 is
equal to 2" is false, while the statement "1 is equal to 1" is true. Here are
some other statements that can be true or false:
"3 is bigger than 2"
"98 is equal to 89"
"0.01 is smaller than 0.1"
"3 is smaller or equal to 3"
|
I think you know which ones are true and which ones are false, if you don't then
check this statement: "RGSS for Dummies isn't equal to RGSS for Idiots". Now, in
programming we can compare two values to get a Boolean value that evaluates the
comparison. We use "==" to indicate equality. Remember when I talked about
variable assignment and I said that the = operator means assignment and not
equality? "var = 5" means assign 5 to var, while "var == 5" means that var is
equal to 5. Let's just try an example:
This will output 'true'. Basically we're asking RGSS to evaluate the statement
"1 is equal to 1", just like we were evaluating statements earlier. Now, change
both numbers and see the various results. "p 1 == 4" would output false, p "0.1
== 0.1" would output true, etc. You can even use strings like "cow" == "cow" or
1 == cow. It's really simple, the statement can be either true or false and RGSS
evaluates it for us. Other than the equality operator "==", we can use ">"
for bigger than, "<" for smaller than, ">=" for bigger or equal to,
"<=" for smaller or equal to and "!=" for not equal to. These examples will
help:
p 1 > 2 # false
p 5 == 5 # true
p 0 >= 0 # true
p 4 < 1 # false
p -19 <= 0 # true
p 1 == 8 # false
p 1 + 3 == 2 + 2 # true
p 4 != 7 # true
|
It's all simple logic, all of those are Boolean statements that can be true or
false. Now, since they're Boolean statements, their evaluation values can be
stored in Booleans, for example:
my_bool1 = 9 == 9
my_bool2 = 3 <= 1
my_bool3 = true
p my_bool1 # true
p my_bool2 # false
p my_bool3 # true
|
I just stored Boolean values in Boolean variables, this should help you
understand the difference between "=" and "==", you use the former to store the
values on the right of the "=" in the variable on the left of it, and you use
"==" to compare two values for equality. Also, note that we can directly store
true or false values in variables, just like I did with my_bool3. Another
thing you can do is to evaluate multiple statements at once. You can use "and",
"or" and "not". You place an "and" between two statements and the new statement
(statement1 and statement2) will evaluate to true if both statements are true,
and to false if one or both of the statements are false. Examples:
p 1 == 1 and "hello" == "hello" # true
p 1 > 5 and 5 >= 1 # false
p 9 < 3 and 6 == 3 # false
|
You place an "or" between two statements and the new statement (statement1 or
statement2) will evaluate to true if at least one of the statements is true (one
is true or both are true), and to false if both statements are false. Examples:
p 1 == 1 or "hello" == "hello" # true
p 1 > 5 or 5 >= 1 # true
p 9 < 3 and 6 == 3 # false
|
Finally, place a "not" before a statement and the new statement (not statement1)
will evaluate to true if the original statement (statement1) is false, and to
false if the original statement is true. In other words, it returns the opposite
of the original statement. "not 1 == 1" is the same as "1 != 1" or "1 is not
equal to 1", which is false. Example:
p not 1 == 1 # false
p not 4 < 2 # true
p not (3 <= 8) # false
|
In the last example, I used parenthesis around the statement, it's generally a
good practice because it can make your code more readable, especially if you
have many statements joined with and's or or's. There's one more thing you
need to know about "and", "or" and "not"; you can abrriviate them to &&,
|| and !. Actually, there's a difference in precedence between the word forms
and the symbol forms, but it's not really that important (at the moment).
Basically, using "&&" is the same as using "and", "||" is like "or" and
"!" is like "not". Why do we use two &s and two |s instead of one? Well,
both & and | have different meanings in ruby so remember not to confuse them
with && and ||. I've rewritten some of the previous and-or-not example
with the new symbols:
p 1 == 1 && "hello" == "hello" # true
p 1 > 5 || 5 >= 1 # true
p !(4 < 2) # true
|
The last example is interesting, "not 4 < 2" works, but "! 4 < 2" doesn't.
! has higher precedence than "<" and than "not". So RGSS reads "! 4 < 2"
as "the opposite of true is less than 2", wait... the opposite of true? Well,
you see... every value in RGSS is true expect for the values false and nil, so
the value 4 on its own is true. You don't understand? Never mind then! Just
forget all about this precedence thing for now, but remember to always (most of
the time actually) use parenthesis around statements when using ! instead of
not.
|
|
2. Important Note
|
|
= is NOT the same as ==, I know I mentioned that already but this is one common
mistake in programming. Even professionals working for Microsoft might fell for
it and use = instead of ==. Always remember that = is only used to assign
values, and that == is used to test for equality of two values. I know you'll do
this mistake sooner or later (I did, a lot!), but when something isn't working
in your program, it's a good idea to check the comparisons to see if you used =
instead of ==.
|
|
3. Conditional Statements
|
|
The hero of light was sent on a mission to retrieve defeat the evil dragon king,
he does that and returns to the king. The king (of happyland) asks for proof and
the hero presents the 'evil dragon king's magical nose™' which makes the king
happy and everyone lives happily ever after. This could be the story of your
upcoming groundbreaking RPG that you plan to send to Squaresoft, they will use
it part of it (because it's too complicated to be fully used) as the story for
the next Final Fantasy game and you'll be very rich and famous. There's one
problem though... how would the king know that the hero has the 'evil dragon
king's magical nose™'? Maybe we want the king to say "You did it! You have the
nose so you must have defeated the dragon" if the player has the item and "Oh,
you don't have the magical nose™! Go defeat the evil dragon king before it's too
late!” In English we might say "If the hero has the item, the king will say the
'you did it!' thing. Otherwise the king will say the 'go defeat the dragon'
thing". Another example is saying "If I was Alex, I would be strong". Notice
the pattern? If some condition is met, something will happen. Conditional
statements are used to evaluate if something is true or false and do something
if it's true.
|
|
3.1. if
|
if condition
do something (true)
else
do something (false)
end
|
The condition is simply a statement that can be true or false, a Boolean
expression in other words, it could also be a simple Boolean variable. And the
first 'do something' could be a block of code that would be executed if
condition is true. The other do something (after else) is another block of code
that'd be executed if the condition is false. So basically, the if statement
allows you to have branches in your script, different thing would happen
depending on different situations. If you used rm2k/3, you might remember the
conditional branch command, which is simply a form of if statements. Here's an
example demonstrating how to use if:
cow = true
if (cow == true)
p 'cow is true!'
else
p 'this will never be executed!'
end
cat = false
if (cat == true)
p 'this will never be executed!'
else
p 'cat is false'
end
|
Note that you can simply use if cow or if cat, there's no need for the
parenthesis surrounding the condition; I just do it because I feel it'd be
clearer that way. One thing you can add to the if statement is an elsif (stands
for else if), elsif is followed by a condition and is executed if the preceding
if condition isn't met. An example might make it clearer:
age = 15
if (age < 13)
p 'child'
elsif (age < 18)
p 'teenager'
elsif (age < 150)
p 'adult'
else
p 'Man, you're too old. You should be dead by now'
end
|
If you run that program you'd get 'teenager' as output. How does it work? First it checks if the age is less than 13, it's not so you'd expect it to go to the else statement. However, elsif is actually an else statement followed by an if, it checks for another condition if the one before it wasn't met. The elsif condition checks if age is less than 18, and prints a message (because the first if failed we know that the age will be >= 13). If you change the age value to
40 instead of 15 the first elsif will fail and the second elsif condition will be evaluated. If you change age to 200 for example then all the conditions will fail and the code after the last else will be executed.
The last thing you need to know about if is that you can nest ifs, like this:
if 1 == 1
if 2 == 2
p 'Hello world!'
end
end
|
The inner if will be executed only if the outer one succeeds. It might look
confusing if you next too ifs inside each other so don't overdo it if you don't
need it. You can also nest loops the same way (as well as classes and methods,
basically all blocks can be nested inside each other, I think...)
|
|
3.2. unless
|
unless (condition)
do something (false)
else
do something (true)
end
|
Unless is the opposite of if. It executes the first statement if the condition is false, and the second if it is true. It's like saying "if not(condition)".
boolean = false
unless boolean
print 'hi'
end
|
As you can see, we didn't use else in this example, it's optional. You can also have if statements without else... actually, most of the time you wouldn't need an else case.
|
|
3.3. Ternary operator
|
var = condition ? value (true) : value (false)
|
There's a shortened form of the if statement, the ternary operator (the ?) checks if condition is true, if it is the first value (left of :) will be returned and stored in var, otherwise it'd store the second value (right of the ":") in var. In other words, the value of var will be value (true) if condition is true, and value (false) if it is false.
monkey = true
my_var = monkey ? 1 : 2
p my_var # 1
|
case var_name
when val1
do something
when val2
do something
when val3
do something
when val4
do something
else
do something
end
|
The case statements compares the expression following it (var_name) with each
expression after a when (val1, val2, val3, val4), it executes the code (do
something) following the matched when and if no when is matched the code after
else (which is optional) will be executed. You can have as many whens as you
like and you can think of the case statement as a long list of if...elsif, but
the only condition we check is equality between the expression after case and
the other expressions after the whens. Here's an example:
number = 1
case number
when 0
p 'The number is zero.'
when 1
p 'The number is one.'
when 2
p 'the number is two.'
Else
p 'The number isn't zero, one or two.'
end
|
|
|
4. Loops
|
|
A conditional expression just checks if a condition is true (or false) and
executes some code. A loop keeps executing some code until a condition is met.
For example, in game programming you generally check for input, do some
calculations and finally draw stuff. Here's what your game source code might
look like:
check input
do calculations
draw stuff
|
There's one problem though, everything will be executed line by line, first it
checks for input, does calculations such as changing hero's position depending
on input and finally draw the map and sprites. The problem is, the program ends
after the last line (draw stuff), there isn't anything else to do, it executed
all the commands and drew one frame and that's it. You might think of asking the
computer to do that again like this:
check input
do calculations
draw stuff
check input
do calculations
draw stuff
...
|
Even if you add thousands of line, the program execution will eventually end.
What you need is a way to ask the program to do things again and again, until
the player exits the game by pressing escape or something. Something like:
while (Esc isn't pressed)
check input
do calculations
draw stuff
end
|
This is how loops work, the condition after while will be checked and as long as
it's true the code will be executed again and again. The condition will be
checked every loop (iteration) so your code will need to break out of the loop
eventually. Loops allow you to create interactive programs that don't 'die',
it's pretty similar to the way RPG Maker's parallel process and auto start
events work, instead of ending somewhere you can do things all over again.
|
| 4.1. while |
while (condition)
do something
end
|
The code between condition and end (do something) will be executed as long as the condition evaluates to true. If it evaluates to false, the loop ends and the code after the loop will be executed. Like the if statement, you don't really need parenthesis around the condition.
|
| 4.2. until |
until (condition)
do something
end
|
Until executes the code between the condition and end (do stuff) until the condition is true, or in other words, while the condition is false. It's the opposite of while.
|
|
4.3. Ranges
|
|
A range is an ordered sequence of objects (numbers, strings, anything), they
aren't loops or anything but they can help you understand the for loop. (which
will be discussed next) Basically, a range written as (0..3) includes 4 numbers:
0, 1, 2 and 3. The range ('A'..'D') includes: A, B, C and D. So, a range is just
a sequence that can be written as (start..end). You can also write it as
(start...end) (3 dots in this version, 2 dots in the earlier examples), doing so
will exclude 'end' from the set, for example, 0...3 includes 0, 1 and 2. You can
store ranges in variables too.
|
|
4.4. for
|
for varname in range/array
do something
end
|
Ruby's for loop is different than the ones you'd find in other programming
languages. It simply iterates over a collection (Range/Array) and the variable
after the for (varname) will hold the value of the current Range/Array element.
For example:
for x in (0..10)
print x
end
|
You'll get numbers from 0 to 10 as output for this example. How? For loops over
the elements in the range (0..10) and each loop x will be assigned to one
element (0, then 1, then 2, etc.), so we just print x's value. If you wanted to
write a similar thing using while, you'd do something like:
x = 0
while (x < 11)
print x
x += 1
end
|
See? It takes more lines to do it that way. You might be wondering what x += 1
means, it's just another way of saying x = x + 1. You can also do x -= number, x
*= number, x /= number, etc.
So, why do we use for anyways? Why'd we need to increase a number each loop? The main use of the for loop is to deal with
arrays, which will be discussed in the next tutorial. An array is just one name
that holds many values, and each value is addressed with a number called index.
Sometimes you might want to change or view all the values in an array and you
use the for loop (or an array method) to do that. More about it in the next
tutorial.
|
|
4.5. loop
|
|
The simplest loop, it doesn't check for any conditions and just keeps looping
for ever. Of course, looping forever isn't a good thing, eventually the user
would want to exit your program/script/game. The only way to exit such a loop is
to break out of it, which is discussed next.
|
|
4.6. break, next, retry, redo
|
|
Sometimes you might like to control your loops, and you use back, next, retry
or/and redo to do that. Break ends the loop and execution continues at the
statements after the loop block. (after end) Next skips everything following it
and starts a new iteration. Retry starts the loop from the very beginning and
redo repeats the current iteration from the start. These examples might help:
# The output of the following loop would be: 0 1 2 3 4 5
# Basically we check if x is equal to 6 and stop looping
for x in (0..10)
if (x == 6)
break
end
p x
end
# The output of the following loop would be: 0 1 2 3 4 6 7 8 9 10
# Notice how the 5 is missing from the output .When x is 5, next
# will skip anything after the if (it'd skip p x) and start the next loop (6)
for x in (0..10)
if (x == 5)
next
end
p x
end
|
As for retry and redo, basically redo will go back to the beginning of the
current loop, if you add a redo after the if in the previous example, the output
would be 0 1 2 3 4 and then you'd get an infinite loop (because it'll never get
to the print statement (p x) and would check if x == 5 again and again. Retry is
similar to redo, but it goes back to the beginning of the entire loop instead
from the beginning of the entire iteration, adding a retry after the if in the
previous example would get you an infinite loop with output like 0 1 2 3 4 0 1 2
3 4 0 1 2 ....
|
|
4.7. Statement Modifiers
|
|
In the break and end examples, we had an if statement like:
You might think it's a bit annoying to put everything on separate lines. In
cases like this, you might like to put everything on one line this way:
This if is called the if modifier, it works just like an if but operates on one
line. Actually, it can also be attached to a block, but that's another story.
You can also have an unless, while, until modifiers:
do something unless condition
do something while condition
do something until condition
|
|
|
5. Conclusion
|
| I realize that this tutorial was boring, but understanding conditional
statements and loops is essential to understand more advanced subjects. I think
it shouldn't be hard to follow because it's just logic, if something then
something, while something is true something will keep happening, for each
element in a sequence do something, etc. The next tutorial will introduce you to
arrays, hashes, methods and some other topics. |
|
6. Summary
|
- A Boolean expression is an expression that evaluates to either true or
false. - Comparison operators such as (>, ==, <) are used to compare
two values and produce a Boolean value. - More complex Boolean expressions
can be formed by combining two or more expressions with && (and) or ||.
(or)
- Conditional statements check if a condition (Boolean expression) is true or false, then executes some code depending on the result. - If and unless are conditional expressions, you can also add an else or an elsif (else if) to them - The case statement compares one expression with many other expressions.
- Loops execute some code until some condition is met. (or while it's not met) - While and until are loop statements. - A range is a sequence of ordered objects. - The for loop iterates over each element in an array or a range. - 3 monkeys are not enough for one day. - You can control loops with break, next, retry and redo. - Statement modifiers allow you to write less code. |
 |
More in the 'RGSS For Dummies' series:
• RGSS For Dummies Tutorial 1: The Basics
• RGSS For Dummies Tutorial 2: Variables
• RGSS For Dummies Tutorial 3: Control Flow
• RGSS For Dummies Tutorial 4: Containers and Methods
• RGSS For Dummies Tutorial 5: Object Oriented Programming and More!
• RGSS For Dummies Tutorial 6: Game Programming 101
• RGSS For Dummies Tutorial 7: Windows for Dummies |
|