Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Wskaźnik analogowy,prymitywy-płynny ruch strzałki

Ostatnio zmodyfikowano 2015-06-07 12:49
Autor Wiadomość
wojtekwjk
Temat założony przez niniejszego użytkownika
Wskaźnik analogowy,prymitywy-płynny ruch strzałki
» 2015-06-07 00:48:18
Witam;
Od pewnego czasu zajmuje się programowaniem w Rad studio XE7.Muszę zrobić miernik analogowy z ruchomą strzałką przy pomocy prymitywów.80% projektu jest już gotowe,problem polega na tym że nie wiem jak zrobić płynny efekt poruszania się strzałki.Szukałem dość długo w internecie,ale niestety nie udało mi się znaleźć nic co by mi pomogło.W moim przypadku strzałka przeskakuje od położenia 0 do oczekiwanej wartości.Próby wciśnięcia kodu na linie o kolorze RGB (250,250,250,) powodowały powstawanie dziwnych figur na polu miernika.Poniżej zamieszczam fragment kodu.Domyślam sie że problem polega na umieszczeniu narzędzie rysujacego w odpowiednim miejscu pętli.Wskazówka porusza się na podstawie wpisanego przez użytkownika wyniku oraz współrzędnych które są na jego podstawie wyliczane.Im większy wynik tym x oraz y większe i pętla rysuje dłużej.
Będe bardzo wdzięczny za jakąkolwiek pomoc,gdyż póki co niestety utknąłem w miejscu.
Pozdrawiam.


if (wynik <50 )
{
  b=102-wynik    ;
  a=16+2*wynik;
  for (x= 16; x <=a; x++)
{
  WskazowkaBiał() ; //zerowanie wskazówki w war 0
for (y = 102; y >=b; y--)
{
}

  }
  Tarcza->Canvas->Pen->Width= 2;
  Tarcza->Canvas->Pen->Color=RGB(253,0,3);
  Tarcza->Canvas->MoveTo(180,295);
  Tarcza->Canvas->LineTo(x,y);
  Image1->Canvas->CopyRect(ProstTarcza,Tarcza->Canvas,ProstTarcza);
}
P-133273
Monika90
» 2015-06-07 11:10:48
Jeżeli chcesz mieć animację to użyj timera. To XE7 chyba ma coś takiego jak TTimer.
P-133278
Monika90
» 2015-06-07 12:49:54
A tak można to zrobić w SFML (oczywiście wiem że ten kod Ci w niczym nie pomoże, ale chciałam pokazać innym :) )
C/C++
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <random>

template < class Animation >
void run( Animation & anim )
{
    sf::ContextSettings settings;
    settings.antialiasingLevel = 8;
    sf::RenderWindow wnd( sf::VideoMode( 640, 480 ), anim.name(), sf::Style::Default, settings );
    wnd.setVerticalSyncEnabled( true );
    while( wnd.isOpen() )
    {
        sf::Event ev;
        while( wnd.pollEvent( ev ) )
        {
            switch( ev.type )
            {
            case sf::Event::Closed: wnd.close(); return;
            case sf::Event::KeyPressed: anim.key_down( ev.key.code ); break;
            }
        }
       
        anim.paint( wnd );
        anim.frame();
        wnd.display();
    }
}

constexpr double pi = 3.1415926535897932384626433832795;

class Lowpass4Pole
{
public:
    explicit Lowpass4Pole( double cutoff, double q = 1 )
    {
        k_ = 1;
        double b1 = 0.76536686473017954 / q / cutoff;
        const double b2 = 1 /( cutoff * cutoff );
        bilinear_lp( b1, b2, b1_1_, b2_1_, k_ );
       
        b1 = 1.8477590650225735 / cutoff;
        bilinear_lp( b1, b2, b1_2_, b2_2_, k_ );
    }
   
    double operator ()( double x )
    {
        x *= k_;
        const double t1 = x - h1_1_ * b1_1_ - h2_1_ * b2_1_;
        const double y1 = t1 + 2 * h1_1_ + h2_1_;
        h2_1_ = h1_1_;
        h1_1_ = t1;
       
        const double t2 = y1 - h1_2_ * b1_2_ - h2_2_ * b2_2_;
        const double y2 = t2 + 2 * h1_2_ + h2_2_;
        h2_2_ = h1_2_;
        h1_2_ = t2;
       
        return y2;
    }
   
private:
    static void bilinear_lp( double b1, double b2, double & out_b1, double & out_b2, double & k )
    {
        const double bd = 4 * b2 + 2 * b1 + 1;
        k /= bd;
        out_b1 =( 2 - 8 * b2 ) / bd;
        out_b2 =( 4 * b2 - 2 * b1 + 1 ) / bd;
    }
   
    double k_, b1_1_, b2_1_, b1_2_, b2_2_;
    double h1_1_ = 0, h2_1_ = 0, h1_2_ = 0, h2_2_ = 0;
};

class Meter
{
public:
    explicit Meter( float x, float y, float radius )
    {
        plate_.setPointCount( 64 );
        plate_.setRadius( radius + 10 );
        plate_.setOrigin( plate_.getRadius(), plate_.getRadius() );
        plate_.setPosition( x, y );
        plate_.setFillColor( { 0, 0, 0 } );
       
        hand_.setPointCount( 3 );
        hand_.setPoint( 0, { 0, - radius } );
        hand_.setPoint( 1, { - 5, 0 } );
        hand_.setPoint( 2, { 5, 0 } );
        hand_.setPosition( x, y );
        hand_.setFillColor( { 255, 0, 0 } );
    }
   
    void set( float target ) { target_ = target; }
   
    void paint( sf::RenderTarget & r ) const
    {
        r.draw( plate_ );
        r.draw( hand_ );
    }
   
    void frame()
    {
        hand_.setRotation( filter_( target_ ) * 45 );
    }
   
private:
    float target_ = 0;
    sf::ConvexShape hand_;
    sf::CircleShape plate_;
    Lowpass4Pole filter_ { 0.126, 1.1 };
};

class Demo
{
public:
    static auto name() { return "Analog Meter"; }
   
    void paint( sf::RenderTarget & r ) const
    {
        r.clear( sf::Color( 100, 180, 255 ) );
        meter_.paint( r );
    }
   
    void frame()
    {
        meter_.frame();
    }
   
    void key_down( int code )
    {
        if( code == sf::Keyboard::Space )
             meter_.set( dist_( rnd_ ) );
       
    }
   
private:
    Meter meter_ { 320, 240, 120 };
    std::mt19937 rnd_;
    std::uniform_real_distribution < float > dist_ { - 1, 1 };
};

int main()
{
    Demo d;
    run( d );
}

Program wyświetla czerwoną wskazówkę, naciśnięcie spacji powoduje przestawienie jej na losową pozycję. Wskazówka ma bezwładność.
P-133282
« 1 »
  Strona 1 z 1