分身編號

分身編號 1 -Scratch分身與執行緒

Scratch 中有個很強的功能『分身』是初學者一定要學會使用的,但分身最多就只能產生 300 個,如果重複產生或忘了刪除最後可能導致整個專案當掉。所以,掌握有多少個分身以及給每個分身一個編號,是 debug 過程中一個重要的手段。

首先,要先提到變數可被設為『適用於所有角色』與『僅適用於當前角色』,學過程式的人應該很快就能將它們理解為「全域變數 (global variable)」和「區域變數 (local variable)」,或者將後者視為「私有變數 (private variable)」。既然Scratch wiki 中主要稱之為 "Local Variable",那我們也就稱之為「區域變數」吧。

當建立變數時如果選擇了區域變數(例如「速度」),除了其他角色無法設定或改變這個變數,重點是這個角色產生出來的每個分身都會有屬於自己的變數「速度」,也就是說,分身 1 號改變了自己的「速度」不會影響到分身 2 號的「速度」。這樣就可以做到讓分身獨立的運作,各自有各自的行進速度。

建立變數時可選擇「僅適用當前角色」的區域變數

建立變數時可選擇「僅適用當前角色」的區域變數

這一篇,目的是要讓每個分身一個編號,編號一定是唯一 (unique) 的,那就要利用到區域變數。最簡單的做法如下:先建立一個區域變數『id』。

『id』是一個區域變數

『id』是一個區域變數

執行的結果,中間的是「本尊」

執行的結果,中間的是「本尊」

執行之後看到每個「分身」說出了自己的編號,而且每個分身的編號都不同。

但很多時候分身是由別的角色或背景來建立,使用的是『建立 OO 的分身』,上面的方式就不行。通常這類情形還會需要紀錄建立了多少分身,那就要利用一個全域變數『分身數量』來紀錄。

變數『分身數量』是一個全域變數

變數『分身數量』是一個全域變數

Sprite1 當分身產生的程式

Sprite1 當分身產生的程式

執行的結果,可由變數『分身數量』知道產生了多少個分身

執行的結果,可由變數『分身數量』知道產生了多少個分身

這樣,既能做到分身數量的管理,又能給每個分身一個編號,更進階的作法,會利用分身編號搭配上清單,就更能有效的管理每個分身。

然而,這裡留下一個問題,為什麼第二個方法中的變數「分身數量」初始值要為 0 而不是 1 呢?這跟我們之前提到的執行緒的機制有關,沒看過的朋友請先跳去看看,再接著看下一篇喔!

分身編號 2 -Scratch分身與執行緒

上一篇介紹了 Scratch 的分身編號,在最後留下了一個問題,這篇我們就來說明這個問題發生的原因。本篇內容同樣取自 Scratch 專家 Cliff Davies 的 "Scratch and its inner workings" 文章的內容。

先來建立兩個變數 『Global』與『 local 』及兩個清單 『Global list』與『 Local list』。其中,變數『local 』是一個區域變數。

程式如下:兩個變數初始值都是 1,呼叫『建立自己的分身』後,兩個變數再分別加 1。而『當分身產生』時將這兩個變數分別加到對應的清單中。

兩個變數都是在『建立自己的分身』之後才改變 1

兩個變數都是在『建立自己的分身』之後才改變 1

執行結果如下:當點擊綠旗開始時,產生了一個分身,兩個變數分別被加到清單中,但清單『Global list』與『 Local list』中的第 1 項的數值竟然不同!

清單『Global list』中的第 1 項的值是 2

清單『Global list』中的第 1 項的值是 2

如果看過上一個單元瞭解了執行緒列表 ,就不難理解『當分身產生』為首的積木串也會是一個執行緒,而當這個執行緒在執行到『建立自己的分身』的時候被建立,並加入到了執行列表中,然而,這個執行緒並沒有馬上開始執行,而是等到了『當綠旗被點擊』為首的程式積木串執行完畢後才執行,這樣造成了兩種變數會有不同的結果。

先來看區域變數『local』,分身獨有的變數『local』是在當『建立自己的分身』執行時跟著執行緒一起被建立,當時的值是 1(就是「繼承」的觀念)。而等到『當分身產生』程式積木串被執行時,加入到清單『Local list』的值是分身獨有的變數『local』的值 1。

但變數『Global』被加入清單時,由於是在『當綠旗被點擊』為首的積木串執行完畢後,『變數 Global 改變 1 』已經被執行了,變成了 2,所以加到清單『Global list』的值是改變後的值 2。

可是!前篇利用全域變數『分身數量』賦予分身編號的程式還有一個『重複 5 次』的迴圈,如果是要等到 5 次重複結束再執行『當分身產生』下的程式積木,那每個分身的編號應該都是 5 啊!

這個理論是不是有問題?還是有什麼沒搞清楚的?待傑夫老師下回說明~

分身編號 3 -Scratch分身與執行緒

前一篇介紹了 Scratch 的分身與執行緒之間的關係,但又留下了一個問題,如果一個程式積木串中有重複迴圈,那麼這個執行緒也會等到迴圈結束才換下一個執行緒執行嗎?本篇繼續探討 Scratch 專家 Cliff Davies 的 "Scratch and its inner workings" 文章的內容。

延續前一篇的程式,並加上『重複 5 次』,如下:

延續上一篇的程式,並加上『重複 5 次』

延續上一篇的程式,並加上『重複 5 次』

執行結果如下:清單『Global list』中的數字,不像前一篇最後預期的都是 5,而是 2, 3, 4, 5, 6,就如第一篇的「分身數量」方式建立分身編號的結果吻合。

清單『Global list』中的數字,不像前一篇最後預期的都是 5

清單『Global list』中的數字,不像前一篇最後預期的都是 5

如果不是等到『重複 5 次』再執行『當分身產生』,那麼合理的"解釋"就是每次迴圈內的程式積木被執行完要返回時暫停了下來,讓『當分身產生』先執行。沒錯,正在執行的執行緒必須在某些時機點暫停,讓列表中下一個執行緒能執行,這樣才是所謂的「多工」或是一開始所說的感覺像是程式在「同步執行」。而執行緒暫停下來讓給下一個執行的時機點,專家 Cliff 稱之為「讓點 (yield point)」。

所以,每一次『變數 local 改變 1』執行完畢時,因為在這個迴圈內有一個『建立自己的分身』,所以列表中有了一個等著要被執行的執行緒,這個執行緒就暫停了下來,讓給了新的執行緒執行,也就是『當分身產生』下的程式。迴圈一次又一次的執行,執行了 5 次,每次都會讓給新的執行緒執行,最後有了我們看到的"合理的"結果。

這也說明了,按照第一篇的「分身數量」方式建立分身編號,『分身數量』的初始值要從 0 開始。

知道了這個「讓點」又對創作 Scratch 遊戲有什麼幫助?傑夫老師會慢慢的告訴你。

後來發現,翻譯文章不如融會貫通了之後再用自己的方式描述出來。英文好的朋友去看看原文。傑夫老師本著教學初衷,先利用一個簡單或常見的問題,來引出文章中的重點,希望大家能夠更容易懂。