Edited at

[ジュニア向け] PythonとProcessingでプログラミング入門:その1 - ブロックくずしを作ろう


この記事について

この記事では、Processing(プロセッシング)のPython(パイソン)モードを使ってプログラミングの基本を学びます。

メインの対象読者は中高生ですが、プログラミング入門者であれば役に立ちます。


完成図

この記事ではかんたんなブロックくずしを作ります。


Processingについて

Processing(プロセッシング)を使うと簡単に画面に絵を出したりマウスの操作で絵を動かせたりできます。


なぜPythonモードか

Processsingでは通常、専用のプログラミング言語を使うのですが、この記事ではPython(パイソン)というプログラミング言語を使って書いていきます。

Pythonは簡単に書け、プログラミングの初心者からプロ中のプロまでが使う便利な言語です。ここでPythonをおぼえるとずっと役に立ちます。


インストール

※子ども向け注意:ページは英語で書かれています。ここはできれば大人に手伝ってもらいましょう


Processingのインストール

https://processing.org/ にアクセスします

以下のようなページがひらきます。左側にある「Download」というリンクをクリックします

次につかっているパソコンの種類にあわせてダウンロードします。

ダウンロードがおわると zipファイル(データが小さくなるよう加工したファイル)がダウンロードフォルダに表れます。

zipファイルをダブルクリックすると、Processingの本体ファイルが現れます。



このアイコンがProcessing本体です。


Pythonモードのインストール

Processingのアイコンをダブルクリックすると以下のようなウィンドウが立ち上がります。右側にある「Java」となっているところをクリックすると「モードの追加..」というメニューが表示されるのでそこをクリックします。

次に出てくる画面で「Python Mode for Processing3」をクリックします

ダウンロードがおわったらその画面を閉じます。

さきほどの画面(ダブルクリックして立ち上げた状態の画面)のJavaのところをクリックして「Python」を選べればOKです


PythonとProcessingの基本

プログラミング言語Pythonと、プログラミングを書いて動かすツールであるProcessingの基本について説明します。


Hello World(ハローワールド)

まずは最初に「Hellow World」と表示させてみましょう

print("Hello World")

このように書いて▶マークの実行ボタンをおすと、エディタ画面の下半分に Hello World と表示されます


円を描く

次に円を描いてみましょう。Processingは絵やアニメーションを描くのが得意なプログラミングツールです

size(300, 300)

ellipse(150, 150, 200, 200)

実行ボタンを押すと、縦300ピクセル横300ピクセルの画面に、縦のx座標150、横のy座標150の位置を中心とした、高さ200ピクセル、横幅200ピクセルの円が描かれます


setup()とdraw()

Procssingのポイントは setup() という関数と draw() という関数です。関数については、あとで詳しく説明しますが、この時点ではプログラミングのかたまり、というようにおぼえてください。

setup関数の中身は最初に一回だけ実行されます

def setup():

#..プログラムの最初に1回だけ実行される

def draw():

# プログラムが止まるまで繰り返し繰り返し実行される。1秒間に何回も実行される


最初に 400ピクセルx400ピクセルの画面を作り、ちょっとずつ位置どずらして円を描き続けている例です

x = 0

y = 0

def setup():
size(400,400)

def draw():
global x,y
x += 1
y += 1
ellipse(x, y, 100, 100)


変数

変数とは、数字や文字列などを入れる箱のようなものです。(*箱というとプロのプログラマーからは違うという意見がでそうですが、ここはジュニア向けなので箱としておきます)。

x = 100 # 100という数字を変数 xに入れた

name = "Taro" # Taroという文字を変数 name に入れた

数字や文字だけでなく、プログラム内でつくったものも入れることができます。例えば、画面、ボタン、スーパーマリオだったらマリオなど。おいおい説明します


if文

ある条件にあてはまったかどうかで処理を分ける場合に if 条件: という書き方をします。その条件の時に実行されるプログラムはインデント(頭に数文字分あけること)で指定します。またifの条件にはずれた時に実行される部分は else というキーワードに続けて書きます

↓の例でifの次の行が頭に数文字分あいていることに注目してください。同じ文字数分あいている数行が同じ条件の中で実行されるかたまり、という意味になります。

if x > 20:

print("ここの部分はxが")
print("20より大きい時に実行されます")
else:
print("ここはxが20以下の時に実行されます")

print("ここはxがどちらの場合も実行されます")


ブロックくずしを作る

ここから実際にブロックくずし作りに入っていきます


ステップ1: 円を動かす

まずは画面上に円を動かしてみましょう。「setup()とdraw()」の項目で作ったものと似ていますが、毎回draw()関数の中で background(0) として画面全体を真っ黒に塗りつぶしている点が違います。


x = 0
y = 0

def setup():
size(300, 300)

def draw():
global x,y
background(0)
fill(255)
x += 1
y += 1
ellipse(x, y, 30, 30)

実行すると下のように動きます


ポイント



  • ellipse は楕円という意味です。中心の位置と縦横の長さを指定して円を描きます


  • fill() は塗りつぶしを指定する命令です。()の中は色が入ります。この例の255は白を意味しています


  • global は関数の外側で作られた変数を操作する時に使います。このxとyは、プログラムの頭の方で最初に作られていて、それをdraw()の中で操作するのでこの宣言が必要です


  • += 1 は1を足すという意味です。


ステップ2: プレイヤーが操作するバーを表示する。

画面上の下の方にバーを表示し、キーボードの左右の矢印で操作できるようにします

x = 0

y = 0

barX = 0
barY = 260

def setup():
size(300, 300)

def draw():
global x,y
background(0)
fill(255)
x += 1
y += 1
ellipse(x, y, 30, 30)
rect(barX, barY, 60, 20)

def keyPressed():
global barX
if keyCode == RIGHT:
barX += 1
elif keyCode == LEFT:
barX -= 1

実行すると下のような動きをします。右矢印を押してバーを右に動かそうとしてますが、遅くてまにあいません


ポイント



  • keyPressed はキーが押されて時に実行されるプロセッシングで使える関数です。今回はこの中で押されたキーのコード keyCode が右または左の時にボールのx座標を 1だけ足したり減らしたりしています


  • if 条件: に続けて別の条件のチェックをする時は elif という宣言をします


ステップ3:壁でボールを反発させる

x = 40

y = 0
speedX = 2
speedY = 2

barX = 150
barY = 250

def setup():
size(300, 300)

def draw():
global x, y, speedX, speedY
background(0)
fill(255)
x += speedX
y += speedY
if x > 300 or x < 0:
speedX = speedX * -1
if y > 300 or y < 0:
speedY = speedY * -1
ellipse(x, y, 30, 30)
rect(barX, barY, 60, 20)

def keyPressed():
global barX
if keyCode == RIGHT:
barX += 3
elif keyCode == LEFT:
barX -= 3


ポイント


  • 本当は下まで来たらゲームオーバーですが、とりあえず下での反発させています

  • 変数 speedX speedY はそれぞれ横方向のスピード、縦方向のスピードをあらわしてます。

  • 画面の端まできたかをチェックしているのが if x > 300 or x < 0: の部分です


  • speedX = speedX * -1 は-1をかけて数字を反転させています。こうすることで逆方向に進むようになります


ステップ4: バーにあたったら跳ね返る


x = 40
y = 0
speedX = 2
speedY = 2

barX = 150
barY = 250

def setup():
size(300, 300)

def draw():
global x, y, speedX, speedY
background(0)
fill(255)
x += speedX
y += speedY
if x > 300 or x < 0:
speedX = speedX * -1
if y > 300 or y < 0:
speedY = speedY * -1
ellipse(x, y, 30, 30)
rect(barX, barY, 60, 20)
if x > barX and x < barX + 60 and y > barY and y < barY + 20:
speedY = speedY * -1

def keyPressed():
global barX
if keyCode == RIGHT:
barX += 3
elif keyCode == LEFT:
barX -= 3


ポイント



  • if x > barX and x < barX + 60 and y > barY and y < barY + 20: の部分でバーにあたったかどうかを判断しています

  • バーの動く速度を最初の例よりはやめています。


ステップ5: ブロックを表示する

横3列、縦3列、合計9個のブロックを表示させます。

x = 40

y = 0
speedX = 2
speedY = 2

barX = 150
barY = 250

def setup():
size(300, 300)

def draw():
global x, y, speedX, speedY
background(0)
fill(255)
x += speedX
y += speedY
if x > 300 or x < 0:
speedX = speedX * -1
if y > 300 or y < 0:
speedY = speedY * -1
ellipse(x, y, 30, 30)
rect(barX, barY, 60, 20)
if x > barX and x < barX + 60 and y > barY and y < barY + 20:
speedY = speedY * -1
for i in range(0, 9):
blockX = (i % 3) * 100
blockY = int(i / 3) * 30
rect(blockX, blockY, 100, 20)

def keyPressed():
global barX
if keyCode == RIGHT:
barX += 3
elif keyCode == LEFT:
barX -= 3

一応それっぽいものが表示されましたが、まだボールがあたっても消えません


ポイント

以下の部分で9個のブロックを表示しています。

    for i in range(0, 9): #9回の繰り返し。iに 0 から8までの数字が入ってこの中の文を繰り返し実行します

blockX = (i % 3) * 100 # ブロックのx座標(横の位置)。 i % 3は余りを計算しています
blockY = int(i / 3) * 30 #ブロックの縦の位置 int(i/3) は3で割って切り捨てしています
rect(blockX, blockY, 100, 20) # 長方形を描いています


ステップ6: ブロック表示部分を関数にする

次のステップでブロックがボールにあたったら消えるにようにします。そのためにブロック表示部分を関数にして draw の外に出しておきましょう


x = 40
y = 0
speedX = 2
speedY = 2

barX = 150
barY = 250

def setup():
size(300, 300)

def draw():
global x, y, speedX, speedY
background(0)
fill(255)
x += speedX
y += speedY
if x > 300 or x < 0:
speedX = speedX * -1
if y > 300 or y < 0:
speedY = speedY * -1
ellipse(x, y, 30, 30)
rect(barX, barY, 60, 20)
if x > barX and x < barX + 60 and y > barY and y < barY + 20:
speedY = speedY * -1
showBlocks()

def keyPressed():
global barX
if keyCode == RIGHT:
barX += 3
elif keyCode == LEFT:
barX -= 3

def showBlocks():
for i in range(0, 9):
blockX = (i % 3) * 100
blockY = int(i / 3) * 30
rect(blockX, blockY, 100, 20)


ポイント



  • showBlock という関数を作ってブロック表示部分をそこにまとめました。

  • draw() の中で showBlocks() という形で作った関数を実行しています


ステップ7: ブロックにあたったら消えるようにする


x = 40
y = 100
speedX = 2
speedY = 2

barX = 150
barY = 250

blocks = []

def setup():
size(300, 300)
createBlocks()

def draw():
global x, y, speedX, speedY
background(0)
fill(255)
x += speedX
y += speedY
if x > 300 or x < 0:
speedX = speedX * -1
if y > 300 or y < 0:
speedY = speedY * -1
ellipse(x, y, 30, 30)
rect(barX, barY, 60, 20)
if x > barX and x < barX + 60 and y > barY and y < barY + 20:
speedY = speedY * -1
checkBallHit()
showBlocks()

def keyPressed():
global barX
if keyCode == RIGHT:
barX += 3
elif keyCode == LEFT:
barX -= 3

def createBlocks():
global blocks
for i in range(0, 9):
blockX = (i % 3) * 100
blockY = int(i / 3) * 30
block = {'x': blockX, 'y': blockY, 'ok': True }
blocks.append(block)

def showBlocks():
global blocks
for block in blocks:
if block['ok']:
rect(block['x'] , block['y'], 100, 20)

def checkBallHit():
global speedY
for block in blocks:
if x > block['x'] and x < block['x'] + 100 and y > block['y'] and y < block['y'] + 20 and block['ok']:
block['ok'] = False # 次から表示しないようにしている
speedY = speedY * -1 # 当たったので縦方向の速度を反転させている


ポイント


  • ここではリスト(配列)ディクショナリという考え方が登場しています。

  • リストは、複数の変数を入れる箱です。ここでは blocks = [] という部分で宣言し、blocks.append() という命令を使って追加しています。

  • リストの中に入っている値は0からはじまる番号で指定することでとりだすことができます。例えば blocks[0] は一番最初に入っている値を、blocks[1]は2番目に入っている値をとりだします。


  • for block in blocks: のところは blocksというリストの入っている変数をひとつひとつ取り出して実行しています

  • ディクショナリは項目名と値のセットをもつ変数です。block = {'x': blockX, 'y': blockY, 'ok': True } の部分でひとつひとつのブロックが x, x, ok という3つの項目をもつものとして作られています

  • ディクショナリのそれぞれの項目の値を取り出す時はディクショナリ変数名[項目名] という形で書きます。つまり、 block = {'x': 100, 'y': 200, 'ok': True } というディクショナリがあったとして y の値を取り出す場合は block['y'] と書きます。


  • True False は真偽値(しんぎち)といって、もともとは、正しいか正しくないかを意味する特殊な値です。この例ではブロックを表示するかどうかという意味で使っています if block['ok']:if block['ok'] == True: と同じ意味です。

いまはスッキリとはわからなくてもとりあえずそのまま書いて動かしてみてください。何度も登場するのでだんだん分かってきます。


ステップ8: ゲームオーバーとクリアの表示

ボールが下の端を超えたらゲームオーバー、全てのブロックを消したらクリアと表示します


x = 40
y = 100
speedX = 2
speedY = 2

barX = 150
barY = 250

blocks = []

def setup():
size(300, 300)
createBlocks()

def draw():
global x, y, speedX, speedY
background(0)
fill(255)
checkClear()
x += speedX
y += speedY
if x > 300 or x < 0:
speedX = speedX * -1
if y < 0:
speedY = speedY * -1
ellipse(x, y, 30, 30)
rect(barX, barY, 60, 20)
if x > barX and x < barX + 60 and y > barY and y < barY + 20:
speedY = speedY * -1
checkBallHit()
showBlocks()
if y > 300:
textSize(30)
text("Game Over", 70, 150)

def keyPressed():
global barX
if keyCode == RIGHT:
barX += 5
elif keyCode == LEFT:
barX -= 5

def createBlocks():
global blocks
for i in range(0, 9):
blockX = (i % 3) * 100
blockY = int(i / 3) * 30
block = {'x': blockX, 'y': blockY, 'ok': True }
blocks.append(block)

def showBlocks():
global blocks
for block in blocks:
if block['ok']:
rect(block['x'] , block['y'], 100, 20)

def checkBallHit():
global speedY
for block in blocks:
if x > block['x'] and x < block['x'] + 100 and y > block['y'] and y < block['y'] + 20 and block['ok']:
block['ok'] = False # 次から表示しないようにしている
speedY = speedY * -1 # 当たったので縦方向の速度を反転させている

def checkClear():
for block in blocks:
if block['ok']:
return
textSize(30)
text("Clear!!", 70, 150)
noLoop()


完成版のコード

ここまでは 300x300の画面でやってきました。600x600まで大きくしたら完成です


# ボールを最初に表示する位置。xは横、yは縦の位置
x = 40
y = 200
# ボールが進むスピード。1回draw()関数が実行される時に何ピクセル進むか。縦横それぞれ定義する
speedX = 2
speedY = 2
# プレイヤーが操作するバーの最初の位置
barX = 300
barY = 550

# ブロックが入るリスト(配列)
blocks = []

def setup():
"""最初に1回だけ実行される部分"""
size(600, 600)
createBlocks()

def draw():
"""プログラムが止まるまでくりかえしくりかえし実行される部分"""
global x, y, speedX, speedY
background(0)
fill(255)
checkClear()
x += speedX
y += speedY
if x > 600 or x < 0:
speedX = speedX * -1
if y < 0:
speedY = speedY * -1
ellipse(x, y, 30, 30)
rect(barX, barY, 100, 20)
if x > barX and x < barX + 100 and y > barY and y < barY + 20:
speedY = speedY * -1
checkBallHit()
showBlocks()
if y > 600:
textSize(40)
text("Game Over", 200, 300)

def keyPressed():
global barX
if keyCode == RIGHT:
barX += 10
elif keyCode == LEFT:
barX -= 10

def createBlocks():
"""blocksというリスト(配列)にブロックをあらわすディクショナリを入れていく"""
global blocks
for i in range(0, 30):
blockX = (i % 6) * 100
blockY = 10 + int(i / 6) * 30
block = {'x': blockX, 'y': blockY, 'ok': True }
blocks.append(block)

def showBlocks():
"""ブロックを表示する"""
global blocks
for block in blocks:
if block['ok']:
# okがTrueのものだけ表示する。それ以外は既に消えている、ということなので。
rect(block['x'] , block['y'], 100, 20)

def checkBallHit():
"""ブロックにボールが当たったかどうかをチェックする"""
global speedY
for block in blocks:
if x > block['x'] and x < block['x'] + 100 and y > block['y'] and y < block['y'] + 20 and block['ok']:
block['ok'] = False # 次から表示しないようにしている
speedY = speedY * -1 # 当たったので縦方向の速度を反転させている

def checkClear():
"""全てのブロックが消えているかチェックし、消えていたらゲームを止める"""
for block in blocks:
if block['ok']:
# ひとつでも ok にTrueが入ってるものがあればこの関数を抜ける。
return
# ここまで来たということは1個もokがTrueなブロックがなかったということ。つまり全て消えている状態
textSize(40)
text("Clear!!", 200, 300)
# drawの実行を止める
noLoop()

次回はもうちょっと高度なプログラミングに挑戦する予定です。おたのしみに


続編