private void ConsumeActorStateFrames(UpperString sprite) { UpperString frames = ConsumeString(); int ticks = ConsumeActorFrameTicks(); ActorFrameProperties properties = ConsumeActorFrameKeywordsIfAny(); Optional <ActorActionFunction> actionFunction = ConsumeActionFunctionIfAny(); foreach (char frame in frames) { if (!IsValidFrameLetter(frame)) { throw MakeException($"Invalid actor frame letter: {frame} (ascii ordinal {(int)frame})"); } ActorFrame actorFrame = new ActorFrame(frameIndex, sprite + frame, ticks, properties, actionFunction); currentDefinition.States.Frames.Add(actorFrame); frameIndex++; } }
private ActorFrameProperties ConsumeActorFrameKeywordsIfAny() { ActorFrameProperties properties = new ActorFrameProperties(); // These can probably come in any order, so we'll need a looping // dictionary. Apparently we have to watch out for new lines when // dealing with `fast` and `slow`. while (true) { if (!PeekCurrentText(out string value)) { throw MakeException($"Ran out of tokens when reading actor frame properties on actor '{currentDefinition.Name}'"); } UpperString upperKeyword = value; if (!FramePropertyKeywords.Contains(upperKeyword)) { break; } // Note: In the future we will need to possibly *not* consume // if its 'fast' or 'slow' and on another line since that may // be a valid sprite frame. This is why we moved the string // consumer into each block because some of them might not do // consumption (whenever we get around to implementing that). switch (upperKeyword.String) { case "BRIGHT": ConsumeString(); properties.Bright = true; break; case "CANRAISE": ConsumeString(); properties.CanRaise = true; break; case "FAST": // TODO: Make sure it's on the same line (ex: if it's a sprite). ConsumeString(); properties.Fast = true; break; case "LIGHT": ConsumeString(); Consume('('); properties.Light = ConsumeString().AsUpper(); Consume(')'); break; case "NODELAY": ConsumeString(); properties.NoDelay = true; break; case "OFFSET": ConsumeString(); Consume('('); int x = ConsumeSignedInteger(); Consume(','); int y = ConsumeSignedInteger(); Consume(')'); properties.Offset = new Vec2I(x, y); break; case "SLOW": ConsumeString(); // TODO: Make sure it's on the same line (ex: if it's a sprite). properties.Slow = true; break; } } return(properties); }