走ってジャンプするゲームの制作に挑戦[Python6か月]
年末年始はゲーム作りに挑戦しました。自分と他人の命を守るためには、出かける頻度を下げ、家で楽しく過ごす必要がありますから。さっそくゲームを紹介します。
『Catch The Power』
プロローグ
女性であるために悔しい思いをした経験もあるでしょう。
だけど、あなたには今のままで大丈夫。
晴れた日に、少し場を見極めて勇気をもってJUMPするだけでPowerに手が届くこともある。
いつでも、あなたはGREATになれて、Powerを集めることができる……。
操作
起動した途端にすべてがはじまります。
移動:マウスカーソルを画面中心から左右にどちらかに動かす
ジャンプ:クリック
遊ぶための準備
このゲームは、Python3系が入っているコンピュータで次のコードスニペットの内容をコピペして.pyファイルを作って実行することで動作する想定です。(Windowsで動く「.exe」形式のファイルでの配布も考えてみましたが、オリジナルのコードではないからどうだろう?という気もします)
モジュールもPythonにはじめからあるtkinterだけで動作する想定です。
『CatchThePower』コード
#Catch The Power
#module
from tkinter import *
#window
window1 = Tk()
window1.title("Catch The Power")
#ゲームスピード1/1000フレーム単位。1/60は16。
gamespeed = 32
#画面のブロックを50*14*14
bloc=50
#canvas size
canvas1 = Canvas(window1,width=bloc*14,height=bloc*14)
#canvas表示(初回)
canvas1.pack()
def title_loop():
global jump_on
#画面クリア
canvas1.delete('all')
#キャンバス作成
canvas1.create_rectangle(0,0,bloc*14,bloc*14,fill="#BCE6EB",width=0)
gamelogo()
#説明
x=350
y=250
canvas1.create_text(x , y-30,font='50', text=r'女性であるために悔しい思いをした経験もあるでしょう。',fil='Blue2')
canvas1.create_text(x , y+30,font='100', text=r'だけど、あなたは今のままで大丈夫。',fil='Blue2')
canvas1.create_text(x , y+60,font='100', text=r'晴れた日に、少し場を見極めて勇気をもってJUMPするだけで',fil='Blue2')
canvas1.create_text(x , y+90,font='100', text=r'Powerに手が届くこともある。',fil='Blue2')
canvas1.create_text(x , y+120,font='100', text=r'いつでも、あなたはGREATになれて、Powerを集めることができる…',fil='Blue2')
def draw_screen():
#画面クリア
canvas1.delete('all')
#キャンバス作成
canvas1.create_rectangle(0,0,bloc*14,bloc*14,fill="#bce6eb",width=0)
#ゲームロゴ
def gamelogo():
#data
glaph0=[0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,0,0,1,1,1,
0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,0,1,1,1,0,0,1,1,1,
1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,
0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1,0,0,1,1,1,
0,0,1,1,1,1,0,0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,1,1,1,0,0,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,0,1,1,1,0,0,1,1,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,0,1,1,1,0,0,1,1,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,1,1,1,1,0,0,0,1,1,1,0,0,1,1,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,1,1,1,1,0,0,0,1,1,1,0,0,1,1,1,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,0,0,0,1,0,0,1,1,0,0,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,
1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,
1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,0,1,1,1,1,0,1,1,1,
1,1,1,1,0,1,1,1,0,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,0,1,1,1,
1,1,1,1,1,1,1,0,0,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,
1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,
1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,1,1,1,0,0,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,0,1,1,0,
1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,1,1,1,0,1,1,1,1,0,1,1,1]
glaph_x=25
glaph_y=25
col1='#fca3cc'
col2='#bce6eb'
i=0
j=0
k=0
dot=5
for i in range(0,len(glaph0)):
if i%44==0:
j = j+1
k = -j*44+44
#1ドットを描画 色の判別あり
if glaph0[i] == 1:
canvas1.create_rectangle(glaph_x+i*dot+k*dot,glaph_y+j*dot,
glaph_x+i*dot+k*dot+dot,glaph_y+j*dot+dot,
fill=col1,width=0)
elif glaph0[i] ==0:
canvas1.create_rectangle(glaph_x+i*dot+k*dot,glaph_y+j*dot,
glaph_x+i*dot+dot+k*dot,glaph_y+j*dot+dot,
fill=col2,width=0)
else:
pass
#地形
def drow_tikei():
canvas1.create_rectangle(0,bloc*12,bloc*7,bloc*14,fill="#6155a6",outline ='#6155a6')
canvas1.create_rectangle(bloc*7,bloc*12,bloc*14,bloc*14,fill="#a685e2",outline ='#a685e2')
#テキストで矢印表示
def the_explaint():
canvas1.create_text(bloc*3,bloc*13,text="<--",fil='#fff')
canvas1.create_text(bloc*10,bloc*13,text="-->")
#キャラ1
#「はるみのゲームライブラリー」のはるみさんありがとうございます。
def drow_cha1():
canvas1.create_rectangle(cha1_x1 - cha1_vx1,
cha1_y1,
cha1_x1+25 - cha1_vx1,
cha1_y1+25,
fill="pink",outline ='pink')
canvas1.create_rectangle(cha1_x1 + 25 - cha1_vx1,
cha1_y1+25,
cha1_x1+25*2 - cha1_vx1,
cha1_y1+25*2,
fill="pink",outline ='pink')
canvas1.create_rectangle(cha1_x1 - cha1_vx1,
cha1_y1+25*2,
cha1_x1+25 - cha1_vx1,
cha1_y1+25*3,
fill="pink",outline ='pink')
def move_cha1():
global cha1_y1,jump_on,ground1
global ido_lr,cha1_x1,cha1_vx1
#ジャンプ
jump_kyori = (ground1 -75) - cha1_y1
#ジャンプボタンON
if jump_on == 1:
#地面から離れていない あがる
if jump_kyori == 0:
cha1_y1 = cha1_y1 - bloc*4
#ジャンプ中 さがる
elif jump_kyori > 0:
cha1_y1 = cha1_y1 + bloc
jump_on = 0
#地面にめりこんでいる
else:
pass
#ジャンプボタンOFF
if jump_on == 0:
#地面から離れていない 何も起きない
if jump_kyori == 0:
pass
#ジャンプ中 さがる
elif jump_kyori > 0:
cha1_y1 = bloc*12 -75
#地面にめりこんでいる
else:
pass
#左右の移動
#移動距離
if ido_lr > bloc*13 or ido_lr < bloc*0:
cha1_vx1 = 0
else:
cha1_vx1 = 1
#マウスの位置がxの中心よりも大きいとき、移動
if ido_lr > bloc*7 and ido_lr < bloc*13:
cha1_x1 = cha1_x1 + cha1_vx1 * bloc
#マウスの位置がxの中心より小さいとき、逆に移動
elif ido_lr < bloc*7 and ido_lr >= 0:
cha1_x1 = cha1_x1 - cha1_vx1 * bloc
#マウスの位置が初期値x位置のとき、何もしない
else:
cha1_x1 = cha1_x1 + 0
#画面はしでとまる
if cha1_x1 + cha1_vx1 >= bloc*13:
cha1_x1 = bloc*13
cha1_vx1 = 0
if cha1_x1 - cha1_vx1 <= bloc*0:
cha1_x1 = bloc*0
cha1_vx1 = 0
#アイテム
#「こんにちはPython」のボールから縦軸移動をコメントアウト
#すがや先生ありがとうございます。
def draw_item():
global item1_x1,item1_y1,item1_vx1,item1_vy1
canvas1.create_oval(item1_x1 - item_size , item1_y1 - item_size , item1_x1 + item_size , item1_y1 + item_size , fill='#ffff00',outline ='#fff5c0')
def move_item():
global item1_x1,item1_y1,item1_vx1,item1_vy1
if item1_x1 + item1_vx1 < 0 or item1_x1 + item1_vx1 > bloc*14:
item1_vx1 *= -1
# if item1_y1 + item1_vy1 < 0 or item1_y1 + item1_vy1 > bloc*14:
# item1_vy1 *= -1
if 0 <= item1_x1 + item1_vx1 <=bloc*14:
item1_x1 = item1_x1 + item1_vx1
# if 0 <= item1_y1 + item1_vy1 <=bloc*14:
# item1_y1 = item1_x1 + item1_vy1
#判定
def hantei():
global item1_x1,item1_vx1,cha1_x1,cha1_vx1,item1_y1,item1_vy1,cha1_y1,sc1
if (item1_x1 + item1_vx1 + item_size < cha1_x1 + cha1_vx1) and (item1_y1 + item_size > cha1_y1) :
canvas1.create_text(item1_x1 + item1_vx1 , item1_y1 - bloc,font='100', text='GREAT',fill='#0a043c')
sc1 = sc1 + 10000
#すこあ
def show_score():
global sc1
canvas1.create_text(450,50,font='10',text='SELECT VECTOR:mouse | JUMP:click')
canvas1.create_text(400,100,font='30',text='Pow: '+str(sc1))
def timer():
global sc1,timer1
canvas1.create_text(480,100,font='30',text='Time:')
if timer1 > 0:
timer1 = timer1 - 1
canvas1.create_text(520,100,font='30',text= str(timer1))
else:
canvas1.create_text(540,100,font='30',text='Time Over')
ending(sc1)
#ending
def ending(sc1):
global item1_x1,item1_vx1,cha1_x1,cha1_vx1,item1_y1,item1_vy1,cha1_y1
#画面の外へ
cha1_x1=0
cha1_vx1=0
cha1_y1=2000
item1_x1=0
item1_vx1=0
item1_y1=1000
item1_vy1=1000
#コメントする
canvas1.create_text(450,500,font='30',text='You gotta more than enough Power.',fil='#000')
canvas1.create_text(450,530,font='30',text='How many? '+ str(sc1),fil='#000')
#初期値
def configration1():
global sc1,timer1,ground1,cha1_x1,cha1_vx1,cha1_y1,jump_kyori,jump_on,ido_lr,cha2_x1,cha2_y1
global item1_x1,item1_y1,item_size,item1_vx1,item1_vy1
#スコア
sc1 = 0
#タイマー
timer1 = 100
#地面の場所
ground1 = bloc*12
#キャラ1
cha1_x1 = bloc*2 #最初の左右位置
cha1_vx1 = 0 #横向きの移動距離
cha1_y1 = ground1 -75 #地面400 身長75
jump_kyori = 0
jump_on = 0
ido_lr = bloc*2
#アイテム
item1_x1 = 300
item1_y1 = bloc*9
item1_vx1 = 30
item1_vy1 = 30
item_size = 10
#キー入力
#マウスの動き
def key_control(event):
global ido_lr
ido_lr = event.x
#マウスの動きを伝える
window1.bind('<Motion>',key_control)
#マウスのボタンの動き
def key_jump(event):
global jump_on
jump_on = event.num
#マウスのボタンの動きを伝える
window1.bind('<Button>',key_jump)
#実行内容
def main_loop():
draw_screen()
gamelogo()
title_loop()
show_score()
drow_tikei()
the_explaint()
drow_cha1()
move_cha1()
draw_item()
move_item()
hantei()
timer()
#ゲームスピード
window1.after(gamespeed,main_loop)
#初期化
configration1()
#ゲーム
main_loop()
#window 表示
window1.mainloop()
プレイ中の画面
静止画
プレイ中の動画。
もしもパッケージイラストがあるとしたら、そのイメージです。
参考にしたゲーム、書籍
「スカッシュ」(『こんにちはPython』収録)
以前、noteへの投稿で『こんにちはPython』最後の章の「スカッシュ」については、また時間のある時に、と思って放置しました。今回、この部分に取り組みました。
ゲームの構造やループの考え方などが見開き1ページのプログラムと丁寧な図解と会話で分かるようになっており、このゲームは基本的にはこのプログラムを改造したものと言えると思います。
少しでも習熟するのではないかと思って、変数の名前などはどんどん変えているのですが。
余談ですが。
「スカッシュ」ゲームのプログラミングはこの書籍のクライマックスです。
このセレクトはさすがだなーと思った話です。
『ゲームセンターあらし』は「インベーダー」というゲームのチャンピオンですが、「インベーダー」は「ブロック崩し」という有名なゲームを発展させたもののようです。「ブロック崩し」は、コミック版であらし本人もプレイしていたと記憶しています。その「ブロック崩し」も「PONG」を発展させたもののようです。
「PONG」は最古のビデオゲームといわれています。Youtuberヒカキンさんの家に豪華な筐体があり、それを観たことがある人はわかると思うのですが、2人用です。
「こんにちはPython」の「スカッシュ」は「PONG」と「ブロック崩し」の間にあるような、まさにインベーダーの先祖のようなゲームです。これぞ、インベーダーチャンピオンのあらしが燃えてプレイしそうなゲームだと思ってセレクトのセンスと漫画としての実現に感動しました。
「ジャンピングエイリアン」(『はるみのゲームライブラリー Part2』収録)
「ジャンピングエイリアン」というゲーム のプログラムを見て、1画面のジャンプゲームとしてやるべきことを検討しました。
主人公の形はトリビュートです。
海外インディーゲーム
例えば、海外インディーゲームを紹介するYoutubeチャンネル「なんてことなの。」で紹介されているのさまざまなゲームを見ると、
ゲームはすぐ終わっていい、色合いはどんどんかわいくしていい、作者のメッセージがあっていいということがわかります。今回のようなゲームが世の中にあってもいいのではないかと思えます。
「スーパーマリオブラザーズ」
自分自身のゲーム体験としては、ジャンプアクションのゲームを多く遊んでいます。
スーパーマリオは最初、四角い物体が動く状態から始まったという伝説がありますが、最初はそこを目指しました。
画面の縦横比についてもスーパーマリオにならってみました。
機能(関数)を作った順
ざっくり、次の順で作りました。
・画面の描画
・キャラクターグラフィックの描画
・地面の描画
・キャラクターの単なる横移動(ただし、画面外に走り去る)
→2キャラがたたかう感じがいいと思って(「ストII」?)、キャラクターは当初2体いて、それぞれ逆方向い走り去る状態でしたが、大変そうだったのでやめました。
・マウス入力受付
・マウスの操作で左右の移動(ただし、画面外に走り去る)
・マウスクリックでのキャラクタージャンプ
→すごく大変でしたが、実装したら、ほんとに走ってジャンプする動きになって感動。
・画面端でとまる
→走り去ってしまうことを止めたくて、止め方のヒントがあるかと「スカッシュ」のボールの動きを写してみました。ヒントになったような……。とにかく現在位置(X)+移動(VX)という組み合わせだったので画面端まで行ったらXとVXの合計値を画面端のX座標に変更してしまうという処理にしました。
・タイムとスコアとゲーム終了時のメッセージ
→ここまでで、画面全体を細かく更新し続けているとわかったので、タイムとスコアについては、あんまり考えなくてもできました。変数を一定数づつ増やしたり減らしたりすればいいので。
・敵をやめて玉にして、当たり判定とGREATを追加
→「マイティボンジャック」はたまた「キン肉マン」のように移動する玉をとるゲームもありではないか?ということで、敵をやめてボールを表示するようにした。そして、当たり判定と「GREAT」表示を追加。適当に入力した「GREAT」がとてもよかったので、この先のゲーム作りの着想となりました。ボールがは斜めよりも水平に飛ぶ場合の方が面白いと思えたので、上下運動はコメントアウトしました。
・ロゴ描画
→やはりここはドット絵がかっこいいのではないかということと、以前に実現できたと思っていたので。実はここに数時間かかりました……。
・タイトル画面(できなかった)
→イントロダクションを数秒出す形や、クリックしたらはじまる形にしようと思ったのですが、Tkinterとしては簡単にはできないようで諦めました。
・言葉の調整、色調整、文字の位置調整
→ここでゲームとして仕上げるために必要と思うことを追加していきました。
ジャンプは想像以上に奥深かった
ジャンプの仕方についてわからなくて苦労しました。
ちょっと検索したらコードを抽出して本物のスーパーマリオのジャンプの仕方まで書いている方もいて、その探求心に本当に驚きました。今回はこの本物のマリオほどちゃんとしたジャンプにはできませんでした。パラメーターが多くて大変そうだからです。
また前述、「ジャンピングエイリアン」のコードをみて、ぶつぶつうんうん言いながらアクティビティ図(風味のメモ書)を起こしながら考えました。
結局、ジャンプの仕方については次の図のように場合分けして考えることにしました。
横移動、画面端で止める作業も奥深かった
「ジャンピングエイリアン」では現在位置(X)と移動距離(VX)による計算をしていることをプログラムの変数の名前から推理するまで時間がかかりました。
物理は高校からまともにやっていないので「VXあったわー」と思い出せるまでは「VXなんてややこしい名前をつけるなあ」と最初は思っていました。
タイトルロゴのドット絵
これは全く動かないドット絵なので、過去にエクセルVBAでがんばって作った覚えがありました。あらためてPythonで実現するのは難しかった……。
一度描画できるようになったら、逆にエクセル方眼紙で0か1かを決めてデータにしました。
レトロゲームとインディーズゲーム(雑記と後記)
・昔のゲームは短いものもあった
昔は 非常に単純なゲームが 書籍などで公開されていました。偶然「はるみのゲームライブラリー Part 2」という本を入手して「こんな人がいるのか!」と思っていました。(いないという説もある)
この本には、BASICという数学の教科書などに載っている言語で書かれたプログラムが印刷されており、一字一句間違わずに入力できたらゲームを遊べるというすごい本でした。
以前、途中までチャレンジしたのですが、入力だけでもくたびれ、ゲームが始まるところまでいけませんでした。いずれのゲームも動いたときは1画面で完結するようです。
・unityではなかったことが自分でも意外だった
最近、全世界的にはインディーズゲームの流れがあります。本当にいろいろな文化背景からうまれたいろいろなゲームがあります。
このPythonよりももっと気軽に2Dや3Dのゲームを作ることができるunityというツールがあって、でき上がったゲームはsteamで公開・販売ができます。Nintendo Switchでも購入できるものもあります。
unityは秋にインストールして解説書を読みつつ少しいじっていたので、最初に自分がアクションゲームを遊べる形までもっていけて、公開するならunityではないかと思っていたのですが、意外にもPythonでした。
・実験から生まれ、直接的メッセージがあるゲームが黎明期っぽい
通常、ゲームを作る場合は企画書があり、新しいゲームがどういう遊びなのか、何が面白いのかが説明されているのだと思います。
企画書はおそらく、ゲーム作りに投資する資本家や資本家から委託されて会社の取締役の人たちに向けてのプレゼンテーションで使われます。プレゼンテーションを受け、ゲームが面白いか、投資したお金が損にならないか、ということを判断しているもの思われます。ゲームを作り始めた後に当初企画と変わるにしても、ゲームを作っている期間はクリエイターの衣食住をゲーム会社がきちんと補償しないといけません。クリエイターも労働者なので衣食住いずれかのクオリティが大きく下がれば安定してゲーム制作を続けられないのでは?と思います。
このようなゲームの制作方法では、取締役や投資家の空気感以上のものは生まれないという制約があります。ゲーム制作者が人として持つ当たり前のメッセージのうち、とても入れにくいものが出てきていると思います。
このゲームは最初に決まった企画書のあるゲームではなく、「移動」「ジャンプ」「当たり判定」それぞれの再現実験からの成り行きでできたゲームでした。
とはいえ、「GREAT」の連発に励まし効果があるとわかり、これを活かそうと思いました。容量不足のレトロゲームで行われてきた説明文によるゲームデザインにて、表現と工数不足の自作ゲームこそフェミニズムやシスターフッドのメッセージ(※)入れることができるのでは?と、目指してみました。
日本のプロのクリエイターは前述の制約に忖度しなくては生き残れないというこだわりがあると思われるほど、テーマをいきなり書くことはしないことが多いみたいです。
このゲームで1行目にいきなり書いてあるものは、個人発信だからできると思います。
※レディー・ガガさんからのさまざまなメッセージや#MeTooのようなイメージです。
・「自分ならちょっとがんばればできるはず」で何十年
子どもの頃は「自分もいつか ゲームを作って発表してみたい」と思ったものでした。いつかゲームを作る目的という口実で長年かけて長時間ゲームに接してきました。(ただの遊び過ぎという説もある)
ですが、若いときにプログラミングが身につかなかったこと、ゲーム制作=プログラミングではないということ、ゲーム自体が年々進化して分業でないと作れなくなってきったことなどがあり(webもいつの間にか同じようになりましたね)、やっぱり自分にはできないかもとぼんやり思っていました。
・「ゲーム作ってみたい」はさまざまな事へチャレンジする動機として活かしてきた
トレンドになり取り上げる人が多い技術やプログラミング言語は本屋で立ち読みしたり@ITの初心者向けコラムを読むなどして、プログラミング言語については「hello world」くらいは書くようにしてきました。
長期休みにゲーム作りに取り組んだこと自体は今までに何回もありましたが(※)、その中でも突出したできばえでした。ほかにやることがとても少ない2020→2021の年末年始ならではの結果ではないでしょうか。12月29日から1月1日いっぱいかかりました。
※エクセルVBAにて、テキストベースのじゃんけんゲーム。全く動かないドットの絵の作成。想定した動きにならず、結果として点滅しながらすすむ車くらいはできたことがあります。車についてもXとVXを理解したので今後はできると思います。
今回できたのは、何度も諦めたジャンプアクションゲームだったので本当にうれしかったです。
自分で描いたプログラムとはいえ、プログラムを実行して画面の中のキャラクターが操作の通り動いたときは、仮想空間のなかの自律したキャラクターのように感じられました。
雑誌などで開発中ゲームの写真をみて待ち焦がれた末に購入し、ついに目当ての主人公キャラクターを自分の手で動かせたときのような感動がそこにありまsちあ。
・プログラミング能力不足という制限のなかからゲーム性を作る面白さ
マウスを使うことによる操作不可能性という不安に対して、「GREAT」表示と「Power」インフレによる快感のインセンティブにゲーム性を生むことができると思いました。加えて、世界観を明示することによる動機作りなど、パズルのピースをそろえていくことでゲームに仕上がっていくことが面白かったです。
・配布への試行錯誤
このゲームをPython環境のない他人に遊んでもらうことはできるの?と、試しにpyinstallerでpyファイルを.exeに書き出してみました。別のPCで稼働実験したら動いたので感動しました。
できた.exeは9メガくらいありました。最盛期には100円ショップなどでも流通していた3.5インチフロッピーディスク。これは1.2メガ。この中には「ドラゴンクエストII」が100本くらい入ると言われていました。
pyinstallerではpython自体を書き出しているという事情がありつつも、ほんものののレトロゲームと比べるととても重い……。
そしてこのファイルを知り合いに送るとき「新しいゲームができました。添付のエグゼファイルをダブルクリックしたら起動します」っていう昔のコンピュータウイルス(これもプログラム)のようなメールを出すのかな(笑)。
・イメージ作り(マーケティングも含めたモノづくり)
プレイヤーにいだいてもらうプレイ前のイメージがとても大事なので、この記事のトップに「いらすとや」さんのイラストを使った主人公のイメージを作って貼ってみました。
筆者はパッケージイラストはゲームの一部だと思っています。
ゲームをプレイしてはいけない日にパッケージイラストを眺めて「あのパッケージイラストのかっこいい&かわいいキャラクターはこのなかのどれ?」「なるほど! そういう意味だったのか」「あれっ?? あのパッケージイラストのかっこいい人はゲームの中のどこに出てきたの? もしかして自機のパイロットという設定?」などと色々想いをめぐらせる体験までもゲームだと思います。
やはり2020年の新作ゲームとしては、最近のヒーロー映画や海外インディーゲームと同様に、弱い立場になる人々がゲーム体験によりより良い気持ちになれるようなお話やゲームデザインを取り入れなければと思ったのでした。
ということで、このパッケージイラストのターゲットはnoteをみてPythonとフェミニズムに関心がある社会人の女性です。
このnote(というSNS的なコンテンツ投稿サイト)では、本当にフェミニズムに関心があれば、そういった内容の記事もありますからね。
結果として得られた仕事に役立つスキル
一旦終了です。おかげさまで充実し、関数をたくさん作って使うという実力もつきました。今後、つまった箇所、こだわった箇所を部分ごとの説明を詳しく書くこともあるかもしれません。
ここまでお読みいただきありがとうございました。