pixi(入门)
Pixi教程
目录:
介绍
安装
安装 Pixi
创建舞台(stage)和画布(renderer)
Pixi 精灵
把图像加载进纹理缓存
显示精灵(sprite)
使用普通的javaScript Img对象或canvas创建一个精灵
给已经加载的文件设定一个名字
监视加载进程
一些关于Pixi的加载器的其他知识
使用别名
一些关于加载的其他知识
定位精灵
大小和比例
角度
从精灵图(雪碧图)中获取精灵
使用一个纹理贴图集
加载纹理贴图集
从一个纹理贴图集创建精灵
移动精灵
使用速度属性
游戏状态
键盘响应
将精灵分组
局部位置和全局位置
使用 ParticleContainer 分组精灵
用 Pixi 绘制几何图形
矩形
圆形
椭圆
圆角矩形
线
多边形
显示文本
碰撞检测
一个 hitTestRectangle 函数
实例学习: 宝物猎人
限制移动范围
创建游戏场景
创建地牢,门,猎人和宝箱
创建泡泡怪(这个怪物好萌)
创建血条
创建提示文本
用 setup 函数初始化游戏
开始游戏
移动猎人
移动泡泡怪们
碰撞检测
处理到达出口和结束游戏
一些关于精灵的其他知识
展望未来
i. Hexi
ii. BabylonJS
支持这个工程
介绍
安装
安装 Pixi
<script src="pixi.min.js"></script>
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Hello World</title> </head> <script src="pixi/pixi.min.js"></script> <body> <script type="text/javascript"> let type = "WebGL" if(!PIXI.utils.isWebGLSupported()){ type = "canvas" } PIXI.utils.sayHello(type) </script> </body> </html>
PixiJS 4.4.5 - * canvas * http://HdhCmsTestpixijs测试数据/ ???
创建Pixi应用和 舞台
//Create a Pixi Application let app = new PIXI.Application({width: 256, height: 256}); //Add the canvas that Pixi automatically created for you to the HTML document document.body.appendChild(app.view);
let app = new PIXI.Application({ width: 256, // default: 800 height: 256, // default: 600 antialias: true, // default: false transparent: false, // default: false resolution: 1 // default: 1 } );
forceCanvas: true,
app.renderer.backgroundColor = 0x061639;
app.renderer.autoResize = true; app.renderer.resize(512, 512);
app.renderer.view.style.position = "absolute";app.renderer.view.style.display = "block";app.renderer.autoResize = true;app.renderer.resize(window.innerWidth, window.innerHeight);
<style>* {padding: 0; margin: 0}</style>
Pixi 精灵
app.stage
用一个单图像文件创建。
用一个 雪碧图 来创建。雪碧图是一个放入了你游戏所需的所有图像的大图。
从一个纹理贴图集中创建。(纹理贴图集就是用JSON定义了图像大小和位置的雪碧图)
将图片加载到纹理缓存中
PIXI.utils.TextureCache["images/cat.png"];
let texture = PIXI.utils.TextureCache["images/anySpriteImage.png"]; let sprite = new PIXI.Sprite(texture);
PIXI.loader .add("images/anyImage.png") .load(setup); function setup() { //This code will run when the loader has finished loading the image }
let sprite = new PIXI.Sprite( PIXI.loader.resources["images/anyImage.png"].texture );
PIXI.loader .add("images/anyImage.png") .load(setup); function setup() { let sprite = new PIXI.Sprite( PIXI.loader.resources["images/anyImage.png"].texture ); }
PIXI.loader .add("images/imageOne.png") .add("images/imageTwo.png") .add("images/imageThree.png") .load(setup);
PIXI.loader .add([ "images/imageOne.png", "images/imageTwo.png", "images/imageThree.png" ]) .load(setup);
显示精灵
app.stage.addChild(cat);
//Create a Pixi Application let app = new PIXI.Application({ width: 256, height: 256, antialias: true, transparent: false, resolution: 1 } ); //Add the canvas that Pixi automatically created for you to the HTML document document.body.appendChild(app.view); //load an image and run the `setup` function when it's done PIXI.loader .add("images/cat.png") .load(setup); //This `setup` function will run when the image has loaded function setup() { //Create the cat sprite let cat = new PIXI.Sprite(PIXI.loader.resources["images/cat.png"].texture); //Add the cat to the stage app.stage.addChild(cat); }
app.stage.removeChild(anySprite)
anySprite.visible = false;
使用别名
let TextureCache = PIXI.utils.TextureCache
let texture = TextureCache["images/cat.png"];
//Aliases let Application = PIXI.Application, loader = PIXI.loader, resources = PIXI.loader.resources, Sprite = PIXI.Sprite; //Create a Pixi Application let app = new Application({ width: 256, height: 256, antialias: true, transparent: false, resolution: 1 } ); //Add the canvas that Pixi automatically created for you to the HTML document document.body.appendChild(app.view); //load an image and run the `setup` function when it's done loader .add("images/cat.png") .load(setup); //This `setup` function will run when the image has loaded function setup() { //Create the cat sprite let cat = new Sprite(resources["images/cat.png"].texture); //Add the cat to the stage app.stage.addChild(cat); }
一些关于加载的其他知识
let base = new PIXI.BaseTexture(anyImageObject), texture = new PIXI.Texture(base), sprite = new PIXI.Sprite(texture);
let base = new PIXI.BaseTexture.fromCanvas(anyCanvasElement),
anySprite.texture = PIXI.utils.TextureCache["anyTexture.png"];
PIXI.loader .add("catImage", "images/cat.png") .load(setup);
let cat = new PIXI.Sprite(PIXI.loader.resources.catImage.texture);
PIXI.loader.on("progress", loadProgressHandler);
PIXI.loader .add([ "images/one.png", "images/two.png", "images/three.png" ]) .on("progress", loadProgressHandler) .load(setup); function loadProgressHandler() { console.log("loading"); } function setup() { console.log("setup"); }
loading loading loading setup
function loadProgressHandler(loader, resource) { /*...*/ }
PIXI.loader .add([ "images/one.png", "images/two.png", "images/three.png" ]) .on("progress", loadProgressHandler) .load(setup); function loadProgressHandler(loader, resource) { //Display the file `url` currently being loaded console.log("loading: " + resource.url); //Display the percentage of files currently loaded console.log("progress: " + loader.progress + "%"); //If you gave your files names as the first argument //of the `add` method, you can access them like this //console.log("loading: " + resource.name); } function setup() { console.log("All files loaded"); }
loading: images/one.png progress: 33.333333333333336% loading: images/two.png progress: 66.66666666666667% loading: images/three.png progress: 100% All files loaded
add(name, url, optionObject, callbackFunction)
.add('key', 'http://...', function () {}) .add('http://...', function () {}) .add('http://...')
.add({ name: 'key2', url: 'http://...' }, function () {}) .add({ url: 'http://...' }, function () {}) .add({ name: 'key3', url: 'http://...' onComplete: function () {} }) .add({ url: 'https://...', onComplete: function () {}, crossOrigin: true })
.add([ {name: 'key4', url: 'http://...', onComplete: function () {} }, {url: 'http://...', onComplete: function () {} }, 'http://...' ]);
精灵位置
cat.x = 96; cat.y = 96;
function setup() { //Create the `cat` sprite let cat = new Sprite(resources["images/cat.png"].texture); //Change the sprite's position cat.x = 96; cat.y = 96; //Add the cat to the stage so you can see it app.stage.addChild(cat); }
sprite.position.set(x, y)
大小和比例
cat.width = 80; cat.height = 120;
function setup() { //Create the `cat` sprite let cat = new Sprite(resources["images/cat.png"].texture); //Change the sprite's position cat.x = 96; cat.y = 96; //Change the sprite's size cat.width = 80; cat.height = 120; //Add the cat to the stage so you can see it app.stage.addChild(cat); }
cat.scale.x = 0.5; cat.scale.y = 0.5;
cat.scale.x = 2; cat.scale.y = 2;
cat.scale.set(0.5, 0.5);
旋转
cat.rotation = 0.5;
cat.anchor.x = 0.5; cat.anchor.y = 0.5;
cat.anchor.set(x, y)
cat.pivot.set(32, 32)
从精灵图(雪碧图)中创建精灵【为了防止与精灵混淆,我在之后的译文中都将采用雪碧图这一译法】
loader .add("images/tileset.png") .load(setup);
function setup() { //Create the `tileset` sprite from the texture let texture = TextureCache["images/tileset.png"]; //Create a rectangle object that defines the position and //size of the sub-image you want to extract from the texture //(`Rectangle` is an alias for `PIXI.Rectangle`) let rectangle = new Rectangle(192, 128, 64, 64); //Tell the texture to use that rectangular section texture.frame = rectangle; //Create the sprite from the texture let rocket = new Sprite(texture); //Position the rocket sprite on the canvas rocket.x = 32; rocket.y = 32; //Add the rocket to the stage app.stage.addChild(rocket); //Render the stage renderer.render(stage); }
let rectangle = new PIXI.Rectangle(x, y, width, height);
let rectangle = new Rectangle(192, 128, 64, 64); texture.frame = rectangle;
let rocket = new Sprite(texture);
使用一个纹理贴图集
"blob.png": { "frame": {"x":55,"y":2,"w":32,"h":24}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":24}, "sourceSize": {"w":32,"h":24}, "pivot": {"x":0.5,"y":0.5} },
加载纹理贴图集
loader .add("images/treasureHunter.json") .load(setup);
从已经加载的纹理贴图集中创建精灵
使用 TextureCache :
let texture = TextureCache["frameId.png"], sprite = new Sprite(texture);
如果你是使用的 loader 来加载纹理贴图集, 使用loader的 resources :
let sprite = new Sprite( resources["images/treasureHunter.json"].textures["frameId.png"] );
要创建一个精灵需要输入太多东西了! 所以我建议你给纹理贴图集的 textures 对象创建一个叫做 id 的别名,象是这样:
let id = PIXI.loader.resources["images/treasureHunter.json"].textures;
let sprite = new Sprite(id["frameId.png"]);
//Define variables that might be used in more //than one function let dungeon, explorer, treasure, id; function setup() { //There are 3 ways to make sprites from textures atlas frames //1. Access the `TextureCache` directly let dungeonTexture = TextureCache["dungeon.png"]; dungeon = new Sprite(dungeonTexture); app.stage.addChild(dungeon); //2. Access the texture using throuhg the loader's `resources`: explorer = new Sprite( resources["images/treasureHunter.json"].textures["explorer.png"] ); explorer.x = 68; //Center the explorer vertically explorer.y = app.stage.height / 2 - explorer.height / 2; app.stage.addChild(explorer); //3. Create an optional alias called `id` for all the texture atlas //frame id textures. id = PIXI.loader.resources["images/treasureHunter.json"].textures; //Make the treasure box using the alias treasure = new Sprite(id["treasure.png"]); app.stage.addChild(treasure); //Position the treasure next to the right edge of the canvas treasure.x = app.stage.width - treasure.width - 48; treasure.y = app.stage.height / 2 - treasure.height / 2; app.stage.addChild(treasure); }
explorer.y = app.stage.height / 2 - explorer.height / 2;
<!doctype html> <meta charset="utf-8"> <title>Make a sprite from a texture atlas</title> <body> <script src="pixi/pixi.min.js"></script> <script> //Aliases let Application = PIXI.Application, Container = PIXI.Container, loader = PIXI.loader, resources = PIXI.loader.resources, TextureCache = PIXI.utils.TextureCache, Sprite = PIXI.Sprite, Rectangle = PIXI.Rectangle; //Create a Pixi Application let app = new Application({ width: 512, height: 512, antialias: true, transparent: false, resolution: 1 } ); //Add the canvas that Pixi automatically created for you to the HTML document document.body.appendChild(app.view); //load a JSON file and run the `setup` function when it's done loader .add("images/treasureHunter.json") .load(setup); //Define variables that might be used in more //than one function let dungeon, explorer, treasure, door, id; function setup() { //There are 3 ways to make sprites from textures atlas frames //1. Access the `TextureCache` directly let dungeonTexture = TextureCache["dungeon.png"]; dungeon = new Sprite(dungeonTexture); app.stage.addChild(dungeon); //2. Access the texture using throuhg the loader's `resources`: explorer = new Sprite( resources["images/treasureHunter.json"].textures["explorer.png"] ); explorer.x = 68; //Center the explorer vertically explorer.y = app.stage.height / 2 - explorer.height / 2; app.stage.addChild(explorer); //3. Create an optional alias called `id` for all the texture atlas //frame id textures. id = PIXI.loader.resources["images/treasureHunter.json"].textures; //Make the treasure box using the alias treasure = new Sprite(id["treasure.png"]); app.stage.addChild(treasure); //Position the treasure next to the right edge of the canvas treasure.x = app.stage.width - treasure.width - 48; treasure.y = app.stage.height / 2 - treasure.height / 2; app.stage.addChild(treasure); //Make the exit door door = new Sprite(id["door.png"]); door.position.set(32, 0); app.stage.addChild(door); //Make the blobs let numberOfBlobs = 6, spacing = 48, xOffset = 150; //Make as many blobs as there are `numberOfBlobs` for (let i = 0; i < numberOfBlobs; i++) { //Make a blob let blob = new Sprite(id["blob.png"]); //Space each blob horizontally according to the `spacing` value. //`xOffset` determines the point from the left of the screen //at which the first blob should be added. let x = spacing * i + xOffset; //Give the blob a random y position //(`randomInt` is a custom function - see below) let y = randomInt(0, app.stage.height - blob.height); //Set the blob's position blob.x = x; blob.y = y; //Add the blob sprite to the stage app.stage.addChild(blob); } } //The `randomInt` helper function function randomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } </script> </body>
let x = spacing * i + xOffset; blob.x = x;
let y = randomInt(0, stage.height - blob.height); blob.y = y;
randomInt(lowestNumber, highestNumber)
let randomNumber = randomInt(1, 10);
function randomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; }
移动精灵
function setup() { //Start the game loop by adding the `gameLoop` function to //Pixi's `ticker` and providing it with a `delta` argument. app.ticker.add(delta => gameLoop(delta)); } function gameLoop(delta){ //Move the cat 1 pixel cat.x += 1; }
cat.x += 1;
cat.x += 1 + delta;
function gameLoop() { //Call this `gameLoop` function on the next screen refresh //(which happens 60 times per second) requestAnimationFrame(gameLoop); //Move the cat cat.x += 1; } //Start the loop gameLoop();
//Aliases let Application = PIXI.Application, Container = PIXI.Container, loader = PIXI.loader, resources = PIXI.loader.resources, TextureCache = PIXI.utils.TextureCache, Sprite = PIXI.Sprite, Rectangle = PIXI.Rectangle; //Create a Pixi Application let app = new Application({ width: 256, height: 256, antialias: true, transparent: false, resolution: 1 } ); //Add the canvas that Pixi automatically created for you to the HTML document document.body.appendChild(app.view); loader .add("images/cat.png") .load(setup); //Define any variables that are used in more than one function let cat; function setup() { //Create the `cat` sprite cat = new Sprite(resources["images/cat.png"].texture); cat.y = 96; app.stage.addChild(cat); //Start the game loop app.ticker.add(delta => gameLoop(delta)); } function gameLoop(delta){ //Move the cat 1 pixel cat.x += 1; //Optionally use the `delta` value //cat.x += 1 + delta; }
使用速度属性
cat.vx = 0; cat.vy = 0;
function setup() { //Create the `cat` sprite cat = new Sprite(resources["images/cat.png"].texture); cat.y = 96; cat.vx = 0; cat.vy = 0; app.stage.addChild(cat); //Start the game loop app.ticker.add(delta => gameLoop(delta)); } function gameLoop(delta){ //Update the cat's velocity cat.vx = 1; cat.vy = 1; //Apply the velocity values to the cat's //position to make it move cat.x += cat.vx; cat.y += cat.vy; }
游戏状态
//Set the game state state = play; //Start the game loop app.ticker.add(delta => gameLoop(delta)); function gameLoop(delta){ //Update the current game state: state(delta); } function play(delta) { //Move the cat 1 pixel to the right each frame cat.vx = 1 cat.x += cat.vx; }
//Define any variables that are used in more than one function let cat, state; function setup() { //Create the `cat` sprite cat = new Sprite(resources["images/cat.png"].texture); cat.y = 96; cat.vx = 0; cat.vy = 0; app.stage.addChild(cat); //Set the game state state = play; //Start the game loop app.ticker.add(delta => gameLoop(delta)); } function gameLoop(delta){ //Update the current game state: state(delta); } function play(delta) { //Move the cat 1 pixel to the right each frame cat.vx = 1 cat.x += cat.vx; }
键盘移动
function keyboard(keyCode) { let key = {}; key.code = keyCode; key.isDown = false; key.isUp = true; key.press = undefined; key.release = undefined; //The `downHandler` key.downHandler = event => { if (event.keyCode === key.code) { if (key.isUp && key.press) key.press(); key.isDown = true; key.isUp = false; } event.preventDefault(); }; //The `upHandler` key.upHandler = event => { if (event.keyCode === key.code) { if (key.isDown && key.release) key.release(); key.isDown = false; key.isUp = true; } event.preventDefault(); }; //Attach event listeners window.addEventListener( "keydown", key.downHandler.bind(key), false ); window.addEventListener( "keyup", key.upHandler.bind(key), false ); return key; }
let keyObject = keyboard(asciiKeyCodeNumber);
keyObject.press = () => { //key object pressed }; keyObject.release = () => { //key object released };
//Define any variables that are used in more than one function let cat, state; function setup() { //Create the `cat` sprite cat = new Sprite(resources["images/cat.png"].texture); cat.y = 96; cat.vx = 0; cat.vy = 0; app.stage.addChild(cat); //Capture the keyboard arrow keys let left = keyboard(37), up = keyboard(38), right = keyboard(39), down = keyboard(40); //Left arrow key `press` method left.press = () => { //Change the cat's velocity when the key is pressed cat.vx = -5; cat.vy = 0; }; //Left arrow key `release` method left.release = () => { //If the left arrow has been released, and the right arrow isn't down, //and the cat isn't moving vertically: //Stop the cat if (!right.isDown && cat.vy === 0) { cat.vx = 0; } }; //Up up.press = () => { cat.vy = -5; cat.vx = 0; }; up.release = () => { if (!down.isDown && cat.vx === 0) { cat.vy = 0; } }; //Right right.press = () => { cat.vx = 5; cat.vy = 0; }; right.release = () => { if (!left.isDown && cat.vy === 0) { cat.vx = 0; } }; //Down down.press = () => { cat.vy = 5; cat.vx = 0; }; down.release = () => { if (!up.isDown && cat.vx === 0) { cat.vy = 0; } }; //Set the game state state = play; //Start the game loop app.ticker.add(delta => gameLoop(delta)); } function gameLoop(delta){ //Update the current game state: state(delta); } function play(delta) { //Use the cat's velocity to make it move cat.x += cat.vx; cat.y += cat.vy }
给精灵分组
//The cat let cat = new Sprite(id["cat.png"]); cat.position.set(16, 16); //The hedgehog let hedgehog = new Sprite(id["hedgehog.png"]); hedgehog.position.set(32, 32); //The tiger let tiger = new Sprite(id["tiger.png"]); tiger.position.set(64, 64);
let animals = new Container();
animals.addChild(cat); animals.addChild(hedgehog); animals.addChild(tiger);
app.stage.addChild(animals);
console.log(animals.children)//Displays: Array [Object, Object, Object]
animals.position.set(64, 64);
console.log(animals.width); //Displays: 112 console.log(animals.height); //Displays: 112
animals.width = 200; animals.height = 200;
局部位置和全局位置
console.log(cat.x);//Displays: 16
parentSprite.toGlobal(childSprite.position)
console.log(animals.toGlobal(cat.position));//Displays: Object {x: 80, y: 80...};
cat.parent.toGlobal(cat.position);
tiger.getGlobalPosition().x tiger.getGlobalPosition().y
sprite.toLocal(sprite.position, anyOtherSprite)
tiger.toLocal(tiger.position, hedgehog).x tiger.toLocal(tiger.position, hedgehog).y
使用 ParticleContainer 分组精灵
let superFastSprites = new PIXI.particles.ParticleContainer();
let superFastSprites = new ParticleContainer(maxSize, properties, batchSize, autoResize);
let superFastSprites = new ParticleContainer( size, { rotation: true, alphaAndtint: true, scale: true, uvs: true } );
用Pixi绘制几何图形
矩形
let rectangle = new Graphics();
rectangle.beginFill(0x66CCFF);
rectangle.lineStyle(4, 0xFF3300, 1);
rectangle.drawRect(x, y, width, height);
rectangle.endFill();
let rectangle = new Graphics(); rectangle.lineStyle(4, 0xFF3300, 1); rectangle.beginFill(0x66CCFF); rectangle.drawRect(0, 0, 64, 64); rectangle.endFill(); rectangle.x = 170; rectangle.y = 170; app.stage.addChild(rectangle);
圆形
drawCircle(x, y, radius)
let circle = new Graphics(); circle.beginFill(0x9966FF); circle.drawCircle(0, 0, 32); circle.endFill(); circle.x = 64; circle.y = 130; app.stage.addChild(circle);
椭圆
drawEllipse(x, y, width, height);
let ellipse = new Graphics(); ellipse.beginFill(0xFFFF00); ellipse.drawEllipse(0, 0, 50, 20); ellipse.endFill(); ellipse.x = 180; ellipse.y = 130; app.stage.addChild(ellipse);
圆角矩形
drawRoundedRect(x, y, width, height, cornerRadius)
let roundBox = new Graphics(); roundBox.lineStyle(4, 0x99CCFF, 1); roundBox.beginFill(0xFF9933); roundBox.drawRoundedRect(0, 0, 84, 36, 10) roundBox.endFill(); roundBox.x = 48; roundBox.y = 190; app.stage.addChild(roundBox);
线段
let line = new Graphics(); line.lineStyle(4, 0xFFFFFF, 1); line.moveTo(0, 0); line.lineTo(80, 50); line.x = 32; line.y = 32; app.stage.addChild(line);
多边形
let path = [ point1X, point1Y, point2X, point2Y, point3X, point3Y ]; graphicsObject.drawPolygon(path);
let triangle = new Graphics(); triangle.beginFill(0x66FF33); //Use `drawPolygon` to define the triangle as //a path array of x/y positions triangle.drawPolygon([ -32, 64, //First point 32, 64, //Second point 0, 0 //Third point ]); //Fill shape's color triangle.endFill(); //Position the triangle after you've drawn it. //The triangle's x/y position is anchored to its first point in the path triangle.x = 180; triangle.y = 22; app.stage.addChild(triangle);
显示文本
let message = new Text("Hello Pixi!"); app.stage.addChild(message);
message.position.set(54, 96);
let style = new TextStyle({ fontFamily: "Arial", fontSize: 36, fill: "white", stroke: '#ff3300', strokeThickness: 4, dropShadow: true, dropShadowColor: "#000000", dropShadowBlur: 4, dropShadowAngle: Math.PI / 6, dropShadowDistance: 6, });
let message = new Text("Hello Pixi!", style);
message.text = "Text changed!";
message.style = {fill: "black", font: "16px PetMe64"};
message.style = {wordWrap: true, wordWrapWidth: 100, align: center};
@font-face { font-family: "fontFamilyName"; src: url("fonts/fontFile.ttf"); }
碰撞检测
hitTestRectangle(spriteOne, spriteTwo)
if (hitTestRectangle(cat, box)) { //There's a collision } else { //There's no collision }
function play(delta) { //use the cat's velocity to make it move cat.x += cat.vx; cat.y += cat.vy; //check for a collision between the cat and the box if (hitTestRectangle(cat, box)) { //if there's a collision, change the message text //and tint the box red message.text = "hit!"; box.tint = 0xff3300; } else { //if there's no collision, reset the message //text and the box's color message.text = "No collision..."; box.tint = 0xccff99; } }
message.text = "Hit!";
box.tint = 0xff3300;
message.text = "No collision..."; box.tint = 0xccff99;
碰撞检测函数
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; };
实例学习: 宝物猎人
代码结构
//Setup Pixi and load the texture atlas files - call the `setup` //function when they've loaded function setup() { //Initialize the game sprites, set the game `state` to `play` //and start the 'gameLoop' } function gameLoop(delta) { //Runs the current game `state` in a loop and renders the sprites } function play(delta) { //All the game logic goes here } function end() { //All the code that should run at the end of the game } //The game's helper functions: //`keyboard`, `hitTestRectangle`, `contain` and `randomInt`
用 setup 函数初始化游戏
function setup() { //Create the `gameScene` group //Create the `door` sprite //Create the `player` sprite //Create the `treasure` sprite //Make the enemies //Create the health bar //Add some text for the game over message //Create a `gameOverScene` group //Assign the player's keyboard controllers //set the game state to `play` state = play; //Start the game loop app.ticker.add(delta => gameLoop(delta)); }
gameScene = new Container(); app.stage.addChild(gameScene); gameOverScene = new Container(); app.stage.addChild(gameOverScene);
gameOverScene.visible = false;
//Create an alias for the texture atlas frame ids id = resources["images/treasureHunter.json"].textures; //Dungeon dungeon = new Sprite(id["dungeon.png"]); gameScene.addChild(dungeon); //Door door = new Sprite(id["door.png"]); door.position.set(32, 0); gameScene.addChild(door); //Explorer explorer = new Sprite(id["explorer.png"]); explorer.x = 68; explorer.y = gameScene.height / 2 - explorer.height / 2; explorer.vx = 0; explorer.vy = 0; gameScene.addChild(explorer); //Treasure treasure = new Sprite(id["treasure.png"]); treasure.x = gameScene.width - treasure.width - 48; treasure.y = gameScene.height / 2 - treasure.height / 2; gameScene.addChild(treasure);
let numberOfBlobs = 6, spacing = 48, xOffset = 150, speed = 2, direction = 1; //An array to store all the blob monsters blobs = []; //Make as many blobs as there are `numberOfBlobs` for (let i = 0; i < numberOfBlobs; i++) { //Make a blob let blob = new Sprite(id["blob.png"]); //Space each blob horizontally according to the `spacing` value. //`xOffset` determines the point from the left of the screen //at which the first blob should be added let x = spacing * i + xOffset; //Give the blob a random `y` position let y = randomInt(0, stage.height - blob.height); //Set the blob's position blob.x = x; blob.y = y; //Set the blob's vertical velocity. `direction` will be either `1` or //`-1`. `1` means the enemy will move down and `-1` means the blob will //move up. Multiplying `direction` by `speed` determines the blob's //vertical direction blob.vy = speed * direction; //Reverse the direction for the next blob direction *= -1; //Push the blob into the `blobs` array blobs.push(blob); //Add the blob to the `gameScene` gameScene.addChild(blob); }
//Create the health bar healthBar = new PIXI.DisplayObjectContainer(); healthBar.position.set(stage.width - 170, 4) gameScene.addChild(healthBar); //Create the black background rectangle let innerBar = new PIXI.Graphics(); innerBar.beginFill(0x000000); innerBar.drawRect(0, 0, 128, 8); innerBar.endFill(); healthBar.addChild(innerBar); //Create the front red rectangle let outerBar = new PIXI.Graphics(); outerBar.beginFill(0xFF3300); outerBar.drawRect(0, 0, 128, 8); outerBar.endFill(); healthBar.addChild(outerBar); healthBar.outer = outerBar;
healthBar.outer = outerBar;
healthBar.outer.width = 30;
let style = new TextStyle({ fontFamily: "Futura", fontSize: 64, fill: "white" }); message = new Text("The End!", style); message.x = 120; message.y = app.stage.height / 2 - 32; gameOverScene.addChild(message);
开始游戏
function play(delta) { //Move the explorer and contain it inside the dungeon //Move the blob monsters //Check for a collision between the blobs and the explorer //Check for a collision between the explorer and the treasure //Check for a collision between the treasure and the door //Decide whether the game has been won or lost //Change the game `state` to `end` when the game is finsihed }
移动探险者
explorer.x += explorer.vx; explorer.y += explorer.vy;
contain(explorer, {x: 28, y: 10, width: 488, height: 480});
function contain(sprite, container) { let collision = undefined; //Left if (sprite.x < container.x) { sprite.x = container.x; collision = "left"; } //Top if (sprite.y < container.y) { sprite.y = container.y; collision = "top"; } //Right if (sprite.x + sprite.width > container.width) { sprite.x = container.width - sprite.width; collision = "right"; } //Bottom if (sprite.y + sprite.height > container.height) { sprite.y = container.height - sprite.height; collision = "bottom"; } //Return the `collision` value return collision; }
移动怪物
blobs.forEach(function(blob) { //Move the blob blob.y += blob.vy; //Check the blob's screen boundaries let blobHitsWall = contain(blob, {x: 28, y: 10, width: 488, height: 480}); //If the blob hits the top or bottom of the stage, reverse //its direction if (blobHitsWall === "top" || blobHitsWall === "bottom") { blob.vy *= -1; } //Test for a collision. If any of the enemies are touching //the explorer, set `explorerHit` to `true` if(hitTestRectangle(explorer, blob)) { explorerHit = true; } });
let blobHitsWall = contain(blob, {x: 28, y: 10, width: 488, height: 480});
if (blobHitsWall === "top" || blobHitsWall === "bottom") { blob.vy *= -1; }
检测碰撞
if(hitTestRectangle(explorer, blob)) { explorerHit = true; }
if(explorerHit) { //Make the explorer semi-transparent explorer.alpha = 0.5; //Reduce the width of the health bar's inner rectangle by 1 pixel healthBar.outer.width -= 1; } else { //Make the explorer fully opaque (non-transparent) if it hasn't been hit explorer.alpha = 1; }
if (hitTestRectangle(explorer, treasure)) { treasure.x = explorer.x + 8; treasure.y = explorer.y + 8; }
处理到达出口和结束游戏
if (hitTestRectangle(treasure, door)) { state = end; message.text = "You won!"; }
if (healthBar.outer.width < 0) { state = end; message.text = "You lost!"; }
state = end;
function gameLoop(delta){ //Update the current game state: state(delta); }
function end() { gameScene.visible = false; gameOverScene.visible = true; }
查看更多关于js pixi框架 极其详细到位(入门)-----转载的详细内容...