📄 players.cpp
字号:
/* BladeMaster 2, a text, rougelike(kinda), arena combat simulation game. Copyright (C) 2002 Blademaster 2 Team, see CREDITS Clone of BladeMaster by Logicom, Inc. Copyright(C) 1990/1993 In no means affliated with the original Blademaster or the original Blademaster creators/programmers. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Useful contact information: Website: blademaster2.sourceforge.net Project page: www.sf.net/projects/blademaster2/ Project Lead (see CREDITS for other members of the developement team) E-Mail: ilswyn@users.sourceforge.net AIM: ilswyn*//* *------------------------------------------------------* | players.cpp players.h | | | | Contain all classes for human and computer players | | and methods of those classes, the classes contain | | all the values and attributes. (stats etc.) | *------------------------------------------------------* */#include <string>#include <cstdlib>#include <ncurses.h>#include <stdlib.h> // need this for exit() - Sairax#include "menus.h"#include "textgfx.h"#include "main.h"#include "arena.h"#include "items.h" // Attack functions, Armor, Weapon classes#include "players.h"#include "shops.h"#include "globals.h"Player::Player(){ obj_pos.setPos_X(getrandom(0, arena_boundary.getPos_X())); obj_pos.setPos_Y(getrandom(0, arena_boundary.getPos_Y())); obj_last_pos = obj_pos; melee_weapon = new Weapon; melee_weapon->setWeaponName("Hands") ; melee_weapon->setMinDmg(1); melee_weapon->setMaxDmg(4); range_weapon = new RangeWeapon; range_weapon->setWeaponName("None"); range_weapon->setMinDmg(1); range_weapon->setMaxDmg(4); current_health = 10; max_health = 10; projectiles = 0; body_armor = new Armor; body_armor->setArmorName("Loin Cloth"); body_armor->setArmorClass(1);}Player::~Player(){}// Takes the numpad # (direction), start position of the player, and the// amount of spaces to move (or attack). Goes the amount of spaces in the// specified direction.Position Player::follow_direction(Position start_pos, int direction, int spaces){ Position newpos; // New position after following direction switch(direction) { case 9: // 9 key = upright newpos.setPos_X( start_pos.getPos_X() + spaces); newpos.setPos_Y( start_pos.getPos_Y() - spaces); break; case 7: // 7 key = upleft newpos.setPos_X(start_pos.getPos_X() - spaces); newpos.setPos_Y(start_pos.getPos_Y() - spaces); break; case 3: // 3 key = downright newpos.setPos_X(start_pos.getPos_X() + spaces); newpos.setPos_Y(start_pos.getPos_Y() + spaces); break; case 1: // 1 key = downleft newpos.setPos_X(start_pos.getPos_X() - spaces); newpos.setPos_Y(start_pos.getPos_Y() + spaces); break; case 8: // 8 key = up newpos.setPos_X(start_pos.getPos_X()); newpos.setPos_Y(start_pos.getPos_Y() - spaces); break; case 2: // 2 key = down newpos.setPos_X(start_pos.getPos_X()); newpos.setPos_Y(start_pos.getPos_Y() + spaces); break; case 6: // 6 key = right newpos.setPos_X(start_pos.getPos_X() + spaces); newpos.setPos_Y(start_pos.getPos_Y()); break; case 4: // 4 key = left newpos.setPos_X(start_pos.getPos_X() - spaces); newpos.setPos_Y(start_pos.getPos_Y()); break; default: // 5 is pass or if any other keys are pressed newpos.setPos_X(start_pos.getPos_X()); newpos.setPos_Y(start_pos.getPos_Y()); break; } return newpos;}void Player::melee_attack(){}// This game is turn based, both the computer and human // players take turns in which they can move once, or perform // an action once (plead for mercy, attack). take_turn() has// to be specialized for human and comp players. No general// actions by just Player are taken.void Player::take_turn(){}// Takes a delta (diffrence between your position and the// destination) and moves that amount. void Player::move_amount(Position delta){ obj_pos.setPos_X(obj_pos.getPos_X() + delta.getPos_X()); obj_pos.setPos_Y(obj_pos.getPos_Y() + delta.getPos_Y()); }// Takes coordinates and moves the player to that specific// spot.void Player::move_to(Position p){ obj_pos = p;}HumanPlayer::HumanPlayer(){ setName("PLAYER X"); obj_char = '@'; draw(); setGoldInHand(300); setGoldInBank(0); setExp(0); setLevel(0); setHealth(10); setProjectiles(0);}HumanPlayer::~HumanPlayer(){}// Directional input by numpad// *** NUMLOCK MUST BE OFF ***// 7 8 9 upleft up upright// \|/ \ | /// 4-5-6 left pass right// /|\ / | \// 1 2 3 downleft down downright// Waits for player to input a numpad key and returns the// numpad # for that direction. This has advantages, generally// it is easier to read these numbers than KEY_NPAGE etc. and// now we can check if the command is not a direction, returning// 0 if that is the case.int HumanPlayer::get_direction(int command){ switch(command) { case KEY_PPAGE: return 9; break; case KEY_HOME: return 7; break; case KEY_NPAGE: return 3; break; case KEY_END: return 1; break; case KEY_LEFT: return 4; break; case KEY_RIGHT: return 6; break; case KEY_UP: return 8; break; case KEY_DOWN: return 2; break; default: // If the input is any other key return 0 (false) return 0; break; }}void HumanPlayer::melee_attack(Position dest_pos){ ArenaObject* victim; // less code, increased speed - Sairax // This whole stuff caused a segmentation fault, fixed it up if ((victim = check_for_obstacle(dest_pos.getPos_X(), dest_pos.getPos_Y())) != NULL) // if is an object { // if is for debuggin // melee_weapon from class Player (melee_weapon does not exist in HumanPlayer (defined in base class) // it is null in this class // fixed it up // -Sairax if (!Player::melee_weapon) { mvwprintw(inventory, 3, 2, "Cannot hit %s (NULL melee_weapon)", victim->getName()); return; } int damage = Player::melee_weapon->do_attack(victim); if (victim->getCurrentHealth() <= 0) // If dead { draw_victory(); current_exp += victim->getExpValue(); if ((current_exp % 100) == 0) { level++; max_health += 10; current_health += 10; } clear(); main_screen_loop(); } else { mvwprintw(inventory, 3, 2, "You hit the %s for %d damage!", victim->getName(), damage); wrefresh(inventory); } } else { mvwprintw(inventory, 2, 2, "There was no one there!"); wrefresh(inventory); }}// Takes two indicators that tell what direction the range attack is in.// For example, if the input was -1, 0 the attack would be all the way to// the left. If it was -1, -1 then the attack would be to the upleftvoid HumanPlayer::range_attack(int x_indicator, int y_indicator){ ArenaObject* victim; // The arrow or bullet or whatever you shoot is auctually a ArenaObject // that travels. ArenaObject* shot; shot->getObjPos().setPos_X( obj_pos.getPos_X() + x_indicator); shot->getObjPos().setPos_Y( obj_pos.getPos_Y() + y_indicator); shot->setObjChar( (char)"/"); // Path in which the projectile is going to be shot int x_path = obj_pos.getPos_X() + x_indicator; int y_path = obj_pos.getPos_Y() + y_indicator; // Returns the victim if the victim is in the path of the shot else it // returns 0. while (in_arena_boundary(shot->getObjPos())) { victim = check_for_obstacle(x_path, y_path); if (victim != NULL && victim->getObjPos().getPos_X() != obj_pos.getPos_X() && victim->getObjPos().getPos_Y() != obj_pos.getPos_Y()) { int damage = Player::range_weapon->do_attack(victim); if (victim->getCurrentHealth() <= 0) // If dead { draw_victory(); current_exp += victim->getExpValue(); if ((current_exp % 100) == 0) { level++; max_health += 10; current_health += 10; } clear(); main_screen_loop(); } else { mvwprintw(inventory, 3, 2, "You shot the %s for %d damage!", victim->getName(), damage); wrefresh(inventory); } while (in_arena_boundary(shot->getObjPos())) { shot->draw(); //shot->obj_pos.x += x_indicator; //shot->obj_pos.y += y_indicator; shot->getObjPos().setPos_X( shot->getObjPos().getPos_X() + x_indicator); shot->getObjPos().setPos_Y( shot->getObjPos().getPos_Y() + y_indicator); } } else { x_path += x_indicator; y_path += y_indicator; } }}void HumanPlayer::plead_for_mercy(){}void HumanPlayer::take_turn(){ int command = get_input(); // Will output the code for the direction if a direction is inputted int direction = get_direction(command); // dest_pos is the destined position to move/attack Position dest_pos = follow_direction(obj_pos, direction, 1); if (direction) { if ((check_for_obstacle(dest_pos.getPos_X(), dest_pos.getPos_Y())) == 0) { move_to(dest_pos); } } else if (!direction) { switch(command) { case 'A': case 'a': { wattron(inventory, A_BOLD); wattron(inventory, COLOR_PAIR(3)); mvwprintw(inventory, 1, 2, "Choose direction of attack: "); wrefresh(inventory); direction = get_direction(get_input()); if (direction) { dest_pos = follow_direction(obj_pos, direction, 1); if ((check_for_obstacle(dest_pos.getPos_X(), dest_pos.getPos_Y())) != 0) { melee_attack(dest_pos); } // Melee attack messes up the colors.. wattron(inventory, COLOR_PAIR(3)); wattron(inventory, A_BOLD); // Clear the Choose direction... mvwprintw(inventory, 1, 2, " "); mvwprintw(inventory, 1, 2, "BATTLE COMMAND:"); wrefresh(inventory); wattroff(inventory, A_BOLD); wattroff(inventory, COLOR_PAIR(3)); } else { wattroff(inventory, A_BOLD); wattroff(inventory, COLOR_PAIR(3)); } } case 'F': case 'f': direction = get_direction(get_input()); if (direction) { dest_pos = follow_direction(obj_pos, direction, 1); // Used for the indicator of range attack int x_diff = (obj_pos.getPos_X() - dest_pos.getPos_X()); int y_diff = (obj_pos.getPos_Y() - dest_pos.getPos_Y()); range_attack(x_diff, y_diff); } break; case 'P': case 'p': break; } } draw();}CompPlayer::CompPlayer(){ setName("PLAYER Y"); obj_char = 'X'; draw();}CompPlayer::~CompPlayer(){}void CompPlayer::melee_attack(ArenaObject* obj){ // if is for debuggin // melee_weapon from class Player (melee_weapon does not exist in HumanPlayer (defined in base class) // it is null in this class // fixed it up // -Sairax if (!Player::melee_weapon) { mvwprintw(inventory, 3, 2, "Compuer cannot hit %s (NULL melee_weapon)", obj->getName()); return; } int damage = Player::melee_weapon->do_attack(obj); if (obj->getCurrentHealth() <= 0) // If dead { draw_loss(); clear(); main_screen_loop(); } else { wattron(inventory, COLOR_PAIR(1)); mvwprintw(inventory, 2, 2, "%s hits you for %d damage!", name.c_str(), damage); wrefresh(inventory); }}void CompPlayer::take_turn(){ ArenaObject* nearest_human; nearest_human = main_arena->get_nearest_type(obj_pos, HUMAN); // Just incase no humans are in the arena (for some reason ;P) ArenaObject* nearest_comp; nearest_comp = main_arena->get_nearest_type(obj_pos, COMP); // Destination, difference between coordinates is the amount of // spaces the comp has left to move go towards nearest human player. int xdest; int ydest; if (nearest_human != 0) { // random stupidness // - Sairax xdest = obj_pos.getPos_X() - nearest_human->getObjPos().getPos_X() + getrandom(-1, 1); ydest = obj_pos.getPos_Y() - nearest_human->getObjPos().getPos_Y() + getrandom(-1, 1); } else if (nearest_comp != 0) { xdest = obj_pos.getPos_X() - nearest_comp->getObjPos().getPos_X(); ydest = obj_pos.getPos_Y() - nearest_comp->getObjPos().getPos_Y(); } else { clear(); main_screen_loop(); } ArenaObject* aobj; // Checks if there is an obstacle in the place ahead, behind, up, // or down.. if not it tracks xdest, and follows to the destination. // if xdest is positive then the comp needs to move backwards (obj_pos.x--) // and if xdest is negative the comp needs to move forwards (obj_pos.x++), // same goes with ydest. aobj = check_for_obstacle(obj_pos.getPos_X()-1, obj_pos.getPos_Y()); if (aobj == 0) { if (xdest > 0) { int tempint = obj_pos.getPos_X(); obj_pos.setPos_X(--tempint); xdest--; } } else melee_attack(aobj); aobj = check_for_obstacle(obj_pos.getPos_X()+1, obj_pos.getPos_Y()); if (aobj == 0) { if (xdest < 0) { int tempint2 = obj_pos.getPos_X(); tempint2 = obj_pos.getPos_X(); obj_pos.setPos_X(++tempint2); xdest++; } } else melee_attack(aobj); aobj = check_for_obstacle(obj_pos.getPos_X(), obj_pos.getPos_Y()-1); if (aobj == 0) { if (ydest > 0) { int temp3 = obj_pos.getPos_Y(); obj_pos.setPos_Y(--temp3); ydest--; } } else melee_attack(aobj); aobj = check_for_obstacle(obj_pos.getPos_X(), obj_pos.getPos_Y()+1); if (aobj == 0) { if (ydest < 0) { int temp4 = obj_pos.getPos_Y(); obj_pos.setPos_Y(++temp4); ydest++; } } else melee_attack(aobj); draw();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -