画线:C Vga图形上鼠标光标出现问题

时间:2015-12-01 03:33:22

标签: c dos vga

我正在尝试创建一个程序,您可以通过单击鼠标绘制线条,然后在按下按钮的同时移动线条将改变大小和方向,并在释放时保留在屏幕上(Just如在油漆或任何其他照片编辑器中)。我正在用256-VGA工作。我遇到的问题是在鼠标光标所在的空间上画一条线。我有两个显示和隐藏鼠标的功能:

typedef struct MOUSE{
    byte on;
    byte button1;
    byte button2;
    byte button3;
    int num_buttons;
    sword x;
    sword y;
    byte under[MOUSE_SIZE];
    MOUSEBITMAP *bmp;


} MOUSE;
/**************************************************************************
 *  show_mouse                                                            *
 *    Displays the mouse.                                                 *
 **************************************************************************/
void show_mouse(MOUSE *mouse){
    int x,y;
    int mx = mouse->x - mouse->bmp->hot_x;
    int my= mouse->y - mouse->bmp->hot_y;
    long screen_offset = (my<<8)+(my<<6);
    word bitmap_offset = 0;
    byte data;
    //memcpy(double_buffer,VGA,SCREEN_SIZE);
    /* allocate memory for double buffer and background image */
    /*if ((double_buffer = (byte *) malloc(SCREEN_SIZE)) == NULL)
    {
        printf("Not enough memory for double buffer.\n");
        exit(1);
    }   */
    for(y=0;y<MOUSE_HEIGHT;y++){
        for(x=0;x<MOUSE_WIDTH;x++,bitmap_offset++){
            mouse->under[bitmap_offset] = VGA[(word) (screen_offset+mx+x)];
            if(mx+x < SCREEN_WIDTH && mx+x >=0 &&
                my+y < SCREEN_HEIGHT && my+y >=0) //Verificando que estemos dentro de pantalla
                {
                    /*Pintando en pantalla*/
                    data = mouse->bmp->data[bitmap_offset];
                    if(data) 
                    {
                        VGA[(word)(screen_offset+mx+x)] = data;
                    }                       
                }           
        }
        screen_offset+=SCREEN_WIDTH;
    }
    /*show_buffer(double_buffer);
    free(double_buffer);*/
}
 /**************************************************************************
 *  hide_mouse                                                            *
 *    hides the mouse.  This code is not optimized.                       *
 **************************************************************************/

void hide_mouse(MOUSE *mouse){

    int x,y;
    int mx = mouse->x - mouse->bmp->hot_x;
    int my = mouse->y - mouse->bmp->hot_y;
    long screen_offset = (my<<8)+(my<<6);
    word bitmap_offset = 0;
    /*memcpy(double_buffer,VGA,SCREEN_SIZE);
    /* allocate memory for double buffer and background image */
    /*if ((double_buffer = (byte *) malloc(SCREEN_SIZE)) == NULL)
    {
        printf("Not enough memory for double buffer.\n");
        exit(1);
    }   */
    for(y=0;y<MOUSE_HEIGHT;x++,y++){

        for(x=0;x<MOUSE_WIDTH;x++,bitmap_offset++){
            //Verificando que este dentro de pantalla
            if(mx+x < SCREEN_WIDTH &&mx+x >=0 &&
                my+y <SCREEN_HEIGHT && my+y >=0){

                    /*Pintando en pantalla*/

                    VGA[(word)(screen_offset+mx+x)] = mouse->under[bitmap_offset];
                }

        }
        screen_offset+=SCREEN_WIDTH;

    }
    /*show_buffer(double_buffer);
    free(double_buffer);*/
} 

我有under结构的MOUSE变量,它在绘制之前具有屏幕背景。为了在按住按钮时使用鼠标移动线,我存储鼠标的先前位置并绘制一条白线(以清理它),然后绘制另一条带有新位置的线。

问题是,然后我将一条线缩小并沿着线移动鼠标指针,重新绘制鼠标再次绘制之前的线。 我得到这样的东西:

缩小线之前: enter image description here

缩小线后:

enter image description here

这是与控制鼠标按钮的循环相关的其余代码void realizar_accion(){

void realizar_accion(){
    /*Caso1: Pintar pixel simple (lapiz)*/
    if(accion==1){

        plot_pixel(mouse_g.x,mouse_g.y,2);
        plot_pixel(mouse_g.x-1,mouse_g.y,2);
        plot_pixel(mouse_g.x,mouse_g.y-1,2);
        plot_pixel(mouse_g.x-1,mouse_g.y-1,2);

    }
    /*Caso2: Pintar Linea*/
    else if(accion==2){
        init_x = mouse_g.x;
        prevx = mouse_g.x;
        init_y = mouse_g.y;
        prevy = mouse_g.y;      
        //line(mouse_g.x,mouse_g.y,mouse_g.x-20,mouse_g.y-20,2);
    }
}
void realizar_accion_mantenido(){
    /*Caso1: Pintar pixel simple (lapiz)*/
    if(accion==1){

        plot_pixel(mouse_g.x,mouse_g.y,2);
        plot_pixel(mouse_g.x-1,mouse_g.y,2);
        plot_pixel(mouse_g.x,mouse_g.y-1,2);
        plot_pixel(mouse_g.x-1,mouse_g.y-1,2);


    }
    /*Caso2: Pintar Linea*/
    else if(accion==2){
        if(on_draw==-1){

            line(init_x,init_y,mouse_g.x,mouse_g.y,2);
            prevx=mouse_g.x;
            prevy=mouse_g.y;
            on_draw=0;

        }
        else{
            if(prevx!=mouse_g.x&&prevy!=mouse_g.y){
                line(init_x,init_y,prevx,prevy,0xFFFF); //borrando la linea anterior
                line(init_x,init_y,mouse_g.x,mouse_g.y,2);
                prevx=mouse_g.x;
                prevy=mouse_g.y;
            }

        }



    }


}

int sobre_barra(){
    if(new_x1>0 && new_x1<33 &&new_y1>0 &&new_y1<181){


        return 1;

    }
    else{

        return -1;
    }


}
void boton_soltado(){

    /*Caso1: Pintar pixel simple (lapiz)*/
    if(accion==1){



    }
    /*Caso2: Pintar Linea*/
    else if(accion==2){
        if(on_draw==0){
            line(init_x,init_y,prevx,prevy,0xFFFF); //borrando la linea anterior
             wait_for_retrace();
             hide_mouse(&mouse_g);
             if (mouse_new!=NULL) mouse_g.bmp=mouse_new;
             mouse_g.x = new_x1;
             mouse_g.y=new_y1;
             show_mouse(&mouse_g);
            line(init_x,init_y,mouse_g.x,mouse_g.y,2);
            prevx=mouse_g.x;
            prevy=mouse_g.y;
            on_draw=-1;         

        }

    }



}
void boton_mantenido(){

    /*Verificar que este dento del buffer de dibujo....*/
    if(sobre_barra()!=1){
        realizar_accion_mantenido();

    }
}
void boton_presionado(){

    if(sobre_barra()==1){
        cambiar_herramienta();

    }
    else{

        realizar_accion();

    }   

}
/**************************************************************************
 *  paint_screen                                                      *
 *    show  main screen paint                                           *
 **************************************************************************/
void paint_screen(BITMAP *fondo){
    int mantenido;
    BITMAP barra,barra_color,normal_ptr_image;
    int anterior_presionado;
    word last_time;
    word redraw,press,release;
    sword dx,dy=0;
    MOUSEBITMAP *mouse_new=NULL;    
    int i,done = 0;
    on_draw=-1;
    accion =2;
    current_color=2;
    /*Pintando fondo blanco*/
    clear_screen();
    /*Pintando barra de herramientas*/
    load_bmp("normal.bmp",&normal_ptr_image);
    load_bmp("mainbar.bmp",&barra);
    load_bmp("colores.bmp",&barra_color);
    set_pallete(fondo->pallete);
    draw_bitmap(&barra,0,0);
    draw_bitmap(&barra_color,0,180);
    load_mouse(&mouse_g);
    show_mouse(&mouse_g);
    wait(50);
    while(!done){
         if(redraw){
             wait_for_retrace();
             hide_mouse(&mouse_g);
             if (mouse_new!=NULL) mouse_g.bmp=mouse_new;
             mouse_g.x = new_x1;
             mouse_g.y=new_y1;
             show_mouse(&mouse_g);
             redraw=0;
             mouse_new=NULL;
         }

        do {                              // check mouse status 
            anterior_presionado = press;
            get_mouse_motion(&dx,&dy);
            press   = get_mouse_press(LEFT_BUTTON);
            release = get_mouse_release(LEFT_BUTTON);
            //Si el estado estaba presionado y no se ha soltado.. el boton esta mantenido
            if(anterior_presionado==1 &&release==0){
              mantenido =1;

            }
        } while (dx==0 && dy==0 && press==0 && release==0&&*my_clock==last_time);    
        if (release){
            mouse_g.button1=0;
            mantenido=0;
            boton_soltado();


        }       

        if (press){

            mouse_g.button1=1;
            boton_presionado();


        } 
        //El boton se mantiene presionado
        else if(mantenido){
            boton_mantenido();
        }
        else{
            release=1;
        }


        if (dx || dy)                     // calculate movement 
        {
          new_x1 = mouse_g.x+dx;
          new_y1 = mouse_g.y+dy; //Actualizamos posicion mouse
          if (new_x1<0)   new_x1=0;
          if (new_y1<0)   new_y1=0;
          if (new_x1>319) new_x1=319;
          if (new_y1>199) new_y1=199;
          redraw=1;
        }

        if(new_x1>=287 && new_x1 <320
            && new_y1>=180 && new_y1 < 200 &&press){

        set_mode(TEXT_MODE); 
        printf("Adios!!");
        wait(25);
        done=0;
        return;


    }   
    }
}

有人可以帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

我不建议在旧线上画一条白线。相反,您应该使用帧缓冲区,这是一个屏幕外存储区,您每次都会重新组装它。画出背景,然后画线。放置线后,将其绘制到背景上......但在此之后,它会被绘制出来。然后在每个循环中将整个事物翻转/复制到屏幕上。有意义吗?