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
|
speed: 100
|
||||||
radius: 25
|
radius: 25
|
||||||
size: [50, 50]
|
size: [50, 50]
|
||||||
first_weapon: pistol.yaml
|
|
||||||
second_weapon: knife.yaml
|
|
||||||
faction: 1
|
faction: 1
|
|
@ -5,6 +5,4 @@ health: 100
|
||||||
speed: 100
|
speed: 100
|
||||||
radius: 25
|
radius: 25
|
||||||
size: [50, 50]
|
size: [50, 50]
|
||||||
first_weapon: pistol.yaml
|
|
||||||
second_weapon: knife.yaml
|
|
||||||
faction: 0
|
faction: 0
|
|
@ -55,8 +55,8 @@ Game::Game(tgui::Window& window) :
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::initPlayer() {
|
void Game::initPlayer() {
|
||||||
mPlayer = std::shared_ptr < Player
|
mPlayer = std::shared_ptr<Player>(new Player(mWorld, mPathfinder,
|
||||||
> (new Player(mWorld, mPathfinder, mGenerator.getPlayerSpawn()));
|
mGenerator.getPlayerSpawn()));
|
||||||
mPlayer->setLeftGadget(std::shared_ptr < Gadget > (new Heal()));
|
mPlayer->setLeftGadget(std::shared_ptr < Gadget > (new Heal()));
|
||||||
mPlayer->setRightGadget(std::shared_ptr < Gadget > (new Shield()));
|
mPlayer->setRightGadget(std::shared_ptr < Gadget > (new Shield()));
|
||||||
mWorld.insertCharacter(mPlayer);
|
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) / 2,
|
||||||
Vector2i(GENERATE_AREA_SIZE, GENERATE_AREA_SIZE));
|
Vector2i(GENERATE_AREA_SIZE, GENERATE_AREA_SIZE));
|
||||||
generateTiles(area);
|
generateTiles(area);
|
||||||
for (const auto& enemyPosition : getEnemySpawns(area)) {
|
for (const auto& enemy : getEnemySpawns(area)) {
|
||||||
float distance = thor::length(enemyPosition - playerPosition);
|
float distance = thor::length(enemy.first - playerPosition);
|
||||||
if (distance > Character::VISION_DISTANCE)
|
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) {
|
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.
|
* Returns coordinates where enemies should spawn.
|
||||||
*
|
*
|
||||||
* @param area Area for which enemy spawns should be returned.
|
* @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) {
|
Generator::getEnemySpawns(const sf::IntRect& area) {
|
||||||
auto compare = [](const Vector2f& a, const Vector2f& b) {
|
std::vector<std::pair<Vector2f, float> > spawns;
|
||||||
return a.x < b.x || (a.x == b.x && a.y < b.y);
|
|
||||||
};
|
|
||||||
std::set<Vector2f, decltype(compare)> ret(compare);
|
|
||||||
for (int x = area.left; x < area.left + area.width; x++) {
|
for (int x = area.left; x < area.left + area.width; x++) {
|
||||||
for (int y = area.top; y < area.top + area.height; y++) {
|
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));
|
Vector2i tilePosition = findClosestFloor(Vector2i(x, y));
|
||||||
ret.insert(Vector2f(tilePosition.x * Tile::TILE_SIZE.x,
|
// Bad way to get a pseudo random, but deterministic value.
|
||||||
tilePosition.y * Tile::TILE_SIZE.y));
|
// 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);
|
explicit Generator(World& world, Pathfinder& pathfinder);
|
||||||
void generateCurrentAreaIfNeeded(const Vector2f& position);
|
void generateCurrentAreaIfNeeded(const Vector2f& position);
|
||||||
Vector2f getPlayerSpawn() const;
|
Vector2f getPlayerSpawn() const;
|
||||||
std::vector<Vector2f> getEnemySpawns(const sf::IntRect& area);
|
std::vector<std::pair<Vector2f, float> > getEnemySpawns(const sf::IntRect& area);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::map<int, std::map<int, Tile::Type> > array;
|
typedef std::map<int, std::map<int, Tile::Type> > array;
|
||||||
|
|
|
@ -9,12 +9,43 @@
|
||||||
|
|
||||||
#include <Thor/Vectors.hpp>
|
#include <Thor/Vectors.hpp>
|
||||||
|
|
||||||
|
#include "items/Heal.h"
|
||||||
|
#include "items/Shield.h"
|
||||||
|
#include "items/Weapon.h"
|
||||||
#include "../util/Yaml.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,
|
Enemy::Enemy(World& world, Pathfinder& pathfinder,
|
||||||
const Vector2f& position) :
|
const Vector2f& position, float seed) :
|
||||||
Character(position, CATEGORY_ACTOR, MASK_ALL, Yaml("enemy.yaml"), world,
|
Character(position, CATEGORY_ACTOR, MASK_ALL, Yaml("enemy.yaml"), world,
|
||||||
pathfinder) {
|
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
|
void
|
||||||
|
|
|
@ -8,14 +8,14 @@
|
||||||
#ifndef DG_ENEMY_H_
|
#ifndef DG_ENEMY_H_
|
||||||
#define DG_ENEMY_H
|
#define DG_ENEMY_H
|
||||||
|
|
||||||
#include "../sprites/abstract/Character.h"
|
#include "abstract/Character.h"
|
||||||
|
|
||||||
class World;
|
class World;
|
||||||
|
|
||||||
class Enemy : public Character {
|
class Enemy : public Character {
|
||||||
public:
|
public:
|
||||||
explicit Enemy(World& world, Pathfinder& pathfinder,
|
explicit Enemy(World& world, Pathfinder& pathfinder,
|
||||||
const Vector2f& position);
|
const Vector2f& position, float seed);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void onThink(int elapsed) override;
|
virtual void onThink(int elapsed) override;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <Thor/Vectors.hpp>
|
#include <Thor/Vectors.hpp>
|
||||||
|
|
||||||
|
#include "items/Weapon.h"
|
||||||
#include "../util/Yaml.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,
|
Character(position, CATEGORY_ACTOR, MASK_ALL, Yaml("player.yaml"), world,
|
||||||
pathfinder),
|
pathfinder),
|
||||||
mDirection(0) {
|
mDirection(0) {
|
||||||
|
setFirstWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::PISTOL));
|
||||||
|
setSecondWeapon(Weapon::getWeapon(world, *this, Weapon::WeaponType::KNIFE));
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2f
|
Vector2f
|
||||||
|
|
|
@ -32,10 +32,6 @@ Character::Character(const Vector2f& position, Category category,
|
||||||
mMaxHealth(config.get("health", 100)),
|
mMaxHealth(config.get("health", 100)),
|
||||||
mCurrentHealth(mMaxHealth),
|
mCurrentHealth(mMaxHealth),
|
||||||
mMovementSpeed(config.get("speed", 0.0f)),
|
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),
|
mActiveWeapon(mFirstWeapon),
|
||||||
mLastPosition(getPosition()),
|
mLastPosition(getPosition()),
|
||||||
mFaction((Faction) config.get("faction", 1)) {
|
mFaction((Faction) config.get("faction", 1)) {
|
||||||
|
@ -48,12 +44,13 @@ Character::~Character() {
|
||||||
* Subtracts health from Actor. Calls onDeath() when health reaches zero and marks
|
* Subtracts health from Actor. Calls onDeath() when health reaches zero and marks
|
||||||
* object for deletion.
|
* object for deletion.
|
||||||
*
|
*
|
||||||
* @param damage Amount of health to subtract.
|
* @param damage Amount of damage taken.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Character::onDamage(int damage) {
|
Character::onDamage(int damage) {
|
||||||
mCurrentHealth -= damage;
|
mCurrentHealth -= damage;
|
||||||
|
|
||||||
|
|
||||||
if (mCurrentHealth > mMaxHealth)
|
if (mCurrentHealth > mMaxHealth)
|
||||||
mCurrentHealth = mMaxHealth;
|
mCurrentHealth = mMaxHealth;
|
||||||
|
|
||||||
|
@ -232,11 +229,35 @@ Character::selectSecondWeapon() {
|
||||||
mActiveWeapon = mSecondWeapon;
|
mActiveWeapon = mSecondWeapon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns current player health.
|
||||||
|
*/
|
||||||
int
|
int
|
||||||
Character::getHealth() const {
|
Character::getHealth() const {
|
||||||
return mCurrentHealth;
|
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
|
void
|
||||||
Character::setLeftGadget(std::shared_ptr<Gadget> gadget) {
|
Character::setLeftGadget(std::shared_ptr<Gadget> gadget) {
|
||||||
|
|
|
@ -59,6 +59,8 @@ protected:
|
||||||
void selectFirstWeapon();
|
void selectFirstWeapon();
|
||||||
void selectSecondWeapon();
|
void selectSecondWeapon();
|
||||||
int getHealth() const;
|
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 setLeftGadget(std::shared_ptr<Gadget> gadget);
|
||||||
void setRightGadget(std::shared_ptr<Gadget> gadget);
|
void setRightGadget(std::shared_ptr<Gadget> gadget);
|
||||||
void useLeftGadget();
|
void useLeftGadget();
|
||||||
|
|
|
@ -38,6 +38,31 @@ Weapon::Weapon(World& world, Character& holder, const Yaml& config) :
|
||||||
mRequiresAmmo(!config.get("requires_no_ammo", false)) {
|
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.
|
* Pull the trigger.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -24,8 +24,20 @@ class Particle;
|
||||||
class Yaml;
|
class Yaml;
|
||||||
|
|
||||||
class Weapon : public Item {
|
class Weapon : public Item {
|
||||||
|
public:
|
||||||
|
enum class WeaponType {
|
||||||
|
KNIFE,
|
||||||
|
PISTOL,
|
||||||
|
ASSAULT_RIFLE,
|
||||||
|
SHOTGUN,
|
||||||
|
AUTO_SHOTGUN,
|
||||||
|
RIFLE,
|
||||||
|
HMG
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Weapon(World& world, Character& holder, const Yaml& config);
|
explicit Weapon(World& world, Character& holder, const Yaml& config);
|
||||||
|
static std::shared_ptr<Weapon> getWeapon(World& world, Character& holder, WeaponType type);
|
||||||
|
|
||||||
void pullTrigger();
|
void pullTrigger();
|
||||||
void releaseTrigger();
|
void releaseTrigger();
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
#define DG_LOADER_H_
|
#define DG_LOADER_H_
|
||||||
|
|
||||||
#include <Thor/Resources.hpp>
|
#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
|
* This class allows to set default resource folders and subfolders, which means that these
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
|
|
||||||
#ifndef DG_RESOURCEMANAGER_H_
|
#ifndef DG_RESOURCEMANAGER_H_
|
||||||
#define DG_RESOURCEMANAGER_H_
|
#define DG_RESOURCEMANAGER_H_
|
||||||
|
|
||||||
#include "../util/Singleton.h"
|
#include "Singleton.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads and manages all resources by providing Singleton access to
|
* Loads and manages all resources by providing Singleton access to
|
||||||
|
|
Reference in a new issue