cacaponがゲームエンジンを使おうとすると壁にぶつかるわけ

最近ゲーム作りにハマっているcacaponなのですが、
どうしても、Unity,Unreal Engine4 を使って作ろうとすると
分からなくて壁にぶつかることがあります~ 特にUnreal Engine4~

というのも、cacaponが知っているゲーム作りの考え方が
ゲームエンジンで作っている時に、うまく表現出来ないことが
多いのです~

今回の記事は、cacaponの考え方を書き、
何で一致しないのかを備忘録として残しておこうと思います~

①cacaponが知っているゲーム作りの考え方とは?

一言でいうと、「無限ループの中に、描く部分と更新する部分がある」です。

例えば、次のような画面と入力装置があるとしましょう~

f:id:cacapon:20191108180645p:plain

このゲームは
矢印キーを入力されると、プレイヤーが動くゲーム
を考えています~
RPG然り、パズルゲームのカーソル然り、
色々な場面で出てきそうなパターンかとcacaponは思います~

ではどうやって実現するか?ですが…
大きく考えなければいけないのが

  • どうやって画面に描くの?
  • どうやって入力を受け付けるの?

の2点になります~ ではそれぞれ見ていきましょう~

・どうやって描くの?

まずは、画面の部分から見ていきましょうか~
仕組みとしては、
超高速でまっさら(今回だと真っ黒?)にしてから描きたいものを描く
という感じになります~

今回のをコードっぽく書くとこんな感じですね~
関数 描く():
    画面をまっさらにする関数()
 四角を描く関数(プレイヤーのX位置、プレイヤーのY位置、色)

無限ループ
 描く()
無限ループ終わり

上のをゆっくり動かすとこんなイメージになります。

f:id:cacapon:20191108183938g:plain

これを目に見えない速さで繰り返し描いているのが、
ゲームの描く部分だとcacaponは思っています~

・どうやって入力を受け付けるの?
 

描く部分は出来ましたが、これだけだとコントローラをいくら押しても
プレイヤーを動かすことができません。
何故なら、コントローラの入力を受け取る部分が出来ていないからです~

ではどうやって受け取る部分を作ればよいのでしょう?

仕組みとしては、
とあるキーが押されているか押されていないかを
無限ループの中で監視する」という感じですね。

今回のをコードっぽくするとこんな感じでしょうか?

関数 描く():
    画面をまっさらにする関数()
 四角を描く関数(プレイヤーさん.xの位置、プレイヤーさん.yの位置、色)

関数 更新する():
 もしも ←キーが押されたら:
  プレイヤーさん.動く(-1,0);
 もしも ↑キーが押されたら:
  プレイヤーさん.動く(0,-1);
 もしも →キーが押されたら:
  プレイヤーさん.動く(1,0);
 もしも ↓キーが押されたら:
  プレイヤーさん.動く(0,1);

クラス プレイヤーさん():
 持っている情報:
  xの位置 = 0
  yの位置 = 2
 出来る事:
  関数 動く(xの移動量、yの移動量):
   自分.xの位置 = 自分.x位置 + xの移動量
   自分.yの位置 = 自分.y位置 + yの移動量

無限ループ

 更新する()
 描く()
無限ループ終わり

更新のイメージはこんな感じでしょうか?

f:id:cacapon:20191108200327g:plain

コードで実現すると大変なのが「とあるキーが押されているか」を
判定する部分なのですが、これはゲームのライブラリなんかで
サポートされている事が多いです~ ありがたやなのです~

ただ、この更新部分は結構めんどくさくて、
値が範囲からオーバーしないようにするにはどうしたらいいの?とか
一回押したら一歩だけしか進めないようにするには?
いやいや、長押しが続いたら一定テンポで進めたいとか
結構考えることがいっぱいあります~

因みに、上のコードには安全対策の処理がないので、
ボタンを押した途端、感知した回数だけ移動するので、
超高速で画面外に消えることになるでしょう~

こんな感じで、ちっちゃいゲームでコード上な感じで作る分には
作るイメージが湧いてくるのですが、
cacaponがUnityなりUnreal Engine4なり最近よく使われるであろう
ゲームエンジンを使ったとたん、良く分からなくなるのです~

その理由を考えてみたところ、以下の理由が当てはまるかなと思いました~

1.描画の部分がゲームエンジンによるところが多く、理解していない

コードだと関数で描画()にして無限ループにすればいいってわかるのですが、
ゲームエンジンの場合
オブジェクト置いて、動かして~っていう感じみたいで、
たぶんそういうやり方をうまく理解していないんじゃないかなと
cacaponは勝手に思っています~

2.更新部分と描画部分を結び付けられない

cacapon的にはここが一番ネックだと思っています~
最近、Unityの方は少し理解できて来たのですが、
置いたオブジェクトと、動かすための部分(スクリプトとかブループリントとか)
の紐づけ方がよくわかっていないことが多いです~

スイッチを押したら、オブジェクトAに火をつける
みたいな動作を

コードだと流れでイメージにすることができるのですが、
Unityはスクリプトの実行順を指定できるしまだナントカ…
Unreal Engine4では…???…という感じなのです。

3.使う関数が多すぎる
色々な場面で対応できるようにするために、UnityもUnreal Engine4も
沢山関数が用意されています。ただ、それが何なのか理解しておらず、
それが壁になることもしばしばです~
ただ、これに関しては慣れもあるかなと思います~
cacaponも最初エクセルの関数とか全然覚えていなかったのですが、
沢山使っていくうちに、sum以外の関数も覚えていきましたし…
たぶんそれと同じなのかなと思います~

4.GUIベースで記述するプログラミングがよくわからない
今まで扱ってきたプログラミングが全てコード上で行うものなので、
Unreal Engine4のブループリントのように、
要素をくっつけていって動かすという
仕組みの考え方がまだ自分の中で怪しいです。
ココの問題は2,3の問題と深く結びついてそうなので
余計にこんがらがってそうです。

5.3Dに慣れていない
作ってきたのが、2Dのレトロゲームばっかりだったので、
3Dのゲーム作りにそもそも慣れていないというのもありそうです~

…む~、なんか前途多難な感じがしますね~
とりあえずはピンっと閃くまで3Dの簡単なゲームを作っていくっていう
感じが解決法になるでしょうか?
特にGUIで動作部分が作れるUnreal Engine4で作ると
理解が深まりそうです~ とりあえず頑張ってみます~

…1年後に見返したときに、「ああここで詰まってたけど、今は楽勝っス!」
ってなっていたらいいなぁ~

頭のよさげな方が考えた自己啓発法が肌に合わないcacaponが考えた、cacapon用自己啓発法

こんにちは、cacaponです~

cacaponは自己啓発本が結構好きでよく読むんですけど、
本屋さんとかに行くと東大式○○とか、
著名な学者さんの理論をベースにした○○法みたいな本が
よく見かけます~

でも、cacaponってそこまで学歴高いわけでもないし、
天才でもないので、そういった○○法って
並みの学力でほどほどな人には合っていないんじゃないかなと
常々思うのです~

もっと良くしたいなぁという気持ちがある一方、
頭が良い人向け啓発法だと敷居が高く感じるcacaponに
合った方法がないのか…というわけで、考えてみました~

まずは、どんなのが向いていて、
どんなのが向いていないのか考えてみることにしました。
cacaponの人生を振り返ってみると、
何個か成功したなぁと自分が思える出来事があるのです。
これはとても幸運なことだなぁとも思っています。

一つは卓球。
最初は2,3回のラリーもできなかったくらいのcacaponなのですが、
個人で全国大会に出場したことがあるくらいまでは成長することが出来ました。

もう一つが高校時代に学んだ情報処理の勉強ですね。
ここでエクセルの使い方を学んだり、タイピングの練習をしていました。
昼休みを使って、タイピングソフトのランキングを全部cacaponにする、
なんかもしてました(笑)


最後の一つはとあるスマホアプリですね。
もうかれこれ5年くらいやっていて、AppStoreにも
Googleplayからも消されたらしいスマホのゲームなのですが、
現在も無課金でサーバー内ランキング個人2位を保持できていたりしています~
(競争相手が少ないのもありますが…)


逆に失敗したことはたくさんあります~

ダイエットはうまく行っていないですし、
勉強自体も気が向いたもので無いと中々進められません。
SNSは苦手なのでトレンドな情報を得るのは苦手ですし、
かといって本の内容を覚えているかと言われるとそうでもないかなと思います~


こうやってみると、自分の伸びるタイプと言いますか、
なんかヒントがあるなぁと思うのです。

ここまで書いてみて自分が感じたのはこんな感じです~

  • 興味の範囲が狭い
  • 特化型が好き
  • 一つの事に集中しやすい
  • 成長している実感があると成功しやすい(特に初期段階)
  • 普通から逸脱している方が好きそう
  • 体験しないと納得できなさそう
  • 最新のもの、人気があるものにはそこまで興味がいかない
  • 大人数より少ない人数の方が良い?

こんな感じで見てみると、
cacaponは「興味の持てる特定の分野をじっくりコツコツやっていく
というのが向いているのかな?と思いました。
また、流行り廃りが激しいものを追うのは性格上向いていないので、
基礎理論とかをやっていく方がよさげだなぁと思いました。

じっくりコツコツやる場合、
フィードバックがあったり、実際に動かしたりしてみるアクションがある
なお良さそうです~
(卓球の場合はラリー回数・勝率など、情報処理はタイピングソフトのランキング、
スマホアプリは個人ランキングとステータスがモチベーションになっていました)

まあ、これはcacapon用なので、万人に合っているとは思いませんが…
これを読んでいる皆さんはどうでしょうか?自分の向いている
成長のさせ方というのは分かっている方が多いのでしょうか?

もしうまく行かないなぁと思ったら、自分の人生を振り返ってみて、
成功したこと、失敗したことを思い出してみると、何か見つかるかもしれません~

 

 

麻雀の順子と刻子の組み合わせってどのくらいあるんだろう?→プログラムで調べてみる

こんにちは~ cacaponです~

皆さんは麻雀ってやったことありますかね?
cacaponは結構麻雀好きなのです~でも、賭け事は嫌いです~
普通に一ゲームとして楽しみたいのですが…
仕方ないので我慢してます~

麻雀で上がるときの形って

(同じ牌が二つ)と
順子(しゅんつ 123みたいな数列)か刻子(こーつ 111みたいな同じ数字)が
4組で上がることができるんですけど…

ふと気になったのです、
この順子と刻子っの4組の組み合わせって何通りくらいあるんだろうと?

というわけで、作ってみました~

麻雀の組み合わせを調べるプログラム(頭は考慮してません)

 

コードの中身としては
最初に、一つの組をつくって…
次にそれを combinations_with_replacement で4つの重複組み合わせを作り…
最後に牌を5個以上使っている組合せを取り除く
って流れでやってます~

では、さっそく実行です~ …ちょっと時間かかるなぁ。
実行終わった後に組み合わせのcsvが出てくるんですけど、
下の行まで行ったら、366528通りありました!いっぱいですね!

ただ、これはあくまで「順子、刻子の4組」の組み合わせになります~
国士無双とか七対子とか特殊は形は考慮してませんし、
そもそも頭は考慮していないので純粋な上がりの組み合わせになると、
もっと多くなります~

頭も含めればいいじゃん、と思われるかと思いますが、
cacaponのプログラムだと抽出に時間がかかってしまいまして、
今回のブログでは断念しました~すみません~

もっと良いアルゴリズムを見つけたり、思いついたら
再チャレンジしたいと思います♪

たぶんどんな環境でも使えるであろう、ゲーム画面遷移の作り方になります~

こんばんは~ 最近ゲーム作りに力を入れているcacaponです~

テレビゲームや携帯ゲームをやったことある方、
見たことある方ならイメージしやすいと思うのですが、

ゲームって色んな画面の集まりなんですよ~
少なくとも、cacaponはそう思っています~

例えば、RPGなんかを考えると…

ゲームを始めますと最初にドドンと「タイトル」が出まして~
次に「どのセーブデータから選ぶか」出まして~
続いて「フィールド」ですね~
てくてく歩いていると敵が現れて「戦闘」です~
無事に終わったらまた「フィールド」~
あ、HPが…と思ったら「アイテム画面」を開いて薬草を~

…分かりますかね?
ちょっと書いただけでもこんなに出てくるのです~

という訳で、ゲームを作る場合は画面をいっぱい作ります~
そして、どこをどうしたらどう切り替えるのかも合わせて考えていきます~
こうすることでゲームの大まかな骨組みが出来上がってくるのですね♪

では、肝心の作り方なのですが…
cacaponはこんな感じで作っています~
①まず、Enumでゲームの名前を定義して、
②つぎに、今の画面が何なのかを覚えておいて、
③そして、あること(イベント)が起きたら指定の画面に変える


…こんな感じでできます~
え?こんなのでできる?と思った方~
ちゃんとサンプル作ってみましたよ♪
出来上がったのがこちら~

コードでゲームシーンの遷移を表現したコードになります~

 

f:id:cacapon:20191017002239g:plain


 

上のコードはpyxelというレトロチックなゲームが作れる
pythonのライブラリで作成したものです~

絵を描く余力がなかったので、文字ですみませんが、
スペースキーを押すと画面が遷移するようにしています~

コードを見ると分かるかもしれませんが、
まず大きくロジックと描画部分に分かれていまして、
さらに画面遷移毎で分割し、現在の遷移のものだけ実行する
…という感じにしてるんです~
こうしていくと、役割分担できるので後で作りやすくなるんですよ~
中の処理が増えてきたらファイル毎に分けるのも良いかもしれません~

もちろん、今回のサンプルはコードだけのものですが、
UnityやUnrealEngineなどのよく使われているゲームエンジンでも
使える考え方かなと思ってます~

例えばUnityだとこんな感じですかね?
f:id:cacapon:20191017000121g:plain

さっきのようなコードを使い、
画面毎にオブジェクトの有効化/無効化を切り替えてます~

どうでしょう?いい感じに動いているのではないでしょうか?

もちろん、今回のやり方はcacaponが扱いやすいやり方なだけであり、
実際にはシーンというもっと大きな枠組みで作ってから
ロードして切り替えたりとか、
他にもエンジン側でサポートしているやり方もありますし、
これが正解ではないかもしれません。

ただ、こんなやり方もあるよ~という選択肢の一つになれば、
cacaponとしては幸いです~

 

簡易な連鎖機能をつくりました〜

最近パズルゲームを作成中のcacaponです~
今日は「落ちものパズルゲームの連鎖」について書いていきたいと思います~

落ちものパズルゲームの連鎖の機能ってどういう風に作ればいいのかな?
…と電車の中でいろいろ考えた結果、とりあえず
簡単なものを作ってみることにしました~


考え方としては、

  1. ステージを描く
  2. 隣に消せるブロックがあったら消す
  3. 隙間を詰める

というのを繰り返す感じですね~


そして、できたコードがこちら

出来る限り簡単にした連鎖処理のプログラムです。

 

実行するとこんな感じになります~

f:id:cacapon:20191011111215g:plain


今回は横隣が同じ数字だったら消す、みたいにしています~
因みに3個消しは未対応です~

内容はコードを見れば分かる方は分かるかもですが…
隣の数字が同じだったら0にして、
下が0だったら落とす、みたいな処理にしています~

チョットめんどくさいというかコード的に美しくないなぁと思ったのが、

描画の作り方で、最初、消した時、落とした時、それぞれで描画をしています~
これどうにかならないかな…

ゲームエンジンでこれを使う場合も、描画と裏方との兼ね合いで
めんどくさそうな部分が出てきそうです~

何はともあれ、無事に連鎖の処理を作ることができました♪
こんな感じで、もっとグラフィカルなものも作ってみたいですね♪

再帰処理について勉強してみました~

再帰処理って知っていますか?
プログラミングをされている方だとご存知の方も多いと思います~

簡単に言うと、「自分自身を呼び出す処理の事」ですね~
そんな関数の事を「再帰関数」ともいうそうです~

例えば、1からxまでを足す関数 add(x) を作ってみたのですが、
これは再帰関数になります~

def add(x):
    if x == 0:
        return 0
    print('x:', x)
    return x + add(x - 1)


print(add(3))

…皆さんはこれの意味分かりますか?私は最初よく分からなくて…
何故足された結果がちゃんと帰っているのか理解できてなかったのです~

という訳でうんうん唸っていたのですが、
図にしてみてやっと理解できました~

f:id:cacapon:20191004213246p:plain

上の図はadd(3)の場合の処理ですね~
まずadd(3)が呼ばれます。return の値は 3 + add(2) になりますね~
次、add(2)が呼ばれます。return の値は 2 + add(1)
次、add(1)が呼ばれます。return の値は 1 + add(0)
最後のadd(0)はif文入るので0を返します~

これが順番に戻るのですね。
add(1) return 1 + 0 で 1が返り、
add(2) return 2 + 1 で 3が返り、
add(3) return 3 + 3 で 6が返ります~
だからprintで表示されるのが6なのですね~

因みに、なんで再帰処理を勉強したのかっていうと、
パズルゲームのステージの処理に使えるなぁと思ったからです~

ドクター〇リオとかぷ〇ぷよとかテ〇リスのカスケードモードみたいに、
隙間があったらパーツが下に落ちる処理を考えていたのですが…

{
 この位置の下の段が空いているとき、
 そのパーツを下にずらず

}を最上段から最下段まで繰り返す

ということをやりたかったのです~
{}の部分が実装できれば、後は何回呼び出すかの問題になりそうですし、
そうなると、add()みたいな関数にすればよいんじゃないかと思ったんです~

今まで二重のfor文でやっててごちゃごちゃしていたのが、
少しきれいになりそうです(笑

回転するブロックを置く処理を実装してみました~

最近、パズルゲーム作りにはまっているcacaponです~

今回は、作っているときに結構大変だった、
「回転するブロックをステージに置く」作り方について
まとめていきたいと思います~

ブロックの形は ■■■■ みたいのが降ってくる某有名落ちものパズルゲームを
想定してください~

さて、早速実装の仕方ですが、
正直言ってもっと良いやり方はありそうな気はします~

もしかしたらスマホだと見にくいかもしれませんがすみません~

①ステージ用の行列を用意する。
まずは、ブロックが動き回れるようなステージを用意しました~
表現の仕方としては、
[
  ['無','無','無','無','無','無','無','無'],
  ['無','無','無','無','無','無','無','無'],
  ['無','無','無','無','無','無','無','無'],


  ['無','無','無','無','無','無','無','無']

]

みたいな感じな行列を作りました~
ブロックが固定されると、
['青','青','青','青','無','無','無','無',]←■■■■ を固定したとき

という感じにします~

②ブロック用の行列を用意する
ステージとは別にブロック用の行列も用意しました。
どのブロックを回しても、高さと幅が4までなので、
4 x 4 の行列ですね~

[

 [
  ['青','青','青','青'],
  ['無','無','無','無'],
  ['無','無','無','無'],
  ['無','無','無','無'],

 ],

 [
  ['青','無','無','無'],
  ['青','無','無','無'],
  ['青','無','無','無'],
  ['青','無','無','無'],

 ] 

 こんな感じに、それぞれの向きの行列を一つずつ用意しました~

③ボタンを押したら回る動きを作る
ボタンを押したら回るようにします~
ここは、ボタンを押した数を4で割った余りで制御しました~
そうすると、012301230123...となるので、
0だったらこの向き~みたいな感じでセッティングすることができます~

④ステージと動かせるブロックを表示する。
ステージ自体は行列の値と表示するブロックを結び付けて表示してました~
例えば、青だったら青のブロック画像を表示させる…みたいな感じですね♪

動かせるブロックに関しては、ブロックの座標を管理して、
ステージの画像の上に上書きするように
その座標にブロックの画像を表示させていました~

⑤固定させるときの処理を作る
いよいよブロックの固定ですね~
実は今回作ったパズルゲームは「落ちる」のではなく、
マウスでブロックを自由に動かして決定ボタンを押したときに、
おけるのなら置く、という形をとっていました~

そのため、実際の落ちものパズルみたいに自由落下はないのですが、
動く範囲を制限したりはみ出たりしないようにしなければいけません。

こちらに関しては完全には達成できませんでしたが、
以下のような処理をして対応しました。

  1. 左右は②で作ったブロックの左上を基準にして、
    その基準がステージを超えないように制限しました
  2. ステージの行列に3幅分見えないバッファ行列を作りました
    例:['無','無','無','無','無','無','無','無','bf','bf','bf'] (bf =バッファ)
  3. ステージの下にも3段分バッファを作りました
    例:['bf','bf','bf','bf','bf','bf','bf','bf','bf','bf','bf']
  4. 決定ボタンを押した時、ブロックの座標から左に4つ、下に四つ、
    計16分の行列をチェックします。
    ブロックの個所が、ステージ側に既に置かれていないかチェックしたいので
    ブロック側の行列とステージ側の行列を見て、
    置く予定の場所が無以外があったら警告音を出して固定させないようにします。
    イメージとしてはこんな感じ…伝わるかなぁ

    f:id:cacapon:20190927155540p:plain

2,3に関しては、4を行うための保険ですね~
これやっとかないと右端や下で置いたときに行列の外に出ちゃうのです~
上のイメージ図下側、13~16でエラーを起こさない為に必要になりました~

さて、こんな感じで実装を進めていきましたら、
なんとか置けるところまで行きました~

固定の処理とかブロック用の行列の用意とか…
もっとスマートなやり方がありそうなのですが、
こんなやり方がありますよ~と知っている方がいたら、
ぜひ教えてくれると嬉しいです♪