当前位置: 首页 > 知识库问答 >
问题:

使用pixi.js优化提示的简单游戏

花品
2023-03-14
    null
js lang-js prettyprint-override">(() => {
  // Variables init
  let defaultState = {
    cubesPerDig : 2000,
    cubesIncome : 0,
    total : 0
  };
  let cubeSize = 2, dropSize = window.innerWidth, downSpeed = 5;
  let state,
      digButton, // Button to manually dig
      gameState, // An object containing the state of the game
      cubes, // Array containing all the spawned cubes
      heightIndex, // fake physics
      cubesPerX, // fake physics helper
      playScene; // The gamescene
  
  // App setup
  let app = new PIXI.Application();
  app.renderer.view.style.position = "absolute";
  app.renderer.view.style.display = "block";
  app.renderer.autoResize = true;
  document.body.appendChild(app.view);
  
  // Resize
  function resize() {
    app.renderer.resize(window.innerWidth, window.innerHeight);
  }
  window.onresize = resize;
  resize();
  
  // Hello ! we can talk in the chat.txt file
  
  // Issue : When there are more than ~10k cubes, performance start to drop
  // To test, click the "mine" button about 5-10 times
  
  // Main state
  function play(delta){
    // Animate the cubes according to their states
    let cube;
    for(let c in cubes){
      cube = cubes[c];
      switch(cube.state) {
        case STATE.LANDING:
          // fake physics
          if(!cube.landed){
            if (cube.y < heightIndex[cube.x]) {
              cube.y+= downSpeed;
            }else if (cube.y >= heightIndex[cube.x]) {
              cube.y = heightIndex[cube.x];
              cube.landed = 1;
              heightIndex[cube.x] -= cubeSize;
            }
          }
          break;
        case STATE.CONSUMING:
          if(cube.y > -cubeSize){
            cube.y -= cube.speed;
          }else{
            removeCube(c);
          }
          break;
        case STATE.EXPLODING:
          if(boundings(c)){
            continue;
          }
          cube.x += cube.eDirX;
          cube.y += cube.eDirY;
          break;
      }
    }
    updateUI();
  }
  
  // Game loop
  function gameLoop(delta){
    state(delta);
  }
  
  // Setup variables and gameState
  function setup(){
    state = play;
    digButton = document.getElementById('dig');
    digButton.addEventListener('click', mine);
    playScene = new PIXI.Container();
    gameState = defaultState;
    
    /* User inputs */
    // Mine
    document.getElementById('consume').addEventListener('click', () => {consumeCubes(50)});
    // Manual explode
    let explodeOrigin = null
    document.querySelector('canvas').addEventListener('click', e => {
      if(!explodeOrigin){
        explodeOrigin = {x: e.clientX, y: e.clientY};
      }else{
        explode(explodeOrigin, {x: e.clientX, y: e.clientY});
        explodeOrigin = null;
      }

    });
    window['explode'] = explode;

    heightIndex = {};
    cubesPerX = [];
    // Todo fill with gameState.total cubes
    cubes = [];
    app.ticker.add(delta => gameLoop(delta));
    app.stage.addChild(playScene);
  }
  
  /*
  * UI
  */
  function updateUI(){
    document.getElementById('total').innerHTML = cubes.length;
  }
  
  /*
  * Game logic
  */
  // Add cube when user clicks
  function mine(){
    for(let i = 0; i < gameState.cubesPerDig; i++){
      setTimeout(addCube, 5*i);
    }
  }
  
  // Consume a number of cubes
  function consumeCubes(nb){
      let candidates = _.sampleSize(cubes.filter(c => !c.eDirX), Math.min(nb, cubes.length));
      candidates = candidates.slice(0, nb);
      candidates.map(c => {
        dropCubes(c.x);
        c.state = STATE.CONSUMING;
      });
  }
  const STATE = {
    LANDING: 0,
    CONSUMING: 1,
    EXPLODING: 2
  }
  // Add a cube
  function addCube(){
    let c = new cube(cubeSize);
    let tres = dropSize / cubeSize / 2;
    c.x = window.innerWidth / 2 + (_.random(-tres, tres) * cubeSize);
    c.y = 0//-cubeSize;
    c.speed = _.random(5,8);
    cubes.push(c);
    c.landed = !1;
    c.state = STATE.LANDING;
    if(!cubesPerX[c.x]) cubesPerX[c.x] = [];
    if (!heightIndex[c.x]) heightIndex[c.x] = window.innerHeight - cubeSize;
    cubesPerX[c.x].push(c);
    playScene.addChild(c);
  }
  
  // Remove a cube
  function removeCube(c){
    let cube = cubes[c];
    playScene.removeChild(cube);
    cubes.splice(c,1);
  }
  
  // Delete the cube if offscreen
  function boundings(c){
    let cube = cubes[c];
    if(cube.x < 0 || cube.x + cubeSize > window.innerWidth || cube.y < 0 || cube.y > window.innerHeight)
    {
      removeCube(c);
      return true;
    }
  }
  
  // explode some cubes
  function explode(origin, dest){
    if(dest.x < origin.x){
      dest = [origin, origin = dest][0]; // swap
    }
    var candidates = cubes.filter(c => c.state != STATE.EXPLODING && c.x >= origin.x && c.x <= dest.x && c.y >= origin.y && c.y <= dest.y);
    if(!candidates.length)
      return;
    
    for(let i = origin.x; i <= dest.x; i++){
      dropCubes(i);
    }
    
    candidates.forEach(c => {
      c.explodingSpeed = _.random(5,6);
      c.eDirX = _.random(-1,1,1) * c.explodingSpeed * c.speed;
      c.eDirY = _.random(-1,1,1) * c.explodingSpeed * c.speed;
      c.state = STATE.EXPLODING;
    });
  }
  
  // Drop cubes
  function dropCubes(x){
    heightIndex[x] = window.innerHeight - cubeSize;
    if(cubesPerX[x] && cubesPerX[x].length)
      cubesPerX[x].forEach(c => {
        if(c.state == STATE.EXPLODING) return;
        c.landed = false; c.state = STATE.LANDING;
      });
  }
  
  /*
   * Graphic display
   */
  
  // Cube definition
  function cube(size){
    let graphic = new PIXI.Graphics();
    graphic.beginFill(Math.random() * 0xFFFFFF);
    graphic.drawRect(0, 0, size, size);
    graphic.endFill();
    return graphic;
  }
  
  // Init
  setup();
})()
/* styles */
/* called by your view template */

* {
  box-sizing: border-box;
}
body, html{
  margin: 0;
  padding: 0;
  color:white;
}

#ui{
  position: absolute;
  z-index: 2;
  top: 0;
  width: 0;
  left: 0;
  bottom: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.8.1/pixi.min.js"></script>
<script>PIXI.utils.skipHello();</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
<!-- Click two points to make cubes explode -->
<div id="ui">
    <button id="dig">
      Dig 2k cubes
    </button>
    <button id="consume">
      Consume 50 cubes
    </button>
    <p>
      Total : <span id="total"></span>
    </p>
  </div>

谢谢

共有1个答案

冯星阑
2023-03-14

使用sprite总是比使用图形快(至少在v5之前!)

所以我把你的多维数据集创建函数改成

function cube(size) {
    const sprite = new PIXI.Sprite(PIXI.Texture.WHITE);
    sprite.tint = Math.random() * 0xFFFFFF;
    sprite.width = sprite.height = size;
    return sprite;
}

这提高了我自己的fps

 类似资料:
  • 我想做的是在屏幕上以小半径呈现一些随机位置的img,然后将其增大到一个值,然后减小它,最后将img从屏幕上移除(或者当点击时)--就像这个游戏:http://mouseaccuracy.com/ 我所做的是我在屏幕上每600毫秒生成一次图像,玩家试着点击它们。问题是当屏幕上有2个以上的图像时,fps显著下降。在android实际设备中测试。我在updateCircle函数结束时更新一次状态。游戏循

  • PixiJS 提供一个适用于所有设备的快速轻量级2D库。 PixiJS 渲染器允许每个人在不事先了解WebGL的情况下享受硬件加速的强大功能。 而且它很快、真的很快,适合创建丰富的交互式图形,跨平台应用程序和游戏。 PixiJS具有完整的WebGL支持,并且可以无缝地回退到 HTML5 的画布。 作为一个框架,PixiJS是用于创作交互式内容的绝佳工具,尤其是近年来远离Adobe Flash。 将

  • 本文向大家介绍python使用 __init__初始化操作简单示例,包括了python使用 __init__初始化操作简单示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了python使用 __init__初始化操作。分享给大家供大家参考,具体如下: 运行结果: C:\Python27\python.exe C:/Users/TLCB/PycharmProjects/untitled2/

  • 我可以阻止吃豆人通过墙的一种方式,但他可以通过墙时去在另一个方向,我使用的代码是: } 我需要他在任何方向上都不要穿过墙!提前谢谢

  • 本文向大家介绍php+mysql查询优化简单实例,包括了php+mysql查询优化简单实例的使用技巧和注意事项,需要的朋友参考一下 本文实例分析了php+mysql查询优化的方法。分享给大家供大家参考。具体分析如下: PHP+Mysql是一个最经常使用的黄金搭档,它们俩配合使用,能够发挥出最佳性能,当然,如果配合Apache使用,就更加Perfect了. 因此,需要做好对mysql的查询优化,下面

  • 本文向大家介绍jQuery 写的简单打字游戏可以提示正确和错误的次数,包括了jQuery 写的简单打字游戏可以提示正确和错误的次数的使用技巧和注意事项,需要的朋友参考一下 /*******************************************HTML页面***************************************************/