Added random weapons for enemies, also added setFirst/SecondWeapon to Character.
This commit is contained in:
parent
b45dd01c72
commit
7bb08ed447
14 changed files with 124 additions and 31 deletions
|
@ -5,6 +5,4 @@ health: 100
|
|||
speed: 100
|
||||
radius: 25
|
||||
size: [50, 50]
|
||||
first_weapon: pistol.yaml
|
||||
second_weapon: knife.yaml
|
||||
faction: 1
|
|
@ -5,6 +5,4 @@ health: 100
|
|||
speed: 100
|
||||
radius: 25
|
||||
size: [50, 50]
|
||||
first_weapon: pistol.yaml
|
||||
second_weapon: knife.yaml
|
||||
faction: 0
|
|
@ -55,8 +55,8 @@ Game::Game(tgui::Window& window) :
|
|||
}
|
||||
|
||||
void Game::initPlayer() {
|
||||
mPlayer = std::shared_ptr < Player
|
||||
> (new Player(mWorld, mPathfinder, mGenerator.getPlayerSpawn()));
|
||||
mPlayer = std::shared_ptr<Player>(new Player(mWorld, mPathfinder,
|
||||
mGenerator.getPlayerSpawn()));
|
||||
mPlayer->setLeftGadget(std::shared_ptr < Gadget > (new Heal()));
|
||||
mPlayer->setRightGadget(std::shared_ptr < Gadget > (new Shield()));
|
||||
mWorld.insertCharacter(mPlayer);
|
||||
|
|
|
@ -65,10 +65,11 @@ Generator::generateCurrentAreaIfNeeded(const Vector2f& playerPosition) {
|
|||
Vector2i(GENERATE_AREA_SIZE, GENERATE_AREA_SIZE) / 2,
|
||||
Vector2i(GENERATE_AREA_SIZE, GENERATE_AREA_SIZE));
|
||||
generateTiles(area);
|
||||
for (const auto& enemyPosition : getEnemySpawns(area)) {
|
||||
float distance = thor::length(enemyPosition - playerPosition);
|
||||
for (const auto& enemy : getEnemySpawns(area)) {
|
||||
float distance = thor::length(enemy.first - playerPosition);
|
||||
if (distance > Character::VISION_DISTANCE)
|
||||
mWorld.insertCharacter(std::shared_ptr<Enemy>(new Enemy(mWorld, mPathfinder, enemyPosition)));
|
||||
mWorld.insertCharacter(std::shared_ptr<Enemy>(new Enemy(
|
||||
mWorld, mPathfinder, enemy.first, enemy.second)));
|
||||
}
|
||||
}
|
||||
if (mGenerated[current.x][current.y] && distance <= GENERATE_AREA_RANGE) {
|
||||
|
@ -258,23 +259,25 @@ Generator::generateTiles(const sf::IntRect& area) {
|
|||
* Returns coordinates where enemies should spawn.
|
||||
*
|
||||
* @param area Area for which enemy spawns should be returned.
|
||||
* @return Pairs of spawn points together with seeds.
|
||||
*/
|
||||
std::vector<Vector2f>
|
||||
std::vector<std::pair<Vector2f, float> >
|
||||
Generator::getEnemySpawns(const sf::IntRect& area) {
|
||||
auto compare = [](const Vector2f& a, const Vector2f& b) {
|
||||
return a.x < b.x || (a.x == b.x && a.y < b.y);
|
||||
};
|
||||
std::set<Vector2f, decltype(compare)> ret(compare);
|
||||
std::vector<std::pair<Vector2f, float> > spawns;
|
||||
for (int x = area.left; x < area.left + area.width; x++) {
|
||||
for (int y = area.top; y < area.top + area.height; y++) {
|
||||
if (mCharacterNoise.getNoise(x, y) < -0.85f) {
|
||||
float noise = mCharacterNoise.getNoise(x, y);
|
||||
if (noise <= -0.85f) {
|
||||
Vector2i tilePosition = findClosestFloor(Vector2i(x, y));
|
||||
ret.insert(Vector2f(tilePosition.x * Tile::TILE_SIZE.x,
|
||||
tilePosition.y * Tile::TILE_SIZE.y));
|
||||
// Bad way to get a pseudo random, but deterministic value.
|
||||
// Just using noise would be better, but that is not uniformly distributed.
|
||||
int seed = ((int) noise * 100000) xor x xor y;
|
||||
spawns.push_back(std::make_pair(Vector2f(tilePosition.x * Tile::TILE_SIZE.x,
|
||||
tilePosition.y * Tile::TILE_SIZE.y), seed));
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::vector<Vector2f>(ret.begin(), ret.end());
|
||||
return spawns;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,7 +25,7 @@ public:
|
|||
explicit Generator(World& world, Pathfinder& pathfinder);
|
||||
void generateCurrentAreaIfNeeded(const Vector2f& position);
|
||||
Vector2f getPlayerSpawn() const;
|
||||
std::vector<Vector2f> getEnemySpawns(const sf::IntRect& area);
|
||||
std::vector<std::pair<Vector2f, float> > getEnemySpawns(const sf::IntRect& area);
|
||||
|
||||
private:
|
||||
typedef std::map<int, std::map<int, Tile::Type> > array;
|
||||
|
|
|
@ -9,12 +9,43 @@
|
|||
|
||||
#include <Thor/Vectors.hpp>
|
||||
|
||||
#include "items/Heal.h"
|
||||
#include "items/Shield.h"
|
||||
#include "items/Weapon.h"
|
||||
#include "../util/Yaml.h"
|
||||
|
||||
/**
|
||||
* Determines items used by this enemy using seed.
|
||||
*
|
||||
* @param seed Random value to seed random number generator.
|
||||
*/
|
||||
Enemy::Enemy(World& world, Pathfinder& pathfinder,
|
||||
const Vector2f& position) :
|
||||
const Vector2f& position, float seed) :
|
||||
Character(position, CATEGORY_ACTOR, MASK_ALL, Yaml("enemy.yaml"), world,
|
||||
pathfinder) {
|
||||
std::ranlux24_base generator(seed);
|
||||
|
||||
// Select primary weapon.
|
||||
switch (std::uniform_int_distribution<int>(0, 4)(generator)) {
|
||||
case 0: setFirstWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::ASSAULT_RIFLE)); break;
|
||||
case 1: setFirstWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::AUTO_SHOTGUN)); break;
|
||||
case 2: setFirstWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::HMG)); break;
|
||||
case 3: setFirstWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::RIFLE)); break;
|
||||
case 4: setFirstWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::SHOTGUN)); break;
|
||||
}
|
||||
|
||||
// Select secondary weapon.
|
||||
switch (std::uniform_int_distribution<int>(0, 1)(generator)) {
|
||||
case 0: setSecondWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::PISTOL));
|
||||
case 1: setSecondWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::KNIFE));
|
||||
}
|
||||
|
||||
// Select gadget.
|
||||
switch (std::uniform_int_distribution<int>(0, 1)(generator)) {
|
||||
case 0: setLeftGadget(std::shared_ptr<Gadget>(new Heal()));
|
||||
case 1: setLeftGadget(std::shared_ptr<Gadget>(new Shield()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
#ifndef DG_ENEMY_H_
|
||||
#define DG_ENEMY_H
|
||||
|
||||
#include "../sprites/abstract/Character.h"
|
||||
#include "abstract/Character.h"
|
||||
|
||||
class World;
|
||||
|
||||
class Enemy : public Character {
|
||||
public:
|
||||
explicit Enemy(World& world, Pathfinder& pathfinder,
|
||||
const Vector2f& position);
|
||||
const Vector2f& position, float seed);
|
||||
|
||||
private:
|
||||
virtual void onThink(int elapsed) override;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <Thor/Vectors.hpp>
|
||||
|
||||
#include "items/Weapon.h"
|
||||
#include "../util/Yaml.h"
|
||||
|
||||
/**
|
||||
|
@ -19,6 +20,8 @@ Player::Player(World& world, Pathfinder& pathfinder,
|
|||
Character(position, CATEGORY_ACTOR, MASK_ALL, Yaml("player.yaml"), world,
|
||||
pathfinder),
|
||||
mDirection(0) {
|
||||
setFirstWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::PISTOL));
|
||||
setSecondWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::KNIFE));
|
||||
}
|
||||
|
||||
Vector2f
|
||||
|
|
|
@ -32,10 +32,6 @@ Character::Character(const Vector2f& position, Category category,
|
|||
mMaxHealth(config.get("health", 100)),
|
||||
mCurrentHealth(mMaxHealth),
|
||||
mMovementSpeed(config.get("speed", 0.0f)),
|
||||
mFirstWeapon(new Weapon(world, *this,
|
||||
Yaml(config.get("first_weapon", std::string())))),
|
||||
mSecondWeapon(new Weapon(world, *this,
|
||||
Yaml(config.get("second_weapon", std::string())))),
|
||||
mActiveWeapon(mFirstWeapon),
|
||||
mLastPosition(getPosition()),
|
||||
mFaction((Faction) config.get("faction", 1)) {
|
||||
|
@ -48,12 +44,13 @@ Character::~Character() {
|
|||
* Subtracts health from Actor. Calls onDeath() when health reaches zero and marks
|
||||
* object for deletion.
|
||||
*
|
||||
* @param damage Amount of health to subtract.
|
||||
* @param damage Amount of damage taken.
|
||||
*/
|
||||
void
|
||||
Character::onDamage(int damage) {
|
||||
mCurrentHealth -= damage;
|
||||
|
||||
|
||||
if (mCurrentHealth > mMaxHealth)
|
||||
mCurrentHealth = mMaxHealth;
|
||||
|
||||
|
@ -232,11 +229,35 @@ Character::selectSecondWeapon() {
|
|||
mActiveWeapon = mSecondWeapon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current player health.
|
||||
*/
|
||||
int
|
||||
Character::getHealth() const {
|
||||
return mCurrentHealth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets first weapon to weapon, also replacing active weapon if first weapon
|
||||
* is active.
|
||||
*/
|
||||
void
|
||||
Character::setFirstWeapon(std::shared_ptr<Weapon> weapon) {
|
||||
if (mFirstWeapon == mActiveWeapon)
|
||||
mActiveWeapon = weapon;
|
||||
mFirstWeapon = weapon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets second weapon to weapon, also replacing active weapon if second weapon
|
||||
* is active.
|
||||
*/
|
||||
void
|
||||
Character::setSecondWeapon(std::shared_ptr<Weapon> weapon) {
|
||||
if (mSecondWeapon == mActiveWeapon)
|
||||
mActiveWeapon = weapon;
|
||||
mSecondWeapon = weapon;
|
||||
}
|
||||
|
||||
void
|
||||
Character::setLeftGadget(std::shared_ptr<Gadget> gadget) {
|
||||
|
|
|
@ -59,6 +59,8 @@ protected:
|
|||
void selectFirstWeapon();
|
||||
void selectSecondWeapon();
|
||||
int getHealth() const;
|
||||
void setFirstWeapon(std::shared_ptr<Weapon> weapon);
|
||||
void setSecondWeapon(std::shared_ptr<Weapon> weapon);
|
||||
void setLeftGadget(std::shared_ptr<Gadget> gadget);
|
||||
void setRightGadget(std::shared_ptr<Gadget> gadget);
|
||||
void useLeftGadget();
|
||||
|
|
|
@ -38,6 +38,31 @@ Weapon::Weapon(World& world, Character& holder, const Yaml& config) :
|
|||
mRequiresAmmo(!config.get("requires_no_ammo", false)) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of the given weapon type and returns it as a
|
||||
* smart pointer.
|
||||
*/
|
||||
std::shared_ptr<Weapon>
|
||||
Weapon::getWeapon(World& world, Character& holder, WeaponType type) {
|
||||
switch (type) {
|
||||
case WeaponType::KNIFE:
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("knife.yaml")));
|
||||
case WeaponType::PISTOL:
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("pistol.yaml")));
|
||||
case WeaponType::ASSAULT_RIFLE:
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("assault_rifle.yaml")));
|
||||
case WeaponType::SHOTGUN:
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("shotgun.yaml")));
|
||||
case WeaponType::AUTO_SHOTGUN:
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("auto_shotgun.yaml")));
|
||||
case WeaponType::RIFLE:
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("rifle.yaml")));
|
||||
case WeaponType::HMG:
|
||||
return std::shared_ptr<Weapon>(new Weapon(world, holder, Yaml("hmg.yaml")));
|
||||
default: return std::shared_ptr<Weapon>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull the trigger.
|
||||
*/
|
||||
|
|
|
@ -24,8 +24,20 @@ class Particle;
|
|||
class Yaml;
|
||||
|
||||
class Weapon : public Item {
|
||||
public:
|
||||
enum class WeaponType {
|
||||
KNIFE,
|
||||
PISTOL,
|
||||
ASSAULT_RIFLE,
|
||||
SHOTGUN,
|
||||
AUTO_SHOTGUN,
|
||||
RIFLE,
|
||||
HMG
|
||||
};
|
||||
|
||||
public:
|
||||
explicit Weapon(World& world, Character& holder, const Yaml& config);
|
||||
static std::shared_ptr<Weapon> getWeapon(World& world, Character& holder, WeaponType type);
|
||||
|
||||
void pullTrigger();
|
||||
void releaseTrigger();
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
#define DG_LOADER_H_
|
||||
|
||||
#include <Thor/Resources.hpp>
|
||||
|
||||
#include "../util/Singleton.h"
|
||||
|
||||
#include "Singleton.h"
|
||||
|
||||
/**
|
||||
* This class allows to set default resource folders and subfolders, which means that these
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
#ifndef DG_RESOURCEMANAGER_H_
|
||||
#define DG_RESOURCEMANAGER_H_
|
||||
|
||||
#include "../util/Singleton.h"
|
||||
|
||||
#include "Singleton.h"
|
||||
|
||||
/**
|
||||
* Loads and manages all resources by providing Singleton access to
|
||||
|
|
Reference in a new issue