0

我想将 2D 精灵缩放为与节点的碰撞框一样大。

我只设法使用Node::SetScale一些手动缩放计算来做到这一点,但我宁愿不使用这种方法,因为它是复杂的,因为我还必须考虑身体的缩放因子。

但是,我找不到该类的SetScale方法StaticSprite2D

关键代码部分是:

#if 0
        // Sprite and collision have the same size,
        // like I want it, but I feel this is very convoluted.
        auto rect = boxSprite->GetRectangle();
        auto scaleX = PIXEL_SIZE * rect.Width();
        auto scaleY = PIXEL_SIZE * rect.Height();
        node->SetScale(Vector3(groundWidth / scaleX, groundHeight / scaleY, 0.0f));
        shape->SetSize(Vector2(scaleX, scaleY));
#else
        // Collision shape is correct, but the sprite is smaller
        // so not what I want.
        shape->SetSize(Vector2(groundWidth, groundHeight));
#endif

下面的完整可运行代码,使用以下样板测试:https ://github.com/cirosantilli/Urho3D-cheat/blob/8c785b38481aa5af48837c5bc3706e46f704ef37/scale_sprite.cpp和 Urho3D @ 5e8a275:

#include <Urho3D/Core/CoreEvents.h>
#include <Urho3D/Core/Object.h>
#include <Urho3D/Engine/Application.h>
#include <Urho3D/Engine/Engine.h>
#include <Urho3D/Engine/EngineDefs.h>
#include <Urho3D/Graphics/Camera.h>
#include <Urho3D/Graphics/DebugRenderer.h>
#include <Urho3D/Graphics/Graphics.h>
#include <Urho3D/Graphics/Octree.h>
#include <Urho3D/Graphics/Renderer.h>
#include <Urho3D/Input/Input.h>
#include <Urho3D/Input/InputEvents.h>
#include <Urho3D/Physics/PhysicsEvents.h>
#include <Urho3D/Resource/ResourceCache.h>
#include <Urho3D/Scene/Scene.h>
#include <Urho3D/Scene/SceneEvents.h>
#include <Urho3D/Urho2D/CollisionBox2D.h>
#include <Urho3D/Urho2D/CollisionCircle2D.h>
#include <Urho3D/Urho2D/Drawable2D.h>
#include <Urho3D/Urho2D/PhysicsWorld2D.h>
#include <Urho3D/Urho2D/RigidBody2D.h>
#include <Urho3D/Urho2D/Sprite2D.h>
#include <Urho3D/Urho2D/StaticSprite2D.h>

using namespace Urho3D;

class Main : public Application {
    URHO3D_OBJECT(Main, Application);
public:
    Main(Context* context) : Application(context) {
    }
    virtual void Setup() override {
        engineParameters_[EP_FULL_SCREEN] = false;
    }
    void Start() {
        SubscribeToEvent(E_POSTRENDERUPDATE, URHO3D_HANDLER(Main, HandlePostRenderUpdate));
        this->scene_ = new Scene(this->context_);
        scene_->CreateComponent<Octree>();
        scene_->CreateComponent<DebugRenderer>();
        scene_->CreateComponent<PhysicsWorld2D>();
        auto physicsWorld = scene_->GetComponent<PhysicsWorld2D>();
        auto cameraNode_ = scene_->CreateChild("camera");
        cameraNode_->SetPosition(Vector3(0.0f, 0.0f, -1.0f));
        auto camera = cameraNode_->CreateComponent<Camera>();
        camera->SetOrthographic(true);
        camera->SetOrthoSize(4.0);
        auto graphics = GetSubsystem<Graphics>();
        auto renderer = GetSubsystem<Renderer>();
        SharedPtr<Viewport> viewport(new Viewport(context_, scene_, cameraNode_->GetComponent<Camera>()));
        renderer->SetViewport(0, viewport);
        auto cache = GetSubsystem<ResourceCache>();
        auto boxSprite = cache->GetResource<Sprite2D>("Urho2D/Box.png");

        auto groundWidth = 2.0;
        auto groundHeight = 2.0;
        auto node = this->scene_->CreateChild("ground");
        node->SetPosition(Vector3(0.0f, 0.0f, 0.0f));
        node->CreateComponent<RigidBody2D>();
        auto shape = node->CreateComponent<CollisionBox2D>();
#if 0
        // Sprite and collision have the same size,
        // like I want it, but I feel this is very convoluted.
        auto rect = boxSprite->GetRectangle();
        auto scaleX = PIXEL_SIZE * rect.Width();
        auto scaleY = PIXEL_SIZE * rect.Height();
        node->SetScale(Vector3(groundWidth / scaleX, groundHeight / scaleY, 0.0f));
        shape->SetSize(Vector2(scaleX, scaleY));
#else
        // Collision shape is correct, but the sprite is smaller
        // so not what I want.
        shape->SetSize(Vector2(groundWidth, groundHeight));
#endif
        auto staticSprite = node->CreateComponent<StaticSprite2D>();
        staticSprite->SetSprite(boxSprite);
    }
    void Stop() {}
private:
    SharedPtr<Scene> scene_;
    void HandlePostRenderUpdate(StringHash eventType, VariantMap& eventData) {
        auto physicsWorld = this->scene_->GetComponent<PhysicsWorld2D>();
        physicsWorld->DrawDebugGeometry();
    }
};

URHO3D_DEFINE_APPLICATION_MAIN(Main);

有趣的是,有一个SetScaleforSprite类,据我在示例中看到的,它用于 3D 场景中的 UI。

超集:2D 中的任意着色器:

也在:https ://discourse.urho3d.io/t/how-to-scale-a-sprite2d-in-urho3d-without-rescaling-the-entire-node/3785/1

4

1 回答 1

0

StaticSprite2D::SetDrawRect

这是我需要的方法,它设置精灵在世界坐标中的大小。

它采用的矩形以原点为中心,我们只给出对象长度并忽略位置。

完整更新的工作代码位于:https ://github.com/cirosantilli/Urho3D-cheat/blob/1905d1f4824c6b88aca867c5be8ccb5dfae957f3/scale_sprite.cpp

关键线路是:

void CreateBox(float x, float y, float width, float height) {
    auto node = this->scene->CreateChild("Box");
    node->SetPosition(Vector3(x, y, 0.0f));
    node->SetRotation(Quaternion(0.0f, 0.0f, 30.0f));
    auto box = node->CreateComponent<CollisionBox2D>();
    box->SetSize(Vector2(width, height));
    box->SetRestitution(0.8);
    box->SetFriction(0.5f);
    box->SetDensity(1.0f);
    auto body = node->CreateComponent<RigidBody2D>();
    body->SetBodyType(BT_DYNAMIC);
    auto staticSprite = node->CreateComponent<StaticSprite2D>();
    staticSprite->SetSprite(this->boxSprite);
    staticSprite->SetDrawRect(Rect(
        width / 2.0f,
        -height / 2.0f,
        -width / 2.0f,
        height / 2.0f
    ));
    staticSprite->SetUseDrawRect(true);
}

学习自:https ://discourse.urho3d.io/t/how-to-scale-a-sprite2d-in-urho3d-without-rescaling-the-entire-node/3785/2

于 2017-12-05T23:07:52.287 回答