2017-01-22 16 views
0

SFMLを使用してC++で基本的なプログラムを構築しています。これにより、ユーザーはオブジェクトをズームインして画面をドラッグすることができます。私は画面を動かすことができましたが、動きはマウスと全く同期しておらず、滑らかではありません。誰も私のコードを書き直して画面がマウスで適切に動くように、どのように示唆していますか?SFMLでの画面のドラッグ

 Time time = milliseconds(5); 
     x1 = Mouse::getPosition().x; 
     y1 = Mouse::getPosition().y; 

     if (Mouse::isButtonPressed(Mouse::Left)) 
     { 
      std::cout << x1 - Mouse::getPosition().x << " " << y1 - Mouse::getPosition().y << std::endl; 
      sleep(time); 
      view.move((x1 - Mouse::getPosition().x)*2, (y1 - Mouse::getPosition().y)*2); 
     } 

答えて

0

を実際にこれを達成するために、複数の異なるアプローチがあります。最も簡単なのは、単にsf::Window::setView()を使ってウィンドウの表示を更新するだけです。

次の例のようにすることができます。コードをコピーするのではなく、コードを理解してください。

#include <SFML/Graphics.hpp> 

int main() 
{ 
    // Let's setup a window 
    sf::RenderWindow window(sf::VideoMode(640, 480), "SFML View Transformation"); 

    // Create something simple to draw 
    sf::Texture texture; 
    texture.loadFromFile("background.jpg"); 
    sf::Sprite background(texture); 

    sf::Vector2f oldPos; 
    bool moving = false; 

    float zoom = 1; 

    // Retrieve the window's default view 
    sf::View view = window.getDefaultView(); 

    while (window.isOpen()) { 
     sf::Event event; 
     while (window.pollEvent(event)) { 
      switch (event.type) { 
       case sf::Event::Closed: 
        window.close(); 
        break; 
       case sf::Event::MouseButtonPressed: 
        // Mouse button is pressed, get the position and set moving as active 
        if (event.mouseButton.button == 0) { 
         moving = true; 
         oldPos = window.mapPixelToCoords(sf::Vector2i(event.mouseButton.x, event.mouseButton.y)); 
        } 
        break; 
       case sf::Event::MouseButtonReleased: 
        // Mouse button is released, no longer move 
        if (event.mouseButton.button == 0) { 
         moving = false; 
        } 
        break; 
       case sf::Event::MouseMoved: 
        { 
         // Ignore mouse movement unless a button is pressed (see above) 
         if (!moving) 
          break; 
         // Determine the new position in world coordinates 
         const sf::Vector2f newPos = window.mapPixelToCoords(sf::Vector2i(event.mouseMove.x, event.mouseMove.y)); 
         // Determine how the cursor has moved 
         // Swap these to invert the movement direction 
         const sf::Vector2f deltaPos = oldPos - newPos; 

         // Move our view accordingly and update the window 
         view.setCenter(view.getCenter() + deltaPos); 
         window.setView(view); 

         // Save the new position as the old one 
         // We're recalculating this, since we've changed the view 
         oldPos = window.mapPixelToCoords(sf::Vector2i(event.mouseMove.x, event.mouseMove.y)); 
         break; 
        } 
       case sf::Event::MouseWheelScrolled: 
        // Ignore the mouse wheel unless we're not moving 
        if (moving) 
         break; 

        // Determine the scroll direction and adjust the zoom level 
        // Again, you can swap these to invert the direction 
        if (event.mouseWheelScroll.delta <= -1) 
         zoom = std::min(2.f, zoom + .1f); 
        else if (event.mouseWheelScroll.delta >= 1) 
         zoom = std::max(.5f, zoom - .1f); 

        // Update our view 
        view.setSize(window.getDefaultView().getSize()); // Reset the size 
        view.zoom(zoom); // Apply the zoom level (this transforms the view) 
        window.setView(view); 
        break; 
      } 
     } 

     // Draw our simple scene 
     window.clear(sf::Color::White); 
     window.draw(background); 
     window.display(); 
    } 
} 

はまた、コードだけでズームイン/アウトになることに注意してください、それはあなたのカーソル位置に向かってズームしていないだろうが、それは追加するのは簡単でなければなりません(基本的にはちょうど私がやったと同様の図を移動マウスの動き)。

+0

ちょうど注意:スクロールホイール 'デルタ 'として報告される実際の値は、ドライバーやプラットフォームに依存する可能性があり、正しいと感じるまではテストが必要かもしれません。 – Mario

+0

こんにちはマリオはあなたの詳細な応答に感謝します。私はmapPixelToCoords()を一度も使用していません。あなたはその機能が何をしているのかを簡単に説明したり、それに関する詳細な文書を私に案内してくれますか? – billy606

+0

私はLorence Hernandezがちょうどそれに答えた愚かな私。 – billy606

0

(私は十分な評判を持っていないので、代わりにコメントの答えを返信)

あなたはsleepcoutを削除しようとしたことがありますか?私はあなたがカスタムビューを使用すると、これらの二つはそれ

+0

そこに存在するかどうかは実際にはそれほど大きな影響を与えません。私は最初のマウスのcoordと最終的なマウスの座標を取得し、オフセットを得るためにそれらを引く必要があるので、私はそこに睡眠を入れた。睡眠がなければ、オフセットは0になります。 – billy606

+0

あなたが望むなら私は完全なコードを投稿して、何をしようとしているのかをより良く知ることができます。 – billy606

0

を引き起こしている、またはあなたは、ウィンドウのサイズを変更すると、ターゲットに表示されるピクセル はもはや2Dの世界での単位と一致していないかなり確信しています。 の例では、ピクセル(10,50)をクリックすると、あなたの世界 のポイント(26.5、-84)に達することがあります。変換関数を使用して ピクセル座標をワールド座標:mapPixelToCoordsにマップする必要があります。デフォルトでは

// get the current mouse position in the window 
sf::Vector2i pixelPos = sf::Mouse::getPosition(window); 

// convert it to world coordinates 
sf::Vector2f worldPos = window.mapPixelToCoords(pixelPos); 

、mapPixelToCoordsは、現在のビューを使用しています。 に、アクティブなものではないビューを使用して座標を変換する場合は、 は、それを関数の追加の引数として渡すことができます。

ワールド座標をピクセル座標に変換する逆は、mapCoordsToPixel関数でも可能な です。

あなたは、ページの下部にここでそれを見ることができます:https://www.sfml-dev.org/tutorials/2.0/graphics-view.php

0

user3881815が、それはそれはtime [ms]でスリープします保証するものではありませんので、問題はあなたのsleep(時間)とであることを示唆しているよう。その代わりに、OSスケジューリング粒度間隔の任意のカウントを追加して、不安定さを引き起こす可能性があります。言い換えれば実行をブロックすることは言うまでもなく...マウスの変更によって動かすのではなく、何らかの比率で動かすことになります(同期していないので驚くことはありません)。どのようにそれを取り除くのですか?

最後のマウスの位置を覚えておいて、処理ループ内のすべての実行を使用する必要があります。例えば:あなたのビューは、ズームを使用している場合

double mx=0,my=0,mx0=0,my0=0; // globals with actual and last mouse position 

// here your main loop or event or whatever 
for (bool exit=false;!exit;) 
{ 
// here your other stuff 

// mouse handler 
mx0=mx; mx = Mouse::getPosition().x; 
my0=my; my = Mouse::getPosition().y; 
// here convert mx,my to coordinate system the view.move needs 
if (Mouse::isButtonPressed(Mouse::Left)) view.move(mx-mx0,my-my0); 
} 

は、あなたが最も可能性の高いmx,myに座標変換適用する必要があるが、それはview.moveが望んでいるものの中に依存します。

私は、私はあなたのビューでの経験がないが、あなたはview.zoomがどこにあるか、あなたのマウスと同期して動きを作るために

view.move((mx-mx0)*view.zoom,(my-my0)*view.zoom); 

または

view.move((mx-mx0)/view.zoom,(my-my0)/view.zoom); 

を試すことができますSFMLでコーディングしませんあなたのビューのスケール。どちらがview表記に依存しているか。

マウスをよりよく扱うには、mousedown、mouseup、mousemoveの各イベントを処理できるように、最後と実際のボタンの状態が必要です。詳細情報については以下を参照してください

関連する問題