Alchemy
Loading...
Searching...
No Matches

effect_slot.c

Go to the documentation of this file.
1/// @file
2/// Effect slots: the particles Psynergy effects move and draw.
3/// Part of psynergy_effects.c, compiled only through it.
4
6
7/// Updates one effect slot: counts its age, runs its callback (after any
8/// delay), moves it and draws it.
9void EffectSlot_Update(struct EffectSlot *effect) {
10 if (effect->active != 0) {
11 effect->age++;
12 if (effect->callbackDelay != 0)
13 effect->callbackDelay--;
14 else if (effect->callback != 0)
15 effect->callback(effect);
16 // A callback may release its own slot; do not move or draw it afterward.
17 if (effect->active != 0) {
18 if (effect->updateMotion != 0)
20 if (effect->render != 0)
22 }
23 }
24}
25
26/// Draws an effect slot's sprite at its screen position and scale, when it is
27/// near the screen. With flag 4 the slot's z also lifts it (0x1fc pixels
28/// less z).
30 struct AnimationObject *sprite;
31 s32 offset;
32 struct SpriteScale scale;
33 struct SpritePlacement position;
34
35 sprite = object->object;
36 offset = 0;
37 if (object->flags & 4)
38 offset = 0x1fc0000 - object->z;
39 scale.x = Iwram_MulQ16(object->scaleX, sprite->scale);
40 scale.y = Iwram_MulQ16(object->scaleY, sprite->scale);
41 position.x = object->x;
42 position.height = offset;
43 position.y = object->z + offset;
44 position.groundHeight = 0;
45 if (object->x > -0x200000 && object->x < 0x1100000 && object->z > -0x200000 &&
46 object->z < 0xe00000)
47 Object_ApplyProjectedPlacementFar(sprite, &position, &scale, 0);
48}
49
50/// Moves an effect slot toward its target, turning at most maxTurnStep a
51/// frame when limitTurnStep is set and speeding up by acceleration to maxSpeed.
52/// A slot that stops at its target lands on it once within 8 pixels.
53void EffectSlot_UpdateMotion(struct EffectSlot *effect) {
54 s32 deltaX;
55 s32 deltaZ;
56 s32 distance;
57 s32 pixelX;
58 s32 pixelZ;
59 s32 speed;
60 s16 angle;
61 s32 heading;
62 s32 facing;
63 s16 turn;
64
65 if (effect->targetX == EFFECT_NO_TARGET)
66 return;
67 deltaX = effect->targetX - effect->x;
68 deltaZ = effect->targetZ - effect->z;
69 if (effect->stopAtTarget != 0) {
70 pixelX = deltaX / 0x10000;
71 pixelZ = deltaZ / 0x10000;
72 distance = Iwram_Sqrt(pixelX * pixelX + pixelZ * pixelZ) << 16;
73 if (distance < 0x800000)
74 distance = FixedSqrt(Iwram_MulQ16(deltaX, deltaX) +
75 Iwram_MulQ16(deltaZ, deltaZ));
76 if (distance <= 0x80000) {
77 EffectSlot_SetPosition(effect, effect->targetX, effect->targetZ);
78 return;
79 }
80 }
81 angle = ArcTan2(deltaZ, deltaX);
82 if (effect->limitTurnStep != 0) {
83 heading = effect->heading;
84 turn = angle - heading;
85 if ((turn >= 0 ? turn : -turn) >= effect->maxTurnStep) {
86 if (turn < 0) {
87 if (-turn > effect->maxTurnStep)
88 turn = -effect->maxTurnStep;
89 } else if (turn > effect->maxTurnStep) {
90 turn = effect->maxTurnStep;
91 }
92 angle = turn + heading;
93 }
94 }
95 facing = (u16)angle;
96 effect->heading = facing;
97 speed = effect->speed + effect->acceleration;
98 if (speed > effect->maxSpeed)
99 speed = effect->maxSpeed;
100 angle = facing;
101 effect->speed = speed;
102 effect->x += Iwram_MulQ16(Trig_Cos(angle), speed);
103 effect->z += Iwram_MulQ16(Trig_Sin(angle), speed);
104}
105
106/// Returns nonzero while an effect slot that stops at its target still has one
107/// (it has not arrived), 0 once it has arrived or when it never stops.
109 // A plain != changes the English instructions at the same extent.
110 u32 targetX;
111
112 if (effect->stopAtTarget == 0) {
113 return 0;
114 }
115 targetX = effect->targetX ^ (u32)EFFECT_NO_TARGET;
116 return ((0u - targetX) | targetX) >> 31;
117}
118
119/// Places an effect slot at (x, z), at rest with no target.
120void EffectSlot_SetPosition(struct EffectSlot *effect, s32 x, s32 z) {
121 effect->targetX = EFFECT_NO_TARGET;
122 effect->targetZ = EFFECT_NO_TARGET;
123 effect->x = x;
124 effect->z = z;
125 effect->speed = 0;
126}
127
128/// Sets the animation of an effect slot's sprite.
129void EffectSlot_SetObjectMode(struct EffectSlot *effect, s32 mode) {
131}
132
133/// Gives an effect slot its per-frame callback, starting at state 0.
135 EffectCallback callback) {
136 effect->callback = callback;
137 effect->callbackDelay = 0;
138 effect->age = 0;
139 effect->state = 0;
140}
141
142/// Fills an effect slot with a new sprite of kind at (x, z): stopping at its
143/// target, top speed 2, acceleration and scale 1, drawn, animation 1.
144void EffectSlot_Initialize(struct EffectSlot *effect, s32 kind, s32 x, s32 z) {
145 s32 unit;
146 struct AnimationObject *object;
147
148 Dma_Fill32(0, effect, sizeof *effect);
149 object = ResourceObject_CreateFar(kind);
150 effect->object = object;
151 if (object != NULL)
152 object->image.priority = 0;
153 EffectSlot_SetPosition(effect, x, z);
154 /* FAKEMATCH(temporary): 1.0 in a local set before maxSpeed takes r2 beside
155 2.0, which lets sched2 load the object ahead of the three stores; as the
156 constant in the chain, 12 of 74 instructions differ in tbs-en. */
157 unit = 0x10000;
158 effect->maxSpeed = 0x20000;
159 effect->acceleration = effect->scaleY = effect->scaleX = unit;
160 effect->originX = x;
161 effect->originZ = z;
162 // BUG: ResourceObject_CreateFar can return NULL, but this and the animation
163 // setup below still require a sprite. Callers also immediately use it, so
164 // guarding this store alone would not establish allocation-failure recovery.
165 {
166 struct AnimationObject *sprite = effect->object;
167 sprite->flags = 0;
168 }
169 effect->stopAtTarget = 1;
170 effect->limitTurnStep = 1;
171 effect->updateMotion = 1;
172 effect->render = 1;
173 effect->active = 1;
174 effect->randomValue = Random16();
175 effect->flags = 4;
176 EffectSlot_SetObjectMode(effect, 1);
177}
178
179/// Frees an effect slot and its sprite.
181 if (slot->object)
183 Dma_Fill32(0, slot, sizeof *slot);
184}
#define Dma_Fill32(value, destination, size)
Fills size bytes at destination with the word value by DMA3.
Definition dma.h:30
u32 EffectSlot_HasPendingTarget(struct EffectSlot *effect)
Returns nonzero while an effect slot that stops at its target still has one (it has not arrived),...
void BattleFx_ClearOwnedSlot(struct EffectSlot *slot)
Frees an effect slot and its sprite.
void EffectSlot_UpdateMotion(struct EffectSlot *effect)
Moves an effect slot toward its target, turning at most maxTurnStep a frame when limitTurnStep is set...
Definition effect_slot.c:53
void EffectSlot_SetPosition(struct EffectSlot *effect, s32 x, s32 z)
Places an effect slot at (x, z), at rest with no target.
void EffectSlot_Update(struct EffectSlot *effect)
Updates one effect slot: counts its age, runs its callback (after any delay), moves it and draws it.
Definition effect_slot.c:9
void EffectSlot_Initialize(struct EffectSlot *effect, s32 kind, s32 x, s32 z)
Fills an effect slot with a new sprite of kind at (x, z): stopping at its target, top speed 2,...
void BattleFx_DrawScaledObject(struct EffectSlot *object)
Draws an effect slot's sprite at its screen position and scale, when it is near the screen.
Definition effect_slot.c:29
void EffectSlot_SetCallback(struct EffectSlot *effect, EffectCallback callback)
Gives an effect slot its per-frame callback, starting at state 0.
void EffectSlot_SetObjectMode(struct EffectSlot *effect, s32 mode)
Sets the animation of an effect slot's sprite.
#define EFFECT_NO_TARGET
Definition effect_slot.h:11
void(*) EffectCallback(struct EffectSlot *)
Definition effect_slot.h:14
s32 AnimationObjects_SelectAnimationFar(struct AnimationObject *state, s32 flags)
struct AnimationObject * ResourceObject_CreateFar(s32 id)
void Object_ApplyProjectedPlacementFar(struct AnimationObject *sprite, const struct SpritePlacement *position, const struct SpriteScale *scale, s32 facing)
Far call to Render_ApplyProjectedPlacement.
void ResourceObject_ReleaseFar(struct AnimationObject *sprite)
s32 Trig_Cos(s32 angle)
s32 Trig_Sin(s32 angle)
static s32 Iwram_Sqrt(s32 value)
Definition iwram_call.h:63
#define Iwram_MulQ16(left, right)
Definition iwram_call.h:127
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
Definition math.c:10
s32 ArcTan2(s32 x, s32 y)
Returns the angle of the vector (x, y), in 1/65536 turns, measured from the y axis: 0 along +y,...
Definition math.c:36
s32 FixedSqrt(s32 value)
Square root of a 16.16 fixed-point value, in 16.16.
Definition math.c:149
What every part of psynergy_effects.c shares: its includes and the macros and types more than one par...
#define NULL
Definition bilibin.h:6
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
Definition animspr.h:108
struct AnimationSpritePart image
Definition animspr.h:109
u8 flags
bits: 1 outlined in ObjectSystemWork's edge and fill colours | 0 shadow drawn (set when created)
Definition animspr.h:128
u8 slot
VRAM cache entry holding its tiles.
Definition animspr.h:112
s32 scale
16.16 fixed point, 0x10000 full size
Definition animspr.h:111
u16 priority
2 when created
Definition animspr.h:100
A particle a Psynergy effect moves and draws: its sprite, its position and target,...
Definition effect_slot.h:18
s16 callbackDelay
frames
Definition effect_slot.h:35
s32 speed
16.16 fixed-point pixels per frame
Definition effect_slot.h:26
s32 scaleY
16.16 fixed point, 0x10000 full size
Definition effect_slot.h:30
EffectCallback callback
run each frame once callbackDelay is 0
Definition effect_slot.h:33
s8 state
the callback's own step; 0 when it is given
Definition effect_slot.h:38
u16 heading
1/65536 turns
Definition effect_slot.h:31
void * object
the slot's sprite, released with the slot
Definition effect_slot.h:19
s32 originX
16.16 fixed-point pixels; where the slot started
Definition effect_slot.h:24
s32 z
16.16 fixed-point pixels
Definition effect_slot.h:21
s32 x
16.16 fixed-point pixels
Definition effect_slot.h:20
s16 maxTurnStep
1/65536 turns a frame
Definition effect_slot.h:32
s8 limitTurnStep
Clamp steering to maxTurnStep; zero faces the target directly.
Definition effect_slot.h:40
s32 originZ
16.16 fixed-point pixels; where the slot started
Definition effect_slot.h:25
s32 targetZ
16.16 fixed-point pixels; EFFECT_NO_TARGET at rest
Definition effect_slot.h:23
s32 scaleX
16.16 fixed point, 0x10000 full size
Definition effect_slot.h:29
s32 targetX
16.16 fixed-point pixels; EFFECT_NO_TARGET at rest
Definition effect_slot.h:22
s8 active
nonzero while the slot is in use
Definition effect_slot.h:44
s8 updateMotion
nonzero: EffectSlot_UpdateMotion moves it each frame
Definition effect_slot.h:42
u8 flags
bits: 2 z also lifts the sprite (set when the slot is filled)
Definition effect_slot.h:47
s32 maxSpeed
16.16 fixed-point pixels per frame
Definition effect_slot.h:27
u16 age
frames
Definition effect_slot.h:34
u8 randomValue
random when filled; not read by name in TBS
Definition effect_slot.h:45
s8 stopAtTarget
nonzero: lands on the target within 8 pixels
Definition effect_slot.h:39
s32 acceleration
16.16 fixed-point pixels per frame, each frame
Definition effect_slot.h:28
s8 render
nonzero: drawn each frame
Definition effect_slot.h:43
A sprite's screen position and its two vertical offsets, in 16.16 pixels.
s32 x
screen x of the sprite's centre
s32 y
screen y at the ground; sets the depth slot
s32 groundHeight
how far the shadow is raised above y
s32 height
how far the image is raised above y
Horizontal and vertical sprite scale; 0x10000 is the original size.
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13