void World::setLevel(const Level::Level& level, const DiabloExe::DiabloExe& exe) { const std::vector<Level::Monster>& monsters = level.getMonsters(); for(size_t i = 0; i < monsters.size(); i++) mActors.push_back(new Monster(exe.getMonster(monsters[i].name), Position(monsters[i].xPos, monsters[i].yPos))); }
std::set<const loader::Room*> CollisionInfo::collectNeighborRooms(const core::ExactTRCoordinates& position, int radius, int height, const level::Level& level) { std::set<const loader::Room*> result; result.insert(level.m_lara->getCurrentRoom()); result.insert(level.findRoomForPosition(position + core::ExactTRCoordinates(radius, 0, radius), level.m_lara->getCurrentRoom())); result.insert(level.findRoomForPosition(position + core::ExactTRCoordinates(-radius, 0, radius), level.m_lara->getCurrentRoom())); result.insert(level.findRoomForPosition(position + core::ExactTRCoordinates(radius, 0, -radius), level.m_lara->getCurrentRoom())); result.insert(level.findRoomForPosition(position + core::ExactTRCoordinates(-radius, 0, -radius), level.m_lara->getCurrentRoom())); result.insert(level.findRoomForPosition(position + core::ExactTRCoordinates(radius, -height, radius), level.m_lara->getCurrentRoom())); result.insert(level.findRoomForPosition(position + core::ExactTRCoordinates(-radius, -height, radius), level.m_lara->getCurrentRoom())); result.insert(level.findRoomForPosition(position + core::ExactTRCoordinates(radius, -height, -radius), level.m_lara->getCurrentRoom())); result.insert(level.findRoomForPosition(position + core::ExactTRCoordinates(-radius, -height, -radius), level.m_lara->getCurrentRoom())); return result; }
void Renderer::renderLoop() { Render::LevelObjects objects; while(!Input::InputManager::get()) {} while(!mDone) { Input::InputManager::get()->poll(); RenderState* current = mCurrent; if(mRenderThreadState == levelChange) { delete mLevel; Level::Level* level = (Level::Level*)mThreadCommunicationTmp; mLevel = Render::setLevel(*level); objects.resize(level->width(), level->height()); mRenderThreadState = running; } else if(mRenderThreadState == loadSprite) { FASpriteGroup* tmp = new FASpriteGroup((CacheSpriteGroup*)NULL); *tmp = loadImageImp(*(std::string*)mThreadCommunicationTmp); mThreadCommunicationTmp = (void*)tmp; mRenderThreadState = running; } else if(mRenderThreadState == guiLoadTexture) { LoadGuiTextureStruct* st = (LoadGuiTextureStruct*) mThreadCommunicationTmp; mThreadCommunicationTmp = (void*) Render::guiLoadImage(*(st->texture_handle), *(st->texture_dimensions), *(st->source)); mRenderThreadState = running; } else if(mRenderThreadState == guiGenerateTexture) { GenerateGuiTextureStruct* st = (GenerateGuiTextureStruct*) mThreadCommunicationTmp; mThreadCommunicationTmp = (void*) Render::guiGenerateTexture(*(st->texture_handle), st->source, *(st->source_dimensions)); mRenderThreadState = running; } else if(mRenderThreadState == guiReleaseTexture) { Render::guiReleaseTexture(*((Rocket::Core::TextureHandle*)mThreadCommunicationTmp)); mRenderThreadState = running; } else if(mRenderThreadState == pause) { mRenderThreadState = stopped; } else if(mRenderThreadState == spriteDestroy) { Render::SpriteGroup* s = (Render::SpriteGroup*)mThreadCommunicationTmp; s->destroy(); mRenderThreadState = running; } if(mRenderThreadState == running && current && current->mMutex.try_lock()) { for(size_t x = 0; x < objects.width(); x++) { for(size_t y = 0; y < objects.height(); y++) { objects[x][y].sprite = NULL; } } for(size_t i = 0; i < current->mObjects.size(); i++) { size_t x = current->mObjects[i].get<2>().current().first; size_t y = current->mObjects[i].get<2>().current().second; objects[x][y].sprite = (*current->mObjects[i].get<0>().get()).mSpriteGroup[current->mObjects[i].get<1>()]; objects[x][y].x2 = current->mObjects[i].get<2>().next().first; objects[x][y].y2 = current->mObjects[i].get<2>().next().second; objects[x][y].dist = current->mObjects[i].get<2>().mDist; } Render::drawLevel(mLevel, objects, current->mPos.current().first, current->mPos.current().second, current->mPos.next().first, current->mPos.next().second, current->mPos.mDist); Render::drawGui(current->guiDrawBuffer); current->mMutex.unlock(); } Render::draw(); } // destroy all remaining sprites here, otherwise they would be destoyed in the game thread, which would not work for(std::map<std::string, boost::weak_ptr<CacheSpriteGroup> >::iterator it = mSpriteCache.begin(); it != mSpriteCache.end(); ++it) { it->second.lock().get()->destroy(); } }
void CollisionInfo::initHeightInfo(const core::ExactTRCoordinates& laraPos, const level::Level& level, int height) { axisCollisions = AxisColl_None; collisionFeedback = {0,0,0}; orientationAxis = *core::axisFromAngle(yAngle, 45_deg); gsl::not_null<const loader::Room*> room = level.m_lara->getCurrentRoom(); const auto refTestPos = laraPos - core::ExactTRCoordinates(0, height + core::ScalpToHandsHeight, 0); gsl::not_null<const loader::Sector*> currentSector = level.findFloorSectorWithClampedPosition(refTestPos.toInexact(), &room); current.init(currentSector, refTestPos.toInexact(), level.m_cameraController, laraPos.Y, height); std::tie(floorSlantX, floorSlantZ) = level.getFloorSlantInfo(currentSector, laraPos.toInexact()); float frontX = 0, frontZ = 0; float frontLeftX = 0, frontLeftZ = 0; float frontRightX = 0, frontRightZ = 0; switch( orientationAxis ) { case core::Axis::PosZ: frontX = yAngle.sin() * collisionRadius; frontZ = collisionRadius; frontLeftZ = collisionRadius; frontLeftX = -collisionRadius; frontRightX = collisionRadius; frontRightZ = collisionRadius; break; case core::Axis::PosX: frontX = collisionRadius; frontZ = yAngle.cos() * collisionRadius; frontLeftX = collisionRadius; frontLeftZ = collisionRadius; frontRightX = collisionRadius; frontRightZ = -collisionRadius; break; case core::Axis::NegZ: frontX = yAngle.sin() * collisionRadius; frontZ = -collisionRadius; frontLeftX = collisionRadius; frontLeftZ = -collisionRadius; frontRightX = -collisionRadius; frontRightZ = -collisionRadius; break; case core::Axis::NegX: frontX = -collisionRadius; frontZ = yAngle.cos() * collisionRadius; frontLeftX = -collisionRadius; frontLeftZ = -collisionRadius; frontRightX = -collisionRadius; frontRightZ = collisionRadius; break; } // Front auto testPos = refTestPos + core::ExactTRCoordinates(frontX, 0, frontZ); auto sector = level.findFloorSectorWithClampedPosition(testPos.toInexact(), &room); front.init(sector, testPos.toInexact(), level.m_cameraController, laraPos.Y, height); if( (frobbelFlags & FrobbelFlag_UnpassableSteepUpslant) != 0 && front.floor.slantClass == SlantClass::Steep && front.floor.distance < 0 ) { front.floor.distance = -32767; } else if( front.floor.distance > 0 && ( ((frobbelFlags & FrobbelFlag_UnwalkableSteepFloor) != 0 && front.floor.slantClass == SlantClass::Steep) || ((frobbelFlags & FrobbelFlag_UnwalkableDeadlyFloor) != 0 && front.floor.lastTriggerOrKill != nullptr && loader::extractFDFunction(*front.floor.lastTriggerOrKill) == loader::FDFunction::Death) ) ) { front.floor.distance = 2 * loader::QuarterSectorSize; } // Front left testPos = refTestPos + core::ExactTRCoordinates(frontLeftX, 0, frontLeftZ); sector = level.findFloorSectorWithClampedPosition(testPos.toInexact(), &room); frontLeft.init(sector, testPos.toInexact(), level.m_cameraController, laraPos.Y, height); if( (frobbelFlags & FrobbelFlag_UnpassableSteepUpslant) != 0 && frontLeft.floor.slantClass == SlantClass::Steep && frontLeft.floor.distance < 0 ) { frontLeft.floor.distance = -32767; } else if( frontLeft.floor.distance > 0 && ( ((frobbelFlags & FrobbelFlag_UnwalkableSteepFloor) != 0 && frontLeft.floor.slantClass == SlantClass::Steep) || ((frobbelFlags & FrobbelFlag_UnwalkableDeadlyFloor) != 0 && frontLeft.floor.lastTriggerOrKill != nullptr && loader::extractFDFunction(*frontLeft.floor.lastTriggerOrKill) == loader::FDFunction::Death) ) ) { frontLeft.floor.distance = 2 * loader::QuarterSectorSize; } // Front right testPos = refTestPos + core::ExactTRCoordinates(frontRightX, 0, frontRightZ); sector = level.findFloorSectorWithClampedPosition(testPos.toInexact(), &room); frontRight.init(sector, testPos.toInexact(), level.m_cameraController, laraPos.Y, height); if( (frobbelFlags & FrobbelFlag_UnpassableSteepUpslant) != 0 && frontRight.floor.slantClass == SlantClass::Steep && frontRight.floor.distance < 0 ) { frontRight.floor.distance = -32767; } else if( frontRight.floor.distance > 0 && ( ((frobbelFlags & FrobbelFlag_UnwalkableSteepFloor) != 0 && frontRight.floor.slantClass == SlantClass::Steep) || ((frobbelFlags & FrobbelFlag_UnwalkableDeadlyFloor) != 0 && frontRight.floor.lastTriggerOrKill != nullptr && loader::extractFDFunction(*frontRight.floor.lastTriggerOrKill) == loader::FDFunction::Death) ) ) { frontRight.floor.distance = 2 * loader::QuarterSectorSize; } checkStaticMeshCollisions(laraPos, height, level); if( current.floor.distance == -loader::HeightLimit ) { collisionFeedback = position - laraPos; axisCollisions = AxisColl_FrontForwardBlocked; return; } if( current.floor.distance <= current.ceiling.distance ) { axisCollisions = AxisColl_InvalidPosition; collisionFeedback = position - laraPos; return; } if( current.ceiling.distance >= 0 ) { axisCollisions = AxisColl_ScalpCollision; collisionFeedback.Y = current.ceiling.distance; } if( front.floor.distance > passableFloorDistanceBottom || front.floor.distance < passableFloorDistanceTop || front.ceiling.distance > neededCeilingDistance ) { axisCollisions = AxisColl_FrontForwardBlocked; switch( orientationAxis ) { case core::Axis::PosZ: case core::Axis::NegZ: collisionFeedback.X = position.X - laraPos.X; collisionFeedback.Z = reflectAtSectorBoundary(frontZ + laraPos.Z, laraPos.Z); break; case core::Axis::PosX: case core::Axis::NegX: collisionFeedback.X = reflectAtSectorBoundary(frontX + laraPos.X, laraPos.X); collisionFeedback.Z = position.Z - laraPos.Z; break; } return; } if( front.ceiling.distance >= neededCeilingDistance ) { axisCollisions = AxisColl_InsufficientFrontCeilingSpace; collisionFeedback = position - laraPos; return; } if( frontLeft.floor.distance > passableFloorDistanceBottom || frontLeft.floor.distance < passableFloorDistanceTop ) { axisCollisions = AxisColl_FrontLeftBlocked; switch( orientationAxis ) { case core::Axis::PosZ: case core::Axis::NegZ: collisionFeedback.X = reflectAtSectorBoundary(frontLeftX + laraPos.X, frontX + laraPos.X); break; case core::Axis::PosX: case core::Axis::NegX: collisionFeedback.Z = reflectAtSectorBoundary(frontLeftZ + laraPos.Z, frontZ + laraPos.Z); break; } return; } if( frontRight.floor.distance > passableFloorDistanceBottom || frontRight.floor.distance < passableFloorDistanceTop ) { axisCollisions = AxisColl_FrontRightBlocked; switch( orientationAxis ) { case core::Axis::PosZ: case core::Axis::NegZ: collisionFeedback.X = reflectAtSectorBoundary(frontRightX + laraPos.X, frontX + laraPos.X); break; case core::Axis::PosX: case core::Axis::NegX: collisionFeedback.Z = reflectAtSectorBoundary(frontRightZ + laraPos.Z, frontZ + laraPos.Z); break; } } }
bool CollisionInfo::checkStaticMeshCollisions(const core::ExactTRCoordinates& position, int height, const level::Level& level) { auto rooms = collectNeighborRooms(position, collisionRadius + 50, height + 50, level); gameplay::BoundingBox baseCollisionBox( position.X - collisionRadius, position.Y - height, position.Z - collisionRadius, position.X + collisionRadius, position.Y , position.Z + collisionRadius ); hasStaticMeshCollision = false; for( const loader::Room* room : rooms ) { for( const loader::RoomStaticMesh& rsm : room->staticMeshes ) { gsl::not_null<const loader::StaticMesh*> sm = level.findStaticMeshById(rsm.meshId); if( sm->doNotCollide() ) continue; gameplay::BoundingBox meshCollisionBox = sm->getCollisionBox(rsm.position, core::Angle{rsm.rotation}); if( !meshCollisionBox.intersects(baseCollisionBox) ) continue; auto dx = meshCollisionBox.max.x - baseCollisionBox.min.x; if( baseCollisionBox.max.x - meshCollisionBox.min.x < dx ) dx = -(baseCollisionBox.max.x - meshCollisionBox.min.x); auto dz = meshCollisionBox.max.z - baseCollisionBox.min.z; if( baseCollisionBox.max.z - meshCollisionBox.min.z < dz ) dz = -(baseCollisionBox.max.z - meshCollisionBox.min.z); switch( orientationAxis ) { case core::Axis::PosX: if( dz > collisionRadius || dz < -collisionRadius ) { collisionFeedback.X = dx - 1; collisionFeedback.Z = this->position.Z - position.Z; axisCollisions = AxisColl_FrontForwardBlocked; hasStaticMeshCollision = true; return true; } if( dz > 0 && dz <= collisionRadius ) { collisionFeedback.X = 0; collisionFeedback.Z = dz; axisCollisions = AxisColl_FrontRightBlocked; hasStaticMeshCollision = true; return true; } if( dz >= 0 || dz < -collisionRadius ) { hasStaticMeshCollision = true; return true; } collisionFeedback.X = 0; collisionFeedback.Z = dz; axisCollisions = AxisColl_FrontLeftBlocked; hasStaticMeshCollision = true; return true; case core::Axis::PosZ: if( dx > collisionRadius || dx < -collisionRadius ) { collisionFeedback.X = this->position.X - position.X; collisionFeedback.Z = dz - 1; axisCollisions = AxisColl_FrontForwardBlocked; hasStaticMeshCollision = true; return true; } if( dx > 0 && dx <= collisionRadius ) { collisionFeedback.X = dx; collisionFeedback.Z = 0; axisCollisions = AxisColl_FrontLeftBlocked; hasStaticMeshCollision = true; return true; } if( dx >= 0 || dx < -collisionRadius ) { hasStaticMeshCollision = true; return true; } collisionFeedback.X = dx; collisionFeedback.Z = 0; axisCollisions = AxisColl_FrontRightBlocked; hasStaticMeshCollision = true; return true; case core::Axis::NegX: if( dz > collisionRadius || dz < -collisionRadius ) { collisionFeedback.X = dx + 1; collisionFeedback.Z = this->position.Z - position.Z; axisCollisions = AxisColl_FrontForwardBlocked; hasStaticMeshCollision = true; return true; } if( dz > 0 && dz <= collisionRadius ) { collisionFeedback.X = 0; collisionFeedback.Z = dz; axisCollisions = AxisColl_FrontLeftBlocked; hasStaticMeshCollision = true; return true; } if( dz >= 0 || dz < -collisionRadius ) { hasStaticMeshCollision = true; return true; } collisionFeedback.X = 0; collisionFeedback.Z = dz; axisCollisions = AxisColl_FrontRightBlocked; hasStaticMeshCollision = true; return true; case core::Axis::NegZ: if( dx > collisionRadius || dx < -collisionRadius ) { collisionFeedback.X = this->position.X - position.X; collisionFeedback.Z = dz + 1; axisCollisions = AxisColl_FrontForwardBlocked; hasStaticMeshCollision = true; return true; } if( dx > 0 && dx <= collisionRadius ) { collisionFeedback.X = dx; collisionFeedback.Z = 0; axisCollisions = AxisColl_FrontRightBlocked; hasStaticMeshCollision = true; return true; } if( dx >= 0 || dx < -collisionRadius ) { hasStaticMeshCollision = true; return true; } collisionFeedback.X = dx; collisionFeedback.Z = 0; axisCollisions = AxisColl_FrontLeftBlocked; hasStaticMeshCollision = true; return true; } hasStaticMeshCollision = true; return true; } } return false; }
std::shared_ptr<gameplay::Node> Room::createSceneNode(gameplay::Game* game, size_t roomId, const level::Level& level, const std::vector<std::shared_ptr<gameplay::Texture>>& textures, const std::map<loader::TextureLayoutProxy::TextureKey, std::shared_ptr<gameplay::Material>>& materials, const std::map<loader::TextureLayoutProxy::TextureKey, std::shared_ptr<gameplay::Material>>& waterMaterials, const std::vector<std::shared_ptr<gameplay::Model>>& staticMeshes, render::TextureAnimator& animator) { RenderModel renderModel; std::map<TextureLayoutProxy::TextureKey, size_t> texBuffers; std::vector<RenderVertex> vbuf; auto mesh = std::make_shared<gameplay::Mesh>(RenderVertex::getFormat(), vbuf.size(), true); for( const QuadFace& quad : rectangles ) { const TextureLayoutProxy& proxy = level.m_textureProxies.at(quad.proxyId); if( texBuffers.find(proxy.textureKey) == texBuffers.end() ) { texBuffers[proxy.textureKey] = renderModel.m_parts.size(); renderModel.m_parts.emplace_back(); auto it = isWaterRoom() ? waterMaterials.find(proxy.textureKey) : materials.find(proxy.textureKey); Expects(it != (isWaterRoom() ? waterMaterials.end() : materials.end())); renderModel.m_parts.back().material = it->second; } const auto partId = texBuffers[proxy.textureKey]; const auto firstVertex = vbuf.size(); for( int i = 0; i < 4; ++i ) { RenderVertex iv; iv.position = vertices[quad.vertices[i]].position.toRenderSystem(); iv.color = vertices[quad.vertices[i]].color; iv.texcoord0 = proxy.uvCoordinates[i].toGl(); vbuf.push_back(iv); } animator.registerVertex(quad.proxyId, {mesh, partId}, 0, firstVertex + 0); renderModel.m_parts[partId].indices.emplace_back(firstVertex + 0); animator.registerVertex(quad.proxyId, {mesh, partId}, 1, firstVertex + 1); renderModel.m_parts[partId].indices.emplace_back(firstVertex + 1); animator.registerVertex(quad.proxyId, {mesh, partId}, 2, firstVertex + 2); renderModel.m_parts[partId].indices.emplace_back(firstVertex + 2); animator.registerVertex(quad.proxyId, {mesh, partId}, 0, firstVertex + 0); renderModel.m_parts[partId].indices.emplace_back(firstVertex + 0); animator.registerVertex(quad.proxyId, {mesh, partId}, 2, firstVertex + 2); renderModel.m_parts[partId].indices.emplace_back(firstVertex + 2); animator.registerVertex(quad.proxyId, {mesh, partId}, 3, firstVertex + 3); renderModel.m_parts[partId].indices.emplace_back(firstVertex + 3); } for( const Triangle& tri : triangles ) { const TextureLayoutProxy& proxy = level.m_textureProxies.at(tri.proxyId); if( texBuffers.find(proxy.textureKey) == texBuffers.end() ) { texBuffers[proxy.textureKey] = renderModel.m_parts.size(); renderModel.m_parts.emplace_back(); auto it = isWaterRoom() ? waterMaterials.find(proxy.textureKey) : materials.find(proxy.textureKey); Expects(it != (isWaterRoom() ? waterMaterials.end() : materials.end())); renderModel.m_parts.back().material = it->second; } const auto partId = texBuffers[proxy.textureKey]; const auto firstVertex = vbuf.size(); for( int i = 0; i < 3; ++i ) { RenderVertex iv; iv.position = vertices[tri.vertices[i]].position.toRenderSystem(); iv.color = vertices[tri.vertices[i]].color; iv.texcoord0 = proxy.uvCoordinates[i].toGl(); vbuf.push_back(iv); } animator.registerVertex(tri.proxyId, {mesh, partId}, 0, firstVertex + 0); renderModel.m_parts[partId].indices.emplace_back(firstVertex + 0); animator.registerVertex(tri.proxyId, {mesh, partId}, 1, firstVertex + 1); renderModel.m_parts[partId].indices.emplace_back(firstVertex + 1); animator.registerVertex(tri.proxyId, {mesh, partId}, 2, firstVertex + 2); renderModel.m_parts[partId].indices.emplace_back(firstVertex + 2); } mesh->rebuild(reinterpret_cast<float*>(vbuf.data()), vbuf.size()); auto resModel = renderModel.toModel(mesh); node = std::make_shared<gameplay::Node>("Room:" + boost::lexical_cast<std::string>(roomId)); node->setDrawable(resModel); for( Light& light : lights ) { const auto f = std::abs(light.specularIntensity) / 8191.0f; BOOST_ASSERT(f >= 0 && f <= 1); switch( light.getLightType() ) { case LightType::Shadow: BOOST_LOG_TRIVIAL(debug) << "Light: Shadow"; light.node = gameplay::Light::createPoint(light.color.r / 255.0f * f, light.color.g / 255.0f * f, light.color.b / 255.0f * f, light.specularFade); break; case LightType::Null: case LightType::Point: BOOST_LOG_TRIVIAL(debug) << "Light: Null/Point"; light.node = gameplay::Light::createPoint(light.color.r / 255.0f * f, light.color.g / 255.0f * f, light.color.b / 255.0f * f, light.specularFade); break; case LightType::Spotlight: BOOST_LOG_TRIVIAL(debug) << "Light: Spot"; light.node = gameplay::Light::createSpot(light.color.r / 255.0f * f, light.color.g / 255.0f * f, light.color.b / 255.0f * f, light.specularFade, light.r_inner, light.r_outer); break; case LightType::Sun: BOOST_LOG_TRIVIAL(debug) << "Light: Sun"; light.node = gameplay::Light::createDirectional(light.color.r / 255.0f * f, light.color.g / 255.0f * f, light.color.b / 255.0f * f); break; } BOOST_LOG_TRIVIAL(debug) << " - Position: " << light.position.X << "/" << light.position.Y << "/" << light.position.Z; BOOST_LOG_TRIVIAL(debug) << " - Length: " << light.length; BOOST_LOG_TRIVIAL(debug) << " - Color: " << light.color.a / 255.0f << "/" << light.color.r / 255.0f << "/" << light.color.g / 255.0f << "/" << light.color.b / 255.0f; BOOST_LOG_TRIVIAL(debug) << " - Specular Fade: " << light.specularFade; BOOST_LOG_TRIVIAL(debug) << " - Specular Intensity: " << light.specularIntensity; BOOST_LOG_TRIVIAL(debug) << " - Inner: " << light.r_inner; BOOST_LOG_TRIVIAL(debug) << " - Outer: " << light.r_outer; BOOST_LOG_TRIVIAL(debug) << " - Intensity: " << light.intensity; } for( const RoomStaticMesh& sm : this->staticMeshes ) { auto idx = level.findStaticMeshIndexById(sm.meshId); BOOST_ASSERT(idx >= 0); BOOST_ASSERT(static_cast<size_t>(idx) < staticMeshes.size()); auto subNode = std::make_shared<gameplay::Node>(""); subNode->setDrawable(staticMeshes[idx]); subNode->setLocalMatrix(glm::translate(glm::mat4{1.0f}, (sm.position - position).toRenderSystem()) * glm::rotate(glm::mat4{1.0f}, util::auToRad(sm.rotation), glm::vec3{0,-1,0})); node->addChild(subNode); } node->setLocalMatrix(glm::translate(glm::mat4{1.0f}, position.toRenderSystem())); for( const Sprite& sprite : sprites ) { BOOST_ASSERT(sprite.vertex < vertices.size()); BOOST_ASSERT(sprite.texture < level.m_spriteTextures.size()); const SpriteTexture& tex = level.m_spriteTextures[sprite.texture]; auto spriteNode = std::make_shared<gameplay::Sprite>(game, textures[tex.texture], tex.right_side - tex.left_side + 1, tex.bottom_side - tex.top_side + 1, tex.buildSourceRectangle()); spriteNode->setBlendMode(gameplay::Sprite::BLEND_ADDITIVE); auto n = std::make_shared<gameplay::Node>(""); n->setDrawable(spriteNode); n->setLocalMatrix(glm::translate(glm::mat4{1.0f}, (vertices[sprite.vertex].position - core::TRCoordinates{0, tex.bottom_side / 2, 0}).toRenderSystem())); node->addChild(n); } // resultNode->addShadowVolumeSceneNode(); return node; }
int realmain(int argc, char** argv) { while(!FARender::Renderer::get()) {} FARender::Renderer& renderer = *FARender::Renderer::get(); Input::InputManager& input = *Input::InputManager::get(); size_t levelNum; boost::program_options::options_description desc("Options"); desc.add_options() ("help,h", "Print help") ("level,l", boost::program_options::value<size_t>(&levelNum)->default_value(0), "Level number to load (0-4)"); boost::program_options::variables_map vm; try { boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm); if(vm.count("help")) { std::cout << desc << std::endl; return 0; } boost::program_options::notify(vm); if(levelNum > 4) throw boost::program_options::validation_error( boost::program_options::validation_error::invalid_option_value, "level"); } catch(boost::program_options::error& e) { std::cerr << "ERROR: " << e.what() << std::endl << std::endl; std::cerr << desc << std::endl; return 1; } DiabloExe::DiabloExe exe; FAWorld::World world; FALevelGen::FAsrand(time(NULL)); std::vector<Level::Level*> levels(5); size_t currentLevel = levelNum; Level::Level* level; if(!(level = getLevel(levelNum, exe))) { done = true; } else { levels[currentLevel] = level; setLevel(levelNum, exe, world, renderer, *level); } FAWorld::Player* player = world.getPlayer(); if(levelNum == 0) player->mPos = FAWorld::Position(75, 68); else player->mPos = FAWorld::Position(level->upStairsPos().first, level->upStairsPos().second); boost::posix_time::ptime last = boost::posix_time::microsec_clock::local_time(); std::pair<size_t, size_t> destination = player->mPos.current(); // Main game logic loop while(!done) { if(mouseDown) { destination = renderer.getClickedTile(xClick, yClick); if(click) level->activate(destination.first, destination.second); click = false; } input.processInput(); if(changeLevel) { int32_t tmp = currentLevel + changeLevel; if(tmp >= 0 && tmp < (int32_t)levels.size()) { currentLevel = tmp; if(levels[currentLevel] == NULL) levels[currentLevel] = getLevel(currentLevel == 0 ? 0 : 1, exe); level = levels[currentLevel]; if(changeLevel == -1) player->mPos = FAWorld::Position(level->downStairsPos().first, level->downStairsPos().second); else player->mPos = FAWorld::Position(level->upStairsPos().first, level->upStairsPos().second); setLevel(currentLevel, exe, world, renderer, *level); } changeLevel = 0; } boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time(); while((size_t)(now.time_of_day().total_milliseconds() - last.time_of_day().total_milliseconds()) < 1000/FAWorld::World::ticksPerSecond) { boost::this_thread::sleep(boost::posix_time::milliseconds(1)); now = boost::posix_time::microsec_clock::local_time(); } last = now; if(player->mPos.current() != destination) { if(player->mPos.mDist == 0) { std::pair<float, float> vector = Misc::getVec(player->mPos.current(), destination); if(!player->mPos.mMoving) { player->mPos.mMoving = true; player->setAnimation(FAWorld::AnimState::walk); } player->mPos.mDirection = Misc::getVecDir(vector); } } else if(player->mPos.mMoving && player->mPos.mDist == 0) { player->mPos.mMoving = false; player->setAnimation(FAWorld::AnimState::idle); } if(!noclip && !(*level)[player->mPos.next().first][player->mPos.next().second].passable()) { player->mPos.mMoving = false; player->setAnimation(FAWorld::AnimState::idle); } world.update(); FARender::RenderState* state = renderer.getFreeState(); state->mPos = player->mPos; world.fillRenderState(state); renderer.setCurrentState(state); } renderer.stop(); while(!renderDone) {} // have to wait until the renderer stops before destroying all our locals for(size_t i = 0; i < levels.size(); i++) delete levels[i]; return 0; }
void runGameLoop(const bpo::variables_map& variables) { FARender::Renderer& renderer = *FARender::Renderer::get(); Input::InputManager& input = *Input::InputManager::get(); Engine::ThreadManager& threadManager = *Engine::ThreadManager::get(); DiabloExe::DiabloExe exe; if (!exe.isLoaded()) { renderer.stop(); return; } FAWorld::World world; FALevelGen::FAsrand(time(NULL)); std::vector<Level::Level*> levels(9); int32_t currentLevel = variables["level"].as<int32_t>(); Level::Level* level = NULL; FARender::Tileset tileset; FAWorld::Player* player = world.getPlayer(); FAGui::initGui(); // -1 represents the main menu if(currentLevel != -1) { if(!(level = getLevel(currentLevel, exe))) { done = true; } else { tileset = renderer.getTileset(*level); levels[currentLevel] = level; setLevel(currentLevel, exe, world, level); } player->mPos = FAWorld::Position(level->upStairsPos().first, level->upStairsPos().second); FAGui::showIngameGui(); playLevelMusic(currentLevel, threadManager); } else { paused = true; FAGui::showMainMenu(); threadManager.playMusic("music/dintro.wav"); } boost::posix_time::ptime last = boost::posix_time::microsec_clock::local_time(); std::pair<size_t, size_t> destination = player->mPos.current(); //bpt::ptree hotkeypt; Misc::readIni("resources/hotkeys.ini", hotkeypt); quit_key = Input::Hotkey("Quit", hotkeypt); noclip_key = Input::Hotkey("Noclip", hotkeypt); changelvlup_key = Input::Hotkey("Changelvlup", hotkeypt); changelvldwn_key = Input::Hotkey("Changelvldwn", hotkeypt); // Main game logic loop while(!done) { input.processInput(paused); boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time(); while((size_t)(now.time_of_day().total_milliseconds() - last.time_of_day().total_milliseconds()) < 1000/FAWorld::World::ticksPerSecond) { boost::this_thread::yield(); now = boost::posix_time::microsec_clock::local_time(); } last = now; if(!paused) { if(mouseDown) { destination = renderer.getClickedTile(xClick, yClick, *level, player->mPos); if(click) level->activate(destination.first, destination.second); click = false; } if(changeLevel) { int32_t tmp = currentLevel + changeLevel; if(tmp >= 0 && tmp < (int32_t)levels.size()) { currentLevel = tmp; if(levels[currentLevel] == NULL) levels[currentLevel] = getLevel(currentLevel, exe); level = levels[currentLevel]; if(changeLevel == -1) player->mPos = FAWorld::Position(level->downStairsPos().first, level->downStairsPos().second); else player->mPos = FAWorld::Position(level->upStairsPos().first, level->upStairsPos().second); destination = player->mPos.current(); setLevel(currentLevel, exe, world, level); tileset = renderer.getTileset(*level); playLevelMusic(currentLevel, threadManager); } changeLevel = 0; } if(player->mPos.current() != destination) { if(player->mPos.mDist == 0) { std::pair<float, float> vector = Misc::getVec(player->mPos.current(), destination); if(!player->mPos.mMoving) { player->mPos.mMoving = true; player->setAnimation(FAWorld::AnimState::walk); } player->mPos.mDirection = Misc::getVecDir(vector); } } else if(player->mPos.mMoving && player->mPos.mDist == 0) { player->mPos.mMoving = false; player->setAnimation(FAWorld::AnimState::idle); } FAWorld::Actor* actorAtNext = world.getActorAt(player->mPos.next().first, player->mPos.next().second); if(!noclip && (!(*level)[player->mPos.next().first][player->mPos.next().second].passable() || (actorAtNext != NULL && actorAtNext != player))) { player->mPos.mMoving = false; destination = player->mPos.current(); player->setAnimation(FAWorld::AnimState::idle); } world.update(); } FAGui::updateGui(); FARender::RenderState* state = renderer.getFreeState(); if(state) { state->mPos = player->mPos; state->tileset = tileset; state->level = level; world.fillRenderState(state); Render::updateGuiBuffer(&state->guiDrawBuffer); } else { Render::updateGuiBuffer(NULL); } renderer.setCurrentState(state); } renderer.stop(); for(size_t i = 0; i < levels.size(); i++) { if(levels[i]) delete levels[i]; } }
void runGameLoop(const bpo::variables_map& variables) { while(!FARender::Renderer::get()) {} FARender::Renderer& renderer = *FARender::Renderer::get(); Input::InputManager input(&keyPress, NULL, &mouseClick, &mouseRelease, &mouseMove, renderer.getRocketContext()); DiabloExe::DiabloExe exe; FAWorld::World world; FALevelGen::FAsrand(time(NULL)); std::vector<Level::Level*> levels(5); size_t currentLevel = variables["level"].as<size_t>(); Level::Level* level; if(!(level = getLevel(currentLevel, exe))) { done = true; } else { levels[currentLevel] = level; setLevel(currentLevel, exe, world, renderer, *level); } FAWorld::Player* player = world.getPlayer(); if(currentLevel == 0) player->mPos = FAWorld::Position(75, 68); else player->mPos = FAWorld::Position(level->upStairsPos().first, level->upStairsPos().second); boost::posix_time::ptime last = boost::posix_time::microsec_clock::local_time(); std::pair<size_t, size_t> destination = player->mPos.current(); FAGui::initGui(); // Main game logic loop while(!done) { if(mouseDown) { destination = renderer.getClickedTile(xClick, yClick); if(click) level->activate(destination.first, destination.second); click = false; } input.processInput(paused); if(changeLevel) { int32_t tmp = currentLevel + changeLevel; if(tmp >= 0 && tmp < (int32_t)levels.size()) { currentLevel = tmp; if(levels[currentLevel] == NULL) levels[currentLevel] = getLevel(currentLevel == 0 ? 0 : 1, exe); level = levels[currentLevel]; if(changeLevel == -1) player->mPos = FAWorld::Position(level->downStairsPos().first, level->downStairsPos().second); else player->mPos = FAWorld::Position(level->upStairsPos().first, level->upStairsPos().second); setLevel(currentLevel, exe, world, renderer, *level); } changeLevel = 0; } boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time(); while((size_t)(now.time_of_day().total_milliseconds() - last.time_of_day().total_milliseconds()) < 1000/FAWorld::World::ticksPerSecond) { boost::this_thread::sleep(boost::posix_time::milliseconds(1)); now = boost::posix_time::microsec_clock::local_time(); } last = now; if(player->mPos.current() != destination) { if(player->mPos.mDist == 0) { std::pair<float, float> vector = Misc::getVec(player->mPos.current(), destination); if(!player->mPos.mMoving) { player->mPos.mMoving = true; player->setAnimation(FAWorld::AnimState::walk); } player->mPos.mDirection = Misc::getVecDir(vector); } } else if(player->mPos.mMoving && player->mPos.mDist == 0) { player->mPos.mMoving = false; player->setAnimation(FAWorld::AnimState::idle); } if(!noclip && !(*level)[player->mPos.next().first][player->mPos.next().second].passable()) { player->mPos.mMoving = false; player->setAnimation(FAWorld::AnimState::idle); } if(!paused) world.update(); FAGui::updateGui(); FARender::RenderState* state = renderer.getFreeState(); state->mPos = player->mPos; world.fillRenderState(state); Render::updateGuiBuffer(state->guiDrawBuffer); renderer.setCurrentState(state); } FAGui::destroyGui(); renderer.stop(); while(!renderDone) {} // have to wait until the renderer stops before destroying all our locals for(size_t i = 0; i < levels.size(); i++) delete levels[i]; }