Goldensteps

個人ブログです 意義はないです

プログラミングが上達するって?

マジもんのクソゲーとは言え一つ作り上げてみたというのは自信になります。そうです、あんなクソゲーでも自分以外が遊べる状態まで完成させる、と自信がつきます。(そしてある程度の技術的実績が自分に積まれます)

だから今話題の渦中にいる、中学生ランキング「将来ゲームクリエイタープログラマー)になりたい」といっているそこのお前! ゲームクリエイターがやる仕事の内容はゲームをクリエイトすることだぜ!クソゲーでいいから作ろう。今この瞬間からできる。こんなオッサンでも1日でこの程度のクソゲーなら作れるぞ!そして傲慢にも「これで遊んでくれぇ~~~」と涙を流しながら放逐しよう!!いけ!!ウンコを投げつけろ!!!

で、今日はそうして作ってみる中で感じたことと学んだことを少し書きます。

◆プログラミングがうめーってなんだよ

プログラムを組んでいて思ったのですが、プログラミングが上達するというのはどういうことを指すのでしょうか。当然、どんな言語を使っても共通で扱える考え方だとかをすぐ引き出せるように熟達しているとか、そういうことがあげられるかとは思います。

とは言えですね、今回のクソゲーだいたい300行くらいあるんですけど、そのほとんどをKuina.ch公式のサンプルプログラムと、kuin.exeに入ってるサンプルプログラムとから借用してきてしまっているんですよね。

ほとんどが借りパク状態なんです。コピペしたわけじゃないんですが、キーボードでコピペ的に入力したところが多い、というのが実態です。どうしてそうなるのかというと… 「何か機能を使いたい時に、すぐ頭の中に使い方が出てこない」からなんですね。

機能どころか、サンプルプログラム内にある演算子1個の記号についても「あれ?これなんの演算子だっけ?」ってなるわけです。すーーーぐ忘れちゃうんですよ。#ってどんな意味?@はなんで使ってんの?みたいに。だから見るしかないんです。kuina.ch公式の言語仕様を読むか、サンプルプログラムで使われてる所をさがして同じように利用する。基本的にはそれしか手法がない。超初心者ってそういう状態だと思います。

では、そうした言語に備わる一つ一つの機能を「暗記的に」思い出して使えたらそれはプログラミングが上達したと言えるのでしょうか? なんか、違う気がしませんか?だってそれは、となりに言語仕様ページなり、参考書なりを置いて参照して書いても、出来上がりにそう大きな差はでない訳じゃないですか。たぶん、上達っていうのとは表現が違いますよね。「慣れ」っていう方が近いんじゃないかと思います。

というかですね、やってて思いましたがよほど何年も同じ言語だけを使ってるでもないかぎり、これ一つ一つの丁寧な書き方とか「忘れる方が普通」ですよね?え?そんなことない?スイマセンIT現場の経験はないんです。いや僕は忘れて当然かなという感じがします。だから、そういうのはプログラミングが上達したというのとはなんとなく本質が違うような気がするのです。

プログラミング作業って「常にカンニングし続けてる」状態ですよね?実際のIT現場はどうなんでしょうか。それが正しい姿でいいと思います。

f:id:trasque:20171006143051p:plain

kuina.ch公式サイトの言語仕様の一部。このあたりは常に開きっぱなしで、見るために何度も往復しました。何度も。

 

◆そんな使い方しらんがな

今回のクソゲーで最も悩んだのは「list構造の処理の仕方」と「マウスの入力に関する調整」です。一番面倒だったのは「あたり判定の座標の位置調整」です。

ひとつずつお話します。

1>list構造の処理の仕方

クソゲーではTwitterの発言みたいのが上から次々と流れてきます。その☆を押して得点になると言うゲームなんですが、この発言を1個として次々リストに放り込んで行くわけですね。で、画面の一番上に一番新しい発言が来るという描画をしたかったわけです。だから、新しい発言が生成されるたびに、listに入っている各発言の描画座標を変更してやらなきゃいけませんでした。

Kuinのサンプルプログラムはインベーダーゲームでした。弾を発射するとあとは勝手に飛んでいく仕様です。だから「弾が飛ぶ描画は時間経過でオッケー」でした。list構造に対する計算も単純です。全て同じ距離を飛ぶから、時間を利用して加算するだけでした。

だけど、ゲームの内容が変わればそういう計算方法は変わります。こうなると、サンプルプログラムには書いてありません。listの順番や、座標を動かす範囲も一定ではなくなってきます。

そうこうしているうちに「アレも考える必要があった?」「コレもおさえてなきゃいけない?」というものがどんどん出てくるんですね。そんなもんしらんがなですよ。サンプルに書いてなけりゃわかんねーんだもん。

そこからプログラミングの上達が始まるんだな、って思った訳です。

作業を進めていると当然「詰まる」時が出てきます。詰まってる時の方が長かったです。ですが同じ「詰まってる状態」でも、いつも同じ状況ではありませんでした。

それは次のように分解できるような気がします。

  1. 疲れるなりして、やる気が出ない
  2. 使いたい機能の書き方を思い出せず瞬時にコードを書けない
  3. どのような組み合わせにしたら動くのか試行錯誤が必要である
  4. そもそも「想定したことが可能なのか」すらわからない

といった感じです、それぞれ微妙に意味は違いますよね?(1)は休むか気合を入れるかしてください。(2)なら調べて順を追ってください。カンニングです。

今回のlist構造で悩んだのは(3)! これです。

インベーダーゲームの弾は、生成したらあとは勝手にY座標が描画フレームごとに増えていって、ある程度いったら消えるという処理でしたから、弾が生成されたら順次追加していけばいいんです。1個前の弾も、1個後の弾も関係ありません。

ぼくのクソゲーは「1個前の発言の座標」を気にして計算しなければいけませんでした。

f:id:trasque:20171006141836p:plain

画像のAトラスクの発言は、ゲーム上「一番最後に生成されたもの(一番新しい)」です。つまりlistの一番最後に追加されたもの、ということになります。

その1個下あさのの発言は、次に新しいものということになります。

このゲームはTwitterの発言を模したような奴を1個としてまとめています(クラス設計って奴ですね!オブジェクト指向やってみたよママ!!)

丸で囲ってあるところを見ると「発言の行数が違う」のがわかると思います。いいでしょこれ?ランダムで1~5行を生成するんです。

1~5行がランダムということは、1個の発言の「高さ」が変わるってことです。Aトラスクの発言とBあさのの発言では大きさが違いますよね?Twitterでも長文爆撃してるクソ野郎がいると、すぐ画面が埋まっちゃうじゃないですか。アレです。

全部同じ高さだったのなら、考える必要はありませんでした。インベーダーゲームと同じように、発言が生成される度、単純に決まった数値を足せばいいからです。

でも、これは違いました「前後で数字を調整しなきゃいけない」んです。

list構造の中で隣り合った者同士をどうにかしないといけない。

そういう問題にブチ当たったんです。

ぼくは考えました。「1個前の要素を見に行けばいいじゃん」って。やってみました。kuina.ch公式にはやり方が書いてあります。「list構造の中にある要素の1つ前に行く」というのがprev()という奴です。

でもprev()しちゃうと、全部1個前に戻っちゃうんですよ。違う!そうじゃない!ぼくは1個前に戻りたいんじゃない!1個前を見たいだけなんだ!

……ってな感じで悩みの沼にハマっていってしまった訳です。

こういうのって、どのタイミングで何の値を保持しておいて、どういう順番でいつ使うか、みたいな問題ですから(3)のように、色々入れ替えたりしてうーんうーんと悩むんですね。

で、もうこれはそもそも根本から間違ってるのかな……?って諦めかけた時にいきなり解決したりするんですよ。

こういう瞬間に「プログラミングが上達する」んじゃないかと感じた訳です。その数秒前までは持っていなかったlist構造の使い方が、柔軟になった訳ですから。

2>マウス入力関係

このクソゲーは☆をクリックできるかどうかっていうゲームなので、あたり判定をシビアにしてクリックできるようでできないっていうイライラがサイコーに面白いところです。クソゲーですね。

でも自分でやってて気づいてしまいました。「マウスを押しっぱなしにしとけば全部☆を押せる」ということに。

さあ困りました。何がってマウス入力関係はkuina.ch公式に詳しく書かれていないんです。同梱のサンプルコードに「マウスが押された時」の記述はあるんですけど、一番基本的なことしか載ってないんですね。

これって(3)のように「どのように組み合わせたらできるのか?」っていう問題とはちょっと異なります。(実際はコレなんですけど)

ここで出てくる悩みが(4)です!

マウスの入力って、基本機能っぽい感じがするじゃないですか。だからkuina.chが用意しているサンプル以外の使い方はできないんじゃないかって思い込んでたんですね。

で、もうこれは仕様だなと思ってたんですけど、そこで諦めちゃいけないんです。冷静になるべきなんです。

世の中のゲームでマウス押しっぱなしが対応できないなんてことが、今の時代にンなことあるか? ……って。

できないのは「今の俺がただ思いついてないだけ」って一旦立ち止まるんです。その理論が正しければ、次に導かれるものはコレです。

がんばれば絶対できる

およそ一人で人工知能を開発するとか、そういうレベルのことをぼくがいきなりやろうと言うわけではないので、できるはずなんです。もちろん「仕様上できない」ってことはあると思うんですが、諦めちゃいけません。ゲーム開発に向けたプログラミング言語だって、くいなちゃんが言ってる訳ですから。

結局、マウスを押したときにロックされる機構を考えて、押しっぱなしは判定されないようにするということを実装できました。これだけのことも、ちゃんと決めてプログラムしないといけないんですね。っていうことを学べた訳です。

3>あたり判定

当たり判定ってどうなってんのか今まで不思議だったんです。

オブジェクト指向っつーくらいなので、なんかこうそういうのイイカンジに勝手に計算してくれんのかなと思ったんですけど、んな訳ありませんでした。

今回のクソゲーは☆をクリックすると反応しますが「星そのものがあたり判定を持ってる訳じゃありません」のです。

「発言1個」をひとまとめにして1つのオブジェクトとしてますが、判ってるのはその発言の左上の座標です。アイコンの左上ですね。

で、その左上からXに140ピクセルくらい、Yに60ピクセルくらいに☆が存在するんですけど、その小さな範囲に入ってる時にクリックしたらあたりとするっていう風にしたんですね。強引ですよね。

実際、数多のアクションゲームがこんな強引なやり方してるとは思えないんですが、これでもどうにかなる訳ですよね。やり方はいくらでもあるってことなんだと思います。

見た感じ正しけりゃいいじゃん!

◆プログラミングの上達は「壁」と共に

プログラミングはおおよそ初めてで、クソゲーを作って体験できたのは「壁と共に上達の種が落ちている」ということでした。

もしこの文章を未経験の方が見ていたら想像して頂きたいのですが「さあ、いま何かゲーム作ってみて」と言われた時に、一切何にもわかんないじゃないですか。その「進める気がしない感じ=壁」を目の前にハッキリと感じたら、それはチャンスなんだと思うんですね。

クソゲーを作ろうと思うにあたって、正直最後まで作れるとは思ってなかったんです。作成途中も「こりゃ最初から作り直すか、諦めるかしかねえかな」って考えたことが何度もありました。それくらい「あっわかんねえ進めない無理っていう壁」が何度もやってきます。

で、その壁が来た時に「ぐぬぬぬぬおおおおーーッ!」と足掻くんです。色々調べるなり、メッチャ考えるなり。それしかないです。なんかそうすると、気付いたら実現してます。欲しかった画面が、実現してるんです。スゴイですよこれ。メッチャ楽しい瞬間でした。プログラミングの楽しさってこのあたりに感じてるんでしょうかね皆さんは。

だから「ゲーム作りたい」ともやもやしてるそこのお前! いいから今すぐ、ぐぬぬぬおおおおーーッ!っと進みましょう!!そしたらできる!!

それが言いたいだけの、今回の記事でした。ありがとうございました。