我正在使用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;
}
}