最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

利用pixi.js制作簡(jiǎn)單的跑酷小游戲

 更新時(shí)間:2022年07月18日 15:52:15   作者:shellingfordly  
PixiJS 提供一個(gè)適用于所有設(shè)備的快速輕量級(jí) 2D 庫(kù)。PixiJS 具有完整的 WebGL 支持,并且可以無(wú)縫地回退到 HTML5 的畫布。 本文將使用pixi.js制作簡(jiǎn)單的跑酷小游戲,感興趣的可以嘗試一下

前言

此項(xiàng)目使用pixi.js和vue實(shí)現(xiàn),部分素材來(lái)自愛(ài)給網(wǎng),本項(xiàng)目?jī)H作用于 pixi.js 學(xué)習(xí)用途,侵權(quán)立刪。

項(xiàng)目地址

shellingfordly/pixi-games

demo地址

pixi-games

初始化項(xiàng)目

使用vite初始化項(xiàng)目

pnpm create vite my-vue-app

安裝pixi.js和pixi-tweener

pixi-tweener一個(gè)做過(guò)度動(dòng)畫的開(kāi)源庫(kù)

pnpm i pixi.js pixi-tweener

主要邏輯

useParkour

此函數(shù)用于創(chuàng)建pixi app,將場(chǎng)景,障礙物,人物添加到app中

  • containerRef canvas的容器
  • gameStart 開(kāi)始游戲
  • start 開(kāi)始狀態(tài)
  • score 分?jǐn)?shù)
  • hp 血量
export function useParkour() {
  const containerRef = ref();
  const app = new Application({
    width: BODY_HEIGHT,
    height: BODY_WIDTH,
    backgroundColor: 0xffffff,
  });
  const start = ref(false);

  Tweener.init(app.ticker);

  const container = new Container();
  app.stage.addChild(container);

  const player = new Player();
  const { scene, runScene, stopScene } = useScene();
  const { trap, runHurdle, score, hp } = useHurdle();
  container.addChild(player);
  container.addChild(scene);
  container.addChild(trap);
  container.sortChildren();

  runScene();

  function gameStart() {
    start.value = true;
    player.play();
    const timer = setTimeout(() => {
      runHurdle(player);
      clearTimeout(timer);
    }, 1000);
  }

  watch(hp, (value) => {
    if (value === 0) {
      player.stop();
      stopScene();
      start.value = false;
    }
  });

  onMounted(() => {
    if (containerRef.value) containerRef.value.appendChild(app.view);
  });

  return { containerRef, app, score, hp, gameStart, start };
}

useScene

此函數(shù)用于創(chuàng)建天空、地面場(chǎng)景

加載天空、地面紋理,創(chuàng)建平鋪精靈(TilingSprite),這個(gè)TilingSprite類比較方便做場(chǎng)景的移動(dòng)

創(chuàng)建ticker遞減精靈的x坐標(biāo)實(shí)現(xiàn)場(chǎng)景移動(dòng)

export function useScene() {
  const loader = new Loader();
  const scene = new Container();
  scene.height = 130;
  scene.zIndex = 1;
  const ticker = new Ticker();

  loader
    .add("footer", FooterImg)
    .add("sky", SkyImg)
    .load(() => {
      const footer = new TilingSprite(
        loader.resources.footer.texture as Texture,
        BODY_HEIGHT,
        130
      );
      footer.y = BODY_WIDTH - 130;
      footer.zIndex = 2;

      const sky = new TilingSprite(
        loader.resources.sky.texture as Texture,
        BODY_HEIGHT,
        BODY_WIDTH - 80
      );
      sky.tileScale.y = 0.6;
      sky.zIndex = 1;
      sky.y = -30;

      scene.addChild(footer);
      scene.addChild(sky);
      scene.sortChildren();

      const sceneTicker = () => {
        footer.tilePosition.x -= 3;
        sky.tilePosition.x -= 3;
      };

      ticker.add(sceneTicker);
    });

  function runScene() {
    ticker.start();
  }

  function stopScene() {
    ticker.stop();
  }

  return { scene, runScene, stopScene };
}

useHurdle

此函數(shù)用于創(chuàng)建障礙物

和創(chuàng)建場(chǎng)景其實(shí)差不多,只是障礙物是普通的精靈類(Sprite),創(chuàng)建ticker移動(dòng)其x

在移動(dòng)時(shí)做和人物的碰撞檢測(cè),如果碰撞則減少生命值,如果沒(méi)有則增加分?jǐn)?shù)

export function useHurdle() {
  const loader = new Loader();
  const trap = new Container();
  const ticker = new Ticker();
  const textures: Texture[] = [];
  let player: Sprite | null = null;
  const hp = ref(100);
  const score = ref(0);
  let timer: NodeJS.Timer;

  trap.zIndex = 3;

  loader.add("trap", TrapImg).load((_, resources) => {
    TrapTexturePosition.forEach((position) => {
      const t = new Texture(
        resources.trap.texture as any,
        new Rectangle(...position)
      );
      textures.push(t);
    });
  });

  loader.load(() => {
    timer = setInterval(() => {
      const index = Math.floor(Math.random() * 2) + 1;
      const item = new Sprite(textures[index]);
      item.width = 80;
      item.height = 40;
      item.x = BODY_HEIGHT;
      item.y = BODY_WIDTH - 120;
      trap.addChild(item);
      let scoreFlag = true;
      let hpFlag = true;
      let isHit = false;

      function itemTicker() {
        item.x -= 8;

        if (player && !isHit) {
          isHit = hitTestRectangle(player, item);
          if (hpFlag && isHit) {
            hp.value -= 10;
            hpFlag = false;
            if (hp.value === 0) stopGame();
          } else if (scoreFlag && item.x < player.x) {
            score.value++;
            scoreFlag = false;
          }
        }

        if (item.x < -item.width) {
          ticker.remove(itemTicker);
          trap.removeChild(item);
        }
      }

      ticker.add(itemTicker);
    }, 2000);
  });

  function runHurdle(target: Sprite) {
    player = target;
    ticker.start();
  }

  function stopGame() {
    timer && clearInterval(timer);
    ticker.stop();
  }

  return { trap, runHurdle, score, hp };
}

Player

玩家類:實(shí)現(xiàn)跑動(dòng)、上跳、滑鏟、入場(chǎng)的效果

通過(guò)變換Sprite的texture實(shí)現(xiàn)跑動(dòng)效果,監(jiān)聽(tīng)鍵盤事件,上鍵時(shí)減y,下鍵時(shí)更換滑鏟紋理

export class Player extends Sprite {
  defaultY = BODY_WIDTH - 160;
  textures: Texture[] = [];
  status: "run" | "jump" | "slide" = "run";
  ticker = new Ticker();

  constructor() {
    super();
    this.width = 80;
    this.height = 80;
    this.x = -120;
    this.y = this.defaultY;
    this.zIndex = 10;
    this.loader();
    this.watchEvent();
  }

  private loader() {
    const loader = new Loader();
    loader.add("player", PlayerImg).load((_, resources) => {
      PlayerTexturePosition.forEach((position, i) => {
        const texture = new Texture(
          resources.player.texture as any,
          new Rectangle(...position)
        );
        this.textures.push(texture);
      });
    });
  }

  private watchEvent() {
    document.addEventListener("keydown", this.keydown);
    document.addEventListener("keyup", this.keyup);
  }

  private clearEvent() {
    document.removeEventListener("keyup", this.keydown);
    document.removeEventListener("keydown", this.keyup);
  }

  private keydown = (e: any) => {
    if (e.code === "ArrowUp") {
      this.status = "jump";
      if (this.y === this.defaultY) {
        Tweener.add(
          { target: this, duration: 0.3, ease: Easing.easeInOutQuint },
          { y: this.y - 120 }
        );
      }
    } else if (e.code === "ArrowDown") {
      this.status = "slide";
      this.texture = this.textures[10];
    }
  };

  private keyup = () => {
    this.status = "run";
  };

  stop() {
    this.ticker.stop();
    this.clearEvent();
  }

  play() {
    this.ticker.autoStart = true;
    const runTicker = () => {
      this.down();
      this.entrance();
      if (this.status === "run") this.run();
      else if (this.status === "jump") this.jump();
    };
    this.ticker.add(runTicker);
  }

  // 跑
  run() {
    this.texture = this.textures[Math.floor(Date.now() / 100) % 8];
  }

  jump() {
    this.texture = this.textures[(Math.floor(Date.now() / 100) % 5) + 11];
  }

  // 下落
  down() {
    if (this.y < this.defaultY) {
      this.status = "jump";
      this.y += 5;
    } else {
      if (this.status === "jump") {
        this.status = "run";
      }
    }
  }

  // 入場(chǎng)
  entrance() {
    if (this.x < 120) this.x += 5;
  }
}

到此這篇關(guān)于利用pixi.js制作簡(jiǎn)單的跑酷小游戲的文章就介紹到這了,更多相關(guān)pixi.js跑酷游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

尼勒克县| 中宁县| 方山县| 东阿县| 离岛区| 楚雄市| 蒙山县| 四平市| 边坝县| 长顺县| 辉南县| 海晏县| 尚志市| 定边县| 那坡县| 湟中县| 江源县| 治县。| 密山市| 平原县| 嘉鱼县| 临洮县| 无极县| 手机| 分宜县| 祥云县| 清苑县| 池州市| 汾西县| 印江| 武宣县| 阿克苏市| 青阳县| 大埔区| 聂拉木县| 班戈县| 萍乡市| 峨眉山市| 泸溪县| 廊坊市| 湟中县|