見出し画像

100日アプリ開発チャレンジ Day39 - サイコロの「目」を1ピクセルずつ手打ちで描画していたら、ゲシュタルト崩壊した話


Day39、座標パズルと格闘した日

100日チャレンジ39日目。今日は「サイコロシミュレーター」を作りました。

ボタンを押すと、画面の中でサイコロがコロコロ転がって、出た目の統計を棒グラフにするアプリです。機能自体はシンプルです。ランダムに1〜6の数字を出すだけですから。

でも、私は変なところにこだわってしまいました。「数字の『1』とか『6』を表示するんじゃなくて、ちゃんとあの黒い点のついたサイコロを描きたい!」

(こだわり、発動)

画像素材を使えば一瞬で終わる話を、あえてコードで描画しようとした結果、「座標計算」という名のパズルに挑むことになりました。

(また、座標...)

昨日、Day38。テンキー。3列×4行。座標計算3回ミス。1時間かかりました。

今日は、サイコロの目。1〜6の目。全部、座標で描く。

(学習してない...)


画像
完成形!!

シミュレーターの操作方法

  • 振るボタン:サイコロを1回振る

  • 10回振るボタン:サイコロを10回連続で振る

  • リセットボタン:統計データをクリア

  • 統計グラフ:1〜6の目が出た回数を棒グラフで表示

  • アニメーション:サイコロが回転しながら結果を表示

サイコロの「目」ってどうなってるの?

サイコロの目をコードで描くには、「1の目は真ん中」「2の目は左上と右下」…といった位置情報を、全部ピクセル単位で指定しないといけません。

ノートに正方形を描いて、X軸とY軸を書き込んで…

「えーっと、5の目は真ん中と、四隅だから…」

(図形問題、始まった)

まるで数学の図形問題です。眠い頭を抱えながらひねり出したコードがこちら。

# 目の位置を定義(ここを書くだけで脳みそが疲労骨折した)
# (-1, -1) は左上、(1, 1) は右下... 呪文かな?
positions = {
    1: [(0, 0)],
    2: [(-1, -1), (1, 1)],
    3: [(-1, -1), (0, 0), (1, 1)],
    4: [(-1, -1), (1, -1), (-1, 1), (1, 1)],
    5: [(-1, -1), (1, -1), (0, 0), (-1, 1), (1, 1)],
    6: [(-1, -1), (1, -1), (-1, 0), (1, 0), (-1, 1), (1, 1)]
}

この(-1, -1)とか(1, 0)という数字の羅列。これ、一つでも間違えるとサイコロじゃなくなります。

(実際、最初は4の目が変な台形みたいになってました)

4の目が台形になった事件

最初の実装:

4: [(-1, -1), (1, -1), (-1, 1), (1, 1)]

これ、正しいはず。四隅。左上、右上、左下、右下。

実行。描画。

(あれ...?)

4の目、変です。台形みたい。点の位置、おかしい。

(なんで...?)

デバッグ。printで座標を出力。(-1, -1)、(1, -1)、(-1, 1)、(1, 1)。

正しい。計算も合ってる。

じゃあ、なんで台形に...?

(30分、悩んだ)

原因:サイコロのサイズ、間違えてました。正方形じゃなくて、微妙に長方形になってた。

(初歩的ミス...)

修正。正方形にする。実行。完璧。

(やっと...)

1の目:真ん中に1個。簡単。

2の目:対角線上に2個。まだ簡単。

3の目:対角線上に3個。これも大丈夫。

4の目:四隅に4個。ここで台形事件。

5の目:四隅と真ん中に5個。座標5個。

6の目:左右に3個ずつ、6個。座標6個。

(全部で21個の座標...)

21個の座標、手打ちしました。(-1, -1)、(1, 1)、(0, 0)、...

(疲労骨折...)

心が折れかけた瞬間:棒グラフの高さ

サイコロ本体ができたと思ったら、次は「統計グラフ」です。出た目の回数に合わせて、棒グラフの高さを変えないといけません。

「最大値に合わせて、棒の高さを画面に収まるように縮小して…」

比率の計算です。文系エンジニアの私にとって、「比率」と「座標」は天敵です。

(また、算数...)

# 棒の高さを計算(算数ドリルかな??)
bar_height = (stats[i] / max_count * (height - 60)) if max_count > 0 else 0
bar_y = y + height - bar_height - 30

height - bar_height - 30って何ですか。この「-30」は何の調整ですか。

(たぶん余白だけど、自分でもよくわかってない)

30という謎の数字

最初:

bar_y = y + height - bar_height

実行。グラフ、表示された。でも、下にはみ出てる。

(枠、突き抜けてる)

調整:

bar_y = y + height - bar_height - 20

実行。まだはみ出てる。

(足りない)

再調整:

bar_y = y + height - bar_height - 30

実行。完璧。枠に収まった。

(なんで30...?)

理由、わかりません。でも、動きます。

(それでいい)

微調整を繰り返して、グラフが枠からはみ出したり、逆に小さすぎて見えなくなったり。

「もうグラフなしでいいじゃん…数字だけでいいじゃん…」

(諦めたい...)

PCの画面をそっと閉じかけました。

(また...)

Day33:PC閉じかけ。

Day34:Command+Q。

Day36:PC閉じかけ。

Day37:電源ボタン。

Day38:YouTube。

Day39:また、PC閉じかけ。

(毎日、限界に挑戦してる...)

自分ルール発動:「それっぽく見えれば正解」

完璧な比率や美しいレイアウトを目指すと終わりません。そこで、魔法の言葉を唱えました。

「パッと見で、棒が伸び縮みしてればヨシ!!」

(ハードル、またまた下げた)

厳密なピクセル数なんて誰も測りません。動けばいいんです。

Day33:「四角が出れば勝ち」

Day34:「重なってなければヨシ」

Day35:「別ウィンドウでもいい」

Day36:「1+1ができれば電卓」

Day37:「色が変われば視覚効果」

Day38:「1ピクセルのズレは味」

Day39:「それっぽく見えれば正解」

(7日連続のハードル下げ...)

そう割り切って実行してみると…

画面の中でサイコロがコロコロと回り(アニメーションも頑張った!)、棒グラフがニョキニョキ伸びていく様子は、予想以上に「実験してる感」があって楽しかったです。

(できた...!)

アニメーションという名の回転

サイコロ、回転させました。

角度を変えて、ぐるぐる回して、最後に結果を表示。

# 回転アニメーション(これ、楽しかった)
for angle in range(0, 360, 30):
    # サイコロを回転させて描画...

これ、作ってる時、楽しかったです。

座標計算、疲れました。でも、アニメーション、楽しかったです。

(メリハリ、大事)

Day39を終えて:結論

苦労して描いたサイコロの「目」は、画像ファイルよりも愛着が湧きますね。

(親バカ)

21個の座標。手打ち。(-1, -1)、(1, 1)、(0, 0)、...

疲れました。でも、できました。

1の目から6の目まで、全部、コードで描きました。

(達成感、ある)

棒グラフの高さ。比率計算。-30という謎の数字。

理由、わかりません。でも、動きます。

(それで、正解)

アニメーション。回転。実験してる感。

楽しかったです。

(報われた)

ただ、もう二度と手動でドットの座標を打ち込みたくはありません。

(二度と、やりたくない)

明日への希望

明日はDay40。40日目。節目です。

もっと座標計算の少ない、平和なアプリを作りたいです…。

(座標、もういい...)

Day33から7日間。ボタン、座標、日本語、画力、テンキー、サイコロ。

毎日、何かと戦ってます。

(でも、毎日、完成させてる)

40日目、何作ろうかな。

(楽しみ)

それでは、また明日!


今日の開発データ

  • 開発時間:約5時間(うちサイコロの目の座標に1時間、グラフ調整に1時間)

  • 実装した機能:サイコロシミュレーター、回転アニメーション、統計グラフ

  • 手打ちした座標の数:21個

  • 4の目が台形になった回数:1回

  • 謎の調整値:-30(理由不明だけど動く)

  • PCを閉じかけた回数:1回

  • 学んだこと:それっぽく見えれば正解、アニメーションは楽しい

100日チャレンジ、Day40に続く。

(節目、来た)


#100日チャレンジ #Python #プログラミング初心者 #ゲーム開発 #Pygame #サイコロ #シミュレーター #座標地獄 #統計グラフ #個人開発

いいなと思ったら応援しよう!

コメント

コメントするには、 ログイン または 会員登録 をお願いします。
100日アプリ開発チャレンジ Day39 - サイコロの「目」を1ピクセルずつ手打ちで描画していたら、ゲシュタルト崩壊した話|ki-kyo | 未経験×AIでアプリ開発を100日継続中
word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word

mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1