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 #include "Weapon.h"
00014
00015
00016 using namespace std;
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
00045 Person::Person(List* personInfo, int x, int y)
00046 :Object(personInfo,x,y),
00047 _xVelocity(0),
00048 _yVelocity(0),
00049 _maxXVel(850),
00050 _invincible(false),
00051
00052
00053 _maxYVel(800),
00054 _maxFallRate(700),
00055
00056 _crouching( false ),
00057
00058 _gravity(2),
00059 _accel(40),
00060 _airAccel(20),
00061 _groundDrag(-2.5),
00062 _airDrag(-0.3),
00063 _xDirection( LEFT ),
00064 _yDirection( MIDDLE ),
00065 _state( JUMPING ),
00066 _health(2),
00067 _jumpTimer(0),
00068 _maxJumpTime(15),
00069 _dropItem(""),
00070 _primaryWeapon(NULL),
00071 _punchWeapon(NULL),
00072 _punchTimer(0),
00073 _wallFallTime(0)
00074 {
00075 _collidable = true;
00076
00077 load(personInfo);
00078
00079 _previousX = _box.x;
00080 _previousY = _box.y;
00081 }
00082
00083 void Person::load(List *personInfo, bool fromConstructor)
00084 {
00085 if(!fromConstructor)
00086 Object::load(personInfo,fromConstructor);
00087
00088 while( !personInfo->empty())
00089 {
00090 List * current = personInfo->firstList();
00091
00092 if(current->firstString() == "maxXVel")
00093 _maxXVel = current->rest()->firstInt();
00094
00095 if(current->firstString() == "maxYVel")
00096 _maxYVel = current->rest()->firstInt();
00097
00098 if(current->firstString() == "maxFallRate")
00099 _maxFallRate = current->rest()->firstInt();
00100
00101 if(current->firstString() == "gravity")
00102 _gravity = current->rest()->firstInt();
00103
00104 if(current->firstString() == "accel")
00105 _accel = current->rest()->firstInt();
00106
00107 if(current->firstString() == "airAccel")
00108 _airAccel = current->rest()->firstInt();
00109
00110 if(current->firstString() == "groundDrag")
00111 _groundDrag = current->rest()->firstDouble();
00112
00113 if(current->firstString() == "airDrag")
00114 _airDrag = current->rest()->firstDouble();
00115
00116 if(current->firstString () == "sprite")
00117 _sprite = (ShowOneSprite *)Sprite::loadSprite( current->rest()->firstString() );
00118
00119 if(current->firstString () == "maxJumpTime")
00120 _maxJumpTime = current->rest()->firstInt();
00121
00122 if(current->firstString () == "health")
00123 _health = current->rest()->firstInt();
00124
00125 if(current->firstString () == "dropItem")
00126 _dropItem = current->rest()->firstString();
00127
00128 if(current->firstString () == "primaryWeapon")
00129 _primaryWeapon = new Weapon(current->rest()->firstString(),this);
00130
00131 if(current->firstString () == "punchWeapon")
00132 _punchWeapon = new WeaponPunch(current->rest()->firstString(),this);
00133
00134 if(current->firstString () == "dX")
00135 _box.x += current->rest()->firstInt();
00136 if(current->firstString () == "dY")
00137 _box.y += current->rest()->firstInt();
00138
00139 personInfo = personInfo ->rest();
00140 }
00141
00142
00143
00144 _box.w = _sprite->box().w;
00145 _box.h = _sprite->box().h;
00146
00147 }
00148
00149 Person::~Person()
00150 {
00151 if(_primaryWeapon)
00152 delete _primaryWeapon;
00153 if(_punchWeapon)
00154 delete _punchWeapon;
00155 }
00156
00157 Object *Person::copy()
00158 {
00159 Person *copy = new Person(*this);
00160 copy->_primaryWeapon = _primaryWeapon->copy(copy);
00161 return copy;
00162 }
00163
00164 void Person::setPos(int x, int y)
00165 {
00166 Object::setPos(x,y);
00167 _previousX = x;
00168 _previousY = y;
00169 }
00170
00171 void Person::collide( Object* o )
00172 {
00173 if( (o->getType() == TILE)|| (o->getType() == DOOR) ||
00174 ((_type == PLAYER)&&(o->getType() == ENEMY ))||
00175 ((_type == ENEMY)&&(o->getType() == PLAYER ))
00176 )
00177 {
00178 int x,y;
00179 if( _previousX != _box.x){
00180
00181 glfuncs::intersectX(o->getBox(),_box,&x);
00182
00183
00184
00185
00186 if( _type == PLAYER &&
00187 !touchingAbove(Level::tileHeight) &&
00188 touchingAbove(Level::tileHeight-1) )
00189 {
00190 _box.y-=Level::tileHeight;
00191 _previousY -= Level::tileHeight;
00192 }
00193 else
00194 {
00195 _box.x += x;
00196 _xVelocity = 0;
00197 }
00198 }
00199 if( _previousY != _box.y){
00200
00201 glfuncs::intersectY(o->getBox(),_box,&y);
00202 _box.y += y;
00203 _yVelocity = 0;
00204 }
00205 }
00206 }
00207
00208 void Person::draw()
00209 {
00210 ShowOneSprite* s = (ShowOneSprite*)_sprite;
00211 s->setDirection( _xDirection );
00212
00213 switch( _state )
00214 {
00215 case STANDING:
00216 s->show( 0 );
00217 break;
00218 case RUNNING:
00219 s->show( 1 );
00220 break;
00221 case JUMPING:
00222 s->show( 2 );
00223 break;
00224 case FALLING:
00225 s->show( 3 );
00226 break;
00227 case WALLFALLING:
00228 s->show( 4 );
00229 break;
00230 case CROUCHING:
00231 s->show( 5 );
00232 break;
00233 case PUNCHING:
00234 s->show( 6 );
00235 break;
00236 case DEAD:
00237 s->show( 7 );
00238 break;
00239 default:
00240 s->show( 0 );
00241 break;
00242 }
00243 s->draw(_box.x,_box.y);
00244 }
00245
00246 void Person::update()
00247 {
00248 _sprite->update();
00249
00250 if(_primaryWeapon)
00251 _primaryWeapon->update();
00252 if(_punchWeapon)
00253 _punchWeapon->update();
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 _box.x += (_xVelocity/Screen::FRAMERATE);
00269 CollisionHandler::instance()->checkCollision(this);
00270 _previousX = _box.x;
00271
00272
00273 _box.y += (_yVelocity/Screen::FRAMERATE);
00274 CollisionHandler::instance()->checkCollision(this);
00275 _previousY = _box.y;
00276
00277
00278 if(_xVelocity != 0)
00279 {
00280 if(!touchingBelow())
00281 incrVelocity((_xVelocity/abs(_xVelocity)) * _airDrag * 1000/Screen::FRAMERATE, 0);
00282 else
00283 incrVelocity((_xVelocity/abs(_xVelocity)) * _groundDrag * 1000/Screen::FRAMERATE, 0);
00284 }
00285
00286
00287
00288
00289 int breakVel = Screen::FRAMERATE;
00290 if(_state !=DEAD){
00291 if(_state == PUNCHING && _punchTimer > 0)
00292 {
00293 _punchTimer--;
00294 }
00295 else if( _punchTimer == 0)
00296 {
00297 if( abs(_yVelocity) < breakVel )
00298 {
00299 if( _state != JUMPING )
00300 _state = STANDING;
00301 }
00302 if( _yVelocity < -breakVel )
00303 {
00304 _state = JUMPING;
00305 } else if(_crouching)
00306 {
00307 _state = CROUCHING;
00308 } else if( _yVelocity > breakVel )
00309 {
00310 _state = FALLING;
00311 if(touchingLeft()||touchingRight())
00312 {
00313
00314
00315 if(_wallFallTime > 7)
00316 _state = WALLFALLING;
00317 _wallFallTime++;
00318 }
00319 } else if(abs(_xVelocity) > breakVel)
00320 {
00321 _state = RUNNING;
00322 }
00323
00324
00325
00326 if(_state != WALLFALLING && _wallFallTime > 8)
00327 _wallFallTime = 0;
00328 }
00329 }
00330
00331 incrVelocity(0,_gravity * 1000/Screen::FRAMERATE);
00332 }
00333
00334 void Person::incrVelocity(int xVel, int yVel)
00335 {
00336 if(abs(_xVelocity + xVel) < _maxXVel)
00337 _xVelocity += xVel;
00338 else
00339 _xVelocity < 0 ? _xVelocity = -_maxXVel : _xVelocity = _maxXVel;
00340
00341
00342 if(abs(_yVelocity + yVel) < _maxFallRate)
00343 _yVelocity += yVel;
00344 else
00345 _yVelocity < 0 ? _yVelocity = -_maxFallRate : _yVelocity = _maxFallRate;
00346 }
00347
00348 int Person::getAccel()
00349 {
00350 if(!touchingBelow())
00351 return _airAccel;
00352
00353 return _accel;
00354 }
00355
00356 void Person::jump(xDirection xDir)
00357 {
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 if( !_crouching &&_jumpReset && touchingBelow() && !touchingAbove() )
00384 {
00385 _yVelocity = -_maxYVel;
00386
00387 _jumpTimer = 0;
00388 _jumpReset = false;
00389 _wallJumpReset = false;
00390 }
00391
00392 else if( touchingAbove() )
00393 {
00394 _jumpTimer = _maxJumpTime;
00395 }
00396
00397
00398 else if( (_wallJumpReset&& _xDirection == RIGHT && _prevXDirection == LEFT && touchingLeft() )
00399 ||(_wallJumpReset && _xDirection == LEFT && _prevXDirection == RIGHT && touchingRight() )
00400 )
00401 {
00402 _xVelocity = (int)_xDirection * .8 * _maxXVel;
00403 _yVelocity = -_maxYVel;
00404 _jumpReset = false;
00405 _wallJumpReset = false;
00406 }
00407 else if(!_jumpReset && _jumpTimer < _maxJumpTime)
00408 {
00409 _yVelocity = -0.25 * _maxYVel;
00410 _jumpTimer ++;
00411 }
00412
00413 }
00414
00415 void Person::live()
00416 {
00417 _invincible = false;
00418 _state = STANDING;
00419 }
00420
00421 void Person::jumpReset()
00422 {
00423 _jumpReset = true;
00424 _wallJumpReset = true;
00425 _jumpTimer = _maxJumpTime;
00426 _sprite->reset(2);
00427 }
00428
00429 void Person::shoot()
00430 {
00431 if(_primaryWeapon)
00432 _primaryWeapon->shoot();
00433
00434 if(_punchWeapon && !_crouching)
00435 {
00436 _punchWeapon->shoot();
00437 _state = PUNCHING;
00438
00439
00440 _punchTimer = 1;
00441 }
00442 }
00443
00447 void Person::crouch()
00448 {
00449 if(!_crouching && touchingBelow())
00450 {
00451 _crouching = true;
00452 _box.h /= 2;
00453 _box.y += _box.h;
00454 _previousY = _box.y;
00455 _previousX = _box.x;
00456 _sprite->setHeight( _box.h );
00457 }
00458 }
00462 void Person::uncrouch()
00463 {
00464 if( _crouching && !touchingAbove( _box.h ) )
00465 {
00466 _crouching = false;
00467 _box.y -= _box.h;
00468 _previousY = _box.y;
00469 _previousX = _box.x;
00470 _box.h *= 2;
00471 _sprite->setHeight( _box.h );
00472 }
00473 }
00474
00478 void Person::die()
00479 {
00480 _collidable = false;
00481 Level::instance()->scheduleDelete( this );
00482
00483 if(_dropItem != "") {
00484 Object *newObject = Object::loadObject(_dropItem,0,0);
00485 SDL_Rect rect = newObject->getBox();
00486 newObject->setPos(_box.x, _box.y + _box.h - rect.h);
00487 Level::instance()->registerObject( newObject );
00488 }
00489 }
00490
00491 bool Person::touchingAbove(int pels)
00492 {
00493 _box.y-=pels;
00494 vector<Object *> objs = CollisionHandler::ObjsColliding( this , true);
00495 _box.y+=pels;
00496 return !objs.empty();
00497 }
00498 bool Person::touchingBelow(int pels)
00499 {
00500 _box.y+=pels;
00501 vector<Object *> objs = CollisionHandler::ObjsColliding( this , true);
00502 _box.y-=pels;
00503 return !objs.empty();
00504 }
00505 bool Person::touchingLeft(int pels)
00506 {
00507 _box.x-=pels;
00508 vector<Object *> objs = CollisionHandler::ObjsColliding( this , true);
00509 _box.x+=pels;
00510 return !objs.empty();
00511 }
00512 bool Person::touchingRight(int pels)
00513 {
00514 _box.x+=pels;
00515 vector<Object *> objs = CollisionHandler::ObjsColliding( this , true);
00516 _box.x-=pels;
00517 return !objs.empty();
00518 }
00519
00520 void Person::addHealth(int dHealth)
00521 {
00522 if( !_invincible || dHealth >= 0 ) {
00523 _health += dHealth;
00524
00525
00526 if( _health <= 0 )
00527 {
00528
00529 if(_type == ENEMY)
00530 CommandManager::instance()->execute(new PlaySoundCommand("sounds/death_male08.wav"));
00531 else if(_type == PLAYER)
00532 CommandManager::instance()->execute(new PlaySoundCommand("sounds/death_male02.wav"));
00533
00534 die();
00535 }
00536 }
00537 }