Necesito ayuda con scrollbar c/c++ en juego 2d.

Iniciado por vangodp, 29 Julio 2014, 12:54 PM

0 Miembros y 1 Visitante están viendo este tema.

vangodp

¡Hola, buenas amigos!
Estoy liado con un tema que me anda consumiendo XD
Ya estuve buscando por todas las partes pero poco encontré =(.
Estoy intentando hacer un scrollbar.
Me estoy dando mil vueltas para conseguirlo.
En Internet hay millones de resultados para java, c# ,html... pero para C++ nada de nada, y lo comprendo ya que c++ no es una librería gráfica. XD
Mi intención es hacer un scrollbar para un menú de un juego en SFML pero no se como hacer.
Lo que he logrado hasta ahora es conseguir saber el tamaño de la barra de scroll según el tamaño del contenido de la imagen.
Dejo una imagen para que lo vean mejor.

No se como lograr que al desplazar la barra hacia abajo mostre el restante del contenido.
Tengo un código echo en miniwin con la ventana y la barra ya con su ancho pero no logro hacer el resto =((
Hojala me puedan ayudar.
Dejo el código de miniwin:
Código (cpp) [Seleccionar]

#include "miniwin.h"
#include <iostream>
#include <sstream>
#include <cmath>
using namespace miniwin;

int main(){
    float ancho = 800;             
    float alto  = 600;             
    float x     = 0;                 //parte de arriba de la pantalla
    float y     = 0;                 //parte izquierda de la pantalla
    float izq   = ancho-20;
    float arr   = y;
    float aba   = y+ancho;
    float der   = izq+20;     
    float borde_izquierdo = 0;     
    float borde_derecho   = ancho;
    float retraso         = 1000;   
    float velocidad       = 5;     
    float total           = 2000;     //contenido
    float visible         = alto;     //area visible del contenido(ventana)
    float scrollbar       = alto;     //digamos que es el rail donde puede desplazar la barra este es el alto de la pantalla
    float anchoBarra      = 0;        //tamaño de la barra segun el tamaño contenido
    std::stringstream ss;        //necesario para imprimir ya que miniwin no permite abrir consola.
    int t;                       
    vredimensiona(ancho, alto);
   
   

    while ( true ) {
        //LOGICA DE JUEGO
        anchoBarra = ( visible / total ) * scrollbar; //ancho de la barra.
        ss << anchoBarra;
       
        t = tecla();

        if(t==ARRIBA){
            //Desplazar hacia arriba
        }
        if(t==ABAJO){
            //Desplazar hacia abajo
        }
       
        //PINTAMOS CAMBIOS   
        color(VERDE);
        rectangulo_lleno( x, y, x+800-20, total);     //contenido
        color(ROJO);
        rectangulo_lleno( izq, arr, der, anchoBarra); //barra       
        texto(0,0,ss.str());
        refresca();                 
        borra();                     
        espera(retraso);             
    }//FIN GAMELOOP

    return 0;
}

Si quieren probar el código miniwin se puede bajar de aquí: http://miniwin.readthedocs.org/en/latest/
Es un proyecto de codeblocks. Aquí tiene una explicación de las funciones de miniwin:
http://miniwin.readthedocs.org/en/latest/
Lo hago en miniwin por que es sumamente fácil en esta librería, pero tengo pensado llevar eso a SFML. Si para vosotros es mejor SFML seria genial.
No os pido que me lo hagan solo si me pueden echar un cable o alguna pagina que pueda tirar esa duda.
¡Gracias desde ya! Un saludo.  ;-)

eferion

La idea puede ser el disponer de un "viewport" que te facilite los datos del área visible en todo momento. Los datos de este viewport se verán afectados en el momento en el que se modifique el estado de la barra de scroll

Para empezar, el control de scroll. Este puede ser todo lo complejo que quieras, pero lo básico sería algo tal que:

Código (cpp) [Seleccionar]

class ScrollBar
{
  public:

    ScrollBar( int max )
      : _max( max ),
        _position( 0 )
   { }

    void Slide( int value )
    {
      _position += value;

      _position = std::max( _position, 0 );
      _position = std::min( _position, _max );
    }

    void SlideUp( )
    { Slide( -5 ); }

    void SlideDown( )
    { Slide( +5 ); }

    int Position( ) const
    { return _position; }

  private:

    int _position;
    int _max;
};


Como se ve, te limita la posición dentro de un rango determinado. Incluye un par de funciones para hacer desplazamientos rápidos, por ejemplo si pones los botones "arriba" y "abajo" característicos de las barras de scroll.

Ahora necesitamos definir el "viewport"... básicamente no deja de ser un rectángulo que podemos desplazar al gusto:

Código (cpp) [Seleccionar]

class ViewPort
{
  public:

    ViewPort( int x, int y, int width, int height )
      : _x( x ), _y( y ), _width( width ), _height( height )
   { }

    int X( ) const
    { return _x; }

    int Y( ) const
    { return _y; }

    int Width( ) const
    { return _width; }

    int Height( ) const
    { return _height; }

    int Left( ) const
    { return _x; }

    int Right( ) const
    { return _x + _width; }

    int Top( ) const
    { return _y; }

    int Bottom( ) const
    { return _y + _height; }

     void MoveTo( int x, int y )
    {
      _x = x;
      _y = y;
    }

  private:

    int _x;
    int _y;
    int _width;
    int _height;
};


Si ahora "cosemos" un poco los elementos, podemos tener un pequeño ejemplo... eso si... sin partes gráficas:

Código (cpp) [Seleccionar]

int main( )
{
  ScrollBar scroll( 0, 20 );

  ViewPort viewPort( 0, 0, 800, 600 );

  std::cout << "Desplazamiento hacia abajo:" <<  std::endl;
  for ( int i = 0; i < 5; i++ )
  {
    scroll.SlideDown( );
    viewPort.MoveTo( 0, scroll.Position( ) );
    std::cout << "Posición: x=" << viewPort.X( ) << " y=" << viewPort.Y( ) << std::endl;
  }

  std::cout << std::endl;
  std::cout << "Desplazamiendo hacia arriba: " << std::endl;
  for ( int i = 0; i < 5; i++ )
  {
    scroll.SlideUp( );
    viewPort.MoveTo( 0, scroll.Position( ) );
    std::cout << "Posición: x=" << viewPort.X( ) << " y=" << viewPort.Y( ) << std::endl;
  }
}


Como se puede apreciar... la barra de scroll limita el desplazamiento del área visible, impidendo que salga de los márgenes definidos.

Una vez echo esto queda "pintar" de forma efectiva el área apuntada por "ViewPort", pero eso ya debería ser facil conociendo las coordenadas del área a pintar... lo que tienes que hacer es coger todos los elementos de ese área y "desplazarlos". Me explico. Imagina que tienes un elemento en (20, 10) y el viewport tiene como coordenada superior (0, 2)... el elemento deberás desplazarlo ese (0, 2), es decir, deberás pintarlo en (20, 8) para que aparezca correctamente pintado en la ventana.

Si no queda muy clara la explicación avísame y te lo comento con más tranquilidad... me tengo que ir a comer XDDDD

vangodp

#2
Gracias eferion.
Voy a intentar implementar el source a ver que tal me queda  y luego comento que tal:D
Muchas gracias =D  ;-)

Edit:
En main: creas un objeto llamando el constructor con 2 parámetros:   ScrollBar scroll( 0, 20 );

Pero el constructor solo tiene definido uno. El otro es _position?  :huh:

eferion

Cita de: vangodp en 29 Julio 2014, 14:02 PM
Edit:
En main: creas un objeto llamando el constructor con 2 parámetros:   ScrollBar scroll( 0, 20 );

Pero el constructor solo tiene definido uno. El otro es _position?  :huh:

Vaya, al final se me olvidó actualizar el main... hice un cambio de última hora y le quité el primer parámetro a ScrollBar... ya que una barra de scroll únicamente se mueve en un plano. Elimina el 0 y listo.