JNR
laMovingCreature.cpp
1 /*
2 
3 Jump'n'Run Engine
4 http://www.atanaslaskov.com/jnr/
5 
6 BSD LICENSE
7 Copyright (c) 2007-2013, Atanas Laskov
8 All rights reserved.
9 
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions are met:
12 1. Redistributions of source code must retain the above copyright notice,
13 this list of conditions and the following disclaimer.
14 2. Redistributions in binary form must reproduce the above copyright notice,
15 this list of conditions and the following disclaimer in the documentation
16 and/or other materials provided with the distribution.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL ATANAS LASKOV BE LIABLE FOR ANY
21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 */
29 
30 //
31 // FILE: laMovingCreature.cpp
32 //
33 // Moving Creature
34 //
35 // Copyright (C) 2007-2013 Atanas Laskov, <latanas@gmail.com>
36 //
37 #include "stdafx.h"
38 #include "Core-Level-JR.h"
39 
40 // Constructor
41 //
42 laMovingCreature::laMovingCreature(rpgSheet* pSheet)
43 {
44  // Instantiate RPG properties sheet
45  //
46  if(pSheet) _pSheet = pSheet;
47  else _pSheet = new rpgSheet_Acrobate;
48 
49  // Set state
50  //
51  _bExplicitFacing = M_FALSE;
52  _nFaceDirection = +1;
53  _nMovementDirection = 0;
54  _bJumping = M_FALSE;
55 
56  _ttTurn.parameters(0.4);
57  _ttTurn.enable();
58 
59  _ttSomersault.parameters(0.4);
60  _ttSomersault.enable(M_FALSE);
61 
62  // Load trail FX
63  //
64  laFileParser fxp;
65  char strFilePath[128]=M_DIR_FX;
66  fxParticleSystem_params param;
67 
68  strcat(strFilePath, "creature_trail.fx");
69  fxp.fileOpen(strFilePath);
70  fxp.readObj(&param, M_FALSE);
71  fxp.fileClose();
72 
73  _fxTrail.create(param);
74  _fxTrail.enable(M_TRUE);
75  _fxTrail.enableGeneration(M_TRUE);
76  _fxTrail.ctlRewind();
77 
78  enableControl();
79 }
80 
81 laMovingCreature::~laMovingCreature(void)
82 {
83 }
84 
85 // Respawn moving creature
86 //
87 void laMovingCreature::respawn()
88 {
89  laStateObject::respawn();
90 
91  // Reset pivot
92  _ptPivot = _ptOriginPos;
93 
94  // Reset facing
95  _nMovementDirection = 0;
96  _bExplicitFacing = M_FALSE;
97 
98  // Reset sheet
99  _pSheet->reset();
100 }
101 
102 // Load from LVL file
103 //
104 void laMovingCreature::load(class laFileParser *fp)
105 {
106  laStateObject::load(fp);
107 
108  //Store the original position (we will need it to respawn)
109  //
110 
111  try{
112  _ptPivot.mass = getObject()->getDouble("mass");
113  }
114  catch(laError_PropertyNotDefined&){ _ptPivot.mass = 1; }
115 
116  _ptOriginPos = _ptPivot;
117 
118  // Extract creature properties
119  _pSheet->load( getObject()->getChild("rpg-sheet") );
120 }
121 
122 // Explicit direction control
123 //
124 void laMovingCreature::setFaceDirection(int nDirection)
125 {
126  // Update face direction
127  //
128  //if( (!_bExplicitFacing) && (_ttTurn.isEnabled()) )
129  //{
130  //int nOldFacing = _nFaceDirection;
131  //if(_nMovementDirection<0) _nFaceDirection=-1;
132  //else if(_nMovementDirection>0) _nFaceDirection=+1;
133 
134  if( nDirection!=_nFaceDirection )
135  {
136  _ttTurn.reset();
137  _ttTurn.enable();
138  }
139  //}
140 
141  _nFaceDirection = nDirection;
142 }
143 
144 // Change movement direction
145 //
146 void laMovingCreature::move(int direction)
147 {
148  if(!isControlEnabled()) return;
149 
150  if( direction!=_nMovementDirection )
151  {
152  //double OldSpeedModifier = M_PLAYER_SPEED * _nMovementDirection * M_UNIT;
153  double NewSpeedModifier = ((rpgSheet_Acrobate*)_pSheet)->modSpeed() * direction ;
154 
155  //If the player is was already moving
156  if(_nMovementDirection)
157  {
158  //...Remove any residual waking velocity
159 
160  //if( M_SIGN(_ptPivot.velocity.x()-OldSpeedModifier) != M_SIGN(_ptPivot.velocity.x()) )
161  _ptPivot.velocity.x(0);
162  //else
163  // _ptPivot.velocity[0] -= OldSpeedModifier;
164 
165  }
166 
167  //Add the new waking velocity (if direction=0 the player will stop)
168  _ptPivot.velocity.x(NewSpeedModifier); /*+=*/
169 
170  //Update playar waking state
171  _nMovementDirection = direction;
172  }
173 
174  _update_facing( (double) _nMovementDirection );
175 }
176 
177 void laMovingCreature::move_v(laPoint3 dir)
178 {
179  if(!isControlEnabled()) return;
180 
181  double NewSpeedModifier = ((rpgSheet_Acrobate*)_pSheet)->modSpeed(); // * M_UNIT;
182 
183  if(dir.lenght() > 1) dir.normalize(); // could be 0~
184  _ptPivot.velocity = dir * NewSpeedModifier;
185 
186  _nMovementDirection = (int) ceil(dir.x());
187  _update_facing( dir.x() );
188 }
189 
190 // Update face direction
191 //
192 void laMovingCreature::_update_facing( double dir_x )
193 {
194  if( (!_bExplicitFacing) && (_ttTurn.isEnabled()) )
195  {
196  //int nOldFacing = _nFaceDirection;
197  if(dir_x<0) setFaceDirection(-1);//_nFaceDirection=-1;
198  else if(dir_x>0) setFaceDirection(+1);//_nFaceDirection=+1;
199 
200  /*if( nOldFacing!=_nFaceDirection )
201  {
202  _ttTurn.reset();
203  _ttTurn.enable();
204  }*/
205  }
206 }
207 
208 
209 // Initiate a jump
210 //
211 M_BOOL laMovingCreature::jump()
212 {
213  if(!isControlEnabled()) return M_FALSE;
214 
215  // Jump only if the creature is on the ground and he is not already jumping
216  //
217  if( (_ptPivot.bOnGround) && (!_bJumping) )
218  {
219  double NewSpeedModifier = ((rpgSheet_Acrobate*)_pSheet)->modJPower(); // * M_UNIT; //TODO: fix this no cbsz
220 
221  _ptPivot.velocity.y( _ptPivot.velocity.y() - NewSpeedModifier);
222  _bJumping = M_TRUE;
223  return M_TRUE;
224  }
225  return M_FALSE;
226 }
227 
228 // Somersault
229 //
231 {
232  if(!isControlEnabled()) return;
233 
234  // NOTE: if there is not _bSomersaultPerformed check,
235  // then its possible to make multiple somersaults
236  // if the player is quick - it is better without the check
237 
238  if( (_ptPivot.velocity.y()<0) /*&& (!_bSomersaultPerformed)*/ )
239  {
240  fxMessages.add(0.8, laColor(255,255,0), "Hop!");
241 
242  double NewSpeedModifier = ((rpgSheet_Acrobate*)_pSheet)->modSPower() ;
243  _ptPivot.velocity.y( _ptPivot.velocity.y() - NewSpeedModifier);
244 
245  _ttSomersault.reset();
246  _ttSomersault.enable();
247  }
248 }
249 
250 unsigned laMovingCreature::_next_state(unsigned nCurrentState )
251 {
252  setBlendTime(0.2);
253 
254  // Choose an appropriate movemnt state
255  //
256  if( _ttSomersault.isEnabled() && (!_ttSomersault.isElapsed()) )
257  return M_STATE_SOMERSAULT;
258 
259  if(_ptPivot.bOnGround)
260  {
261  //if( this->getState()==M_STATE_SOMERSAULT)
262 
263  if( M_ABS(_ptPivot.velocity.x())>0.01*M_UNIT )
264  return M_STATE_WALK;
265  else
266  return M_STATE_STAND;
267  }
268  else
269  {
270  if(_ptPivot.velocity.y()>0)
271  return M_STATE_JUMP_D;
272  else
273  return M_STATE_JUMP_U;
274  }
275 
276  return laStateObject::_next_state(nCurrentState);
277 }
278 
279 // Animate
280 //
281 void laMovingCreature::animate(laTimer &t)
282 {
283  ERRORLEVEL_BEGIN;
284 
285  // Animate pivot physics
286  //
287  _ptPivot.simulate(t);
288  _ptPivot.projectShadow();
289 
290  //If the character is already descending, make sure that
291  //jumping will be possible when he lands
292  if( _ptPivot.velocity.y()>0 ) _bJumping = M_FALSE;
293 
294  // Animate trail
295  // Control particle generation for the movement trail FX
296  //
297  _fxTrail.enableGeneration( (_nMovementDirection!=0) || (!_ptPivot.bOnGround) );
298  _fxTrail.position( _ptPivot /*- _ptPivot.size/2.0*/ );
299  _fxTrail.animate(t);
300 
301  // Animated somersault roatation
302  //
303  if(_ptPivot.bOnGround)
304  _ttSomersault.enable(M_FALSE);
305 
306  if( _ttSomersault.isEnabled() && (!_ttSomersault.isElapsed()) )
307  {
308  _ptPivot.angleZ = -360*_ttSomersault.reminder();
309  //state(M_STATE_SOMERSAULT);
310  }
311  else _ptPivot.angleZ = 0;
312 
313  _ttSomersault.animate(t);
314  _ttTurn.animate(t);
315 
316  // Default animation for the state object
317  //
318  laStateObject::animate(t);
319  ERRORLEVEL_END;
320 }
321 
322 // Draw FX
323 //
324 void laMovingCreature::_drawFx_positioned(laRenderer *r) {
325  laStateObject::_drawFx_positioned(r);
326 
327  r->transPush();
328  r->transTranslate( -1*_ptPivot );
329  _fxTrail.draw(r);
330  r->transPop();
331 }
332 
333 //void laMovingCreature::_draw_notrans(laRenderer *r, laPoint3 ptBasePos) {
334 //}
335 
336 // Draw geometry
337 //
338 void laMovingCreature::drawGeometry(laRenderer *r, laPoint3 ptBasePos)
339 {
340  // Gradual rotation when changing direction
341  //
342  if(_nFaceDirection>0) _ptPivot.angleY = -180*_ttTurn.reminder() /*+ (0)*(1-_ttTurn.reminder())*/;
343  else _ptPivot.angleY = /*(0)*_ttTurn.reminder() +*/ -180*(1-_ttTurn.reminder());
344 
345  laStateObject::drawGeometry(r, ptBasePos);
346 }
#define M_UNIT
Unit of 1 meter.
Animated Text Effect.
Definition: fxMessages.h:64
#define M_DIR_FX
Visual effects directory.
Abstract RPG Properties Sheet.
Definition: rpgSheet.h:107
#define M_ABS(a)
Return abs(a)
Acrobatics RPG Properties.
Virtual interface for the Engine graphics renderer.
Definition: laRenderer.h:98
virtual void move(int direction)
virtual void somersault()
File Parser.
Definition: laFileParser.h:41