![]() |
Kukatz 3D
0.1
Török Attila szakdolgozata
|
00001 /* 00002 * kukac.cpp - Kukatz 3D 00003 * Copyright (c) 2010, 2011 - TÖRÖK Attila (torokati44@gmail.com) 00004 * 00005 * This software is provided 'as-is', without any express or implied 00006 * warranty. In no event will the authors be held liable for any damages 00007 * arising from the use of this software. 00008 * 00009 * Permission is granted to anyone to use this software for any purpose, 00010 * including commercial applications, and to alter it and redistribute it 00011 * freely, subject to the following restrictions: 00012 * 00013 * 1. The origin of this software must not be misrepresented; you must not 00014 * claim that you wrote the original software. If you use this software 00015 * in a product, an acknowledgment in the product documentation would be 00016 * appreciated but is not required. 00017 * 00018 * 2. Altered source versions must be plainly marked as such, and must not be 00019 * misrepresented as being the original software. 00020 * 00021 * 3. This notice may not be removed or altered from any source 00022 * distribution. 00023 */ 00024 00025 #include "kukac.hpp" 00026 00027 #include "obstacle.hpp" 00028 #include "misc.hpp" 00029 #include "edible.hpp" 00030 #include "game.hpp" 00031 #include "resourcemanager.hpp" 00032 #include "staticobject.hpp" 00033 #include "animatedobject.hpp" 00034 00035 Kukac::Kukac(Grid& g, unsigned int t, const sf::Vector3i& start, 00036 const sf::Vector3i& dir, const sf::Vector3i& u, unsigned int l = 4, 00037 float startingspeed = 1.f): 00038 step_time(0), ratio(0), speed((startingspeed < 10.0f)?startingspeed:10.0f), 00039 alive(true), growth(l - 2), moved(false), turned(false), reversed(false), 00040 should_reverse(false), grid(g), type(t), direction(dir), next_direction(dir), 00041 upward(u), next_upward(u) 00042 { 00043 head = new body_part_t(start); 00044 tail = new body_part_t(start - direction); 00045 00046 head->backward = tail; 00047 tail->forward = head; 00048 00049 switch (type % 3) 00050 { 00051 case 0: 00052 { 00053 head->object = new StaticObject("HEAD_SOLDIER", "ATLAS_1"); 00054 } 00055 break; 00056 case 1: 00057 { 00058 head->object = new StaticObject("HEAD_KID", "ATLAS_1"); 00059 } 00060 break; 00061 case 2: 00062 { 00063 head->object = new AnimatedObject("HEAD_PACMAN", "ATLAS_1"); 00064 } 00065 break; 00066 } 00067 00068 neck_forward = new AnimatedObject("NECK_FORWARD", "ATLAS_1"); 00069 neck_turn = new AnimatedObject("NECK_TURN", "ATLAS_1"); 00070 00071 head->object->set_position(start); 00072 00073 sf::Vector3i offset(20, 20, 20); 00074 00075 grid(start + offset).type = 00076 grid(start - dir + offset).type = 00077 grid(start + dir + offset).type = GridCell::KUKAC; 00078 00079 grid(start + offset).k_ptr = 00080 grid(start - dir + offset).k_ptr = 00081 grid(start + dir + offset).k_ptr = 00082 grid(start + dir + dir + offset).fk_ptr = 00083 this; 00084 00085 00086 head->object->set_x_axis(direction); 00087 head->object->set_z_axis(upward); 00088 head->object->set_y_axis(); 00089 00090 neck_forward->set_position(start); 00091 neck_forward->set_x_axis(direction); 00092 neck_forward->set_z_axis(upward); 00093 neck_forward->set_y_axis(); 00094 00095 neck_turn->set_position(start); 00096 neck_turn->set_x_axis(direction); 00097 neck_turn->set_z_axis(upward); 00098 neck_turn->set_y_axis(); 00099 00100 tail_to_straight = new AnimatedObject("TAIL_TO_STRAIGHT", "ATLAS_1"); 00101 tail_to_corner = new AnimatedObject("TAIL_TO_CORNER", "ATLAS_1"); 00102 00103 tail_grow_straight = new AnimatedObject("TAIL_GROW_STRAIGHT", "ATLAS_1"); 00104 tail_grow_corner = new AnimatedObject("TAIL_GROW_CORNER", "ATLAS_1"); 00105 00106 00107 tail->object = tail_grow_straight; 00108 tail->object->set_position(start - direction); 00109 00110 tail->object->set_x_axis(direction); 00111 tail->object->set_z_axis(upward); 00112 tail->object->set_y_axis(); 00113 } 00114 00115 00116 Kukac::body_part_t::body_part_t( 00117 sf::Vector3i p, 00118 body_part_t* b, body_part_t* f): 00119 pos(p), backward(b), forward(f) 00120 { 00121 00122 } 00123 00124 Kukac::body_part_t::body_part_t(const Kukac::body_part_t& x): 00125 pos(x.pos), backward(x.backward), forward(x.forward) 00126 { 00127 00128 } 00129 00130 00131 // b: backward, f: forward, nf: next forward 00132 AnimatedObject* Kukac::get_anim(const sf::Vector3i b, const sf::Vector3i& f, 00133 const sf::Vector3i& nf) 00134 { 00135 AnimatedObject* ret; 00136 00137 if (crossprod(b, f) == sf::Vector3i(0, 0, 0)) 00138 { 00139 // straight 00140 //std::cout << "straight\n"; 00141 if (crossprod(f, nf) == sf::Vector3i(0, 0, 0)) 00142 { 00143 //straight to straight 00144 //std::cout << "straight to straight\n"; 00145 ret = new AnimatedObject("STRAIGHT_TO_STRAIGHT", "ATLAS_1"); 00146 00147 ret->set_x_axis(f); 00148 ret->set_z_axis(f.y, f.z, f.x); 00149 ret->set_y_axis(); 00150 } 00151 else 00152 { 00153 // straight to corner 00154 //std::cout << "straight to corner\n"; 00155 ret = new AnimatedObject("STRAIGHT_TO_CORNER", "ATLAS_1"); 00156 00157 ret->set_x_axis(-b); 00158 ret->set_z_axis(nf); 00159 ret->set_y_axis(); 00160 } 00161 } 00162 else 00163 { 00164 //std::cout << "corner\n"; 00165 // corner 00166 if (crossprod(f, nf) == sf::Vector3i(0, 0, 0)) 00167 { 00168 // corner to straight 00169 //std::cout << "corner to straight\n"; 00170 ret = new AnimatedObject("CORNER_TO_STRAIGHT", "ATLAS_1"); 00171 } 00172 else 00173 { 00174 // corner to corner 00175 //std::cout << "corner to corner\n"; 00176 if (nf == (-b)) 00177 { 00178 // 0 00179 //std::cout << "0\n"; 00180 ret = new AnimatedObject("CORNER_TO_CORNER_0", "ATLAS_1"); 00181 } 00182 else 00183 { 00184 if ((nf - b) == sf::Vector3i(0, 0, 0)) 00185 { 00186 // 180 00187 //std::cout << "180\n"; 00188 ret = new AnimatedObject("CORNER_TO_CORNER_180", "ATLAS_1"); 00189 } 00190 else 00191 { 00192 if (crossprod(b, f) == nf) 00193 { 00194 // 90 00195 //std::cout << "90\n"; 00196 ret = new AnimatedObject("CORNER_TO_CORNER_90", "ATLAS_1"); 00197 } 00198 else 00199 { 00200 // 270 00201 //std::cout << "270\n"; 00202 ret = new AnimatedObject("CORNER_TO_CORNER_270", "ATLAS_1"); 00203 } 00204 } 00205 } 00206 } 00207 00208 ret->set_x_axis(-b); 00209 ret->set_z_axis(f); 00210 ret->set_y_axis(); 00211 } 00212 00213 return ret; 00214 } 00215 00216 void Kukac::update(float dt) 00217 { 00218 // itt tart épp a két ugrás közt 00219 step_time += dt; 00220 00221 moved = false; 00222 00223 if (!alive) 00224 { 00225 if (step_time > 10) 00226 { 00227 step_time = 10; 00228 } 00229 return; 00230 } 00231 00232 ratio = step_time * speed; // nos... ez JÓ :D és [ 0 <= ratio <= 1 ] tutira oké, csak matek 00233 00234 00235 if ((1.0f / speed) <= step_time) 00236 { 00237 step(); 00238 if (alive) 00239 { 00240 step_time -= (1.f / speed); 00241 ratio -= 1; 00242 } 00243 } 00244 00245 head->object->set_position(itof3(head->pos) + itof3(direction) * ratio); 00246 00247 for(body_part_t* i = tail; i; i = i->forward) 00248 { 00249 AnimatedObject* ani = dynamic_cast< AnimatedObject* >(i->object); 00250 if (ani) 00251 { 00252 ani->set_time(ratio); 00253 } 00254 } 00255 00256 neck_forward->set_time(ratio); 00257 neck_turn->set_time(ratio); 00258 00259 return; 00260 } 00261 00262 void Kukac::render() 00263 { 00264 if (alive) 00265 { 00266 reset_material(); 00267 } 00268 else 00269 { 00270 set_material(sf::Color(255/step_time, 255/step_time, 255/step_time)); 00271 } 00272 00273 //cam.render(); 00274 00275 for (body_part_t* i = head; i; i = i->backward) 00276 { 00277 i->object->render(); 00278 } 00279 00280 if (direction == (head->pos - head->backward->pos)) 00281 { 00282 neck_forward->render(); 00283 } 00284 else 00285 { 00286 neck_turn->render(); 00287 } 00288 00289 reset_material(); 00290 } 00291 00292 void Kukac::step() 00293 { 00294 if (alive) 00295 { 00296 sf::Vector3i offset(20, 20, 20); 00297 00298 if (grid(head->pos + direction + next_direction + offset).fk_ptr == this) 00299 { 00300 grid(head->pos + direction + next_direction + offset).fk_ptr = 0; 00301 } 00302 00303 body_part_t* old_head = head; 00304 body_part_t* new_head = new body_part_t(head->pos + direction); 00305 00306 direction = next_direction; 00307 upward = next_upward; 00308 00309 old_head->forward = new_head; 00310 new_head->backward = old_head; 00311 00312 head = new_head; 00313 head->object = old_head->object; // NO NEED TO DELETE 00314 00315 head->object->set_position(head->pos); 00316 00317 head->object->set_x_axis(direction); 00318 head->object->set_z_axis(upward); 00319 head->object->set_y_axis(); 00320 00321 00322 neck_forward->set_position(head->pos); 00323 00324 neck_forward->set_x_axis(direction); 00325 neck_forward->set_z_axis(upward); 00326 neck_forward->set_y_axis(); 00327 00328 00329 neck_turn->set_position(head->pos); 00330 00331 neck_turn->set_x_axis(head->pos - head->backward->pos); 00332 neck_turn->set_y_axis(direction); 00333 neck_turn->set_z_axis(); 00334 00335 old_head->object = get_anim(old_head->backward->pos - old_head->pos, 00336 new_head->pos - old_head->pos, direction); 00337 00338 old_head->object->set_position(old_head->pos); 00339 00340 if (growth > 0) 00341 { 00342 --growth; 00343 00344 if (growth == 0) 00345 { 00346 if (crossprod(tail->pos - tail->forward->pos, 00347 tail->forward->forward->pos - tail->forward->pos) == 00348 sf::Vector3i(0, 0, 0)) 00349 { 00350 tail->object = tail_to_straight; 00351 00352 sf::Vector3i v = tail->forward->pos - tail->pos; 00353 tail->object->set_z_axis(v.y, v.z, v.x); 00354 } 00355 else 00356 { 00357 tail->object = tail_to_corner; 00358 00359 tail->object->set_z_axis( 00360 tail->forward->forward->pos - tail->forward->pos); 00361 } 00362 00363 tail->object->set_x_axis(tail->forward->pos - tail->pos); 00364 tail->object->set_y_axis(); 00365 tail->object->set_position(tail->pos); 00366 } 00367 } 00368 else 00369 { 00370 grid(tail->pos + offset).type = GridCell::FREE; 00371 grid(tail->pos + offset).k_ptr = 0; 00372 00373 body_part_t* old_tail = tail; 00374 body_part_t* new_tail = tail->forward; 00375 00376 new_tail->backward = 0; 00377 00378 delete new_tail->object; 00379 00380 if (crossprod(new_tail->pos - new_tail->forward->pos, 00381 new_tail->forward->forward->pos - new_tail->forward->pos) == 00382 sf::Vector3i(0, 0, 0)) 00383 { 00384 new_tail->object = tail_to_straight; 00385 00386 sf::Vector3i v = new_tail->forward->pos - new_tail->pos; 00387 new_tail->object->set_z_axis(v.y, v.z, v.x); 00388 } 00389 else 00390 { 00391 new_tail->object = tail_to_corner; 00392 00393 new_tail->object->set_z_axis( 00394 new_tail->forward->forward->pos - new_tail->forward->pos); 00395 } 00396 00397 new_tail->object->set_x_axis(new_tail->forward->pos - new_tail->pos); 00398 new_tail->object->set_y_axis(); 00399 new_tail->object->set_position(new_tail->pos); 00400 00401 tail = new_tail; 00402 00403 delete old_tail; 00404 } 00405 00406 // must be in the end 00407 grid(head->pos + offset).type = GridCell::KUKAC; 00408 grid(head->pos + offset).k_ptr = this; 00409 00410 turned = false; 00411 moved = true; 00412 00413 00414 // -------- REVERSING IF NEEDED -------- 00415 00416 if (should_reverse) 00417 { 00418 body_part_t* tmp; 00419 00420 for (body_part_t* i = head; i; i = i->forward) // forward is the new backward 00421 { 00422 tmp = i->backward; 00423 i->backward = i->forward; 00424 i->forward = tmp; 00425 } 00426 00427 tmp = head; 00428 head = tail; 00429 tail = tmp; 00430 00431 00432 GameObject* tmp2 = head->object; 00433 head->object = tail->object; 00434 tail->object = tmp2; 00435 00436 next_direction = direction = head->pos - head->backward->pos; 00437 00438 if (crossprod(direction, upward) == sf::Vector3i(0, 0, 0)) 00439 { 00440 upward.x = direction.y; 00441 upward.y = direction.z; // is this hacky? 00442 upward.z = direction.x; 00443 } 00444 00445 // TAIL 00446 00447 if (crossprod(tail->pos - tail->forward->pos, 00448 tail->forward->forward->pos - tail->forward->pos) == 00449 sf::Vector3i(0, 0, 0)) 00450 { 00451 if (growth > 0) 00452 { 00453 tail->object = tail_grow_straight; 00454 } 00455 else 00456 { 00457 tail->object = tail_to_straight; 00458 } 00459 00460 sf::Vector3i v = tail->forward->pos - tail->pos; 00461 tail->object->set_z_axis(v.y, v.z, v.x); 00462 } 00463 else 00464 { 00465 if (growth > 0) 00466 { 00467 tail->object = tail_grow_corner; 00468 } 00469 else 00470 { 00471 tail->object = tail_to_corner; 00472 } 00473 00474 tail->object->set_z_axis( 00475 tail->forward->forward->pos - tail->forward->pos); 00476 } 00477 00478 tail->object->set_x_axis(tail->forward->pos - tail->pos); 00479 tail->object->set_y_axis(); 00480 tail->object->set_position(tail->pos); 00481 00482 // neck: 00483 tmp = head->backward; // TMP IS NECK 00484 00485 delete tmp->object; 00486 tmp->object = get_anim(tmp->backward->pos - tmp->pos, head->pos - tmp->pos, direction); 00487 tmp->object->set_position(tmp->pos); 00488 00489 // we must skip the head, the tail, and the "neck" 00490 for (body_part_t* i = tail->forward; i != tmp; i = i->forward) 00491 { 00492 delete i->object; 00493 i->object = get_anim(i->backward->pos - i->pos, i->forward->pos - i->pos, 00494 i->forward->forward->pos - i->forward->pos); 00495 i->object->set_position(i->pos); 00496 } 00497 00498 head->object->set_position(itof3(head->pos) + itof3(direction) * ratio); 00499 00500 for(body_part_t* i = tail; i; i = i->forward) 00501 { 00502 AnimatedObject* ani = dynamic_cast< AnimatedObject* > (i->object); 00503 if (ani) 00504 { 00505 ani->set_time(ratio); 00506 } 00507 } 00508 00509 should_reverse = false; 00510 reversed = true; 00511 00512 if (!can_move_to(head->pos + direction)) 00513 { 00514 bool u = false; 00515 bool l = false; 00516 bool d = false; 00517 bool r = false; 00518 00519 bool OK = false; 00520 00521 turned = false; 00522 00523 while (!(OK || (u && l && d && r))) 00524 { 00525 switch (sf::Randomizer::Random(0, 3)) 00526 { 00527 case 0: 00528 { 00529 u = true; 00530 if (can_move_to(head->pos + upward)) 00531 { 00532 turn_up(); 00533 OK = true; 00534 } 00535 } 00536 break; 00537 case 1: 00538 { 00539 l = true; 00540 if (can_move_to(head->pos - crossprod(direction, upward))) 00541 { 00542 turn_left(); 00543 OK = true; 00544 } 00545 } 00546 break; 00547 case 2: 00548 { 00549 d = true; 00550 if (can_move_to(head->pos - upward)) 00551 { 00552 turn_down(); 00553 OK = true; 00554 } 00555 } 00556 break; 00557 case 3: 00558 { 00559 r = true; 00560 if (can_move_to(head->pos + crossprod(direction, upward))) 00561 { 00562 turn_right(); 00563 OK = true; 00564 } 00565 } 00566 break; 00567 } 00568 } 00569 00570 turned = false; 00571 00572 upward = next_upward; 00573 direction = next_direction; // it is intentional! 00574 } 00575 00576 if (crossprod(next_direction, next_upward) == sf::Vector3i(0, 0, 0)) 00577 { 00578 next_upward.x = next_direction.y; 00579 next_upward.y = next_direction.z; // is this hacky? 00580 next_upward.z = next_direction.x; 00581 upward = next_upward; 00582 } 00583 00584 head->object->set_x_axis(direction); 00585 head->object->set_z_axis(upward); 00586 head->object->set_y_axis(); 00587 } 00588 else 00589 { 00590 reversed = false; 00591 } 00592 00593 // -------- DYING IF MUST -------- 00594 00595 sf::Vector3i next_headpos = head->pos + direction; 00596 00597 if (can_move_to(next_headpos)) 00598 { 00599 grid(next_headpos + offset).type = GridCell::KUKAC; 00600 grid(next_headpos + offset).k_ptr = this; 00601 00602 if (can_move_to(head->pos + direction + next_direction)) 00603 { 00604 grid(head->pos + direction + next_direction + offset).fk_ptr = this; 00605 } 00606 } 00607 else 00608 { 00609 die(); // looks like something else after a few days of coding php... 00610 } 00611 } 00612 } 00613 00614 void Kukac::reverse() 00615 { 00616 if (alive) 00617 { 00618 should_reverse = !should_reverse; // simply true is not good enough! really 00619 } 00620 } 00621 00622 void Kukac::grow(unsigned int n) 00623 { 00624 if (n > 0) 00625 { 00626 growth += n; 00627 00628 if (crossprod(tail->pos - tail->forward->pos, 00629 tail->forward->forward->pos - tail->forward->pos) == 00630 sf::Vector3i(0, 0, 0)) 00631 { 00632 tail->object = tail_grow_straight; 00633 00634 sf::Vector3i v = tail->forward->pos - tail->pos; 00635 tail->object->set_z_axis(v.y, v.z, v.x); 00636 } 00637 else 00638 { 00639 tail->object = tail_grow_corner; 00640 00641 tail->object->set_z_axis( 00642 tail->forward->forward->pos - tail->forward->pos); 00643 } 00644 00645 tail->object->set_x_axis(tail->forward->pos - tail->pos); 00646 tail->object->set_y_axis(); 00647 tail->object->set_position(tail->pos); 00648 } 00649 } 00650 00651 void Kukac::accelerate(float s) 00652 { 00653 speed += s; 00654 if (speed > 10.0f) 00655 { 00656 speed = 10.0f; 00657 } 00658 } 00659 00660 const float& Kukac::get_ratio() const 00661 { 00662 return ratio; 00663 } 00664 00665 const float& Kukac::get_speed() const 00666 { 00667 return speed; 00668 } 00669 00670 unsigned int Kukac::get_length() const 00671 { 00672 unsigned int ret = 0; 00673 00674 for (body_part_t* part = tail; part; part = part->forward, ++ret) 00675 { 00676 00677 } 00678 return ret; 00679 } 00680 00681 const unsigned int& Kukac::get_growth() const 00682 { 00683 return growth; 00684 } 00685 00686 const bool& Kukac::did_move() const 00687 { 00688 return moved; 00689 } 00690 00691 const bool& Kukac::did_reverse() const 00692 { 00693 return reversed; 00694 } 00695 00696 const bool& Kukac::is_alive() const 00697 { 00698 return alive; 00699 } 00700 00701 void Kukac::die() 00702 { 00703 ratio = 0; 00704 step_time = 1; 00705 alive = false; 00706 } 00707 00708 void Kukac::turn_left() 00709 { 00710 if (!turned) 00711 { 00712 if (grid(head->pos + direction + next_direction + sf::Vector3i(20, 20, 20)).fk_ptr == this) 00713 { 00714 grid(head->pos + direction + next_direction + sf::Vector3i(20, 20, 20)).fk_ptr = 0; 00715 } 00716 00717 next_direction = crossprod(upward, direction); 00718 turned = true; 00719 00720 grid(head->pos + direction + next_direction + sf::Vector3i(20, 20, 20)).fk_ptr = this; 00721 } 00722 } 00723 00724 void Kukac::turn_right() 00725 { 00726 if (!turned) 00727 { 00728 if (grid(head->pos + direction + next_direction + sf::Vector3i(20, 20, 20)).fk_ptr == this) 00729 { 00730 grid(head->pos + direction + next_direction + sf::Vector3i(20, 20, 20)).fk_ptr = 0; 00731 } 00732 00733 next_direction = crossprod(direction, upward); 00734 turned = true; 00735 00736 grid(head->pos + direction + next_direction + sf::Vector3i(20, 20, 20)).fk_ptr = this; 00737 } 00738 } 00739 00740 void Kukac::turn_up() 00741 { 00742 if (!turned) 00743 { 00744 if (grid(head->pos + direction + next_direction + sf::Vector3i(20, 20, 20)).fk_ptr == this) 00745 { 00746 grid(head->pos + direction + next_direction + sf::Vector3i(20, 20, 20)).fk_ptr = 0; 00747 } 00748 00749 next_direction = upward; 00750 next_upward = -direction; 00751 turned = true; 00752 00753 grid(head->pos + direction + next_direction + sf::Vector3i(20, 20, 20)).fk_ptr = this; 00754 } 00755 } 00756 00757 void Kukac::turn_down() 00758 { 00759 if (!turned) 00760 { 00761 if (grid(head->pos + direction + next_direction + sf::Vector3i(20, 20, 20)).fk_ptr == this) 00762 { 00763 grid(head->pos + direction + next_direction + sf::Vector3i(20, 20, 20)).fk_ptr = 0; 00764 } 00765 00766 next_direction = -upward; 00767 next_upward = direction; 00768 turned = true; 00769 00770 grid(head->pos + direction + next_direction + sf::Vector3i(20, 20, 20)).fk_ptr = this; 00771 } 00772 } 00773 00774 bool Kukac::can_move_to(const sf::Vector3i& v) 00775 { 00776 if (v.x < -20 || v.x > 20 || v.y < -20 || v.y > 20 || v.z < -20 || v.z > 20) 00777 { 00778 return false; 00779 } 00780 00781 sf::Vector3i o(20, 20, 20); 00782 00783 return 00784 ( 00785 (grid(v + o).type == GridCell::FREE) 00786 || (grid(v + o).type == GridCell::EDIBLE) 00787 || 00788 ( 00789 (grid(v + o).type == GridCell::KUKAC) 00790 && (grid(v + o).k_ptr == this) 00791 && (v == tail->pos) 00792 && (growth == 0) 00793 ) 00794 ) && ((grid(v + o).fk_ptr == 0) || (grid(v + o).fk_ptr == this)); 00795 } 00796 00797 Kukac::~Kukac() 00798 { 00799 for (body_part_t* i = tail->forward; i; i = i->forward) // tail is separated 00800 { 00801 delete i->object; 00802 delete i; 00803 } 00804 00805 delete neck_forward; 00806 delete neck_turn; 00807 00808 delete tail; 00809 00810 delete tail_to_straight; 00811 delete tail_to_corner; 00812 delete tail_grow_straight; 00813 delete tail_grow_corner; 00814 }