00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "kgrfigure.h"
00019
00020 #include "kgrconsts.h"
00021 #include "kgrobject.h"
00022 #include "kgrcanvas.h"
00023
00024 #include <stdio.h>
00025 #include <QList>
00026
00027 KGrFigure::KGrFigure (int px, int py) : direction (RIGHT)
00028 {
00029 x = mem_x = px;
00030 y = mem_y = py;
00031 relx = mem_relx = 0;
00032 rely = mem_rely = 0;
00033
00034 absx = px*16;
00035 absy = py*16;
00036
00037 nuggets = 0;
00038 status = STANDING;
00039
00040 walkTimer = new QTimer (this);
00041 fallTimer = new QTimer (this);
00042 }
00043
00044
00045 bool KGrFigure::variableTiming = true;
00046 bool KGrFigure::alwaysCollectNugget = true;
00047 bool KGrFigure::runThruHole = true;
00048 bool KGrFigure::reappearAtTop = true;
00049 SearchStrategy KGrFigure::searchStrategy = LOW;
00050
00051 int KGrFigure::herox = 0;
00052 int KGrFigure::heroy = 0;
00053
00054
00055 int KGrFigure::speed = NSPEED;
00056 int KGrBrick::speed = NSPEED;
00057
00058
00059
00060
00061
00062 Timing KGrFigure::fixedTiming = {45, 50, 55, 100, 500, 40};
00063
00064 Timing KGrFigure::varTiming[6] = {
00065 {40, 58, 78, 88, 170, 23},
00066 {50, 68, 78, 88, 170, 32},
00067 {57, 67, 114, 128, 270, 37},
00068 {60, 70, 134, 136, 330, 40},
00069 {63, 76, 165, 150, 400, 46},
00070 {70, 80, 189, 165, 460, 51}
00071 };
00072
00073 int KGrBrick::HOLETIME = 0;
00074
00075 int KGrFigure::getx()
00076 {
00077 return absx;
00078 }
00079
00080 int KGrFigure::gety()
00081 {
00082 return absy;
00083 }
00084
00085 Status KGrFigure::getStatus()
00086 {
00087 return status;
00088 }
00089
00090 void KGrFigure::init (int a,int b)
00091 {
00092 walkTimer->stop();
00093 fallTimer->stop();
00094 x = mem_x = a;
00095 y = mem_y = b;
00096 relx = mem_relx = 0;
00097 rely = mem_rely = 0;
00098 nuggets = 0;
00099 status = STANDING;
00100 }
00101
00102 void KGrFigure:: setNuggets (int n)
00103 {
00104 nuggets = n;
00105 }
00106
00107
00108 bool KGrFigure::canWalkRight()
00109 {
00110 return (((*playfield)[x+1][y]->whatIam() != BRICK) &&
00111 ((*playfield)[x+1][y]->whatIam() != BETON) &&
00112 ((*playfield)[x+1][y]->whatIam() != FBRICK));
00113 }
00114
00115 bool KGrFigure::canWalkLeft()
00116 {
00117 return (((*playfield)[x-1][y]->whatIam() != BRICK) &&
00118 ((*playfield)[x-1][y]->whatIam() != BETON) &&
00119 ((*playfield)[x-1][y]->whatIam() != FBRICK));
00120 }
00121
00122 bool KGrFigure::canWalkUp()
00123 {
00124 return (((*playfield)[x][y-1]->whatIam() != BRICK) &&
00125 ((*playfield)[x][y-1]->whatIam() != BETON) &&
00126 ((*playfield)[x][y-1]->whatIam() != FBRICK) &&
00127 ((*playfield)[x][y]->whatIam() == LADDER));
00128 }
00129
00130 bool KGrFigure::canWalkDown()
00131 {
00132 return (((*playfield)[x][y+1]->whatIam() != BRICK) &&
00133 ((*playfield)[x][y+1]->whatIam() != BETON) &&
00134
00135
00136 (((*playfield)[x][y+1]->whatIam() == LADDER)||
00137 ((*playfield)[x][y]->whatIam() == LADDER)));
00138 }
00139
00140 bool KGrFigure::canStand()
00141 {
00142 return (((*playfield)[x][y+1]->whatIam() == BRICK) ||
00143 ((*playfield)[x][y+1]->whatIam() == BETON) ||
00144 ((*playfield)[x][y+1]->whatIam() == USEDHOLE)||
00145 ((*playfield)[x][y+1]->whatIam() == LADDER)||
00146 ((*playfield)[x][y]->whatIam() == LADDER)||
00147 standOnEnemy());
00148 }
00149
00150 bool KGrFigure::hangAtPole()
00151 {
00152 return ((*playfield)[x][y]->whatIam() == POLE);
00153 }
00154
00155 void KGrFigure::walkUp (int WALKDELAY)
00156 {
00157 actualPixmap = (actualPixmap == CLIMB1) ? CLIMB2 : CLIMB1;
00158 if (actualPixmap == CLIMB1) {
00159 emit stepDone (true);
00160 }
00161 if (walkCounter++ < gameCycle) {
00162
00163 if (canWalkUp()) {
00164 rely -= STEP;
00165 absy -= STEP;
00166 }
00167 walkTimer->setSingleShot (true);
00168 walkTimer->start ((WALKDELAY * NSPEED) / speed);
00169 }
00170 else {
00171
00172 if (canWalkUp()) {
00173 y--;
00174 }
00175
00176 rely = 0;
00177 absy = y*16;
00178
00179
00180 status = STANDING;
00181 }
00182 }
00183
00184 void KGrFigure::walkDown (int WALKDELAY, int FALLDELAY)
00185 {
00186 if (hangAtPole() || (! canStand())) {
00187
00188 initFall (FALL2, FALLDELAY);
00189 }
00190 else {
00191 actualPixmap = (actualPixmap == CLIMB1) ? CLIMB2 : CLIMB1;
00192 if (actualPixmap == CLIMB1) {
00193 emit stepDone (true);
00194 }
00195 if (walkCounter++ < gameCycle) {
00196
00197 if (canWalkDown()) {
00198 rely += STEP;
00199 absy += STEP;
00200 }
00201 walkTimer->setSingleShot (true);
00202 walkTimer->start ((WALKDELAY * NSPEED) / speed);
00203 }
00204 else {
00205
00206 if (canWalkDown()) {
00207 y++;
00208 }
00209
00210 rely = 0;
00211 absy = y*16;
00212
00213
00214 if (! (canStand() || hangAtPole()))
00215 initFall (FALL2, FALLDELAY);
00216 else
00217
00218 status = STANDING;
00219 }
00220 }
00221 }
00222
00223 void KGrFigure::walkLeft (int WALKDELAY, int FALLDELAY)
00224 {
00225
00226 if (walkCounter++ != 0) {
00227
00228 if ((++actualPixmap % gameCycle) != 0) {
00229
00230 if (canWalkLeft()) {
00231 relx -= STEP;
00232 absx -=STEP;
00233 }
00234 walkTimer->setSingleShot (true);
00235 walkTimer->start ((WALKDELAY * NSPEED) / speed);
00236 }
00237 else {
00238
00239 alternateStepGraphics = true;
00240 if ((actualPixmap % graphicsCycle) == 0) {
00241 alternateStepGraphics = false;
00242 actualPixmap -= graphicsCycle;
00243 }
00244
00245 if (canWalkLeft()) {
00246 x--;
00247 }
00248
00249 relx = 0;
00250 absx = x*16;
00251
00252 int frame = actualPixmap % graphicsCycle;
00253 if ((frame == 0) || (frame == 4)) {
00254 emit stepDone(hangAtPole());
00255 }
00256
00257 if (! (canStand() || hangAtPole()))
00258 initFall (FALL1, FALLDELAY);
00259 else
00260 status = STANDING;
00261 }
00262 }
00263 else {
00264 status = STANDING;
00265 }
00266 }
00267
00268 void KGrFigure::walkRight (int WALKDELAY, int FALLDELAY)
00269 {
00270 if (walkCounter++) {
00271 if ((++actualPixmap % gameCycle) != 0) {
00272
00273 if (canWalkRight()) {
00274 relx += STEP;
00275 absx += STEP;
00276 }
00277 walkTimer->setSingleShot (true);
00278 walkTimer->start ((WALKDELAY * NSPEED) / speed);
00279 }
00280 else {
00281
00282 alternateStepGraphics = true;
00283 if ((actualPixmap % graphicsCycle) == 0) {
00284 alternateStepGraphics = false;
00285 actualPixmap -= graphicsCycle;
00286 }
00287
00288 if (canWalkRight()) {
00289 x++;
00290 }
00291
00292 relx = 0;
00293 absx = x*16;
00294 int frame = actualPixmap % graphicsCycle;
00295 if ((frame == 0) || (frame == 4)) {
00296 emit stepDone(hangAtPole());
00297 }
00298
00299 if (!(canStand()||hangAtPole()))
00300 initFall (FALL2, FALLDELAY);
00301 else
00302 status = STANDING;
00303 }
00304 }
00305 else {
00306 status = STANDING;
00307 }
00308 }
00309
00310 void KGrFigure::initFall (int apm, int FALLDELAY)
00311 {
00312 emit falling (true);
00313 status = FALLING;
00314 actualPixmap = apm;
00315 walkCounter=1;
00316 walkTimer->stop();
00317 fallTimer->setSingleShot (true);
00318 fallTimer->start ((FALLDELAY * NSPEED) / speed);
00319 }
00320
00321 void KGrFigure::showFigure()
00322 {
00323 }
00324
00325 void KGrFigure::setPlayfield (KGrObject * (*p)[30][22])
00326 {
00327 playfield = p;
00328 }
00329
00330 KGrFigure::~KGrFigure()
00331 {
00332 }
00333
00334 KGrHero::KGrHero (KGrCanvas * view, int x, int y)
00335 :KGrFigure (x, y)
00336 {
00337 heroView = view;
00338 status = STANDING;
00339 actualPixmap = FALL1;
00340
00341 herox = x;
00342 heroy = y;
00343
00344 started = false;
00345 mouseMode = true;
00346 walkCounter = 1;
00347
00348 walkFrozen = false;
00349 fallFrozen = false;
00350 alternateStepGraphics = false;
00351
00352 connect (walkTimer, SIGNAL (timeout()), SLOT (walkTimeDone()));
00353 connect (fallTimer, SIGNAL (timeout()), SLOT (fallTimeDone()));
00354 }
00355
00356 int KGrHero::WALKDELAY = 0;
00357 int KGrHero::FALLDELAY = 0;
00358
00359
00360
00361
00362 void KGrHero::startWalk()
00363 {
00364 switch (nextDir) {
00365 case UP:
00366 if ((*playfield)[x][y]->whatIam() == LADDER) {
00367 walkCounter = 1;
00368 direction = UP;
00369 }
00370 break;
00371 case RIGHT:
00372 if (hangAtPole())
00373 actualPixmap = (alternateStepGraphics)? RIGHTCLIMB5:RIGHTCLIMB1;
00374 else
00375 actualPixmap = (alternateStepGraphics)? RIGHTWALK5 : RIGHTWALK1;
00376 if (direction != RIGHT)
00377 walkCounter = 0;
00378 else
00379 walkCounter = 1;
00380 direction = RIGHT;
00381 break;
00382 case DOWN:
00383 if (((*playfield)[x][y]->whatIam() == LADDER)||
00384 ((*playfield)[x][y+1]->whatIam() == LADDER))
00385 {walkCounter = 1;
00386 direction = DOWN;}
00387 else
00388
00389 if (hangAtPole() && (!canStand())) {
00390 status = STANDING;
00391 actualPixmap = (direction==RIGHT) ? FALL2 : FALL1;
00392 walkCounter = 1;
00393 direction = STAND;
00394 walkTimer->stop();
00395 }
00396 break;
00397 case LEFT:
00398 if (hangAtPole())
00399 actualPixmap = (alternateStepGraphics)? LEFTCLIMB5 : LEFTCLIMB1;
00400 else
00401 actualPixmap = (alternateStepGraphics)? LEFTWALK5 : LEFTWALK1;
00402 if (direction != LEFT)
00403 walkCounter = 0;
00404 else
00405 walkCounter = 1;
00406 direction = LEFT;
00407 break;
00408 default :
00409 direction = STAND;
00410 status = FALLING;
00411 break;
00412 }
00413 nextDir = STAND;
00414 if (status != FALLING) {
00415 status = WALKING;
00416 showFigure();
00417 }
00418 }
00419
00420 void KGrHero::setKey (Direction key)
00421 {
00422
00423
00424 mouseMode = false;
00425 stopped = false;
00426 switch (key) {
00427 case UP: mousex = x; mousey = 0; break;
00428 case DOWN: mousex = x; mousey = FIELDHEIGHT + 1; break;
00429 case LEFT: mousex = 0; mousey = y; break;
00430 case RIGHT: mousex = FIELDWIDTH + 1; mousey = y; break;
00431 case STAND: stopped = true; mousex = x; mousey = y; break;
00432 }
00433 }
00434
00435 void KGrHero::setDirection (int i, int j)
00436 {
00437
00438 mouseMode = true;
00439 stopped = false;
00440 mousex = i;
00441 mousey = j;
00442 }
00443
00444 void KGrHero::setNextDir()
00445 {
00446 int dx, dy;
00447
00448 if (! mouseMode) {
00449
00450 if (stopped) {
00451 mousex = x;
00452 mousey = y;
00453 }
00454 if ((mousey < 1) || (mousey > FIELDHEIGHT)) {
00455 mousex = x;
00456 }
00457 else if ((mousex < 1) || (mousex > FIELDWIDTH)) {
00458 mousey = y;
00459 }
00460 }
00461
00462 dx = mousex - x; dy = mousey - y;
00463
00464 if ((dy == 0) && (y == 1) && (nuggets <= 0)) {
00465 nextDir = UP;
00466 }
00467 else if ((dy > 0) &&
00468 (canWalkDown() ||
00469
00470
00471
00472
00473
00474 (hangAtPole() && ((*playfield)[x][y+1]->whatIam() != BRICK) &&
00475 ((*playfield)[x][y+1]->whatIam() != BETON)))) {
00476 nextDir = DOWN;
00477 }
00478 else if ((dy < 0) && canWalkUp()) {
00479 nextDir = UP;
00480 }
00481 else if (dx > 0) {
00482 nextDir = RIGHT;
00483 }
00484 else if (dx < 0) {
00485 nextDir = LEFT;
00486 }
00487 else if (dx == 0) {
00488 nextDir = STAND;
00489 }
00490 }
00491
00492 void KGrHero::doStep() {
00493 if (walkFrozen) {
00494 walkFrozen = false;
00495 walkTimeDone();
00496 }
00497 if (fallFrozen) {
00498 fallFrozen = false;
00499 fallTimeDone();
00500 }
00501 }
00502
00503 void KGrHero::showState (char option)
00504 {
00505 printf ("(%02d,%02d) - Hero ", x, y);
00506 switch (option) {
00507 case 'p': printf ("\n"); break;
00508 case 's': printf (" nuggets %02d status %d walk-ctr %d ",
00509 nuggets, status, walkCounter);
00510 printf ("dirn %d next dirn %d\n", direction, nextDir);
00511 printf (" rel (%02d,%02d) abs (%03d,%03d)",
00512 relx, rely, absx, absy);
00513 printf (" pix %02d", actualPixmap);
00514 printf (" mem %d %d %d %d", mem_x, mem_y, mem_relx, mem_rely);
00515 if (walkFrozen) printf (" wBlock");
00516 if (fallFrozen) printf (" fBlock");
00517 printf ("\n");
00518 break;
00519 }
00520 }
00521
00522 void KGrHero::init (int a,int b)
00523 {
00524 walkTimer->stop();
00525 fallTimer->stop();
00526 walkCounter = 1;
00527 started = false;
00528
00529 x = mem_x = a;
00530 y = mem_y = b;
00531 relx = mem_relx = 0;
00532 rely = mem_rely = 0;
00533
00534 absx = 16*x;
00535 absy = 16*y;
00536
00537 nuggets = 0;
00538
00539 if (herox < 1) {
00540 heroView->makeHeroSprite (x, y, actualPixmap);
00541 }
00542 herox = x;
00543 heroy = y;
00544
00545 actualPixmap = FALL2;
00546 heroView->moveHero (absx, absy, actualPixmap);
00547 }
00548
00549 void KGrHero::start()
00550 {
00551 started = true;
00552 walkFrozen = false;
00553 fallFrozen = false;
00554
00555 if (!(canStand()||hangAtPole())) {
00556 status = FALLING;
00557 fallTimeDone();
00558 }
00559 else {
00560 status = STANDING;
00561 walkTimeDone();
00562 }
00563 }
00564
00565 void KGrHero::setSpeed (int gamespeed)
00566 {
00567 if (gamespeed >= 0) {
00568 if (gamespeed < MINSPEED)
00569 speed++;
00570 else
00571 speed = gamespeed;
00572 if (speed > MAXSPEED)
00573 speed = MAXSPEED;
00574 }
00575 else {
00576 speed--;
00577 if (speed < MINSPEED)
00578 speed = MINSPEED;
00579 }
00580
00581 KGrBrick::speed = speed;
00582 }
00583
00584 void KGrHero::walkTimeDone()
00585 {
00586 if (! started) return;
00587 if (KGrObject::frozen) {
00588 walkFrozen = true;
00589 return;
00590 }
00591
00592 if ((*playfield)[x][y]->whatIam() == BRICK) {
00593 emit caughtHero();
00594 return;
00595 }
00596
00597 if ((y == 1) && (nuggets <= 0)) {
00598 emit leaveLevel();
00599 return;
00600 }
00601
00602 if (status == STANDING)
00603 setNextDir();
00604 if ((status == STANDING) && (nextDir != STAND)) {
00605 if ((standOnEnemy()) && (nextDir == DOWN)) {
00606 emit caughtHero();
00607 return;
00608 }
00609 startWalk();
00610 }
00611 if (status != STANDING) {
00612 switch (direction) {
00613 case UP: walkUp (WALKDELAY); break;
00614 case DOWN: walkDown (WALKDELAY, FALLDELAY); break;
00615 case RIGHT: walkRight (WALKDELAY, FALLDELAY); break;
00616 case LEFT: walkLeft (WALKDELAY, FALLDELAY); break;
00617 default :
00618
00619
00620 if (!canStand() || hangAtPole())
00621 initFall (FALL1, FALLDELAY);
00622 else status = STANDING;
00623 break;
00624 }
00625 herox=x; heroy=y;
00626 if ((relx==0)&&(rely==0)) {
00627 collectNugget();
00628 }
00629 }
00630 if (status == STANDING)
00631 if (!canStand()&&!hangAtPole())
00632 initFall (FALL1, FALLDELAY);
00633 else {
00634 walkTimer->setSingleShot (true);
00635 walkTimer->start ((WALKDELAY * NSPEED) / speed);
00636 }
00637
00638
00639
00641 showFigure();
00642 if (isInEnemy()) {
00643 walkTimer->stop();
00644 emit caughtHero();
00645 }
00646 }
00647
00648 void KGrHero::fallTimeDone()
00649 {
00650 if (! started) return;
00651 if (KGrObject::frozen) {
00652 fallFrozen = true;
00653 return;
00654 }
00655
00656 if (!standOnEnemy()) {
00657 if (walkCounter++ < gameCycle) {
00658 fallTimer->setSingleShot (true);
00659 fallTimer->start ((FALLDELAY * NSPEED) / speed);
00660 rely+=STEP;
00661 absy+=STEP;
00662 }
00663 else {
00664
00665 heroy = ++y;
00666 rely = 0;
00667 absy = y*16;
00668 collectNugget();
00669 if (! (canStand()||hangAtPole())) {
00670 fallTimer->setSingleShot (true);
00671 fallTimer->start ((FALLDELAY * NSPEED) / speed);
00672 walkCounter = 1;
00673 }
00674 else {
00675 status = STANDING;
00676 walkTimer->setSingleShot (true);
00677 walkTimer->start ((WALKDELAY * NSPEED) / speed);
00678 direction = (actualPixmap == FALL2) ? RIGHT : LEFT;
00679 if ((*playfield)[x][y]->whatIam() == POLE)
00680 actualPixmap = (direction == RIGHT)? RIGHTCLIMB1:LEFTCLIMB1;
00681
00682
00683
00684 }
00685 }
00686 showFigure();
00687 }
00688 else {
00689 if (rely == 0) {
00690
00691 status = STANDING;
00692 direction = (actualPixmap == FALL2) ? RIGHT : LEFT;
00693 if ((*playfield)[x][y]->whatIam() == POLE)
00694 actualPixmap = (direction == RIGHT)? RIGHTCLIMB1:LEFTCLIMB1;
00695
00696
00697
00698 walkTimer->setSingleShot (true);
00699 walkTimer->start ((WALKDELAY * NSPEED) / speed);
00700 }
00701 else {
00702
00703 fallTimer->setSingleShot (true);
00704 fallTimer->start ((FALLDELAY * NSPEED) / speed);
00705 }
00706 }
00707 if (status != FALLING) {
00708 emit falling (false);
00709 }
00710 if (isInEnemy() && (! standOnEnemy()))
00711 emit caughtHero();
00712 }
00713
00714
00715 void KGrHero::showFigure() {
00716
00717 heroView->moveHero (absx, absy, actualPixmap);
00718
00719
00720 mem_x = x;
00721 mem_y = y;
00722 mem_relx = relx;
00723 mem_rely = rely;
00724 }
00725
00726 void KGrHero::dig()
00727 {
00728 if (direction == LEFT)
00729 digLeft();
00730 else if (direction == RIGHT)
00731 digRight();
00732 }
00733
00734 void KGrHero::digLeft()
00735 {
00736 int i = 1;
00737 if (status == STANDING)
00738 setNextDir();
00739 if ((status == WALKING) ||
00740 ((status == STANDING) && ((nextDir == LEFT) || (nextDir == RIGHT)))) {
00741 if ((direction == LEFT) && canWalkLeft())
00742 i = 2;
00743 else if ((direction == RIGHT) && canWalkRight())
00744 i = 0;
00745 }
00746 int tileType = (*playfield)[x - i][y + 1]->whatIam();
00747 int tile2Type = (*playfield)[x - i][y]->whatIam();
00748 if ((tileType == BRICK) &&
00749 ((tile2Type == HLADDER) || (tile2Type == FREE) || (tile2Type == HOLE))) {
00750 ((KGrBrick*)(*playfield)[x-i][y+1])->dig();
00751 emit digs();
00752 }
00753 }
00754
00755 void KGrHero::digRight()
00756 {
00757 int i = 1;
00758 if (status == STANDING)
00759 setNextDir();
00760 if ((status == WALKING) ||
00761 ((status == STANDING) && ((nextDir == LEFT) || (nextDir == RIGHT)))) {
00762 if ((direction == LEFT) && canWalkLeft())
00763 i = 0;
00764 else if ((direction == RIGHT) && canWalkRight())
00765 i = 2;
00766 }
00767 int tileType = (*playfield)[x + i][y + 1]->whatIam();
00768 int tile2Type = (*playfield)[x + i][y]->whatIam();
00769 if ((tileType == BRICK) &&
00770 ((tile2Type == HLADDER) || (tile2Type == FREE) || (tile2Type == HOLE))) {
00771 ((KGrBrick*)(*playfield)[x+i][y+1])->dig();
00772 emit digs();
00773 }
00774 }
00775
00776 void KGrHero::setEnemyList (QList<KGrEnemy *> * e)
00777 {
00778 enemies = e;
00779 }
00780
00781 bool KGrHero::standOnEnemy()
00782 {
00783 int c = 0;
00784 int range = enemies->count();
00785 if (range > 0) {
00786 for (KGrEnemy * enemy = enemies->at (c); c < range;) {
00787 enemy = enemies->at (c++);
00788
00789
00790 if ((((absy + 16) == enemy->gety()) ||
00791 ((absy + 12) == enemy->gety())) &&
00792 (((absx - 16) < enemy->getx()) &&
00793 ((absx + 16) > enemy->getx()))) {
00794 if (((absy + 12) == enemy->gety()) &&
00795 (enemy->getStatus() != FALLING)) {
00796 absy = absy - rely;
00797 rely = 0;
00798