2
1

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 2024

Day 20

なでしこさんのDOM部品でトランプを作るよ♥️♣️♦️♠️

Last updated at Posted at 2024-12-20

 先日の、部品を絶対位置配置することを使ってトランプを作ります。

 そして、CSSアニメーションを使ってカードをめくったり配ったりします。
 やっぱ、なんかゲームっぽいもの作りたい!
 あるいは、「DOMスキン設定」の活用。
 あるいはまた、雑に過去作品の紹介🐷

最初にDOMスキン設定

 なでしこさんには「DOMスキン設定」という命令があります。

👉なでしこ3 マニュアル > plugin_browser/DOMスキン設定

 何かというと、クラスでCSSを付ける機能です。
 なでしこさんの「DOMスタイル設定」や「DOMスタイル一括設定」はDOM部品のスタイルプロパティに直接設定するものですが、こちらは部品のclassNameを設定してスタイルシートを反映させる的な?

 ちょっと使いにくくてあんまり使ったことは無かったんですよ。
 なにしろスタイルシート自体は普通に「HTML設定」することになっているんですもの、当然和スタイルは使えません。
 普通に部品を作った後にクラスを「DOM属性設定」するのとたいして変わらないんじゃないの? とか。

 スキンを定義する「DOMスキン辞書」の内容は関数オブジェクトで指定することになっているので、単にクラスを設定するだけではなく、なんかかんか便利な使い方が出来そうな気がするのですが、まだひらめいてはいません💧
 TYPEで特定の要素に設定したりしなかったり出来る的な?
 これはアレだ。スタイルシートは自分で設定するというよりかは、世の中に色々とある良さそげな資産を活用出来るようにすることを想定した機能なのかなという感じ?

 でも、ワタクシひらめきました!
 「DOMスキン設定」は、「className」を「DOM属性設定」する場合とは逆で、先に設定します。そして、一度「DOMスキン設定」すると、以降作られる部品全てにそのクラスが設定されます
 先日やりましたDOM部品を絶対位置指定で配置したいという場合、

 全ての部品の「position」に「absolute」をDOMスタイル設定しなきゃならないの、まあまあめんどくさい。
 日本語で短く書けるよう関数にしてみたところで、やっぱりめんどくさい。

 これ、DOMスキンにすれば良いんじゃないの?!

# スタイルを設定
「style」DOM部品作成
それ『.絶対位置 {position: absolute;}
.相対位置 {position: relative;}』
HTML設定

# スキンを定義
DOMスキン辞書@「相対位置」=関数(TYPE,OBJ)
  OBJ「className」「相対位置」DOM属性設定
ここまで
DOMスキン辞書@「絶対位置」=関数(TYPE,OBJ)
  OBJ「className」「絶対位置」DOM属性設定
ここまで

# 「相対位置」のスキンを設定
「相対位置」DOMスキン設定

# 部品を作る場所を作成
母艦「div」DOM部品作成
母艦.420px
母艦.高さ100px
母艦DOM親部品設定

# 「絶対位置」のスキンを設定
「絶対位置」DOMスキン設定

# 以降作られる部品は全て「左」と「上」で配置出来るようになります。
「いろは」ラベル作成
それ.20px
それ.20px

「OK」ボタン作成
それ.360px
それ.42px

「テスト」エディタ作成
それ.20px
それ.40px
 出来ました!  最初のスタイル設定してスキンを定義する部分を関数にしてしゅっと呼べるようにしておけば、簡単に自由配置ができるようになりそう🎶

トランプを作る

 そんなこんなでトランプです。
 トランプって切り札のことだからカードやゲームのことを指してトランプっていうのは間違ってるとかそんなマメ知識はいりません。トランプったらトランプです!
 DOMを利用したゲームは、キャンバスを使う場合より高速な処理には向きませんが、なにしろイベントがめっちゃ楽~✨
 カードをクリックして進めていくようなトランプゲームには向いていると思います。

カードを一枚作る

 カード一枚の大枠はこんな感じ。

#トランプのカードを一枚作る
カード「div」DOM部品作成
カードDOM親要素設定
表カード「div」DOM部品作成
裏カード「div」DOM部品作成

 カードdivの中に表面用と、裏面用のdivが入ってます。
 まだなんの設定もしていないので、何も見えませんが。
 なんでこんなフクザツなことになっているかというと、後にカードをひっくり返すのに必要だからです。

DOMスキン作成

 今回は折角学んだDOMスキンを使ってカードの設定を作ってみます。

# 設定
変数 [画面幅,画面高さ][300,300]
変数 [カード幅,カード高さ][63,89]

# DOMスキンを作成
## スタイルを設定
DOM和スタイル.角丸「border-radius」
変数 SDOM和スタイル

「style」DOM部品作成
それ『.絶対位置 {position: absolute;}
.相対位置 {position: relative;}
&「.カード {波カッコ}
    {S.幅}: {カード幅}px;
    {S.高さ}: {カード高さ}px;
    {S.ボーダー}: solid 6px {白色};
    {S.角丸}: 12px;
    box-sizing: border-box;
{波カッコ閉じ}」
HTML設定

## スキンを定義
DOMスキン辞書@「相対位置」=関数(TYPE,OBJ)
  OBJ「className」「相対位置」DOM属性設定
ここまで
DOMスキン辞書@「絶対位置」=関数(TYPE,OBJ)
  OBJ「className」「絶対位置」DOM属性設定
ここまで
DOMスキン辞書@「カード」=関数(TYPE,OBJ)
  OBJ「className」「絶対位置 カード」DOM属性設定
ここまで

 カードの縁として太めに白いボーダーを付け、角丸(border-radius)を設定しました。
 角丸にすると何でも可愛く見えて好き❤️
 「box-sizing」を「border-box」にすると、ボーダーを付けてもカードのサイズが変わりません。

 そうまでして日本語にしたいか?! って感じになってますが、分かりやすいように&ワタクシが書きやすいように!!
 DOM和スタイルも追加しています。
 DOM和スタイル、こうして自分で追加して使うことが出来るんですよ!
 でも、「box-sizing」とか「border-box」とかとか日本語が思いつかなくて挫折💧

# ゲーム画面の作成
「相対位置」DOMスキン設定
ゲーム画面「div」DOM部品作成
ゲーム画面.画面幅&「px」
ゲーム画面.高さ画面高さ&「px」
ゲーム画面.背景色「green」
ゲーム画面DOM親部品設定

# カードを作成
「絶対位置」DOMスキン設定
カード「div」DOM部品作成
# カードをゲーム画面の中央に置く
カード.(画面幅-カード幅)/2&「px」
カード.(画面高さ-カード高さ)/2&「px」

カードDOM親要素設定
「カード」DOMスキン設定

# カードの表面を作成
表カード「div」DOM部品作成
表カード.背景色赤色

# カードの裏面を作成
裏カード「div」DOM部品作成
裏カード.背景色青色

 DOMスキンにより絶対位置が設定されていることにより、表カードと裏カードが重なりました。
 重なり(z-index)を指定していなければ、後から作成された部品が上になるので、裏カードの青色だけが見えている状態です。

トランプ裏.jpg

カードをくるんとめくる

 まず、表カードの「transform」に「rotateY(-180deg)」をDOMスタイル設定します。
 これは、要素を、Y軸(縦軸)を中心に180度裏向きに回転させる設定。

# カードの表面を作成
表カード「div」DOM部品作成
表カード.背景色赤色
表カード「transform」「rotateY(180deg)」DOMスタイル設定。  # 要素を、Y軸を中心に裏返しておく設定

 そして、表裏ともに「backface-visibility」に「hidden」を設定します。
 これは、要素の背面は非表示にするという設定です。

 さらに表裏ともに「transition」に「transform 0.6s」を設定します。
 トランスフォームを0.6秒かけて変化させるという設定で、カードが0.6秒かけて裏返るということです。

 こちらはカードのDOMスキンに含めてしまいます。
 呪文感が増してきましたが、こんな感じ?

「style」DOM部品作成
それ『.絶対位置 {position: absolute;}
.相対位置 {position: relative;}
&「.カード {波カッコ}
    {S.幅}: {カード幅}px;
    {S.高さ}: {カード高さ}px;
    {S.ボーダー}: solid 6px {白色};
    {S.角丸}: 12px;
    box-sizing: border-box;
    backface-visibility: hidden;
    transition: transform 0.6s;
{波カッコ閉じ}」
HTML設定

 まだ見た目は何も変わっていませんが、表カードは裏返しになっていて、ちょうどカードを机に伏せて置いたような状態になっています。

 そして、イベントで、クリックしたら表カードはもとに戻し、裏カードを裏返しにします。

# イベント
カードクリックした時には
    表カード「transform」「rotateY(0)」DOMスタイル設定
    裏カード「transform」「rotateY(-180deg)」DOMスタイル設定
ここまで

 クリックしたらカードがくるんと回転して赤い表面が見えるようになりました!

一組作る

 今回は対応する絵柄と番号をテキスト設定して、文字色をスタイル設定することで表面を作ります。
 カードの設定。

変数 [カード幅,カード高さ][63,89]
変数 カード絵柄["♣","♦","♥","♠"]
変数 カード番号["A","2","3","4","5","6","7","8","9","10","J","Q","K"]
変数 カード文字色[緑色,金色,赤色,青色]
変数 [カード裏色,カード表色,カード縁色]["#FFCCCC",白色,白色]

 そして、

変数 親カード空配列
変数 カード表空配列
変数 カード裏空配列

 のようにカード用の配列を用意して、0から51まで繰り返しで作っていけば良いだけ!
 13で割れば絵柄と文字色が、割った余りでカード番号が分かるって寸法です。

 ・・・なんですけれどね。
 要素を配列に収めると、オブジェクトプロパティ構文が使えないんですよよよ。

ID0から51まで繰り返す
    
親カード[ID]「div」DOM部品作成
    親カード[ID].100px

 とかは、できません。
 しょうが無いので、一回別の変数にコピーします。

ID0から51まで繰り返す
    
親カード[ID]「div」DOM部品作成
    変数 カード親カード[ID]
    カード.100px

 なでしこさんの配列は普通に代入すると参照コピーになって、コピーしたものに変更を加えると元のヤツも変更が反映されます。
 v1のつもりでコピーすると、あれれ~?!?! ってなるヤツですが、こんな時には便利です✨

ID0から51まで繰り返す
    
ゲーム画面DOM親部品設定
    # カードを作成
    「親カード」DOMスキン設定
    親カード[ID]「div」DOM部品作成
    変数 カード親カード[ID]
    # カードをゲーム画面の中央に置く
    カード.(画面幅/2-カード幅-4)&「px」
    カード.(画面高さ-カード高さ)/2&「px」

    親カード[ID]DOM親要素設定
    # カードの表面を作成
    「カード表」DOMスキン設定
    カード表[ID]「div」DOM部品作成
    変数 表カードカード表[ID]
    変数 絵柄(ID/13)整数変換
    変数 番号ID%13
    表カード「{カード絵柄[絵柄]}<BR>{カード番号[番号]}」テキスト設定
    表カード.カード文字色[絵柄]
    表カード「transform」「rotateY(-180deg)」DOMスタイル設定。  # 要素を、Y軸を中心に裏返しておく設定

    # カードの裏面を作成
    「カード裏」DOMスキン設定
    カード裏[ID]「div」DOM部品作成
    変数 裏カードカード裏[ID]
    裏カード「カードid」IDデータ属性設定

 できました。

てん切る

 って方言なんですってねー!!
 じゃじゃじゃあ標準語じゃなんて言うんです?
 シャッフルは分かりますけど、日本語は?!

●カードシャッフル
    変数 カード0から51までの配列連番作成
    カード配列シャッフル
    カード反復
        親カード[対象]「重なり」対象キーDOMスタイル設定
    ここまで
    カード戻す
ここまで

 「配列シャッフル」という、まさにそれ! な命令があります。
 ここでは、クリックでめくっていけるよう、それに合わせて重なり(z-index)を設定しています。

 これで、トランプ一組できました!

ぶたのしっぽ🐷

 というトランプゲームがあります。
 元ネタはマイナビ連載の、ゼロからはじめてみる日本語プログラミング「なでしこ」第77回 『トランプ「ぶたのしっぽ」を作ってみよう』でした。

 記事の最後に『また、多人数で遊べるようにしたり、グラフィックスを付け足してみたりと、自分でいろいろ改良してみると、より楽しめるでしょう。』とあったので、早速改造してみたやつです。
 ゲーム内容はほぼ変わらず、ぶたのしっぽらしくカードを丸く配置して動くようにしただけだけど、それだけでめちゃくちゃゲームっぽくなりますよね🎶
 肝心のゲーム部分のプログラムはほとんどそのままなので、是非元の記事を読んでみて下さい。

カードを移動する

 配ったり引いたり捨てたり、色々しますよね。

カード「transform」「translate({x}px,{y}px)」DOMスタイル設定

 こんだけ!

 移動先の座標を指定するだけで、今ある場所からアニメーションして移動して行きますよ!!
 移動時間はカードをめくるでtransitionに指定した0.6秒です。
 簡単なアニメーションが簡単に実現出来るのも良い所です。

完成(?!)

 最新版のなでしこで正しく動作するよう修正し、画面やカードの作成を今回の記事の内容に合わせて変更しました。

 是非遊んでみたり、さらなる改造をしてみたり、色々してみてください✨

おわります

 本当は、何か別のトランプゲームを新しく作ろうと思っていたのですが、時間が足りなかったのと、ムダに長期連載するまでもなくありがたいことにカレンダーが全て埋まったので、雑に過去作品でお茶を濁しちゃいました~😅🙏

2
1
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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?