讀古今文學網 > 父與子的編程之旅:與小卡特一起學Python > 16.4 單個像素 >

16.4 單個像素

有時我們並不想畫一個圓或矩形,而是希望畫單個的點或像素。比如,我們要創建數學程序,想畫一條正弦曲線。

別擔心,放鬆點!

如果你不知道什麼是正弦曲線也不用擔心。學習本章的內容,只要知道這是一種波浪形的曲線就可以了。

另外也不用擔心後面幾個示例程序中的數學公式,按代碼清單原樣鍵入這些程序就行。這些公式只是為了保證得到大小合適的波浪形狀,能夠放入我們的 Pygame 窗口中。

由於沒有 pygame.draw.sinewave 這種方法,所以我們必須利用單個的點來畫這樣一條曲線。一種方法是畫很小的圓或矩形(圓或矩形的大小只有一個或兩個像素)。代碼清單 16-7 顯示了用矩形畫出來的曲線是什麼樣的。

代碼清單 16-7 用大量很小的矩形畫曲線

運行這個程序時會看到如下圖所示的結果。

每個點都是寬和高分別為 1 像素的矩形。注意我們使用的線寬為 1,而不是 0。如果使用線寬 0,什麼都不會顯示,因為這樣一個矩形沒有「中間部分」可以填充。

連接多個點

如果你看得確實很仔細,可能會注意到,這個正弦曲線並不是連續的,中間的點之間存在空格。這是因為,在正弦曲線比較陡的部分,我們必須上移(或下移)3 個像素而向右只移動 1 個像素。而且由於我們畫的是單個的點,而不是線,所以沒有什麼來填充它們之間的間隔。

下面還是做同樣的工作,不過現在要用一條短線把各個點連接起來。Pygame 有一個畫線的方法,另外還有一種方法可以在一系列點之間畫線(類似於「連接多個點」)。這個方法是 pygame.draw.lines,它需要下面這 5 個參數。

  • 畫線的表面(surface)。

  • 顏色(color)。

  • 是否要畫一條線將最後一個點與第一個點相連接,使形狀閉合(closed)。我們不希望正弦曲線閉合,所以對我們來說,這個參數是 False

  • 要連接的點的列表(list)。

  • 線寬(width)。

所以,在我們的正弦曲線例子中,pygame.draw.lines 方法是這樣的:

pygame.draw.lines(screen, [0,0,0],False, plotPoints, 1)  

for 循環中,並沒有畫出各個點,我們只是創建了 draw.lines 將要連接的點列表。然後在 for 循環之外調用一次 draw.lines。整個程序如代碼清單 16-8 所示。

代碼清單 16-8 一條完美連接的正弦曲線

現在運行這個程序時,可以看到如下圖所示的曲線。

這就好多了,點與點之間不再有間隔。如果把線寬增加到 2,看上去會更好,如下圖所示。

再來連接多個點

還記得小時候玩過的連數字畫圖嗎?這裡給出一個 Pygame 版本。

代碼清單 16-9 中的程序使用了 draw.lines 函數和一個點列表來創建圖形。要想看到這個神秘的圖片,必須鍵入代碼清單 16-9 中的程序。這一次沒有捷徑可走!我們沒有把這個程序包含在 examples 文件夾中,如果你想看到這個神秘的圖片,就必須自己鍵入。不過鍵入所有這些數字可能有點乏味,所以你可以在 examples 文件夾或網站上的一個文本文件中找到這個 dots 列表。

代碼清單 16-9 連連看神秘圖片

逐點繪製

下面再來考慮逐點繪製。如果我們只想改變一個像素的顏色,畫一個小圓或矩形就會有點傻。你可以不使用 draw 函數,而是利用 Surface.set_at 方法訪問一個表面上的單個像素。你要指出希望設置哪個像素,以及要設置成什麼顏色:

screen.set_at([x, y], [0, 0, 0])  

如果在我們的正弦曲線例子中使用這行代碼(放在代碼清單 16-7 的第 8 行),看上去與使用 1 個像素寬的矩形畫出的結果完全相同。

還可以用 Surface.get_at 方法檢查一個像素設置為什麼顏色。只需要傳入你想要檢查的那個像素的坐標,比如: pixel_color = screen.get_at([320, 240])。在這個例子中,screen 是表面的名字。