目录
- 安装
- 创建Pixi应用和stage(舞台)
- sprites(精灵)
- 精灵的定位,大小,缩放,旋转
- 使用雪碧图制作精灵
- 使用纹理贴图集制作精灵
- 移动精灵
- 游戏状态
- 键盘移动
- 精灵分组
- 图形绘制
- 碰撞检测
1. 安装
要使用Pixi
,您还需要在根项目目录中运行Web
服务。
最便利的方法是使用node.js
,然后安装http-server
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World</title>
</head>
// pixi.js文件目录
<script src="pixi/pixi.min.js"></script>
<body>
// 链接Pixi并测试它是否正常运行
// 如果Pixi链接正确,通常会在浏览器的JavaScript控制台中显示类似于下面的内容。
// PixiJS 4.4.5 - * canvas * http://www.pixijs.com/ ♥♥♥
<script type="text/javascript">
let type = "WebGL"
if(!PIXI.utils.isWebGLSupported()){
type = "canvas"
}
PIXI.utils.sayHello(type)
</script>
</body>
</html>
2. 创建Pixi应用和stage(舞台)
// 使用Pixi上的Application对象创建一个矩形显示区域
let app = new PIXI.Application({
width: 256, // default: 800 宽度
height: 256, // default: 600 高度
antialias: true, // default: false 反锯齿(使字体和图形边缘更加平滑)
transparent: false, // default: false 透明度(使canvas背景透明)
resolution: 1, // default: 1 分辨率
forceCanvas: true //阻止选择WebGL渲染器, 使用canvas绘图API(WebGL非常快,所以Pixi的renderer对象将默认为WebGL)
});
// 将画布添加到html文档上
document.body.appendChild(app.view);
// 创建画布后,改变背景颜色, 需设置十六进制颜色值
app.renderer.backgroundColor = 0x061639;
// 查看渲染器的宽度和高度
app.renderer.view.width
app.renderer.view.height
// 改变画布大小
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);
// 请确保所有HTML元素的默认内边距和边距设置为0:
<style>* {
padding: 0; margin: 0}</style>
画布按比例缩放到任何浏览器窗口大小,方案:
https://github.com/kittykatattack/scaleToWindow
3. sprites(精灵)
3.1 sprites(精灵)与stage(舞台)
stage
(舞台)对象是场景中所有可见事物的根容器。你在stage
(舞台)里放的任何东西都会在canvas
画面上渲染出来。sprite
(精灵)是一种的特殊图像对象。您可以控制它们的位置、大小和其他属性。
使用Pixi
的Sprite
类来创建精灵的三种方法:
- 通过单个图像文件
- 通过雪碧图
- 通过纹理贴图
3.2 加载图像到纹理缓存
Pixi
使用WebGL
在GPU
上渲染图像,图像需要转换为GPU
可以处理的东西,这个东西被称为texture
纹理)。- 为保证快速高效,
Pixi
使用texture cache
(纹理缓存)来存储和引用你的精灵需要的所有纹理。 texture
(纹理)的名称就是引用图像的文件的路径
// 找到"images/anySpriteImage.png"的纹理缓存
let texture = PIXI.utils.TextureCache["images/anySpriteImage.png"];
// 利用这个纹理,创建精灵
let sprite = new PIXI.Sprite(texture);
Pixi的内置loader
(加载器)对象
// 加载图像文件并将其转换为纹理,并在加载完成时调用一个名为setup的函数
PIXI.loader
.add("images/anyImage.png")
.load(setup);
function setup() {
let sprite = new PIXI.Sprite(
// 引用loader的resources对象中的纹理来创建精灵
PIXI.loader.resources["images/anyImage.png"].texture
);
}
loader加载形式:
// 通过链接调用add方法加载多张图片
PIXI.loader
.add("images/imageOne.png")
.add("images/imageTwo.png")
.add("images/imageThree.png")
.load(setup);
// 调用一个add方法来加载数组中的图片
PIXI.loader
.add([
"images/imageOne.png",
"images/imageTwo.png",
"images/imageThree.png"
])
.load(setup);
loader(加载器)还允许您加载JSON文件。
3.3 显示精灵
// 使用Pixi上的Application对象创建一个矩形显示区域
let app = new PIXI.Application({
width: 256,
height: 256,
antialias: true,
transparent: false,
resolution: 1
}
);
// 将画布添加到html文档上
document.body.appendChild(app.view);
// 加载完"images/cat.png"图片后,调用setup函数
PIXI.loader
.add("images/cat.png")
.load(setup);
function setup() {
// 使用"images/cat.png"纹理创建精灵
let cat = new PIXI.Sprite(PIXI.loader.resources["images/cat.png"].texture);
// 将精灵添加到舞台上
app.stage.addChild(cat);
}
// 从舞台上删除一个精灵
app.stage.removeChild(anySprite)
// 或将精灵的visible属性设置为false (更简单、有效)
anySprite.visible = false;
3.4 使用别名
对经常使用的Pixi
对象和方法创建简短的别名,能节省一些输入,使代码更具可读性。
// 创建TextureCache对象的别名
let TextureCache = PIXI.utils.TextureCache
// 使用这个别名
let texture = TextureCache["images/cat.png"];
3.5 关于加载的额外内容
创建和改变纹理:
- 从一个普通的JavaScript
Image
对象创建一个纹理let base = new PIXI.BaseTexture(anyImageObject), texture = new PIXI.Texture(base), sprite = new PIXI.Sprite(texture);
- 从现有的Canvas画布元素中创建纹理
let base = new PIXI.BaseTexture.fromCanvas(anyCanvasElement)
- 使用纹理属性改变精灵显示的纹理(在游戏中,可以以此动态地改变精灵的外观)
anySprite.texture = PIXI.utils.TextureCache["anyTexture.png"];
为加载文件分配一个名称:
// 在add方法中提供名称(字符串)作为第一个参数
PIXI.loader
.add("catImage", "images/cat.png")
.load(setup);
function setup() {
let cat = new PIXI.Sprite(PIXI.loader.resources.catImage.texture);
app.stage.addChild(cat);
}
监控加载进度:
Pixi
的加载器有一个特殊的progress
事件,它将调用一个自定义函数,该函数将在每次加载文件时运行
PIXI.loader
.add([
"images/one.png",
"images/two.png",
"images/three.png"
])
.on("progress", loadProgressHandler)
.load(setup);
function loadProgressHandler(loader, resource) {
//显示当前加载的文件url
console.log("loading: " + resource.url);
// 显示当前已加载的总资源百分比
console.log("progress: " + loader.progress + "%");
// 显示当前加载的文件的别名
//console.log("loading: " + resource.name);
// resource对象上的其他属性。
// resource.error将告诉您尝试加载文件时发生的任何可能的错误。
// resource.data允许您访问文件的原始二进制数据。
}
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
关于Pixi加载器的更多知识:
Pixi
的loader
具有丰富的特性和可配置性- 加载器的链式方法
add
有4个基本参数:
add(name, url, optionObject, callbackFunction)
- name (string): 要加载的资源的名称
- url (string): 必须,这个资源的url,相对于baseUrl
- options (object): 加载配置项
options.crossOrigin
(Boolean): 请求是否跨域,默认是自动确定
options.loadType
: 如何加载资源?默认值是Resource.LOAD_TYPE.XHR
options.xhrType
: 在使用XHR时,应该如何解析加载的数据?默认值是Resource.XHR_RESPONSE_TYPE.DEFAULT
- callbackFunction: 资源完成加载时要调用的函数
- 重置
loader
并加载新的文件,请调用加载程序的reset
方法:PIXI.loader.reset()
// 官方,正常语法
.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
})
https://github.com/englercj/resource-loader
4. 精灵的定位,大小,缩放,旋转
function setup() {
// 创建精灵
let cat = new Sprite(resources["images/cat.png"].texture);
// 设置精灵的位置
cat.x = 96;
cat.y = 96;
// 可以统一设置
// cat.position.set(96, 96)
// 设置精灵的宽高
cat.width = 80;
cat.height = 120;
// 按比例改变精灵的宽度和高度
// 1表示100%(全尺寸),0.5表示50%(半尺寸),2表示加倍
cat.scale.x = 0.5;
cat.scale.y = 0.5;
// 更简洁的设置方式
// cat.scale.set(0.5, 0.5);
// 设置弧度值让精灵旋转
// 默认精灵的左上角为锚点(anchor),精灵围绕锚点旋转
cat.rotation = 0.5;
// 设置精灵的锚点
// 从0到1(0%到100%)。将它设置为0.5,使纹理在点上居中。
// 点本身的位置不会改变,只会改变纹理的位置。(精灵的纹理向上并向左移动)
cat.anchor.x = 0.5;
cat.anchor.y = 0.5;
// 简写方式
// cat.anchor.set(x, y)
// pivot轴心点设置了精灵的原点。
// 精灵会绕着原点旋转旋转
// 假设精灵是64x64像素,精灵现在会绕着它的中心点旋转。
cat.pivot.set(32, 32)
// 把精灵添加到舞台上
app.stage.addChild(cat);
}
锚点和原点的区别:
- 锚点改变了精灵图片纹理的原理,值的范围是0-1;
- 原点改变了精灵的原点,使用的像素值;
- 如果你改变一个精灵的原点,你也就改变了它的坐标。
5. 使用雪碧图制作精灵
在一个雪碧图上存储和访问所有的游戏图形是一种非常高效的处理和存储图形的方式
loader
.add("images/tileset.png")
.load(setup);
function setup() {
// 获取纹理
let texture = TextureCache["images/tileset.png"];
// Pixi.Rectangle 用于定义矩形形状的通用对象
// 四个参数:矩形的x和y位置 宽度width和高度height
let rectangle = new Rectangle(96, 64, 32, 32);
// Pixi纹理有一个有用的属性叫做frame,可以设置为任何Rectangle对象
// frame将纹理裁剪为矩形的尺寸
texture.frame = rectangle;
// 使用裁剪后的纹理来创建精灵
let rocket = new Sprite(texture);
// 设置精灵显示位置
rocket.x = 32;
rocket.y = 32;
// 把精灵添加到场景上
app.stage.addChild(rocket);
// 渲染场景
app.renderer.render(app.stage);
}
6. 使用纹理贴图集制作精灵
纹理贴图集:
- 纹理贴图集能快速的利用雪碧图创建精灵。
- 纹理贴图集是一个
JSON
数据文件,其中包含子图像在雪碧图上的位置和大小。如果你使用纹理贴图集,你只需要知道子图像的名字。
纹理打包器Texture Packer: 用来制作纹理贴图集
https://www.codeandweb.com/texturepacker
http://renderhjs.net/shoebox/
https://github.com/krzysztof-o/spritesheet.js/
三种从纹理图集创建精灵的方法:
- 1、使用纹理缓存
TextureCache
:let texture = TextureCache["frameId.png"], sprite = new Sprite(texture);
- 2、如果你已经使用
Pixi
的loader
加载了纹理贴图集,那你可以用loader
的resource
来创建:let sprite = new Sprite( resources["images/treasureHunter.json"].textures["frameId.png"] );
- 3、创建一个别名
id
,指向贴图集的textures
对象:let id = PIXI.loader.resources["images/treasureHunter.json"].textures; let sprite = new Sprite(id["frameId.png"]);
7. 移动精灵
游戏循环:
- 使用
Pixi
的ticker
创建一个循环函数,这被称为游戏循环(game loop)。
你放入游戏循环的任何代码,每秒都会被执行60次。function setup() { // 加入到ticker的函数都,每秒被调用60次 // delta: 帧与帧之间的平均间隔 // 设备运行较慢(代码计算量较大,也可能导致这种情况),不能满足60帧/秒,或者帧间隔相差较大,才会考虑delta,纠正显示效果。 app.ticker.add(delta => gameLoop(delta)); } function gameLoop(delta){ // 猫(cat)精灵以每帧1像素的速度向右移动 cat.x += 1; }
- 使用
requestAnimationFrame
创建游戏循环:function gameLoop() { requestAnimationFrame(gameLoop); cat.x += 1; } gameLoop();
使用速度属性:
速度属性(vx和vy):
- vx用于设置精灵在x轴上(水平)的速度和方向
- vy用于在y轴上(垂直)设置精灵的速度和方向
function setup() {
// 创建精灵
// 将vx和vy设置为0表示精灵不移动
cat = new Sprite(resources["images/cat.png"].texture);
cat.y = 96;
cat.vx = 0;
cat.vy = 0;
app.stage.addChild(cat);
app.ticker.add(delta => gameLoop(delta));
}
function gameLoop(delta){
// 更新精灵的移动速度vx和vy
cat.vx = 1;
cat.vy = 1;
// 让精灵每秒开始移动
cat.x += cat.vx;
cat.y += cat.vy;
}
8. 游戏状态
let cat, state;
function setup() {
cat = new Sprite(resources["images/cat.png"].texture);
cat.y = 96;
cat.vx = 0;
cat.vy = 0;
app.stage.addChild(cat);
// 设置游戏状态
state = play;
// 开始游戏循环
app.ticker.add(delta => gameLoop(delta));
}
function gameLoop(delta){
// 每秒60次更新
state(delta);
}
function play(delta) {
// 每帧向右移动1个像素
cat.vx = 1
cat.x += cat.vx;
}
9. 键盘移动
自定义键盘监听函数, 参数为想监听的按键名称
function keyboard(value) {
let key = {
};
key.value = value;
key.isDown = false;
key.isUp = true;
key.press = undefined;
key.release = undefined;
// 键盘按下
key.downHandler = event => {
if (event.key === key.value) {
if (key.isUp && key.press) key.press();
key.isDown = true;
key.isUp = false;
event.preventDefault();
}
};
// 键盘释放
key.upHandler = event => {
if (event.key === key.value) {
if (key.isDown && key.release) key.release();
key.isDown = false;
key.isUp = true;
event.preventDefault();
}
};
// 添加键盘监听
const downListener = key.downHandler.bind(key);
const upListener = key.upHandler.bind(key);
window.addEventListener(
"keydown", downListener, false
);
window.addEventListener(
"keyup", upListener, false
);
// 移除键盘监听
key.unsubscribe = () => {
window.removeEventListener("keydown", downListener);
window.removeEventListener("keyup", upListener);
};
return key;
}
通过键盘上下左右键移动精灵
代码如下:
function setup() {
cat = new Sprite(resources["images/cat.png"].texture);
cat.y = 96;
cat.vx = 0;
cat.vy = 0;
app.stage.addChild(cat);
let left = keyboard("ArrowLeft"),
up = keyboard("ArrowUp"),
right = keyboard("ArrowRight"),
down = keyboard("ArrowDown");
// 左箭头按下事件
left.press = () => {
//Change the cat's velocity when the key is pressed
cat.vx = -5;
cat.vy = 0;
};
// 左箭头释放事件
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.press = () => {
cat.vy = -5;
cat.vx = 0;
};
// 上箭头释放事件
up.release = () => {
if (!down.isDown && cat.vx === 0) {
cat.vy = 0;
}
};
// 右箭头按下事件
right.press = () => {
cat.vx = 5;
cat.vy = 0;
};
// 右箭头释放事件
right.release = () => {
if (!left.isDown && cat.vy === 0) {
cat.vx = 0;
}
};
// 下箭头按下事件
down.press = () => {
cat.vy = 5;
cat.vx = 0;
};
// 下箭头释放事件
down.release = () => {
if (!up.isDown && cat.vx === 0) {
cat.vy = 0;
}
};
// 设置游戏状态
state = play;
// 游戏循环
app.ticker.add(delta => gameLoop(delta));
}
function gameLoop(delta){
// 更新游戏状态
state(delta);
}
function play(delta) {
// 移动精灵
cat.x += cat.vx;
cat.y += cat.vy
}
10. 精灵分组
分组
Pixi
有一个名为Container
的对象,它可以把精灵们组合在一起。
// 创建cat精灵
let cat = new Sprite(id["cat.png"]);
cat.position.set(16, 16);
// 创建hedgehog刺猬精灵
let hedgehog = new Sprite(id["hedgehog.png"]);
hedgehog.position.set(32, 32);
// 创建tiger老虎精灵
let tiger = new Sprite(id["tiger.png"]);
tiger.position.set(64, 64);
// 创建一个animals容器
let animals = new PIXI.Container();
// 把三个精灵添加到容器中
animals.addChild(cat);
animals.addChild(hedgehog);
animals.addChild(tiger);
// 把这个分组添加到场景上
// stage对象也是一个容器(container),它是所有Pixi精灵的根容器
app.stage.addChild(animals);
// 使用children属性列出它包含的所有精灵
console.log(animals.children)
// 输出: Array [Object, Object, Object]
// 在父容器上更改的任何属性值都将以一种相对的方式影响子精灵(改变它的x、y、alpha、scale等值)
animals.position.set(64, 64);
// animals分组也有其自己的尺寸,该尺寸基于包含的精灵所占据的面积
console.log(animals.width);
console.log(animals.height);
局部坐标和全局坐标
当您将一个精灵添加到容器中时,它的x
和y
坐标相对于分组的左上角
x
和y
就是局部坐标
精灵也有一个全局坐标
全局坐标是从舞台左上角到精灵的定位点(通常是精灵的左上角)的距离
- 使用
toGlobal
方法查看一个精灵的全局坐标:console.log(animals.toGlobal(cat.position)); //Displays: Object {x: 80, y: 80...};
- 如果你不知道精灵的父元素是谁
// parent的属性,它会告诉你精灵的父容器是谁 cat.parent.toGlobal(cat.position);
- 最好的一种方式:使用
getGlobalPosition
方法// 画布左上角到精灵的距离 cat.getGlobalPosition().x cat.getGlobalPosition().y
- 将全局坐标转换为本地坐标
// 使用toLocal查看精灵和其他精灵之间的距离 tiger.toLocal(tiger.position, cat).x tiger.toLocal(tiger.position, cat).y
使用粒子容器ParticleContainer
对精灵进行分组
Pixi
有另一种高性能的方式来组合精灵,称为粒子容器ParticleContaine(PIXI.particles.ParticleContainer)
- 任何在
ParticleContainer
中的精灵渲染速度都比在常规容器中快2到5倍,这对于游戏来说是一个巨大的性能提升。
// 创建一个ParticleContainer
// 有四个可选参数:size、properties、batchSize和autoResize。
let superFastSprites = new ParticleContainer(maxSize, properties, batchSize, autoResize);
// 然后使用addChild向它添加精灵,就像使用任何普通容器一样。
maxSize
: 默认值为1500。如果想要显示更多的sprite,请将其设置为更大的数字。properties
: 是一个可以设置5个布尔值的对象:
scale
,position
,rotation
,uvs
和alphaAndTint
。
position
的默认值为true
,但其他所有值均设置为false
。- 如果您想在
ParticleContainer
中更改子画面的rotation
,scale
,tint
或uvs
,则必须将这些属性设置为true
如果您决定使用ParticleContainer
,则必须做出一些妥协:
ParticleContainer
中的精灵只有几个基本属性:x
、y
、width
、height
、scale
、pivot
、alpha
、visible
等等。- 一个
ParticleContainer
也不能使用Pixi
的高级视觉效果,如过滤器和混合模式。 - 每个
ParticleContainer
只能使用一个纹理(所以如果你想要不同外观的精灵,你必须使用雪碧图) - 为什么精灵在粒子容器中的速度如此之快?因为精灵的位置是直接在
GPU
上计算的
11. 图形绘制
所有形状的绘制,都先从创建Pixi
的Graphics
类(Pixi.Graphics
)的实例开始。
矩形
let rectangle = new Graphics();
// 设置4像素的红色外边框,透明度alpha设为1
rectangle.lineStyle(4, 0xFF3300, 1);
// 填充颜色为淡蓝色
rectangle.beginFill(0x66CCFF);
// 绘制矩形x,y,宽,高
rectangle.drawRect(0, 0, 64, 64);
// 结束绘制
rectangle.endFill();
// 设置坐标
rectangle.x = 170;
rectangle.y = 170;
// 将矩形添加到场景中
app.stage.addChild(rectangle);
圆形
let circle = new Graphics();
circle.beginFill(0x9966FF);
// 绘制圆形:x、y、半径radius
circle.drawCircle(0, 0, 32);
circle.endFill();
circle.x = 64;
circle.y = 130;
app.stage.addChild(circle);
椭圆
let ellipse = new Graphics();
ellipse.beginFill(0xFFFF00);
// 绘制椭圆:x,y,宽,高
ellipse.drawEllipse(0, 0, 50, 20);
ellipse.endFill();
ellipse.x = 180;
ellipse.y = 130;
app.stage.addChild(ellipse);
圆角矩形
let roundBox = new Graphics();
roundBox.lineStyle(4, 0x99CCFF, 1);
roundBox.beginFill(0xFF9933);
// 绘制圆角矩形:x,y,宽,高,圆角半径(决定了圆角的大小)
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 triangle = new Graphics();
triangle.beginFill(0x66FF33);
// 将点连成线组成多边形
triangle.drawPolygon([
-32, 64, // 第一个点
32, 64, // 第二个点
0, 0 // 第三个点
]);
triangle.endFill();
// 三角形的x,y位置锚定到路径中的第一个点
triangle.x = 180;
triangle.y = 22;
app.stage.addChild(triangle);
显示文字
-
使用
Text
对象(PIXI.Text
)在舞台上显示文字let message = new Text("Hello Pixi!"); app.stage.addChild(message);
-
Pixi
的Text
对象继承自Sprite
类,因此它们包含精灵类的全部属性,如x
、y
、width
、height
、alpha
和rotation
-
使用
Pixi
的TextStyle
函数来定义自定义文本样式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);
// 如果希望在创建文本对象之后更改它的文本内容,请使用text属性。 message.text = "Text changed!"; // 如果要重新定义样式属性,请使用style属性。 message.style = { fill: "black", font: "16px PetMe64"}; // Pixi也可以对超长字符串换行。 // align对单行文本不生效 message.style = { wordWrap: true, wordWrapWidth: 100, align: center}; // 使用自定义字体文件 @font-face { font-family: "fontFamilyName"; src: url("fonts/fontFile.ttf"); }
-
Pixi
还支持位图字体。可以使用Pixi
的loader
加载位图字体XML
文件,就像加载JSON
或图像文件一样。
12. 碰撞检测
碰撞检测函数:hitTestRectangle
函数
该函数检查是否有两个矩形的Pixi精灵正在接触
代码:
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 occurring. 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;
};