ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript を使用して Pongo の Web バージョンのデザインアイデアとソースコードを実装する_JavaScript スキルの共有

JavaScript を使用して Pongo の Web バージョンのデザインアイデアとソースコードを実装する_JavaScript スキルの共有

WBOY
WBOYオリジナル
2016-05-16 16:44:221271ブラウズ

1. ゲーム背景の紹介 (前に書かれたナンセンス):

5月初旬のある日、このゲーム「Pongo」を勧めているウェブサイトを見つけたので、ダウンロードしてiPadに試してみました。2つのゲームをプレイした後、とても楽しいと感じました。携帯ゲーム機については誰もが知っています。

しかし、しばらくして、このゲームは iPad にいくつかのバグがあるようで、しばらくプレイしていると固まってしまい、強制終了しなければならなかったのですが、とても心配で、記録はまだ待っていました。壊れる。

どうすればいいですか?ゲームをプレイするのは、自分で作ったゲームをプレイするほど良いものではないという邪悪な考えが再び湧き上がり、傷心した私は黙ってコンピュータに戻り、フリーズしない独自のゲームを書き始めました。 。

基本的なフレームワークを書くのに約 2 時間かかりました。その後、Sina アプリで試してみました。エフェクトは基本的に再生可能でした。その後、寝ました。

翌日目が覚めると、週末は何もすることがなかったので、インターフェースの設計に時間を費やしましたが、残念ながらいくつかの重大なバグが見つかり、最終的にそれらを修正することに時間を費やしました。

最終的に、ゲームは「Pongo」という名前になりました (携帯電話でクリックしてプレイしてください) 現時点ではコンピューター版はサポートされていないため、ソースコードを Github にアップロードし、スコア送信モジュールを削除しました。

2. ゲーム体験版 Web サイト:

Pongo (モバイル版のみ): http://mypongo.sinaapp.com/

github オープン ソース (ゲームを改善するためのフォークを歓迎します): https://github.com/ChenReason/pongo/blob/gh-pages/index.html

3. ゲームのルールとゲームプレイ:

画面をクリックするとベゼルの移動方向が変わります 1回クリックすると、転がるボールをブロックして大きな円から飛び出すのを防ぐことが目的です。長ければ長いほど良いです!最後に、独自の結果をランキングに投稿することができます。

4. ゲームで使用されるテクノロジー:

HTML、CSS、JavaScript、キャンバス、PHP

5. ゲームデザインのアイデア:

a) Canvas を使用して、ゲームのメイン インターフェイスを描画します。下部は、大きな円で覆われた単色の長方形です。大きな円の上に、非常に小さい円も描画されます。バッフルの中央にサイズ 1 ピクセルの円を配置します (衝突検出を実装するため)。

b) 小さな円の移動方向は、上下、左、右、左上、左下、右上、右下の 8 方向です。

c) バッフルの動きは時計回りと反時計回りの 2 方向のみです。

d) 衝突検知はエンジンを使用せず、バッフル中央の小円と超小円との距離を判定することで簡易的な衝突検知を実現します。

e) 常識的に考えて、合計 8 つの状況をリストしてください。

6. ゲーム実装の難しさ:

a) 衝突検出。

b) タイマー setInterval をクリアするタイミングとそれが明確かつ徹底されているかどうか。

c) タイマー期間の長さとゲーム体験の関係。

d) Android デバイスと IOS デバイスのパフォーマンスの違いによって生じるゲームの流暢性の問題。

7. ゲームの現在の問題点:

a) 衝突検出は 2 つの円の中心間の距離を比較し、タイマーを使用するため、タイマーの間隔が非常に短いため、肉眼で見える 1 回の衝突の背後に実際には数十回の衝突が発生していることになります。最適化後、ボールの最終的な実際の反発方向が実際の物理定理と異なることが発生する可能性は低くなりますが、それでもボールが正確にバリアに当たらない場合は避けられない場合があります。 , ボードの中央にあるとゲームが失敗する可能性があります。

b) 機能が冗長すぎ、実行効率が低く、タイマーを使用するため、Andorid でのゲーム体験は iOS や他のモバイル端末とは異なります (全体的に iOS の方が Android より優れています) 。

c) ランキングはリアルタイムで自動的に更新されません。 (データベースの使い方がまだ分かりません)

8. ゲームインターフェースのプレビュー:

(写真 1 は最初のバージョン、写真 2 はボタンを削除したもの、写真 3 は最終バージョン、写真 4 はランキングです)

JavaScript を使用して Pongo の Web バージョンのデザインアイデアとソースコードを実装する_JavaScript スキルの共有

写真 1

JavaScript を使用して Pongo の Web バージョンのデザインアイデアとソースコードを実装する_JavaScript スキルの共有

写真 2

JavaScript を使用して Pongo の Web バージョンのデザインアイデアとソースコードを実装する_JavaScript スキルの共有

写真 3

JavaScript を使用して Pongo の Web バージョンのデザインアイデアとソースコードを実装する_JavaScript スキルの共有

9. ゲームの JavaScript ソース コードの一部:

コードをコピー コードは次のとおりです:

var ifingame=0;
var maxgrade=0,grade=0;
var Grade1,grade2;
var ニックネーム;
var gamespeed=1.4;//小球速度
var linespeed=Math.PI/95; //跟追跡回線速度
var crash distancefaild=-7;//碰撞检测パラメータ
var crash distancesucc=15
var fantanjuli=7;   
var themaxgradeline=12.1;    
function getCookie1(ニックネーム)
{
if (document.cookie.length>0)
{
c_start=document.cookie.indexOf(ニックネーム "=")
if ( c_start!=-1)
{
c_start=c_start Nickname.length 1;
c_end=document.cookie.indexOf(",",c_start);
if (c_end==-1)
c_end=document.cookie.length;
return unescape(document.cookie.substring(c_start,c_end));
}
}
return ""
}
function getCookie2(mymaxgrade)
{
if (document.cookie.length>0)
{
c_start=document.cookie.indexOf(mymaxgrade "=")
if (c_start!= -1)
{
c_start=c_start mymaxgrade.length 1;
c_end=document.cookie.indexOf(";",c_start);
if (c_end==-1)
c_end=document.cookie.length;
return unescape(document.cookie.substring(c_start,c_end));
}
}
return ""
}
function setCookie( Nickname,value,mymaxgrade,maxgrade,expiredays)
{
var exdate=new Date()
exdate.setDate(exdate.getDate()expiredays)
document.cookie=nickname "=エスケープ(値) "," mymaxgrade "="escape(maxgrade) ((expiredays==null) ? "" : ";expires=" exdate.toGMTString());
}
function checkCookie()
{
nickname=getCookie1('nickname');
maxgrade=parseInt(getCookie2 ('mymaxgrade'));
if(isNaN(maxgrade)==true)
{
maxgrade=0;
}
if (ニックネーム!=null && ニックネーム!="" )
{
alert('欢迎' ニックネーム '回来!' 'n' "如果喜欢请分享一下哈~");
}
else
{
nickname=prompt ('请输入你的昵称:(名字太长上支持可是会显示不完整的哦)',"")
if (nickname!=null && Nickname!="")
{
var maxgradestring=maxgrade.toString();
setCookie('nickname',nickname,'mymaxgrade',maxgradestring,365);
}
}
}

var objpane= document.getElementById("pane");
var ctxpane=objpane.getContext("2d");
ctxpane.translate(150,150);//必备画布中心点平移
function sendmail()
{
if(grade2>themaxgradeline)
var max_grade=grade2;
window.location.href='index.php?max_grade=' max_grade '&nick_name=' ニックネーム;
/* {

$grade=$_GET['max_grade'];
$nickname=$_GET['nick_name'];
$mail = new SaeMail();
$ ret = $mail->quickSend( 'reasonpongo@163.com' , $grade , $nickname ,'reasonpongo@163.com' , 'mypongo' );
$mail->clean();
?>
}*/
alert(ニックネーム "你的成绩:" Grade2 "提交成功~");
}


var gamedirection={
shang : 1、
xia : 5、
zuo : 7、
you : 3、
zuoshang: 8、
zuoxia : 6、
youshang: 2,
youxia : 4,
クロック : 0,
アンチクロック: 9,
};// 方向
var Canvas={
幅 : 300,
高さ: 300,
};//Canvas

var bigcircle = {//大きな円のパラメータ
x: 0, //円の中心の x 軸座標値
y: 0, //y-円の中心の軸座標値
r: 150, //円の半径
c: 'rgb(255,255,255)',
};//大きな円
var smallcircle = {//小さな円のパラメータ
x: 0, / / 円の中心の x 軸座標値
y: 0, // 円の中心の y 軸座標値
r: 12, //円の半径
c: 'rgb(204,105,106)',
方向 : gamedirection.xia,
};//小さな円

var line = {//バッフルラインのパラメータ
x: 0, //円の中心のx軸座標値
y : 0, //円の中心のy軸座標値Circle
r: 150, //円弧の半径
start:(Math.PI/2-Math.PI/16),
end: (Math .PI/2 Math.PI/16) ),
c : 'rgb(55,55,55)',
方向: gamedirection.anti Clock,
};//トレースライン
var dot = {//トラッキングポイントパラメータ
x: (bigcircle.r*Math.cos(line.start Math.PI/16)),//大きな円を原点とする
y: (bigcircle.r*Math. sin(line.start Math .PI/16)),
r : 1,
}//トラッキングポイント
function changelinedirection()
{
if(line.direction==gamedirection . Clock)
{
line.direction=gamedirection.antilock;
}
else
{
line.direction=gamedirection.clock;
}
}

関数get distance(){
var distance=Math.sqrt((smallcircle.x)*(smallcircle.x ) (smallcircle.y )*(smallcircle.y ));
距離を返す
}//小さなボールと大きな円の中心との二乗距離を返す get distance()

関数 ifgameover(){//範囲外か判定
if((get distance() - bigcircle. r)>5 )
return true;
else
return false;
} //ゲームが終了したかどうかを判定 ifgameover()
function ifcrash(){ //衝突検出
var dx = dot.x-smallcircle.x;
var dy = dot.y-smallcircle.y;
var dd=Math.sqrt(dx*dx dy*dy);
if( dd< crash distancesucc)
return true;
else
return false;
}//衝突検出 ifcrash()

function randomback()
{
var x =Math.floor(Math.random()*3);
switch (smallcircle.direction){
case gamedirection.shang:
{
switch (x)
{
ケース 0:
smallcircle .direction=gamedirection.xia;
smallcircle.y=smallcircle.y fantanjuli;
ブレーク;
ケース 1:
smallcircle.direction=gamedirection.zuoxia;
smallcircle.x=smallcircle;
smallcircle.y=smallcircle.y fantanjuli;
ブレイク;
ケース 2:
.direction=gamedirection.youxia;
smallcircle .x=smallcircle.x fantanjuli;
smallcircle.y=smallcircle.y fantanjuli;
ブレーク;
デフォルト:
ブレーク;
} ブレーク;
}
case gamedirection.xia:
{
switch (x)
{
case 0:
smallcircle.direction=gamedirection.shang;
smallcircle.y=smallcircle.y -fantanjuli;
break;
ケース 1:
smallcircle.direction=gamedirection.zuoshang;
smallcircle.x=smallcircle.x-fantanjuli;
smallcircle.y=smallcircle.y-fantanjuli ;
break;
ケース 2:
smallcircle.direction=gamedirection.youshang;
smallcircle.x=smallcircle.x fantanjuli;
smallcircle.y=smallcircle.y-fantanjuli;
ブレーク;
デフォルト:
ブレーク;     
} break;
}
case gamedirection.zuo:
{
switch (x)
{
smallcircle.direction=gamedirection .あなた;
smallcircle.x=smallcircle.x fantanjuli;
break;
ケース 1:
smallcircle.direction=gamedirection.youshang;
smallcircle.x=smallcircle.x fantanjuli;
小円.y=smallcircle.y-fantanjuli;
break;
ケース 2:
smallcircle.direction=gamedirection.youxia;
smallcircle.x=smallcircle.x fantanjuli;
smallcircle.y= smallcircle.y fantanjuli;
break;
default:
break;
} break;
}
case gamedirection.you:
{
switch (x)
{
case 0:
smallcircle.direction=gamedirection.zuo;
smallcircle.x=smallcircle.x-fantanjuli;
break;
case 1:
smallcircle.direction =gamedirection.zuoxia;
smallcircle.x=smallcircle.x-fantanjuli;
smallcircle.y=smallcircle.y fantanjuli;
break;
ケース 2:
smallcircle.direction=gamedirection。 zuoshang;
smallcircle.x=smallcircle.x-fantanjuli;
smallcircle.y=smallcircle.y-fantanjuli;
break;
デフォルト:
break;
} break;

}
case gamedirection.zuoshang:
{
switch (x)
{
case 0:
smallcircle.direction=gamedirection.youxia;
smallcircle .x=smallcircle.x fantanjuli;
smallcircle.y=smallcircle.y fantanjuli;
break;
ケース 1:
smallcircle.direction=gamedirection.xia;
smallcircle.y=smallcircle .y fantanjuli;
break;
ケース 2:
smallcircle.direction=gamedirection.you;
smallcircle.x=smallcircle.x fantanjuli;
break;
default:
休憩;
} 休憩;

}
case gamedirection.zuoxia:
{
switch (x)
{
case 0:
smallcircle.direction=gamedirection.youshang;
smallcircle.x=smallcircle。 × fantanjuli;
smallcircle.y=smallcircle.y-fantanjuli;
break;
ケース 1:
smallcircle.direction=gamedirection.shang;
smallcircle.y=smallcircle.y-fantanjuli;
break;
ケース 2:
smallcircle.direction=gamedirection.you;
smallcircle.x=smallcircle.x fantanjuli;
break;
default:
休憩;
} break;

}
case gamedirection.youshang:
{
switch (x)
{
case 0:
smallcircle.directイオン=ゲームの方向。 zuoxia;
smallcircle.x=smallcircle.x-fantanjuli;
smallcircle.y=smallcircle.y fantanjuli;
break;
ケース 1:
smallcircle.direction=gamedirection.zuo;
smallcircle.x=smallcircle.x-fantanjuli;
break;
ケース 2:
smallcircle.direction=gamedirection.xia;
smallcircle.y=smallcircle.y fantanjuli;
休憩;
default:
break;
} break;

}
case gamedirection.youxia:
{
switch (x)
{
ケース 0:
smallcircle.direction=gamedirection.zuoshang;
smallcircle.x=smallcircle.x-fantanjuli;
smallcircle.y=smallcircle.y-fantanjuli;
break;
ケース 1 :
smallcircle.direction=gamedirection.zuo;
smallcircle.x=smallcircle.x-fantanjuli;
break;
ケース 2:
smallcircle.direction=gamedirection.shang;
smallcircle.y=smallcircle.y-fantanjuli;
break;
default:
break;
} break;

}
default:
{
壊す;  
}
}
}//小球随机反方向randomback()
function smallcircledirection()
{
switch (smallcircle.direction){ //による小球方向移行
case gamedirection.shang:
{
smallcircle.y=smallcircle.y-gamespeed;
grade ;
if(grade>maxgrade)
{
maxgrade=グレード;
newrecoder();
}
addone();
break;
}
case gamedirection.xia:
{
smallcircle.y=smallcircle.y gamespeed;
grade ;
if(grade>maxgrade)
{
maxgrade=grade;
newrecoder();
}
addone();
break;
}
case gamedirection.zuo:
{
smallcircle.x=smallcircle.x-gamespeed ;
グレード ;
if(グレード>maxgrade)
{
maxgrade=grade;
newrecoder();
}
addone();
break;
}
case gamedirection.you:
{
smallcircle.x=smallcircle.x gamespeed;
グレード ;
if(グレード>maxgrade)
{
maxgrade=グレード;
newrecoder();
}
addone();
break;
}
case gamedirection.zuoshang:
{
smallcircle.x=smallcircle. x-gamespeed*0.8;
smallcircle.y=smallcircle.y-gamespeed*0.8;
grade ;
if(grade>maxgrade)
{
maxgrade=grade;
新しいレコーダー();
addone();
break;
}
case gamedirection.zuoxia:
{
smallcircle.x=smallcircle.x-ゲームスピード*0.8;
smallcircle.y=smallcircle.y ゲームスピード*0.8;
グレード ;
if(グレード>maxgrade)
{
maxgrade=grade;
newrecoder();
}
addone();
break;
}
case gamedirection.youshang:
{
smallcircle.x=smallcircle.x gamespeed*0.8;
smallcircle.y=smallcircle.y-gamespeed*0.8;
グレード ;
if (グレード>maxgrade)
{
maxgrade=grade;
newrecoder();
}
addone();
break;
}
case gamedirection.youxia :
{
smallcircle.x=smallcircle.x ゲームスピード*0.8;
smallcircle.y=smallcircle.y ゲームスピード*0.8;
グレード ;
if(グレード>maxgrade)
{
maxgrade=grade;
newrecoder();
}
addone();
break;
}
デフォルト:
{
break;  
}
}
}//小球移動 smallcircledirection()
/*画出底部圆*/
ctxpane.beginPath(); //大圆
ctxpane.arc(bigcircle.x,bigcircle.y,bigcircle.r,0,Math.PI*2,true);
ctxpane.fillStyle = bigcircle.c;
ctxpane.fill ();
ctxpane.closePath();
/*画出底部追尾線条*/
ctxpane.beginPath();
ctxpane.lineWidth=6;
ctxpane.drawingStyle = line .c;
ctxpane.arc(line.x, line.y, line.r, line.start, line.end,false);
ctxpane.ストローク();
ctxpane.closePath();
function Tapme()//tapme
{
ctxpane.beginPath();
ctxpane.ストロークスタイル="rgb(255,222,195)";
ctxpane .font = "80px パピルス";
ctxpane.ストロークText('TAP',-95,30);
ctxpane.fillStyle="rgb(255,205,105)";
ctxpane.font = "35px パピルス" ;
ctxpane.fillText('me',70,30);
ctxpane.closePath();
}
function newrecoder()
{
ctxpane.beginPath();
ctxpane.fillStyle="rgb(255,0,0)";
ctxpane.font = "18px Papyrus";
ctxpane.fillText("New!",58,80);
ctxpane.closePath();
}
function addone()
{
grade1=(grade/150).toFixed(1);
grade2=(maxgrade/150).toFixed( 1);
varsay1="now";
varsay2="best"
ctxpane.beginPath();
ctxpane.drawingStyle="rgb(250,222,185)";
ctxpane。 font = "60px Papyrus";
ctxpane.drawingText(grade1,-45,-60);
ctxpane.drawingText(grade2,-45,100);

ctxpane.fillStyle="rgb(255) ,0,100)";
ctxpane.font = "15px Papyrus";
ctxpane.fillText(say1,58,-60);

ctxpane.fillStyle="rgb(255,0,100)" ;
ctxpane.font = "15px Papyrus";
ctxpane.fillText(say2,58,100);
ctxpane.closePath();
}
function movetest(){

if(ifgameover())
{
ifingame=0;
if(maxgrade>parseInt(getCookie2('mymaxgrade')))
{
setCookie('ニックネーム',ニックネーム,'mymaxgrade',maxgrade.toString(),365);  
}
clearInterval(timer);
tapme();
}
else
{
if(ifcrash())
{
randomback() ;
}
ctxpane.clearRect(-150,-150,300,300); //清屏

ctxpane.beginPath(); //大圆
ctxpane.arc(bigcircle.x,bigcircle.y,bigcircle.r,0,Math.PI*2,true);
ctxpane.fillStyle = bigcircle.c;
ctxpane.fill ();
ctxpane.closePath();
if(line.direction==gamedirection. Clock) //跟追跡回線顺時間针
{
line.start=line.start linespeed; 
line.end=line.end linespeed;
ctxpane.beginPath();
ctxpane.lineWidth=4;
ctxpane.ストロークスタイル = line.c;
ctxpane.arc(line. x、line.y、line.r、line.start、line.end、false);
ctxpane.ストローク();
ctxpane.closePath(); 
}
if(line.direction==gamedirection.anti Clock) //跟追跡逆顺時間针
{
line.start=line.start - linespeed; 
line.end=line.end -linespeed;
ctxpane.beginPath();
ctxpane.lineWidth=4;
ctxpane.ストロークスタイル = line.c;
ctxpane.arc(line .x、line.y、line.r、line.start、line.end、false);
ctxpane.ストローク();
ctxpane.closePath();  
}

dot.x=bigcircle.r*Math.cos(line.start Math.PI/32) //跟追跡点
dot.y=bigcircle.r*Math.sin( line.start Math.PI/32)
ctxpane.beginPath();//線上跟追跡点
ctxpane.arc(dot.x,dot.y,dot.r,0,Math.PI*2 ,true);
ctxpane.fillStyle = smallcircle.c;
ctxpane.fill();
ctxpane.closePath(); 
smallcircledirection();//小圆
ctxpane.save();
ctxpane.beginPath();
ctxpane.arc(smallcircle.x,smallcircle.y,smallcircle.r,0, Math.PI*2,true);
ctxpane.fillStyle = smallcircle.c;
ctxpane.fill();
ctxpane.closePath();
ctxpane.restore();
}
}//主関数数

/////////////////////////////////////////
タップ();
var timer;
function startgame(){//开始游戏

if(ifingame==0)
{
ifingame=1;
Grade=0;
var xx=Math.floor(Math.random()*8);
/* switch(xx)
{
case 0:
smallcircle.direction=gamedirection.shang;
break;
case 1:
smallcircle.direction=gamedirection.xia;
break;
ケース 2:
smallcircle.direction=gamedirection.zuo;
break;
ケース 3:
smallcircle.direction=gamedirection.you;
break;
ケース 4:
smallcircle.direction=gamedirection.zuoshang;
break;
ケース 5:
smallcircle.direction=gamedirection.zuoxia;
break;
ケース 6:
smallcircle.direction=gamedirection.youshang;
break;
ケース 7:
smallcircle.direction=gamedirection.youxia;
break;
デフォルト:
break;
} */
smallcircle.direction=gamedirection.xia;
smallcircle.x=smallcircle.y=0;
line.start=Math.PI/2-Math.PI/26;
行。 end=Math.PI/2 Math.PI/26;
line.direction=gamedirection.anti Clock;

clearInterval(timer);
timer=setInterval(movetest,10);
}
}//开始游戏 startgame()
function opentop()
{
window.location="http://pongotop.sinaapp.com";
}

10.写在最後

この所属はまた個人的なもので、書き終えてから 3 日目に、開始された忙しい投函業務の空き時間に空き時間がなくなり、友友圈に友友玩去されました。もう一度再確認してください、感觉它不そのような死掉、本人不何技巧、得很遅略、したがってこの篇を発行しました文字希望能帮にいくつかのポンゴ感関心のある友友、再者就是希望如果有此面

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。