Basic

Control Flow: Conditionals

Make code choose. With if/else if/else and comparison operators, a program can react, "if there's a pit ahead, jump", which is the heart of a game.

What you will see

no jump left no jump left

About 4 min of reading

Quick check

Before this new lesson, one small question about the lesson you just finished. Recall it, do not look it up.

Try It

A reactive game is a loop of questions asked every frame, am I on the ground? did I touch a spike? did I pass a coin?, and with if, else if, and else a program can answer them and choose what happens. I want to stop thinking conditionals are just booleans and actually make code branch, watch it pick one path and skip the rest, and reproduce the exact double-jump decision the finished game ships so the first real game logic feels familiar.

1

Every decision starts with a question that is only true or false. I set a score, ask whether it is above a pass mark with a comparison, and put the answer inside an if block. score > 50 is itself a value, a boolean, and the block runs only when that boolean is true.

let score = 80 if (score > 50) { console.log("You win!"); }

Before you run it, say out loud what it will print. Then open the answer.

What it prints
You win!
The comparison operator > makes a question; a single = assigns a value and would never check anything. Write ===, >, <, >=, or <= inside the parentheses, and keep the code to run inside the curly braces.
2

A second if with a harder threshold is skipped, proving the chain only runs the questions that are true. I ask whether score beats 100, it does not, so that block disappears, while the first block already ran. That is the whole rule: if true runs the block, else it skips.

let score = 80 if (score > 50) { console.log("You win!"); } if (score > 100) { console.log("Mega win!"); }

Before you run it, say out loud what it will print. Then open the answer.

What it prints
You win!
Only the first block prints. The mega win block is skipped because 80 > 100 is false. Each if is independent, so both are checked; only the true one produces output.
3

Now the real chain: if, else if, else, with each condition more specific than the last. I grade a score of 80 and trace it out loud, not >= 90, so skip; >= 80, so print Grade: B, then the chain stops. The first matching branch wins and nothing below it runs.

let score = 80 if (score >= 90) { console.log("Grade: A"); } else if (score >= 80) { console.log("Grade: B"); } else if (score >= 70) { console.log("Grade: C"); } else { console.log("Grade: F"); }

Before you run it, say out loud what it will print. Then open the answer.

What it prints
Grade: B
Order matters: the chain checks top to bottom and stops at the first true branch. If I put score >= 70 above score >= 80, an 80 would wrongly print Grade: C. Put the most specific conditions first.
4

I lift the exact structure out of the game's Player.js and run it as a real function, passing onGround in as a parameter so I can show both decisions. jump(true) is on the ground (full jump); jump(false) fires the double jump. This is the double-jump decision from the finished game in app1/js/entities/Player.js, the same if, else if shape, just with a number written into a property instead of a log.

let jumpsLeft = 1 function jump(onGround) { if (onGround) { console.log('full jump'); } else if (jumpsLeft > 0) { console.log('double jump'); jumpsLeft = jumpsLeft - 1; } } jump(true) jump(false)

Before you run it, say out loud what it will print. Then open the answer.

What it prints
full jump double jump
jump(true) runs the onGround branch for a full jump and never touches jumpsLeft. jump(false) skips the first branch and fires the double jump, using up the one jump left. The real game decides the same way inside its loop every frame, just by reading this.onGround and this.jumpsLeft.
5

I flip the question on purpose to watch the chain take the lower branch and consume a jump, then run once more to see what else prints when nothing matches. onGround is false and jumpsLeft is now 0, so neither branch runs and the else prints.

let jumpsLeft = 0 function jump(onGround) { if (onGround) { console.log('full jump'); } else if (jumpsLeft > 0) { console.log('double jump'); jumpsLeft = jumpsLeft - 1; } else { console.log('no jump left'); } } jump(false) jump(false)

Before you run it, say out loud what it will print. Then open the answer.

What it prints
no jump left no jump left
With onGround false and jumpsLeft at 0, neither branch runs, so the else prints. That fall-through is exactly why real game code guards every input: when a decision has no answer left, the fallback tells you something is wrong.

Put it in order

Before you write anything, put these lines back in the right order. Click a line to move it up one step. This support step is easier than writing code from scratch, and it is here to make the last example stick.

Data Flow

A comparison evaluates to a boolean, and the first matching branch of an if chain runs before the chain stops.
1 Evaluate a question like score > 50
↓
2 It becomes true or false
↓
3 if: true runs the block, false skips it
↓
4 else if checks the next question only if the last was false
↓
5 else runs only when nothing matched, then the chain stops
Why this works
Comparison operators

Every decision starts with a boolean question. These operators all evaluate to true or false:

OperatorMeansExample
===exactly equalscore === 100
!==not equallives !== 0
< / >less / greater thanspeed > 700
<= / >=with equalityscore >= highScore

Use === (triple) to compare. = (single) assigns. Confusing them is one of the most common beginner bugs, if (score = 100) doesn't check anything, it just writes 100.

and / or / not combine questions and **short-circuit*: evaluation stops as soon as the result is known.

Why the game asks questions every frame

A reactive game is a loop of questions. Every single frame the code asks:

  • "Am I on the ground?" → if yes, I can jump again.
  • "Did I touch a spike?" → if yes, I took damage.
  • "Did I pass a coin?" → if yes, score +1.

The grade example in this lesson is structurally identical to that. The only difference is that in a real game those if statements live inside the game loop (we meet the loop in the Advanced tier), so the questions are re-asked ~60 times a second.

The key idea: a program does the same thing every time unless code chooses. Conditionals are the choosing.

Examples

The if statement

A decision needs a question that can only be answered true or false. We build those with comparison operators.

const score = 80;
if (score > 50) {
  console.log("You win!");      // runs: 80 > 50 is true
}
if (score > 100) {
  console.log("Mega win!");     // skipped: 80 > 100 is false
}

The question goes in ( ...), the code to run in { ... } (the block). If the question is true the block runs; otherwise it's skipped.

Read it out loud: "if score is greater than 50, then print 'You win!'". The result of score > 50 is itself a value, true: and you can even store it: const isBig = score > 50;.

if / else if / else

Often there's more than one possibility. Chain them with else if and finish with else (the "none of the above" fallback):

const score = 80;
if (score >= 90) {
  console.log("Grade: A");
} else if (score >= 80) {
  console.log("Grade: B");     // runs: 80 is not >= 90, but is >= 80
} else if (score >= 70) {
  console.log("Grade: C");
} else {
  console.log("Grade: F");
}

JavaScript checks each question top to bottom and runs the first one that's true, then stops. So order matters, put the most specific conditions first.

Trace score = 80: is it >= 90? No, skip. >= 80? Yes → print "Grade: B" and stop.

Real game decision: the double jump

The most complex decision in the whole game is deciding which kind of jump to do. Here's the shape from the real app1/js/entities/Player.js:

jump() {
  if (this.onGround) {
    // First jump: from the ground, full impulse.
    this.vy = CONFIG.JUMP_IMPULSE;
  } else if (this.jumpsLeft > 0) {
    // Second jump (double jump), a slightly weaker impulse.
    this.vy = CONFIG.Double_JUMP_IMPULSE;
    this.jumpsLeft--;
  }
}

That's the same if / else if structure as the grade example, the first matching branch runs, then the function moves on. The decision reads like plain English: "if I'm on the ground, full jump; else if I still have a jump left, double jump."

Watch out: remember === for comparisons. = assigns; === checks.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Math and Expressions
Previous Lesson
Math and Expressions
Next Lesson
Loops (Repetition)
Loops (Repetition) →