`

JavaFX打砖块游戏开发 第一课

阅读更多

突然发现,之前还有个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/

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics