想法來源 javascript
出於練習看到這篇文章 沒有什麼難度 效果以下,接下來會用pixijs講解如何實現html
建立應用及舞臺java
HTML部分只建立標籤引入 pixi.min.js 便可:數組
<script src="pixi.min.js"></script>
javascript:app
let app = new PIXI.Application({ width: 350, height: 526 }) document.body.appendChild(app.view);
運行後,頁面是一個黑色區域,沒錯這是正常的。接下來添加精靈dom
建立精靈函數
首先加載圖片使用PIXI自帶loader,來實現圖片預加載,圖片所有加載完畢後再執行其它操做oop
定義圖片列表:spa
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:code
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;
這時會發現,飛船 飛出舞臺以外了 ,接下來,檢測是否到舞臺邊緣 有兩種方式能夠檢測
一、自定義一個容器的寬高,來判斷是否到該容器邊緣
二、直接判該該精靈是否到舞臺邊緣
直接就用第二種了,
// 判斷是否到舞臺邊緣 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({ width: 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>