PIXI 太空玉兔游戏(6)

想法来源 

出于练习看到这篇文章   没有什么难度  效果如下,接下来会用pixijs讲解如何实现

 

创建应用及舞台

HTML部分只创建标签引入 pixi.min.js  即可:

<script src="pixi.min.js"></script>

javascript:

 let app = new PIXI.Application({
     350,
    height: 526
  })
  document.body.appendChild(app.view); 

  

运行后,页面是一个黑色区域,没错这是正常的。接下来添加精灵

创建精灵

   

首先加载图片使用PIXI自带loader,来实现图片预加载,图片全部加载完毕后再执行其它操作

定义图片列表:

  var imgList = [
    "img/bg.jpg",
    "img/bg1.jpg",
    "img/food21.png",
    "img/food2.png",
    "img/icon.png",
    "img/player.png",
    "img/heart.png",
  ]

  

是用loader预加载图片,也可以监听加载进度onprogress:

   PIXI.loader
      .add(imgList)
       .load(function () {
// 图片素在记载完毕后,创建精灵 bgimg = new PIXI.Sprite(PIXI.loader.resources["img/bg.jpg"].texture); })

  

把精灵添加到舞台

app.stage.addChild(bgimg);

  

背景图片滚动效果

  原理如图,创建两个精灵,一个在可见区域,一个在可见区域上边或者下边,操作背景移动 ,当背景移动区域大于背景图片高度,重新绘制。

可以见图,方向是从上往下运动的

通过中间变量:

var bgDistance = 0; // 获取移动y值大小

var bgHeight = 背景图片高度; // 获取背景图片高度来 判断bgDistance移动大小是否,超过背景图片高度,超过重新渲染


背景图片移动向下飞船向前行驶,使用PIXI ticker

tips:bgDistance 变量在上边已声明默认:0
app.ticker.add(function (delta) {
           // 背景图片1位置
          bgimg.x = 0;
          bgimg.y = bgDistance - bgHeight;
           // 背景图片2位置
          bgimg1.x = 0;
          bgimg1.y = bgDistance;

          if(bgDistance >= bgHeight){
            bgloop = 0;
          }
          bgDistance  = ++bgloop;
        })

  

会看到背景在移动,接下来在页面添加飞船,操作跟添加背景图片一样,创建一个精灵添加到舞台中:

这时会看到飞船出现在太空中,飞船有些怪怪的,接下来大小及位置修改

        player.scale.x = 0.5;
        player.scale.y = 0.5;

        player.x = (app.view.width - player.width)/2;
        player.y = app.view.height - player.height -100;

  

scale 进行缩放

app.view.width/height 获取舞台的宽高,

player.width/height  获取当前容器或是精灵所占的大小

 接下来,让飞船移动,通过键盘   上下左右来控制 及监听事件 keydown 

document.addEventListener("keydown", function (event) {
//    alert(event.keyCode)
    switch (event.keyCode) {
      case 37:

        player.vx = -5;
        break;
      case 38:
        player.vy = -5;
        break;
      case 39:
        player.vx = 5;
        break;
      case 40:
        player.vy = 5;
        break;
    }

  }, false)


  document.addEventListener("keyup", function () {
    player.vx = 0;
    player.vy = 0;
  })

  

键盘事件写完后,在ticker控制改变飞船位置

player.x += player.vx;
player.y += player.vy;

这时会发现,飞船 飞出舞台之外了 ,接下来,检测是否到舞台边缘 有两种方式可以检测
1、自定义一个容器的宽高,来判断是否到该容器边缘
2、直接判该该精灵是否到舞台边缘

直接就用第二种了,
   // 判断是否到舞台边缘
          if(player.x<=0){
            player.x = 0;
          }else if( player.x >= bgimg.width- player.width){
            player.x = bgimg.width- player.width;
          }
           // 同理, y的判断 也是一样的。。。

  

靠近边缘,不会出舞台外边;

接下来考虑,随机掉月饼有两种类型的月饼

 function randomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  

每个随机玉兔位置应该为:

var randomType = Math.floor(Math.random()*2 +1);
    return {
      rabbitType : randomInt(1, 2),
      x: randomInt(1,app.view.width),
      y: 0,
speed:randomInt(1,4), // 向下移动速度
isHas: false // 是否存在舞台中
}
}

  

在舞台中,显示玉兔,创建精灵并把精灵放到舞台上 ,让精灵从上往下移动使用ticker 对y ++操作 ,当玉兔跟月饼相碰是,

精灵销毁 ,销毁,销毁! 当精灵到屏幕最下方是,也要做销毁处理。

月饼下实际上就是对数组操作,当到底部在数组中移除操作

定义存放数组


var ybArry = []; // 存放月饼
var imgOjbArry = []; // 存放图片对象,把每个创建的精灵添加的舞台上

在ticker随机调用数组函数 ,数组里边最多存放五个元素。

// 处理月饼下路 假定 一直值显示五个 月饼
if(Math.random() > 0.9 && ybArry && ybArry.length < 5){
var randPoint = randomRabbit();
ybArry.push(randPoint);
}

对每个随机生成的坐标y ,进行++ 操作,数组中每个元素都会有下路效果

  for(var i = 0; i < ybArry.length; i++){
            ybArry[i].y += ybArry[i].speed;
          }

  

跟随机月饼数,创建图片精灵,让图片运动

          // 根据随机数组创建精灵
          for(var j = 0; j< ybArry.length; j++){
            if(ybArry[j].isHas == false){
              var sprite = new PIXI.Sprite(
                  PIXI.loader.resources["img/food"+ybArry[j].rabbitType+".png"].texture
              );
              ybArry[j].isHas = true;
              imgOjbArry.push(sprite);
              app.stage.addChild(sprite);

            }
          }

  

把数组月饼中的y 赋值给图片精灵坐标

   for(var k  = 0; k < imgOjbArry.length; k++){
            imgOjbArry[k].x = ybArry[k].x;
            imgOjbArry[k].y =  ybArry[k].y;

            if(imgOjbArry[k].y >= app.view.height){
              imgOjbArry[k].destroy();
              ybArry.splice(k, 1);
              imgOjbArry.splice(k, 1);

            }
          }

  

舞台就会显示精灵运动,细心会看到,随机产生不一样的图。根据不同图片,碰撞那个加分那个结束。自己定义;

碰撞检测实现:(官网的函数copy)

//The `hitTestRectangle` function
function hitTestRectangle(r1, r2) {

  //Define the variables we'll need to calculate
  let hit, combinedHalfWidths, combinedHalfHeights, vx, vy;

  //hit will determine whether there's a collision
  hit = false;

  //Find the center points of each sprite
  r1.centerX = r1.x + r1.width / 2; 
  r1.centerY = r1.y + r1.height / 2; 
  r2.centerX = r2.x + r2.width / 2; 
  r2.centerY = r2.y + r2.height / 2; 

  //Find the half-widths and half-heights of each sprite
  r1.halfWidth = r1.width / 2;
  r1.halfHeight = r1.height / 2;
  r2.halfWidth = r2.width / 2;
  r2.halfHeight = r2.height / 2;

  //Calculate the distance vector between the sprites
  vx = r1.centerX - r2.centerX;
  vy = r1.centerY - r2.centerY;

  //Figure out the combined half-widths and half-heights
  combinedHalfWidths = r1.halfWidth + r2.halfWidth;
  combinedHalfHeights = r1.halfHeight + r2.halfHeight;

  //Check for a collision on the x axis
  if (Math.abs(vx) < combinedHalfWidths) {

    //A collision might be occuring. Check for a collision on the y axis
    if (Math.abs(vy) < combinedHalfHeights) {

      //There's definitely a collision happening
      hit = true;
    } else {

      //There's no collision on the y axis
      hit = false;
    }
  } else {

    //There's no collision on the x axis
    hit = false;
  }

  //`hit` will be either `true` or `false`
  return hit;
};

  

碰撞后的月饼透明度降低,是带花的,五仁的无变化。

          for(var k  = 0; k < imgOjbArry.length; k++){
            imgOjbArry[k].x = ybArry[k].x;
            imgOjbArry[k].y =  ybArry[k].y;
            imgOjbArry[k].rabbitType = ybArry[k].rabbitType;


            // 碰撞检测
            var hitStatus = hitTestRectangle(player, imgOjbArry[k]);
            //  console.log(imgOjbArry[k].rabbitType )
            if(hitStatus){
              if(imgOjbArry[k].rabbitType == 2){
                imgOjbArry[k].alpha = 0.5;
              }
            }


            if(imgOjbArry[k].y >= app.view.height){
              imgOjbArry[k].destroy();
              ybArry.splice(k, 1);
              imgOjbArry.splice(k, 1);

            }

          }

  

其它操作根据需要添加,记录分数或或是关数。

代码如下:勉强看吧,没整理。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>天空</title>
  <script src="lib/pixi.min.js"></script>
</head>
<body>


<script>
  var bgDistance = 0;
  var bgHeight;  // 背景图片高度
  var bgloop = 0;


  var ybArry = [];  // 存放月饼
  var imgOjbArry = [];  // 存放图片对象,把每个创建的精灵添加的舞台上


  let app = new PIXI.Application({
     350,
    height: 526
  });
  document.body.appendChild(app.view);

  // 随机创建玉兔(有两种根据类型来区分)
  //randomRabbit();
  function randomRabbit(){
    var randomType = Math.floor(Math.random()*2 +1);
    return {
      rabbitType : randomInt(1, 2),
      x: randomInt(1,app.view.width),
      y: 0,
      speed:randomInt(1,4), // 向下移动速度
      isHas: false // 是否存在舞台中
    }
  }

   console.log(randomRabbit())

  function randomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  var imgList = [
    "img/bg.jpg",
    "img/food1.png",
    "img/food2.png",
    "img/icon.png",
    "img/player.png",
  ]

  PIXI.loader
      .add(imgList)
      .load(function () {          // 图片素在记载完毕后,创建精灵
        bgimg = new PIXI.Sprite(PIXI.loader.resources["img/bg.jpg"].texture);
        bgimg1 = new PIXI.Sprite(PIXI.loader.resources["img/bg.jpg"].texture);
        player = new PIXI.Sprite(PIXI.loader.resources["img/player.png"].texture);

        player.scale.x = 0.5;
        player.scale.y = 0.5;

        player.x = (app.view.width - player.width) / 2;
        player.y = app.view.height - player.height - 100;

        player.vx = 0;
        player.vy = 0;


        bgHeight = bgimg.height;


        app.stage.addChild(bgimg);
        app.stage.addChild(bgimg1);
        app.stage.addChild(player);


        app.ticker.add(function (delta) {

          bgimg.x = 0;
          bgimg.y = bgDistance - bgHeight;

          bgimg1.x = 0;
          bgimg1.y = bgDistance;

          if (bgDistance >= bgHeight) {
            bgloop = 0;
          }
          bgDistance = ++bgloop;


          player.x += player.vx;
          player.y += player.vy;

          // 判断是否到舞台边缘
          if(player.x<=0){
            player.x = 0;
          }else if( player.x >= bgimg.width- player.width){
            player.x = bgimg.width- player.width;
          }
           // 同理, y的判断 也是一样的。。。


          // 处理月饼下路 假定 一直值显示五个 月饼
          if(Math.random() > 0.9 && ybArry && ybArry.length < 5){
            var randPoint = randomRabbit();
            ybArry.push(randPoint);
          }

          for(var i = 0; i < ybArry.length; i++){
            ybArry[i].y += ybArry[i].speed;
          }

          // 根据随机数组创建精灵
          for(var j = 0; j< ybArry.length; j++){
            if(ybArry[j].isHas == false){
              var sprite = new PIXI.Sprite(
                  PIXI.loader.resources["img/food"+ybArry[j].rabbitType+".png"].texture
              );
              ybArry[j].isHas = true;
              imgOjbArry.push(sprite);
              app.stage.addChild(sprite);

            }
          }

          for(var k  = 0; k < imgOjbArry.length; k++){
            imgOjbArry[k].x = ybArry[k].x;
            imgOjbArry[k].y =  ybArry[k].y;
            imgOjbArry[k].rabbitType = ybArry[k].rabbitType;


            // 碰撞检测
            var hitStatus = hitTestRectangle(player, imgOjbArry[k]);
            //  console.log(imgOjbArry[k].rabbitType )
            if(hitStatus){
              if(imgOjbArry[k].rabbitType == 2){
                imgOjbArry[k].alpha = 0.5;
              }
            }


            if(imgOjbArry[k].y >= app.view.height){
              imgOjbArry[k].destroy();
              ybArry.splice(k, 1);
              imgOjbArry.splice(k, 1);

            }

          }

        })
      });


  document.addEventListener("keydown", function (event) {
//    alert(event.keyCode)
    switch (event.keyCode) {
      case 37:

        player.vx = -5;
        break;
      case 38:
        player.vy = -5;
        break;
      case 39:
        player.vx = 5;
        break;
      case 40:
        player.vy = 5;
        break;
    }

  }, false)


  document.addEventListener("keyup", function () {
    player.vx = 0;
    player.vy = 0;
  })


  //The `hitTestRectangle` function
  function hitTestRectangle(r1, r2) {

    //Define the variables we'll need to calculate
    let hit, combinedHalfWidths, combinedHalfHeights, vx, vy;

    //hit will determine whether there's a collision
    hit = false;

    //Find the center points of each sprite
    r1.centerX = r1.x + r1.width / 2;
    r1.centerY = r1.y + r1.height / 2;
    r2.centerX = r2.x + r2.width / 2;
    r2.centerY = r2.y + r2.height / 2;

    //Find the half-widths and half-heights of each sprite
    r1.halfWidth = r1.width / 2;
    r1.halfHeight = r1.height / 2;
    r2.halfWidth = r2.width / 2;
    r2.halfHeight = r2.height / 2;

    //Calculate the distance vector between the sprites
    vx = r1.centerX - r2.centerX;
    vy = r1.centerY - r2.centerY;

    //Figure out the combined half-widths and half-heights
    combinedHalfWidths = r1.halfWidth + r2.halfWidth;
    combinedHalfHeights = r1.halfHeight + r2.halfHeight;

    //Check for a collision on the x axis
    if (Math.abs(vx) < combinedHalfWidths) {

      //A collision might be occuring. Check for a collision on the y axis
      if (Math.abs(vy) < combinedHalfHeights) {

        //There's definitely a collision happening
        hit = true;
      } else {

        //There's no collision on the y axis
        hit = false;
      }
    } else {

      //There's no collision on the x axis
      hit = false;
    }

    //`hit` will be either `true` or `false`
    return hit;
  };


</script>
</body>
</html>

  


























原文地址:https://www.cnblogs.com/congxueda/p/9356291.html