1週間あたりの2Dスクロールシューティングゲーム

そして、それがどのように甘く始まったか



スクロールゲームの視差は一般的ですが、視差の発達の程度はゲームごとに大きく異なります。 本当に美しく興味深い背景を取得することは非常に困難です。 効果が自然に得られるため、一般に効果が消えるため、多くの人が現在3Dと視差に切り替えています。

昔は、背景に対して、視差効果のあるドット(星)が打ち上げられ、少し後に、いくつかの異なるレイヤーで背景を作り始めました。 そして今、あなたはいくつかのレイヤーやスクロールする背景なしではできません。もう少し必要です。





Lightforce、コモドール64、1986



注意、カットの下には大きな写真があります。



現代のコンピューター(およびモバイルデバイス)の能力は日々増大しており、その効果はしばしば非常に単純です。 問題が何であるかを理解してみましょう:機器の低電力、複雑な背景の作成の複雑さ、怠laz ...これはおそらく不十分な研究ですか? 詳細への注意の欠如?



これを自分でやろうとするのが一番簡単でした。 怠lazを克服して、私はやり始めました。 私は芸術家ではないので、私の敵は抽象的である(鏡球)、背景はホーサーのノイズによって生成され、塗装された唯一のボートは私の古い友人リカルドのペンに属していることをすぐに謝罪するようお願いしますそのような状況。



ビデオで結果を評価できます:





記事中のスクリーンショットはビデオとは少し異なります。実際、スクリーンショットの背景のみが変更されており、もう少し魅力的です。



視差



視差効果の本質は、オブジェクトの速度(およびサイズ)がオブザーバーからの距離に依存することです。オブジェクトが遠いほど、オブザーバーに対するオブジェクトの動きが遅くなり、サイズが小さくなります。 もちろん、これは静止しているオブジェクト、または同じ速度で移動する場合にのみ当てはまります(一般に同等です)。 したがって、長期計画はまったく動かないという事実を当然と考えることができます。 または、わずかに移動します。 2番目のオプションを使用すると、より良い動きの感覚が得られますが、1番目のオプションを使用すると、星などの非常に遠くのオブジェクトを表示できます。



理論から実践へ



このトピックで私が言ったことはすべて単純な理論ではないように、少なくとも60fpsのIntelの統合ビデオ(HD2000)で実行されるアプリケーションのスクリーンショットですべての計算を提供します。 記事を書く前にゲームを書いたので(プロトタイプはより正確になります)、ポイント、FPS、およびヘルススケールがフレームに収まります。 すみません、すぐに気づかなかったので、スクリーンショットに残すことにしました。 彼らは問題の本質を変えません。



遠い計画



アクションは宇宙で行われるので、星と星雲は遠い計画になります。 もちろん、ゲームをNASAの写真と比較したくないので、星雲は明るいです。 カラフルな擬似宇宙背景を作成するために、FilterForge 3.0ユーティリティを使用しました。 30日間の試用期間があり、誰でもそれを感じることができます。



また、背景には、シーン全体で最も明るいオブジェクトになるだけでなく、背景の速度で移動するのに十分な距離にある星を配置しました。





平均プラン



中央の計画は、まだ主なものではないため、より装飾的な外観を持っていますが、すでに注目を集めています。 したがって、彼は死んではいけません。 彼は生きていなければならず、最も原始的であっても、そこで行動しなければなりません。 計画を活性化するために、私は小惑星と巨大な宇宙農場を利用します。 小惑星はすべて同じですが、背景については今ではこれは最も重要ではありません。 ぼかしさえも有益なので、あまり注意をそらしません。

農場は私がPhotoshopで数分で描いたもので、小惑星は正直にインターネットから取られました。



空にならないように、ほこりを追加します。 理想的には、オブジェクトは当然、かなり大きくする必要があります。 他の船、惑星、駅、流星...言い換えれば、頭に浮かぶすべてのもの。





主な計画



主な計画はゲームであるため、ゲームオブジェクトのみがここにあります。 私が死ぬことなくスクリーンショットを撮らないようにするために、敵をオフにしました。残念ながら、爆発と敵の影響はありません。





前景



はい、これは間違いではありません。前景はメインプランにより近くなります。 彼があまり干渉せず、プレイヤーを怖がらせないように、彼はどのように焦点が合っていなくてもぼやけます。 その上にあるのはすべてゴミです。 それにもかかわらず、ゲームでは、メインのゲーム計画の一部を隠すため、フォアグラウンドは追加の複雑化の役割も果たします。





ゴミ箱



確かに、ゴミ! 私は完全に忘れました。 ゴミを追加する必要があり、主にメインのゲームプランに追加します(視覚的な危険を与えないように非常に小さい)。 メインプランにオブジェクトがないため、プレーヤーは完全に混乱します。 プレイヤーは奥行き感を失い、アクションがどのプランで行われるかを忘れます。 ゴミは上記の計画のいずれかに含まれることもあります。

コンテストのためにこのゲームをやったので、締め切りは非常に厳しかったです。 すべて、すべてが1週間であり、多くの機能を放棄する必要がありました。 ゴミがナイフの下にたどり着きました。



だから



私は何を間違えましたか? 実際、すべてが真実ですが、それはひどいようです! それでも美しさをもたらし、ジャムをきれいにする必要があります。 最初に、明るさに従ってオブジェクトを分配し、一般に、オブジェクトがシーンから落ちないようにミュートします。



コントラストは大きいままでしたが、このような明らかな色の違いは目立ちません。 最も注意深い読者は、太陽が正しく描かれていないことに気づきました。 シーンの背後にあり、ゲームオブジェクトとフォアグラウンドによってのみオーバーラップする必要があります。 修正中です。



ここで、不足しているタッチを1つだけ追加します...



はるかに良い。 しかし、これは1つのポストプロセスシェーダーにすぎません。 サラウンドライトシェーダー。 どのように機能しますか?



どのように機能しますか?



そのようなフレームを形成するための元の画像は、奇妙なことに、前の画像です。 ただし、もう1つあります。 形成されたフレームを脇に置き、特別な効果を得るために、光とそれに重なるオブジェクトに関する情報を含む追加のテクスチャを準備します。 次のようになります。



このテクスチャでは、光源と、光を遮断できるすべてのものをレンダリングします。 そして、それをより暗くすればするほど、それはより多くの光を遮ります。 このフレームの光源は画面の中心です(レンダリング中に光源の座標がシェーダーに追加送信されます)。

シーン1v1は、オブジェクトの位置とサイズによって表示されるものを繰り返すことに注意してください。



上は光線のテクスチャ、下は通常のレンダリングです

このテクスチャをボリュームライトの光線に変換するには、シェーダーで処理する必要があります。シェーダーのコードは記事の最後に添付します。 結果は、Photoshopの放射状のぼかし効果に非常に似ており、本質的には光源の座標に合わせて調整されます。



光線を手に入れました。 あとは、このテクスチャをシーン全体の上に追加して追加し、ミックスするだけです。 最終結果はわずかに高く、違いを見るために、画面の半分にのみエフェクトを適用します。



サラウンドライトの光線がある左、右はない



履歴書の代わりに



塗られた計画。 それらは4つしかありませんが、1つの平面内のオブジェクトは異なる速度で移動できるため、連続空間の効果が作成されます。 これに必要なのは、速度とサイズを変えることだけです。 より大きな美しさとボリュームを与えるために-ボリュームライトの効果。

モーションブラーや光の収差など、追加の効果の使用を除外しません。 目標は、プロセッサに組み込まれたラップトップのビデオプロセッサで60fpsで実行されるゲームを作成することだったので、そのような複雑さを放棄する必要がありました。 視差を作成する際には、ゲーム自体のその後の実装によりパフォーマンスが低下するため、毎秒60フレームではなく、120フレームすべてが必要であったことをすぐに認めなければなりません。 また、解像度-1280 * 720を考慮する必要があります。これは、フルスクリーンのポストプロセスエフェクトの処理速度に制限を課します。



ツールキット



私がよく知っている開発ツール、つまり、Direct3D9用の独自のフレームワーク、HLSL、およびバイナリエフェクトコードを作成するためのMicrosoftコンパイラを使用しました。 メインコードはEmbarcadero Delphi XE3で記述されています。 FilterForge 3.0で背景テクスチャをレンダリングしました。



シェーダー



sampler2D DiffuseMap : register(s0); float2 LightPos : register(c0); float4 Params : register(c1); float4 std_PS(vertexOutput Input) : COLOR { float4 Output; int NumSamples = 20; float Weight = 1.0; float Density = 0.5; float Exposure = 0.25; float2 DeltaTexCoord = (Input.TexCoord - LightPos); DeltaTexCoord *= 1.0 / NumSamples * Density; float3 Diff = tex2D(DiffuseMap, Input.TexCoord); float illuminationDecay = 1.0; for (int i = 0; i < NumSamples; i++) { Input.TexCoord -= DeltaTexCoord; float3 sample = tex2D(DiffuseMap, Input.TexCoord); sample *= illuminationDecay * Weight; Diff += sample; illuminationDecay *= 0.9;//Decay; } Output = float4(Diff * Exposure, 1); return Output; }
      
      







UPD:

ソースコードとバイナリは、bitbucket.orgのリポジトリから取得できます。



All Articles