我自学了LibGdx并且正在关注简单的游戏教程,不幸的是大多数代码都在一个类中。我想重构代码,这样我就可以根据随机数使用多个纹理来降雨。
我会附上主程序的代码,然后是我开始上课的。
到目前为止一切正常,除了Rain纹理/ img没有在屏幕上显示。
public class GameScreen implements Screen {
public static FruitHarvest game;
protected final Texture dropImage;
//protected final Texture dropImage2;
private final Texture bucketImage;
public static Rectangle bucket;
public static Sound dropSound;
//private static Music rainMusic;
private final OrthographicCamera camera;
public static Array<Rectangle> raindrops;
private long lastDropTime;
public static int dropsGathered;
// private int random = MathUtils.random(0,1);
private Drops drop;
//Iterator<Rectangle> iterator = raindrops.iterator();
public GameScreen(final FruitHarvest game) {
this.game = game;
// load the images for the droplet and the bucket, 64x64 pixels each
dropImage = new Texture(Gdx.files.internal("droplet.png"));
//dropImage2 = new Texture(Gdx.files.internal("droplet1.png"));
bucketImage = new Texture(Gdx.files.internal("bucket.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"));
//rainMusic.setLooping(true);
// create the camera and the SpriteBatcher
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
// create a Rectangle to logically represent the bucket
bucket = new Rectangle();
bucket.x = 800 / 2 - 64 / 2; // Center the bucket horizontally
bucket.y = 20; // Bottom left corner of the bucket is 20 pixels above the bottom screen edge;
bucket.width = 64;
bucket.height = 64;
// Create the raindrops array and spawn the first raindrop
raindrops = new Array<Rectangle>();
long delta = 0;
drop = new Drops(dropImage, 64, 64, raindrops, delta);
}
@Override
public void render(float delta) {
// 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, .5f, 1);
Gdx.gl.glClear(GL20.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.
game.batch.setProjectionMatrix(camera.combined);
// begin a new batch and draw the bucket and all drops
game.batch.begin();
game.font.draw(game.batch, "Drops collected: " + dropsGathered, 0, 480);
game.batch.draw(bucketImage, bucket.x, bucket.y, bucket.width, bucket.height);
// Draws the Items Falling
for (Rectangle raindrop : raindrops) {
game.batch.draw(dropImage, raindrop.x, raindrop.y);
}
game.batch.end();
// process user input
if (Gdx.input.isTouched()) {
Vector3 touchPos = new Vector3();
touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);
bucket.x = touchPos.x - 64 / 2;
}
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) bucket.x -= 200 * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) bucket.x += 200 * Gdx.graphics.getDeltaTime();
// make sure the bucket stays within the screen bounds
if (bucket.x < 0) bucket.x = 0;
if (bucket.x > 800 - 64) bucket.x = 800 - 64;
// check if we need to create a new raindrop
if (TimeUtils.nanoTime() - drop.getLastDropTime() > 1000000000) {
drop.spawnRaindrop();
}
// move the raindrops, remove any that are beneath the bottom edge of the screen
// or that hit the bucket. In the later case we increase the value our drops counter
// and add a sound effect.
Iterator<Rectangle> iter = raindrops.iterator();
drop.update(delta);
// while (iter.hasNext()) {
// Rectangle raindrop = iter.next();
// raindrop.y -= 200 * Gdx.graphics.getDeltaTime();
// if (raindrop.y + 64 < 0) iter.remove();
// if (raindrop.overlaps(bucket)) {
// dropsGathered++;
// dropSound.play();
// iter.remove();
// }
// }
}
private void spawnRaindrop() {
Rectangle raindrop = new Rectangle();
raindrop.x = MathUtils.random(0, 800 - 64);
raindrop.y = 480;
raindrop.width = 64;
raindrop.height = 64;
raindrops.add(raindrop);
lastDropTime = TimeUtils.nanoTime();
}
// public void randomDrop(int value, float dropX, float dropY) {
// switch (value) {
// case 0:
// game.batch.draw(dropImage, dropX, dropY);
// break;
// case 1:
// //game.batch.draw(dropImage2, dropX, dropY);
// break;
// default:
// game.batch.draw(dropImage, dropX, dropY);
// break;
// }
// }
@Override
public void resize(int width, int height) {
}
@Override
public void show() {
// start the playback of the background music when the screen is shown
//rainMusic.play();
}
@Override
public void hide() {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void dispose() {
dropImage.dispose();
bucketImage.dispose();
dropSound.dispose();
//rainMusic.dispose();
}
}
继承我的课程
public class Drops {
private Rectangle raindrop;
private int imageHeight, imageWidth, x, y;
private Array<Rectangle> raindrops;
private long lastDropTime;
private Texture dropImage = new Texture(Gdx.files.internal("droplet.png"));
Iterator<Rectangle> iter = GameScreen.raindrops.iterator();
private float runTime = 0;
public Drops(Texture img, int imageHeight, int imageWidth, Array<Rectangle> drop, float delta) {
this.imageHeight = imageHeight;
this.imageWidth = imageWidth;
this.raindrops = drop;
this.dropImage = img;
}
public void update(float delta) {
while (iter.equals(true)) {
raindrop = iter.next();
raindrop.y -= 200 * Gdx.graphics.getDeltaTime();
if (raindrop.y + 64 < 0) iter.remove();
onCollision();
}
}
public void onCollision() {
if (raindrop.overlaps(bucket)) {
GameScreen.dropsGathered++;
GameScreen.dropSound.play();
iter.remove();
}
}
public void spawnRaindrop() {
Rectangle raindrop = new Rectangle();
raindrop.x = MathUtils.random(0, 800 - 64);
raindrop.y = 480;
raindrop.width = imageWidth;
raindrop.height = imageHeight;
raindrops.add(raindrop);
lastDropTime = TimeUtils.nanoTime();
}
public long getLastDropTime() {
return lastDropTime;
}
}
答案 0 :(得分:0)
通过drop.spawnRaindrop();
您可以在Drops类中向Array<Rectangle> raindrops;
添加数据,但是为了绘制而使用
for (Rectangle raindrop : raindrops) {
game.batch.draw(dropImage, raindrop.x, raindrop.y);
}
哪个会在您的raindrop
中循环播放GameScreen
数组列表,该列表为空。
因此要么在Dropsh中绘制数组列表,要么在GameScreen中填充数组列表。
答案 1 :(得分:0)
重构时需要更加小心。您在屏幕类中留下了原始的矩形阵列数组,并且您正在绘制它(现在为空)。然后在Drops类中,您将引用屏幕类中现在无用数组的迭代器。你正在屏幕的渲染方法中更新那个空数组。
基本上,需要在一个地方处理掉落,但是你要处理两个不同类中的冗余数组,并将它们全部混淆。
我不清楚为什么你甚至有一个名为Drops的类试图处理与桶的冲突。没有理由将顶级游戏逻辑移动到单独的类中,因为这会使代码复杂化。如果你有一个更复杂的游戏,可以有单独的类来跟踪和更新游戏的各个方面。
顺便提一下,你正在泄漏你在这一行加载的纹理:
private Texture dropImage = new Texture(Gdx.files.internal("droplet.png"));
因为在构造函数中用另一个引用替换引用之前,你从不处理它。在LibGDX中,任何实现Disposable的对象必须在其引用丢失之前处理,否则它将泄漏本机内存。
允许多张图像的直接方式:
1)使用屏幕类中的所有游戏逻辑返回原始单个班级。
2)将您的掉落图像加载到数组中以便于访问。
private final Array<Texture> dropImages = new Array<Texture>(); // replaces your dropImage declaration
//...
// in constructor:
dropImages.add(new Texture(Gdx.files.internal("droplet.png")));
dropImages.add(new Texture(Gdx.files.internal("droplet1.png")));
// etc. as many variations as you like
// don't forget to dispose of them:
@Override
public void dispose() {
for (Texture dropImage : dropImages) dropImage.dispose();
bucketImage.dispose();
dropSound.dispose();
}
3)创建一个扩展Rectangle的类Drop,并为图像类型添加一个附加参数。您可能还希望通过图像索引进行这些排序,以避免在绘制时多次在Textures之间进行交换,这会导致批量刷新,因为您没有使用TextureAtlas。
public class Drop extends Rectangle implements Comparable<Drop>{
public int imageIndex;
public Drop (){
super();
}
public int compareTo(Drop otherDrop) {
return (int)Math.signum(imageIndex - otherDrop.imageIndex);
}
}
4)将您的Array<Rectangle>
更改为Array<Drop>
。当你产生一个drop时,也给它一个随机的图像索引:
private void spawnRaindrop() {
Drop raindrop = new Drop ();
raindrop.x = MathUtils.random(0, 800 - 64);
raindrop.y = 480;
raindrop.width = 64;
raindrop.height = 64;
raindrop.imageIndex = MathUtils.random(dropImages.size); // <-- HERE
raindrops.add(raindrop);
lastDropTime = TimeUtils.nanoTime();
}
5)绘制水滴时,使用drop的imageIndex来绘制正确的纹理。您可以先对它们进行排序,以避免来回交换纹理:
// Draws the Items Falling
raindrops.sort();
for (Drop raindrop : raindrops) {
game.batch.draw(dropImages.get(raindrop.imageIndex), raindrop.x, raindrop.y);
}