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

saalek110

Well-Known Member
صفحه ۴:

میگم شاید بهتر باشه یک بازی به سبک ماریو بسازیم...
یعنی تانک و هواپیما را بزاریم کنار و یک آدم بیاد جای قهرمان....

mariogames.png

من قبلا در گیم میکر ، آدمکی که راه برود ساخته بودم، خیلی جالب بود. تجربه خوبی بود.
لینک:

سی آوریل ۲۰۲۳ کار کردم. زیاد هم قدیمی نیست.

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

دو نما از بازی:

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

Screenshot_۲۰۲۴-۰۲-۱۸_۱۳۳۳۳۱.jpg
 
آخرین ویرایش:

saalek110

Well-Known Member
JavaScript:
  ctx.font = "48px serif";
  ctx.fillText("Hello world", 10, 50);

JavaScript:
ctx.font = "48px serif";
  ctx.strokeText("Hello world", 10, 50);


در بالا دو روش نوشتن متن را می بینید.
سایت بالا مثالهای خوبی دارد ، دوست داشتید مرور کنید.
 

saalek110

Well-Known Member
JavaScript:
ctx.fillStyle = "orange";
ctx.fillStyle = "#FFA500";
ctx.fillStyle = "rgb(255 165 0)";
ctx.fillStyle = "rgb(255 165 0 / 100%)";

معرفی رنگ به روشهای مختلف.
 

saalek110

Well-Known Member
پترن:
JavaScript:
function draw() {
  const ctx = document.getElementById("canvas").getContext("2d");

  // create new image object to use as pattern
  const img = new Image();
  img.src = "canvas_createpattern.png";
  img.onload = () => {
    // create pattern
    const ptrn = ctx.createPattern(img, "repeat");
    ctx.fillStyle = ptrn;
    ctx.fillRect(0, 0, 150, 150);
  };
}

 

saalek110

Well-Known Member
JavaScript:
function draw() {
  const ctx = document.getElementById("canvas").getContext("2d");

  ctx.shadowOffsetX = 2;
  ctx.shadowOffsetY = 2;
  ctx.shadowBlur = 2;
  ctx.shadowColor = "rgb(0 0 0 / 50%)";

  ctx.font = "20px Times New Roman";
  ctx.fillStyle = "Black";
  ctx.fillText("Sample String", 5, 30);
}
متن با سایه.

 

saalek110

Well-Known Member
JavaScript:
ctx.beginPath();
    ctx.moveTo(75, 25);
    ctx.quadraticCurveTo(25, 25, 25, 62.5);
    ctx.quadraticCurveTo(25, 100, 50, 100);
    ctx.quadraticCurveTo(50, 120, 30, 125);
    ctx.quadraticCurveTo(60, 120, 65, 100);
    ctx.quadraticCurveTo(125, 100, 125, 62.5);
    ctx.quadraticCurveTo(125, 25, 75, 25);
    ctx.stroke();

ایجاد شکلی شبیه نقل قول. بالای سر یک نفر و داخلش یک چیزی بنویسیم....


 

saalek110

Well-Known Member
JavaScript:
ctx.beginPath();
    ctx.moveTo(75, 40);
    ctx.bezierCurveTo(75, 37, 70, 25, 50, 25);
    ctx.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5);
    ctx.bezierCurveTo(20, 80, 40, 102, 75, 120);
    ctx.bezierCurveTo(110, 102, 130, 80, 130, 62.5);
    ctx.bezierCurveTo(130, 62.5, 130, 25, 100, 25);
    ctx.bezierCurveTo(85, 25, 75, 37, 75, 40);
    ctx.fill();

شکل قلب. برای نماد جون خوبه.

 

saalek110

Well-Known Member
JavaScript:
  // Center main canvas area to the middle of the screen
  ctx.translate(
    (window.innerWidth - canvasWidth) / 2 - sceneOffset,
    (window.innerHeight - canvasHeight) / 2
  );


داشتم کدهای بازی ایشان را می خواندم که کد بالا را دیدم. گویا برای وسط قرار دادن کانواس در صفحه است.
این هم تابع رسم hero است:
JavaScript:
function drawHero() {
  ctx.save();
  ctx.fillStyle = "black";
  ctx.translate(
    heroX - heroWidth / 2,
    heroY + canvasHeight - platformHeight - heroHeight / 2
  );

  // Body
  drawRoundedRect(
    -heroWidth / 2,
    -heroHeight / 2,
    heroWidth,
    heroHeight - 4,
    5
  );

  // Legs
  const legDistance = 5;
  ctx.beginPath();
  ctx.arc(legDistance, 11.5, 3, 0, Math.PI * 2, false);
  ctx.fill();
  ctx.beginPath();
  ctx.arc(-legDistance, 11.5, 3, 0, Math.PI * 2, false);
  ctx.fill();

  // Eye
  ctx.beginPath();
  ctx.fillStyle = "white";
  ctx.arc(5, -7, 3, 0, Math.PI * 2, false);
  ctx.fill();

  // Band
  ctx.fillStyle = "red";
  ctx.fillRect(-heroWidth / 2 - 1, -12, heroWidth + 2, 4.5);
  ctx.beginPath();
  ctx.moveTo(-9, -14.5);
  ctx.lineTo(-17, -18.5);
  ctx.lineTo(-14, -8.5);
  ctx.fill();
  ctx.beginPath();
  ctx.moveTo(-10, -10.5);
  ctx.lineTo(-15, -3.5);
  ctx.lineTo(-5, -7);
  ctx.fill();

  ctx.restore();
}

هرو را در عکس زیر می بینید:
 

پیوست ها

  • Screenshot_۲۰۲۴-۰۲-۱۸_۱۵۱۶۰۹.jpg
    Screenshot_۲۰۲۴-۰۲-۱۸_۱۵۱۶۰۹.jpg
    9.8 کیلوبایت · بازدیدها: 0
آخرین ویرایش:

saalek110

Well-Known Member
JavaScript:
function drawBackground() {
  // Draw sky
  var gradient = ctx.createLinearGradient(0, 0, 0, window.innerHeight);
  gradient.addColorStop(0, "#BBD691");
  gradient.addColorStop(1, "#FEF1E1");
  ctx.fillStyle = gradient;
  ctx.fillRect(0, 0, window.innerWidth, window.innerHeight);

  // Draw hills
  drawHill(hill1BaseHeight, hill1Amplitude, hill1Stretch, "#95C629");
  drawHill(hill2BaseHeight, hill2Amplitude, hill2Stretch, "#659F1C");

  // Draw trees
  trees.forEach((tree) => drawTree(tree.x, tree.color));
}

// A hill is a shape under a stretched out sinus wave
function drawHill(baseHeight, amplitude, stretch, color) {
  ctx.beginPath();
  ctx.moveTo(0, window.innerHeight);
  ctx.lineTo(0, getHillY(0, baseHeight, amplitude, stretch));
  for (let i = 0; i < window.innerWidth; i++) {
    ctx.lineTo(i, getHillY(i, baseHeight, amplitude, stretch));
  }
  ctx.lineTo(window.innerWidth, window.innerHeight);
  ctx.fillStyle = color;
  ctx.fill();
}

function drawTree(x, color) {
  ctx.save();
  ctx.translate(
    (-sceneOffset * backgroundSpeedMultiplier + x) * hill1Stretch,
    getTreeY(x, hill1BaseHeight, hill1Amplitude)
  );
توابع رسم پشت صفحه ، تپه و درخت و ...

Screenshot_۲۰۲۴-۰۲-۱۸_۱۵۱۹۳۱.jpg
 

saalek110

Well-Known Member
JavaScript:
function drawRoundedRect(x, y, width, height, radius) {
  ctx.beginPath();
  ctx.moveTo(x, y + radius);
  ctx.lineTo(x, y + height - radius);
  ctx.arcTo(x, y + height, x + radius, y + height, radius);
  ctx.lineTo(x + width - radius, y + height);
  ctx.arcTo(x + width, y + height, x + width, y + height - radius, radius);
  ctx.lineTo(x + width, y + radius);
  ctx.arcTo(x + width, y, x + width - radius, y, radius);
  ctx.lineTo(x + radius, y);
  ctx.arcTo(x, y, x, y + radius, radius);
  ctx.fill();
}
مستطیل گوشه گرد...معنی اسم تابع بالاست.
 

saalek110

Well-Known Member
چرا این کدها را اینجا پست زدم.؟.. گاهی بهتره از تجربیات دیگران استفاده کرد تا همه کارهای را خودت انجام دهی...
افراد زیادی کاری را که ما داریم انجام می دهیم را قبلا انجام دادند... از تجربیات اونها اگر استفاده کنیم سریعتر به هدف می رسیم.

در حال کار بر پروژه هستم...
یک فایل به نام functions ساختم تا توابع را داخلش قرار دهیم.
 
آخرین ویرایش:

saalek110

Well-Known Member
کار با Sprite Sheet ها:

Sprite Sheet به عکسهای مولتی مناسب بازی میگن.

Green-Cap-Character-16x18.png


JavaScript:
<canvas width="300" height="200"></canvas>
<script>
let img = new Image();
img.src = 'https://opengameart.org/sites/default/files/Green-Cap-Character-16x18.png';
img.onload = function() {
  init();
};

let canvas = document.querySelector('canvas');
let ctx = canvas.getContext('2d');

const scale = 2;
const width = 16;
const height = 18;
const scaledWidth = scale * width;
const scaledHeight = scale * height;

function drawFrame(frameX, frameY, canvasX, canvasY) {
  ctx.drawImage(img,
                frameX * width, frameY * height, width, height,
                canvasX, canvasY, scaledWidth, scaledHeight);
}

function init() {
  drawFrame(0, 0, 0, 0);
  drawFrame(1, 0, scaledWidth, 0);
  drawFrame(0, 0, scaledWidth * 2, 0);
  drawFrame(2, 0, scaledWidth * 3, 0);
}


</script>

کد بالا را من امتحان کردم ، ۴ تا عکس کنار هم نشان می دهد:
Screenshot_۲۰۲۴-۰۲-۱۸_۱۹۰۰۲۰.jpgاشتباه نگیرید ، این ۴ آدمک حاصل اجرای کد است..اسپریت شیت اول پست زده شده.

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

saalek110

Well-Known Member
ایجاد دکمه داخل کانواس:

JavaScript:
<!DOCTYPE html>
<html>
  <head>
    <script src="https://unpkg.com/[email protected]/konva.min.js"></script>
    <meta charset="utf-8" />
    <title>Konva Hide and Show Demo</title>
    <style>
      body {
        margin: 0;
        padding: 0;
        overflow: hidden;
        background-color: #f0f0f0;
      }
      #buttons {
        position: absolute;
        left: 10px;
        top: 0px;
      }
      button {
        margin-top: 10px;
        display: block;
      }
    </style>
  </head>
  <body>
    <div id="container"></div>
    <div id="buttons">
      <button id="show">show</button>
      <button id="hide">hide</button>
    </div>
    <script>
      var width = window.innerWidth;
      var height = window.innerHeight;

      var stage = new Konva.Stage({
        container: 'container',
        width: width,
        height: height,
      });
      var layer = new Konva.Layer();

      var pentagon = new Konva.RegularPolygon({
        x: stage.width() / 2,
        y: stage.height() / 2,
        sides: 5,
        radius: 70,
        fill: 'red',
        stroke: 'black',
        strokeWidth: 4,
        visible: false,
      });

      // add the shape to the layer
      layer.add(pentagon);

      // add the layer to the stage
      stage.add(layer);

      // add button event bindings
      document.getElementById('show').addEventListener(
        'click',
        function () {
          pentagon.show();
        },
        false
      );

      document.getElementById('hide').addEventListener(
        'click',
        function () {
          pentagon.hide();
        },
        false
      );
    </script>
  </body>
</html>

 

saalek110

Well-Known Member

HTML5 Canvas Pointer Events Tutorial​


مختصات محل لمس را می گوید.
 

saalek110

Well-Known Member
لینک بازی snake:



این شخص ، یکی از بازیهایش snake بود که ویندوزی بود ، من دکمه اضافه کردم تا بشه در گوشی بازی کرد.

فایل html آن که دکمه های من هم داخلش است:
HTML:
<html>
    <head>
        <title>Snake Game</title>
        <script src="script.js"></script>
    </head>
    <body>
        <div class="gameArea">
            <canvas id="myCanvas" width="800" height="800"></canvas>
        </div>
 
 
 
<center>
<p id="the_heart"></p>
<table><tr><td>
<button type="button" style=" font-size:35px; height:80px; width:140px" onclick="accelerate(4)">left</button>
</td>
<td>
<button type="button" style=" font-size:12px; height:150px; width:100px" onclick="accelerate(1)">up</button>
<br>
<button type="button" style=" font-size:12px; height:150px; width:100px" onclick="accelerate(3)">down</button>
</td>
<td>
<button type="button" style=" font-size:35px; height:80px; width:140px" onclick="accelerate(2)">right</button>
</td></tr>
</table>
</center>
    </body>
</html>

فایل بازی snake:
اون تابع accelerate که ته فایل است را من اضافه کردم، پاسخ به دکمه های من است...باقی کدها از نویسنده است.

جناب PratikGarai. تشکر می کنم ازش.

.Hello PratikGarai, my friend, thank for game


JavaScript:
var canvas = undefined;
var canvasContext = undefined;

const size = 20;
const rows = 40;
const cols = 40;

const col1 = "#79e332";      // body
const col2 = "#0e3fed";      // head
const col3 = "#ed460e";      // food

var Snake = {
    head_x : undefined,
    head_y : undefined,
    body : undefined,
    direction : 1,
    food_x : undefined,
    food_y : undefined
}

var direction_mapper = {
    1 : [0, -1],        // up
    2 : [1, 0],         // right
    3 : [0, 1],         // down
    4 : [-1, 0]         // left
}

const generateFood = () => {
    Snake.food_x = Math.floor(Math.random()*rows);
    Snake.food_y = Math.floor(Math.random()*cols);
}

const start = () => {
    canvas = document.getElementById("myCanvas");
    canvasContext = canvas.getContext("2d");
    init();
    mainLoop();
}

const init = () => {
    generateFood();

    canvasContext
        .clearRect(
            0,
            0,
            canvas.width,
            canvas.height
        );

    canvasContext.fillStyle = "black";
    canvasContext
        .fillRect(
            0,
            0,
            canvas.width,
            canvas.height
        );
 
    Snake.head_x = 20;
    Snake.head_y = 20;
    Snake.body = [];
 
    drawPixel(col2, Snake.head_x,Snake.head_y);
    drawPixel(col3, Snake.food_x,Snake.food_y);
 
    setTimeout(()=> console.log("Started"), 1000);
}

const update = () => {

    Snake.body.unshift([Snake.head_x, Snake.head_y]);

    Snake.head_x = Snake.head_x+direction_mapper[Snake.direction][0];
    Snake.head_y = Snake.head_y+direction_mapper[Snake.direction][1];

    if(Snake.head_x>=rows)
        Snake.head_x = 0;
    if(Snake.head_y>=cols)
        Snake.head_y = 0;
    if(Snake.head_x<0)
        Snake.head_x = rows-1;
    if(Snake.head_y<0)
        Snake.head_y = cols-1;

    Snake.body.forEach(bod => {
        if(Snake.head_x==bod[0] && Snake.head_y==bod[1])
        {
            console.log("Lost!");
            init();
        }
    });

    if(Snake.head_x==Snake.food_x && Snake.head_y==Snake.food_y)
    {
        generateFood();
    }
    else
    {
        Snake.body.pop();
    }
}

const draw = () => {
    canvasContext.fillStyle = "black";
    canvasContext
        .fillRect(
            0,
            0,
            canvas.width,
            canvas.height
        );

    drawPixel(col2, Snake.head_x,Snake.head_y);

    Snake
        .body
        .forEach(bod => {
            drawPixel(col1, bod[0], bod[1]);
        });

    drawPixel(col3, Snake.food_x,Snake.food_y);
}

const drawPixel = (col, x, y) => {
    canvasContext.fillStyle = col;
    canvasContext.fillRect(x*size+1,y*size+1,size-1,size-1);
}

const keyHandler = (e) => {
    // W : 119
    // S : 115
    // A : 97
    // D : 100
    switch(e.keyCode)
    {
        case 119 :
            Snake.direction = 1;
            break;
        case 115 :
            Snake.direction = 3;
            break;
        case 97 :
            Snake.direction = 4;
            break;
        case 100 :
            Snake.direction = 2;
            break;
    }
}

const mainLoop = () => {
    update();
    draw();
    window.setTimeout(mainLoop, 100);
}

document.addEventListener('DOMContentLoaded', start);
document.addEventListener("keypress", keyHandler, true);

function accelerate(n) {
    if (n==1)    Snake.direction = 1;
    if (n==2)    Snake.direction = 2;
    if (n==3)    Snake.direction = 3;
    if (n==4)    Snake.direction = 4;
 }

شرح ساختار برنامه:
در این بازی برخلاف اون بازی w3school کلاسی وجود ندارد ولی یک چیزی شبیه اون هست ،
در زبان سی بهش میگن استراکت. احتمالادر جاوا اسکریپت هم اسمش همینه. من زیاد با جاوا اسکریپت آشنا نیستم. من بیشتر سی و php کار کردم.
JavaScript:
var Snake = {
    head_x : undefined,
    head_y : undefined,
    body : undefined,
    direction : 1,
    food_x : undefined,
    food_y : undefined
}
در کد بالا ، متغیر snake که همون مار است ، یک سری صفات داره...در اون بازی wschool کلاسهای hero و component صفات را نگه داری می کردند. خوب حالا می بینیم که استراکت هم یک راه این کار است.
در استراکت بالا می بینیم که مختصات food هم هست. food یا غذا همون هدفی است که مار به سمتش می رود.

در بحث بازی w3school دیدیم با تابع setinterval تابع updategamearea یک تابع هر ۲۰ میلی سکند اجرا میشد ، شاید اینجا settimeout داره این کارو میکنه. و تابع update و تابع draw ، در این بازی مجموعا ، احتمالا مشابه تابع updategamearea بازی w3school است. من فعلا بررسی نکردم ، فعلا فقط حدس می زنم. باید کدها از هم جدا بشوند و امتحان بشوند. تابع استارت را ببینید:

JavaScript:
const start = () => {
    canvas = document.getElementById("myCanvas");
    canvasContext = canvas.getContext("2d");
    init();
    mainLoop();
}

تابع start است که کانواس را شروع کرده ، و تابع init را صدا می زنه و تابع mainoop را صدا می زنه ، تابع mainloop را نگاه کنید:

JavaScript:
const mainLoop = () => {
    update();
    draw();
    window.setTimeout(mainLoop, 100);
}

لوپ یعنی چرخش ، شاید چرخش در تابع لوپ انجام میشه که به نوبت تابع های update و draw را صدا می زنه... اینها حدس های من بود....شاید کمک کنه.

اگر یک قالب ساده تر برای بازی می خواستید ، این بازی شاید از اون بازی w3school ساختار ساده تری داشته باشه.
کلاسی درش نیست ولی اون استراکت نقش کلاس را بازی می کند. در این بازی کلا دو تا شخصیت بیشتر نداریم ، مار و غذایش... پس لزومی هم نداشته کلاس بیاید چند هزار شی را مشخصاتش را حفظ کند. همون استراکت را شریکی دارند مار و غذا استفاده می کنند.

من ، عوض نوشتن بازی ، شده ام تحلی گر بازی مردم... مثل کسانی که فیلم تحلیل می کنند ، من بازی تحلیل می کنم.

فایل کدش ۱۶۰ خط است. دستورات کانواس را که بلدید..اگر بلد نیستید در تاپیک کانواس نگاه کنید.
 
آخرین ویرایش:

saalek110

Well-Known Member

در لینک بالا می خوام کمی بازی را دستکاری کنم.

اون عدد ۱۰۰ در تابع mainloop اگر زیاد بشه حرکت مار آهسته تر میشه. یکی از کارهای من ساده سازی بازیهاست.
فکر کنم ۱۵۰ خوب باشه تا هم وقت فکر کردن داشته باشیم و هم زیاد منتظر رسیدن مار نمانیم.
خوبی این بازیهای کند اینه که وقت داریم به مسائل زندگی فکر کنیم.
 
آخرین ویرایش:

saalek110

Well-Known Member
قالب خیلی ساده برای ساخت بازیهای کانواس:


نویسنده خوب این بازی :rose: :rose: در یک پوشه دیگر ، اسکلت بازی را گذاشته بود.
دیگه لازم نیست ، من بیام اجزای بازی را خارج کنم.


Thank you PratikGarai, so much:clap::)
I was worried because my friends needed a game structure

نوشتم من نگران بودم چون دوستانم یک ساختار بازی نیاز داشتند.

کد زیر برای بررسی ساختار بازی بهتره.. من که اجرا کردم فقط یک مربع آبی بود که به طور مایل حرکت می کرد.

کد را هم که نگاه کنید در تابع update ، فقط افزایش x و y است. دو خط بیشتر نیست... و تابع draw هم پاک کردن صفحه و رسم اون مربع است.

پس می توانید کد زیر را برای ساخت بازیهای خود بردارید.


من نگران یک سری بودم ، چون قالب بازی w3school کمی پیچیده بود..ولی حالا با داشتن این قالب ، خیالم راحت شد.
JavaScript:
"use strict";

var Game = {
    canvas : undefined,
    canvasContext : undefined,
    rectangle_x : 0,
    rectangle_y : 0,
    rectangle_h : 10,
    rectangle_w : 10
};

Game.start = () => {
    Game.canvas = document.getElementById("myCanvas");
    Game.canvasContext = Game.canvas.getContext("2d");
    Game.mainLoop();
}

Game.update = () => {
    Game.rectangle_x += 1;
    Game.rectangle_y += 1;
}

Game.draw = () => {
    Game
        .canvasContext
        .clearRect(
            0,
            0,
            Game.canvas.width,
            Game.canvas.height
        );

    Game.canvasContext.fillStyle = "blue";
    Game
        .canvasContext
        .fillRect(
            Game.rectangle_x,
            Game.rectangle_y,
            Game.rectangle_w,
            Game.rectangle_h
        );
}

Game.mainLoop = () => {
    Game.update();
    Game.draw();
    window.setTimeout(Game.mainLoop, 1000/60);
}

document.addEventListener('DOMContentLoaded', Game.start);
 
آخرین ویرایش:

saalek110

Well-Known Member
ساختار PratikGarai همراه با دو کلاس:

این هم سومین کار PratikGarai عزیز است.

دو کلاس قهرمان و شی دارد کد زیر.
یک سری تابع کلاس قهرمان دارد ، به نامهای مینی جامپ ، جامپ ، و سوپر جامپ.

از همون ساختار قبلی استفاده کرده ، ولی کلاس قهرمان و شی دارد.

پس دوستانی که نیاز به چنین ساختاری همراه با کلتس بودند ، استفاده کنند.





HTML:
<html>
    <head>
        <title>Dino Game</title>
        <script src="basescript.js"></script>
    </head>
    <body>
        <div class="gameArea">
            <canvas id="myCanvas" width="500" height="400"></canvas>
        </div>
    </body>
</html>

JavaScript:
var canvas = undefined;
var canvasContext = undefined;

let datas;
let height;
let width;
let player;
let obstacle;
let env;
let isObs = 0;
const obsNames = ['wall', 'cacti', 'bird', 'trench'];

const obsVel = 20;
const gravity = 5;

class Environment {
    constructor()
    {
        this.obstacle = undefined;
    }

    update(){
        if(isObs==0)
        {
            this.obstacle = new Obstacle(obsNames[Math.floor(Math.random()*obsNames.length)]);
            isObs = 1;
        }
        this.obstacle.x -= obsVel;
        if((this.obstacle.x+this.obstacle.w/2)<0){
            isObs = 0;
        }
    }

    draw(){
        this.obstacle.draw();
    }
}

class Player {
    constructor(base_x, base_y, w, h, env) {
        this.bx = base_x;
        this.by = base_y;
        this.w = w;
        this.h = h;
        this.v = 0;
        this.env = env;
    }

    draw() {
        canvasContext.fillStyle = "cyan";
        canvasContext.fillRect(this.bx-this.w/2, this.by-this.h, this.w, this.h);
    }

    move() {
        if(this.v==0)
        {
            switch(this.env.obstacle.type)
            {
                case 'wall':
                    if(this.env.obstacle.x>=this.bx+25 && this.env.obstacle.x<=this.bx+100)
                        this.superJump();
                    break;
                case 'cacti':
                    if(this.env.obstacle.x>=this.bx+25 && this.env.obstacle.x<=this.bx+100)
                        this.jump();
                    break;
                case 'trench':
                    if(this.env.obstacle.x>=this.bx+50 && this.env.obstacle.x<=this.bx+100)
                        this.miniJump();
                    break;
                case 'bird':
                    if(this.env.obstacle.x>=this.bx+50 && this.env.obstacle.x<=this.bx+100 && this.h==50)
                        this.h -= 15;
                    if(this.env.obstacle.x<this.bx-25 && this.h!=50)
                        this.h += 15;
            }
        }
        if(this.v>0 && this.by+this.v>height-100){
            this.v = 0;
            this.by = height-100;
        }
        else {
            this.by += this.v;
            this.v += gravity;
        }
    }

    miniJump() {
        this.v = -25;
    }

    jump() {
        this.v = -30;
    }

    superJump() {
        this.v = -40;
    }
}

class Obstacle {
    constructor(type) {
        const d = datas[type];
        this.x = d.x;
        this.y = d.y;
        this.w = d.w;
        this.h = d.h;
        this.color = d.color;
        this.type = type;
    }

    draw() {
        canvasContext.fillStyle = this.color;
        canvasContext.fillRect(this.x-this.w/2, this.y-this.h/2, this.w, this.h);
    }
}

function start()
{
    canvas = document.getElementById("myCanvas");
    canvasContext = canvas.getContext("2d");
    height = canvas.height;
    width = canvas.width;

    datas = {
        'bird' : {
            x : width,
            y : height-160,
            w : 40,
            h : 40,
            color : "black"
        },
        'wall' : {
            x : width,
            y : height-140,
            w : 40,
            h : 80,
            color : "brown"
        },
        'cacti' : {
            x : width,
            y : height-120,
            w : 40,
            h : 40,
            color : "green"
        },
        'trench' : {
            x : width,
            y : height-90,
            w : 40,
            h : 20,
            color : "blue"
        }
    }

    env = new Environment();
    player = new Player(30, height-100, 40, 50, env);
    mainLoop();
}

function drawGround () {
    canvasContext.fillStyle = "black";
    canvasContext.beginPath();
    canvasContext.moveTo(0, height-100);
    canvasContext.lineTo(width, height-100);
    canvasContext.stroke();
}

function update()
{
    env.update();
    player.move();
}

function draw()
{
    canvasContext.fillStyle = "white";
    canvasContext.fillRect(0,0, width, height);
    drawGround();
    player.draw();
    env.draw();
}

function mainLoop()
{
    update();
    draw();
    window.setTimeout(mainLoop, 1000/27);
}

document.addEventListener('DOMContentLoaded', start);
 
آخرین ویرایش:

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

بالا