bool Character::update(float elapsed) { float distance = speed * elapsed; //Distanz zum nächsten Feld berechnen CL_Point nextField = getNextField(moveDirection); CL_Pointf nextFieldCoordinates = getCoordinates(nextField); float distanceToField = abs(position.x - nextFieldCoordinates.x) + abs(position.y - nextFieldCoordinates.y); //Ist die zurückzulegende Distanz größer als die Distanz zum nächsten Feldmittelpunkt //und ist das Feld frei, so muss eine eventuelle Richtungsänderung geprüft werden while (distance > distanceToField && world->getLevel()->isFreeField(nextField)) { //Zum Feldmittelpunkt bewegen move(distanceToField); distance -= distanceToField; currentField = getIndices(nextFieldCoordinates); //wird für erbende Klassen aufgerufen, um Aktionen auf dem Feldmittelpunkt ausführen zu können onFieldCenter(); //Ist eine Richtungsänderung möglich, dann Richtung ändern if(world->getLevel()->isFreeField(getNextField(newDirection))) moveDirection = newDirection; //Distanz zum nächsten Feld berechnen nextField = getNextField(moveDirection); nextFieldCoordinates = getCoordinates(nextField); distanceToField = abs(position.x - nextFieldCoordinates.x) + abs(position.y - nextFieldCoordinates.y); } //Spielfigur weiterbewegen bzw. Richtung ändern if(world->getLevel()->isFreeField(nextField)) move(distance); else if(world->getLevel()->isFreeField(getNextField(newDirection))) moveDirection = newDirection; animationPos += elapsed * animationSpeed; while (animationPos >= animationLength) animationPos -= animationLength; body.set_frame(getAnimationPos()); return true; }
// bestimmt die Richtung anhand eines Ziel-Felds void Character::goTo(const CL_Point& field, bool force) { // Abstand zum Ziel berechnen CL_Vec2<int> delta = currentField - field; CL_Vec2<int> direction; // Richtungen in x und y Richtung bestimmen direction.x = (delta.x != 0) ? 2 + delta.x / abs(delta.x) : 1; direction.y = (delta.y != 0) ? 1 - delta.y / abs(delta.y) : 0; // Richtung mit der größeren Entfernung wählen targetDirection = (abs(delta.x) > abs(delta.y)) ? direction.x : direction.y; targetField = field; newDirection = targetDirection; // umliegende Felder abrufen CL_Point moveField = getNextField(moveDirection); CL_Point rightField = getNextField((moveDirection + 1) % 4); CL_Point leftField = getNextField((moveDirection - 1) % 4); const Level& level = world->getLevel(); // wenn umliegende Felder (vorne, links, rechts) nicht frei if (!level.isFreeField(moveField) && !level.isFreeField(leftField) && !level.isFreeField(rightField)) // umdrehen newDirection = (moveDirection + 2) % 4; // wenn Feld in gewünschter Richtung nicht frei else if (!level.isFreeField(getNextField(newDirection)) || (abs(newDirection - moveDirection) == 2 && !force)) { // Richtung mit der kleineren Entfernung wählen newDirection = (newDirection == direction.x) ? direction.y : direction.x; // solange Feld in gewünschter Richtung nicht frei while (!level.isFreeField(getNextField(newDirection)) || (abs(newDirection - moveDirection) == 2 && !force)) // im Uhrzeigersinn drehen newDirection = (newDirection + 1) % 4; } }
int moveInhabitants() { for(int iinhabitant = 0; iinhabitant < g_inhabitantCount; iinhabitant++) { inhabitant* cSnake = &g_inhabitants[iinhabitant]; //if the snakes direction is null too, use a random one if(cSnake->direction == 0 && iinhabitant != 0 && (iinhabitant != 1 || !g_confTwoPlayer)) { cSnake->direction = getRandomDirection(); } int nextCollision; int actCollision; point nextPosition = getNextField(cSnake->direction, cSnake->body[cSnake->length-1]); actCollision = collisionDetection(cSnake->body[cSnake->length-1]); nextCollision = collisionDetection(nextPosition); if ((nextCollision == EMPTY || nextCollision == FRUIT)) { // && cSnake->length < MAX_INHABITANT_LENGTH){ cSnake->body[cSnake->length] = nextPosition; } else { // snake dead ! cSnake->alive = false; } if (actCollision != FRUIT) { int count; for(count = 0; count < cSnake->length; count++) { cSnake->body[count] = cSnake->body[count + 1]; } if(cSnake->alive && rand() % POINTS_LEN_ROUNDS == 0) { //for every 10 length -> get one point per round cSnake->points = cSnake->points + (cSnake->length/POINTS_LEN); } } else { reInitFruit(cSnake->body[cSnake->length-1]); if(cSnake->length < MAX_INHABITANT_LENGTH) { cSnake->length++; } //get points for eating fruit! cSnake->points = cSnake->points + POINTS_FRUIT; } if(cSnake->points > g_confWin) { return 0; } } return 1; }
void initWalls(int wallCount) { int count; int innerCount; int wallLength; for(count = 0 ; count < wallCount; count++) { wallLength = getRandomWallLength(); g_walls[count].parts[0] = getRandomCoordinateInField(); g_walls[count].colorpair = COLOR_PAIR_WALL; g_walls[count].length = wallLength; int direction = getRandomDirection(); for (innerCount = 1; innerCount < wallLength; innerCount++) { g_walls[count].parts[innerCount] = getNextField(direction, g_walls[count].parts[innerCount - 1]); } g_wallCount++; } }
void drawInhabitants() { //loop through all inhabitants (snakes) for(int iinhabitant = 0; iinhabitant < g_inhabitantCount; iinhabitant++) { inhabitant cinhabitant = g_inhabitants[iinhabitant]; if(cinhabitant.alive) { attron(COLOR_PAIR(cinhabitant.colorpair)); //loop through all parts of the snake //count backwards because the snake parts are saved in the array from tail to head for(int ipart = 0; ipart < cinhabitant.length; ipart++) { point cpart = cinhabitant.body[ipart]; if(ipart == cinhabitant.length - 1) { //draw head element mvaddch(cpart.y, cpart.x, ACS_DIAMOND); } else if (ipart == 0) { point cLastPart = cinhabitant.body[ipart+1]; if(point_equals(cLastPart, getNextField(DIRECTION_UP, cpart)) || point_equals(cLastPart, getNextField(DIRECTION_DOWN, cpart))) { mvaddch(cpart.y, cpart.x, ACS_VLINE); } else { mvaddch(cpart.y, cpart.x, ACS_HLINE); } } else { //draw body element point cNextPart = cinhabitant.body[ipart-1]; point cLastPart = cinhabitant.body[ipart+1]; //mvaddch(cpart.y, cpart.x, '~'); // draw top to down line if((point_equals(cLastPart, getNextField(DIRECTION_UP, cpart)) || point_equals(cLastPart, getNextField(DIRECTION_DOWN, cpart))) && (point_equals(cNextPart, getNextField(DIRECTION_UP, cpart)) || point_equals(cNextPart, getNextField(DIRECTION_DOWN, cpart)))) { mvaddch(cpart.y, cpart.x, ACS_VLINE); // draw left right element } else if((point_equals(cLastPart, getNextField(DIRECTION_LEFT, cpart)) || point_equals(cLastPart, getNextField(DIRECTION_RIGHT, cpart))) && (point_equals(cNextPart, getNextField(DIRECTION_LEFT, cpart)) || point_equals(cNextPart, getNextField(DIRECTION_RIGHT, cpart)))) { mvaddch(cpart.y, cpart.x, ACS_HLINE); // draw top left element } else if((point_equals(cLastPart, getNextField(DIRECTION_UP, cpart)) || point_equals(cLastPart, getNextField(DIRECTION_LEFT, cpart))) && (point_equals(cNextPart, getNextField(DIRECTION_UP, cpart)) || point_equals(cNextPart, getNextField(DIRECTION_LEFT, cpart)))) { mvaddch(cpart.y, cpart.x, ACS_LRCORNER); // drwa top right element } else if((point_equals(cLastPart, getNextField(DIRECTION_UP, cpart)) || point_equals(cLastPart, getNextField(DIRECTION_RIGHT, cpart))) && (point_equals(cNextPart, getNextField(DIRECTION_UP, cpart)) || point_equals(cNextPart, getNextField(DIRECTION_RIGHT, cpart)))) { mvaddch(cpart.y, cpart.x, ACS_LLCORNER); // draw down left } else if((point_equals(cLastPart, getNextField(DIRECTION_DOWN, cpart)) || point_equals(cLastPart, getNextField(DIRECTION_LEFT, cpart))) && (point_equals(cNextPart, getNextField(DIRECTION_DOWN, cpart)) || point_equals(cNextPart, getNextField(DIRECTION_LEFT, cpart)))) { mvaddch(cpart.y, cpart.x, ACS_URCORNER); // draw down right } else if((point_equals(cLastPart, getNextField(DIRECTION_DOWN, cpart)) || point_equals(cLastPart, getNextField(DIRECTION_RIGHT, cpart))) && (point_equals(cNextPart, getNextField(DIRECTION_DOWN, cpart)) || point_equals(cNextPart, getNextField(DIRECTION_RIGHT, cpart)))) { mvaddch(cpart.y, cpart.x, ACS_ULCORNER); // draw } } } attroff(COLOR_PAIR(cinhabitant.colorpair)); //end coloring } //draw points on bottom mvprintw(iinhabitant, g_confX+1, "Player %d: %d Punkte ", iinhabitant, cinhabitant.points); } }
bool Character::update(float elapsed) { // zurückzulegende Distanz berechnen float distance = speed * elapsed; // aktuelle Animationsposition berechnen und setzen animationPos += elapsed * animationSpeed; while (animationPos >= animationLength) animationPos -= animationLength; body.set_frame(getAnimationPos()); const Level& level = world->getLevel(); // nächstes Feld in Bewegungsrichtung abrufen CL_Point nextField = getNextField(moveDirection); // wenn Richtung geändert werden soll und nächste Feld nicht frei ist if (moveDirection != newDirection && !level.isFreeField(nextField)) { // Richtung ändern moveDirection = newDirection; // nächstes Feld in neuer Richtung abrufen nextField = getNextField(moveDirection); } CL_Pointf coordinates = level.getCoordinates(nextField); // Distanz zum Mittelpunkt des nächsten Feldes berechnen float distanceToField = abs(position.x - coordinates.x) + abs(position.y - coordinates.y); // solange nächstes Feld frei und zurückzulegende Distanz größer als Distanz zum Mittelpunkt while (level.isFreeField(nextField) && distance > distanceToField) { // zum Mittelpunkt des nächsten Feldes gehen move(distanceToField); // aktuelles Feld ändern currentField = nextField; // Benachrichtigung für Subklassen (zur Pfadfindung) arrivedAtField(); // zurückzulegende Distanz verringern distance -= distanceToField; // wenn nächstes Feld in gewünschter Richtung if (level.isFreeField(getNextField(newDirection))) // zur gewünschten Richtung moveDirection = newDirection; // nächstes Feld abrufen nextField = getNextField(moveDirection); // Distanz zum nächsten Feld berechnen coordinates = level.getCoordinates(nextField); distanceToField = abs(position.x - coordinates.x) + abs(position.y - coordinates.y); } // wenn nächstes Feld frei if (level.isFreeField(nextField)) // Restdistanz in Bewegungsrichtung zurücklegen move(distance); return true; }