我建議你把你的level.bricks []數組在ArrayList中列表,以便您可以便宜刪除()和/或在飛行的名單摧毀()他們,避免檢查在level.bricks數組中重複每次迭代(除非您的設置不介意數組中的null)。再加上它會救你就不必檢查數組中,每次迭代中,對所有的磚的大小,每一個渲染週期中...
List<Brick> brickList = new ArrayList<Brick>();
for (brick: level.bricks) {
brickList.add(new Brick(brick));
}
//-------or-------
//if the brick object is a Sprite
for (brick: level.bricks) {
brickList.add(brick);
}
我相信被檢測爲錯誤磚的問題「打「與試圖補償球紋理有關,並且作爲Rectangle。我會推薦使用com.badlogic.gdx.math.Circle類來定義球的邊界。以下是com.badlogic.gdx.math.Intersector的一個骯髒的自定義衝突包裝,它應該與上面的嘗試一致。它假定球的視覺像素延伸至紋理的邊緣和球質地方:
public class Collider {
private String bounceType = "";
private boolean vertical = false;
private boolean horizontal = false;
// Segment Vertices of the Rectangle
private Vector2 leftStart = new Vector2();
private Vector2 leftEnd = new Vector2();
private Vector2 topStart = new Vector2();
private Vector2 topEnd = new Vector2();
private Vector2 rightStart = new Vector2();
private Vector2 rightEnd = new Vector2();
private Vector2 bottomStart = new Vector2();
private Vector2 bottomEnd = new Vector2();
private Vector2 center = new Vector2();
private Circle ballBounds = new Circle();
// Pointers passed once during construction
private Ball ball;
private List<Brick> brickList;
private List<Score> scoreList;
/**
* Constructor requires that ball and brickList pointers are given.
* <p>
* Runs the updateBallBounds() method after assigning the parameters
*
*@param ball points to the ball to be used for the collision calculations
*@param brickList points to a list of brick objects to check against
*@param scoreList points to a list of score objects to track the score
*/
public Collider(Ball ball, List<Brick> brickList, List<Score> scoreList) {
this.ball = ball;
this.brickList = brickList;
updateBallBounds(this.ball, this.ballBounds);
}
/**
* Sets the position and radius of the bounding circle
* for the given ball with a rectangular shape in order
* to prepare it for bounds checking.
*
* @param ball The ball object to
* @param bounds The circle object that will store the bounds information
*/
private void updateBallBounds(Ball ball, Circle bounds) {
bounds.set((ball.ballRect.x + (ball.ballRect.width/2)), //Center x pos
(ball.ballRect.y + (ball.ballRect.height/2)), //Center y pos
(ball.ballRect.width/2)); //Radius of ball
}
/**
* Builds the start and end Vectors for each of the segments
* of the provided rectangle. Also builds the center Vector for
* the ball.
* <p>
* Used to prepare for finding which segments of the rectangle the
* ball is intersecting
*
* @param brickRect The rectangle to process the line segments from
*/
private setVectors(Rectangle brickRect) {
leftStart.set(brickRect.x, brickRect.y);
leftEnd.set(brickRect.x, brickRect.height);
topStart.set(brickRect.x, brickRect.height);
topEnd.set(brickRect.width, brickRect.height);
rightStart.set(Poyline(brickRect.width, brickRect.y);
rightEnd .set(brickRect.width, brickRect.height);
bottomStart.set(brickRect.x, brickRect.y);
bottomEnd.set(brickRect.width, brickRect.y);
center.set(ballBounds.x, ballBounds.y);
}
/**
* Finds bricks in the list that the ball is currently
* colliding with.
* <p>
* For every rectangle that the ball is currently colliding with,
* the method calls the setVectors() method to prepare the start-end
* vertices for the processCollision() method.
* <p>
* WARNING: this may not handle multiple collision very well. It
* should work, but you most likely will not give very good results
* on multiple brick hit detected. You should think about including
* a break statement after the first collision is detected and let
* the Collider find an additional collision during the next render()
* call.
*/
public void detectCollisions() {
updateBallBounds(ball, ballBounds);
for (brick: brickList) {
if(Intersector.overlaps(ballBounds, brick.brickRect)) {
setVectors(brick.brickRect);
processCollision(brick, brick.brickRect);
//break;
}
}
}
/**
* Detects how to handle the collision based on the segments being hit.
*
*@param brick the brick found by detectCollision() method. will be
* destroyed after collision is processed
*/
public void processCollision(Brick brick) {
if (Intersector.intersectSegmentCircle(topStart, topEnd,
center * center,
ballBounds.radius) ||
Intersector.intersectSegmentCircle(bottomStart, bottomEnd,
center * center,
ballBounds.radius)) {
vertical = true;
}
if (Intersector.intersectSegmentCircle(leftStart, leftEnd,
center * center,
ballBounds.radius) ||
Intersector.intersectSegmentCircle(rightStart, rightEnd,
center * center,
ballBounds.radius)) {
horizontal = true;
}
// The following could return the value to a calling entity.
// Then the game logic of what to do here would be decoupled.
if (vertical && horizontal) {
bounceType = "CORNER"
} else if (vertical && !horizontal) {
bounceType = "VERTICAL"
} else if() {
bounceType = "HORIZONTAL"
} else {
// The game blows up...
}
switch (bounceType) {
case "VERTICAL":
ball.ballSpeedY = -ball.ballSpeedY;
break;
case "HORIZONTAL":
ball.ballSpeedX = -ball.ballSpeedX;
break;
case "CORNER":
ball.ballSpeedY = -ball.ballSpeedY;
ball.ballSpeedX = -ball.ballSpeedX;
break;
default: // Try not to blow up the game...
break;
}
Score score = new Score(brick.getScore(), brick.x, brick.y)
scoreList.add(score);
brickList.remove(brick);
brick.destroy();
}
}
我敢肯定,這裏有錯誤,它沒有進行測試。除了前面的假設之外,它不會阻止磚塊在您的數組中呈現(除非destroy()負責處理該數據,並且希望不會在渲染時尋找空值...)。
基本結構可以變得更好......
- 有了一些除,嘗試,抓東西。
- 您可以添加更多的類型化構造函數和方法來覆蓋更多的形狀。
- 空間分區可以添加一個方法來映射 構造的靜態邊界。然後,您的動態對象可以記錄它們當前佔用的分區,並僅查詢記錄在這些分區列表中的其他對象的碰撞結果。
- 我認爲這個類的實現應該在其他地方解耦和處理 。
- 這也可以讓你創建一個碰撞類或事件返回/觸發。
希望這對我有所幫助。
我也建議你看看Box2D。你的要求看起來很簡單,可以在使用中輕鬆學習。 This page可以向您展示如何配置和使用LibGDX。這可以讓你快速實現對物體的屬性,旋轉球,速度變化,有角度的籃板......,各種善良的自動魔法,這將節省你的大腦一些週期。物理引擎爲你做所有的數學。你只是初始化和分步,聽事件(如碰撞)。
祝你好運與你的遊戲。
如果球的角落與磚塊碰撞,我會逐個檢查。然後基於此,我會檢查球應該去的地方。我也會檢查所有相互碰撞的磚塊,然後讓球跳下去。這會防止當擊中超過1塊磚時球進入一個奇怪的方向。這種技術的問題在於,如果球速度很快(但你現在擁有的球員不會那麼做),它就不起作用。 – Zelenova 2013-05-07 02:31:21
這就是我遇到的問題。搞清楚如何檢查。我嘗試了一些不正確的方法。我理解它的原理。它只是把它變成代碼。 – Bassex 2013-05-07 02:37:16
我不知道如何rects在java中工作,但原則上,檢查一個點是否在你應該做的矩形內:'boolean colliding =((point.x> rect.x && point.x rect.y && point.y
Zelenova
2013-05-07 02:47:19