00001 #include <iostream>
00002 
00003 #include "Person.h"
00004 #include "List.h"
00005 #include "CollisionHandler.h"
00006 #include "CommandManager.h"
00007 #include "Command.h"
00008 #include "glfuncs.h"
00009 #include "bullet.h"
00010 #include "level.h"
00011 #include "ShowOneSprite.h"
00012 #include "Screen.h"
00013 
00014 
00015 using namespace std;
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 Person::Person(List* personInfo, int x, int y)
00045 :Object(personInfo,x,y),
00046  _xVelocity(0),
00047  _yVelocity(0),
00048  _maxXVel(850),
00049 
00050 
00051 
00052  _maxYVel(800),
00053  _maxFallRate(700),
00054 
00055  _crouching( false ),
00056 
00057  _gravity(2), 
00058  _accel(40),
00059  _airAccel(20),
00060  _groundDrag(-2.5), 
00061  _airDrag(-0.3),
00062  _xDirection( LEFT ),
00063  _yDirection( MIDDLE ), 
00064  _state( JUMPING ), 
00065  _health(2), 
00066  _waitShoot(15), 
00067  _framesSinceShoot(0),
00068  _jumpTimer(0),
00069  _bulletSpeed(500),
00070  _maxJumpTime(15)
00071 {
00072         _collidable = true;
00073 
00074         load(personInfo);
00075 
00076         _previousX = _box.x;
00077         _previousY = _box.y;
00078 }
00079 
00080 void Person::load(List *personInfo)
00081 {
00082         while( !personInfo->empty())
00083         {
00084                 List * current = personInfo->firstList();
00085                 
00086                 if(current->firstString() == "maxXVel")
00087                         _maxXVel = current->rest()->firstInt();
00088 
00089                 if(current->firstString() == "maxYVel")
00090                         _maxYVel = current->rest()->firstInt();
00091 
00092                 if(current->firstString() == "maxFallRate")
00093                         _maxFallRate = current->rest()->firstInt();
00094                 
00095                 if(current->firstString() == "gravity")
00096                         _gravity = current->rest()->firstInt();
00097 
00098                 if(current->firstString() == "accel")
00099                         _accel = current->rest()->firstInt();
00100 
00101                 if(current->firstString() == "airAccel")
00102                         _airAccel = current->rest()->firstInt();
00103 
00104                 if(current->firstString() == "groundDrag")
00105                         _groundDrag = current->rest()->firstDouble();
00106 
00107                 if(current->firstString() == "airDrag")
00108                         _airDrag = current->rest()->firstDouble();
00109 
00110                 if(current->firstString () == "sprite")
00111                         _sprite = Sprite::loadSprite( current->rest()->firstString() );
00112 
00113                 if(current->firstString () == "waitShoot")
00114                         _waitShoot = current->rest()->firstInt();
00115 
00116                 if(current->firstString () == "bulletSpeed")
00117                         _bulletSpeed = current->rest()->firstInt();
00118 
00119                 if(current->firstString () == "maxJumpTime")
00120                         _maxJumpTime = current->rest()->firstInt();
00121                 
00122                 if(current->firstString () == "health")
00123                         _health = current->rest()->firstInt();
00124 
00125                 personInfo = personInfo ->rest();
00126         }
00127 
00128         _box.w = _sprite->width();
00129         _box.h = _sprite->height();
00130 }
00131 
00132 void Person::collide( Object* o )
00133 {
00134         if(     (o->getType() == TILE)|| (o->getType() == DOOR) ||
00135                 ((_type == PLAYER)&&(o->getType() == ENEMY ))||
00136                 ((_type == ENEMY)&&(o->getType() == PLAYER ))
00137                 )
00138         {
00139                 int x,y;
00140                 if( _previousX != _box.x){
00141 
00142                         
00143                         
00144 
00145 
00146 
00147 
00148 
00149                         glfuncs::intersectX(o->getBox(),_box,&x);
00150                         _box.x += x;
00151                         _xVelocity = 0;
00152                 }
00153                 if( _previousY != _box.y){
00154 
00155                         
00156                         
00157 
00158 
00159 
00160 
00161 
00162                         glfuncs::intersectY(o->getBox(),_box,&y);
00163                         _box.y += y;
00164                         _yVelocity = 0;
00165                 }
00166         }
00167 }
00168 
00169 void Person::draw()
00170 {
00171         ShowOneSprite* s = (ShowOneSprite*)_sprite;
00172         s->setDirection( _xDirection ); 
00173         
00174         switch( _state )
00175         {
00176         case STANDING:
00177                 s->show( 0 );
00178                 break;
00179         case RUNNING:
00180                 s->show( 1 );
00181                 break;
00182         case JUMPING:
00183                 s->show( 2 );
00184                 break;
00185         case FALLING:
00186                 s->show( 3 );
00187                 break;
00188         default:
00189                 s->show( 0 );
00190                 break;
00191         }
00192         s->draw(_box.x,_box.y);
00193 }
00194 
00195 void Person::update()
00196 {
00197         
00198         if( _health <= 0 )
00199         {       
00200                 die();
00201                 return;
00202         }
00203         
00204         _framesSinceShoot++;
00205 
00206         
00207         
00208 
00209 
00210 
00211 
00212 
00213         
00214         
00215         
00216         
00217         
00218         
00219         _box.x += (_xVelocity/Screen::FRAMERATE);
00220         CollisionHandler::instance()->checkCollision(this);
00221         _previousX = _box.x;
00222 
00223         
00224         _box.y += (_yVelocity/Screen::FRAMERATE);
00225         CollisionHandler::instance()->checkCollision(this);
00226         _previousY = _box.y;
00227 
00228         
00229         if(_xVelocity != 0)
00230         {
00231                 if(!touchingBelow())
00232                         incrVelocity((_xVelocity/abs(_xVelocity)) * _airDrag * 1000/Screen::FRAMERATE, 0);
00233                 else
00234                         incrVelocity((_xVelocity/abs(_xVelocity)) * _groundDrag * 1000/Screen::FRAMERATE, 0);
00235         }
00236         
00237 
00238         
00239         
00240         int breakVel = Screen::FRAMERATE;
00241         if( abs(_yVelocity) < breakVel )
00242         {
00243                 if( _state != JUMPING )
00244                         _state = STANDING;
00245         } else if( _yVelocity < -breakVel )
00246         {
00247                 _state = JUMPING;
00248         } else if( _yVelocity > breakVel )
00249         {
00250                 _state = FALLING;
00251         }
00252 
00253         incrVelocity(0,_gravity * 1000/Screen::FRAMERATE);
00254 }
00255 
00256 void Person::incrVelocity(int xVel, int yVel)
00257 {
00258         if(abs(_xVelocity + xVel) < _maxXVel)
00259                 _xVelocity += xVel;
00260         else
00261                 _xVelocity < 0 ? _xVelocity = -_maxXVel : _xVelocity = _maxXVel;
00262 
00263 
00264         if(abs(_yVelocity + yVel) < _maxFallRate)
00265                 _yVelocity += yVel;
00266         else
00267                 _yVelocity < 0 ? _yVelocity = -_maxFallRate : _yVelocity = _maxFallRate; 
00268 }
00269 
00270 int Person::getAccel()
00271 {
00272         if(!touchingBelow())
00273                 return _airAccel;
00274 
00275         return _accel;
00276 }
00277 
00278 void Person::jump(xDirection xDir)
00279 {
00280         
00281         
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00297 
00298 
00299 
00300 
00301 
00302 
00303 
00304         
00305         if( touchingBelow() && _jumpReset )
00306         {
00307                 _yVelocity = -_maxYVel;
00308                 
00309                 _jumpTimer = 0;
00310                 _jumpReset = false;
00311                 _wallJumpReset = false;
00312         }
00313         
00314         
00315         else if(  (_wallJumpReset&& _xDirection == RIGHT && _prevXDirection == LEFT && touchingLeft() ) 
00316                         ||(_wallJumpReset && _xDirection == LEFT && _prevXDirection == RIGHT && touchingRight() )
00317                         )
00318         {
00319                 _xVelocity = (int)_xDirection * .8 * _maxXVel;
00320                 _yVelocity = -.9 * _maxYVel;
00321                 _jumpReset = false;
00322                 _wallJumpReset = false;
00323         }
00324         else if(!_jumpReset && _jumpTimer < _maxJumpTime)
00325         {
00326                 _yVelocity = -_maxYVel;
00327                 _jumpTimer ++;
00328         }
00329 
00330 }
00331 
00332 void Person::jumpReset()
00333 {
00334         _jumpReset = true;
00335         _wallJumpReset = true;
00336         _jumpTimer = _maxJumpTime;
00337 }
00338 
00339 void Person::shoot()
00340 {
00341         
00342         if(_framesSinceShoot >= _waitShoot)
00343         {
00344                 Level::instance()->registerObject( new Bullet( this, _bulletSpeed, _xDirection, _yDirection ) );
00345                 _framesSinceShoot = 0;
00346         }
00347 }
00348 
00352 void Person::crouch()
00353 {
00354         _crouching = true;
00355         _box.h /= 2;
00356         _box.y += _box.h;
00357         _sprite->setHeight( _box.h );
00358 }
00362 void Person::uncrouch()
00363 {
00364         if( !touchingAbove())
00365         {
00366                 _crouching = false;
00367                 _box.y -= _box.h;
00368                 _box.h *= 2;
00369                 _sprite->setHeight( _box.h );
00370         }
00371 }
00372 
00376 void Person::die()
00377 {
00378         _collidable = false;
00379         Level::instance()->scheduleDelete( this );
00380 }
00381 
00382 
00383 bool Person::touchingAbove()
00384 {
00385         _box.y--;
00386         vector<Object *> objs = CollisionHandler::ObjsColliding( this );
00387         _box.y++;
00388         return !objs.empty();
00389 }
00390 bool Person::touchingBelow()
00391 {
00392         _box.y++;
00393         vector<Object *> objs = CollisionHandler::ObjsColliding( this );
00394         _box.y--;
00395         return !objs.empty();
00396 }
00397 bool Person::touchingLeft()
00398 {
00399         _box.x--;
00400         vector<Object *> objs = CollisionHandler::ObjsColliding( this );
00401         _box.x++;
00402         return !objs.empty();
00403 }
00404 bool Person::touchingRight()
00405 {
00406         _box.x++;
00407         vector<Object *> objs = CollisionHandler::ObjsColliding( this );
00408         _box.x--;
00409         return !objs.empty();
00410 }