0

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

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,它在绘制之前具有屏幕背景。为了在按住按钮时使线条随鼠标移动,我存储鼠标的先前位置并绘制一条白线(以清理它),然后在新位置绘制另一条线。

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

缩小线之前: 在此处输入图像描述

缩小线后:

在此处输入图像描述

这是与控制鼠标按钮的循环相关的其余代码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;


    }   
    }
}

谁能帮我解决这个问题?

4

1 回答 1

1

I don't recommend drawing a white line over the old line. Instead, you should be using a frame-buffer, which is an off-screen memory area where you re-assemble it each time. Draw the background, then the line. Once you place the line, draw it onto the background.. but until then it's drawn afterwards. Then the whole thing is flipped/copied to the screen on each loop. Make sense?

于 2015-12-01T04:19:27.790 回答