Skip to content

Commit c330d6b

Browse files
committed
src/critter: fix flickering rotation on 3way movement glitch
1 parent c3f9be9 commit c330d6b

File tree

1 file changed

+36
-47
lines changed

1 file changed

+36
-47
lines changed

src/critter.cpp

+36-47
Original file line numberDiff line numberDiff line change
@@ -118,24 +118,29 @@ constexpr auto rotation_to_similar_array = map(rotation_to_similar_, iota_array<
118118

119119
constexpr std::array<rotation, 3> rotation_to_similar(rotation r)
120120
{
121-
CORRADE_ASSUME(r < rotation_COUNT);
122121
return rotation_to_similar_array.data()[(uint8_t)r];
123122
}
124123

125-
template<rotation r> constexpr uint8_t get_length_axis()
124+
constexpr uint8_t get_length_axisʹ(rotation r)
126125
{
127-
static_assert((int)r % 2 == 0);
128126
using enum rotation;
129-
if constexpr(r == N || r == S)
127+
if (r == N || r == S)
130128
return 1;
131-
else if constexpr(r == W || r == E)
129+
else if (r == W || r == E)
132130
return 0;
133-
fm_assert(false);
131+
else
132+
return 0; // garbage in, garbage out
133+
}
134+
135+
constexpr uint8_t get_length_axis(rotation r)
136+
{
137+
constexpr auto table = map(get_length_axisʹ, iota_array<rotation, (size_t)rotation_COUNT>);
138+
return table.data()[(size_t)r];
134139
}
135140

136141
template<bool MultiStep>
137142
CORRADE_NEVER_INLINE
138-
bool update_movement_body(size_t& i, critter& C, const anim_def& info, uint8_t nsteps, rotation new_r)
143+
bool update_movement_body(size_t& i, critter& C, const anim_def& info, uint8_t nsteps, rotation new_r, rotation visible_r)
139144
{
140145
const auto vec = rotation_to_vec(new_r);
141146
using Frac = decltype(critter::offset_frac);
@@ -156,7 +161,7 @@ bool update_movement_body(size_t& i, critter& C, const anim_def& info, uint8_t n
156161
C.offset_frac = Frac(rem * frac);
157162
if (C.can_move_to(off_i))
158163
{
159-
C.move_to(i, off_i, new_r);
164+
C.move_to(i, off_i, visible_r);
160165
if constexpr(MultiStep)
161166
(C.frame += nsteps) %= info.nframes;
162167
else
@@ -173,64 +178,60 @@ bool update_movement_body(size_t& i, critter& C, const anim_def& info, uint8_t n
173178
return false;
174179
}
175180

176-
template<rotation r>
177-
CORRADE_ALWAYS_INLINE
178-
bool update_movement_3way(size_t& i, critter& C, const anim_def& info)
181+
bool update_movement_3way(size_t& i, critter& C, const anim_def& info, rotation new_r)
179182
{
180-
constexpr auto rotations = rotation_to_similar(r);
181-
if (update_movement_body<false>(i, C, info, 0, rotations[0]))
183+
const auto rotations = rotation_to_similar(new_r);
184+
if (update_movement_body<false>(i, C, info, 0, rotations.data()[0], new_r))
182185
return true;
183-
if (update_movement_body<false>(i, C, info, 0, rotations[1]))
186+
if (update_movement_body<false>(i, C, info, 0, rotations.data()[1], new_r))
184187
return true;
185-
if (update_movement_body<false>(i, C, info, 0, rotations[2]))
188+
if (update_movement_body<false>(i, C, info, 0, rotations.data()[2], new_r))
186189
return true;
187190
return false;
188191
}
189192

190193
constexpr bool DoUnroll = true;
191194

192-
template<rotation new_r>
193-
requires ((int)new_r % 2 != 0)
194-
CORRADE_ALWAYS_INLINE
195-
bool update_movement_1(critter& C, size_t& i, const anim_def& info, uint32_t nframes)
195+
template<bool IsEven>
196+
requires (!IsEven)
197+
bool update_movement_1(critter& C, size_t& i, const anim_def& info, uint32_t nframes, rotation new_r)
196198
{
199+
//Debug{} << "< nframes" << nframes;
197200
if constexpr(DoUnroll)
198201
{
199-
//Debug{} << "< nframes" << nframes;
200202
while (nframes > 1)
201203
{
202204
auto len = (uint8_t)Math::min(nframes, (uint32_t)C.bbox_size.min());
203205
if (len <= 1)
204206
break;
205-
if (!update_movement_body<true>(i, C, info, len, new_r))
207+
if (!update_movement_body<true>(i, C, info, len, new_r, new_r))
206208
break;
207209
//Debug{} << " " << len;
208210
nframes -= len;
209211
}
210-
//Debug{} << ">" << nframes;
211212
}
213+
//Debug{} << ">" << nframes;
212214

213215
for (auto k = 0u; k < nframes; k++)
214-
if (!update_movement_3way<new_r>(i, C, info))
216+
if (!update_movement_3way(i, C, info, new_r))
215217
return false;
216218
return true;
217219
}
218220

219-
template<rotation new_r>
220-
requires ((int)new_r % 2 == 0)
221-
CORRADE_ALWAYS_INLINE
222-
bool update_movement_1(critter& C, size_t& i, const anim_def& info, uint32_t nframes)
221+
template<bool IsEven>
222+
requires IsEven
223+
bool update_movement_1(critter& C, size_t& i, const anim_def& info, uint32_t nframes, rotation new_r)
223224
{
224225
if constexpr(DoUnroll)
225226
{
226227
//Debug{} << "< nframes" << nframes;
227228
while (nframes > 1)
228229
{
229-
constexpr auto len_axis = get_length_axis<new_r>();
230+
const auto len_axis = get_length_axis(new_r);
230231
auto len = (uint8_t)Math::min(nframes, (uint32_t)C.bbox_size.data()[len_axis]);
231232
if (len <= 1) [[unlikely]]
232233
break;
233-
if (!update_movement_body<true>(i, C, info, len, new_r))
234+
if (!update_movement_body<true>(i, C, info, len, new_r, new_r))
234235
break;
235236
//Debug{} << " " << len;
236237
nframes -= len;
@@ -239,20 +240,11 @@ bool update_movement_1(critter& C, size_t& i, const anim_def& info, uint32_t nfr
239240
}
240241

241242
for (auto k = 0u; k < nframes; k++)
242-
if (!update_movement_body<false>(i, C, info, 0, new_r))
243+
if (!update_movement_body<false>(i, C, info, 0, new_r, new_r))
243244
return false;
244245
return true;
245246
}
246247

247-
template bool update_movement_1<(rotation)0>(critter& C, size_t& i, const anim_def& info, uint32_t nframes);
248-
template bool update_movement_1<(rotation)1>(critter& C, size_t& i, const anim_def& info, uint32_t nframes);
249-
template bool update_movement_1<(rotation)2>(critter& C, size_t& i, const anim_def& info, uint32_t nframes);
250-
template bool update_movement_1<(rotation)3>(critter& C, size_t& i, const anim_def& info, uint32_t nframes);
251-
template bool update_movement_1<(rotation)4>(critter& C, size_t& i, const anim_def& info, uint32_t nframes);
252-
template bool update_movement_1<(rotation)5>(critter& C, size_t& i, const anim_def& info, uint32_t nframes);
253-
template bool update_movement_1<(rotation)6>(critter& C, size_t& i, const anim_def& info, uint32_t nframes);
254-
template bool update_movement_1<(rotation)7>(critter& C, size_t& i, const anim_def& info, uint32_t nframes);
255-
256248
struct step_s
257249
{
258250
uint32_t count;
@@ -441,15 +433,12 @@ void critter::update_movement(size_t& i, const Ns& dt, rotation new_r)
441433

442434
switch (new_r)
443435
{
436+
using enum rotation;
444437
default: std::unreachable();
445-
case (rotation)0: ret = update_movement_1<(rotation)0>(*this, i, info, nframes); break;
446-
case (rotation)1: ret = update_movement_1<(rotation)1>(*this, i, info, nframes); break;
447-
case (rotation)2: ret = update_movement_1<(rotation)2>(*this, i, info, nframes); break;
448-
case (rotation)3: ret = update_movement_1<(rotation)3>(*this, i, info, nframes); break;
449-
case (rotation)4: ret = update_movement_1<(rotation)4>(*this, i, info, nframes); break;
450-
case (rotation)5: ret = update_movement_1<(rotation)5>(*this, i, info, nframes); break;
451-
case (rotation)6: ret = update_movement_1<(rotation)6>(*this, i, info, nframes); break;
452-
case (rotation)7: ret = update_movement_1<(rotation)7>(*this, i, info, nframes); break;
438+
case N: case E: case S: case W:
439+
ret = update_movement_1<true >(*this, i, info, nframes, new_r); break;
440+
case NW: case NE: case SE: case SW:
441+
ret = update_movement_1<false>(*this, i, info, nframes, new_r); break;
453442
}
454443

455444
if (!ret) [[unlikely]]

0 commit comments

Comments
 (0)