Skip to content

Commit

Permalink
Merge pull request #199 from ucsd-cse125-sp24/feat/multiple-player-mo…
Browse files Browse the repository at this point in the history
…dels

Feat/multiple player models
  • Loading branch information
Tyler-Lentz authored Jun 6, 2024
2 parents 5adc128 + 380c648 commit fc0e16e
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 61 deletions.
6 changes: 3 additions & 3 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
"server": {
"lobby_name": "Hope you're doing well!1",
"lobby_broadcast": true,
"max_players": 1,
"max_players": 2,
"disable_dm": true,
"skip_intro": false
"skip_intro": true
},
"client": {
"default_name": "Conan O'Brien",
"lobby_discovery": true,
"fullscreen": true,
"fullscreen": false,
"draw_bboxes": false,
"fps_counter": true,
"presentation": false
Expand Down
8 changes: 4 additions & 4 deletions include/client/animationmanager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@
class AnimationManager
{
public:
explicit AnimationManager(Animation* animation);
explicit AnimationManager();

void updateAnimation(float dt);

void playAnimation(Animation* pAnimation);

void calculateBoneTransform(const AssimpNodeData* node, glm::mat4 parentTransform);

void addAnimation(Animation* anim, ObjectType objType, AnimState animState);
void addAnimation(Animation* anim, ModelType modelType, AnimState animState);

void setAnimation(EntityID id, ObjectType objType, AnimState animState);
void setAnimation(EntityID id, ModelType modelType, AnimState animState);

std::vector<glm::mat4> getFinalBoneMatrices() { return m_finalBoneMatrices; }

private:
std::vector<glm::mat4> m_finalBoneMatrices;
std::unordered_map<EntityID, std::pair<float, Animation*>> entityAnimMap;
std::unordered_map<ObjectType, std::unordered_map<AnimState, Animation*>> objAnimMap;
std::unordered_map<ModelType, std::unordered_map<AnimState, Animation*>> objAnimMap;
Animation* m_currentAnimation;
EntityID currEntity;
float m_currentTime;
Expand Down
5 changes: 4 additions & 1 deletion include/client/client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,10 @@ class Client {
std::shared_ptr<Shader> deferred_light_box_shader;

/* Character models and lighting objects, might need to move to different classes later */
std::unique_ptr<Model> player_model;
std::unique_ptr<Model> fire_player_model;
std::unique_ptr<Model> lightning_player_model;
std::unique_ptr<Model> water_player_model;

std::unique_ptr<Model> bear_model;
std::unique_ptr<Model> torchlight_model;
std::unique_ptr<Model> wall_model;
Expand Down
4 changes: 3 additions & 1 deletion include/shared/game/sharedmodel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
*/
enum class ModelType {
Cube,
Player,
PlayerFire,
PlayerLightning,
PlayerWater,
WarrenBear,
HealthPotion,
InvisibilityPotion,
Expand Down
22 changes: 13 additions & 9 deletions src/client/animationmanager.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#include "client/animationmanager.hpp"

AnimationManager::AnimationManager(Animation* animation) {
AnimationManager::AnimationManager() {
currEntity = 0;
m_currentTime = 0.0;
m_currentAnimation = animation;
m_currentAnimation = nullptr;

m_deltaTime = 0; // Tyler: is this still used? linter complaining about it not being initialized

Expand Down Expand Up @@ -31,6 +31,10 @@ void AnimationManager::playAnimation(Animation* pAnimation) {
}

void AnimationManager::calculateBoneTransform(const AssimpNodeData* node, glm::mat4 parentTransform) {
if (m_currentAnimation == nullptr) {
return; // note from tyler: added this check because no longer setting currentAnimation in constructor
}

std::string nodeName = node->name;
glm::mat4 nodeTransform = node->transformation;

Expand Down Expand Up @@ -58,19 +62,19 @@ void AnimationManager::calculateBoneTransform(const AssimpNodeData* node, glm::m
calculateBoneTransform(&node->children[i], globalTransformation);
}

void AnimationManager::setAnimation(EntityID id, ObjectType objType, AnimState animState) {
if (entityAnimMap.find(id) == entityAnimMap.end() || entityAnimMap[id].second != objAnimMap[objType][animState]) {
entityAnimMap[id] = std::make_pair(0.0f, objAnimMap[objType][animState]);
void AnimationManager::setAnimation(EntityID id, ModelType modelType, AnimState animState) {
if (entityAnimMap.find(id) == entityAnimMap.end() || entityAnimMap[id].second != objAnimMap[modelType][animState]) {
entityAnimMap[id] = std::make_pair(0.0f, objAnimMap[modelType][animState]);
}
currEntity = id;
}

void AnimationManager::addAnimation(Animation* anim, ObjectType objType, AnimState animState) {
if (objAnimMap.find(objType) == objAnimMap.end()) {
void AnimationManager::addAnimation(Animation* anim, ModelType modelType, AnimState animState) {
if (objAnimMap.find(modelType) == objAnimMap.end()) {
std::unordered_map<AnimState, Animation*> animMap;
objAnimMap[objType] = animMap;
objAnimMap[modelType] = animMap;
}

this->objAnimMap[objType][animState] = anim;
this->objAnimMap[modelType][animState] = anim;
}

112 changes: 73 additions & 39 deletions src/client/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,30 +235,47 @@ bool Client::init() {
auto exit_model_path = env_models_dir / "exit.obj";
this->exit_model = std::make_unique<Model>(exit_model_path.string(), true);

auto player_model_path = graphics_assets_dir / "player_models/char_3/model_char_3.fbx";
auto player_walk_path = graphics_assets_dir / "animations/walk.fbx";
auto player_jump_path = graphics_assets_dir / "animations/jump.fbx";
auto player_idle_path = graphics_assets_dir / "animations/idle.fbx";
auto player_run_path = graphics_assets_dir / "animations/run.fbx";
auto player_atk_path = graphics_assets_dir / "animations/slash.fbx";
auto player_use_potion_path = graphics_assets_dir / "animations/drink.fbx";

this->player_model = std::make_unique<Model>(player_model_path.string(), false);
Animation* player_walk = new Animation(player_walk_path.string(), this->player_model.get());
Animation* player_jump = new Animation(player_jump_path.string(), this->player_model.get());
Animation* player_idle = new Animation(player_idle_path.string(), this->player_model.get());
Animation* player_run = new Animation(player_run_path.string(), this->player_model.get());
Animation* player_atk = new Animation(player_atk_path.string(), this->player_model.get());
Animation* player_use_potion = new Animation(player_use_potion_path.string(), this->player_model.get());

animManager = new AnimationManager(player_idle);

animManager->addAnimation(player_walk, ObjectType::Player, AnimState::WalkAnim);
animManager->addAnimation(player_jump, ObjectType::Player, AnimState::JumpAnim);
animManager->addAnimation(player_idle, ObjectType::Player, AnimState::IdleAnim);
animManager->addAnimation(player_run, ObjectType::Player, AnimState::SprintAnim);
animManager->addAnimation(player_atk, ObjectType::Player, AnimState::AttackAnim);
animManager->addAnimation(player_use_potion, ObjectType::Player, AnimState::DrinkPotionAnim);
auto fire_player_model_path = player_models_dir / "char_1_rename/char1.fbx";
auto lightning_player_model_path = player_models_dir / "char_2_rename/char2.fbx";
auto water_player_model_path = player_models_dir / "char_3/model_char_3.fbx";

this->fire_player_model = std::make_unique<Model>(fire_player_model_path.string(), false);
this->lightning_player_model = std::make_unique<Model>(lightning_player_model_path.string(), false);
this->water_player_model = std::make_unique<Model>(water_player_model_path.string(), false);

const int NUM_PLAYER_MODELS = 3;
std::array<std::pair<ModelType, Model*>, NUM_PLAYER_MODELS> player_models = {
// for some reason the first one only works if it is std::make_pair but the other two are fine with the
// curly brace syntax... WTF, just making them all use std::make_pair so they line up
std::make_pair(ModelType::PlayerFire, this->fire_player_model.get()),
std::make_pair(ModelType::PlayerLightning, this->lightning_player_model.get()),
std::make_pair(ModelType::PlayerWater, this->water_player_model.get())
};

animManager = new AnimationManager();

for (int i = 0; i < NUM_PLAYER_MODELS; i++) {
Animation* player_walk = new Animation(player_walk_path.string(), player_models.at(i).second);
Animation* player_jump = new Animation(player_jump_path.string(), player_models.at(i).second);
Animation* player_idle = new Animation(player_idle_path.string(), player_models.at(i).second);
Animation* player_run = new Animation(player_run_path.string(), player_models.at(i).second);
Animation* player_atk = new Animation(player_atk_path.string(), player_models.at(i).second);
Animation* player_use_potion = new Animation(player_use_potion_path.string(), player_models.at(i).second);

animManager->addAnimation(player_walk, player_models.at(i).first, AnimState::WalkAnim);
animManager->addAnimation(player_jump, player_models.at(i).first, AnimState::JumpAnim);
animManager->addAnimation(player_idle, player_models.at(i).first, AnimState::IdleAnim);
animManager->addAnimation(player_run, player_models.at(i).first, AnimState::SprintAnim);
animManager->addAnimation(player_atk, player_models.at(i).first, AnimState::AttackAnim);
animManager->addAnimation(player_use_potion, player_models.at(i).first, AnimState::DrinkPotionAnim);
}

this->configureGBuffer();

Expand Down Expand Up @@ -825,7 +842,7 @@ void Client::geometryPass() {
break; // don't render dead players
}

animManager->setAnimation(sharedObject->globalID, sharedObject->type, sharedObject->animState);
animManager->setAnimation(sharedObject->globalID, sharedObject->modelType, sharedObject->animState);

/* Update model animation */
animManager->updateAnimation(timeElapsed);
Expand All @@ -846,11 +863,28 @@ void Client::geometryPass() {
player_dir = glm::vec3(0.0f, 0.0f, 1.0f);
}
player_dir.y = 0.0f;
this->player_model->rotateAbsolute(glm::normalize(player_dir), true);
this->player_model->translateAbsolute(player_pos);
// this->player_model->setDimensions(sharedObject->physics.dimensions);
this->player_model->scaleAbsolute(PLAYER_MODEL_SCALE);
this->player_model->draw(

Model* curr_player_model;
switch (sharedObject->modelType) {
case ModelType::PlayerFire:
curr_player_model = this->fire_player_model.get();
break;
case ModelType::PlayerLightning:
curr_player_model = this->lightning_player_model.get();
break;
case ModelType::PlayerWater:
curr_player_model = this->water_player_model.get();
break;
default:
std::cerr << "WARNING: player with non valid model type detected, defaulting to fire...";
curr_player_model = this->fire_player_model.get();
break;
}

curr_player_model->rotateAbsolute(glm::normalize(player_dir), true);
curr_player_model->translateAbsolute(player_pos);
curr_player_model->scaleAbsolute(PLAYER_MODEL_SCALE);
curr_player_model->draw(
this->deferred_geometry_shader.get(),
this->cam->getPos(),
true);
Expand All @@ -859,29 +893,29 @@ void Client::geometryPass() {
}
// CHANGE THIS
case ObjectType::DungeonMaster: {
// don't render yourself
// shouldn't render DM at all?

if (sharedObject->globalID == self_eid) {
// TODO: Update the player eye level to an acceptable level
glm::vec3 pos = sharedObject->physics.getCenterPosition();
pos.y += PLAYER_EYE_LEVEL;
cam->updatePos(pos);
break;
}

auto player_pos = sharedObject->physics.corner;
auto player_dir = sharedObject->physics.facing;

// this->player_model->setDimensions(sharedObject->physics.dimensions);
this->player_model->translateAbsolute(player_pos);
if (player_dir == glm::vec3(0.0f)) {
player_dir = glm::vec3(0.0f, 0.0f, 1.0f);
}
player_dir.y = 0.0f;
this->player_model->rotateAbsolute(glm::normalize(player_dir), true);
this->player_model->draw(
this->deferred_geometry_shader.get(),
this->cam->getPos(),
true);
// auto player_pos = sharedObject->physics.corner;
// auto player_dir = sharedObject->physics.facing;

// // this->player_model->setDimensions(sharedObject->physics.dimensions);
// this->player_model->translateAbsolute(player_pos);
// if (player_dir == glm::vec3(0.0f)) {
// player_dir = glm::vec3(0.0f, 0.0f, 1.0f);
// }
// player_dir.y = 0.0f;
// this->player_model->rotateAbsolute(glm::normalize(player_dir), true);
// this->player_model->draw(
// this->deferred_geometry_shader.get(),
// this->cam->getPos(),
// true);
break;
}
case ObjectType::Slime: {
Expand Down
2 changes: 2 additions & 0 deletions src/server/game/introcutscene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ IntroCutscene::IntroCutscene():
// hard code direction to face right based on the intro cutscene maze orientation
Player* player = new Player(this->state.getGrid().getRandomSpawnPoint(), directionToFacing(Direction::RIGHT));
Player* player_left = new Player(this->state.getGrid().getRandomSpawnPoint(), directionToFacing(Direction::RIGHT));
player_left->modelType = ModelType::PlayerLightning;
Player* player_right = new Player(this->state.getGrid().getRandomSpawnPoint(), directionToFacing(Direction::RIGHT));
player_right->modelType = ModelType::PlayerWater;

this->state.objects.createObject(player);
this->state.objects.createObject(player_left);
Expand Down
5 changes: 3 additions & 2 deletions src/server/game/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ std::unordered_map<ModelType, glm::vec3> Object::models ({
// can't move around anywhere. we should eventually solve this
// by tucking in the player's arms since right now they're
// spread out in the model
{ModelType::Player, {FIRE_PLAYER_DIMENSIONS * PLAYER_BBOX_SCALE}}, // for bbox, rendering is done separately in geometryPass b/c weird
// discrepencies between the model size in world and reported dimensions
{ModelType::PlayerFire, {FIRE_PLAYER_DIMENSIONS * PLAYER_BBOX_SCALE}},
{ModelType::PlayerLightning, {LIGHTNING_PLAYER_DIMENSIONS * PLAYER_BBOX_SCALE}},
{ModelType::PlayerWater, {WATER_PLAYER_DIMENSIONS * PLAYER_BBOX_SCALE}},
{ModelType::WarrenBear, (BEAR_DIMENSIONS / 4.0f)},
{ModelType::Torchlight, glm::vec3(1.0f)},
{ModelType::SunGod, (SUNGOD_DIMENSIONS / 2.0f)}
Expand Down
2 changes: 1 addition & 1 deletion src/server/game/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ SharedObject Player::toShared() {
}

Player::Player(glm::vec3 corner, glm::vec3 facing):
Creature(ObjectType::Player, corner, facing, ModelType::Player, SharedStats(
Creature(ObjectType::Player, corner, facing, ModelType::PlayerFire, SharedStats(
Stat(0, 100, 100),
Stat(0, 10, 5)
)),
Expand Down
25 changes: 24 additions & 1 deletion src/server/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,30 @@ std::chrono::milliseconds Server::doTick() {
}

std::cout << "Assigned player " + std::to_string(index) + " to be the DM" << std::endl;
std::cout << "Starting game!" << std::endl;
}

int player_idx = 0; // only increment when assigning a model

auto players = this->state.objects.getPlayers();
for (int i = 0; i < players.size(); i++) {
auto player = players.get(i);
if (player == nullptr) continue;

if (player_idx == 0) {
player->modelType = ModelType::PlayerFire;
}
else if (player_idx == 1) {
player->modelType = ModelType::PlayerLightning;
}
else if (player_idx == 2) {
player->modelType = ModelType::PlayerWater;
}

player_idx++;

if (player_idx > 2) {
player_idx = 0;
}
}

if (this->config.server.skip_intro) {
Expand Down

0 comments on commit fc0e16e

Please sign in to comment.