我正在使用AndEngine开发适用于Android的游戏,并且有一系列汽车对象在不同的​​车道上从屏幕上的左右移动。当汽车超过摄像头宽度(屏幕尺寸)时,我将其位置设置为0(屏幕左侧)-spriteWidth()(仅在屏幕视口的左侧)。我的问题是,由于返回的随机coordiantes,汽车一直在互相装载。我已经尝试了很多东西,但是一直都在发生。

这是用于在游戏开始时设置汽车坐标的方法,也用于在右侧屏幕之外显示。

public Vector2 randomRoadCoord()
{
    int Y;
    int X;

    int arrayLength = rManager.getInstance().roadPosition.length;
    int arrayFirstValue = 1;

    Random xR = new Random();
    int Low = (int) (5 *(0 - rManager.getInstance().car_region.getWidth()));
    int High = (int) (0 - rManager.getInstance().car_region.getWidth());
    X = xR.nextInt(High-Low) + Low;

    Random yR = new Random();

    int LowY = arrayFirstValue;
    int HighY = arrayLength;
    Y = yR.nextInt(HighY-LowY) + LowY;;

    if (firstLoad)
    {
        for(int i = 0; i < rManager.getInstance().carArray.length; i++)
        {
            for(int j = 0; j < rManager.getInstance().carArray.length; j++)
            {
                while(rManager.getInstance().carArray[i].getCarSprite().collidesWith(rManager.getInstance().carArray[j].getCarSprite()))
                    X-= 150;
            }
        }
    }

    lastX = X;
    lastY = Y;
    return new Vector2(X, Y);
}


如您所见,随机x和y值在某些区域之间返回;具体来说,是摄影机的顶部和底部(静态摄影机,因此基本上是视口),并且在屏幕外的-50至-450之间(类似)。我的问题是,我需要它们停止在彼此之上加载,因为如果发生碰撞,则用户会输掉游戏。我尝试检查每辆汽车精灵,以查看它在加载时是否已与另一辆汽车发生碰撞(尽管这肯定会导致减速,如果确实如此,请将X坐标向左移动,但似乎没有任何作用。

/*if (firstLoad)
        {
        for(int i = 0; i < rManager.getInstance().carArray.length; i++)
        {
            while(rManager.getInstance().carArray[i].getCarX() + 100 > X && X > rManager.getInstance().carArray[i].getCarX() - 100)
                X-= 150;
        }
        firstLoad = true;
    }   */


我还尝试检查汽车是否在其他汽车的x + 150和x-150之间,但这也无济于事。并非所有汽车都可以互相装载,但肯定超过1个,这太多了。

谢谢。请随时提出任何问题。

---------------------------------更新:

我尝试使用整形外科医生的建议,但是仍然存在相同的问题。尽管将汽车装载到另一辆汽车上的可能性要小得多,但它仍然偶尔发生。我这次已经注释了代码,因此应该更容易理解。

for (int i = 0; i < rManager.getInstance().carArray.length; i++)
            {
                if(rManager.getInstance().carArray[i].getCarSprite().getX() < (rManager.camera.getWidth() + rManager.getInstance().carArray[i].getCarSprite().getWidth()))
                {
                    // moves car from left to right
                    rManager.getInstance().carArray[i].getCarSprite().setPosition(rManager.getInstance().carArray[i].getCarSprite().getX() + (rManager.getInstance().carArray[i].getSpeed() * 4), rManager.getInstance().carArray[i].getCarSprite().getY());
                }

                else //if out of the screen
                {
                    //set the position to the left of the screen
                    rManager.getInstance().carArray[i].getCarSprite().setPosition(randomRoadCoord().x, rManager.getInstance().roadPosition[(int) randomRoadCoord().y].y);

                    //if colliding with another car
                    while(collidesWithExisting(rManager.getInstance().carArray[i]))
                    {   //set a new random pos
                        rManager.getInstance().carArray[i].getCarSprite().setPosition(randomRoadCoord().x, rManager.getInstance().roadPosition[(int) randomRoadCoord().y].y);
                    }
                }
            }


方法:

boolean collidesWithExisting(Car pCar)
{
    for(int j = 0; j < rManager.getInstance().carArray.length; j++)
    {
        if (rManager.getInstance().carArray[j] == pCar)
            return false;

        if(rManager.getInstance().carArray[j].getCarSprite().collidesWith(pCar.getCarSprite()))
            return true;
    }
    return false;
}


再次感谢。

最佳答案

您的循环至少存在一个问题:
X值更改时,您检查的.collidesWith()条件不会更改。因此,可能还会发生其他误报。

第二个问题是,如果发生collidesWith()事件,则无法知道新的x是否还会在循环的更早时间在另一辆汽车上导致collidesWith()事件。想象一下,在两辆太近的汽车之间放置第三辆汽车,以至于它们之间无法容纳一辆汽车。没有办法在单循环或双循环中解决该问题。

因此,这里有一个不同的策略:仅使一个轴完全随机。沿X轴(轿厢的行进方向)每次步进一个轿厢长度。随机确定在该位置上是否应该有汽车。如果是,则将汽车沿Y轴随机放置。
没有太多麻烦,您可以使每步放置一辆或多辆汽车成为可能。

如果您不希望栅格像平时一样,则可以将X循环前进1/2车长。然后,您只需要检查与上次迭代中放置的一辆或多辆汽车之间的碰撞,并且只需要在Y轴上偏移即可防止碰撞。

这也是第二种策略:
将每辆车随机成环。循环测试以查看当前汽车是否与其他任何汽车发生碰撞。保持随机重新分配其x和y,直到不会发生碰撞。
最后,您将拥有一系列不接触的汽车。

   Car newCar = new Car();
   newCar.setPosition(randomXPostion, randomYPosition);
   while(testCarCollidesWithExisting(newCar)){
       newCar.setPosition(randomXPostion, randomYPosition);
   }


“ testCarCollidesWithExisting”方法循环遍历一系列已放置的汽车,如果新汽车重叠,则返回true,如果汽车不重叠,则返回false。

==更新完整示例==

这是一个有效的例子。使用的图形是andengine示例中的“油箱”。
有一个警告:如果您放置的坦克数量超出了其承受能力,脚本将挂起,因为它陷入了while循环中。我认为在这种尺寸的图像和舞台尺寸的情况下,大约20倍于您。

打包com.example.andenginetestbed;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import org.andengine.engine.camera.Camera;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.Background;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.util.FPSLogger;
import org.andengine.opengl.texture.ITexture;
import org.andengine.opengl.texture.bitmap.BitmapTexture;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.texture.region.TextureRegionFactory;
import org.andengine.ui.activity.SimpleBaseGameActivity;
import org.andengine.util.adt.io.in.IInputStreamOpener;
import org.andengine.util.debug.Debug;

import android.os.Bundle;
import android.view.Menu;

public class TestBed extends SimpleBaseGameActivity {

    // ===========================================================
    // Constants
    // ===========================================================

    private static final int CAMERA_WIDTH = 720;
    private static final int CAMERA_HEIGHT = 480;

    // ===========================================================
    // Fields
    // ===========================================================

    private ITexture mTexture;
    private ITextureRegion mFaceTextureRegion;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_test_bed);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.test_bed, menu);
        return true;
    }

    @Override
    public EngineOptions onCreateEngineOptions() {
        final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);

        return new EngineOptions(true, ScreenOrientation.LANDSCAPE_SENSOR, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
    }

    @Override
    public void onCreateResources() {
        try {
            this.mTexture = new BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
                @Override
                public InputStream open() throws IOException {
                    return getAssets().open("tank.png");
                }
            });

            this.mTexture.load();
            this.mFaceTextureRegion = TextureRegionFactory.extractFromTexture(this.mTexture);
        } catch (IOException e) {
            Debug.e(e);
        }
    }
    ArrayList<Sprite> placedSprites = new ArrayList<Sprite>();
    @Override
    protected Scene onCreateScene() {
        this.mEngine.registerUpdateHandler(new FPSLogger());

        final Scene scene = new Scene();
        scene.setBackground(new Background(0.09804f, 0.6274f, 0.8784f));

        /* Calculate the coordinates for the face, so its centered on the camera. */
        final float centerX = (CAMERA_WIDTH - this.mFaceTextureRegion.getWidth()) / 2;
        final float centerY = (CAMERA_HEIGHT - this.mFaceTextureRegion.getHeight()) / 2;

        /* Create the face and add it to the scene. */
        for (int i = 0; i < 20; i++) {
            final Sprite face = new Sprite(centerX, centerY, this.mFaceTextureRegion, this.getVertexBufferObjectManager());
            scene.attachChild(face);
            face.setPosition((float)(Math.random()*CAMERA_WIDTH), (float)(Math.random()*CAMERA_HEIGHT));
            while(faceDoesNotOverlap(face)){
                face.setPosition((float)(Math.random()*CAMERA_WIDTH), (float)(Math.random()*CAMERA_HEIGHT));
            }
            placedSprites.add(face);

        }

        return scene;
    }

    private boolean faceDoesNotOverlap(Sprite face) {
        for (int i = 0; i < placedSprites.size(); i++) {
            if(face.collidesWith(placedSprites.get(i))){
                return true;
            }
        }
        return false;
    }



}

10-08 01:28