#include "precompile.h" #include "playermgr.h" #include "player.h" #include "cs_proto.pb.h" #include "room.h" #include "android.h" #include "metamgr.h" #include "movement.h" #include "bullet.h" #include "collider.h" #include "obstacle.h" const int ROOM_MAX_PLAYER_NUM = 50; const int ANDROID_NUM = 0; void Room::Update(int delta_time) { elapsed_time_ += delta_time; while (elapsed_time_ >= 50) { ResetFrameData(); int i = 0; for (auto& pair : moveable_hash_) { pair.second->Update(50); pair.second->updated_times++; ++i; assert(i < 1000); } ClearDeletedObjects(); ProcAddedObjects(); elapsed_time_ -= 50; } } bool Room::IsFull() { return accountid_hash_.size() >= ROOM_MAX_PLAYER_NUM; } int Room::GetPlayerNum() { return accountid_hash_.size(); } Player* Room::GetPlayerByAccountId(const std::string& accountid) { auto itr = accountid_hash_.find(accountid); return itr != accountid_hash_.end() ? itr->second : nullptr; } Player* Room::GetPlayerByUniId(unsigned short uniid) { Entity* entity = GetEntityByUniId(uniid); return entity->entity_type == ET_Player && entity->entity_subtype == EST_Player ? (Player*)entity : nullptr; } Entity* Room::GetEntityByUniId(unsigned short uniid) { auto itr = uniid_hash_.find(uniid); return itr != uniid_hash_.end() ? itr->second : nullptr; } int Room::AliveCount() { return alive_count_; } void Room::AddPlayer(Player* hum) { { hum->pos.x = 1000 + rand() % 100; hum->pos.y = 2000 + rand() % 200; hum->attack_dir = hum->pos; hum->attack_dir.Normalize(); hum->attack_dir.Rotate(a8::RandAngle()); } hum->room = this; uniid_hash_[hum->entity_uniid] = hum; moveable_hash_[hum->entity_uniid] = hum; accountid_hash_[hum->account_id] = hum; human_hash_[hum->entity_uniid] = hum; ++alive_count_; hum->new_objects.insert(hum); hum->part_objects.insert(hum); for (auto& pair : human_hash_) { if (pair.second != hum) { pair.second->new_objects.insert(hum); pair.second->part_objects.insert(hum); hum->new_objects.insert(pair.second); hum->part_objects.insert(pair.second); } } } unsigned short Room::AllocUniid() { while (GetEntityByUniId(++current_uniid) || be_added_hash_.find(current_uniid) != be_added_hash_.end() || current_uniid == 0) {} return current_uniid; } void Room::ShuaAndroid() { MetaData::Player* hum_meta = MetaMgr::Instance()->GetPlayer(40002); assert(hum_meta); if (!hum_meta) { abort(); } for (int i = 0; i < ANDROID_NUM; ++i) { Android* hum = new Android(); hum->name = a8::Format("机器人%d", {i+1}); hum->meta = hum_meta; hum->entity_uniid = AllocUniid(); { hum->pos.x = 100 + rand() % 400; hum->pos.y = 200 + rand() % 500; hum->attack_dir = hum->pos; hum->attack_dir.Normalize(); hum->attack_dir.Rotate(a8::RandAngle()); } hum->room = this; hum->Initialize(); uniid_hash_[hum->entity_uniid] = hum; moveable_hash_[hum->entity_uniid] = hum; human_hash_[hum->entity_uniid] = hum; ++alive_count_; for (auto& pair : human_hash_) { if (pair.second != hum) { pair.second->new_objects.insert(hum); pair.second->part_objects.insert(hum); hum->new_objects.insert(pair.second); hum->part_objects.insert(pair.second); } } } } void Room::ShuaObstacle(Human* hum) { MetaData::MapThing* a_thing = MetaMgr::Instance()->GetMapThing(61001); MetaData::MapThing* b_thing = MetaMgr::Instance()->GetMapThing(61007); if (!a_thing || !b_thing) { return; } #if 1 { Obstacle* entity = new Obstacle(); entity->room = this; entity->meta = a_thing; entity->entity_uniid = AllocUniid(); #if 0 entity->dir = Vector2D::UP; #endif #if 0 entity->pos = Vector2D(100.0f, 164.0f); #else entity->pos = hum->pos - Vector2D::LEFT * hum->meta->i->radius() - 100; #endif entity->Initialize(); uniid_hash_[entity->entity_uniid] = entity; for (auto& pair : human_hash_) { pair.second->new_objects.insert(entity); pair.second->part_objects.insert(entity); } } #endif #if 1 { Obstacle* entity = new Obstacle(); entity->room = this; entity->meta = b_thing; entity->entity_uniid = AllocUniid(); #if 0 entity->dir = Vector2D::UP; #endif #if 0 entity->pos = Vector2D(100.0f, 100.0f); #else entity->pos = hum->pos + Vector2D::RIGHT * hum->meta->i->radius() + 100; #endif entity->Initialize(); uniid_hash_[entity->entity_uniid] = entity; for (auto& pair : human_hash_) { pair.second->new_objects.insert(entity); pair.second->part_objects.insert(entity); } } #endif } bool Room::RandomPos(Human* hum, float distance, Vector2D& out_pos) { Vector2D dir = hum->pos; dir.Rotate(a8::RandAngle()); dir.Normalize(); CircleCollider collider; collider.owner = hum; collider.pos = dir * distance; collider.rad = hum->meta->i->radius(); for (auto& pair : uniid_hash_) { if (pair.second->entity_type == ET_Player || pair.second->entity_type == ET_Bullet ) { continue; } else { for (auto& itr : pair.second->colliders) { if (collider.Intersect(itr)) { return false; } } } } out_pos = hum->pos + collider.pos; return true; } Human* Room::FindEnemy(Human* hum) { std::vector enemys; enemys.reserve(50); for (auto& pair : accountid_hash_) { if (pair.second->team_id == 0 || pair.second->team_id != hum->team_id ) { enemys.push_back(pair.second); } } std::sort(enemys.begin(), enemys.end(), [hum] (Human* a, Human *b) -> bool { return (hum->pos - a->pos).Norm() < (hum->pos - b->pos).Norm(); }); return !enemys.empty() ? enemys[0] : nullptr; } void Room::AddBullet(Bullet* bullet) { be_added_hash_[bullet->entity_uniid] = bullet; } void Room::CollisionDetection(Entity* sender, int detection_flags, std::vector& objects) { assert(uniid_hash_.size() < 1000); for (auto& pair : uniid_hash_) { if (a8::HasBitFlag(detection_flags, ET_Player) && pair.second->entity_type == ET_Player) { if (sender->entity_type == ET_Bullet) { Bullet* bullet = (Bullet*)sender; Human* hum = (Human*)pair.second; if (hum != bullet->player && (hum->team_id == 0 || bullet->player->team_id != hum->team_id)) { if (bullet->TestCollision(hum)) { objects.push_back(hum); } } } } if (a8::HasBitFlag(detection_flags, ET_Obstacle) && pair.second->entity_type == ET_Obstacle) { if (sender->entity_type == ET_Bullet || sender->entity_type == ET_Player) { if (pair.second != sender && sender->TestCollision(pair.second)) { objects.push_back(pair.second); } } } } } void Room::AddDeletedObject(unsigned short obj_uniid) { frame_data.deleted_objects.insert(obj_uniid); } void Room::FillSMJoinedNotify(Player* self_hum, cs::SMJoinedNotify& msg) { msg.set_team_mode(msg.team_mode()); msg.set_player_id(self_hum->entity_uniid); msg.set_started(false); for (auto& pair : uniid_hash_) { if (pair.second->entity_type == ET_Player) { Human* hum = (Human*)pair.second; cs::MFPlayerInfo* info = msg.add_player_infos(); info->set_player_id(hum->entity_uniid); info->set_team_id(hum->team_id); info->set_name(hum->name); } } } void Room::ResetFrameData() { frame_data.deleted_objects.clear(); frame_data.explosions.Clear(); frame_data.emotes.Clear(); frame_data.bullets.Clear(); frame_data.shots.Clear(); } void Room::ClearDeletedObjects() { for (auto& obj_uniid : frame_data.deleted_objects) { Entity* entity = GetEntityByUniId(obj_uniid); if (entity) { if (entity->entity_type != ET_Player) { uniid_hash_.erase(entity->entity_uniid); moveable_hash_.erase(entity->entity_uniid); } delete entity; } } } void Room::TouchPlayerList(a8::XParams param, std::function func) { if (!func) { return; } for (auto& pair : accountid_hash_) { if (pair.second) { func(pair.second, param); } } } void Room::ProcAddedObjects() { if (!be_added_hash_.empty()) { for (auto& pair : be_added_hash_) { uniid_hash_[pair.second->entity_uniid] = pair.second; switch (pair.second->entity_type) { case ET_Player: case ET_Bullet: { moveable_hash_[pair.second->entity_uniid] = pair.second; } break; default: abort(); break; } } be_added_hash_.clear(); } } void Room::BeAddedObject(Entity* entity) { be_added_hash_[entity->entity_uniid] = entity; }