2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

🐋「なでしこで、トランプゲームを作りたい時があります!(もちろん、ありますよね?)」

😺「はい先生! もちろんです!!」

 日本語プログラミング言語「なでしこ」 Advent Calendar 2025 4日目は、クジラ飛行机さまによる『なでしこで絵柄の綺麗なカードゲームを作るには?』でした。

 著作権フリー(CC0)の画像を用いて簡単にトランプカードの表示ができるライブラリが紹介されていますので、さっそくお試ししてみましょう。

とりあえずつかう

!「貯蔵庫:playing_card.nako3」取り込む
Mハート1[0,0]カード表示

 こんだけで、画面上にハートのエースが表示されました!
 直感的にわかりやすく、おそろしく初心者ライクですね✨️

 でもですよ。
 ゲームを作る際、プログラム中であらかじめどのカードを出すか指定して表示することは稀です。
 フツーは一組のトランプからランダムにカードを出していくものでしょう。

シャッフルしたトランプから一枚引く

 とゆうわけで、自分で「ハートの1を表示したい!」と思った場合には分かりやすくて簡単便利ですが、シャッフルされたカードをランダムに一枚引いて表示したい場合には?

トランプを作成

 トランプのカードを一組作るなら、だいたい通し番号の配列を使うのが普通です。

 こちらにトランプの作り方の分かりやすい解説がありますから、ぜひご覧くださいねぇ~。

 で、こんな感じ?

0から51までの配列連番作成してトランプ代入
トランプ配列シャッフル

 今は、配列連番作成という超便利な命令があります🎶
 シャッフルするのも、配列シャッフルというまさにそれ! な命令があります。

絵柄と番号

 この状態だとハートのAは26番です。
 コレを絵柄と番号にしてやらなきゃなりません。

 こんなかんじ?

C26絵柄番号取得
C.絵柄C.番号[0,0]カード表示

●(Noの)絵柄番号取得
    絵柄No/13切り捨て
    番号No%13+1
    {絵柄:絵柄,番号:番号}戻す
ここまで

 番号が配列と違い分かりやすいよう1スタートになっているので、+1してやる必要があります。
 どうしようかと思いましたが、辞書型で戻すことにしました。
 表示して確認しようかとおもったら、配列と違ってJSONエンコードが必要というめんどくささがありますが、使う分にはわかりやすくて間違いない。

 自前でカードを表示する命令を作るなら、この部分も入れ込んで、No.だけでしゅっと表示できるようにするところですが……
 でででもこれはタブンわざとですよね?
 一次元配列を二次元に変換するのは、重要な課題の一つですから?

一枚引いて表示

 配列ポップは、配列Aの末尾をいっこ取り出して返す命令です。
 Aの内容を書き換える、とあり、取り出した分は配列から消えますので、まさにシャッフルして伏せておいた山札から一枚引いて捨てるといったことができるワケです。

トランプから配列ポップして絵柄番号取得
それ.絵柄それ.番号[0,0]カード表示

辞書型で管理する?

 うーん、毎回絵柄番号取得するのはめんどくさい。
 いっそ、あらかじめ変換しちゃう?

トランプ空配列
0から51までの配列連番作成して反復:
    
トランプ[対象キー]空辞書
    トランプ[対象キー]["絵柄"]対象/13切り捨て
    トランプ[対象キー]["番号"]対象%13+1
トランプ配列シャッフル

トランプから配列ポップ
それ.絵柄それ.番号[0,0]カード表示

 これで、トランプ配列の中身は、

[{"絵柄":0,"番号":1},{"絵柄":0,"番号":2},...(中略)...{"絵柄":3,"番号":12},{"絵柄":3,"番号":13}]]

 ということになりました。
 うーん、先の解説記事の逆をいっていますね😅️
 でもま、このライブラリのカード表示を使うなら、こっちのが楽そう?

👇️動作確認

 毎回違ったカードが表示されるのが確認できます。

カード大きすぎ問題

 このライブラリに読み込まれている画像のカードサイズは、

カードW=150
カードH=210

 となっています。
 貯蔵庫の標準キャンバスに、2枚しか並びませんよ。
 このサイズで七並べなんて、デスクトップに表示しきれませんよよよ~💧️

 自前でカード表示命令を作るなら、画像部分描画で任意のサイズに縮小して描画することができるのですが、このライブラリのカード表示では、

カードIMG[XX,YY,カードW,カードH+1][XY[0],XY[1],カードW,カードH]画像部分描画

 と、等倍決め打ちで描画することになっているんですからどうしょうもない。
 オプションとかで表示倍率が変えられるようになっていたりすると助かるような気がしますけれどねぇ~。

 でもま、どうせカードを反転させるのに描画変換マトリクス設定したりする予定だから、そこで縮小もできますがね。
 でも、コレ系使うとなると途端に初心者ライクじゃなくなりますよね~?
 縮小して表示するだけなら、描画拡大だけでできそうですが🤔️

!「貯蔵庫:playing_card.nako3」取り込む
# キャンバスのサイズを設定
倍率0.6
画面幅1950*倍率
画面高さ840*倍率
描画中キャンバス.幅属性画面幅
描画中キャンバス.高さ属性画面高さ

F絵柄0から3まで繰り返す
    
F番号0から12まで繰り返す
        
XX=F番号×カードW
        YY=F絵柄×カードH

        キャンバス状態保存
        # ---
        [倍率,倍率]だけ描画拡大
        F絵柄(F番号+1)[XX,YY]カード表示
        # ---
        キャンバス状態復元

 あるいは、大きなキャンバスにフツーに描画して、スタイル設定でキャンバスごと縮小表示するとか?🤔️

!「貯蔵庫:playing_card.nako3」取り込む
# キャンバスのサイズを大きく設定して
画面幅1950
画面高さ840
描画中キャンバス.幅属性画面幅
描画中キャンバス.高さ属性画面高さ

# 表示を縮小
描画中キャンバス「幅」画面幅*0.6&「px」DOMスタイル設定
描画中キャンバス「高さ」画面高さ*0.6&「px」DOMスタイル設定

F絵柄0から3まで繰り返す
    
F番号0から12まで繰り返す
        
XX=F番号×カードW
        YY=F絵柄×カードH
        F絵柄(F番号+1)[XX,YY]カード表示

 キャンバスの属性の幅と高さは、キャンバスそのもののサイズを変更しますが、スタイルの幅と高さは表示サイズを変更します。

カードはくるんとめくりたい

 ようやく本題。
 昨年DOM部品を使ってトランプを作った際には、transformtransitionのスタイル設定するだけで簡単にめくるアニメーションができました。

 キャンバスの場合は?
 描画命令の中には描画変換マトリクス追加(transform)などの描画を変化させる命令がありますので、もちろんできるハズです。

設定

 とりあえず伏せて置いた一枚のカードをくるんとひっくり返して表向きにします。
 元画像を見ると、5355に当たる位置がカードの裏側、5254がジョーカーとなっているようです。

表カード26絵柄番号取得# {"絵柄":2,"番号":1}
裏カード55絵柄番号取得# {"絵柄":4,"番号":4}

 そして、画面中央にあらかじめ裏カードを表示しておきます。

画面幅描画中キャンバス.幅属性
画面高さ描画中キャンバス.高さ属性
カードX(画面幅-カードW)/2
カードY(画面高-カードH)/2

裏カード.絵柄裏カード.番号[カードX,カードY]カード表示

反転させる

 描画変換マトリクス追加の引数[a,b,c,d,e,f]の内容は、[伸縮x, 傾斜y, 傾斜x, 伸縮y, 移動x, 移動y]となっており、角度に応じて「伸縮x」(カード幅)を変化させ、半分までは裏側がだんだん細くなっていき、次に表側がだんだん太くなっていくことでカードがひっくり返るように見せかけます。
 これだけでも割とそれっぽく見えるんですが、少し傾斜を与えて奥行きを表現すると良いそうです。

 この伸縮の起点がカードの中央になるように、描画の起点をカード幅の半分だけ右にずらして伸縮を行い、実際の描画の前に元に戻します。

角度0
●(角度で)カード反転描画
    cosCOS((角度ラジアン変換))絶対値
    sinSIN((角度ラジアン変換))*0.15

    キャンバス状態保存

    [カードW/2,0]描画起点設定
    //[cos,0,0,1,カードX,カードY]だけ描画変換マトリクス追加。
    [cos,sin,0,1,カードX,カードY]だけ描画変換マトリクス追加
    [-1*カードW/2,0]描画起点設定
    もし角度90ならば
        [0,0]裏カード.絵柄裏カード.番号カード表示
    違えば
        [0,0]表カード.絵柄表カード.番号カード表示
    ここまで

    キャンバス状態復元
ここまで 

 あとは、キャンバスをクリックしたら、角度を0から180まで増やしながら繰り返しカード反転描画するよう画面更新時実行で再帰します。

●カード反転
    [0,0,画面幅,画面高さ]四角描画
    角度角度+6
    角度カード反転描画
    もし角度180ならば:
        
角度戻る
    「カード反転」画面更新時実行
ここまで

描画中キャンバスクリックした時にはカード反転。。。

 できました!

トランプ.gif

👇動作確認

 こちらでは、クリックごとに裏から表、表から裏へとトグルするようにしています。

続くかも知れないし続かないかも知れない

 今回は雑にグローバルに角度を用意して、一枚だけひっくり返しましたが、複数のカードを次々ひっくり返したりできるよう、カードそれぞれに角度や状態を持たせたらどうかなあ?
 絵柄や番号を辞書型にしたのも実はそのためでした。
 でも、そーなると移動のアニメーションもとか、角度の増加量決め打ちじゃなく、画面更新時実行のタイムスタンプを取って、CSSのと同じように何秒かけて変化するか指定できるようにしたい? とかとか、やっぱなんかゲームっぽいもの作りたいとかとかとか、いろいろ考えちゃうけど、そんな時間はにゃいのだ~😹️

 しかし、カレンダーが埋まらなくてぴんちだと、雑な感じで続くかも?

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?