gpt4 book ai didi

java - libgdx 中的突破球碰撞

转载 作者:行者123 更新时间:2023-12-01 14:35:02 25 4
gpt4 key购买 nike

我目前正在尝试使用 java 和 libgdx 进行突破克隆。我目前在让球以适当的角度从木 block 上弹起时遇到困难。简而言之,我遇到的问题是球每帧移动 12 像素,并且并不总是与砖 block 的边缘对齐。如果有人对移动球的更好方法或检查碰撞的不同方法有任何建议,我们将不胜感激!

主要游戏类

    package com.kyleparker.breakout;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.Array;

public class BreakoutGameScreen implements ApplicationListener {
Texture dropImage;
Sound dropSound;
Music rainMusic;
SpriteBatch batch;
OrthographicCamera camera;
Rectangle bucket;
Paddle paddle;
//Brick bricks[];
Array<Brick> bricks;
Ball ball;

@Override
public void create() {
// load the images for the droplet, 64x64 pixels
dropImage = new Texture(Gdx.files.internal("droplet.png"));

// load the drop sound effect and the rain background "music"
dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav"));
rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));

// start the playback of the background music immediately
rainMusic.setLooping(true);
rainMusic.play();

// create the camera and the SpriteBatch
camera = new OrthographicCamera();
camera.setToOrtho(false, 1280, 720);
batch = new SpriteBatch();

paddle = new Paddle(new Texture(Gdx.files.internal("bucket.png")));

bricks = new Array<Brick>();
populateBricks();

ball = new Ball(new Texture(Gdx.files.internal("bucket.png")), paddle, bricks);
}

private void populateBricks() {
bricks.add(new Brick(200,100));
for (int i = 0; i < 5; i++) {
for (int j = 0; j <= 7; j++) {
bricks.add(new Brick (j * 144 + 76, i * 80 + 300)); //Offsets each new brick
}
}
}

@Override
public void render() {
// clear the screen with a dark blue color. The
// arguments to glClearColor are the red, green
// blue and alpha component in the range [0,1]
// of the color to be used to clear the screen.
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

// tell the camera to update its matrices.
camera.update();

// tell the SpriteBatch to render in the
// coordinate system specified by the camera.
batch.setProjectionMatrix(camera.combined);

// begin a new batch and draw the bucket and
// all drops
batch.begin();

paddle.render(batch, camera);

ball.move();
ball.render(batch, camera);

for (int x = bricks.size - 1; x > 0; x--) {
bricks.get(x).render(batch,camera);
}

batch.end();
}

@Override
public void dispose() {
// dispose of all the native resources
dropImage.dispose();
dropSound.dispose();
rainMusic.dispose();
batch.dispose();
paddle.dispose();
}

@Override
public void resize(int width, int height) {
}

@Override
public void pause() {
}

@Override
public void resume() {
}
}

球类

    package com.kyleparker.breakout;

import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.Array;

public class Ball{
Texture ballImage;
Rectangle ball;
private int xdir;
private int ydir;
Paddle paddle;
Array<Brick> bricks;
final int BALL_SPEED = 12;

public Ball(Texture ballImage, Paddle paddle, Array<Brick> bricks) {
// load the ball image
this.ballImage = ballImage;
xdir = 1;
ydir = -1;

// create a Rectangle for the balls collision
ball = new Rectangle();
ball.x = 1280 / 2 - 64 / 2; // center the ball
ball.y = 100; // put the ball 200px away from the bottom of the screen
ball.width = 64;
ball.height = 64;

this.paddle = paddle;
this.bricks = bricks;
}

public void render(SpriteBatch batch, OrthographicCamera camera) {
// draw the paddle onto the batch of the level
batch.draw(ballImage, ball.x, ball.y);
}

public void move() {
ball.x += xdir * BALL_SPEED;
ball.y += ydir * BALL_SPEED;

if (ball.x <= 0) {
setXDir(1);
}

if (ball.x >= 1280 - 64) {
setXDir(-1);
}

if (ball.y <= 0) {
setYDir(1);
}

if (ball.y >= 720 - 64) {
setYDir(-1);
}

if (ball.overlaps(paddle.getRect())) {
setYDir(1);
}

for (int i = 0; i < bricks.size; i++) {
if (ball.overlaps(bricks.get(i).getRect())) {
if ((ball.x == (bricks.get(i).getRect().x + 128)))
{
setXDir(1);
bricks.get(i).setDestroyed(true);
System.out.println("Collision RIGHT");
}
if (((ball.x + 64) == bricks.get(i).getRect().x))
{
setXDir(-1);
bricks.get(i).setDestroyed(true);
System.out.println("Collision LEFT");
}
if ((ball.y == (bricks.get(i).getRect().y + 64)))
{
setYDir(1);
bricks.get(i).setDestroyed(true);
System.out.println("Collision TOP");
}
if (((ball.y + 64) == bricks.get(i).getRect().y))
{
setYDir(-1);
bricks.get(i).setDestroyed(true);
System.out.println("Collision BOTTOM");
}
}
}// end of for
}

public void setXDir(int x) {
xdir = x;
}

public void setYDir(int y) {
ydir = y;
}

public int getYDir() {
return ydir;
}

public int getXDir() {
return xdir;
}

public Rectangle getRect() {
// return the collision rectangle for checking overlaps
return ball;
}

public void dispose() {
// dispose of all the native resources
ballImage.dispose();
}
}// end of class

砖 block 代码以防万一

package com.kyleparker.breakout;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Rectangle;

public class Brick{
Texture brickImage;
Rectangle brick;
boolean destroyed;

public Brick(int x, int y) {
brickImage = new Texture(Gdx.files.internal("brick.png"));

// create a Rectangle for the bricks collision
brick = new Rectangle();
brick.x = x;
brick.y = y;
brick.width = 128;
brick.height = 64;

destroyed = false;
}

public void render(SpriteBatch batch, OrthographicCamera camera) {
// draw the brick onto the batch of the level
batch.draw(brickImage, brick.x, brick.y);
}

public boolean isDestroyed() {
// return the collision rectangle for checking overlaps
return destroyed;
}

public void setDestroyed(boolean destroyed)
{
this.destroyed = destroyed;

if (this.destroyed == true) {
dispose();
brick.x = -1000;
brick.y = -1000;
}
}

public Rectangle getRect() {
return brick;
}

public void dispose() {
// dispose of all the native resources
brickImage.dispose();
}
}

最佳答案

不必担心球并不总是与需要处理碰撞的对象对齐这一事实 - 这实际上并不相关。您可以(并且应该)不太“精确”地处理碰撞。也就是说,球的路径是固定的,因此您可以计算它在未来任何点的位置。检查它的位置,计算它在下一帧中的位置(无论如何绘制它都必须这样做),并添加一些代码来处理即将发生的碰撞,而不是尝试检测和处理处理已经发生的碰撞。如果您确实想要干净的反射,您可以放慢球的速度,或者您可以加快帧速率,或者您可以让球在反射之前被物体部分“吸收”:

public class Ball {
. . .
public void move() {
. . .
if (collisionObject.overlaps(new Rectangle(ball.x + xdir, ball.y + ydir, ball.width, ball.height))) {
//a collision will have occurred in the next frame
//handle the collision however you please
}
}
}

我还注意到您的 BALL_SPEED字段命名不准确。按照目前的编码,球始终以 45° 角移动,速度约为每帧 17 像素(沿该方向)。您已将其 x 和 y 偏移编码为 12 像素,但如果(何时?)您更改球的方向,您会发现速度会剧烈波动,具体取决于 xdir 中放置的值。和ydir字段。例如,如果您要(在某种程度上)随机化这些,但保持其余代码不变,您可能会发现 xdir = 2ydir = 4在一个实例中,xdir = 6ydir = 12另外一个。请注意,这些描述了相同的方向,但第二个版本的移动速度是原来的三倍。

为了正确处理球的方向和速度,指定一个角度,并计算 xdirydir通过适当的三角函数( xdir = BALL_SPEED * Math.cos(ballAngle)ydir = BALL_SPEED * Math.sin(ballAngle) )计算值。

关于java - libgdx 中的突破球碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16554296/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com