tag:crieit.net,2005:https://crieit.net/users/inwan78/feed いんわんの投稿 - Crieit Crieitでユーザーいんわんによる最近の投稿 2022-04-03T12:42:20+09:00 https://crieit.net/users/inwan78/feed tag:crieit.net,2005:PublicArticle/18159 2022-04-03T12:30:16+09:00 2022-04-03T12:42:20+09:00 https://crieit.net/posts/CSS-624914c890151 CSSで文字をアニメーションさせる方法 <p>文字をアニメーションさせて目立たせるやり方です。</p> <p>見出しに使ったりワンポイントに使ったりいろいろできると思います。</p> <p>この記事では以下のpタグの文字をアニメーションさせていきます。</p> <pre><code><p id="text">あいうえお</p> </code></pre> <h2 id="文字の色を変える"><a href="#%E6%96%87%E5%AD%97%E3%81%AE%E8%89%B2%E3%82%92%E5%A4%89%E3%81%88%E3%82%8B">文字の色を変える</a></h2> <p><a href="https://crieit.now.sh/upload_images/3520c28939be4266608647d457cf6d6a6249130632cb5.gif" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/3520c28939be4266608647d457cf6d6a6249130632cb5.gif?mw=700" alt="image" /></a></p> <p>まずは簡単な色を変えるアニメーションです。</p> <pre><code class="css">#text { animation: color-loop 1s infinite; } @keyframes color-loop { 0% { color: red; } 50% { color: blue; } 100% { color: red; } } </code></pre> <p>「animation: color-loop 1s infinite」はcolor-loopを1秒間で繰り返し(infinite)行うという意味です。</p> <p>@keyframesは時間のどの割合の時に何を変更するかを指定します。赤から50%で青になり100%で赤に戻るという内容です。</p> <p>もちろんこの割合をもっと細かく設定したり色の数を増やしたりできます。</p> <h2 id="文字を拡大縮小させる"><a href="#%E6%96%87%E5%AD%97%E3%82%92%E6%8B%A1%E5%A4%A7%E7%B8%AE%E5%B0%8F%E3%81%95%E3%81%9B%E3%82%8B">文字を拡大縮小させる</a></h2> <p><a href="https://crieit.now.sh/upload_images/86b0d51084338445cae86902dcfa8d226249135893e1f.gif" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/86b0d51084338445cae86902dcfa8d226249135893e1f.gif?mw=700" alt="image" /></a></p> <pre><code class="css">#text { display: inline-block; animation: scale-loop 1s infinite;; } @keyframes scale-loop { 0% { transform: scale(1, 1); } 50% { transform: scale(2, 2); } 100% { transform: scale(1, 1); } } </code></pre> <p>scale()で拡大縮小をさせることができます。拡大縮小したい倍率を指定すればOKです。(X方向 、Y方向)になっています。</p> <p>一つ注意なのが「display: inline-block」を指定しておく必要があることです。これが無いと変化する幅が文字列の幅より大きくなってしまいX軸方向で大きくずれてしまいます。</p> <h2 id="文字を回転させる"><a href="#%E6%96%87%E5%AD%97%E3%82%92%E5%9B%9E%E8%BB%A2%E3%81%95%E3%81%9B%E3%82%8B">文字を回転させる</a></h2> <p><a href="https://crieit.now.sh/upload_images/9be7097c344163386497a613bc758b8262491383f0ec4.gif" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/9be7097c344163386497a613bc758b8262491383f0ec4.gif?mw=700" alt="image" /></a></p> <pre><code class="css">#text { display: inline-block; animation: rotate-loop 1s infinite linear; } @keyframes rotate-loop { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } </code></pre> <p>linearは変化を等間隔で変化するようにする指定です。</p> <p>scaleは度(degree)で指定します。マイナスの値にすると反対に回ります。</p> <h2 id="一文字ずつずらしてアニメーションさせる"><a href="#%E4%B8%80%E6%96%87%E5%AD%97%E3%81%9A%E3%81%A4%E3%81%9A%E3%82%89%E3%81%97%E3%81%A6%E3%82%A2%E3%83%8B%E3%83%A1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%95%E3%81%9B%E3%82%8B">一文字ずつずらしてアニメーションさせる</a></h2> <p><a href="https://crieit.now.sh/upload_images/cf0f3ca9180595c73cd744d4cbeac62b6249140575b6a.gif" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/cf0f3ca9180595c73cd744d4cbeac62b6249140575b6a.gif?mw=700" alt="image" /></a></p> <p>最後に文字列を一文字ずつずらしてアニメーションさせてみます。</p> <p>まずはCSSはこんな感じです。</p> <pre><code class="css">#text { /*今回は無しです*/ } #text span { display: inline-block; animation: scale-loop 1s infinite linear; } #text span:nth-child(2) { animation-delay: 0.1s; } #text span:nth-child(3) { animation-delay: 0.2s; } #text span:nth-child(4) { animation-delay: 0.3s; } #text span:nth-child(5) { animation-delay: 0.4s; } </code></pre> <p>span:nth-child(n)は文字の数だけ用意しておきます。今回は5文字なので5までしか作っていません(1は遅らせる必要が無いのでありません)。</p> <p>animation-delayはアニメーションを遅らせたい時間です。</p> <p>次にjavascript。</p> <pre><code class="javascript">window.addEventListener("load", function(){ textAnimation(); }); function textAnimation(){ var elm = document.getElementById("text"); var text = elm.innerHTML; for(let i = 0; i < text.length; i++){ html += "<span>" + text[i] + "</span>" } elm.innerHTML = html; } </code></pre> <p>id=textの文字を取得して文字を分割してspanタグで挟んでいます。</p> <p>これで一文字ずつ指定した時間分遅れてアニメーションします。</p> <h3 id="javascriptだけでやってみた"><a href="#javascript%E3%81%A0%E3%81%91%E3%81%A7%E3%82%84%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F">javascriptだけでやってみた</a></h3> <p>上のサンプルのjavascriptを改造してcssを減らして楽にできるようにしてみました。</p> <pre><code class="javascript">window.addEventListener("load", function(){ textAnimation("text", 0.1); }); function textAnimation(id, delayTime){ var elm = document.getElementById(id); if(!elm)return; var text = elm.innerHTML; elm.innerHTML = ""; for(let i = 0; i < text.length; i++){ const span = document.createElement('span'); const node = document.createTextNode(text[i]); span.appendChild(node); span.style.animationDelay = delayTime * i + 's'; elm.appendChild(span); } } </code></pre> <p>これならCSSの「span:nth-child(n)」の部分をわざわざ記述する必要が無くなってとても楽ちんです。</p> <p>引数でidと時間の間隔も指定できるようにしたので使い勝手もかなり良くなりました。</p> <h3 id="もうちょっと派手にしてみた"><a href="#%E3%82%82%E3%81%86%E3%81%A1%E3%82%87%E3%81%A3%E3%81%A8%E6%B4%BE%E6%89%8B%E3%81%AB%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F">もうちょっと派手にしてみた</a></h3> <p>最後に色も追加して派手に目立つようにしました。</p> <p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="xxpPYpG" data-user="inwan78" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;"> <span>See the Pen <a target="_blank" rel="nofollow noopener" href="https://codepen.io/inwan78/pen/xxpPYpG"> 文字アニメーション</a> by いんわん (<a target="_blank" rel="nofollow noopener" href="https://codepen.io/inwan78">@inwan78</a>) on <a target="_blank" rel="nofollow noopener" href="https://codepen.io">CodePen</a>.</span> </p> いんわん tag:crieit.net,2005:PublicArticle/17552 2021-08-01T21:54:06+09:00 2022-08-18T12:13:07+09:00 https://crieit.net/posts/022ab7e5fad6719e3b95c32ad8e6fb23 ブラウザゲームの操作入力を一括管理するインプットマネージャーを作る <p>ブラウザゲームを作るときにゲームを操作できるものがたくさんあります。キーボード、マウス、ゲームパッド、そしてスマホのタッチ入力。これらからの入力を一括して管理できればめちゃくちゃ楽で便利ですよね。</p> <p>というわけでこれらの操作入力を一括管理をしてくれる便利なinputManagerクラスを作りたいと思います。</p> <p>あ、一括管理と言いましたけどスマホやマウスのただのタッチ入力は関係ありません。これは個別で必要に応じて作ればいいです。まとめて管理するのはキーボード、ゲームパッド、そしてスマホのバーチャルキーパッドの入力です。</p> <p>けっこう長いプログラムになるので面倒ですが一回作れば今後のゲーム開発がクッソ楽になるので頑張ってつくりましょう(‘ω’)ノ</p> <p>ちなみに開発環境はpixi.js + Typescritptですが今回はpixi.jsは関係ないです。javascriptでもゲームパッド以外はできると思います(ゲームパッドはnpmで入れてるのでjsなら要自作。他はenchant.jsでも同じもの作ってました)。他の言語については全く分かりませんがどうやってるかってのは参考になるかなと思います(‘ω’)</p> <h2 id="ゲーム操作に必要な定数を作る"><a href="#%E3%82%B2%E3%83%BC%E3%83%A0%E6%93%8D%E4%BD%9C%E3%81%AB%E5%BF%85%E8%A6%81%E3%81%AA%E5%AE%9A%E6%95%B0%E3%82%92%E4%BD%9C%E3%82%8B">ゲーム操作に必要な定数を作る</a></h2> <p>ではまず先に入力の判断に使う定数を作ります。</p> <h3 id="方向入力の定数"><a href="#%E6%96%B9%E5%90%91%E5%85%A5%E5%8A%9B%E3%81%AE%E5%AE%9A%E6%95%B0">方向入力の定数</a></h3> <p>方向入力の定数を作ります。方向入力は8方向で作ります。</p> <p>で、まず8方向のうちの4方向、上下左右を4桁の2進数で考えるようにします。0000が何も押されていない状態です。で<br /> - 0001 上<br /> - 0010 右<br /> - 0100 下<br /> - 1000 左</p> <p>と考えてください。こうすると上と右が押されると3になります。左上が押されると9になります。こんな感じで8方向の定数を作ると</p> <pre><code>public keyDirections = { UP: 1, UP_RIGHT: 3, RIGHT: 2, DOWN_RIGHT: 6, DOWN: 4, DOWN_LEFT: 12, LEFT: 8, UP_LEFT: 9, } </code></pre> <p>となります。</p> <p>キーボードではいくつも同時にキーが押せるため変な数字になることがありますが入力判定処理時にこの定数以外の場合は無視すればOKです。</p> <h3 id="ボタンの状態管理用定数"><a href="#%E3%83%9C%E3%82%BF%E3%83%B3%E3%81%AE%E7%8A%B6%E6%85%8B%E7%AE%A1%E7%90%86%E7%94%A8%E5%AE%9A%E6%95%B0">ボタンの状態管理用定数</a></h3> <p>キーボードやゲームパッドのボタンは単純に押した離しただけではなくて、正確にゲームでコントロールしようと思うと「今押した」「押しっぱなし」「今離した」「押してない」という4つの状態が必要になります。</p> <p>なのでその定数を作っておきます。</p> <pre><code>public keyStatus = { HOLD: 2, DOWN: 1, UNDOWN: 0, RELEASE: -1, } </code></pre> <h3 id="ボタンの状態管理用変数"><a href="#%E3%83%9C%E3%82%BF%E3%83%B3%E3%81%AE%E7%8A%B6%E6%85%8B%E7%AE%A1%E7%90%86%E7%94%A8%E5%A4%89%E6%95%B0">ボタンの状態管理用変数</a></h3> <p>次はボタンの状態を入れておく変数を作ります。</p> <p>で、この状態を管理する変数ですが1つのボタンについて2つ作ります。これはボタンが「今押した」のか「押されっぱなし」なのかという状態を知るために前の状態を残しておくためです。一つ前の状態が押されているかどうか分かれば今押された(離した)のかどうかが分かります。</p> <pre><code>public input = { //入力されたキーのチェック用 keys: { Up: false, Right: false, Down: false, Left: false, A: false, B: false, Start: false }, //一つ前のキーの状態管理用 keysPrev: { Up: false, Right: false, Down: false, Left: false, A: false, B: false, Start: false } } </code></pre> <p>私は方向入力以外はAボタン、Bボタン、スタートボタンしか作ってないですがもっと欲しい人は追加してください。</p> <h2 id="キーボード入力イベントを作る"><a href="#%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E5%85%A5%E5%8A%9B%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%82%92%E4%BD%9C%E3%82%8B">キーボード入力イベントを作る</a></h2> <p>キーボードの入力イベントを作ります。</p> <p>なんかkeyCodeが非推奨みたいですがそんなの気にしない(^^;)気になる方は修正してください。押されたキーをtrueに、離したらfalseにしてます。</p> <pre><code>document.addEventListener('keydown', (e) => { switch(e.keyCode){ case 87://w this.input.keys.Up = true; break; //以下同様に他のボタンも作る } }); document.addEventListener('keyup', (e) => { switch(e.keyCode){ case 87://w this.input.keys.Up = false; break; //以下同様に他のボタンも作る } }); </code></pre> <h2 id="キーの入力をチェックする関数"><a href="#%E3%82%AD%E3%83%BC%E3%81%AE%E5%85%A5%E5%8A%9B%E3%82%92%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%81%99%E3%82%8B%E9%96%A2%E6%95%B0">キーの入力をチェックする関数</a></h2> <h3 id="入力方向を調べる関数"><a href="#%E5%85%A5%E5%8A%9B%E6%96%B9%E5%90%91%E3%82%92%E8%AA%BF%E3%81%B9%E3%82%8B%E9%96%A2%E6%95%B0">入力方向を調べる関数</a></h3> <p>押されている方向キーの数字を合算して返します。単純に足してるだけです。</p> <pre><code> public checkDirection() { let direction = 0; if(this.input.keys.Up){ direction += this.keyDirections.UP; } if(this.input.keys.Right){ direction += this.keyDirections.RIGHT; } if(this.input.keys.Down){ direction += this.keyDirections.DOWN; } if(this.input.keys.Left){ direction += this.keyDirections.LEFT; } return direction; } </code></pre> <h3 id="入力状態の取得"><a href="#%E5%85%A5%E5%8A%9B%E7%8A%B6%E6%85%8B%E3%81%AE%E5%8F%96%E5%BE%97">入力状態の取得</a></h3> <p>現在のキーの状態を取得します。引数は状態管理用変数に使っているボタンの名前(UpとかAとかStart)を入れて使います。これで返ってくる値が現在のボタンの状態です。</p> <p>またこれを使うのは毎フレーム1回だけです。ここでkeyPrev(前回の状態)を書き換えているので2回以上使うとおかしくなります。必要な場合は戻り値を保存して使ってください。</p> <pre><code>public checkButton(key: string) { if(this.input.keys[key]){ if(this.input.keysPrev[key] == false){ this.input.keysPrev[key] = true; return this.keyStatus.DOWN;//押されたとき } return this.keyStatus.HOLD;//押しっぱなし }else{ if(this.input.keysPrev[key] == true){ this.input.keysPrev[key] = false; return this.keyStatus.RELEASE;//ボタンを離した時 } return this.keyStatus.UNDOWN;//押されていない } } </code></pre> <h3 id="上の2つの処理がミソ"><a href="#%E4%B8%8A%E3%81%AE2%E3%81%A4%E3%81%AE%E5%87%A6%E7%90%86%E3%81%8C%E3%83%9F%E3%82%BD">上の2つの処理がミソ</a></h3> <p>このinputManagerの一番のポイントはゲームの入力をチェックする際にキーボードだろうがゲームパッドだろうがバーチャルパッドだろうが上の2つの処理から入力をチェックできることです。これができるようにするためにボタンの状態管理用変数を作っているわけです。</p> <p>inputManagerの役目はゲームのプログラムを書くときに入力デバイスのことを考える必要がないようにすることです。</p> <h3 id="ゲームパッドの入力について"><a href="#%E3%82%B2%E3%83%BC%E3%83%A0%E3%83%91%E3%83%83%E3%83%89%E3%81%AE%E5%85%A5%E5%8A%9B%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6">ゲームパッドの入力について</a></h3> <p>ゲームパッドの入力については先にこちらの記事を読んでください(‘ω’)ノ<br /> <a target="_blank" rel="nofollow noopener" href="https://techlog.wgc-cosmo.com/use-gamepad/">ブラウザゲームでもコントローラーで操作できるようにする!</a></p> <p>で、ゲームパッドの入力判定してるところで</p> <pre><code>if(this.gamepad.button('dpad down')){ this.input.keys.Down = true; }else{ this.input.keys.Down = false; } </code></pre> <p>て感じで状態管理用フラグを変えてやればOKです。楽勝だね(*‘∀‘)</p> <h3 id="バーチャルゲームパッドの入力について"><a href="#%E3%83%90%E3%83%BC%E3%83%81%E3%83%A3%E3%83%AB%E3%82%B2%E3%83%BC%E3%83%A0%E3%83%91%E3%83%83%E3%83%89%E3%81%AE%E5%85%A5%E5%8A%9B%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6">バーチャルゲームパッドの入力について</a></h3> <p>バーチャルゲームパッドについてはこちらの記事を先に読んでください(‘ω’)ノ<br /> <a target="_blank" rel="nofollow noopener" href="https://inwans.com/how-to-make-vpad/">バーチャルパッドの作り方</a></p> <p>で、もうわかると思いますがこれも同様に入力判定してるところで状態管理用フラグを変えてやればOKです。</p> <pre><code>class Btn { constructor(key: string){ this.addEventListener("touchstart", () => { InputManager.input.keys[key] = true; }); this.addEventListener("touchend", () => { InputManager.input.keys[key] = false; }); } } </code></pre> <p>クラスの内容は省略してますがこんな感じです。</p> <h2 id="おしまい"><a href="#%E3%81%8A%E3%81%97%E3%81%BE%E3%81%84">おしまい</a></h2> <p>以上な感じで私はInputManagerというクラスを作って入力を管理しております。これで入力デバイスを意識することなくゲームを作っていくことができます。<br /> ちなみにこのInputManagerを使ってるゲームがこちらです(‘ω’)ノ<br /> <a target="_blank" rel="nofollow noopener" href="https://wgc-cosmo.com/game/toilet/">トイレへの道</a></p> いんわん