6.1 Groups

Aligned outcomes:

SLO 3

Describe, design, implement, and test structured programs using currently accepted methodology.

Learning Objectives

By the end of this section, you will be able to:

In this section, you will learn to:
  • Create a Group to manage many sprites that share traits.
  • Spawn sprites into a group using new groupName.Sprite(...).
  • Set group defaults that apply to every sprite in the group.
  • Use the built-in allSprites group and attach custom, non-built-in properties to a group of your own.

6.1.1 What is a Group?

A Group holds many sprites that share traits. Set a property on the group and every sprite spawned into it inherits that value as its default.

Think of a group like a cookie cutter with a preset dough color. You set the color once on the group, and every sprite you stamp out of that group starts with that color. You can still change individual sprites afterward, but the default comes from the group.

Definition 6.1.1: Group

A collection in moSHion that holds sprites sharing common traits. Properties set on a group become defaults for sprites spawned into it.

Try It Now 6.1.1

Create a group and set its color to 'gold'. Spawn three sprites from the group. All three should be gold without you setting their color individually.

Editor
runs in a sandboxed frame
▶ Press Run to see the output…
Solution
Editor
runs in a sandboxed frame
▶ Press Run to see the output…

You should see three gold circles at (100,100), (200,200), and (300,300). All three inherited the color, diameter, and collider settings from the stars group.

6.1.2 Creating and Using Groups

Create a group with new Group(). Then spawn sprites into it with new groupName.Sprite(...) — note the capital S. That factory reads the group's color, diameter, collider, and other defaults, copies them onto the new sprite, and adds the sprite to the group.

The capital S in new groupName.Sprite(...) matters. Group is a class, and .Sprite is a special method on each group instance that creates new sprites pre-configured with the group's defaults. If you use lowercase sprite, it won't work.

Try It Now 6.1.2

Create two groups: one for stars (gold, small) and one for planets (various colors, larger). Spawn two sprites from each group. Each group's sprites should have different defaults.

Editor
runs in a sandboxed frame
▶ Press Run to see the output…
Solution
Editor
runs in a sandboxed frame
▶ Press Run to see the output…

You should see two small gold stars at the top and two larger blue planets below. The stars are gold and small (diameter 16) because those are the stars group defaults. The planets are steelblue and larger (diameter 40) because those are the planets group defaults.

6.1.3 Group Defaults

Common defaults to set right after creating a group: color, diameter (for circles) or w/h, collider ('none' is useful for pickups and decorations), and layer.

Setting collider to 'none' means the sprite won't participate in physics collisions at all. This is perfect for decorations, background stars, and items the player should pass through.

Definition 6.1.2: Collider

A property that determines whether a sprite participates in physics collisions. 'none' means no collisions; the default value means full collision detection.

Try It Now 6.1.3

Create a group of 10 stars scattered randomly across the canvas. Use a loop to spawn them. Set the group's collider to 'none' so they don't interact with physics.

Editor
runs in a sandboxed frame
▶ Press Run to see the output…
Solution
Editor
runs in a sandboxed frame
▶ Press Run to see the output…

You should see 10 gold circles scattered randomly across the dark canvas. their positions come from the loop counter i. The stars don't fall or collide because their collider is 'none'.

6.1.4 allSprites and Custom Properties

Every sprite you've ever created — player, ground, stars, coins, all of them — joined a built-in group called allSprites the moment it was made. You never construct it; it's already there. It's useful whenever you want to touch "every sprite in the scene" at once: allSprites.length for a live total count, or for (const s of allSprites) to loop over the whole world regardless of which group anything else belongs to.

Groups also aren't limited to moSHion's own properties like color and diameter. Assign any property name you like on a group, and it becomes a default for every sprite spawned into it afterward — coins.value = 1 gives every coin an .value of 1 the moment it's created. Each sprite gets its own independent copy of that value on spawn (exactly like §5.3.2's independence rule), so changing one coin's .value later doesn't touch the others; the group just holds the starting template.

Definition: Custom Group Property

Any property name assigned directly on a Group (not one of moSHion's built-ins like color) becomes a default copied onto every sprite spawned from that group afterward. Each spawned sprite gets its own independent copy — it's a way to attach your own game data (like a point value or a hit-points count) to every member of a group without writing a custom class.

This is the same idea §5.4 built a whole Goal class around — a piece of data that travels with an object — but reached a lighter way. A custom class is right when an object needs its own behavior (methods like isNear/collect). A custom group property is enough when every member just needs to carry the same starting value, like every coin being worth 1 point.

Try It Now 6.1.4

Give your coins group a custom .value = 1 property, set on the group right after creating it. Confirm allSprites.length reports every sprite in the scene, not just the coins.

Editor
runs in a sandboxed frame
▶ Press Run to see the output…
Solution
Editor
runs in a sandboxed frame
▶ Press Run to see the output…

Every coin picked up its own .value of 1 from the group's default, the same way each one already picks up color, diameter, and collider. allSprites.length reports 8 here because every sprite so far — all of it — is a coin; add a player sprite and that count would climb to 9 without touching coins.length at all, since the two groups are tracking different (overlapping) memberships.

6.1.5 Challenge: Extend It Yourself

No starter code this time — you build it. Create a group called coins, gold, diameter 20, collider = 'none', and spawn 8 of them scattered across the canvas (not in a straight line — use randomness or a grid). This exact group is what §6.2 turns into a scoring pickup game, so keep the sketch — you'll build directly on top of it next section.

Hint (try the Challenge yourself first!)

Math.random() * 400 for each coordinate gives you scattered positions; wrap the spawn in a loop of 8 iterations, same shape as Try It Now 6.1.3's loop of 10.

Problem Set 6.1

Problem 1. What is a Group in moSHion? What problem does it solve?

Solution

Step 1 — Define the concept: A Group in shPlay is a collection that holds many sprites sharing common traits. You create one with new Group().

Step 2 — Explain the problem it solves: Without groups, you would have to set color, diameter, collider, and other properties individually on every sprite — tedious and error-prone when you have 10 stars or 50 coins. A group lets you set those defaults once on the group, and every sprite spawned into it via the factory inherits them automatically. It also gives you a way to manage all members together (loop over them, count them with .length, etc.).

Answer: A Group is a collection of sprites with shared traits; it solves the problem of repeatedly configuring many similar sprites by letting group-level defaults apply to every sprite spawned into it.

Problem 2. How do you spawn a sprite into an existing group? What is the syntax?

Solution

Step 1 — Recall the factory syntax: You spawn a sprite into an existing group using the group's special factory method:

new groupName.Sprite(x, y);

For example: new stars.Sprite(100, 100);

Step 2 — Note the capital S: The S in .Sprite must be capitalized. The group is a class instance, and .Sprite is a special method that creates a new sprite pre-configured with the group's defaults (like color, diameter, collider) and adds it to the group. Using lowercase sprite will not work.

Answer: Use new groupName.Sprite(x, y) — with a capital S. This copies the group's defaults onto the new sprite and adds it to the group's membership.

Problem 3. If you set stars.color = 'gold' and then spawn a sprite with new stars.Sprite(100, 100), what color will the sprite be? What if you then set sprite.color = 'red'?

Solution

Step 1 — First spawn: Since stars.color = 'gold' was set before spawning, the factory copies that default onto the new sprite. So new stars.Sprite(100, 100) produces a gold sprite.

Step 2 — After overriding: Setting sprite.color = 'red' afterward changes only that individual sprite. Group defaults are just starting values copied at spawn time; each sprite owns its own independent copy of every property. The group's color stays 'gold', and any other sprites in the group remain gold too.

Answer: The sprite spawns gold (inheriting the group default). Setting sprite.color = 'red' changes only that one sprite to red — the group default and other sprites are unaffected.

Problem 4. What does setting collider to 'none' do? When would you use this?

Solution

Step 1 — What 'none' does: Setting collider = 'none' means the sprite does not participate in physics collisions at all. It won't bounce off things, block movement, or be affected by collision forces.

Step 2 — When to use it: Use it for anything the player should pass through or that shouldn't interact physically: decorations, background stars, pickups/coins (until §6.2 adds manual overlap detection), particles, and UI-like elements. Without it, decorative sprites would collide with the player and ground like solid objects.

Answer: collider = 'none' disables physics collisions entirely for the sprite; use it for decorations, background elements, and pickups the player should pass through rather than bump into.

Problem 5. Create a group called coins with a gold color, diameter 20, and no collider. Spawn 5 coins in a row using a loop.

Solution

Step 1 — Create and configure the group: Set the required defaults once on the group so every coin inherits them:

Editor
runs in a sandboxed frame
▶ Press Run to see the output…

Step 2 — Spawn 5 coins in a row with a loop: A loop keeps the code short and spaces the coins evenly across the canvas:

  for (let i = 0; i < 5; i++) {
    new coins.Sprite(60 + i * 70, 200);
  }

Each iteration places a coin at \(x = 60, 130, 200, 270, 340\), all at \(y = 200\).

Full sketch:

Editor
runs in a sandboxed frame
▶ Press Run to see the output…

Answer: Five gold coins of diameter 20 with no collider appear in a horizontal row across the middle of the canvas, all configured by the group defaults set once in setup().

Problem 6. What is the difference between new Sprite(100, 100, 20) and new coins.Sprite(100, 100)? When would you use each one?

Solution

Step 1 — Compare the two calls:

  • new Sprite(100, 100, 20) creates a standalone sprite not belonging to any custom group. Its diameter is 20, but its color, collider, etc. are shPlay's generic defaults.
  • new coins.Sprite(100, 100) uses the group factory: it creates a sprite pre-configured with everything set on the coins group (gold color, diameter 20, collider = 'none') and registers it as a member of coins.

Step 2 — When to use each: Use plain new Sprite(...) for one-off objects with unique traits — a single player, a single goal. Use the group factory whenever you're making many sprites that share traits, because it saves repeating configuration and lets you manage them as a set (coins.length, looping over coins).

Answer: new Sprite(100, 100, 20) makes an independent sprite with generic defaults; new coins.Sprite(100, 100) makes a sprite stamped from the coins group's defaults and added to that group. Use the former for unique one-offs, the latter for batches of similar sprites.

Problem 7. Can you change a sprite's properties after it has been spawned from a group? Does that affect other sprites in the same group?

Solution

Step 1 — Can you change properties after spawn? Yes. Group settings are only defaults copied onto the sprite at the moment it's created. Afterward, the sprite is fully independent — you can write someSprite.color = 'red' or someSprite.diameter = 30 freely.

Step 2 — Does it affect other sprites? No. Each sprite gets its own independent copy of every property at spawn time (the same independence rule as §5.3.2). Changing one sprite's property touches only that sprite — the group's default and all other members keep their values.

Answer: Yes, you can change a spawned sprite's properties anytime, and doing so affects only that sprite — other group members and the group's defaults are untouched.

Problem 8. What happens if you set a property on the group after sprites have already been spawned? Do existing sprites get the new value?

Solution

Step 1 — What happens to existing sprites: Nothing changes for them. The group's properties act as a template read at spawn time. Sprites already created received their own copies of the values as they were when they were spawned.

Step 2 — Who gets the new value: Only sprites spawned after the change inherit the updated default. Existing sprites keep their old values unless you update them individually (e.g., loop over the group and assign the new value yourself).

Answer: Changing a group property after spawning does not retroactively update existing sprites; only future sprites spawned from the group get the new value.

Problem 9. What is allSprites, and how is it different from a group you create yourself with new Group()?

Solution

Step 1 — What allSprites is: allSprites is a built-in Group that every sprite automatically joins the moment it's created — whether made with new Sprite(...), a group factory, or anything else. You never construct it; it already exists.

Step 2 — How it differs from your own groups: A group you create with new Group() only contains the sprites you explicitly spawn into it, and you can give it custom defaults. allSprites instead tracks everything in the scene regardless of membership in other groups (a sprite can be in both coins and allSprites). It's useful for scene-wide operations: allSprites.length counts every sprite, and for (const s of allSprites) loops over the whole world.

Answer: allSprites is the built-in group containing every sprite in the scene automatically, whereas a self-made group contains only the sprites you spawn into it. Use allSprites for counting or touching everything at once; use custom groups for managing specific kinds of sprites.

Problem 10. You set enemies.hp = 3 on a group before spawning any enemies from it. What happens to enemies.hp if you later change one specific enemy's .hp to 1? Does it affect the group's default or the other enemies?

Solution

Step 1 — At spawn time: Because enemies.hp = 3 was set before spawning, every enemy created from the group starts with its own independent copy of .hp = 3.

Step 2 — After changing one enemy: Setting oneEnemy.hp = 1 modifies only that enemy's copy. The group's default enemies.hp remains 3, and every other enemy still has .hp = 3. Custom group properties follow exactly the same independence rule as built-ins like color.

Answer: Only that one enemy's .hp becomes 1; the group's default stays 3 and all other enemies keep .hp = 3, since each sprite gets an independent copy of the group's values at spawn.

Key Terms

Term Definition
Collider A property that determines whether a sprite participates in physics collisions; 'none' disables collisions
Group A collection in moSHion that holds sprites sharing common traits; properties set on the group become defaults for spawned sprites
Group factory The new groupName.Sprite(...) syntax that creates a sprite pre-configured with the group's defaults
allSprites A built-in Group every sprite automatically joins on creation; useful for touching or counting every sprite in the scene at once
Custom group property A non-built-in property assigned directly on a Group, copied as a default onto every sprite spawned from it afterward