javascript - 我如何在 Canvas 上创建 "Choose your Own Adventure game"?

标签 javascript html canvas branch

刚接触编码,我决定使用我从网上提取的 6 张图片创建一个交互式的点击式冒险游戏。

我将第一张图片添加到 Canvas 上,并在 Canvas 上的图像前面放了一个很酷的小动画,但现在我遇到了一个大问题。

整个游戏是在一个 Canvas 上完成的,有多个,以及点击事件的分支。

示例:在标题屏幕上,用户可以选择“开始游戏”或“致谢名单”(作为可点击文本完成)。

如果用户选择“开始游戏”,画面会跳转到2号图,再次点击后,2号图会变模糊,旁白文字会出现在用户面前。然而,如果他们选择“致谢名单”,屏幕将转为另一张图片,即 3 号图片。在 3 号图片上,致谢名单以缓慢的自动向上滚动方式显示。

我在网上查过这个,但我通常会在我要找的东西的大致范围内得到答案,我发现的一些结果是开关案例(没有太多经验,更不用说进行分支开关了case),用于交互式故事讲述、事件处理程序等的 Undum 框架。

我对 Javascript 或 canvas 的工作不多,在我着手这个项目之前,我认为最好直接提出我的项目问题并获得经验丰富的意见,并将项目逐个分解并形成某种攻击方法。

知道这个项目将如何运作,你们会推荐我使用哪些资源或编码方法?这个“分支”动画树会是什么样子?

到目前为止,这是我的代码:

-- HTML --

<html>
<head>
    <title>Detective</title>
  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
  <%= javascript_include_tag  'application', 'data-turbolinks-track' => true %>
  <%= csrf_meta_tags %>
  <!--   load in the jquery -->
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.js">
    </script>
</head>
<body>

</body>
</html>

-- CSS --

body{
  background:#000;
  width: 100%;
  height: 100%;
  overflow:hidden;
}

canvas{
/*the code below this activates the canvas border, turn it on to visibly see how big the canvas is */

/*  border: 1px solid red;*/  

    position: absolute;
    top:0;
    bottom: 0;
    left: 0;
    right: 0;
    margin:auto;
    display: none;
}

@font-face{
  font-family: 'Betty Noir Regular';
  src: url('/assets/bettynoir.ttf');
}

-- JS --

var canvas = document.createElement('canvas'); 
var w = canvas.width = 800,
    h = canvas.height = 400;
var c = canvas.getContext('2d');

var img = new Image();
img.src = 'http://oi41.tinypic.com/4i2aso.jpg';

var background = new Image();
background.src = "https://i2.wp.com/i2.listal.com/image/2669447/500full.jpg";



var position = {x : 410, y : 238};

document.body.appendChild(canvas);

var particles = [];
var random = function(min, max){
  return Math.random()*(max-min)*min;
};

function Particle(x, y){
  this.x = x;
  this.y = y;
  this.velY = -2;
  this.velX = (random(1, 10)-5)/10;
  this.size = random(3, 5)/10;
  this.alpha = 1;
  this.update = function(){
    this.y += this.velY;
    this.x += this.velX;
    this.velY *= 0.99;
    if(this.alpha < 0){this.alpha = 0;}
    c.globalAlpha = this.alpha;
    c.save();
    c.translate(this.x, this.y);
    c.scale(this.size, this.size);
    c.drawImage(img, -img.width/2, -img.height/2);
    c.restore();
    this.alpha *= 0.96;
    this.size += 0.02;//  
  };
}

var draw = function(){
  var p = new Particle(position.x, position.y);
  particles.push(p);

  // draw the background image before you draw the particles
  c.drawImage(background,160,0);
  c.font="20px Betty Noir Regular";
  c.fillStyle = "white";
  c.fillText("Start",500,200);

  c.font="20px Betty Noir Regular";
  c.fillStyle = "white";
  c.fillText("Credits",500,250);

  while(particles.length > 500) particles.shift();

  for(var i = 0; i < particles.length; i++)
  {
    particles[i].update();
  }
};



setInterval(draw, 3500/60);


$(document).ready(function() {
 $("canvas").fadeIn(7000);
});

$(document).ready(function() {
    $("#noir-song").get(0).play();
});

最佳答案

看起来不错。

我想说摆脱 setInterval 因为从长远来看它只会给你带来问题。由于您拥有粒子系统,因此某些设备可能无法很好地处理负载,因为 setInterval 不会检查最后的渲染作业是否已完成,因为它会在您可以结束的调用堆栈上进行调用溢出调用堆栈并导致应用程序崩溃。

使用window.requestAnimationFrame(functionName)

如下

// your main render function
function draw(){
    // do your stuff
    requestAnimationFrame(draw); // needs to be call for every new frame
}
draw(); // start it all happening.

requestAnimationFrame 对渲染负载敏感,会尽量保持均匀的帧率 1/60th 或 60fps。如果可能,与显示器刷新率同步,这样您就不会出现失真。它是为动画设计的(因此得名),所以试试吧。

我会问“为什么要使用 jquery?”您将使用支持 canvas 和 jquery 的浏览器,除了对旧版浏览器的支持之外,没有任何实际好处,只会增加页面的复杂性并增加加载时间。您只将它用于准备好页面,所以看起来有点浪费。移除 jQuery 并使用 onload 替换 ready 调用

window.addEventListener("load",function(){
   // your startup up code
});

创建粒子的更好方法。使用 new 很慢,尤其是当您创建同一事物的多个实例时。

尝试

// define the function to update once. In the new Particle() version
// javascript actually has to create this function every time you create a particle.
// This makes it quicker.
var particleUpdate = function(){
    this.y += this.velY;
    this.x += this.velX;
    this.velY *= 0.99;
    // a quicker way to clamp a value
    // if(this.alpha < 0){this.alpha = 0;} // done in the following line
    c.globalAlpha = Math.max(0,this.alpha); // returns the max value so while 
                                            // alpha > 0 it returns alpha
                                            // when alpha < 0 returns max 
                                            // which is 0;
    //c.save();  // dont need this here do it outside the loop that renders
                 // the particles. Save and restore are expensive in  terms
                 // of GPU performance and should be avoided if possible. 
    // the translate and scale can be done in one call halving the time
    // to do the same thing
    //c.translate(this.x, this.y);
    //c.scale(this.size, this.size);
    // use setTransform does the same as translate and scale but in one step
    c.setTransform(this.size,0,0,this.size,this.x,this.y)
    c.drawImage(img, -img.width/2, -img.height/2);
    // c.restore(); see above
    this.alpha *= 0.96;
    this.size += 0.02;//  
};
var createParticle = function(x,y){
    return {
        x:x,
        y:y,
        velY:-2,
        velX:(random(1, 10)-5)/10,
        size:random(3, 5)/10,
        alpha = 1,
        update:particleUpdate,
    }
}

然后创建

particles.push(createParticle(position.x, position.y));

更新和剔除就像您已经在做的那样,只需将保存和恢复添加到循环之外。获取“particles.length”也比直接变量慢。所以重写循环如下

  var len = particles.length
  c.save()
  for(var i = 0; i < len; i++){
       particles[i].update();
  }
  c.restore();

在这种情况下不会有太大区别,因为没有发生太多事情。但是随着您追求越来越多的 fx,每帧性能的提升将成为一个主要问题。尽早学习有效的方法会有帮助。

关于javascript - 我如何在 Canvas 上创建 "Choose your Own Adventure game"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33879265/

相关文章:

javascript - 在 html5 中使用 javascript/jQuery 制作类似 Soundcoud Player 的波形

javascript - 如何使用 rxjs 的 sum 运算符?

javascript - util 函数直接导出 vs util 类

javascript - 将单选按钮的值发送到 Canvas 元素

php - 将碰撞元素并排放置

javascript - HTML DOM 和 jQuery DOM 在一行简单的代码中?

javascript - 在 JavaScript 中获取对象的属性

javascript - 通过调用 Web 服务从 JavaScript 上传文件

php - 如何使用从数据库创建的动态下拉列表来构建 MySQL 查询

javascript - IE 在 Canvas 上调用 toDataUrl 时抛出安全错误