`

JavaFX打砖块游戏开发 第三课

 
阅读更多

突然发现,JavaFX游戏开发的教程好久没有更新了...

不过没关系,以后更新的可能会频繁一点.

下面我们来进行JavaFX打砖块游戏开发第三课。


在上一课里面,我们创建了一个鼠标控制的挡板。和一个在屏幕上四处弹的小球。

这一课里面,我们将会增加一些砖块等等的。

事先声明,这里我们不会涉及到算法问题。也就是说,游戏中使用的都是最简单最基本的,而且肯定是会有很多的问题。大家可以自行修改,或者我在后面会专门开一篇文章讲解。


首先我们建立一个砖块类。

import javafx.geometry.Bounds;
import javafx.scene.effect.BoxBlur;
import javafx.scene.effect.Lighting;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;

public class Brick extends BaseObject
{
  private Rectangle mRectangle;
  private int hp;
  private BoxBlur mBlur;

  public Brick(Color color, int hp)
  {
    this.hp = hp;
    this.mRectangle = new Rectangle();
    this.mRectangle.widthProperty().bindBidirectional(widthProperty());
    this.mRectangle.heightProperty().bindBidirectional(heightProperty());
    this.mRectangle.xProperty().bindBidirectional(xProperty());
    this.mRectangle.yProperty().bindBidirectional(yProperty());

    this.mRectangle.setFill(color);
    this.mBlur = new BoxBlur();
    this.mBlur.setWidth(5);
    this.mBlur.setHeight(5);
    this.mRectangle.setEffect(new Lighting());
    setWidth(100);
    setHeight(25);
    getChildren().add(this.mRectangle);
  }

  public Bounds getBounds() {
    return this.mRectangle.getLayoutBounds();
  }

  public int getHp() {
    return this.hp;
  }

  public void setHp(int hp) {
    this.hp = hp;
  }
}

很简单的,其实就是一个矩形,包含了一个Blur的效果,和一个HP的属性。我们将矩形的属性与object的属性进行绑定,这样,我们操作object就是操作矩形了。


接下来,创建一个关卡load的类。

import javafx.scene.paint.Color;

public class LevelLoader
{
  private static int[][] level1 = { { 0, 1, 1, 1, 1, 1, 0 }, { 0, 1, 1, 1, 1, 1, 0 }, { 0, 1, 1, 1, 1, 1, 0 }, { 0, 1, 1, 1, 1, 1, 0 } };

  public static void load(GameScene scene, int level)
  {
    int[][] datas = getLevel(level);
    for (int i = 0; i < datas.length; i++)
      for (int j = 0; j < datas[0].length; j++)
        if (datas[i][j] != 0) {
          Brick brick = new Brick(Color.RED, datas[i][j]);
          brick.setWidth(108.0D);
          brick.setX((760- 7 * brick.getWidth()) / 2.0D + j * (brick.getWidth()));
          brick.setY(i * (brick.getHeight()) + 100);
          scene.addChild(brick);
          scene.getBricks().add(brick);
        }
  }

  public static int[][] getLevel(int i)
  {
    if (i == 1) {
      return level1;
    }
    return (int[][])null;
  }
}

这里,我们通过一个二维数组来摆放砖块的位置。GameScene是我们的游戏场景,当然也经过了很多的修改。这里砖块的HP值,根据二维数组里的值来确定。大家也可以将砖块的颜色与值绑定,同样能直接通过一个二维数据来确定砖块的种类和HP值。


接下来,我们来看看场景GameScene类:

import java.util.concurrent.CopyOnWriteArrayList;

import javafx.animation.FadeTransition;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Parent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;

public class GameScene extends Parent {
	private int width;
	private int height;
	private Rectangle background;
	private MainBrick mainBrick = new MainBrick();
	private Ball ball = new Ball(15, 15, 15);
	private Timeline timeline;
	private KeyFrame keyFrame;
	private CopyOnWriteArrayList<Brick> bricks = new CopyOnWriteArrayList<>();

	public GameScene(int width, int height) {
		this.width = width;
		this.height = height;

		initGameObjects();
		initTimeLine();
		initLevel();
	}

	private void initGameObjects() {
		this.background = new Rectangle(0.0D, 0.0D, this.width, this.height);
		this.background.setOnMouseMoved(new EventHandler<MouseEvent>() {

			@Override
			public void handle(MouseEvent event) {
				mainBrick.onMouseMove(event);

			}
		});
		this.background.setFill(Color.BLACK);

		this.mainBrick.setX(0.0D);
		this.mainBrick.setY(this.height - this.mainBrick.getHeight());
		this.ball.setX((this.mainBrick.getWidth() - this.ball.getWidth()) / 2.0D);
		this.ball.setY(this.height - this.mainBrick.getHeight() - this.ball.getHeight());

		getChildren().add(this.background);
		getChildren().add(this.mainBrick);
		getChildren().add(this.ball);
	}

	private void initTimeLine() {
		this.timeline = new Timeline();
		this.timeline.setCycleCount(-1);
		this.keyFrame = new KeyFrame(Duration.millis(5.0D), new EventHandler<ActionEvent>() {
			public void handle(ActionEvent arg0) {
				ball.moveX(ball.getSpeedX());
				ball.moveY(ball.getSpeedY());

				if ((ball.getX() <= 0.0D) || (ball.getX() >= 800.0D - ball.getWidth())) {
					ball.setSpeedX(-ball.getSpeedX());
				}

				if ((ball.getY() <= 0.0D) || (ball.getY() >= 600.0D - ball.getHeight())) {
					ball.setSpeedY(-ball.getSpeedY());
				}

				if (ball.isCollisionWith(mainBrick)) {
					ball.setSpeedY(-ball.getSpeedY());
				}

				for (Brick brick : bricks) {
					if (ball.isCollisionWith(brick)) {
						brick.setHp(brick.getHp() - 1);
						ball.setSpeedY(-ball.getSpeedY());
						if (brick.getHp() <= 0) {
							destroyObject(brick);
						}
						break;
					}
				}
			}
		}, new KeyValue[0]);

		this.timeline.getKeyFrames().add(this.keyFrame);
		this.timeline.play();
	}

	private void destroyObject(final BaseObject brick) {
		FadeTransition fade = new FadeTransition(Duration.millis(200.0D), brick);
		fade.setFromValue(1.0D);
		fade.setToValue(0.0D);
		fade.setOnFinished(new EventHandler<ActionEvent>() {
			public void handle(ActionEvent t) {
				getChildren().remove(brick);
			}
		});
		this.bricks.remove((Brick) brick);
		fade.play();
	}

	private void initLevel() {
		LevelLoader.load(this, 1);
	}

	public void addChild(Parent parent) {
		getChildren().add(parent);
	}

	public CopyOnWriteArrayList<Brick> getBricks() {
		return this.bricks;
	}
}

GameScene里包含了一个brick砖块的集合。我们鼠标控制的挡板MainBrick和一个小球Ball。

我们通过创建一个时间轴,在帧中进行小球的移动,碰撞判断。

每次碰撞brick的hp就减一,当hp小于或等于0时,执行destroyobject方法。这个方法通过对brick执行一个FadeTransition,让它进行一个渐变的消失。然后从集合中移除。


大家可以看看效果:


当然,这里的碰撞会有问题。然后与挡板的碰撞,也没有进行角度等的判断。不过没关系,这些都可以在以后解决。

我们首先要完成的是整个游戏的流程。

下一课里,我们将会创建游戏菜单,然后进行关卡的完成得分等。


转载请注明出处: http://blog.csdn.net/ml3947


------------------------------------------------------------------------------------------------------------------------

最近在捣鼓着自己的个人博客。申请了一个域名和一个空间。目前博客是专注于JavaFX技术的,而且正在进行WJFXGameEngine的开发工作,申请了个GoogleCode开源项目。进度还是不错的,就是JavaFX目前的Canvas上面的效率不敢恭维。

不过我相信以后会有很大的改进的,毕竟Canvas也是在最近版本才出来的,而且在JDK 8上也有JavaFX 3D。

等我个人开发的WJFXGameEngine的游戏示例和JavaFX的软件增多后,再在文章置顶网站链接,到时候大家可以去看看。

------------------------------------------------------------


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics