15

私が見ているように、マウスイベントを処理して絵を描く方法は 2 つあります。

1 つ目は、マウスの移動を検出し、マウスがある場所に線を引くことです (ここに示す) 。ただし、これに伴う問題は、ブラシ サイズが大きいと、線のストローク サイズを使用して太い線を作成するため、直線ではない各「線」の間に多くのギャップが発生することです。

もう 1 つの方法は、ここに示すように、マウスの移動時に円を描くことです。これに伴う問題は、コンピューターがマウス入力を検出するよりも速くマウスを動かすと、各円の間に隙間ができることです。

両方の問題に関するスクリーンショットを次に示します。

http://imgur.com/32DXN.jpg

MS Paint のようなブラシを、線のストロークに隙間がなく、各円の間に隙間がなく、適度に大きなブラシ サイズで実装する最良の方法は何ですか?

4

5 に答える 5

16

なぜ両方をしないのですか?

各端点に円を描き、2 つの端点の間に線を引きます。

編集rofl、自分を止めることができませんでした。

pygame.draw.line実際には、ごまかすので使いたくありません。ピクセルの 1 ピクセル幅の行または列 (迎角に応じて) を埋めます。ほぼ垂直な角度、0 度または 90 度で行った場合、これは問題ではありませんが、45 度では、一種のサヤインゲン効果に気付くでしょう。

唯一の解決策は、すべてのピクセルの距離で円を描くことです。ここ...

import pygame, random

screen = pygame.display.set_mode((800,600))

draw_on = False
last_pos = (0, 0)
color = (255, 128, 0)
radius = 10

def roundline(srf, color, start, end, radius=1):
    dx = end[0]-start[0]
    dy = end[1]-start[1]
    distance = max(abs(dx), abs(dy))
    for i in range(distance):
        x = int( start[0]+float(i)/distance*dx)
        y = int( start[1]+float(i)/distance*dy)
        pygame.draw.circle(srf, color, (x, y), radius)

try:
    while True:
        e = pygame.event.wait()
        if e.type == pygame.QUIT:
            raise StopIteration
        if e.type == pygame.MOUSEBUTTONDOWN:
            color = (random.randrange(256), random.randrange(256), random.randrange(256))
            pygame.draw.circle(screen, color, e.pos, radius)
            draw_on = True
        if e.type == pygame.MOUSEBUTTONUP:
            draw_on = False
        if e.type == pygame.MOUSEMOTION:
            if draw_on:
                pygame.draw.circle(screen, color, e.pos, radius)
                roundline(screen, color, e.pos, last_pos,  radius)
            last_pos = e.pos
        pygame.display.flip()

except StopIteration:
    pass

pygame.quit()
于 2009-02-28T02:50:16.167 に答える
3

各ループステップでブリットしないと、描画の速度が向上します (前のコードから変更されたこのコードを使用すると、マシンのラグの問題を取り除くことができます)

import pygame, random

screen = pygame.display.set_mode((800,600))

draw_on = False
last_pos = (0, 0)
color = (255, 128, 0)
radius = 10

def roundline(srf, color, start, end, radius=1):
    dx = end[0]-start[0]
    dy = end[1]-start[1]
    distance = max(abs(dx), abs(dy))
    for i in range(distance):
        x = int( start[0]+float(i)/distance*dx)
        y = int( start[1]+float(i)/distance*dy)
        pygame.display.update(pygame.draw.circle(srf, color, (x, y), radius))

try:
    while True:
        e = pygame.event.wait()
        if e.type == pygame.QUIT:
            raise StopIteration
        if e.type == pygame.MOUSEBUTTONDOWN:
            color = (random.randrange(256), random.randrange(256), random.randrange(256))
            pygame.draw.circle(screen, color, e.pos, radius)
            draw_on = True
        if e.type == pygame.MOUSEBUTTONUP:
            draw_on = False
        if e.type == pygame.MOUSEMOTION:
            if draw_on:
                pygame.display.update(pygame.draw.circle(screen, color, e.pos, radius))
                roundline(screen, color, e.pos, last_pos,  radius)
            last_pos = e.pos
        #pygame.display.flip()

except StopIteration:
    pass

pygame.quit()
于 2011-05-05T16:04:42.680 に答える
2

最初の問題については、色だけでも背景が必要です。私が作ったレプリカポンゲームでも同じ問題がありました。これは私が作成したレプリカ ペイント プログラムの例です。左クリックで描画、右クリックで消去、カラー イメージをクリックして色を選択、上ボタンで画面をクリアします。

import os
os.environ['SDL_VIDEO_CENTERED'] = '1'
from pygamehelper import *
from pygame import *
from pygame.locals import *
from vec2d import *
from math import e, pi, cos, sin, sqrt
from random import uniform

class Starter(PygameHelper):
    def __init__(self):
        self.w, self.h = 800, 600
        PygameHelper.__init__(self, size=(self.w, self.h), fill=((255,255,255)))

        self.img= pygame.image.load("colors.png")
        self.screen.blit(self.img, (0,0))

        self.drawcolor= (0,0,0)
        self.x= 0

    def update(self):
        pass

    def keyUp(self, key):
        if key==K_UP:
            self.screen.fill((255,255,255))
            self.screen.blit(self.img, (0,0))




    def mouseUp(self, button, pos):
        pass

    def mouseMotion(self, buttons, pos, rel):
        if pos[1]>=172: 
            if buttons[0]==1:
                #pygame.draw.circle(self.screen, (0,0,0), pos, 5)
                pygame.draw.line(self.screen, self.drawcolor, pos, (pos[0]-rel[0], pos[1]-rel[1]),5)                
            if buttons[2]==1:
                pygame.draw.circle(self.screen, (255,255,255), pos, 30)
            if buttons[1]==1:
                #RAINBOW MODE
                color= self.screen.get_at((self.x, 0))
                pygame.draw.line(self.screen, color, pos, (pos[0]-rel[0], pos[1]-rel[1]), 5)

                self.x+= 1
                if self.x>172: self.x=0

        else:
            if pos[0]<172:
                if buttons[0]==1:
                    self.drawcolor= self.screen.get_at(pos)
                    pygame.draw.circle(self.screen, self.drawcolor, (250, 100), 30)

    def draw(self):
        pass
        #self.screen.fill((255,255,255))
        #pygame.draw.circle(self.screen, (0,0,0), (50,100), 20)

s = Starter()
s.mainLoop(40)
于 2011-04-16T23:31:12.337 に答える
0

ラウンドライン関数のより効率的なバージョンを作成しました。

import pygame as pg,random,math


screen = pg.display.set_mode((800,600))

draw_on = False
last_pos = (0, 0)
color = (255, 128, 0)
radius = 10

def roundline(srf, color, start, end, radius=1):
    pg.display.update([drawline(srf,color,start,end,radius),
                       pg.draw.circle(srf, color, end, radius),
                       pg.draw.circle(srf, color, start, radius)])

def drawline(srf, color,start,end,width):
    v=(start[0]- end[0],start[1]- end[1])
    betrag=width/math.sqrt(v[0]*v[0]+v[1]*v[1])
    v_=(v[1]*betrag,-betrag*v[0])
    return pg.draw.polygon(srf, color,(
            (int(start[0]+v_[0]),int(start[1]+v_[1])),
            (int(start[0]-v_[0]),int(start[1]-v_[1])),
            (int(end[0]-v_[0]),int(end[1]-v_[1])),
            (int(end[0]+v_[0]),int(end[1]+v_[1]))
            ))

try:
    while True:
        e = pg.event.wait()
        if e.type == pg.QUIT:
            raise StopIteration
        elif e.type == pg.MOUSEBUTTONDOWN:
            color = (random.randrange(256), random.randrange(256), random.randrange(256))
            #pg.draw.circle(screen, color, e.pos, radius)
            draw_on = True
            start=e.pos
        elif e.type == pg.MOUSEBUTTONUP:
            draw_on = False
        elif e.type == pg.MOUSEMOTION:
            if draw_on:
                roundline(screen, color, e.pos, last_pos,  radius)
            last_pos = e.pos
        elif e.type == pg.MOUSEWHEEL:
            radius=max(1,radius+e.y)
finally:
    pg.quit()

于 2021-02-27T23:47:41.137 に答える