ساخت بازی با کانواس و جاوا اسکریپت

saalek110

Well-Known Member
setInterval:

JavaScript:
<!DOCTYPE html>
<html>
<body>

<h1>The Window Object</h1>
<h2>The setInterval() Method</h2>

<p id="demo"></p>

<script>
setInterval(displayHello, 1000);

function displayHello() {
  document.getElementById("demo").innerHTML += "Hello";
}
</script>

</body>
</html>

کار setInterval اینه که تابعی را هر چند وقت یک بار صدا بزنه.
در لینک زیر:

برنامه بالا ، هر یک ثانیه یک بار به شما hello می دهد.

در برنامه بازی چند پست قبل setInterval استفاده شده بود که توضیح دادم.
 

saalek110

Well-Known Member
اسکلت کلی برنامه:

راجع به کلاس آبجکتها یعنی component صحبت کردیم و فهمیدیم setinterval کارش چیه.
حالا بیایید کل آبجکت های برنامه را بریزیم بیرون و اسکلت کلی برنامه را بررسی کنیم.
در کد زیر ، من هر چیزی مربوط به کلاس و اشیا کلاس بود را حذف کردم... فقط اسکلت اصلی باقی مونده. قهرمان داستان و دیوارها و امتیاز همه اشیا کلاس بودند.

چیزی که در کد زیر مونده ، خلق پنجره کانواس است و یک سری توابع...
اول mygamearea اجرا میشه و داخلش setinterval هست که باعث میشه تابع updategamearea هر ۲۰ میلی ثانیه اجرا بشه...داخل تابع updategamearea یک قسمتی است که با نگاه به یک عدد که خود تابع updategamearea اون را یکی یکی افزایش میده ، هر ۱۵۰ تا از این عدد یک بار اجرا میشه.
من برای اینکه موقع اجرا ، اینها قابل دیدن باشه ، چاپ هایی به برنامه اضافه کردم ، که زیر پنجره کانواس اون چاپ ها را می بینید.

JavaScript:
<html>

<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>

canvas {
    border:1px solid #d3d3d3;
    background-color: #f1f1f1;
}

</style>
</head>
<body onload="startGame()">
<script>



function startGame() {
document.getElementById("p1").innerHTML="start game" ;
 
    myGameArea.start();

}
var myGameArea = {

    canvas : document.createElement("canvas"),

    start : function() {
document.getElementById("p2").innerHTML+="myGameArea start" ;

        this.canvas.width = 480;
        this.canvas.height = 270;
        this.context = this.canvas.getContext("2d");
        document.body.insertBefore(this.canvas, document.body.childNodes[0]);
        this.frameNo = 0;
        this.interval = setInterval(updateGameArea, 2000);
        },

    clear : function() {

        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
    }

}

function updateGameArea() {
document.getElementById("p3").innerHTML+= "updategamearea" ;
    var x, height, gap, minHeight, maxHeight, minGap, maxGap;
 

    myGameArea.clear();
    myGameArea.frameNo += 1;
document.getElementById("p4").innerHTML=  "frameno= " + JSON.stringify(myGameArea.frameNo) ;
    if (myGameArea.frameNo == 1 || everyinterval(5)) {
document.getElementById("p5").innerHTML=  "frameno= " + JSON.stringify(myGameArea.frameNo) ;
    }
}

function everyinterval(n) {
    if ((myGameArea.frameNo / n) % 1 == 0) {return true;}
    return false;
}


</script>
<br>
<p id="p1"></p>
<p id="p2"></p>
<p id="p3"></p>
<p id="p4"></p>
<p id="p5"></p>
<button onmousedown="accelerate(-0.2)" onmouseup="accelerate(0.05)">ACCELERATE</button>
<p>Use the ACCELERATE button to stay in the air</p>
<p>How long can you stay alive?</p>
</body>
</html>

نتیجه اجرا را در لینک زیر ببینید:


در اجرا ، کلمه ای انگلیسی مرتب چاپ و زیرش دو تا عدد در حال شمارش است که همون فریم نامبر است ، یک عدد ساختگی توسط طراح برنامه است تا با نگاه به اون بتونه برنامه را کنترل کنه.. مثل نگاه مردم به ساعت ، تا سر ساعت کارهاشون را انجام بدهند.‌ در لینک بالا یک عدد ، یکی یکی داره افزایش پیدا می کنه ولی عدد بعدی هر ۵ تا یهو ۵ تا افزایش پیدا می کنه....چون اون قسمت داخلی فقط در مضارب ۵ فریم نامبر اجرا میشه. عدد ۵ را من دادم تا قابل رویت بشه ، در اصل ۱۵۰ بود.. یعنی هر۱۵۰ تا که فریم نامبر برود بالا، یک بار اون قسمت داخلی اجرا میشه..و چون تابع updategamearea هر ۲۰ میلی ثانیه اجرا میشه ، به خاطر اون ۲۰ که به تابع setinterval داده بودند ، پس قسمت داخلی هر ۱۵۰ ضربدر ۲۰ میلی سکند اجرا میشه ، میشه ۳ ثانیه....یعنی دیوارها هر ۳ ثانیه یک بار ایجاد می شوند. چون دیوارها در اون قسمت داخلی ایجاد می شوند.

من با خالی کردن برنامه از کااس و اشیا ، خواستم بدانید اسکلت کلی برنامه چطور کار می کند.
پس تابع updategame area هر ۲۰ میلی ثانیه اجرا میشه و همه کارهای بازی را انجام می دهد ، شامل تکون دادن دیوارها و بررسی برخوردها و تکون دادن قهرمان، و اون قسمت داخلی که داخل تابع updateganearea است ، هم کارش ایجاد دیوارهای جدید هر ۳ ثانیه یک بار است.
 
آخرین ویرایش:

saalek110

Well-Known Member
گویا تابع start از mygamearea فقط یک بار اجرا میشه ولی اون setinterval هر دو ثانیه اجرا میشه.
البته در برنامه اصلی ۲۰ میلی ثانیه بود نه ۲ ثانیه.
یعنی هر ۲۰ میلی ثاتیه ، تابع updateGameArea اجرا میشه.
و اون تکه داخلی این تابع ، هر گاه فریم نامبر مضرب ۱۵۰ باشه اجرا میشه. که من به جای ۱۵۰ نوشتم ۵ تا راحت تر پیگیری کنیم.

حالا ببینیم کار تابع updateGameArea و اون قسمت داخلی که با مضرب ۱۵۰ فریم نامبر اجرا میشه چیه.

JavaScript:
function updateGameArea() {
    var x, height, gap, minHeight, maxHeight, minGap, maxGap;
    for (i = 0; i < myObstacles.length; i += 1) {
        if (myGamePiece.crashWith(myObstacles[i])) {

            return;
        }
    }

    myGameArea.clear();
    myGameArea.frameNo += 1;
    if (myGameArea.frameNo == 1 || everyinterval(150)) {
        x = myGameArea.canvas.width;
        minHeight = 20;
        maxHeight = 200;
        height = Math.floor(Math.random()*(maxHeight-minHeight+1)+minHeight);
        minGap = 50;
        maxGap = 200;
        gap = Math.floor(Math.random()*(maxGap-minGap+1)+minGap);
        myObstacles.push(new component(10, height, "green", x, 0));
        myObstacles.push(new component(10, x - height - gap, "green", x, height + gap));

    }
    for (i = 0; i < myObstacles.length; i += 1) {
        myObstacles[i].x += -1;
        myObstacles[i].update();
    }

    myScore.text="SCORE: " + myGameArea.frameNo;
    myScore.update();
    myGamePiece.newPos();
    myGamePiece.update();
}

در تابع updateGameArea در قسمت اول برخورد اشیا بررسی می شود...
بعد گویا صفحه پاک میشه و فریم نامبر افزایش پیدا می کند ،
و هر ۱۵۰ فریم نامبر شی سازی انجام میشه.... احتمالا طراح برنامه دیده اگر هر ۱۵۰ فریم نامبر شی بسازه فاصله شان خوب درمیاد....
در ادامه همگی اشیا یک قدم به چپ میاد و رسم میشن و بعد قهرمان و فریم نامبر چاپ میشه....

خوب همه کارها انگار در updateGameArea انجام میشه با فواصل ۲۰ میلی سکندی و داخلش اشیاسازی هر ۱۵۰ فریم نامبر... فکر کنم اشیا سازی میشه ۱۵۰ ضربدر ۲۰ میلی ثانیه ....یعنی هر ۳ ثانیه شی جدید خلق میشه.

البته آبجکت ها کارهاشون را با کلاس component انجام می دهند که ما برای خلوت شدن حذفش کردیم.
 
آخرین ویرایش:

saalek110

Well-Known Member
حالا بیاییم اعداد واقعی را بدهیم....

JavaScript:
<html>

<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>

canvas {
    border:1px solid #d3d3d3;
    background-color: #f1f1f1;
}

</style>
</head>
<body onload="startGame()">
<script>



function startGame() {
document.getElementById("p1").innerHTML="start game" ;
 
    myGameArea.start();

}
var myGameArea = {

    canvas : document.createElement("canvas"),

    start : function() {
document.getElementById("p2").innerHTML+="myGameArea start" ;

        this.canvas.width = 480;
        this.canvas.height = 270;
        this.context = this.canvas.getContext("2d");
        document.body.insertBefore(this.canvas, document.body.childNodes[0]);
        this.frameNo = 0;
        this.interval = setInterval(updateGameArea, 20);
        },

    clear : function() {

        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
    }

}

function updateGameArea() {
//document.getElementById("p3").innerHTML+= "updategamearea" ;
    var x, height, gap, minHeight, maxHeight, minGap, maxGap;
 

    myGameArea.clear();
    myGameArea.frameNo += 1;
document.getElementById("p4").innerHTML=  "frameno= " + JSON.stringify(myGameArea.frameNo) ;
    if (myGameArea.frameNo == 1 || everyinterval(150)) {
document.getElementById("p5").innerHTML=  "frameno= " + JSON.stringify(myGameArea.frameNo) ;
    }
}

function everyinterval(n) {
    if ((myGameArea.frameNo / n) % 1 == 0) {return true;}
    return false;
}


</script>
<br>
<p id="p1"></p>
<p id="p2"></p>
<p id="p3"></p>
<p id="p4"></p>
<p id="p5"></p>
<button onmousedown="accelerate(-0.2)" onmouseup="accelerate(0.05)">ACCELERATE</button>
<p>Use the ACCELERATE button to stay in the air</p>
<p>How long can you stay alive?</p>
</body>
</html>


حالا ببینید اشیا سازی هر چند ثانیه است.
به نظر من همان ۳ ثانیه است. اجرای فایل بالا را ببینید.
 

saalek110

Well-Known Member
حالا که ساختار برنامه فوق را یاد گرفتیم ، می توانیم از این ساختار در برنامه های خود استفاده کنیم.

یک قسمتی از برنامه هست که هر چند میلی ثانیه اجرا میشه و هر ۱۵۰ اجرای اون قسمت ، یک قسمت دیگه اجرا میشه.

و یک کارخانه آبجکت داشتیم که آبجکت ها اونجا کارهاشون انجام میشد.

توجه کنید که شما هم به این تابعی که هر ۲۰ میلی ثانیه اجرا شود نیاز دارید ، چون اگر مدام بازی بخواد کار کنه مخل کار دستگاه یعنی گوشی شماست. باید هر چند میلی ثانیه فقط کار کنه و اجازه بده گوشی به کار خودش ادامه بده..

اون قسمت کامپوننت هم محل ایجاد دیوارهاست و تمام اطلاعات دیوارها مثل محل قرارگیری و طول و عرض دیوار را نگه داری می کند. و شما می توانید بی نهایت اطلاعات دیگر در مورد دیوارها به کلاس اضافه کنید. یک جور ثبت احوال دیوارهاست کلاس copmponent.
 
آخرین ویرایش:

saalek110

Well-Known Member
فریم :
در برنامه فوق فعالیت برنامه هر ۲۰ میلی ثانیه یک بار است. شاید طراح دلیل خاصی داشته که این عدد را انتخاب کرده.. شاید اگر دیرتر باشه ، برنامه کند به نظر برسه و اگر زیادتر باشه سیستم را بی دلیل مشغول کند.
 

saalek110

Well-Known Member
لینک کلی:



یک سری بسته ها اینجاست که بعضی کانواس است.
 

saalek110

Well-Known Member

saalek110

Well-Known Member
آخرین ویرایش:

saalek110

Well-Known Member
بازی کامل است ، دکمه برای گوشی هم دارد.
موش باید گربه ها را گیر بیاندازد.
لول بعدی هم دارد.

مشاهده پیوست 117795
در تحلیل بازی سایت w3school , دیدیم که هر ۲۰ میلی سکند کارهای بازی انجام میشد....مثل حرکت دادن قطعات دشمن و حرکت دادن قهرمان و تنظیم دیگر چیزها... من هنوز کدهای بازی موش و گربه را ندیدم.. ولی حرکت گربه ها ، وابسته به محل موش است و باید هر چند وقت یک بار انجام شود. احتمالا xو y گربه به x و y موش نزدیک می شود...
یادمه چتد سال پیش یک بازی ویژوال بیسیک را تحلیل می کردم... اونجا ریختن آجرها مطرح بود... حرکت آجرها هم هر چند وقت یک بار انجام میشد....

پس در بازی w3school با اون تابع ست اینتروال ، یک تابعی هر ۲۰ میلی ثانیه فراخوانی میشد و کارهای بازی اونجا انجام میشد... و داخل اون تابع هم یک قسمتی بود که هر ۱۵۰ بار که اون تابع اجرا میشد ، اشیای جدید ساخته میشد....با افزایش دادن یک عدد در تابع مرور شونده به نان فریم نامبر ، میشد عدد ۱۵۰ را بدست آورد. اونجا کدش را توضیح ندادم ولی حاصل تقسیم فریم نامبر بر ۱۵۰ باید صفر میشد... عملگر باقی مانده استفاده شده بود.

در بازی موش و گربه ، اشیای جدید نداریم ، همه اشیا اول بازی چیده شده که شامل گربه ها و جعبه ها است.
در بازی w3 school اشیا جدید مستطیل هایی بودند که با تابع راندوم سایزشان تعیین میشد ، بازی هواپیمای آتاری را خیلی ها یادشان است... اونجا کشتی ها و هواپیماها راندوم ظاهر نمیشد... هر کشتی یا هواپیما ، نقطه شروع خاصی داشت ، و وقتی قهرمان بازی وارد صحنه میشد ، اون کشتی ها و هواپیماها حرکت رفت و برگشت خود را در کانال شروع می کردند.
 

saalek110

Well-Known Member
استفاده از همان اسکلت بازی w3school:

از اسکلت اصلی و حتی از کلاس آبجکت بازی سایت w3school می توانیم در بازیهای خود استفاده کنیم...
فقط دشمنان و قهرمان ظاهرشان عوض میشه ولی ساختار برنامه همان است....
شاید بتوانیم با همان اسکلت w3school بازی هواپیمای آتاری را هم بسازیم... در محل خلق اشیا دیگه از تابع راندوم استفاده نمیشه و یک مپ احتمالا باید وجود داشته باشه....
من چند سال پیش یک بازی ماشین با سی شارپ ساختم ، برای ایجاد جاده و مناظر اطراف یک ابتکار ساده به کار برده بودم ، و باعث میشد بازیکن احساس می کرد داره از محیط های مختلف رد میشه... یک مپ مشخصی بازی نداشت ولی یک نظمی داشت ، الان دقیقا یادم نیست چطوری کار کرده بودم... نگاه کردن به بازیهای دیگران کمک می کنه ایده هایی که اونها استفاده کردند را یاد بگیریم و ما هم استفاده کنیم....
در استفاده از بازی سازهایی مثل game maker ابزارها مشخص تر و محدود تر است ولی در کار با جاوا اسکریپت دست باز تر است و به همان اندازه نیاز به چارچوبهایی احساس می شود که بر اساس اون چارچوب ها بازی ساخته شود....
من دارم در مورد همون چارچوب ها صحبت می کنم....چون ما بازی ساز خاصی کار نمی کنیم و کدهای جاوا اسکریپت ابزار دست ماست و جاوا اسکریپت یک بازی ساز نیست ، یعنی برای بازی سازی طراحی نشده ولی توانایی های مختلفی دارد.

یک کار هم تغییر دادن بازیهای دیگران است...همون کاری که من کردم و اون بازی را ساده تر کردم.همچنین اون بازی بزای کامپیوتر بود ولی با اضافه کردن دکمه هایی مناسب گوشی کردم. در گام بعد میشه قسمتهای بیشتری از بازی را تغییر داد. مثلا در اون بازی وقتی دکمه بالا و پایین را رها می کردی قهرمان سرعت می گرفت و باید مدام دکمه بالا و پایین را متناوب می زدی تا اون را تحت کنترل نگه داری... فکر کنم بشه اون افزایش سرعت را حذف کرد... و یک تغییر دیگر هم ضخیم کردن اون دیوارها است... و یا کلا یک سری هواپیما و کشتی ، مثل بازی هواپیمای آتاری به جای اون دیوارها وارد بازی کرد. مثلا من برنامه ساعت را تغییر دادم ، و به جای عقربه ساعت یک ماشین ساختم. در تاپیک svg است. الان اون ماشین در سایتم به چپ و راست در حال حرکت است.

Screenshot_۲۰۲۴-۰۲-۱۶_۲۱۴۶۲۵.jpg

در بازی سایت w3school هم می توان به جای دیوارهای ساده طرحهای پیچیده تر ساخت ، در اون بازی هر دیوار فقط یک مستصیل بود ، ولی در svg گروه بندی شکل ها وجود داشت.... در بازی w3school هم باید یک جور گروه بندی شکل ها صورت بگیرد و هر گروه با هم حرکت کند.یعنی هر شکلی که خلق میشود باید یک شماره گروه هم داشته باشد...و موقع حرکت دادن هم ، بر اساس شماره گروه باشه نه شماره شکل ها... در اون بازی بر اساس شماره شکلها کار انجام میشد، یعنی در یک حلقه ، تمامی شکل ها حضور و غیاب میشد... من دنبال جایی می گشتم که اشیا وقتی از سمت چپ صفحه خارج می شوند بمیرند و نابود شوند ، ولی چنین چیزی در بازی پیدا نکردم.... یعنی فکر کنم حتی اشیایی که از سمت چپ از بازی خارج می شدند هم چک می شدند که به قهرمان خورده اند یا نه. البته باید یک بار دیگر بازی را ببینم، که اون حلقه اعدادش را از کجا می آورد.
....
الان رفتم دقیق تر نگاه کردم ، یک متغیر آرایه ای تعریف شده و اون متغیر push می کنه ، تا آبجکت جدید ساخته بشه... در اون حلقه هم طول ارایه ملاک است... پس مرگ اشیا نداریم...شاید طراح گفته بازیکن خیلی زود می سوزه و مهم نیست که اشیای مرده هم مورد محاسبه قرار گیرد. بهرحال اگر بازی بخواهد طولانی شود باید اشیایی که از سمت چپ خارج می شوند حذف شوند...شاید یک راه این باشه که یک ارایه با تعداد محدود داشته باشیم ، و مدام برگردیم از اول داخلش بنویسیم ، مثل هارد دوربین های مدار بسته که وقتی پر میشه ، می رود از اول از اون طرفش دوباره رویش می نویسد...یعنی فیلم چند ماه پیش را دیگر شما ندارید و فقط فیلم های چند روز اخیر را شما دارید.
الان دقیق نمی دونم اون کلاس آبجکت ساز چطوری باید شماره های تکراری را به آبجکت های ساخته شده بدهد... شاید طراح هم راهی به ذهنش نرسیده و راه راحت را رفته... البته راه که میشه برایش پیدا کرد ولی کمی فکر می خواد... بهرحال خواستم این هم بحث شود تا جا بیافتد...در بازیهای سه بعدی ... فقط جایی که قهرمان هست رسم می شود تا بازی سنگین نشود ، دراین بازی هم نبای آبجکت های بیرون صفحه پردازش میشد... البته محاسبات ریاضی سرعت خیلی بالایی دارد و با رسم اشیای ۳ بعدی قابل مقایسه نیست... شاید طراح هم می دونسته که یک سری محاسبات ریاضی ، فشاری به بازی وارد نمی کنه. لی مثلا می تونست بگه وقتی ایکس اون دیوار خیلی دور از قهرمان است دیگه باقی محاسبات را دیگه انجام ندهد، این جوری محاسبات باطل یک هشتم تا یک بیستم میشد.
شما با مرور کدهای بازیهای مختلف می توانید صاحب تجربه شوید.
 
آخرین ویرایش:

saalek110

Well-Known Member
JavaScript:
        myObstacles.push(new component(148, height, "green", x, 0));
        myObstacles.push(new component(148, x - height - gap, "green", x, height + gap));
من بازی را تغییر دادم... در دو خط بالا ، عرض دیوار را نزدیک ۱۵۰ گرفتم.... این عدد ۱۵۰ همون عددی است که هر ۱۵۰ تایی که فریم نامبر بالا می رفت شی جدید خلق میشد.. پس اگر عرض دیوار ۱۴۸ باشه تقریبابه شی بعدی می رسه...

شکل زیر:

Screenshot_۲۰۲۴-۰۲-۱۶_۲۲۳۹۲۷.jpg

و می بینید بازی کردن سخت میشه..پس جون را به جای ۲۰۰ کردم ۱۰۰۰۰




پس ستونهای خیلی ضخیم جالب نشد ، پس ستونها را باز باریک تر کردم و جون را هزار کردم. ورژن ۱۰۰۰ ساخته شد:


در ورژن بالا ستونها فقط کمی ضخیم هستند و جون ۱۰۰۰ است. به نظرم از ورژن ۲۰۰ بهتر است. نمای ستون ها جالب تر است فکر کنم.
 
آخرین ویرایش:

saalek110

Well-Known Member
ورژن ستونهای رنگی:


Screenshot_۲۰۲۴-۰۲-۱۶_۲۳۰۹۳۳.jpg

JavaScript:
   if (height>120)
        {
        myObstacles.push(new component(40, height, "red", x, 0));
         myObstacles.push(new component(40, x - height - gap, "red", x, height + gap));

        }//height>120
        if (height<=120)
         {
        myObstacles.push(new component(40, height, "green", x, 0));
        myObstacles.push(new component(40, x - height - gap, "green", x, height + gap));
          }// height<=120

بر اساس طول ستون ، ستونهار بزرگ را قرمز کردم.
 

saalek110

Well-Known Member
ورژن f4


به جای قهرمان عکس یک هواپیما قرار کرفته.

Screenshot_۲۰۲۴-۰۲-۱۷_۰۲۱۷۴۳.jpg

من اومدم شبیه score یک type برای قهرمان قائل شدم به نام hero و در کلاس componentدر قسمت update یک if باز کردم ، گفتم اگر type از نوع hero بود عکس نمایش بده.

JavaScript:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
canvas {
    border:1px solid #d3d3d3;
    background-color: #f1f1f1;
}
  #the_heart {
    border:3px solid #fff733;
    border-radius:25px;

font-size:20px;

    margin-right:150px;
    margin-left:150px;

    padding-top:3px;
    padding-bottom:3px;

    padding-left:30px;

    background-color:rgba(250,130,30,1);
       }
</style>
</head>
<body onload="startGame()">
<img id="plane" src="images/plane33.jpg" alt="plane" width="10" height="10">

 <script type='text/javascript'>
var myGamePiece;
var myObstacles = [];
var myScore;
let heart=1000;


function startGame() {

    myGamePiece = new component(2, 2, "red", 10, 120 , "hero");
    myGamePiece.gravity = 0.05;
    myScore = new component("30px", "Consolas", "black", 280, 40, "text");
    myGameArea.start();
}

var myGameArea = {
    canvas : document.createElement("canvas"),
    start : function() {
        this.canvas.width = 480;
        this.canvas.height = 270;
        this.context = this.canvas.getContext("2d");
        document.body.insertBefore(this.canvas, document.body.childNodes[0]);
        this.frameNo = 0;
        this.interval = setInterval(updateGameArea, 20);
        },
    clear : function() {
        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
    }
}

function component(width, height, color, x, y, type) {
    this.type = type;
    this.score = 0;
    this.width = width;
    this.height = height;
    this.speedX = 0;
    this.speedY = 0; 
    this.x = x;
    this.y = y;
    this.gravity = 0;
    this.gravitySpeed = 0;
    this.update = function() {
        ctx = myGameArea.context;
        if (this.type == "text") {
            ctx.font = this.width + " " + this.height;
            ctx.fillStyle = color;
            ctx.fillText(this.text, this.x, this.y);
        } else if(this.type=="hero")
        {
              var img = document.getElementById("plane");
                ctx.drawImage(img,this.x,this.y);
        }
        else {
            ctx.fillStyle = color;
            ctx.fillRect(this.x, this.y, this.width, this.height);
        }
    }
    this.newPos = function() {
        this.gravitySpeed += this.gravity;
        this.x += this.speedX;
        this.y += this.speedY + this.gravitySpeed;
        this.hitBottom();
    }
    this.hitBottom = function() {
        var rockbottom = myGameArea.canvas.height - this.height;
        if (this.y > rockbottom) {
            this.y = rockbottom;
            this.gravitySpeed = 0;
        }
    }
    this.crashWith = function(otherobj) {
        var myleft = this.x;
        var myright = this.x + (this.width);
        var mytop = this.y;
        var mybottom = this.y + (this.height);
        var otherleft = otherobj.x;
        var otherright = otherobj.x + (otherobj.width);
        var othertop = otherobj.y;
        var otherbottom = otherobj.y + (otherobj.height);
        var crash = true;
        if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) {
            crash = false;
        }
        return crash;
    }
}

function updateGameArea() {
    var x, height, gap, minHeight, maxHeight, minGap, maxGap;
    for (i = 0; i < myObstacles.length; i += 1) {
        if (myGamePiece.crashWith(myObstacles[i])) {
heart--;
if (heart<0)
            return;
        }
    }
    myGameArea.clear();
    myGameArea.frameNo += 1;
    if (myGameArea.frameNo == 1 || everyinterval(150)) {
        x = myGameArea.canvas.width;
        minHeight = 20;
        maxHeight = 200;
        height = Math.floor(Math.random()*(maxHeight-minHeight+1)+minHeight);
        minGap = 100
        maxGap = 150;
        gap = Math.floor(Math.random()*(maxGap-minGap+1)+minGap)+50;
        if (height>120)
        {
        myObstacles.push(new component(40, height, "red", x, 0));
         myObstacles.push(new component(40, x - height - gap, "red", x, height + gap));

        }//height>120
                if (height<=120)
         {
        myObstacles.push(new component(40, height, "green", x, 0));
        myObstacles.push(new component(40, x - height - gap, "green", x, height + gap));
          }// height<=120
    }
    for (i = 0; i < myObstacles.length; i += 1) {
        myObstacles[i].x += -1;
        myObstacles[i].update();
    }
    myScore.text="SCORE: " + myGameArea.frameNo;
//  heart.text="heart= ";  //+heart.toString();
    myScore.update();
 //heart.update();
document.getElementById("the_heart").innerHTML="heart= " + JSON.stringify(heart);
    myGamePiece.newPos();
    myGamePiece.update();
}

function everyinterval(n) {
    if ((myGameArea.frameNo / n) % 1 == 0) {return true;}
    return false;
}

function accelerate(n) {
    myGamePiece.gravity = n;
  
}
</script>
<br>
<br>
<br>

<center>
<p id="the_heart"></p>
<button type="button" style=" font-size:35px; height:100px; width:220px" onclick="accelerate(-0.04)">up</button>


<button type="button" style=" font-size:12px; height:55px; width:120px" onclick="accelerate(0.5)">ground</button>


<button type="button" style=" font-size:35px; height:100px; width:220px" onclick="accelerate(0.04)">down</button>
</center>

<p>Use the up and down button to stay in the air</p>


<p>How long can you stay alive?</p>
</body>
</html>
 
آخرین ویرایش:

جدیدترین ارسال ها

بالا