snippetpythonModerate
How can I shorten this paint program?
Viewed 0 times
thiscanshortenprogramhowpaint
Problem
I am currently in a challenge with my buddy to see who can code a simple paint program in the least lines. The only requirement, is that the program must include an eraser. How can I possibly shorten this code, while still using proper, beautiful syntax?
import sys, pygame
from pygame.locals import *
pygame.init() #Starts pygame
screen = pygame.display.set_mode((1000,720)) #window, and sets the size
screen.fill((255,255,255)) # Fills background color
brush = pygame.image.load("brush.jpg") #Loads the image into a variable
eraser = pygame.image.load("white.png") #Loads the image into a variable
brush = pygame.transform.scale(brush, (10,10)) #Scales the image into a more useable
eraser = pygame.transform.scale(eraser, (100,100)) #Scales the image into a more
clock = pygame.time.Clock() #Makes a clock to track the ticks within the game
z = 0
while True:
clock.tick(60) #Limits the ticks to 60 (FPS)
x,y = pygame.mouse.get_pos() #Sets two variables for the mouse position
for event in pygame.event.get(): #Recieves events
if event.type == QUIT: #Checks if the event is a QUIT event
pygame.quit() ##Quits##
sys.exit() ##Quits##
elif event.type == MOUSEBUTTONDOWN:
z = 1 #If you press the mouse button down, it sets the screen blit to true
elif event.type == MOUSEBUTTONUP:
z = z - 1 #Does the opposite of the above elif statement
if z == 1: #Cheks if the variable z is true, if it is; updates the screen with the brush
screen.blit(brush,(x-5,y-5))
if event.type == KEYDOWN:
screen.blit(eraser,(x-5,y-5))
pygame.display.update()Solution
Here's my best effort (8 lines):
Notes:
-
-
In this program there's nothing that animates, so there's no need for a clock, and the display only needs to be updated when it changes.
-
You didn't post your images
-
By changing the program to draw white-on-black I can avoid the initial
-
I've used colour names
-
I've used the two-argument form of
-
By using
-
I've changed the user interface so that the left mouse button draws and the right mouse button erases. This is done by looking up the tuple returned by
-
from pygame import *
init()
screen = display.set_mode((1000,720))
for e in iter(event.wait, event.Event(QUIT)):
col = {(1, 0, 0): 'white', (0, 0, 1): 'black'}.get(mouse.get_pressed())
if col and e.type in (MOUSEBUTTONDOWN, MOUSEMOTION):
display.update(screen.fill(Color(col), Rect(mouse.get_pos(), (20, 20))))
quit()Notes:
-
from module import * is normally deprecated because you don't know all the names you're importing, and some of these might conflict with or shadow names from other modules. But in simple cases like this, with no other dependencies, it's justified because it results in code that's easy to read. You can always go through and change X to pygame.X if you want.-
In this program there's nothing that animates, so there's no need for a clock, and the display only needs to be updated when it changes.
-
You didn't post your images
brush.jpg and white.png so I've used solid colour rectangles. (Also, why a JPEG? JPEGs are lossy, so not appropriate for bitmap graphics.)-
By changing the program to draw white-on-black I can avoid the initial
screen.fill and save a line.-
I've used colour names
'white' and 'black' which are clearer than RGB tuples like (255, 255, 255).-
I've used the two-argument form of
iter to avoid the test for event.type == QUIT. (This feature is useful when you want to exit an iteration on a special value.)-
By using
event.wait instead of event.get I can reduce the two loops to one.-
I've changed the user interface so that the left mouse button draws and the right mouse button erases. This is done by looking up the tuple returned by
mouse.get_pressed in a dictionary, to get the colour for the fill.-
Surface.fill returns the rectangle that was filled, which is exactly the part of the display that needs to be updated, so I can pass it directly to display.update.Code Snippets
from pygame import *
init()
screen = display.set_mode((1000,720))
for e in iter(event.wait, event.Event(QUIT)):
col = {(1, 0, 0): 'white', (0, 0, 1): 'black'}.get(mouse.get_pressed())
if col and e.type in (MOUSEBUTTONDOWN, MOUSEMOTION):
display.update(screen.fill(Color(col), Rect(mouse.get_pos(), (20, 20))))
quit()Context
StackExchange Code Review Q#38494, answer score: 12
Revisions (0)
No revisions yet.