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次。

由于您的问题仅表示上下扭曲,我认为您不需要额外的代码。