ScummVM API documentation
character.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef CHARACTER_H
23 #define CHARACTER_H
24 
25 #include "common/hashmap.h"
26 #include "common/ptr.h"
27 #include "common/rect.h"
28 #include "common/scummsys.h"
29 
30 namespace Common {
31 class SeekableReadStream;
32 class ReadStream;
33 class WriteStream;
34 } // namespace Common
35 namespace Graphics {
36 struct Surface;
37 class ManagedSurface;
38 } // namespace Graphics
39 
40 namespace AGDS {
41 
42 class AGDSEngine;
43 class Object;
44 using ObjectPtr = Common::SharedPtr<Object>;
45 class Animation;
46 using AnimationPtr = Common::SharedPtr<Animation>;
47 
48 class Character {
50  AGDSEngine *_engine;
51  ObjectPtr _object;
52  AnimationPtr _animation;
53  FogPtr _fog;
54  bool _jokes;
55  Common::String _name;
56  Common::String _processName;
57  Common::Point _pos;
58  Common::Point _animationPos;
59  bool _enabled;
60  bool _visible;
61  bool _stopped;
62  bool _shown;
63  int _phase;
64  int _frames;
65  int _direction;
66  int _jokesDirection;
67  int _movementDirections;
68  int _fogMinZ, _fogMaxZ;
69 
70  struct AnimationDescription {
71  struct Frame {
72  int x, y; // cumulative walk displacement from animation start
73  uint w, h; // cropped bitmap size of this frame
74  uint canvasW, canvasH; // logical canvas size (anchor and scale reference)
75  int offX, offY; // anchor tweak of the crop inside the logical canvas
76  int cropX, cropY; // position of the crop inside the full FLIC frame
77  };
78 
79  Common::String filename;
80  Common::Array<Frame> frames;
81  };
83  const AnimationDescription *_description;
84  bool _standing;
85 
86  // Phased characters (Black Mirror main cast) store 5 animations per
87  // facing direction: start(0), cycle A(1), cycle B(2), stop from A(3),
88  // stop from B(4). Their animation index is dir * 5 + phase.
89  static const int kAnimsPerDirection = 5;
90 
91  bool phased() const {
92  return _movementDirections != 0 &&
93  _animations.size() >= (uint)(_movementDirections * kAnimsPerDirection);
94  }
95 
96  int animIndexFor(int dir, int phase) const {
97  return phased() ? dir * kAnimsPerDirection + phase : dir;
98  }
99 
100  const AnimationDescription::Frame *frameAt(int dir, int phase, int frame) const {
101  const AnimationDescription *desc = animationDescription(animIndexFor(dir, phase));
102  if (!desc || desc->frames.empty())
103  return nullptr;
104  if (frame < 0)
105  frame = 0;
106  if (frame >= (int)desc->frames.size())
107  frame = desc->frames.size() - 1;
108  return &desc->frames[frame];
109  }
110 
111  bool animate(int animIndex, int speed, bool jokes);
112  float perspectiveScale() const;
113  Common::Point animationPosition() const;
114 
115  // --- Walk state machine (mirrors the original engine) ---
116  enum WalkState {
117  kWalkIdle = 0,
118  kWalkWalking = 1, // normal walk along the path
119  kWalkLeaving = 2, // walking off-screen
120  kWalkTurning = 3, // turning in place only
121  kWalkRemovePending = 5, // finish current cycle, then re-issue moveTo
122  kWalkLeavePending = 6, // finish current cycle, then leave
123  kWalkStopPending = 9 // finish current cycle, play stop anim, idle
124  };
125 
126  int _walkState;
127  int _targetDir;
129  uint _pathIndex;
130  Common::Point _segStart, _segTarget, _finalTarget;
131  int _finalDir;
132  bool _exactMove;
133  int _walkPhase; // 0..4 walk phase, -1 = finished
134  int _cyclesA, _cyclesB;
135  bool _playStopAnim;
136  Common::Array<int> _cycleScales; // permyriad scale per planned cycle
137  int _scaleIdx;
138  int _errX, _errY, _errStepX, _errStepY;
139  int _errPeriodX, _errPeriodY, _errPhaseX, _errPhaseY;
140  int _walkTickCnt;
141  int _cycleErrX, _cycleErrY, _corrX, _corrY;
142  int _decodedFrame; // FLIC frame currently decoded into _animation
143 
144  void walkUpdateTick();
145  void turnOneStep();
146  void startNextSegment();
147  void setCycleScale(uint idx, int scale);
148  void setupSegmentPhased(int dx, int dy);
149  int advanceWalkPhase(bool cont);
150  void advanceWalkFrame();
151  bool walkTickAdvance();
152  void stepErrorCorrection();
153  void walkingTick();
154  void arrive(int prevState);
155  void stopMoving(bool force);
156  bool loadWalkAnim();
157  Common::Point totalDisp(int dir, int phase) const;
158  int perspectiveScalePermyriad(int y) const;
159  int scaleForSegmentY(int simY, int targetY) const;
160  static double scalePermyriad(int v, int scale);
161  void checkTrapRegions();
162 
163 public:
164  Character(AGDSEngine *engine, const Common::String &name);
165  ~Character();
166 
167  void associate(const Common::String &name);
168 
169  const AnimationDescription *animationDescription(uint index) const {
170  auto it = _animations.find(index);
171  return it != _animations.end() ? &it->_value : nullptr;
172  }
173 
174  const Common::String &name() const {
175  return _name;
176  }
177 
178  const ObjectPtr &object() const {
179  return _object;
180  }
181 
182  void load(Common::SeekableReadStream &stream);
183  void loadState(Common::ReadStream &stream);
184  void saveState(Common::WriteStream &stream) const;
185 
186  void enable(bool enabled = true) {
187  _enabled = enabled;
188  }
189 
190  void visible(bool visible);
191  bool visible() const {
192  return _visible && _shown;
193  }
194 
195  bool active() const {
196  return _enabled && _visible;
197  }
198 
199  bool animate(Common::Point pos, int direction, int speed);
200 
201  void stop();
202  void leave(const Common::String &processName);
203 
204  int phase() const {
205  return _jokes ? _phase : -1;
206  }
207  void phase(int phase) {
208  _phase = phase;
209  }
210 
211  void position(Common::Point pos) {
212  // placing the character cancels any walk in progress
213  cancelWalk();
214  _pos = pos;
215  }
216 
217  void cancelWalk() {
218  _walkState = kWalkIdle;
219  _path.clear();
220  _pathIndex = 0;
221  _targetDir = _direction;
222  }
223 
224  Common::Point position() const {
225  return _pos;
226  }
227  bool pointIn(Common::Point pos) const;
228 
229  void notifyProcess(const Common::String &processName);
230  // leave: walk off-screen instead of stopping at the destination
231  bool moveTo(const Common::String &processName, Common::Point dst, int direction,
232  bool userMove = false, bool leave = false);
233  void pointTo(const Common::String &processName, Common::Point dst);
234  // Graceful stop: finish the current walk cycle, play the stop
235  // animation, then face dir (-1 keeps the current facing).
236  void requestStop(int dir);
237 
238  bool walking() const {
239  return _walkState != kWalkIdle;
240  }
241 
242  bool direction(int dir);
243 
244  int direction() const {
245  return _jokes ? _jokesDirection : _direction;
246  }
247 
248  // base facing direction (0-15), ignoring any jokes gesture in progress
249  int baseDirection() const {
250  return _direction;
251  }
252 
253  void tick(bool reactivate);
254  void paint(Graphics::Surface &backbuffer, Common::Point pos) const;
255 
256  int getDirectionForMovement(Common::Point delta);
257 
258  int z() const;
259 
260  void reset();
261  void setFog(Graphics::ManagedSurface *surface, int minZ, int maxZ);
262 };
263 
264 } // End of namespace AGDS
265 
266 #endif /* AGDS_CHARACTER_H */
Definition: managed_surface.h:51
Definition: str.h:59
Definition: surface.h:67
Definition: stream.h:77
void clear()
Definition: array.h:321
Definition: character.h:48
Definition: stream.h:745
Definition: agds.h:59
Definition: algorithm.h:29
Definition: formatinfo.h:28
Definition: rect.h:144
Definition: stream.h:385
Definition: agds.h:82