4
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?

More than 1 year has passed since last update.

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

4
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」
変数 S=DOM和スタイル。

「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で割れば絵柄と文字色が、割った余りでカード番号が分かるって寸法です。

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

IDを0から51まで繰り返す:
    
親カード[ID]は「div」のDOM部品作成。
    親カード[ID].左=100px。

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

IDを0から51まで繰り返す:
    
親カード[ID]は「div」のDOM部品作成。
    変数 カード=親カード[ID]
    カード.左=100px。

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

IDを0から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秒です。
 簡単なアニメーションが簡単に実現出来るのも良い所です。

完成(?!)

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

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

おわります

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

4
1
2

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
4
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?