简体   繁体   English

Pygame - blitting预览图片

[英]Pygame - blitting for a preview picture

First off, this is a school assignment so I want to be upfront about that. 首先,这是一项学校作业,所以我想提前做好准备。 Second I'm just asking for advice on the approach, possible help with the code. 其次,我只是在寻求有关方法的建议,可能对代码提供帮助。 I'm working on a MSPAINT style clone using some pre-existing code from our book. 我正在使用我们书中的一些预先存在的代码开发MSPAINT样式克隆。 The code already has the use of the draw.line when pressing mouse button 1. Teacher wants us to add ability to make circles or rectangles. 当按下鼠标按钮1时,代码已经使用了draw.line。教师希望我们添加制作圆形或矩形的功能。 I'm working on the circle part and I have figured out (thanks to the forums on here) how to implement what I wanted to do with the MOUSEBUTTONDOWN and MOUSEBUTTONUP events.. This has brought me to a new Question.. How would I blit then erase then blit a preview of the circle until it is the size the user wants and they release the MOUSEBUTTON and view the final blit... 我正在研究圈子部分,我已经想出了(感谢这里的论坛)如何实现我想用MOUSEBUTTONDOWN和MOUSEBUTTONUP事件做的事情。这给我带来了一个新的问题..我怎么会blit然后擦除然后blit预览圆圈,直到它是用户想要的大小,他们释放MOUSEBUTTON并查看最后的blit ...

while keepGoing:
    clock.tick(30)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            keepGoing = False
        elif event.type == pygame.MOUSEMOTION:
            lineEnd = pygame.mouse.get_pos()
            if pygame.mouse.get_pressed() == (1,0,0):
                pygame.draw.line(background, drawColor, lineStart, lineEnd, lineWidth)
            lineStart = lineEnd
        elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 3:
                    circleStart = pygame.mouse.get_pos()
        elif event.type == pygame.MOUSEBUTTONUP and event.button == 3: 
                    circleEnd = pygame.mouse.get_pos()
                    size = (circleEnd[0] - circleStart[0])
                    pygame.draw.circle(background, drawColor, circleStart, size, lineWidth)
        elif event.type == pygame.KEYDOWN:
            myData = (event, background, drawColor, lineWidth, keepGoing)
            myData = checkKeys(myData)
            event, background, drawColor, lineWidth, keepGoing) = myData

Thanks so much 非常感谢

-Ben -ben

So after some thinking this is the best solution I came up with using pygame. 所以经过一番思考,这是我用pygame想出的最佳解决方案。 Tell me what you think and if it has helped you. 告诉我你的想法以及它是否对你有所帮助。

import pygame,sys,math #---- Import modules we will need

pygame.init() #---- Initialize the module

def get_rad(origin_x,origin_y,x,y): #----- Returns the appropriate radius
    return math.sqrt((origin_x - x)**2 + (origin_y - y)**2) #----- Distance between 2
                                                            #----- points

screen = pygame.display.set_mode((400,400)) #----- Sets up the screen
clock  = pygame.time.Clock() #------- Sets up the clock

mouse_button = 0 #--------- This variable is used to determine whether a mouse button
                 #--------- has been pressed

draw_final_circle = False #---------- This variable lets us know that we should draw the 
                          #---------- final circle

while True: #------ main loop

    clock.tick(60) #------ Limit the Fps

    mouse_button0  = mouse_button #-------- This variable holds the previous value of 
                                  #-------- mouse_button(it will be useful later)

    mouse_x,mouse_y = pygame.mouse.get_pos() #----- Get the mosue coordinates

    for e in pygame.event.get(): #---- Cycle through events

        if e.type == pygame.QUIT: pygame.quit();sys.exit() #--Quit when window is closed

        if e.type == pygame.MOUSEBUTTONDOWN: #---- If the mouse button is pressed
            if mouse_button == 0: #---- if the mouse button is released
                mouse_button = 1 #----- set it to pressed basically
                originx,originy = mouse_x,mouse_y #---- keep the mouse_x,mouse_y pos

        if e.type == pygame.MOUSEBUTTONUP: #---- if the mouse button is released
             if mouse_button == 1: #-------- if it is pressed
                 mouse_button = 0 #--------- set it to released

    screen.fill((255,255,255)) #---- clear the screen


    #-------- If a mouse button is pressed and a circle can be drawn (rad>width) ------#
    if mouse_button == 1 and get_rad(originx,originy,mouse_x,mouse_y) > 1:

        rad = int(get_rad(originx,originy,mouse_x,mouse_y)) #---- get the radius(as int)
        pos = mouse_x,mouse_y
        pygame.draw.circle(screen,(0,0,0),pos,rad,1) #--- draw the circle

    #----------------------------------------------------------------------------------#


    #---------- if the button is released but in the previous loop it was pressed -----#
    if mouse_button == 0 and mouse_button0 == 1:

        draw_final_circle = True #----- set the final circle boolean to True

    if draw_final_circle: #----- if the final circle is decided
        pygame.draw.circle(screen,(0,0,0),pos,rad,1) #---- keep drawing it 

    pygame.display.flip() #----- flip the buffer

I suggest you implement the different modes of your drawing program into different classes that represent the current mode and its state. 我建议你将绘图程序的不同模式实现到代表当前模式及其状态的不同类中。 This way, implementing different modes become very easy. 这样,实现不同的模式变得非常容易。


As for a circle drawing mode, you want to take a copy the screen surface when the user presses the mouse button, and blit that copy to the screen every frame. 对于圆形绘制模式,您希望在用户按下鼠标按钮时复制屏幕表面 ,并且每帧复制到屏幕。

Then draw your circle on that copy. 然后在该副本上绘制圆圈。 This way, you basically "erase" the temporary circles. 这样,你基本上“擦除”临时圈。


Here's a simple example. 这是一个简单的例子。 Press SPACE to cycle between the different modes (draw, circle, rect) and TAB for different colors: SPACE可在不同模式(绘图,圆形,矩形)和TAB之间循环显示不同的颜色:

import pygame
from math import hypot
from itertools import cycle
from operator import itemgetter

pygame.init()
screen = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()

colors = cycle(sorted(pygame.color.THECOLORS.iteritems(), key=itemgetter(0)))
color = next(colors)[1]

class DrawMode(object):
    def __init__(self):
        self.last = None
    def handle(self, e):
        if e.type == pygame.MOUSEBUTTONDOWN and e.button == 1:
            self.last = pygame.mouse.get_pos()
        if e.type == pygame.MOUSEBUTTONUP and e.button == 1:
            self.last = None
    def draw(self, screen):
        pos = pygame.mouse.get_pos()
        if self.last:
            pygame.draw.line(screen, color, self.last, pos)
            self.last = pos

class ClickReleaseMode(object):
    def __init__(self):
        self.tmp = None
        self.start = None
    def handle(self, e):
        if e.type == pygame.MOUSEBUTTONDOWN and e.button == 1:
            self.start = pygame.mouse.get_pos()
        if e.type == pygame.MOUSEBUTTONUP and e.button == 1:
            self.start = self.tmp = None
    def draw(self, screen):
        if not self.tmp:
            self.tmp = screen.copy()

        pos = pygame.mouse.get_pos()
        screen.blit(self.tmp, (0,0))
        if self.start:
            self.do_draw(screen, pos)

class CircleMode(ClickReleaseMode):
    def __init__(self):
        super(CircleMode, self).__init__()

    def do_draw(self, screen, pos):
        r = hypot(pos[0] - self.start[0], pos[1] - self.start[1])
        if r >= 2:
            pygame.draw.circle(screen, color, self.start, int(r), 2)

class RectMode(ClickReleaseMode):#
    def __init__(self):
        super(RectMode, self).__init__()

    def do_draw(self, screen, pos):
        p = pos[0] - self.start[0], pos[1] - self.start[1]
        pygame.draw.rect(screen, color, pygame.Rect(self.start, p), 2)

quit = False
modes = cycle((DrawMode, CircleMode, RectMode))
mode = next(modes)()
while not quit:
    quit = pygame.event.get(pygame.QUIT)
    for e in pygame.event.get():
        if e.type == pygame.KEYDOWN:
            if e.key == pygame.K_SPACE:
                mode = next(modes)()
                print 'enter', mode.__class__.__name__
            if e.key == pygame.K_TAB:
                name, color = next(colors)
                print 'changing color to', name, color
        mode.handle(e)
    mode.draw(screen)
    pygame.display.flip()
    clock.tick(60)

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM