Notmuch123
Notmuch123

Reputation: 25

Copying the surface and bliting it on the screen

So I am working on my pygame version of Paint and am currently working on UNDO property. I have figured it out where I would save the screen (was thinking to use deque) but can't figure it out how to save the content on the screen, what is the method for saving the content on the screen so I can append it on the deque every time there is a change made on the screen and get back to the old screen if user clicks undo button. I have tried copy() method but I guess I am not implementing it right..

It would be of much help if you give me an example how to blit the copy of the old surface.

Hope I was clear enough.

Upvotes: 2

Views: 382

Answers (1)

Kingsley
Kingsley

Reputation: 14906

Here's a quick example of making a copy of the screen surface.

It calls window.copy() to make an "undo point" on start, and whenever the user clicks on [KEEP]. If the user clicks on [UNDO], the copied surface is re-blitted to the screen to erase the existing one.

undo-example

I'm not sure if keeping a copy of the screen is a great way to do this, it uses a lot of memory. A better approach would be to store the drawing primitives in a list, then only re-draw up to N-1 entry on undo.

import pygame

# Window size
WINDOW_WIDTH    = 400
WINDOW_HEIGHT   = 400
WINDOW_SURFACE  = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE

DARK_BLUE = (   3,   5,  54 )
YELLOW    = ( 250, 250,   0 )
RED       = ( 200,   0,   0 )


### initialisation
pygame.init()
pygame.mixer.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )
pygame.display.set_caption("Undo Example")


font = pygame.font.SysFont('freesansbold.ttf', 30)
undo_text = font.render( "[UNDO]", True, YELLOW )
undo_rect = undo_text.get_rect()
undo_rect.x = 50
keep_text = font.render( "[KEEP]", True, YELLOW )
keep_rect = keep_text.get_rect()
keep_rect.x = 200

window.fill( DARK_BLUE )

### The undo buffer
undo_save = None

### Main Loop
clock = pygame.time.Clock()
pen_down = False
last_point = None
done = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.MOUSEMOTION ):
            mouse_pos = event.pos
            if ( pen_down ):
                if ( last_point != None ):
                    pygame.draw.line( window, RED, last_point, mouse_pos )
                    last_point = mouse_pos
        elif ( event.type == pygame.MOUSEBUTTONDOWN ):
            pen_down = True
            if ( last_point == None ):
                last_point = event.pos
        elif ( event.type == pygame.MOUSEBUTTONUP ):
            pen_down = False
            last_point = None

            ### Handle the KEEP/UNDO button presses
            if ( undo_rect.collidepoint( event.pos ) ):
                if ( undo_save != None ):
                    window.blit( undo_save, ( 0, 0 ) )
                    print( "UNDO Image Restored" )
            if ( keep_rect.collidepoint( event.pos ) ):
                undo_save = window.copy()
                print( "UNDO Image Saved" )

    window.blit( undo_text, undo_rect )
    window.blit( keep_text, keep_rect )

    # Update the window, but not more than 60fps
    pygame.display.flip()

    # make the first undo automatically
    if ( undo_save == None ):
        undo_save = window.copy()

    # Clamp FPS
    clock.tick(60)


pygame.quit()

Upvotes: 1

Related Questions