Javascript Canvasゲームの作成


こんにちは あなたと私は、Javascript Canvasの1台のコンピューターで複数の人向けの小さなカジュアルゲームを作成することをお勧めします。
この記事では、 MooToolsLibCanvasを使用してこのようなゲームを作成するプロセスをステップごとに分析し、小さなアクションごとに停止し、新しいコードを追加して既存のコードをリファクタリングする理由とロジックを説明しました。


ps残念ながら、Habrは、ペーストビンの記事からコードのいくつかのセクションを削除することを余儀なくされたため、60文字のどこかで大きな色の記事を切り取ります。 コードを探してリンクを介さずに記事を読みたい場合は、ミラーを使用できます

ルール


プレイヤー(プレイヤー)をコントロールします。プレイヤーはベイト(ベイト)を捕まえる必要があります-同時に表示される「捕食者」(バリア)をかわします。
ゲームの目標は、捕食者に触れることなく、最大数の餌を捕まえることです。
捕食者の1人と接触すると、それらすべて(捕食者)が消え、ポイントがゼロにリセットされます。これは実際には、ゲームをゼロから開始するのと同じです。

HTMLファイル


キャンバスアプリケーションの初期ファイルを作成します。 libcanvas Webサイトでホストされているファイルを使用しましたが、これは必要ありません。 JavaScriptファイルはゲームの作成中に追加されましたが、もうこのファイルに戻りたくないので、すぐに宣言します。

[[ pastebinのコード./index.html ]]



プロジェクトを作成する


最初に、プロジェクト自体を作成します。 これは、ドキュメントの準備ができたときにのみ行う必要がありますdomreadyによって提供される「 domready 」イベントを使用します
また、アニメーションを支援するLibCanvas.Canvas2Dオブジェクトを作成します。

./js/start.js
window . addEvent ( 'domready' , function () {
//
var elem = $$( 'canvas' )[ 0 ];
// LibCanvas
var libcanvas = new LibCanvas . Canvas2D ( elem );
// ,
libcanvas . autoUpdate = true ;
// 60 fps
libcanvas . fps = 60 ;

//
libcanvas . start ();
});


ユーザーを追加


マウスで制御される新しいオブジェクト-Playerを追加します-その座標はマウスカーソルの座標と等しくなります。
このオブジェクトは、特定の色とサイズの円のように見えます(プロパティで指定)

[[ pastebinのコード./js/Player.js ]]



libcanvas.start();前にlibcanvas.start();を追加しlibcanvas.start();
libcanvas . listenMouse ();

var
player = new Player (). setZIndex ( 30 );
libcanvas . addElement ( player );

=ステップ1 =



各フレームの後にキャンバスが自動的にクリアされないため、結果が予想とまったく異なることに気付くかもしれません。
./js/start.jsにクレンジングおよびブラックフィルプリプロセッサーを追加する必要があります

libcanvas . addProcessor ( 'pre' ,
new
LibCanvas . Processors . Clearer ( '#000' )
);

=ステップ2 =



餌を追加


[[ pastebinのコード./js/Bait.js ]]



./js/start.jsに追加します
// ,
var bait = new Bait (). setZIndex ( 20 );
libcanvas . addElement ( bait );


リファクタリング-親クラスを作成する


よく似たBaitクラスとPlayerクラスがあります。 GameObjectクラスを作成して、そこから継承します。

はじめに、PlayerクラスのコンストラクターからcreatePositionを作成します。
./js/Player.js
var Player = new Class({
// ...
initialize : function () {
// ..
this . shape = new LibCanvas . Shapes . Circle ({
center : this . createPosition ()
// ...
},

createPosition : function () {
return
this . libcanvas . mouse . point ;
},


GameObjectクラスを作成します

[[ pastebin上のコード./js/GameObject.js ]]



その後、他のクラスを軽量化できます。

./js/Bait.js
var Bait = new Class({
Extends :
GameObject ,

radius : 15 ,
color : '#f0f'
});


./js/Player.js
var Player = new Class({
Extends :
GameObject ,

radius : 15 ,
color : '#080' ,

createPosition : function () {
return
this . libcanvas . mouse . point ;
},

draw : function () {
if (
this . libcanvas . mouse . inCanvas ) {
this . parent ();
}
}
});


何も壊れていない場合、我々は見て:

=ステップ3 =



やった! すべてがどこでも機能し、コードがはるかに簡単になりました。

餌プレイヤーの友達


画面上のすべてのものは動いていますが、実際には私たちの行動に対する反応はありません。
餌とプレイヤーの友達を作ることから始めましょう-彼らがそれに遭遇したとき、餌は別のランダムな場所に移動するはずです。
これを行うには、レンダリングとは別のタイムアウトを作成します。これにより、接続がチェックされます。

最後に./js/start.jsを書きます
(function(){
bait . isCatched ( player );
}.
periodical ( 30 ));


次に、./js/Bait.jsにisCatchedメソッドを実装する必要があります。
isCatched : function ( player ) {
if (
player . shape . intersect ( this . shape )) {
this . move ();
return
true ;
}
return
false ;
},

move : function () {
//
this . shape . center = this . createPosition ();
}

=ステップ4 =



ほぼ優れていますが、この運動は失礼で迷惑なことがわかります。 餌がスムーズに逃げた方が良いでしょう。
これを行うには、LibCanvasの動作のいずれかを使用できます。 1行追加して移動方法をわずかに変更するだけで十分です。

次に、./js/Bait.jsにisCatchedメソッドを実装する必要があります。
var Bait = new Class({
Extends :
GameObject ,
Implements : [
LibCanvas . Behaviors . Moveable ],

// ...

move : function () {
// (800),
this . moveTo ( this . createPosition (), 800 );
}
});


とても簡単ですね そして、私は結果がはるかに好きです:

=ステップ5 =



捕食者を追加する



./js/Barrier.js
var Barrier = new Class({
Extends :
GameObject ,

full : null ,
speed : null ,
radius : 8 ,
color : '#0ff' ,

initialize : function () {
this . parent ();
this . speed = new LibCanvas . Point (
$random ( 2 , 5 ), $random ( 2 , 5 )
);
// ,
$random ( 0 , 1 ) && ( this . speed . x *= - 1 );
// ,
$random ( 0 , 1 ) && ( this . speed . y *= - 1 );
},
move : function () {
this . shape . center . move ( this . speed );
return
this ;
},
intersect : function ( player ) {
return (
player . shape . intersect ( this . shape ));
}
});


また、。 / js / start.jsを少し変更して、餌を狙うときに捕食者が現れるようにします。
bait . isCatched ( player );
//
if ( bait . isCatched ( player )) {
player . createBarrier ();
}
player . checkBarriers ();


プレーヤーのバリア、。 / js / Player.jsの追加を実装し、すべてのチェックごとにそれらを移動します。
barriers : [],

createBarrier : function () {
var
barrier = new Barrier (). setZIndex ( 10 );
this . barriers . push ( barrier );
// libcanvas,
this . libcanvas . addElement ( barrier );
return
barrier ;
},

checkBarriers : function () {
for (var
i = this . barriers . length ; i --;) {
if (
this . barriers [ i ]. move (). intersect ( this )) {
this .die();
return
true ;
}
}
return
false ;
},

die : function () { },;

=ステップ6 =



さて、ゲームには動きがありました。 しかし、次の3つの問題があります。
1.捕食者は競技場に飛び立ちます-「壁からの戦い」を行う必要があります。
2.餌が飛び立つまで、餌を2回つかむことがある場合があります。「無敵」の短いタイムアウトを設定する必要があります。
3.死亡例は処理されません。

捕食者は壁を撃退し、餌は「無敵」の短い時間を得る


壁ストライキの実現は簡単です。 ファイル./js/Barrier.jsの Barrierクラスのmoveメソッドをわずかに変更します。

[[ pastebinのBarrier.moveコード ]]



ベイトの問題の修正もそれほど難しくありません-./js/Bait.jsファイルでベイトクラスに変更を加えます

[[ pastebinのBait.makeInvulnerableコード ]]



=ステップ7 =



死と得点を実現します


なぜなら ポイント-これはベイトがキャッチされる回数であり、画面上の捕食者の数に等しい-ポイントを数えるのは非常に簡単です:
Playerクラスのdrawメソッド、ファイル./js/Player.jsを少し拡張しましょう
draw : function () {
// ...
this . libcanvas . ctx . text ({
text : 'Score : ' + this . barriers . length ,
to : [ 20 , 10 , 200 , 40 ],
color : this . color
});
},

// .. - - -
die : function () {
for (var
i = this . barriers . length ; i --;) {
this . libcanvas . rmElement ( this . barriers [ i ]);
}
this . barriers = [];
}


シングルプレイヤーゲームが終了しました!

=ステップ8-シングルプレイヤー=



1台のコンピューターでマルチプレイヤーゲームを実現します


キーボードの動き


まず、マウスからキーボードに制御を移します。 libcanvas.listenMouse()libcanvas.listenKeyboard()変更しlibcanvas.listenMouse()
その中で、 player.checkMovement();をタイムアウトに追加しplayer.checkMovement();
./js/Player.jsでは 、オーバーライドcreatePosition 削除します。drawメソッドでは、マウスチェックを削除し、矢印を使用して移動を実装します。

speed : 8 ,
checkMovement : function () {
var
pos = this . shape . center ;
if (
this . libcanvas . getKey ( 'left' )) pos . x -= this . speed ;
if (
this . libcanvas . getKey ( 'right' )) pos . x += this . speed ;
if (
this . libcanvas . getKey ( 'up' )) pos . y -= this . speed ;
if (
this . libcanvas . getKey ( 'down' )) pos . y += this . speed ;
},

=ステップ9 =



不快なニュアンス-プレイヤーが画面の後ろをい回ると、そこに迷うことがあります。
その動きを制限し、コードを少しリファクタリングして、キーの状態を別のメソッドに移しましょう
isMoveTo : function ( dir ) {
return
this . libcanvas . getKey ( dir );
},
checkMovement : function () {
var
pos = this . shape . center ;
var
full = this . getFull ();
if (
this . isMoveTo ( 'left' ) && pos . x > 0 ) pos . x -= this . speed ;
if (
this . isMoveTo ( 'right' ) && pos . x < full . width ) pos . x += this . speed ;
if (
this . isMoveTo ( 'up' ) && pos . y > 0 ) pos . y -= this . speed ;
if (
this . isMoveTo ( 'down' ) && pos . y < full . height ) pos . y += this . speed ;
},


また、isMoveToメソッドをわずかに変更します。これにより、キーを簡単に変更してプレーヤーを制御できます。

control : {
up : 'up' ,
down : 'down' ,
left : 'left' ,
right : 'right'
},
isMoveTo : function ( dir ) {
return
this . libcanvas . getKey ( this . control [ dir ]);
},

=ステップ10 =



2番目のプレイヤーを入力します


ファイル./js/start.jsを変更します。

var player = new Player (). setZIndex ( 30 );
libcanvas . addElement ( player );

// =>

var players = [];
(
2 ). times (function ( i ) {
var
player = new Player (). setZIndex ( 30 + i );
libcanvas . addElement ( player );
players . push ( player );
});

//
players [ 1 ]. color = '#ff0' ;
players [ 1 ]. control = {
up : 'w' ,
down : 's' ,
left : 'a' ,
right : 'd'
};


タイマーの内容はplayers . each (function ( player ) { /* * */ });ラップされていplayers . each (function ( player ) { /* * */ }); players . each (function ( player ) { /* * */ });

=ステップ11 =



少し修正する必要があります。
1. 2番目のプレーヤーのスコアを最初のプレーヤーのスコアよりも低くします。
2.異なるプレイヤーの捕食者を異なる色で着色します。
3.統計のために、「記録」を入力します-プレーヤーが到達した最大スコアは何ですか。

./js/Player.jsに適切な変更を加えます。
var Player = new Class({

// ...

// :
createBarrier : function () {
// ...
barrier . color = this . barrierColor || this . color ;
// ...
},

//
maxScore : 0 ,
die : function () {
this . maxScore = Math . max ( this . maxScore , this . barriers . length );
// ...
},

index : 0 ,
draw : function () {
this . parent ();
this . libcanvas . ctx . text ({
// :
text : 'Score : ' + this . barriers . length + ' (' + this . maxScore + ')' ,
// 20 :
to : [ 20 , 10 + 20 * this . index , 200 , 40 ],
color : this . color
});
}
});


./js/start.jsで修正を行います。

( 2 ). times (function ( i ) {
var
player = new Player (). setZIndex ( 30 + i );
player . index = i ;
// ...
});

players [ 0 ]. color = '#09f' ;
players [ 0 ]. barrierColor = '#069' ;

//
players [ 1 ]. color = '#ff0' ;
players [ 1 ]. barrierColor = '#960' ;
players [ 1 ]. control = {
up : 'w' ,
down : 's' ,
left : 'a' ,
right : 'd'
};


おめでとうございます、ゲームは完了です!

=ステップ12-2人でプレイ=



3番目と4番目のプレーヤーを追加する


必要に応じて、3番目と4番目のプレーヤーを追加するのは非常に簡単です。

players [ 2 ]. color = '#f30' ;
players [ 2 ]. barrierColor = '#900' ;
players [ 2 ]. control = {
up : 'i' ,
down : 'k' ,
left : 'j' ,
right : 'l'
};

// players[0] uses numpad
// players[3] uses home end delete & pagedown
players [ 3 ]. color = '#3f0' ;
players [ 3 ]. barrierColor = '#090' ;
players [ 3 ]. control = {
up : '$' ,
down : '#' ,
left : 'delete' ,
right : '"'
};

=ステップ13-4人でプレイ=

Source: https://habr.com/ru/post/J102010/


All Articles