Improve animation decoding

This commit is contained in:
Jeremy Penner 2023-12-23 12:06:52 -05:00
parent f8035c7709
commit eb758b7f3a

View file

@ -201,14 +201,6 @@ const decodeCel = (data, changesColorRam) => {
return cel return cel
} }
const decodeFrame = (byte, stateCount) => {
const frameIndex = byte & 0x7f
if (frameIndex > stateCount) {
return null
}
return { state: frameIndex, cycle: (byte & 0x80) != 0 }
}
const decodeSide = (byte) => { const decodeSide = (byte) => {
const side = byte & 0x03 const side = byte & 0x03
if (side == 0x00) { if (side == 0x00) {
@ -242,7 +234,7 @@ const decodeProp = (data) => {
colorBitmask: data.getUint8(1), colorBitmask: data.getUint8(1),
containerXYOff: data.getUint8(3), // TODO: parse this when nonzero containerXYOff: data.getUint8(3), // TODO: parse this when nonzero
walkto: { left: decodeWalkto(data.getUint8(4)), right: decodeWalkto(data.getUint8(5)), yoff: data.getInt8(6) }, walkto: { left: decodeWalkto(data.getUint8(4)), right: decodeWalkto(data.getUint8(5)), yoff: data.getInt8(6) },
frames: [], animations: [],
celmasks: [], celmasks: [],
cels: [] cels: []
} }
@ -272,12 +264,16 @@ const decodeProp = (data) => {
// the props in the Habitat source tree. // the props in the Habitat source tree.
// It's possible for there to be no frames, which is represented by an offset of 0 (no_animation) // It's possible for there to be no frames, which is represented by an offset of 0 (no_animation)
if (graphicStateOff != 0) { if (graphicStateOff != 0) {
for (let frameOff = graphicStateOff; ; frameOff ++) { for (let frameOff = graphicStateOff; ; frameOff += 2) {
const frame = decodeFrame(data.getUint8(frameOff), stateCount) // each animation is two bytes: the starting state, and the ending state
if (!frame) { // the first byte can have its high bit set to indicate that the animation should cycle
const cycle = (data.getUint8(frameOff) & 0x80) != 0
const startState = data.getUint8(frameOff) & 0x7f
const endState = data.getUint8(frameOff + 1)
if (startState >= stateCount || endState >= stateCount) {
break break
} }
prop.frames.push(frame) prop.animations.push({ cycle: cycle, startState: startState, endState: endState })
} }
} }
for (let celOffsetOff = celOffsetsOff; allCelsMask != 0; celOffsetOff += 2) { for (let celOffsetOff = celOffsetsOff; allCelsMask != 0; celOffsetOff += 2) {