Alchemy
Loading...
Searching...
No Matches

prism.c

Go to the documentation of this file.
1/// @file
2/// Prism.
3/// Part of effect.c, the battle effect object, compiled only through it.
4
6
7#define PRISM_GROUND_Y 0x380000 ///< y 56, where the crystals shatter
8#define PRISM_SHARD_CELLS (32 * 64) ///< the shards, after the 32x64 crystal
9
10/// Crystals drop out of the sky onto the targets' side, 8 frames apart, and
11/// shatter on the ground into 16 spinning shards each, flashing the targets and
12/// shaking the screen; the battle shows the damage 80 frames before the end,
13/// and the canvas darkens away over the last 8.
14///
15/// Abilities: Prism, Hail Prism, Freeze Prism (kind 8).
16///
17/// effect->variant picks the volley from gPrism_Counts (crystals and frames: 1
18/// in 110, 4 in 134, 12 in 166); with variant 2 the camera also swings round
19/// for the first 104 frames. The crystals are particles[]: z is 1 once
20/// shattered, variant is the frame it starts to fall. The shards are 16 per
21/// crystal in PARTICLES: z is how fast it spins.
22///
23/// Positions are canvas pixels in 16.16. Loads the crystal palette into the
24/// first 64 background colours and sets REG_BLDALPHA, the camera's yaw
25/// (variant 2) and work->shakeFrames, and flashes the targets at each
26/// shatter.
28 BlitterPair draw;
29 void **cursor;
30 struct BattleEffectWork *work;
31 void *canvas;
32 s32 frame;
33 struct EffectStep *seed;
34 struct EffectStep *crystal;
35 struct EffectStep *shards;
36 struct EffectStep *shard;
37 s32 x;
38 s32 cell;
39 s32 i;
40 s32 j;
41
42 shards = PARTICLES;
44 work = *cursor++;
45 canvas = *cursor;
46 work->effect = effect;
48 REG_BLDALPHA = BLEND_ALPHA(16, 16);
51 // Trails keep half of each pixel a frame.
53
54 // Line the crystals up above the screen, each starting 8 frames after
55 // the last and drifting towards the middle as it falls: each starts 18
56 // frames' drift short of its random x.
57 for (j = 0; j != gPrism_Counts[work->effect->variant][PRISM_CRYSTAL_COUNT];
58 j++) {
59 seed = &work->particles[j];
60 // This first random number is drawn and discarded.
61 x = Random16() & 31;
62 seed->y = -0x400000;
63 if (work->effect->side == 1) {
64 x = ((Random16() & 31) + 80) << 16;
65 seed->velocityX = (Random16() & 63) << 12;
66 } else {
67 x = ((Random16() & 31) + 8) << 16;
68 seed->velocityX = -(Random16() & 63) << 12;
69 }
70 seed->x = x - seed->velocityX * 18;
71 seed->velocityY = 0;
72 seed->z = 0;
73 seed->variant = j * 8;
74 }
75
76 for (frame = 0; frame != gPrism_Counts[work->effect->variant][PRISM_FRAMES];
77 frame++) {
78 if (work->effect->variant == 2 && frame <= 103) {
79 // Swing the camera round, slowing from frame 96.
80 struct BattleCamera *camera = gCameraWork;
81 s32 speed;
82
83 if (frame <= 95)
84 speed = 192;
85 else
86 speed = 2496 - frame * 24;
87 if (work->effect->side == 0)
88 camera->yaw -= speed;
89 else
90 camera->yaw += speed;
91 }
92 if (frame == gPrism_Counts[work->effect->variant][PRISM_FRAMES] - 80)
94 if (frame == gPrism_Counts[work->effect->variant][PRISM_FRAMES] - 8) {
95 // Darken the canvas away over the last 8 frames.
97 }
98 if (frame <= gPrism_Counts[work->effect->variant][PRISM_FRAMES] - 8) {
99 for (i = 0;
101 i++) {
102 crystal = &work->particles[i];
103 if (crystal->z == 1) {
104 // A shattered crystal: its shards fly and spin, slowing down. A
105 // shard draws one of three pictures of its kind (j % 5), stepping
106 // every 96 of its spin (variant); shards 0 to 2 draw additively.
107 // XXX: kind 4 (shards 4, 9 and 14) asks for cells 12 to 14, past
108 // the twelve pictures of the gPrism_Shard tables, and reads
109 // whatever follows each table; the crystal sheet's picture would
110 // show whether a fifth kind was meant.
111 for (j = 0; j != 16; j++) {
112 cell = (j % 5) * 3 + (shards[i * 16 + j].variant / 96) % 3;
113 shard = &shards[i * 16 + j];
114 draw[j <= 2](
115 canvas,
116 work->sheet + gPrism_ShardOffsets[cell] + PRISM_SHARD_CELLS,
117 Q_16_16_TO_INT(shard->x) - gPrism_ShardWidths[cell] / 2,
118 Q_16_16_TO_INT(shard->y) - gPrism_ShardHeights[cell] / 2,
120 EffectStep_AdvanceWithGravity2D(shard, 64, 0x2000);
121 shard->variant += shard->z;
122 if (shard->z > 1 && (frame & 1))
123 shard->z--;
124 }
125 } else if (frame >= crystal->variant) {
126 // A falling crystal (32x64), odd ones additive.
127 draw[i & 1](canvas, work->sheet, Q_16_16_TO_INT(crystal->x) - 16,
128 Q_16_16_TO_INT(crystal->y), 32, 64);
129 EffectStep_AdvanceWithGravity2D(crystal, 64, 0x10000);
130 if (crystal->y > PRISM_GROUND_Y) {
131 // Shatter it on reaching the ground (y 56).
132 crystal->z = 1;
133 crystal->y = PRISM_GROUND_Y;
134 for (j = 0; j != 16; j++) {
135 shard = &shards[i * 16 + j];
136 shard->x =
137 ((gPrism_ShardStarts[j][PRISM_SHARD_START_X] - 40) << 16) +
138 crystal->x;
139 shard->y = gPrism_ShardStarts[j][PRISM_SHARD_START_Y] << 16;
140 shard->velocityX = ((Random16() & 127) - 64) << 11;
141 shard->velocityY = -(Random16() & 127) << 11;
142 // Odd crystals' shards fly twice as fast.
143 if (i & 1) {
144 shard->velocityX *= 2;
145 shard->velocityY *= 2;
146 }
147 shard->z = 32;
148 shard->variant = 0;
149 }
150 work->shakeFrames = 8;
155 }
156 }
157 }
158 }
159 Camera_ApplyShake(work->effect->variant * 2 + 4,
160 work->effect->variant * 4 + 8);
161 EFFECT_END_FRAME(work);
162 }
163
165}
166
167/// Rebuilds the background palette's first ramp as a grey ramp whose red,
168/// green and blue each sway with the frame, out of step by their phases
169/// (1/65536ths of a turn), so the effect shimmers through colours.
170///
171/// Called each frame by BattleFx_RunBind and BattleFx_RunTriangleStrike
172/// (bind.c), BattleFx_RunShiningStar (stars.c) and BattleFx_RunThor
173/// (thor.c). Level n's channel is (n + sway) / 2, the sway up to 32 levels
174/// either way, clamped to 0 to 31.
175///
176/// XXX: the 64 entries, black first, are copied to colours 1 to 64, so each
177/// level shows in the colour one above it and colour 64, the first of
178/// palette 4, is overwritten too. Whether the canvas's levels are meant to be
179/// one off would show in a capture of Thor or Bind against this palette.
180///
181/// frame : the effect's frame; the sway turns 1/64 of a circle a frame
182/// redPhase, greenPhase, bluePhase : each channel's offset in the sway
183void Graphics_UpdatePhasePalette(s32 frame, s32 redPhase, s32 greenPhase,
184 s32 bluePhase) {
185 u16 palette[64];
186 u16 *output;
187 s32 phase;
188 s32 redOffset;
189 s32 greenOffset;
190 s32 blueOffset;
191 s32 index;
192
193 phase = frame * 0x400;
194 redOffset = (Trig_Sin(phase + redPhase) * 16) >> 15;
195 greenOffset = (Trig_Sin(phase + greenPhase) * 16) >> 15;
196 blueOffset = (Trig_Sin(phase + bluePhase) * 16) >> 15;
197
198 palette[0] = 0;
199 index = 1;
200 output = &palette[1];
201 do {
202 s32 red;
203 s32 green;
204 s32 blue;
205
206 red = (index + redOffset) / 2;
207 green = (index + greenOffset) / 2;
208 blue = (index + blueOffset) / 2;
209
210 CLAMP(red, 0, 31);
211 CLAMP(green, 0, 31);
212 CLAMP(blue, 0, 31);
213
214 *output++ = RGB(red, green, blue);
215 index++;
216 } while (index != 64);
217
218 Iwram_CopyWords((void *)&BG_PLTT[1], palette, sizeof(palette));
219}
220
221#undef PRISM_GROUND_Y
222#undef PRISM_SHARD_CELLS
@ SPRITE_COLOR_WHITE
solid colour 15, white
Definition animspr.h:26
@ POSE_DAMAGE
taking damage
Definition battle.h:176
struct BattleCamera * gCameraWork
#define EFFECT_FOR_EACH_TARGET(i, effect)
Loops i over the effect's targets, effect->actors[0] to effect->actors[effect->count - 1]: the loops ...
void BattleFx_BeginCanvasLayer(s32 bgControl)
Opens the canvas layer: starts the background palette fade, makes BG2 the canvas, alpha-blended over ...
Definition canvas.c:314
void Resource_LoadAndDecompress(s32 id, void *dst, s32 skipPalette, s32 copyPalette)
Decompresses a resource whose first 128 bytes may be a palette.
void ObjectGroup_UpdateMembers(s32 actorId, s32 palette, s32 animation, s32 timerSlot, s32 timerFrames)
Updates every animation group of one battler's object.
Definition dispatch.c:254
What every part of the battle effect object shares: its includes, macros and frame-loop helpers.
#define EFFECT_SET_TRANSFER(work, mode, value)
Sets how the canvas transfer treats what is left in the canvas after each copy: mode with value (see ...
@ CANVAS_COPY_AND_DARKEN
copy, then darken the canvas by transferValue
@ CANVAS_COPY_AND_FADE
copy, keeping 50% or 75% (transferValue) of each pixel in the canvas for the next frame
#define EFFECT_FINISH_CANVAS()
The usual end of a canvas effect: stops the transfer callback before freeing what it reads,...
#define EFFECT_SHOW_DAMAGE(hitSound)
Lets the battle show the damage: resumes its paused playback, which plays hitSound (an SE_ id; 0 keep...
#define EFFECT_START_TRANSFER(work, mode, value)
Sets the transfer, then starts copying the canvas to VRAM once a frame.
#define EFFECT_END_FRAME(work)
The usual end of an effect frame: counts down the targets' flash timers (ObjectGroup_TickMemberTimers...
u8 gPrism_ShardStarts[][2]
Where each of the 16 shards starts in the crystal: x, then y.
u8 gPrism_ShardHeights[]
s32 gPrism_ShardOffsets[]
u8 gPrism_Counts[][2]
Prism, by variant: crystals and frames.
u8 gPrism_ShardWidths[]
@ PRISM_CRYSTAL_COUNT
crystals drawn
@ PRISM_FRAMES
the effect's frames
@ PRISM_SHARD_START_X
pixels from the crystal's left
@ PRISM_SHARD_START_Y
pixels from its top
void AudioCommand_PlayFar(s32 id)
s32 Trig_Sin(s32 angle)
void Camera_ApplyShake(s32 rangeX, u32 rangeY)
Shakes the battle view while gBattleFxWork's shakeFrames lasts, moving BG1 and the projection centre ...
Definition hail.c:364
@ HEAP_SLOT_BATTLE_EFFECT
Definition heap_state.h:42
#define RGB(r, g, b)
A 15-bit colour from its red, green and blue levels (0 to 31 each), as the palette stores it: blue in...
Definition io_reg.h:164
#define BLEND_ALPHA(top, bottom)
A REG_BLDALPHA value: top and bottom are the two targets' weights, out of 16.
Definition io_reg.h:145
#define REG_BLDALPHA
Definition io_reg.h:142
#define BG_PLTT
Definition io_reg.h:157
static s32 Iwram_CopyWords(volatile void *destination, const volatile void *source, s32 size)
Definition iwram_call.h:85
#define CLAMP(v, low, high)
Keeps v within low to high, the low bound tested first.
Definition macros.h:23
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
Definition math.c:10
void BattleFx_FetchRectangleBlitters(s32 flip, BlitterPair out)
Builds the two usual routines that draw onto the 128x128 canvas, both clipped on both axes.
void EffectStep_AdvanceWithGravity2D(struct EffectStep *step, s32 damping, s32 gravity)
Moves a particle one frame on the screen: adds its velocity, then gravity to its vertical speed,...
Definition positions.c:46
void Graphics_UpdatePhasePalette(s32 frame, s32 redPhase, s32 greenPhase, s32 bluePhase)
Rebuilds the background palette's first ramp as a grey ramp whose red, green and blue each sway with ...
Definition prism.c:183
#define PRISM_GROUND_Y
y 56, where the crystals shatter
Definition prism.c:7
void BattleFx_RunPrism(struct BattleEffectArgument *effect)
Crystals drop out of the sky onto the targets' side, 8 frames apart, and shatter on the ground into 1...
Definition prism.c:27
#define PRISM_SHARD_CELLS
the shards, after the 32x64 crystal
Definition prism.c:8
char ResourceId_CrystalSheet
#define SE_144
Definition songs.h:137
#define SE_HEAVY_IMPACT
Definition songs.h:127
void * gWorkSlot[]
The battle camera: its eye, the focus it turns about, and its pitch, yaw and distance.
u16 yaw
1/65536 turns
The command shared by an effect's caller, dispatcher and handlers.
s32 side
1 when the targets are the party, 0 for enemies
s16 actors[8]
the targets' unit ids, count of them
s32 variant
the ability's size, from 0 (Quake, then Earthquake)
The running battle effect's work: its canvas image, 64 particles, the display registers it stages and...
s32 frame
frame counter some effects keep, from 0
s32 shakeFrames
shake frames left; Camera_ApplyShake counts down
struct BattleEffectArgument * effect
the command being run
struct EffectStep particles[64]
free while variant is -1
A moving point of an effect: its position, its velocity and a value each effect uses its own way (a s...
Definition effect_step.h:13
s32 velocityX
16.16 fixed-point pixels per frame
Definition effect_step.h:28
s32 z
16.16 fixed-point pixels
Definition effect_step.h:26
s32 variant
each effect's own: a size, a countdown, -1 for idle
Definition effect_step.h:31
s32 x
16.16 fixed-point pixels
Definition effect_step.h:24
s32 y
16.16 fixed-point pixels
Definition effect_step.h:25
s32 velocityY
16.16 fixed-point pixels per frame
Definition effect_step.h:29
signed int s32
Definition types.h:14
unsigned short u16
Definition types.h:13
#define Q_16_16_TO_INT(v)
Definition effect.h:231
#define PARTICLES
The map cell buffer (gMapCellBuffer), which the effects borrow, has two views here: Ram_MapCellBuffer...
Definition effect.h:221
DrawRectangle BlitterPair[2]
A blitter pair: [0] built in HEAP_SLOT_BLITTER and [1] in HEAP_SLOT_BLITTER_ALTERNATE (BattleFx_Fetch...
Definition effect.h:244