对象没有出现在画布主体载荷上

时间:2018-08-11 21:37:30

标签: javascript canvas

我一直在尝试为我的太空侵略者游戏编写启动部分。但是,当身体加载我的一个对象(startbtn变量)时,它没有出现在画布上。

以下是我游戏的代码

    <html>
    <head>
         <title>Space Invaders</title>
    </head>
    <body onload="startGame()">
    <script type="text/javascript">

    var startbtn;
    function startGame(){
            startbtn = new compenent(50, 20, "blue", 120, 10);
            myGameArea.start();
    }

    var myGameArea = {

        canvas: document.createElement("canvas"),
        start: function(){
            this.canvas.width = 420;
            this.canvas.height = 220;
            ctx = this.context = this.canvas.getContext("2d");
            document.body.insertBefore(this.canvas, 
            document.body.childNodes[0]);
                ctx.font="35px Verdena";
                ctx.fillText("Welcome to Space Invaders",10,50);



            },
            clear : function(){
                this.context.clearRect(0, 0, this.canvas.width , 
                this.canvas.height);


            }

    }

    function compenent(width, height, color, x, y){
        this.width = width;
        this.height = height;
        this.x = x;
        this.y = y;
        this.update = function(){
            ctx = myGameArea.context;
            ctx.fillStyle = color;
            ctx.fillRect(this.x, this.y, this.width, this.height);
        }
    }

    function updateGame(){
        myGameArea.clear();
        startbtn.update();
    }
    </script>
    </body>
    </html>

如果有人可以帮助我,那就太好了。

1 个答案:

答案 0 :(得分:1)

主要问题是从未调用updateGame()。您可以将其添加到startGame()函数中,以在设置画布后运行。完成此操作后,蓝色框显示但不显示文本。原因是因为myGameArea.clear();清除了myGameArea.start函数中绘制的文本。删除myGameArea.clear();会导致:

var startbtn;

function startGame() {
  startbtn = new compenent(50, 20, "blue", 120, 10);
  myGameArea.start();
  updateGame();
}

var myGameArea = {
  canvas: document.createElement("canvas"),
  start: function() {
    this.canvas.width = 420;
    this.canvas.height = 220;
    ctx = this.context = this.canvas.getContext("2d");
    document.body.insertBefore(this.canvas,
      document.body.childNodes[0]);
    ctx.font = "35px Verdena";
    ctx.fillText("Welcome to Space Invaders", 10, 50);
  },
  clear: function() {
    this.context.clearRect(0, 0, this.canvas.width,
      this.canvas.height);
  }
}

function compenent(width, height, color, x, y) {
  this.width = width;
  this.height = height;
  this.x = x;
  this.y = y;
  this.update = function() {
    ctx = myGameArea.context;
    ctx.fillStyle = color;
    ctx.fillRect(this.x, this.y, this.width, this.height);
  }
}

function updateGame() {
  //myGameArea.clear();
  startbtn.update();
}

startGame(); // moved from body.onload

但是,在这一点上,很明显,在制作功能齐全的太空侵略者游戏时,存在一些潜在的设计障碍。您正在使用的w3schools教程正在尝试基本的entity-component system,但是对于初学者来说这可能会造成混淆,因此,如果没有其他问题,我鼓励您在其他教程中进行浏览。

随着示例的发展,动画具有基本组成部分:

  1. 初始化例程(创建对象并为所有内容设置初始位置)
  2. 更新例程(重新定位对象,计算碰撞和损坏)
  3. 渲染例程(绘制框架)

该初始化运行一次,或者在某些情况下每当需要重置动画(或游戏级别)时运行。更新和渲染例程每秒运行多次,并共同构成主动画循环(每个动画循环每帧执行一次,因此它们实质上是同一“动画循环”功能的一部分):

              ----------------
              |              |
              v              |
init -----> update -----> render

这要求每个例程对他们的任务负责,别无其他。每次渲染调用都应清除屏幕,然后绘制每个可见对象。例如,init函数不应包含任何渲染代码。

还值得一提:绘制的所有内容都是一个对象(或实体)。 W3schools的教程可帮助您入门,但是如何区分button组件和spaceInvader组件呢?您可以将objects/classes完全分开作为初学者。

下一个抽象级别是一个状态,每个状态都有自己的init --> update --> render函数:

 ----------------------------------------    ---------------------------------------- 
 |             menu state               |    |             game state               |
 |                                      |    |                                      |
 |                 ----------------     |    |                 ----------------     |
 |                 |              |     |    |                 |              |     |
 |                 v              |     |    |                 v              |     |
 |   init -----> update -----> render   |    |   init -----> update -----> render   |
 ----------------------------------------    ----------------------------------------

这一切对您的示例意味着什么?您正在尝试通过一些文本和按钮来设置菜单状态以开始游戏。管理一堆游戏状态可能会变得非常复杂,因此Phaser之类的图形库提供了built-in state management systems。如果希望或推迟问题,可以设计一个,然后使用变量或布尔值确定您所处的状态。对于初学者,我建议以单一状态工作,然后在必要时添加更多状态。换句话说,请考虑简化或跳过菜单状态,而改用游戏状态,直到准备好使用状态为止。

制作动画的另一个可能具有挑战性的方面是处理鼠标事件。您如何知道单击按钮的时间?至少,您需要使用event listener and some math。图书馆可以do it for you

无论哪种方式,在JS中循环going都需要requestAnimationFrame或(不太可能/不推荐)setInterval。从MDN网络文档中查看一些basic examples

我希望这可以为您提供一条前进的道路,并突出显示您可能需要研究的一些领域,然后再采用当前的方法。