突然发现,之前还有个JavaFX游戏开发 第一课。不过,这两个教程并不冲突。目前这个系列是做一个完整的打砖块游戏。
第一课主要用到的知识有,JavaFX的动态绑定,Rectangle的使用,简单的MouseMove事件,BoxBlur特效。
那么,我们首先创建一个名叫BrickBlock的JavaFX Project。本人是使用的e(fx)clipse进行开发的。
e(fx)clipse的官方网站为:http://www.efxclipse.org/ ,下载整合插件的eclipse即可。
首先创建一个游戏对象的基类BaseObject,继承于Parent。
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.Parent;
/**
* @author wing
* @date 2012/7/26
*/
public abstract class BaseObject extends Parent{
protected DoubleProperty widthProperty = new SimpleDoubleProperty(0);
protected DoubleProperty heightProperty = new SimpleDoubleProperty(0);
protected DoubleProperty xProperty = new SimpleDoubleProperty(0);
protected DoubleProperty yProperty = new SimpleDoubleProperty(0);
public DoubleProperty widthProperty() {
return widthProperty;
}
public double getWidth(){
return widthProperty.get();
}
public void setWidth(double width){
this.widthProperty.set(width);
}
public DoubleProperty heightProperty() {
return heightProperty;
}
public double getHeight(){
return heightProperty.get();
}
public void setHeight(double height){
this.heightProperty.set(height);
}
public DoubleProperty xProperty() {
return xProperty;
}
public double getX(){
return xProperty.get();
}
public void setX(double x){
this.xProperty.set(x);
}
public DoubleProperty yProperty() {
return yProperty;
}
public double getY(){
return yProperty.get();
}
public void setY(double y){
this.yProperty.set(y);
}
public void moveX(double x){
this.xProperty.set(getX() + x);
}
public void moveY(double y){
this.yProperty.set(getY() + y);
}
public boolean isCollisionWith(BaseObject baseObject){
if(getX() + getWidth() > baseObject.getX() && getX() < baseObject.getX() + baseObject.getWidth() && getY() + getHeight() > baseObject.getY() && getY() < baseObject.getY() + baseObject.getHeight()){
return true;
}
return false;
}
}
可以看到,基类BaseObject中,包含有坐标和宽高的属性,并且还有一个检测碰撞的isCollisionWith方法。
大家可以看到,基类BaseObject中没有使用常规的数据类型,而是使用的DoubleProperty。而DoubleProperty这样
的类型,也正是JavaFX中的动态绑定的机制,set get方法只是改变DoubleProperty的值。
为了方便,isCollisionWith只是简单的矩形碰撞。
下面我们创建一个打砖块中底部拦截的游戏对象类MainBrick。
import javafx.scene.effect.BoxBlur;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import org.wing.game.BrickBlock;
/**
* @author wing
* @date 2012/7/25
*/
public class MainBrick extends BaseObject{
private Rectangle mRectangle;
private BoxBlur mBlur;
public MainBrick(){
mRectangle = new Rectangle();
mRectangle.widthProperty().bindBidirectional(widthProperty());
mRectangle.heightProperty().bindBidirectional(heightProperty());
mRectangle.xProperty().bindBidirectional(xProperty());
mRectangle.yProperty().bindBidirectional(yProperty());
mRectangle.setArcWidth(20);
mRectangle.setArcHeight(20);
mRectangle.setFill(Color.YELLOW);
mBlur = new BoxBlur();
mBlur.setWidth(5);
mBlur.setHeight(5);
mRectangle.setEffect(mBlur);
setWidth(150);
setHeight(25);
getChildren().add(mRectangle);
}
public void onMouseMove(MouseEvent event){
if (event.getX() >= getWidth()/2 && event.getX() <= BrickBlock.WIDTH - getWidth()/2) {
setX(event.getX() - getWidth()/2);
}
}
}
MainBrick中的代码也很简单。
1.创建了一个Rectangle,这里使用了bindBidirectional方法,这个方法在JavaFX中的意义是双向绑定,只能对Property使用。
我们将Rectangle的宽度,高度,坐标与基类的属性进行了双向绑定,也就是说整个MainBrick已经是一个Rectangle了。
2.设置Rectangle的圆角,让它成为一个圆角矩形。
3.创建了一个BoxBlur效果,通过setEffect给Rectangle设置BoxBlur效果。
4.设置MainBrick的宽度和高度,由于进行了双向绑定,在这里setWidth,setHeight属性将会同步更新到Rectangle的width和height属性。
5.这里还有一个onMouseMove的事件,主要是让Rectangle跟着鼠标动,通过判断使矩形不会超出左右边界,并且将Rectangle中心与鼠标对齐。当然,这个事件现在是不能执行的。
接下来,我们创建一个游戏场景类GameScene,继承Parent。
import org.wing.game.object.MainBrick;
import javafx.animation.KeyFrame;
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, height;
private Rectangle background;
private MainBrick mainBrick = new MainBrick();
public GameScene(int width, int height){
this.width = width;
this.height = height;
initGameObjects();
}
private void initGameObjects(){
background = new Rectangle(0, 0, this.width, this.height);
background.setOnMouseMoved(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
mainBrick.onMouseMove(event);
}
});
background.setFill(Color.BLACK);
mainBrick.setX(0);
mainBrick.setY(height - mainBrick.getHeight());
getChildren().add(background);
getChildren().add(mainBrick);
}
}
在游戏场景类GameScene中,我们通过构造函数,传入场景的宽度和高度。
然后创建了一个背景Rectangle。
设置Rectangle的onMouseMove事件,在其中执行MainBrick中我们刚才写的onMouseMove函数。通过setFill将Rectangle的填充色设为黑色。
接下来,将MainBrick的作为设置为屏幕最下方。
最后,通过getChildern().add()将背景Rectangle和MainBrick添加进GameScene中。
最后就是我们的JavaFX Main Class了。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
* @author wing
* @date 2012/7/26
*/
public class BrickBlock extends Application {
public static final int WIDTH = 800;
public static final int HEIGHT = 600;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
GameScene root = new GameScene(WIDTH, HEIGHT);
primaryStage.setTitle("BrickBlock");
primaryStage.setScene(new Scene(root, WIDTH, HEIGHT));
primaryStage.show();
}
}
大家可以看到,由于将游戏对象和游戏场景都分离出来,主类已经变得很简洁了。
那么我们运行运行看看效果。
图中的黄色的砖块会跟着鼠标移动,并且不会超过左右的边界。(截图看不到鼠标...)
看似效果很简单,不过我们整体的结构已经差不多了,这将有利于我们后续的开发。
在第二课中,我们将会增加一个小球在这个空间中弹来弹去,并且可以与图中的黄色砖块进行碰撞。
转载请注明出处:http://blog.csdn.net/ml3947/