js13kGamesリトルゲームコンテストへの参加方法





プログラミング競技では、事後の執筆が広く受け入れられ奨励されています。 葬儀はありません。実際、これは「コンテストに参加して学んだこと」というトピックに関するエッセイです。

小さなjs13kGames javascript ゲームのコンテストも例外ではありません。初心者のイグロデロの蓄積した感覚をHabrと共有したいと思います。



(プレイしたいが、啓示を読みたくない人のために、ここにゲームへのリンクがあります。)







競争自体について開始するには



死後のprintf Habraiser すでにそれを説明しいますが、完全を期すために、私はまだ繰り返します:

ゲームをjsで記述する必要があります。zipでパッケージ化すると、13キロバイト以下になります(より正確には、「キビバイト」になりますが、このユニットに誰もが慣れているわけではありません)。 もちろん、外部から接続されるリソースはありません。



ちなみに、 コードゴルフ愛好家向けのzipの13 kbは、膨大なスペースであることが判明しました。 私は先に進み、13 kbのうち8を少ししか使用できなかったので、非常に不快な沈殿物が生じた- ゲームは未完成で、もっと頑張らなければならなかった、場所が許す、ミーム! しかし、それは後のことであり、今では非常に最初のものです。



コンテストの1か月前



はい、作業はすでに始まっています。 むしろ、研究と調整。 I(ロシア)、Maxime Euziere(フランス)、Jim Herrero(アメリカ)は、以前は小さなゴルフプロジェクトで一緒に働いていました。 さて、私たちは一緒にゲームを切ることにしました。



これまでのところ、ゲームの形式も主題も知られていない。 ゲームが圧縮され、ZIPがより良くまたはより悪く圧縮されることが知られています。 さまざまなアーカイブ方法の有効性の遅い現在のテスト、どのプラットフォームでどのアンパッカーがサポートされているか、一般的なzipのコードの書き方が行われました。 簡単な進捗レポートはgist.github.com (英語)で入手できます。 つまり、Deflate圧縮のみが通常サポートされています。



そして、レポートに含まれなかったものについて少し説明します(ただし、表面上にあります)。 deflateを使用すると、完全に向きを変えてzopfliをアタッチできます! 私は一般的にzopfliをさまざまなものに適用するのが好きです。 結局のところ、zipを最適化するために自転車を書く必要さえありませんでした(essnoを作成しましたが)-スマートな既製のリパッカーAdvZipがあります。 ts-ssのみ!



そのため、事前に準備を整えて、競争の開始とトピックの発表を待ち始めました。



「要素:土、水、空気、火」



それがテーマの読み方です。 スカイプでブレーンストーミングが始まりました。 さまざまなオプションが提供されました-障害物を使用したランニング( タートルズキャントスケートは 、メカニズムについては議論されたもの著しく似ています )からレミングのようなゲーム( 再び。このアイデアは私たちだけではありませんでした )。 しかし、最終的に(3日目または4日目に)、宝石をちりばめたようなことをすることが決定されました。



そして、ここに継ぎ目があります。マキシムは仕事を辞め、別の都市に移ることに決めました。 彼はコードを書くことに積極的に参加することができず、彼はゴルフを手伝うと考えられていました-コードのサイズを減らします。 ところで、これは役に立たなかった。 しかし、彼の考え、提案、アルゴリズムの概要は私を大いに助けてくれ、彼は「クレジット」で言及するに値しました。 すべて同じですが、1つのヘッドが優れており、2つのヘッドが優れています。 「2」-ジムは、ブレインストーミングの直後に、私には未知の理由で未知の方向に投げ出したからです。



プログラマーを管理することは、猫を放牧するようなものです。 そして、それらが地球の異なる側にある場合-そして最後にピペット。



開発



そのため、アイデアは単純です。ボード上には、組み合わせることができるタイル(タイル)があります。 水と地球を組み合わせて、汚れを取ります。 汚れが並んだタイルを収集すると、それらは消え、ポイントが付与されます。 さらに、汚れは水や土と再び結合することはできません。さもないと、オプションの数が屋根を通り過ぎてしまい、プレイヤーは錬金術の要素のこの表を理解することはほとんどありません。



タイル



開始するには、タイル自体を生成しますMath.random()



からの形状、明るい砂のMath.random()



です。 目が無意識のうちに類似の要素を見つけ始めたときに「バッテリー効果」が存在しないように、タイルごとにこのテクスチャが再作成されます。 ちなみに、タイルとファビコンは、各ページの読み込み後にわずかに異なります。



生のキャンバスデータcreateImageData



/ putImageData



操作することで、すべてがはるかに簡単になりました。 確かに、タイルの角は丸くありません-これは、余白のあるアクセス可能な場所に収まることをまだ知らなかった初期のアウトラインでした。 しかし、後でそれがさらに面白かったように思えました。



アイコンのベジェ曲線は、キャンバスAPIの力と手段によって既に上から描かれています。



結果のイメージから作成されます( new Image()



)。 キャンバスの形のままにしておくこともできますが、デバッグは簡単で、キャンバスにピクセルをコピーする操作は高速です。



背景は、生のピクセルの手続き的な操作によっても生成されます。 背景は少し青みがかっており、タイルは黄色がかっています。これはピクセルアートで広く使用されている古いジョークです。黄色が近いようです。 この背景はcssの背景としてcanvas要素に設定されています。すべてを手動で再レンダリングする必要はありません。ブラウザに影響を与えます。 ちなみに、Chromeデバッガーは苦しんでいました。 ヒント: data:image/*



のbackground-imageに高額な画像を入れないでください。デバッガはうまくハングアップします。



カーソル座標の処理



まあ、すべてが簡単です。 手動でドラッグアンドドロップを書いたことがあれば、すべて同じです。 また、ブラウザ動物園が極端に乱れているため、座標は「画面からの座標から要素の左上隅の座標を引いたもの」として計算する必要があります。 これは2014年です。



マウスイベントと指イベントの処理は基本的に同じです。 唯一のことは、すべてがWindows Phoneで機能するように、ポインターイベントをdrれさせなければならなかったことです。 はい、はい、Windows Phone、ゲームはもともとモバイルデバイス用に設計されたもので、モバイルデバイスはiPadだけではありません。



レンダリングとアニメーション



気取らないおもちゃでは、通常、再描画はsetTimeout



/ setInterval



発生しsetInterval



。 このアプローチでは、フレームレートは低く、ほぼ一定であり、「物理」はフレームごとに処理されます。 はい、jsではタイマーはイベントループでロードするときにスリップする可能性がありますが、これは無視できます。



しかし、私はそれを「大きな男の子のように」し、 requestAnimationFrame



(ある場合)を使用することにしました。 これにより、レンダリングとアニメーションのプロセスが上下逆になります。フレームは、毎秒60回から1時間に数回まで、いつでもどこでも動作しました。 しかし紳士、これはクールです。 結果ははるかに快適です。



エンジン(それを呼び出すことができる場合)は次のように動作します:競技場の配列、「モデル」があります。 モデル内の何かが変更されると、即座に発生しますが、アニメーションを定義するオブジェクトは、 blockingAnimations



配列に配置されます。 すべてのアニメーションが完了するまで、requestAnimationFrameは継続的にスピンします。 終了すると、タイルが重力の影響下に落ちたり、爆発したり消えたりする可能性があるかどうかを確認するためのチェックが行われます。 そうでない場合、requestAnimationFrameをリクエストしません。プロセッサを不必要に焼き付ける必要はありません。



ここで小さなコメントをしたいと思います(他の誰かが私を読んでいる場合):ゲームはカジュアルとして計算され、ユーザーがプレイして別のタブで開いたままにした場合は本当です。 また、Windows 98の一部の古いOperaでは、隣接するタブに永続的なレンダラーが表示されると、ゲームを終了したいという欲求しか生じません。 ユーザーではなく、プレイヤーであっても、ユーザーの注意を払ってください!



アニメーションをブロックしている間は、ユーザーは何もできません。そのため、モデルの状態が突然変更されることはありません。 すべてがシンプルです。



ベータ版 というか、アルファ



その後、私は最初の公開テストのために成熟しました。 多くのレビューと提案を得ました。



最初の要求は、できるだけ早くポイントを入力することです。 完了しました。



2つ目は、すべてのアニメーションを非ブロックにすることです。 それから私は拒否しなければなりませんでした、私は魔術師ではなく、私はただ学んでいます。



しかし、私を襲った主なものはゲームをプレイすることでした! 本当に! リンクを2人に渡し、5人でプレイしました。 それは私が始めたものをやめないように促しました。



ポイントが追加され、レンダリング中に恐ろしいバグが修正されました。 ベータ版の時間です。 私は正直にそれを行った-彼女を前に見たことがない人に。 そして、彼らは皆、何をすべきか理解していないと言った。 私は「遊び方」をギャグしなければなりませんでした(それは不明瞭だったようです)。 これにより、レンダリング時にバグが追加されました。 つまり、開発はそのままです。



しかし、「遊び方」の後でさえ、質問がありました:英語での説明! ローカリゼーションという決定的なステップを踏まなければなりませんでした。 その結果、ゲームには英語、ロシア語、フランス語の3つの言語があります。



モバイル機器



「元々敷設されていた」ものは、​​それを引き出す時でした。 すべてがコードでゴージャスですが、ディスプレイではありません。



まず、メタビューポート。 このろくでなしは動作しません。 むしろ、それは機能しますが、期待どおりに機能しません。 助けを借りて、少なくとも750×770の領域を画面に表示できると言うことができますが、これを行うブラウザはありません。 width=device-width,height=device-height



、CSS変換(サポートされている場合)を通じてこれらすべてをエミュレートする必要がありました。



そして、ここで.clientWidth



満足しています- .clientWidth



document.documentElement.clientHeight



/ .clientWidth



は常に.clientWidth



に等しくなります。 iPhone / iPad専用の松葉杖を貼り付け、 window.innerHeight



で判断するwindow.innerHeight







繰り返しますが、別の問題が浮上しました-キャンバスの減少により、すべてがクールに見えますが、... ghm ...少なくともまあまあ増加します。 すべてが面倒で面倒です。 別の松葉杖、および増加は2の係数でのみ行われます(削減-すべての場合)。 そして未来への印:固定サイズのキャンバスが道です。





あと数日。 サイズではなく、すでに制限要因となったのは時間でした。 サウンドを追加するとどうなりますか?



私は完成したライブラリを取りたくありませんでした。 残念ながら、私はトラッカーを知らず、特に音楽を書くことができません。 はい、そしてなぜウェブページのバックグラウンドミュージックですか?



音は別の問題です。 基礎として、私はp01からWAVジェネレーターを取得しました 。 音がダンディや80年代のSFの特殊効果のように見えないように、彼はそれを16ビットと44100 Hzに変更しました。 そして彼は実験を始めました。



トーンをより自然にするために、 高調波を使用しました。 それは退屈であることが判明したので、倍音の振幅については、サイン、対数、指数などの地獄のような係数を導入し始め、その結果を確認しました。 面白いことが出てきました-耳が聞こえないクリックからベルまで。 そして時々 これ



その結果、多かれ少なかれ適切なものが判明し、私はそれをゲームに貼り付けました。 スタイルの面では、サウンドは砂岩のグラフィックスとあまり組み合わされていませんが、正直に認めます-適切な音のトンから選択するには、多くの忍耐が必要であり、最も重要なことは、プレーヤーをオフにします。 そして、私は単に音楽愛好家のような犠牲を払うことができませんでした。



まとめ



紳士の皆さん、インディーのイグロデルは面白いですね! その結果、1か月間は興味を持って過ごし、多くの経験(およびほとんどが "異なる方法で行う必要がありました"形式)、そし​​て最も重要なことは、作業中のゲームです。



ところで、それはjs13kGamesのQuintessenceです



All Articles