Exemple #1
0
    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;
 }
Exemple #3
0
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;
    }
Exemple #7
0
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;
}
Exemple #8
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];
    }
}
Exemple #9
0
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];
}