PIXI 宝物猎人(7)
介绍 ,本实例来自官网
代码结构
打开 treasureHunter.html
文件,你将会看到所有的代码都在一个大的文件里。下面是一个关于如何组织所有代码的概览:
- //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
函数创建了两个被称为gameScene
和 gameOverScene
的 Container
分组。他们都被添加到了舞台上。
- gameScene = new Container();
- app.stage.addChild(gameScene);
- gameOverScene = new Container();
- app.stage.addChild(gameOverScene);
尽管它是在 setup
函数中添加的,但是 gameOverScene
不应在游戏一开始的时候显示,所以它的 visible
属性被初始化为 false
。
- gameOverScene.visible = false;
你会在后面看到,为了在游戏结束之后显示文字,当游戏结束gameOverScene
的 visible
属性会被设置为 true
。
制造泡泡怪们
六个泡泡怪是被循环创建的。每一个泡泡怪都被赋予了一个随机的初始位置和速度。每个泡泡怪的垂直速度都被交替的乘以 1
或者 -1
,这就是每个怪物和相邻的下一个怪物运动的方向都是相反的原因,每个被创建的怪物都被放进了一个名为 blobs
的数组。
- 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);
- }
制作血条
当你玩儿宝藏猎人的时候,你会发现当猎人碰到其中一个敌人时,场景右上角的血条宽度会减少。这个血条是如何被制作的?他就是两个相同的位置的重叠的矩形:一个黑色的矩形在下面,红色的上面。他们被分组到了一个单独的 healthBar
分组。 healthBar
然后被添加到 gameScene
并在舞台上被定位。
- //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 = outerBar;
你可以不这么做,但是为什么不呢?这意味如果你想控制红色 outerBar
的宽度,你可以像这样顺畅的写如下代码:
- healthBar.outer.width = 30;
这样的代码相当整齐而且可读性强,所以我们会一直保留它!
制作消息文字
当游戏结束的时候, “You won!” 或者 “You lost!” 的文字会显示出来。这使用文字纹理制作的,并添加到了 gameOverScene
。因为 gameOverScene
的 visible
属性设为了 false
,当游戏开始的时候,你看不到这些文字。这段代码来自 setup
函数,它创建了消息文字,而且被添加到了 gameOverScene
。
- 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);
控制运动的范围
一个新的地方的是,探险者的运动是被包裹在地牢的墙体之内的。绿色的轮廓表明了探险者运动的边界。
通过一个名为 contain
的自定义函数可以帮助实现。
- contain(explorer, {x: 28, y: 10, width: 488, height: 480});
contain
接收两个参数。第一个是你想控制的精灵。第二个是包含了 x
, y
, width
和height
属性的任何一个对象。在这个例子中,控制对象定义了一个区域,它稍微比舞台小了一点,和地牢的尺寸一样。
这里是实现了上述功能的 contain
函数。函数检查了精灵是否跨越了控制对象的边界。如果超出,代码会把精灵继续放在那个边界上。 contain
函数也返回了一个值可能为"top", "right", "bottom" 或者 "left" 的 collision
变量,取决于精灵碰到了哪一个边界。(如果精灵没有碰到任何边界,collision
将返回 undefined
。)
- 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;
- }
你会在接下来看到 collision
的返回值在代码里是如何让怪物在地牢的顶部和底部之间来回反弹的。
移动怪物
play
函数也能够移动怪物,保持它们在地牢的墙体之内,并检测每个怪物是否和玩家发生了碰撞。如果一只怪物撞到了地牢的顶部或者底部的墙,它就会被设置为反向运动。完成所有这些功能都是通过一个 forEach
循环,它每一帧都会遍历在 blobs
数组里的每一个怪物。
- 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;
- }
- });
你可以在上面这段代码中看到, contain
函数的返回值是如何被用来让怪物在墙体之间来回反弹的。一个名为 blobHitsWall
的变量被用来捕获返回值:
- let blobHitsWall = contain(blob, {x: 28, y: 10, width: 488, height: 480});
blobHitsWall
通常应该是 undefined
。但是如果怪物碰到了顶部的墙,blobHitsWall
将会变成 "top"。如果碰到了底部的墙,blobHitsWall
会变为 "bottom"。如果它们其中任何一种情况为 true,你就可以通过给怪物的速度取反来让它反向运动。这是实现它的代码:
- if (blobHitsWall === "top" || blobHitsWall === "bottom") {
- blob.vy *= -1;
- }
把怪物的 vy
(垂直速度)乘以 -1
就会反转它的运动方向。
检测碰撞
在上面的循环代码里用了 hitTestRectangle
来指明是否有敌人碰到了猎人。
- if(hitTestRectangle(explorer, blob)) {
- explorerHit = true;
- }
如果 hitTestRectangle
返回 true
,意味着发生了一次碰撞,名为 explorerHit
的变量被设置为了 true
。如果 explorerHit
为 true
, play 函数让猎人变为半透明,然后把 health
条减少1像素的宽度。
- 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;
- }
如果 explorerHit
是 false
,猎人的 alpha
属性将保持1,完全不透明。
这段代码实现了上述效果:
- if (hitTestRectangle(explorer, treasure)) {
- treasure.x = explorer.x + 8;
- treasure.y = explorer.y + 8;
- }
PIXI 宝物猎人(7)的更多相关文章
- pixi.js webgl库
分析pixi源码,刚搭建环境gulp+webpack,目前正在看... https://github.com/JsAaron/webgl-demo
- (原)用pixi.js 实现 方块阵点击后原地自转效果
源码 各位,请教一个问题,我这个还有BUG,我是想实现,点击一下可以 停止转动,然后再点一下重新转动.而不是一直加速,有没有什么好办法? PS:问题已经解决,谢谢评论的大神@Antineutrino ...
- 让hammer完美支持Pixi.js - 2D webG库
由于项目改造,采用2D webG的pixi库,那么基于canvas的结构上,事件就是最大的一个问题了 改造的原理很简单,把hammer里面的addEventListeners事件绑定给第三方库代替,事 ...
- 利用pixi.js制作精灵动画
CSS Sprites 技术对于广大的前端工程师来说应该是一点也不陌生.国内开发者昵称为CSS精灵,通过一定的技术手段,让精灵动起来,我称其为精灵动画,那么目前有哪些实现方式 呢?下面让我们详细的聊聊 ...
- pixi.js教程中文版--基础篇
前言 Pixi.js使用WebGL,是一个超快的HTML5 2D渲染引擎.作为一个Javascript的2D渲染器,Pixi.js的目标是提供一个快速的.轻量级而且是兼任所有设备的2D库.提供无缝 C ...
- HTML5骨骼动画Demo | 使用min2d、createjs、pixi播放spine动画
Spine做骨骼动画是比较流行的,使用起来可能相对复杂,但功能毕竟强大,所以市场占有率较大. 在unity.cocos2d.starling中使用spine已经很成熟了,而HTML5这一块可能刚刚起步 ...
- HTML5游戏开发引擎Pixi.js完全入门手册(二)元素对象属性解析
下面,我们来解释下PIXI里面对象的各个属性.. 首先我们来看看这个各个元素对象里面到底长啥样.. alpha Number 整个舞台对象的透明度. buttonMode Boolean 渲染是否作为 ...
- HTML5游戏开发引擎Pixi.js完全入门手册(一)框架简介及框架结构分析,作者思路剖析
前言: 最近无聊在淘宝弄了个小店,打算做一个兼职.遇到一个客户,要我帮忙拷贝一个html5游戏.. 我这人有一个习惯,拿到自己没见过的东西.都会去研究一番.去网上查了下发现,资料都是英文版.感觉极度不 ...
- pixi.js
添加基本文件(库文件) 渲染库 pixi.js pixi.lib.js是pixi.js的子集,依赖class.js,cat.js,event_emiter.js文件 pixi.scroller.js ...
随机推荐
- On the nightmare that is JSON Dates. Plus, JSON.NET and ASP.NET Web API
Ints are easy. Strings are mostly easy. Dates? A nightmare. They always will be. There's different c ...
- Linq学习<三> linq to entity
之前一直用sql选择出数据放在一个集合中,然后再用Linq或者lambda去操作数据,今天学了Linq to entity 才知道原来linq产生是为了Entity.也就是EDM(实体数据模型) 关于 ...
- Position Independent Code (PIC) in shared libraries on x64
E原文地址:http://eli.thegreenplace.net/2011/11/11/position-independent-code-pic-in-shared-libraries-on-x ...
- httpClient-3.1学习笔记
http://hc.apache.org/httpclient-3.x/tutorial.htmlThe general process for using HttpClient consists o ...
- spring深入了解心得
spring 主要核心组件 :Core.上下文(Context) .实体(Bean): spring 主要由两大特色:控制反转(IOC).面向对象(AOP): spring中Core主要用于组建Bea ...
- logback-记录日志
一:根节点<configuration>包含的属性: scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true. scanPeriod: 设置监测配 ...
- Promise超时重新请求
export default function (promiseProducer, params, interval, attemptTimes) { interval = typeof interv ...
- django开发日志配置
做django开发离不开 日志,这用于保存我门的服务器的日志信息,便于开发人员的维护. 直接上代码: 在setting.py文件里直接配置即可 LOGGING = { 'version': 1, 'd ...
- Navicat 远程连接 MySQL
Navicat 远程连接 MySQL 相信大家都有在远程服务器上进行开发吧,其中 MySQL 的使用率应该也会挺高,如果使用 Navicat 等可视化工具来操作远程数据库不失为一种很好的选择,避免了在 ...
- linux安装配置阿里云的yum源和python3
一.yum源理解 yum源仓库的地址 在/etc/yum.repos.d/,并且只能读出第一层的repo文件 yum仓库的文件都是以.repo结尾的 二.下载阿里云的.repo仓库文件 ,放到/etc ...