Added cycle weapons command and the ability to hold more than one weapon.
This commit is contained in:
parent
1f38730c96
commit
90a843946a
14 changed files with 139 additions and 47 deletions
|
|
@ -14,7 +14,7 @@ enum class AIState {
|
|||
Patrol
|
||||
};
|
||||
|
||||
class AI {
|
||||
class AI : public std::enable_shared_from_this<AI> {
|
||||
public:
|
||||
AI(const std::shared_ptr<GameActor>& actor, const std::shared_ptr<Raycaster>& raycaster);
|
||||
void update();
|
||||
|
|
@ -30,7 +30,7 @@ public:
|
|||
private:
|
||||
AIState state;
|
||||
std::shared_ptr<Raycaster> raycaster;
|
||||
std::shared_ptr<AIScript> behaviour;
|
||||
std::shared_ptr<AIScript> behaviour;
|
||||
std::shared_ptr<GameActor> actor;
|
||||
std::shared_ptr<GameActor> target;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@
|
|||
|
||||
class Camera;
|
||||
struct PhysicsComponent;
|
||||
|
||||
// TODO: Allow speed to be changed and add speed as creation value in XML File!
|
||||
// TODO: Create Entity System that loads entity types and creates them in scene according to name.
|
||||
class Entity
|
||||
{
|
||||
public:
|
||||
|
|
@ -18,7 +19,7 @@ public:
|
|||
position(glm::vec3(0.0f)),
|
||||
scale(glm::vec3(1.0f)),
|
||||
rotation(0.0f),
|
||||
speed(5.0f) {};
|
||||
speed(20.0f) {};
|
||||
virtual ~Entity() {};
|
||||
|
||||
void setPosition(const glm::vec3& position);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <unordered_map>
|
||||
#include <SDL_timer.h>
|
||||
#include <optional>
|
||||
|
||||
#include "gameplay/entity.h"
|
||||
#include "utility/mousestate.h"
|
||||
|
|
@ -12,6 +13,9 @@ class AI;
|
|||
class Weapon;
|
||||
class EventManager;
|
||||
|
||||
// TODO: Finish weapon cycling code and add default weapon to every actor
|
||||
// TODO: Add ammo system, then work on some basic UI design
|
||||
|
||||
class GameActor : public Entity
|
||||
{
|
||||
public:
|
||||
|
|
@ -19,12 +23,12 @@ public:
|
|||
~GameActor();
|
||||
|
||||
void addComponent(std::shared_ptr<Component> component);
|
||||
void equipWeapon(std::shared_ptr<Weapon> weapon);
|
||||
void attachEventManager(std::shared_ptr<EventManager> eventManager);
|
||||
void pickupWeapon(std::shared_ptr<Weapon> weapon);
|
||||
void hookEventManager(std::shared_ptr<EventManager> eventManager);
|
||||
void update(float deltaTime) override;
|
||||
void render(const std::shared_ptr<Camera>& camera) override;
|
||||
|
||||
const std::shared_ptr<Weapon>& getHeldWeapon() const;
|
||||
const std::optional<std::shared_ptr<Weapon>>& getHeldWeapon() const;
|
||||
const int getActorID() const { return actorid; }
|
||||
|
||||
void setRotation(const float& rotation) override;
|
||||
|
|
@ -39,13 +43,19 @@ public:
|
|||
void moveBackward();
|
||||
void strafeLeft();
|
||||
void strafeRight();
|
||||
void fireWeapon();
|
||||
void fireWeapon() const;
|
||||
void cycleUpWeapons();
|
||||
void cycleDownWeapons();
|
||||
void cycleWeapons(const MouseState&);
|
||||
void followMouse(const MouseState&);
|
||||
private:
|
||||
using component_vector_t = std::vector<std::shared_ptr<Component>>;
|
||||
using weapon_vector_t = std::vector<std::shared_ptr<Weapon>>;
|
||||
|
||||
int actorid;
|
||||
std::vector<std::shared_ptr<Component>> components;
|
||||
std::shared_ptr<AI> ai;
|
||||
std::shared_ptr<Weapon> currentWeapon = nullptr;
|
||||
component_vector_t components;
|
||||
weapon_vector_t weapons;
|
||||
size_t currentWeaponIndex = 0;
|
||||
std::shared_ptr<EventManager> eventManager;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ enum {
|
|||
MOUSE_BUTTON_LEFT = 1,
|
||||
MOUSE_BUTTON_RIGHT = 2,
|
||||
MOUSE_BUTTON_MIDDLE = 4,
|
||||
MOUSE_MOTION = 8
|
||||
MOUSE_MOTION = 8,
|
||||
MOUSE_SCROLL = 16
|
||||
};
|
||||
|
||||
class Keyboard
|
||||
|
|
@ -49,6 +50,8 @@ protected:
|
|||
mouse_state.x = static_cast<float>(e.motion.x);
|
||||
mouse_state.y = static_cast<float>(e.motion.y);
|
||||
}
|
||||
if (e.type == SDL_MOUSEWHEEL)
|
||||
mouse_state.scroll = e.wheel.preciseY;
|
||||
}
|
||||
MouseState mouse_state;
|
||||
std::unordered_map<Uint8, bool> mouseButtons;
|
||||
|
|
@ -85,14 +88,17 @@ public:
|
|||
void bindMouseMotion(MouseCommand* command) {
|
||||
mouseMotionCommand = command;
|
||||
}
|
||||
void bindMouseScroll(MouseCommand* command) {
|
||||
mouseScrollCommand = command;
|
||||
}
|
||||
void handleInput();
|
||||
|
||||
private:
|
||||
GameActor* actor = nullptr;
|
||||
// final int is delay
|
||||
std::unordered_map<SDL_Keycode, CommandWithDelay> keyCommands;
|
||||
std::unordered_map<Uint8, MouseCommandWithDelay> mouseCommands;
|
||||
MouseCommand* mouseMotionCommand = nullptr;
|
||||
MouseCommand* mouseScrollCommand = nullptr;
|
||||
};
|
||||
|
||||
#endif // _H_INPUT_H
|
||||
|
|
@ -30,6 +30,8 @@ public:
|
|||
Weapon(const WeaponData* data, const std::shared_ptr<Shader>& weaponShader, const std::shared_ptr<Shader>& bulletShader, ResourceManager* resourceManager);
|
||||
|
||||
void setWielder(const std::shared_ptr<GameActor>& wielder) { this->wielder = wielder; }
|
||||
void wield() { wielded = true; }
|
||||
void putaway() { wielded = false; }
|
||||
|
||||
void addComponent(const std::shared_ptr<Component>& component);
|
||||
void attachScript(const std::shared_ptr<WeaponScript>& script);
|
||||
|
|
@ -79,6 +81,8 @@ private:
|
|||
std::shared_ptr<UTIL::RandomGenerator> bulletModifer;
|
||||
|
||||
std::shared_ptr<GameActor> wielder;
|
||||
// is the weapon currently active
|
||||
bool wielded = false;
|
||||
int lastFireTime = 0;
|
||||
|
||||
Direction lastDir;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,27 @@ public:
|
|||
void execute(GameActor& actor) override;
|
||||
};
|
||||
|
||||
class CycleUpCommand : public Command
|
||||
{
|
||||
public:
|
||||
CycleUpCommand() {}
|
||||
void execute(GameActor& actor) override;
|
||||
};
|
||||
|
||||
class CycleDownCommand : public Command
|
||||
{
|
||||
public:
|
||||
CycleDownCommand() {}
|
||||
void execute(GameActor& actor) override;
|
||||
};
|
||||
|
||||
class CycleCommand : public MouseCommand
|
||||
{
|
||||
public:
|
||||
CycleCommand() {}
|
||||
void execute(GameActor& actor, const MouseState& mouse_state) override;
|
||||
};
|
||||
|
||||
class ShootCommand : public MouseCommand
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
struct MouseState {
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
|
||||
float scroll = 0.0f;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -11,11 +11,11 @@ AI::AI(const std::shared_ptr<GameActor>& actor, const std::shared_ptr<Raycaster>
|
|||
|
||||
void AI::attachBehaviourScript(const std::shared_ptr<AIScript>& behaviour)
|
||||
{
|
||||
// passing out instance of raycaster this Ai into our scripting api
|
||||
// passing out instance of raycaster and this AI into our scripting api
|
||||
// pay special attention each ai script has control of only their own instance of ai!
|
||||
this->behaviour = behaviour;
|
||||
this->behaviour->lua["raycaster"] = raycaster;
|
||||
this->behaviour->lua["ai"] = std::shared_ptr<AI>(this);
|
||||
this->behaviour->lua["ai"] = shared_from_this();
|
||||
}
|
||||
|
||||
void AI::update()
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ bool Game::init()
|
|||
|
||||
inputHandler->bindMouseCommand(MOUSE_BUTTON_LEFT, 100, new ShootCommand());
|
||||
inputHandler->bindMouseMotion(new FollowMouseCommand());
|
||||
inputHandler->bindMouseScroll(new CycleCommand());
|
||||
|
||||
game_state |= GAME_RUNNING;
|
||||
resourceManager = std::make_shared<ResourceManager>();
|
||||
|
|
|
|||
|
|
@ -14,21 +14,25 @@ void GameActor::addComponent(std::shared_ptr<Component> component)
|
|||
components.push_back(component);
|
||||
}
|
||||
|
||||
const std::shared_ptr<Weapon>& GameActor::getHeldWeapon() const
|
||||
const std::optional<std::shared_ptr<Weapon>>& GameActor::getHeldWeapon() const
|
||||
{
|
||||
return currentWeapon;
|
||||
return (weapons.empty() || currentWeaponIndex >= weapons.size()) ? std::nullopt : std::make_optional(weapons[currentWeaponIndex]);
|
||||
}
|
||||
|
||||
void GameActor::equipWeapon(std::shared_ptr<Weapon> weapon)
|
||||
void GameActor::pickupWeapon(std::shared_ptr<Weapon> weapon)
|
||||
{
|
||||
currentWeapon = std::move(weapon);
|
||||
if (currentWeapon)
|
||||
currentWeapon->setWielder(std::shared_ptr<GameActor>(this));
|
||||
weapon->setWielder(std::shared_ptr<GameActor>(this));
|
||||
weapons.push_back(weapon);
|
||||
getHeldWeapon().value()->putaway();
|
||||
currentWeaponIndex = weapons.size() - 1;
|
||||
getHeldWeapon().value()->wield();
|
||||
}
|
||||
|
||||
void GameActor::attachEventManager(std::shared_ptr<EventManager> eventManager)
|
||||
void GameActor::hookEventManager(std::shared_ptr<EventManager> eventManager)
|
||||
{
|
||||
this->eventManager = eventManager;
|
||||
for (auto& weapon : weapons)
|
||||
weapon->hookEventManager(eventManager);
|
||||
}
|
||||
|
||||
void GameActor::setRotation(const float& rotation)
|
||||
|
|
@ -48,8 +52,8 @@ void GameActor::update(float deltaTime)
|
|||
|
||||
for (auto& component : components)
|
||||
component->update();
|
||||
if (currentWeapon)
|
||||
currentWeapon->update(deltaTime);
|
||||
for (auto& weapon : weapons)
|
||||
weapon->update(deltaTime);
|
||||
}
|
||||
|
||||
void GameActor::render(const std::shared_ptr<Camera>& camera)
|
||||
|
|
@ -65,8 +69,8 @@ void GameActor::render(const std::shared_ptr<Camera>& camera)
|
|||
component->bind();
|
||||
component->render();
|
||||
}
|
||||
if (currentWeapon)
|
||||
currentWeapon->render(camera);
|
||||
for (auto& weapon : weapons)
|
||||
weapon->render(camera);
|
||||
isMoving = false;
|
||||
}
|
||||
|
||||
|
|
@ -76,11 +80,28 @@ void GameActor::moveLeft() { if (physics) physics->rigidBody.applyForce(glm::vec
|
|||
void GameActor::moveRight(){ if (physics) physics->rigidBody.applyForce(glm::vec3( 1.f, 0.f, 0.f), 1500.25f); isMoving = true; }
|
||||
|
||||
// top-down shooter mode controls
|
||||
void GameActor::strafeLeft() { position.x += sin(glm::radians(rotation)) * speed; position.y -= cos(glm::radians(rotation)) * speed; }
|
||||
void GameActor::strafeRight() { position.x -= sin(glm::radians(rotation)) * speed; position.y += cos(glm::radians(rotation)) * speed; }
|
||||
void GameActor::moveBackward() { position.x -= cos(glm::radians(rotation)) * speed; position.y -= sin(glm::radians(rotation)) * speed; }
|
||||
void GameActor::moveForward() { if (physics) physics->rigidBody.applyForce(glm::vec3(cos(glm::radians(rotation)), sin(glm::radians(rotation)), 0.f), 1000.f); isMoving = true; }
|
||||
void GameActor::fireWeapon() { if (currentWeapon) currentWeapon->shoot(); }
|
||||
void GameActor::fireWeapon()const { if (auto& weapon = getHeldWeapon()) weapon.value()->shoot(); }
|
||||
void GameActor::cycleUpWeapons() {
|
||||
if (!weapons.empty()) {
|
||||
weapons[currentWeaponIndex]->putaway();
|
||||
currentWeaponIndex = (currentWeaponIndex + 1) % weapons.size();
|
||||
weapons[currentWeaponIndex]->wield();
|
||||
}
|
||||
}
|
||||
void GameActor::cycleDownWeapons() {
|
||||
if (!weapons.empty()) {
|
||||
weapons[currentWeaponIndex]->putaway();
|
||||
currentWeaponIndex = (currentWeaponIndex + weapons.size() - 1) % weapons.size();
|
||||
weapons[currentWeaponIndex]->wield();
|
||||
}
|
||||
}
|
||||
void GameActor::cycleWeapons(const MouseState& mouse_state)
|
||||
{
|
||||
if (mouse_state.scroll < 0)
|
||||
cycleUpWeapons();
|
||||
else if (mouse_state.scroll > 0)
|
||||
cycleDownWeapons();
|
||||
}
|
||||
void GameActor::followMouse(const MouseState& mouse_state)
|
||||
{
|
||||
glm::vec2 direction = glm::vec2(mouse_state.x, mouse_state.y) - glm::vec2(localPosition.x + 0.5f * scale.x, localPosition.y + 0.5f * scale.y);
|
||||
|
|
@ -91,3 +112,13 @@ void GameActor::followMouse(const MouseState& mouse_state)
|
|||
//setRotation(glm::degrees(glm::atan(direction.y, direction.x)));
|
||||
this->rotation = newRotation;
|
||||
}
|
||||
void GameActor::strafeLeft() { position.x += sin(glm::radians(rotation)) * speed; position.y -= cos(glm::radians(rotation)) * speed; }
|
||||
void GameActor::strafeRight() { position.x -= sin(glm::radians(rotation)) * speed; position.y += cos(glm::radians(rotation)) * speed; }
|
||||
void GameActor::moveBackward() { position.x -= cos(glm::radians(rotation)) * speed; position.y -= sin(glm::radians(rotation)) * speed; }
|
||||
void GameActor::moveForward() {
|
||||
if (physics) {
|
||||
physics->rigidBody.velocity.x += cos(glm::radians(rotation)) * speed;
|
||||
physics->rigidBody.velocity.y += sin(glm::radians(rotation)) * speed;
|
||||
}
|
||||
isMoving = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ void InputHandler::handleInput()
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!mouseMotionCommand) return;
|
||||
mouseMotionCommand->execute(*actor, mouse_state);
|
||||
if (mouseMotionCommand)
|
||||
mouseMotionCommand->execute(*actor, mouse_state);
|
||||
if (mouseScrollCommand)
|
||||
mouseScrollCommand->execute(*actor, mouse_state);
|
||||
mouse_state.scroll = 0.0f; // clear mouse scroll since we have handled the event.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@
|
|||
#include "utility/raycaster.h"
|
||||
#include "utility/debugdraw.h"
|
||||
|
||||
#include <execution>
|
||||
|
||||
// Scene xml files, should contain a node called <player> that holds the sprite location
|
||||
/*
|
||||
like this:
|
||||
|
|
@ -67,12 +69,13 @@ void Scene::loadDebugShooterScene()
|
|||
}
|
||||
else
|
||||
entitySprite = resourceManager->loadSpriteAnimated(entityData.sprite, entityData.frameSize);
|
||||
auto defaultWeapon = resourceManager->loadWeapon("pistolGun", weaponShader, bubbleShader);
|
||||
auto entityWeapon = resourceManager->loadWeapon(entityData.weapon, weaponShader, bubbleShader);
|
||||
|
||||
entityWeapon->hookEventManager(eventManager);
|
||||
entity->addComponent(std::make_shared<SpriteComponent>(entitySprite, eventManager));
|
||||
entity->equipWeapon(entityWeapon);
|
||||
entity->attachEventManager(eventManager);
|
||||
entity->pickupWeapon(defaultWeapon);
|
||||
entity->pickupWeapon(entityWeapon);
|
||||
entity->hookEventManager(eventManager);
|
||||
entity->setPosition(glm::vec3(entityData.x * mapData.tileSize, entityData.y * mapData.tileSize, 0.f));
|
||||
entity->setScale(glm::vec3(mapData.tileSize, mapData.tileSize, 1.f));
|
||||
|
||||
|
|
@ -119,7 +122,7 @@ std::shared_ptr<GameActor> Scene::getPlayer() const
|
|||
|
||||
void Scene::update(float deltaTime)
|
||||
{
|
||||
for (auto& [id, e] : entities)
|
||||
for (const auto& [id, e] : entities)
|
||||
{
|
||||
e->update(deltaTime);
|
||||
if (camera->getTarget() == e.get())
|
||||
|
|
@ -151,7 +154,8 @@ void Scene::hookSceneEvents()
|
|||
std::shared_ptr<GameActor> shooter = getGameActorByID(collideEvent->ownerID);
|
||||
std::shared_ptr<GameActor> target = getGameActorByID(collideEvent->victimID);
|
||||
if (shooter && target)
|
||||
shooter->getHeldWeapon()->onHitCallback(target, collideEvent->bullet, collideEvent->normal);
|
||||
if (auto& weapon = shooter->getHeldWeapon())
|
||||
weapon.value()->onHitCallback(target, collideEvent->bullet, collideEvent->normal);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,22 +102,28 @@ void Weapon::onHitCallback(std::shared_ptr<GameActor> target, std::shared_ptr<Ph
|
|||
void Weapon::update(float deltaTime)
|
||||
{
|
||||
Entity::update(deltaTime);
|
||||
// move the weapon into place as the wielder rotates and moves
|
||||
if (wielder)
|
||||
adjustWeapon();
|
||||
if (wielded)
|
||||
{
|
||||
// move the weapon into place as the wielder rotates and moves
|
||||
if (wielder)
|
||||
adjustWeapon();
|
||||
|
||||
for (auto& component : components)
|
||||
component->update();
|
||||
for (auto& component : components)
|
||||
component->update();
|
||||
}
|
||||
bulletManager->update(deltaTime);
|
||||
}
|
||||
|
||||
void Weapon::render(const std::shared_ptr<Camera>& camera)
|
||||
{
|
||||
Entity::render(camera);
|
||||
for (auto& component : components)
|
||||
if (wielded)
|
||||
{
|
||||
component->bind();
|
||||
component->render();
|
||||
for (auto& component : components)
|
||||
{
|
||||
component->bind();
|
||||
component->render();
|
||||
}
|
||||
}
|
||||
bulletManager->render(camera);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ void MoveForwardCommand::execute(GameActor& actor) { actor.moveForward(); }
|
|||
void MoveBackwardCommand::execute(GameActor& actor) { actor.moveBackward(); }
|
||||
void StrafeLeftCommand::execute(GameActor& actor) { actor.strafeLeft(); }
|
||||
void StrafeRightCommand::execute(GameActor& actor) { actor.strafeRight(); }
|
||||
void ShootCommand::execute(GameActor& actor, const MouseState& mouse_state) { actor.fireWeapon(); }
|
||||
void CycleUpCommand::execute(GameActor& actor) { actor.cycleUpWeapons(); }
|
||||
void CycleDownCommand::execute(GameActor& actor) { actor.cycleDownWeapons(); }
|
||||
|
||||
void ShootCommand::execute(GameActor& actor, const MouseState& mouse_state) { actor.fireWeapon(); }
|
||||
void CycleCommand::execute(GameActor& actor, const MouseState& mouse_state) { actor.cycleWeapons(mouse_state); }
|
||||
void FollowMouseCommand::execute(GameActor& actor, const MouseState& mouse_state) { actor.followMouse(mouse_state); }
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue