Forty bricks, and not one of them written by hand.
const spawnBrick = useSpawn(Brick);
for (let row = 0; row < BRICK_ROWS; row++) {
for (let col = 0; col < BRICK_COLS; col++) {
spawnBrick({ row, col });
}
}Two loops, one grid
A loop walks a list. Two nested loops walk a grid: for every row, every column. Five rows by eight columns, forty passes, forty bricks.
And the position comes from arithmetic, not a table:
const x = MARGIN_X + col * (BRICK_W + GAP_X);
const y = TOP + row * (BRICK_H + GAP_Y);Start at the margin, then advance one brick plus one gap per column. Change BRICK_COLS
to 12 and the wall rebuilds itself. With forty hand-written positions, changing the layout
would be an afternoon.
The colour comes from the row too:
tint: getColor(ROW_COLORS[row]),ROW_COLORS is a list of five colours and ROW_COLORS[row] picks the matching one: [0]
is the first, [1] the second. Lists start counting at zero, always, in every language
you're going to meet.
A second file
Something new here: there are two tabs above the editor. bricks.ts is a separate file,
and the main one pulls it in with:
import { BRICK_COLS, BRICK_ROWS, Brick } from './bricks';It isn't ceremony, it's the natural moment. The old file did one thing; now there are two subjects (the match and the bricks) and each fits whole in your head. One file per subject is what keeps a game editable three months later.
useSpawn: an object of its own for each brick
const spawnBrick = useSpawn(Brick);
spawnBrick({ row: 0, col: 3 });Up to now you were making loose sprites in the scene. useSpawn prepares a brick maker, and
every call to it gives birth to an object with an identity of its own, bundling
everything Brick registers: its sprite, its state, its loops. Whatever you pass between
the parentheses reaches Brick as its argument.
Right now it looks like a wrapper with no payoff. Next chapter it's what lets you delete one specific brick without touching the other thirty-nine.
What exactly does a `for` do?
for (let col = 0; col < 8; col++) {
// ...
}Three parts separated by semicolons:
let col = 0: start counting at zero.col < 8: keep going while this is true.col++: and after each pass, add one.
So the block runs with col equal to 0, 1, 2, 3, 4, 5, 6 and 7. Eight passes. At 8 the
condition fails and it stops.
When you put a for inside another, the inner one runs its whole cycle for every pass
of the outer one. Five outer × eight inner = forty.
Your turn
Try BRICK_ROWS = 8. Try BRICK_COLS = 4 (note the wall comes up short: the brick width
is fixed, so there's a gap on the right).
And change the colours in ROW_COLORS. Five strings, any CSS colour.
The ball still sails straight through the bricks. That's next.