PIXI 在场景中无限移动精灵(显示在顶部和隐藏在底部)
PIXI Endlessly move sprite over the scene (show at the top as much as hide in bottom)
有一个从上到下不断移动的精灵“绿色方块”,它起作用了。是否有可能在顶部显示像“围绕”舞台表演一样移动的精灵,就像隐藏在底部一样。我不知道如何调用这种效果,但我的意思是当绿色块开始向下移动场景边界时,然后再次开始在顶部显示它。如何做到这一点,你能展示一下如何做到这一点吗?
const WIDTH = 500;
const HEIGHT = 500;
const app = new PIXI.Application({
width: WIDTH,
height: HEIGHT,
backgroundColor: 0x000000
});
document.body.appendChild(app.view);
const sprite = PIXI.Sprite.from('https://i.ibb.co/b3Sjn6M/greeenblock.png');
sprite.width = 100;
sprite.height = 100;
// Center
sprite.anchor.set(0.5);
sprite.x = app.screen.width / 2;
sprite.y = app.screen.height / 2;
app.stage.addChild(sprite);
// Listen for animate update
app.ticker.add((delta) => {
// Move from topto bottom
sprite.position.y += delta * 2;
if (sprite.position.y > HEIGHT + sprite.height / 2) {
sprite.position.y = -sprite.height / 2;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.3.3/pixi.min.js"></script>
@Blindman67提供的解决方案(有闪烁):
const WIDTH = 500;
const HEIGHT = 500;
const app = new PIXI.Application({
width: WIDTH,
height: HEIGHT,
backgroundColor: 0x000000
});
document.body.appendChild(app.view);
const sprite = PIXI.Sprite.from('https://i.ibb.co/b3Sjn6M/greeenblock.png');
const spriteReverse = PIXI.Sprite.from('https://i.ibb.co/b3Sjn6M/greeenblock.png');
sprite.width = 100;
sprite.height = 100;
spriteReverse.width = 100;
spriteReverse.height = 100;
// Center
sprite.anchor.set(0.5);
sprite.x = app.screen.width / 2;
sprite.y = app.screen.height / 2;
spriteReverse.anchor.set(0.5);
spriteReverse.x = app.screen.width / 2;
spriteReverse.y = app.screen.height / 2;
app.stage.addChild(sprite);
app.stage.addChild(spriteReverse);
let y = 0;
// Euqlidian modulo
const modAbs = (value, modulo) => (value % modulo + modulo) % modulo;
// Listen for animate update
app.ticker.add((delta) => {
// Move from topto bottom
y += delta * 2;
if (y > HEIGHT + sprite.height / 2) {
y = -sprite.height / 2;
}
// use modulo to warp
y = modAbs(y, HEIGHT);
// check if sprite overlaps the screen edge
spriteReverse.visible = false;
if (y + sprite.height > HEIGHT) { // is crossing then
spriteReverse.visible = true;
spriteReverse.position.y = (y - HEIGHT) // ... draw a copy at opposite edge.
}
sprite.position.y = y
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.3.3/pixi.min.js"></script>
如果我理解你的话:你有一个盒子,你希望从上到下无限循环移动它。一旦它到达底部,它应该开始显示在顶部。
我能想到的最简单的方法是有两个相同的盒子。
两者都从顶部开始,只有一个向下移动。一旦它到达底部,另一个盒子就可以开始向下移动。
当第一个框完全 off-screen 时,您将重置它的位置。
并重复。
%
余数运算符
这可以使用余数运算符来完成%
例如,如果屏幕为 1000 像素宽,您的坐标为 1500,则使用取余运算符 1500 % 1000 = 500
.
,对象绕屏幕旋转 1.5 倍
如果只是朝正方向移动那么这就是所需要的(除了弹出)
x = x % screenWidth;
// and/or for y
y = y % screenHeight;
否定space
然而,如果对象向另一个方向移动,则会出现问题,因为余数运算会保留数字 -1500 % 1000 === -500
的符号,更糟糕的是,如果您对结果使用 Math.abs
,您仍然得到错误的值 Math.abs(-1200 % 1000) === 200
应该是 800
您可以使用稍微复杂一点的函数来解决这个问题。您可以将其添加到 Math
对象或使用如下独立函数。
const modAbs = (value, modulo) => (value % modulo + modulo) % modulo;
使用上述函数,负值可以正确地移动到正值 space。
所以如果你有一个坐标 x, y 使它扭曲屏幕
x = modAbs(x, screenWidth);
y = modAbs(y, screenHeight);
接缝很容易,但不幸的是还有一些问题需要克服。
弹出
使用上面的函数在屏幕上变形并没有考虑精灵的大小,因为当精灵穿过运动场边缘时你只渲染一个副本,它不会出现在另一边直到坐标越过边缘。
这会导致精灵根据移动方向和精灵原点的位置弹出或弹出。
有两种解决方法。
扩展运动场
如果您使游戏区域比视图(可视区域)大 2 倍于 sprite 的大小,并使用较大的游戏区域扭曲,则 sprite 在完全从视图中消失之前不会扭曲。这可以防止变形时丑陋的东西突然出现和突然出现,并且最适合 NPC 类型的精灵。对于玩家(专注的)精灵,这不是一个好的选择,因为精灵在穿过屏幕边缘时不会完全可见。
渲染额外副本。
为了让精灵始终完全可见,您需要在它穿过屏幕时多次渲染它。示例伪代码
// use modulo to warp
x = modAbs(x, screenWidth);
// check if sprite overlaps the screen edge
if (x + spriteWidth > screenWidth) { // is crossing then
drawSprite(x - screenWidth, // ... draw a copy at opposite edge.
如果您只是在顶部和底部(或左右)之间变形,这就是所需要的。
如果您要向各个方向变形,则最多需要渲染精灵 4 次。穿过上下或左右时两次。如果在拐角处穿过4次。
由于您的问题仅表示上下扭曲,我认为您不需要额外的代码。
有一个从上到下不断移动的精灵“绿色方块”,它起作用了。是否有可能在顶部显示像“围绕”舞台表演一样移动的精灵,就像隐藏在底部一样。我不知道如何调用这种效果,但我的意思是当绿色块开始向下移动场景边界时,然后再次开始在顶部显示它。如何做到这一点,你能展示一下如何做到这一点吗?
const WIDTH = 500;
const HEIGHT = 500;
const app = new PIXI.Application({
width: WIDTH,
height: HEIGHT,
backgroundColor: 0x000000
});
document.body.appendChild(app.view);
const sprite = PIXI.Sprite.from('https://i.ibb.co/b3Sjn6M/greeenblock.png');
sprite.width = 100;
sprite.height = 100;
// Center
sprite.anchor.set(0.5);
sprite.x = app.screen.width / 2;
sprite.y = app.screen.height / 2;
app.stage.addChild(sprite);
// Listen for animate update
app.ticker.add((delta) => {
// Move from topto bottom
sprite.position.y += delta * 2;
if (sprite.position.y > HEIGHT + sprite.height / 2) {
sprite.position.y = -sprite.height / 2;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.3.3/pixi.min.js"></script>
@Blindman67提供的解决方案(有闪烁):
const WIDTH = 500;
const HEIGHT = 500;
const app = new PIXI.Application({
width: WIDTH,
height: HEIGHT,
backgroundColor: 0x000000
});
document.body.appendChild(app.view);
const sprite = PIXI.Sprite.from('https://i.ibb.co/b3Sjn6M/greeenblock.png');
const spriteReverse = PIXI.Sprite.from('https://i.ibb.co/b3Sjn6M/greeenblock.png');
sprite.width = 100;
sprite.height = 100;
spriteReverse.width = 100;
spriteReverse.height = 100;
// Center
sprite.anchor.set(0.5);
sprite.x = app.screen.width / 2;
sprite.y = app.screen.height / 2;
spriteReverse.anchor.set(0.5);
spriteReverse.x = app.screen.width / 2;
spriteReverse.y = app.screen.height / 2;
app.stage.addChild(sprite);
app.stage.addChild(spriteReverse);
let y = 0;
// Euqlidian modulo
const modAbs = (value, modulo) => (value % modulo + modulo) % modulo;
// Listen for animate update
app.ticker.add((delta) => {
// Move from topto bottom
y += delta * 2;
if (y > HEIGHT + sprite.height / 2) {
y = -sprite.height / 2;
}
// use modulo to warp
y = modAbs(y, HEIGHT);
// check if sprite overlaps the screen edge
spriteReverse.visible = false;
if (y + sprite.height > HEIGHT) { // is crossing then
spriteReverse.visible = true;
spriteReverse.position.y = (y - HEIGHT) // ... draw a copy at opposite edge.
}
sprite.position.y = y
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.3.3/pixi.min.js"></script>
如果我理解你的话:你有一个盒子,你希望从上到下无限循环移动它。一旦它到达底部,它应该开始显示在顶部。
我能想到的最简单的方法是有两个相同的盒子。 两者都从顶部开始,只有一个向下移动。一旦它到达底部,另一个盒子就可以开始向下移动。 当第一个框完全 off-screen 时,您将重置它的位置。 并重复。
%
余数运算符
这可以使用余数运算符来完成%
例如,如果屏幕为 1000 像素宽,您的坐标为 1500,则使用取余运算符 1500 % 1000 = 500
.
如果只是朝正方向移动那么这就是所需要的(除了弹出)
x = x % screenWidth;
// and/or for y
y = y % screenHeight;
否定space
然而,如果对象向另一个方向移动,则会出现问题,因为余数运算会保留数字 -1500 % 1000 === -500
的符号,更糟糕的是,如果您对结果使用 Math.abs
,您仍然得到错误的值 Math.abs(-1200 % 1000) === 200
应该是 800
您可以使用稍微复杂一点的函数来解决这个问题。您可以将其添加到 Math
对象或使用如下独立函数。
const modAbs = (value, modulo) => (value % modulo + modulo) % modulo;
使用上述函数,负值可以正确地移动到正值 space。
所以如果你有一个坐标 x, y 使它扭曲屏幕
x = modAbs(x, screenWidth);
y = modAbs(y, screenHeight);
接缝很容易,但不幸的是还有一些问题需要克服。
弹出
使用上面的函数在屏幕上变形并没有考虑精灵的大小,因为当精灵穿过运动场边缘时你只渲染一个副本,它不会出现在另一边直到坐标越过边缘。
这会导致精灵根据移动方向和精灵原点的位置弹出或弹出。
有两种解决方法。
扩展运动场
如果您使游戏区域比视图(可视区域)大 2 倍于 sprite 的大小,并使用较大的游戏区域扭曲,则 sprite 在完全从视图中消失之前不会扭曲。这可以防止变形时丑陋的东西突然出现和突然出现,并且最适合 NPC 类型的精灵。对于玩家(专注的)精灵,这不是一个好的选择,因为精灵在穿过屏幕边缘时不会完全可见。
渲染额外副本。
为了让精灵始终完全可见,您需要在它穿过屏幕时多次渲染它。示例伪代码
// use modulo to warp
x = modAbs(x, screenWidth);
// check if sprite overlaps the screen edge
if (x + spriteWidth > screenWidth) { // is crossing then
drawSprite(x - screenWidth, // ... draw a copy at opposite edge.
如果您只是在顶部和底部(或左右)之间变形,这就是所需要的。
如果您要向各个方向变形,则最多需要渲染精灵 4 次。穿过上下或左右时两次。如果在拐角处穿过4次。
由于您的问题仅表示上下扭曲,我认为您不需要额外的代码。