scratch の覚え書き

初版作成  2013.12.27
最終更新  2024.04.01


◆◆ サイトの場所 ◆◆


scratch.mit.edu

◆◆ たちの悪いバグ ◆◆


scratch でプログラミングをしていて
if の動作がおかしく「なぜだ!」となることがある
(ex. if 0 < 1 が偽となる) 。
その原因は全角の数字を使っていることにある。

scratch のフォントは全角と半角の区別がつきにくい
1 桁の場合 (たとえば 0) は気がつかない。

ありがちなパターンは
「日本語の変数を使うために、日本語入力モードにして
戻し忘れる」


◆◆ 基本操作 ◆◆


ブラウザによっては右クリックが効かないことがある。
そのときは

  shift + 左クリック

◆◆ 座標 ◆◆


x 座標が -240 〜 239
y 座標が -180 〜 179

座標値は実数で保持する

◆◆ プログラムの open と save ◆◆


プログラムはクラウドに保存される。

プログラムは半自動でセーブされる。
明示的にセーブしたいときは「ファイル」→「直ちに保存」

別のプログラムを開きたいときは、右上の
「ユーザー名▼」→「私の作品」


◆◆ scratch の概念 ◆◆


scratch は「オブジェクト指向」「イベント駆動型」
の言語である。各オブジェクトはスレッドとして動作
するようだ。

オブジェクトは「背景」「スプライト○」である。

オブジェクトごとに「スクリプト」を組む


◆◆ プログラムのスタートとストップ ◆◆


「緑色の旗」をクリックするとスタート
「赤色の八角形」をクリックすると停止

「イベント:緑旗がクリックされたとき」で
ゲームスタート時の初期設定を行う。


◆◆ プログラムの組み方 ◆◆


プログラムはブロックをドラッグして接続する
ことで組む。

最上行の「複製 (スタンプマーク)」をクリックし、
ブロックをクリックすると、複数のブロックをコピー
することができる。

あるブロックをドラッグすると、下側が全てついてくる。

a
b
c

を

a
c
b

にしたいときは、b をドラッグして bc を引き離し、
c をドラッグして c を引き離し、a の下につけ、
b をドラッグして b の下につける。


◆◆ ダイレクトモード ◆◆


ブロック (ブロックエリア・スクリプトエリア どちらでも) を
クリックすると、そのブロックを実行 (basic のダイレクト命令に相当)。

たとえば「隠す」をクリックするとスプライトが消える。

◆◆ スプライトの操作法 ◆◆


「見た目:次のコスチュームにする」
を使うと、歩くアニメーションが作れる。

スプライトが見えないときは
  「見た目:表示する」
  「動き:x 座標を 0 にする」
  「動き:y 座標を 0 にする」
などをクリック

「動き:○度に向ける」において、
スプライトをそのまま表示するのは 90度

スプライトは x, y 座標に加えて向き(-180度 〜 +360度)を
持っている。「10 歩動かす」はその向きへ 10 ドット移動させる。
真上が 0 度、左が -90 度、右が 90 度、下が 180 度
デフォルトは 90 度。

スプライトの位置や向きは、「動き」の下の方にある
(スクロールしないと見えないことがある)。

他のスプライトの位置は
「調べる」の「『ステージ▼』の『背景』」を
「『スプライト名▼』の『x』」で得る。


◆◆ スプライト画像の変更 ◆◆


スプライトをクリックし、「コスチューム」
中央の「+」マークがスプライトの座標


◆◆ ステージ上でのスプライトの拡大・縮小 ◆◆


最上行の中央部にアイコンがある。

消す      :ハサミマークをクリックし、スプライトの上でクリック
縮小, 拡大:縮小, 拡大のアイコンをクリックして、スプライトの上でクリック
新規に選ぶ:「スプライトをライブラリーから選択」アイコンをクリック


◆◆ 背景の変更 ◆◆


左端の背景の領域をクリックすると、中央の領域に「背景」という
タグが出現する。


◆◆ 色の選び方 ◆◆


「調べる」のブロックの色の選び方は以下の通り。

1. ブロックの色の上でクリック。
2. 目的の色の上でクリック。


◆◆ 変数 ◆◆


「データ」にある。
配列は「リスト」。添字は整数で 1 からはじまる。

「すべてのスプライト用」にチェックを入れるとグローバル変数
「このスプライトのみ」にチェックを入れるとオブジェクトのローカル変数
「クローン」を作ると「このスプライトのみ」の変数は「各クローン毎」に
用意される。

変数名の横のチェックボックスに印を入れると、
変数の内容が常に表示される。

変数への代入は「データ」の
「○○ を △△ にする」というブロックを使う。
「演算」の「○ = △」ではない。

A = A + 2 は「 A を 2 ずつ変える」
A = A - 3 は「 A を -3 ずつ変える」


◆◆ 値のキー入力 ◆◆


「調べる:○○と聞いて待つ」
で入力用テキストボックスが出現する。
入力した値は「答え」という名前の変数に入る。


◆◆ メッセージの使い方 ◆◆


「イベント:メッセージを送る」でメッセージを送り、
他のスプライトのスクリプトで「イベント:メッセージを受け取ったとき」
で受け取る。

(注意!)

メッセージはすべてのオブジェクトが受け取る。
あるスプライトのクローンが 2 つ作成されていたとすると、
「本体」「クローン1」「クローン2」の 3 個が受け取り、
それぞれのオブジェクトが「メッセージを受け取ったとき」以降を
実行する。

たとえば、メッセージを受け取ったとき A = A + 1 を実行し、
クローンを含めてオブジェクトが 3 個あったとき、A は 3 増える。


◆◆ キー入力 ◆◆


キー入力の調べ方は 2 通りある。

1. 無限ループの中で「調べる:○キーが押された」
2.「イベント:○キーが押されたとき」

1. はその瞬間にキーが押されているかどうかを調べる

2. のイベントの発生のタイミングは、メモ帳や Word において、
画面に出現する文字と同じである。

たとえば、a キーを押し続けるとき、「a キーが押されたとき」
というイベントが発生するのは以下のようになる。

   a       aaaa
 ------------------> 時間

シューティングゲームなどリアルタイムのゲームでは
1. の方式を使う。

2 つのキーを同時に押したとき、両方を検知できる
のは 1. である。

2. は以下のようになる。
たとえば、a と b を同時に押し、a の方が一瞬
はやかったとき、イベントの発生は

    ab      bbbb
 ------------------> 時間

となり、a キーを押し続けることを検知できない。

シューティングゲームなどで、弾を連射するとき、
以下のように組む。

もし[調べる:○キーが押された]なら
  弾発生の処理
  制御:[ (○キーが押された) ではない]まで待つ


◆◆ シューティングゲームのキー入力の組み方 ◆◆


2 種類のキー入力を処理する必要がある。

1. 移動キー
2. 弾発射キー

弾を正しく連射するには、弾発射キーを一度離してから
再度押すことを検知する必要がある。

   [ (○キーが押された) ではない]まで待つ

を使う。これを実行するときに移動が止まってはいけないので、
「移動」と「弾発射」は別々の無限ループを組む。

弾発射キーを調べる無限ループは
「移動体スプライト」「弾スプライト」など
どのスプライトのコード領域に置いてもよい。
弾スプライトに置くのが分かりやすい。

複数の弾を扱うときのコードの組み方は、
難解である。次の項目で説明する。


◆◆ クローン ◆◆


複数の弾を撃つ、複数の敵などはクローンを使う。

「制御:○のクローンを作る」

弾などは「見た目:隠す」でゲーム開始時に隠し、
弾発射を検知したらクローンを作る。
「見た目:表示する」で出現させ、
「このクローンを削除する」で消す。


シューティングゲームにおいて、
弾スプライトのコード領域に
複数の数を発生させるコードを書く場合を考える。

「自分自身のクローンを作る」は1箇所で実行する。
複数の場所で実行してはいけない。
たとえば、以下のように組んではいけない。

   弾発射キーを検知 → メッセージ1を送る
   メッセージ1を受け取った → 自分自身のクローンを作る

メッセージは全てのオブジェクトが受け取る。
「本体」「クローン1」「クローン2」があったとき、
3 個のオブジェクトがそれぞれメッセージを受け取り、
各自のクローンを作るので
「本体」「クローン1〜5」の 6 個に増殖する。
ネズミ算式に弾数が増える。
そして複数の弾が同じ位置に重なって描かれるという
たちの悪いバグが発生する。

「クローンされた後」のブロックに続く部分の中で
「自分自身のクローンを作る」を実行しても
同じことが起こる。「クローンされた後」のスレッドは
クローンの個数だけ実行されるので、その中で
「自分自身のクローンを作る」を実行すると、
ネズミ算が発生する。

シューティングゲームの弾発射は、
1個しか存在しないスレッド(通常は緑旗が押されたとき
から続くスレッド)に以下のようにブロックを配置する。

「ずっと」
  「もし「弾発射キーが押された」なら」
    「自分自身のクローンを作る」
    「「「弾発射キーが押された」ではない」まで待つ」


◆◆ ゲームの当たり判定 ◆◆


「調べる」の中に「○○に触れた」というのがある。
当たり判定はこれを利用する。

「隠す」の状態では「○○に触れた」は反応しない。

「端に触れた」は枠外に出ようとしたか否かが判定できる。

「調べる」の中の「x座標 of Sprite2」というブロックを
利用すると他のスプライトの位置が分かる(クローンの位置は
わからない)。

A と B が接触し、どちらもクローンを消滅させたいとする。

  A: もし B に触れたら、クローンを削除
  B: もし A に触れたら、クローンを削除

ではうまくいかない。
先に if の判定をした方だけが削除される。
タイミングによって、どちらかが消滅するということになる。

クローンを削除する直前に 0.1 秒のディレイ入れるという
方法もあるが、美しくない。このようにする。

  A: もし B に触れたら
         メッセージ1 を送って待つ
     このクローンを削除する

  B: メッセージ1 を受け取ったとき
     もし A に触れたら
     このクローンを削除する

ミソは「メッセージ1 を送って待つ」である。
メッセージを受け取った側のスクリプト(全てのオブジェクトが
受け取る)が終了してから「このクローンを削除する」が
実行される。

上の場合、クローンの個数が少ない方を A に割り当てた方が
処理が速くなる。

----------------

「○色に触れた」の色の選び方は以下の通り。
色の場所を左クリックすると色選択モードに入る。
マウスカーソルを動かし、目的の色のドットの上に置いて左クリック


◆◆ 当たり判定の tips ◆◆


「スプライト〇に触れた」と「○色に触れた」違いは以下の通り

・スプライト○に触れた
 - 自分が「表示する」になっていないと yes にならない
 - 同じスプライト(クローン)に対しては適用できない

・○色に触れた
 - 自分の状態(表示する/隠す)は関係ない
 - 同じスプライト(クローン)に対しても yes となる。

「○色に触れた」を使う場合、色の部分でクリックすると
色選択メニューに入り、一番下のスポイトマークを押すと、
ゲーム場の中の色を拾うことができる。

◆◆ お気に入りを見る ◆◆


「ユーザー名▼」→「プロフィール」

薮お気に入りのゲーム

title: brick_road
author: 103769

title: Tetris remix
author: mygame11

title: 青に触れるな!
author: tatsu777

他人のプログラムを見ている画面で、右上の「リミックス」
ボタンを押すと、自分のプロジェクトとして取り込むことが
できる。


◆◆ if における >= と <= ◆◆


a >= 5  は以下のように表現する

[a > 5] または [a = 5]


◆◆ ゲームオーバー or クリア の表現 ◆◆


Game Over あるいは Clear と書いた
スプライトを用意する。

ゲーム開始時に [隠す]

ゲーム終了のイベントで [表示する]


◆◆ 乱数 ◆◆


演算ブロックに

  [○から○までの乱数]

がある。[1 から 3 までの乱数]とすると
1, 2, 3 のいずれかを発生する。

[1 から 3.0 までの乱数]とすると実数の乱数を
発生する。

ゲームで敵をランダムに出現させるとき、
無限ループの組み方は 2 通りある。

  もし [1 から 3 までの乱数] = 1 なら
    クローンを作る
  0.5 秒待つ

  -----------------------

  [0.2 から 2 までの乱数] 秒待つ
  クローンを作る


◆◆ 敵(複数:クローン)が弾を発射するときの処理 ◆◆


弾の xy 座標の初期値は敵(クローン)の xy 座標である。

敵(クローン)が弾(クローン)に位置を伝えるためには
グローバル変数を使うしかない。

1 個目の敵が弾のクローンを作成し、弾がグローバル変数を読む
直前に 2 個目の敵が弾のクローンを作成すると、
2 個の弾が重なってしまう。

以下のように組むことで、可能な限り上記の現象を防ぐ。

---------- 敵のスクリプト ------------
flag = 0
ずっと
    もし  乱数 = 弾発生 なら
        もし flag = 0 なら       (1)
            flag = 1             (2)
            x を [x 座標] にする
            y を [y 座標] にする
            弾のクローンを作る

---------- 弾のスクリプト ------------

クローンされたとき
x 座標を [x] にする
y 座標を [y] にする
flag = 0
表示する

-----------------------------------------

(1)→(2) の間にスレッドが切り替わったときは
上記の書き方でも NG である。

配列を使うと以下のように書ける。しかし、問題は
解決されない。

---------- 敵のスクリプト ------------
ずっと
    もし  乱数 = 弾発生  なら
        x 座標を xlinst に追加
        y 座標を xlinst に追加
        弾のクローンを作る

---------- 弾のスクリプト ------------

クローンされたとき
x 座標を 1 番目 [xlist] にする   (1)
1 番目を [xlist] から削除する    (2)
y 座標を 1 番目 [ylist] にする   (3)
1 番目を [ylist] から削除する    (4)

        ----------------

(1)→(2)  あるいは (3)→(4) の間にスレッドの
切り替えが行われると、x 座標, あるいは y 座標が
誤った位置になる。


◆◆ 画像エディタの操作法 ◆◆


画像は 480 x 360

下にパレットがある。
左上が前景色:ペン・長方形・塗りつぶしの色
右下が背景色:消しゴムで消すときの色

アイコン 意味
----------------------------
ペン   ペンで書く
直線   ドラッグで直線を描く
長方形  長方形を描く
丸    円を描く
T    文字を書く
バケツ  閉領域を塗りつぶす
消しゴム 背景色で書く

選択   領域を選択する
     移動 回転 拡大縮小


◆◆ ブロック定義 ◆◆


関数の定義のこと 引数も取れる

ブロック定義 --- ブロックを作る で関数定義開始