CHGame 0.3.0
Libraries for the CHGame handheld
Loading...
Searching...
No Matches
Sizzle.h
Go to the documentation of this file.
1/// @file Sizzle.h
2/// @brief Sizzle: the particle pool, the pop-up banner and the floating "+$15"
3/// texts the games share, on top of fx:: (chgame/Fx.h).
4///
5/// This is an implementation header, not part of <CHGame.h>. See
6/// @ref chgame_sizzle for how a game configures and compiles it.
7#pragma once
8#include <stdint.h>
9#include <CHGame.h>
10
11/// @defgroup chgame_sizzle Particles, banners and floating texts
12/// @ingroup lib_chgame
13/// @brief fx:: particles (sparks, confetti, coins ...), the pop-up banner and
14/// floating texts, configured per game.
15///
16/// The library is compiled apart from a sketch and sees none of its defines,
17/// and the twenty games differ in what they need (how many particles, which
18/// kinds, which banner, floats or not) and in the size tuning of the file
19/// that holds the code. So a game configures it in its own src/fx/Fx.h and
20/// the bodies are compiled in the game's src/fx/Fx.cpp:
21///
22/// @code
23/// // src/fx/Fx.h
24/// #pragma once
25/// #include <CHGame.h>
26/// #define SIZZLE_CONFIGURED 1
27/// #define SIZZLE_POOL 64 // only what differs from the defaults below
28/// #include <chgame/Sizzle.h>
29/// namespace fx { void explode(int x, int y, uint8_t n); } // the game's own extras, if any
30///
31/// // src/fx/Fx.cpp
32/// #pragma GCC optimize("Os") // line 1: it governs the bodies included below
33/// #include "Fx.h"
34/// #include <chgame/Sizzle.inl>
35/// @endcode
36///
37/// Every call site stays fx::burst(), fx::banner() and so on. Each frame:
38/// fx::update() once per logic tick; when drawing, fx::drawParticles(),
39/// fx::drawFloats() and fx::drawBanner() on top of the scene.
40///
41/// Positions are pixels; particle velocities are in 1/16 px per tick. This
42/// page documents the default configuration (the kinds SPARK, CONFETTI, STAR
43/// and DUST; the five banner styles; floats on).
44///
45/// The switches (the games' own are listed in docs/chgame-library.md):
46///
47/// | Switch | Default | Meaning |
48/// |---|---|---|
49/// | `SIZZLE_POOL` | 48 | particles in the pool |
50/// | `SIZZLE_KIND_SPARK` / `_STAR` / `_DUST` | 1 | the kinds that exist (CONFETTI always does) |
51/// | `SIZZLE_KIND_COIN` | 0 | bouncing coins; also fountain(Kind, ...) instead of fountain(x, y, n) |
52/// | `SIZZLE_KIND_RAIN` | 0 | falling drops, named SIZZLE_RAIN_KIND_NAME (RAIN_DROP; RAIN in the card games, whose hue table is then not exported under that name) |
53/// | `SIZZLE_KIND_GOO` | 0 | CHBingo's ink blobs |
54/// | `SIZZLE_KIND_ORDER` | - | the enumerators in another order (CHBoardwalk: COIN last) |
55/// | `SIZZLE_BURST` | 1 | burst() exists |
56/// | `SIZZLE_COLOUR_INLINE` | 0 | (code shape) drawParticles() reads p.colour in place instead of a local |
57/// | `SIZZLE_COIN_LATE` | 0 | (code shape) the COIN case comes after DUST and STAR, as in CHBoardwalk |
58/// | `SIZZLE_DUST` | 3 | how DUST draws: 1 one pixel, 2 a puff of size 2, 3 a puff of the size drawParticles(dust) is given (default 2) |
59/// | `SIZZLE_FOUNTAIN_GOLD_COINS` | = COIN | fountain(COIN, ...) spawns gold coins (else confetti colours) |
60/// | `SIZZLE_COIN_FLOOR` | 122 | the row coins bounce on; `SIZZLE_COIN_FLOOR_RUNTIME` 1 adds setFloor() |
61/// | `SIZZLE_HUES` | {RED, GOLD, FELT_LT, CYAN, BLUE} | the casino rainbow |
62/// | `SIZZLE_HUES_EXPORT` | 1 | exported as `extern const uint8_t SIZZLE_HUES_NAME[5]` (RAIN) |
63/// | `SIZZLE_CONFETTI_COLOURS` | {RED, GOLD, FELT_LT, CYAN, BLUE, WHITE} | confetti's colours |
64/// | `SIZZLE_NO_PARTICLES` | 0 | 1: spawn(), burst(), fountain() and drawParticles() do nothing (a game's device debug build sets it to make room) |
65/// | `SIZZLE_FLOATS` | 1 | floatText()/drawFloats(); `SIZZLE_FLOAT_CHARS` 8 (the text, with its 0), `SIZZLE_FLOAT_CLAMP` 0 (keep it on screen), `SIZZLE_FLOAT_BLINK_FIRST` 0 |
66/// | `SIZZLE_BANNER_DROP` | 0 | 0: letters of the 3x5 font pop in at 2x, 4x, 3x (maskText35); 1: the game's display font, letters dropping in one by one (the game provides maskFont(), fontWidth() and FONT_H, or `SIZZLE_FONT_MASK`/`SIZZLE_FONT_WIDTH`/`SIZZLE_FONT_H`) |
67/// | `SIZZLE_BANNER_CHARS` | 14 | the banner's text, with its 0 |
68/// | `SIZZLE_BANNER_ROWS_UP` / `_DOWN` | 18/18 (drop: 30/12) | rows around the centre activeRows() reports |
69/// | `SIZZLE_STYLES` | RAINBOW\|GOLD\|RED\|CYAN\|WHITE | the BannerStyle enumerators (`SIZZLE_BLACK`, `SIZZLE_GREEN` too) |
70/// | `SIZZLE_STYLE_RAMPS` | = STYLES | the styles with a colour ramp of their own (the rest draw as the default) |
71/// | `SIZZLE_CYAN_INK` | CYAN | (drop) the B_CYAN ink |
72/// | `SIZZLE_BANNER_FILL` | 0 | the mask's fill (unused under a ramp; kept per game for identical code) |
73/// | `SIZZLE_HOLD_BANNER` | 1 | holdBanner() |
74/// | `SIZZLE_BANNER_WRAP` | 1 | the dance phase wraps to 128 (kept per game for identical code) |
75/// | `SIZZLE_SHAKE` | 1 | the screen shake joins activeRows(), update() and clear() |
76/// | `SIZZLE_BANNER_AFTER(x, y, dy, gap)` | - | (drop) a pass after the banner is drawn (CHDominoes' half ink) |
77/// @{
78
79#ifndef SIZZLE_CONFIGURED
80#error "include the game's src/fx/Fx.h (its SIZZLE_* switches, then <chgame/Sizzle.h>), not this header alone"
81#endif
82
83// ---------------------------------------------------------------- defaults
84#ifndef SIZZLE_POOL
85#define SIZZLE_POOL 48
86#endif
87#ifndef SIZZLE_KIND_SPARK
88#define SIZZLE_KIND_SPARK 1
89#endif
90#ifndef SIZZLE_KIND_STAR
91#define SIZZLE_KIND_STAR 1
92#endif
93#ifndef SIZZLE_KIND_DUST
94#define SIZZLE_KIND_DUST 1
95#endif
96#ifndef SIZZLE_KIND_COIN
97#define SIZZLE_KIND_COIN 0
98#endif
99#ifndef SIZZLE_KIND_RAIN
100#define SIZZLE_KIND_RAIN 0
101#endif
102#ifndef SIZZLE_RAIN_KIND_NAME
103#define SIZZLE_RAIN_KIND_NAME RAIN_DROP
104#endif
105#ifndef SIZZLE_KIND_GOO
106#define SIZZLE_KIND_GOO 0
107#endif
108#ifndef SIZZLE_BURST
109#define SIZZLE_BURST 1
110#endif
111#ifndef SIZZLE_COLOUR_INLINE
112#define SIZZLE_COLOUR_INLINE 0
113#endif
114#ifndef SIZZLE_COIN_LATE
115#define SIZZLE_COIN_LATE 0
116#endif
117#ifndef SIZZLE_DUST
118#define SIZZLE_DUST 3
119#endif
120#ifndef SIZZLE_FOUNTAIN_GOLD_COINS
121#define SIZZLE_FOUNTAIN_GOLD_COINS SIZZLE_KIND_COIN
122#endif
123#ifndef SIZZLE_COIN_FLOOR
124#define SIZZLE_COIN_FLOOR 122
125#endif
126#ifndef SIZZLE_COIN_FLOOR_RUNTIME
127#define SIZZLE_COIN_FLOOR_RUNTIME 0
128#endif
129#ifndef SIZZLE_HUES
130#define SIZZLE_HUES {RED, GOLD, FELT_LT, CYAN, BLUE}
131#endif
132#ifndef SIZZLE_HUES_EXPORT
133#define SIZZLE_HUES_EXPORT 1
134#endif
135#ifndef SIZZLE_HUES_NAME
136#define SIZZLE_HUES_NAME RAIN
137#endif
138#ifndef SIZZLE_CONFETTI_COLOURS
139#define SIZZLE_CONFETTI_COLOURS {RED, GOLD, FELT_LT, CYAN, BLUE, WHITE}
140#endif
141#ifndef SIZZLE_NO_PARTICLES
142#define SIZZLE_NO_PARTICLES 0
143#endif
144#ifndef SIZZLE_FLOATS
145#define SIZZLE_FLOATS 1
146#endif
147#ifndef SIZZLE_FLOAT_CHARS
148#define SIZZLE_FLOAT_CHARS 8
149#endif
150#ifndef SIZZLE_FLOAT_CLAMP
151#define SIZZLE_FLOAT_CLAMP 0
152#endif
153#ifndef SIZZLE_FLOAT_BLINK_FIRST
154#define SIZZLE_FLOAT_BLINK_FIRST 0
155#endif
156#ifndef SIZZLE_BANNER_DROP
157#define SIZZLE_BANNER_DROP 0
158#endif
159#ifndef SIZZLE_BANNER_CHARS
160#define SIZZLE_BANNER_CHARS 14
161#endif
162#ifndef SIZZLE_BANNER_ROWS_UP
163#define SIZZLE_BANNER_ROWS_UP (SIZZLE_BANNER_DROP ? 30 : 18)
164#endif
165#ifndef SIZZLE_BANNER_ROWS_DOWN
166#define SIZZLE_BANNER_ROWS_DOWN (SIZZLE_BANNER_DROP ? 12 : 18)
167#endif
168#define SIZZLE_RAINBOW 1
169#define SIZZLE_GOLD 2
170#define SIZZLE_RED 4
171#define SIZZLE_CYAN 8
172#define SIZZLE_WHITE 16
173#define SIZZLE_BLACK 32
174#define SIZZLE_GREEN 64
175#ifndef SIZZLE_STYLES
176#define SIZZLE_STYLES (SIZZLE_RAINBOW | SIZZLE_GOLD | SIZZLE_RED | SIZZLE_CYAN | SIZZLE_WHITE)
177#endif
178#ifndef SIZZLE_STYLE_RAMPS
179#define SIZZLE_STYLE_RAMPS SIZZLE_STYLES
180#endif
181#ifndef SIZZLE_CYAN_INK
182#define SIZZLE_CYAN_INK CYAN
183#endif
184#ifndef SIZZLE_BANNER_FILL
185#define SIZZLE_BANNER_FILL 0
186#endif
187#ifndef SIZZLE_HOLD_BANNER
188#define SIZZLE_HOLD_BANNER 1
189#endif
190#ifndef SIZZLE_BANNER_WRAP
191#define SIZZLE_BANNER_WRAP 1
192#endif
193#ifndef SIZZLE_SHAKE
194#define SIZZLE_SHAKE 1
195#endif
196#ifndef SIZZLE_FONT_MASK
197#define SIZZLE_FONT_MASK(m, x, y, s, dy, gap) maskFont(m, x, y, s, dy, gap)
198#endif
199#ifndef SIZZLE_FONT_WIDTH
200#define SIZZLE_FONT_WIDTH(s, gap) fontWidth(s, gap)
201#endif
202#ifndef SIZZLE_FONT_H
203#define SIZZLE_FONT_H FONT_H
204#endif
205#ifndef SIZZLE_BANNER_AFTER
206#define SIZZLE_BANNER_AFTER(x, y, dy, gap)
207#endif
208// DUST puffs spread along the floor in burst(); the pixel kind does not.
209#define SIZZLE_DUST_SPREAD (SIZZLE_KIND_DUST && SIZZLE_DUST >= 2)
210#if !SIZZLE_KIND_DUST
211#undef SIZZLE_DUST
212#define SIZZLE_DUST 0
213#endif
214
215#define SIZZLE_CAT_(a, b) a##b
216#define SIZZLE_CAT(a, b) SIZZLE_CAT_(a, b)
217#define SIZZLE_WORD_RAIN 1
218#define SIZZLE_WORD_RAIN_DROP 2
219#define SIZZLE_WORD_HUES 3
220#if SIZZLE_KIND_RAIN && SIZZLE_HUES_EXPORT && \
221 SIZZLE_CAT(SIZZLE_WORD_, SIZZLE_RAIN_KIND_NAME) == SIZZLE_CAT(SIZZLE_WORD_, SIZZLE_HUES_NAME)
222#error "SIZZLE_RAIN_KIND_NAME and SIZZLE_HUES_NAME are the same word: name the kind RAIN_DROP, or export the hues as HUES"
223#endif
224
225namespace fx {
226
227// ---------------------------------------------------------------- particles
228#ifdef SIZZLE_KIND_ORDER
229enum Kind : uint8_t { SIZZLE_KIND_ORDER };
230#else
231/// @brief The particle kinds (the game's switches decide which exist).
232enum Kind : uint8_t {
233#if SIZZLE_KIND_SPARK
234 SPARK, ///< A pixel with a cross-shaped flash for its first 8 ticks, falling slowly.
235#endif
236 CONFETTI, ///< A 2 px scrap that flips flat and upright as it falls. Always present.
237#if SIZZLE_KIND_COIN
238 COIN,
239#endif
240#if SIZZLE_KIND_RAIN
241 SIZZLE_RAIN_KIND_NAME,
242#endif
243#if SIZZLE_KIND_STAR
244 STAR, ///< A small plus sign, falling slowly.
245#endif
246#if SIZZLE_KIND_DUST
247 DUST, ///< A puff that slows to a stop and shrinks to a speck (see SIZZLE_DUST).
248#endif
249#if SIZZLE_KIND_GOO
250 GOO,
251#endif
252};
253#endif
254
255/// @brief Launch one particle. When the pool is full it takes a random one's place.
256/// @param k Its kind.
257/// @param x,y Where it starts, in pixels.
258/// @param vx16 Horizontal speed in 1/16 px per tick (-127..127).
259/// @param vy16 Vertical speed in 1/16 px per tick (-127..127; negative is up).
260/// @param life How many ticks it lives.
261/// @param colour Its colour.
262void spawn(Kind k, int x, int y, int vx16, int vy16, uint8_t life, uint8_t colour);
263#if SIZZLE_BURST
264/// @brief A radial burst: n particles flying out from a point.
265/// @param k Their kind.
266/// @param x,y The centre.
267/// @param n How many.
268/// @param speed16 Top speed in 1/16 px per tick (each gets half to all of it).
269/// @param colour Their colour.
270void burst(Kind k, int x, int y, uint8_t n, int speed16, uint8_t colour); // radial
271#endif
272#if SIZZLE_KIND_COIN
273void fountain(Kind k, int x, int y, uint8_t n); // confetti or coins, up
274#else
275/// @brief A fountain of confetti thrown up from a point (a win).
276/// @param x,y Where it springs from.
277/// @param n How many pieces.
278void fountain(int x, int y, uint8_t n); // confetti up
279#endif
280#if SIZZLE_COIN_FLOOR_RUNTIME
281void setFloor(int y); // where coins bounce
282#endif
283/// @brief Whether any particle is still flying.
284/// @return true while one is alive.
285bool particles(); // any still flying
286/// @brief The same as particles().
287/// @return true while a particle is alive.
288inline bool particlesAlive() { return particles(); }
289#if SIZZLE_HUES_EXPORT
290extern const uint8_t SIZZLE_HUES_NAME[5]; // the casino rainbow
291#endif
292
293// ---------------------------------------------------------------- banner
294/// @brief Banner colour styles (the game's SIZZLE_STYLES decide which exist).
295enum BannerStyle : uint8_t {
296#if SIZZLE_STYLES & SIZZLE_RAINBOW
297 B_RAINBOW, ///< The casino rainbow.
298#endif
299#if SIZZLE_STYLES & SIZZLE_GOLD
300 B_GOLD, ///< Gold.
301#endif
302#if SIZZLE_STYLES & SIZZLE_RED
303 B_RED, ///< Red.
304#endif
305#if SIZZLE_STYLES & SIZZLE_CYAN
306 B_CYAN, ///< Cyan.
307#endif
308#if SIZZLE_STYLES & SIZZLE_WHITE
309 B_WHITE, ///< White.
310#endif
311#if SIZZLE_STYLES & SIZZLE_BLACK
312 B_BLACK,
313#endif
314#if SIZZLE_STYLES & SIZZLE_GREEN
315 B_GREEN,
316#endif
317};
318/// @brief Show a banner: big centred lettering with an outline that pops in,
319/// holds, and blinks out ("BLACKJACK!", "YOU WIN").
320/// @param text The text (copied; at most SIZZLE_BANNER_CHARS - 1 characters).
321/// @param s Its style.
322/// @param cy The row its centre sits on.
323/// @param frames How many ticks it stays up, blinking out at the end (default 70).
324/// @details One banner at a time: a new one replaces the last.
325void banner(const char *text, BannerStyle s, int cy, uint8_t frames = 70);
326#if SIZZLE_HOLD_BANNER
327/// @brief Keep the banner up (before it blinks out) until let go.
328/// @param on true to hold it; false to let it blink out.
329void holdBanner(bool on); // keep the banner up (before it blinks out) until false
330#endif
331/// @brief Whether a banner is showing.
332/// @return true until it has blinked out.
334
335// ---------------------------------------------------------------- floats
336#if SIZZLE_FLOATS
337/// @brief A floating text ("+$15") that rises from a point and fades out.
338/// @param text The text (copied; at most SIZZLE_FLOAT_CHARS - 1 characters).
339/// @param x,y Where it starts.
340/// @param colour Its colour.
341/// @details Several can be up at once; a new one takes the first free slot
342/// (or the first slot when all four are busy). Each lives 50 ticks.
343void floatText(const char *text, int x, int y, uint8_t colour);
344/// @brief Draw the floating texts: while drawing, on top of the scene.
346#endif
347
348/// @brief The band of rows everything transient covers (particles, floats,
349/// banner, shake): what a partial redraw must include.
350/// @param lo Gets the top row.
351/// @param hi Gets the bottom row.
352/// @return false if nothing is moving (lo and hi are then meaningless).
353bool activeRows(int &lo, int &hi);
354
355/// @brief Remove every particle, float and the banner at once (and stop a shake).
356void clear();
357/// @brief Move everything on by one tick: once per logic tick.
358void update(); // once per logic tick
359#if SIZZLE_DUST == 3
360/// @brief Draw the particles: while drawing, on top of the scene.
361/// @param dust The size of a DUST puff in pixels (default 2).
362void drawParticles(uint8_t dust = 2); // dust: the size of a DUST puff in pixels
363#else
364void drawParticles();
365#endif
366/// @brief Draw the banner, if one is showing: while drawing, last.
368
369} // namespace fx
370
371/// @}
The one include for a CHGame sketch.
Effects: motion maths, the screen shake, and (chgame/Sizzle.h) particles, banners and floating texts.
Definition Fx.h:25
bool activeRows(int &lo, int &hi)
The band of rows everything transient covers (particles, floats, banner, shake): what a partial redra...
void update()
Move everything on by one tick: once per logic tick.
BannerStyle
Banner colour styles (the game's SIZZLE_STYLES decide which exist).
Definition Sizzle.h:295
@ B_RED
Red.
Definition Sizzle.h:303
@ B_WHITE
White.
Definition Sizzle.h:309
@ B_RAINBOW
The casino rainbow.
Definition Sizzle.h:297
@ B_GOLD
Gold.
Definition Sizzle.h:300
@ B_CYAN
Cyan.
Definition Sizzle.h:306
Kind
The particle kinds (the game's switches decide which exist).
Definition Sizzle.h:232
@ CONFETTI
A 2 px scrap that flips flat and upright as it falls. Always present.
Definition Sizzle.h:236
@ STAR
A small plus sign, falling slowly.
Definition Sizzle.h:244
@ SPARK
A pixel with a cross-shaped flash for its first 8 ticks, falling slowly.
Definition Sizzle.h:234
@ DUST
A puff that slows to a stop and shrinks to a speck (see SIZZLE_DUST).
Definition Sizzle.h:247
void drawParticles(uint8_t dust=2)
Draw the particles: while drawing, on top of the scene.
void fountain(int x, int y, uint8_t n)
A fountain of confetti thrown up from a point (a win).
void spawn(Kind k, int x, int y, int vx16, int vy16, uint8_t life, uint8_t colour)
Launch one particle.
void clear()
Remove every particle, float and the banner at once (and stop a shake).
bool bannerActive()
Whether a banner is showing.
bool particlesAlive()
The same as particles().
Definition Sizzle.h:288
void burst(Kind k, int x, int y, uint8_t n, int speed16, uint8_t colour)
A radial burst: n particles flying out from a point.
void floatText(const char *text, int x, int y, uint8_t colour)
A floating text ("+$15") that rises from a point and fades out.
void banner(const char *text, BannerStyle s, int cy, uint8_t frames=70)
Show a banner: big centred lettering with an outline that pops in, holds, and blinks out ("BLACKJACK!...
bool particles()
Whether any particle is still flying.
void drawFloats()
Draw the floating texts: while drawing, on top of the scene.
void drawBanner()
Draw the banner, if one is showing: while drawing, last.
void holdBanner(bool on)
Keep the banner up (before it blinks out) until let go.