`

JavaFX游戏开发--第二课 基础游戏框架

 
阅读更多

之前有一个第一课,讲精灵动画的。那个时候JavaFX 2.2还没出来,所以那一课中根本就没有用到Canvas。


但是既然在JavaFX 2.2出来后,新增加了Canvas,那么就大不一样了。


这一章教程中,我们将在JavaFX中创建一个简单的游戏框架。


首先大家看一看结构,主要的几个类。


这一课,我们只讲基础游戏框架,所以我们只看WApplication,WSystem,WObject 和 WScreen这四个类。


由这四个类组成一个简单的游戏框架。


首先是所有的游戏Object的基类WObject:

package org.wing.jfx.game.core.component;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.canvas.GraphicsContext;

/**
 * @author wing
 * @date 2012/8/25
 */
public abstract class WObject{
    protected DoubleProperty widthProperty = new SimpleDoubleProperty(0);
    protected DoubleProperty heightProperty = new SimpleDoubleProperty(0);
    protected DoubleProperty xProperty = new SimpleDoubleProperty(0);
    protected DoubleProperty yProperty = new SimpleDoubleProperty(0);    
    protected BooleanProperty visibleProperty = new SimpleBooleanProperty(true);
    protected BooleanProperty updateProperty = new SimpleBooleanProperty(true);
    
    public WObject(double x, double y, double width, double height){
    	this.xProperty = new SimpleDoubleProperty(x);
    	this.yProperty = new SimpleDoubleProperty(y);
    	this.widthProperty = new SimpleDoubleProperty(width);
    	this.heightProperty = new SimpleDoubleProperty(height);
    }
    
    public WObject(){
    	this.xProperty = new SimpleDoubleProperty(0);
    	this.yProperty = new SimpleDoubleProperty(0);
    	this.widthProperty = new SimpleDoubleProperty(0);
    	this.heightProperty = new SimpleDoubleProperty(0);    	
    }
    
    
    public abstract void draw(GraphicsContext gc);
    
    public abstract void update();   
    
    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 BooleanProperty visibleProperty(){
    	return visibleProperty;
    }  
    public void setVisible(boolean isVisible){
    	this.visibleProperty.set(isVisible);
    }
    public boolean isVisible(){
    	return visibleProperty.get();
    }
 
    public BooleanProperty updateProperty(){
    	return updateProperty;
    }  
    public void setUpdate(boolean isUpdate){
    	this.updateProperty.set(isUpdate);
    }
    public boolean isUpdate(){
    	return updateProperty.get();
    }
    
    
    public void moveX(double x){
    	this.xProperty.set(getX() + x);
    }
    
    public void moveY(double y){
    	this.yProperty.set(getY() + y);
    }
    
    public boolean isCollisionWith(WObject baseObject){
    	if(getX() + getWidth() > baseObject.getX() && getX() < baseObject.getX() + baseObject.getWidth() && getY() + getHeight() > baseObject.getY() && getY() < baseObject.getY() + baseObject.getHeight()){
    		return true;
    	}
    	return false;
    }   
}

这个类很简单,主要是x,y,width,height,visible,update几个属性,使用了JavaFX中可进行绑定的Property。

另外是几个简单的移动碰撞的方法。


可能以后会增加一些别的东西,但是目前这个类就是这样的。



接下来是WScreen类,这个类是继承于Canvas的,意味着这是一个容器,可以绘制的容器。由于我们的WObject并

未继承任何JavaFX的系统类,那么所有的WObject都需要在WScreen中渲染。而且还需要WScreen提供一个刷新界

面的方法。


package org.wing.jfx.game.core.screen;

import java.util.ArrayList;
import java.util.List;

import org.wing.jfx.game.core.component.WObject;

import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.KeyEvent;
import javafx.util.Duration;
/**
 * Screen
 * @author wing
 * 2012/8/25
 */
public abstract class WScreen extends Canvas {
	protected enum GameState {GAME_MENU, GAME_START, GAME_CONTINUE, GAME_HELP, GAME_SET,GAME_EXIT,GAME_PAUSE};
	private List<WObject> mObjects = new ArrayList<WObject>();
	private Timeline timeline;
	private KeyFrame keyFrame;
	private int duration = 10;
    protected GameState mGameState = GameState.GAME_MENU;
	public WScreen(double width, double height) {
		super(width, height);
		initTimeLine();	
	}
	
	public void initEvents(){
		getParent().getScene().setOnKeyPressed(new EventHandler<KeyEvent>() {

			@Override
			public void handle(KeyEvent event) {
				onKeyPressed(event);
			}
		});
		getParent().getScene().setOnKeyReleased(new EventHandler<KeyEvent>() {

			@Override
			public void handle(KeyEvent event) {
				onKeyReleased(event);
			}
		});
	}
	
	protected abstract void onKeyPressed(KeyEvent event);
	
	protected abstract void onKeyReleased(KeyEvent event);
	

	/**
	 * add the object
	 * @param baseObject the object to be add
	 */
	public void addObject(WObject baseObject){
		this.mObjects.add(baseObject);
	}
	
	/**
	 * remove the object
	 * @param baseObject the object to be remove
	 */
	public void removeObject(WObject baseObject){
		this.mObjects.remove(baseObject);
	}
	
	/**
	 * remove the object with the index
	 * @param index the index of the object
	 */
	public void removeObjectAtIndex(int index){
		this.mObjects.remove(index);
	}
	
	/**
	 * draw the objects
	 * @param gc
	 */
	public void draw(GraphicsContext gc){
		gc.clearRect(0, 0, getWidth(), getHeight());
		for (int i = 0; i < mObjects.size(); i++) {
			WObject wObject = mObjects.get(i);
			if (wObject.isVisible()) {
				wObject.draw(gc);
			}
		}
	}
	
	/**
	 * update all the objects
	 */
	public void update(){
		for (int i = 0; i < mObjects.size(); i++) {
			WObject wObject = mObjects.get(i);
			if (wObject.isUpdate()) {
				mObjects.get(i).update();
			}
		}
	}
	
	/**
	 * init the timeline
	 */
	private void initTimeLine() {
		timeline = new Timeline();
		timeline.setCycleCount(Timeline.INDEFINITE);

		keyFrame = new KeyFrame(Duration.millis(duration), new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent arg0) {
				draw(getGraphicsContext2D());
				update();
			}
		});
		timeline.getKeyFrames().add(keyFrame);
	}
	
	/**
	 * start the update timeline
	 */
	public void start(){
		timeline.play();
	}
	
	/**
	 * pause the update timeline
	 */
	public void pause(){
		timeline.pause();
	}
	
	/**
	 * stop the update timeline
	 */
	public void stop(){
		timeline.stop();
	}
	
}

由上面的代码可见,我们包含一个游戏状态的枚举(目前没有用到),一个WObject的列表。然后通过创建一个无

限循环的Timeline来进行所有的WObject的绘制和刷新(可能有更好的方法,但目前这个游戏框架中暂时这样做)。

同时可以进行timeline的控制。

同样的,这里也暂时只提供了KeyPressed和KeyReleased两个事件方法,不过鼠标的事件添加也是很简单的。


下面看看WSystem,这个类暂时很简单,只是记录窗口的大小的类。因为只是简单的框架,其他的东西可能在后续

添加进去。

一般来说使用公共静态变量之类的并不符合Java规范,不过要纠结于此的话,可以将它更改为单例模式,并赋予一

些set get方法。

public class WSystem {
	public static int WIDTH = 800, HEIGHT = 600;
	
	public static void init(int width, int height){
		WIDTH = width;
		HEIGHT = height;
	}
}

再下面看看WApplication,这个是继承与JavaFX中的Application类,作为应用程序的启动类,JavaFX的这个游戏框

架中,任何示例的主类都需要继承WApplication。

package org.wing.jfx.game.core;

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;

public abstract class WApplication extends Application {
    private Group mGroup;
    private Scene mScene;
	@Override
	public void start(Stage primaryStage) throws Exception {
		loadBefore();
		mGroup= new Group();
		mScene = new Scene(mGroup, WSystem.WIDTH, WSystem.HEIGHT);		
		loadEnd();
		showStage(primaryStage);
	}
	
	protected abstract void loadBefore();
	
	protected abstract void loadEnd();
	
	protected void showStage(Stage stage){
		stage.setScene(mScene);
		stage.show();
	}
	
	protected Scene getScene(){
		return mScene;
	}
	
	protected Group getRoot(){
		return mGroup;
	}
	
	public void setWindowSize(int width, int height){
		WSystem.init(width, height);
	}

}

这里的方法也是很容易理解的。


那么,我们就来看看如何使用这个简单的框架来构造JavaFX程序吧。


首先我们创建一个Rect继承WObject,这样会出现两个需要实现的方法:draw 和 update。


我们这里就简单的画一个矩形,然后在update方法进行移动。


package org.wing.jfx.game.test;

import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;

import org.wing.jfx.game.core.component.WObject;

public class Rect extends WObject {
    
    public Rect(double x, double y, double width, double height){
    	super(x, y, width, height);
    }
    
	@Override
	public void draw(GraphicsContext gc) {
         gc.setFill(Color.CHOCOLATE);
         gc.fillRect(getX(), getY(), getWidth(), getHeight());
	}

	@Override
	public void update() {
         moveX(1);
	}

}

这就是这个框架中自己实现的一个简单的Object。


然后创建一个自己的Screen。命名为TestScreen,然后继承WScreen。


当然,只出现了两个Key事件的方法,我们可以在TestScreen中创建上面的Rect,然后添加到TestScreen中,再通

过Key事件来进行控制。


package org.wing.jfx.game.test;

import javafx.scene.input.KeyEvent;

import org.wing.jfx.game.core.WSystem;
import org.wing.jfx.game.core.screen.WScreen;

public class TestScreen extends WScreen {
    private Rect player;
	public TestScreen(double width, double height) {
		super(width, height);
		
		player = new Rect(50, 50, 100, 100);
		addObject(player);
	}

	@Override
	protected void onKeyPressed(KeyEvent event) {
       switch (event.getCode()) {
	case UP:
		player.moveY(-1);
		break;
	case DOWN:
		player.moveY(1);
		break;
	case ENTER:
		addObject(new Rect(Math.random() * WSystem.WIDTH, Math.random() * WSystem.HEIGHT, 100, 100));
		break;
	default:
		break;
	}
	}

	@Override
	protected void onKeyReleased(KeyEvent event) {

	}

}

如上面的代码所示,我们在构造函数中创建了一个坐标50,50 宽 100 高 100 的Rect。然后在事件处理中,上下控

制Rect的移动,通过Enter键,在屏幕上随机增加一个Rect。


由于我们在Rect的Update方法中增加了Move的操作,所以所有的Rect将一直往右移动。


下面创建我们的主类MainClass继承WApplication:


package org.wing.jfx.game.test;

import javafx.scene.paint.Color;
import javafx.stage.Stage;

import org.wing.jfx.game.core.WApplication;
import org.wing.jfx.game.core.WSystem;

public class MainClass extends WApplication {

	@Override
	protected void loadBefore() {
		setWindowSize(800, 600);
	}

	@Override
	protected void loadEnd() {		
		TestScreen testScreen = new TestScreen(WSystem.WIDTH, WSystem.HEIGHT);
		getRoot().getChildren().add(testScreen);
		testScreen.start();
		testScreen.initEvents();
		
		getScene().setFill(Color.BLACK);
	}
	
	@Override
	protected void showStage(Stage stage){
		super.showStage(stage);
		stage.setTitle("JavaFX游戏开发 第二课 基础游戏框架");
	}
	public static void main(String[] args) {
		launch(args);
	}
}

这个就是我们的主类了,我们在loadBefore中设定了窗口的大小,在loadEnd中创建了TestScreen,启动了

TestScreen的循环Timeline,载入了TestScreen的事件,并设定场景背景为黑色,然后重写了父类的showStage方法

修改了程序的标题。


后面的就是用这个简单的游戏框架创建的简单的程序了,只要整个框架搭建好,后面每次进行游戏开发的时候,就

可以节省很多的代码量了。



运行结果倒是不怎样,不过我们在这一章中,主要是构建了游戏框架。


在下一章中,我们会增加动画精灵以及地图的绘制。


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




分享到:
评论

相关推荐

    JavaFX-Game-Engine:使用 JavaFX 制作的游戏引擎

    总之,JavaFX-Game-Engine是JavaFX技术在游戏开发领域的实践,它展示了JavaFX如何被用来创建一个功能齐全的游戏开发框架,为游戏开发者提供了快速构建游戏的基础。通过深入研究这个项目,开发者不仅可以提升JavaFX...

    java游戏开发--书

    2. **图形库和API**:Java提供了丰富的图形库,如JavaFX和AWT/Swing,用于创建游戏界面。书中可能会详细讲解如何使用这些库来绘制游戏场景、处理图形和动画。 3. **游戏架构设计**:游戏开发需要一个稳定且可扩展的...

    JavaFX2.0基础教程(整合版)

    #### 四、JavaFX开发入门 - **开发流程**:从创建项目到最终部署的完整开发流程。 - **代码示例**:提供实际的代码示例,帮助理解开发过程中的具体操作。 #### 五、FXML入门教程 **5.1 为何使用FXML** - **FXML ...

    使用JavaFX2.0编写国际象棋游戏

    在本项目中,我们将探讨如何使用JavaFX 2.0框架来开发一款国际象棋游戏。JavaFX是一个用于创建桌面、Web以及移动设备上富客户端应用程序的强大的图形库。通过这个项目,我们可以深入理解JavaFX的基本概念,以及如何...

    JavaFX初学者指南

    1. **Hello World示例**:编写第一个JavaFX程序通常从创建一个简单的“Hello World”窗口开始,了解如何设置主类、启动方法以及创建基本的界面元素。 2. **Node和Scene**:在JavaFX中,所有可视化的元素都是Node对象...

    JavaFX编程程序

    通过学习和实践以上知识点,你可以逐步掌握使用JavaFX开发游戏程序的技能,从而创造出引人入胜的用户体验。同时,随着技术的发展,JavaFX也不断更新,比如引入JavaFX 11及以后版本,需要与OpenJFX和模块系统配合使用...

    java框架开发雷电游戏

    在实际开发中,开发者可能会使用一些特定的Java游戏框架,如LibGDX,它提供了一套完整的游戏开发工具,包括图形渲染、物理引擎、输入处理等,大大简化了游戏开发过程。如果"雷电游戏"使用了类似框架,那么开发者将能...

    Android游戏与应用开发最佳学习路线图

    ### Android游戏与应用开发最佳学习路线图 #### 一、路线图概览 本学习路线图旨在为初学者提供一个全面且系统的学习路径,帮助其掌握Android应用与游戏开发的核心技能。通过本路线图的学习,学员将能够从零开始...

    一款利用JavaFx编写的飞机大战小游戏PlaneShoot.zip

    标题中的“一款利用JavaFx编写的飞机大战小游戏...以上就是基于JavaFX开发“PlaneShoot”飞机大战游戏可能涉及的主要技术和知识领域。通过分析源代码和相关文档,我们可以深入理解JavaFX的游戏开发过程和技巧。

    Java游戏开发ppt

    11. **框架和库**:有许多开源的Java游戏框架,如LibGDX、Slick2D和jMonkeyEngine,它们提供了许多预设的功能,简化了游戏开发过程。 12. **游戏设计**:除了技术层面,游戏设计也非常重要,包括游戏规则、关卡设计...

    马里奥java游戏开发

    2. **图形库与游戏框架**: - 在Java中,我们可以使用如JavaFX或LibGDX这样的图形库来创建游戏界面。JavaFX提供了丰富的UI组件和2D图形功能,而LibGDX则是一个强大的跨平台游戏开发框架,包含丰富的游戏开发工具和...

    Java开发-使用Java语言实现刷微信跳一跳小游戏的分数.zip

    2. **图形用户界面(GUI)**:项目可能使用了Java的Swing或JavaFX库来创建游戏界面,这涉及到组件的布局管理、事件监听和处理,以及自定义组件的绘制。 3. **网络编程**:由于需要与微信服务器交互,项目可能涵盖了...

    程序设计JAVA(游戏开发).zip

    3. **图形与动画**:Java的AWT和Swing库可以用于创建基本的2D游戏,而更高级的游戏可能需要使用JavaFX或者第三方库如LibGDX来实现更复杂的图形渲染和动画效果。学习如何使用这些库来绘制游戏场景、处理碰撞检测、...

    最新45款Java手机游戏开发源代码免费下载

    通过分析源代码,可以学习到如何构建模块化的游戏框架。 2. **图形渲染**:学习如何使用Java 2D或3D图形API(如JavaFX或JOGL)创建游戏场景,理解渲染循环和动画更新。 3. **碰撞检测**:游戏中的碰撞检测是关键,...

    纯Java实现的游戏引擎框架,开发中…….zip

    在`J2D-GameEngine-master`这个项目中,我们可以看到作者是如何组织这些组件并构建出一个功能齐全的游戏框架的。通过阅读源码,我们可以学习到如何在实际项目中应用Java技术,以及如何优化代码性能,提高游戏的流畅...

    基于Java语言的游戏软件开发(含源文件).rar_Java游戏_软件开发

    9. **游戏框架**:如LibGDX或Slick2D这样的第三方框架可以简化游戏开发过程,提供游戏开发所需的各种组件和工具,如图像加载、物理引擎等。 10. **源码分析**:提供的源文件是学习的好材料,通过阅读和分析,可以...

    21天学会用JAVA开发网络游戏

    第二阶段:图形与用户界面 游戏的视觉表现至关重要,因此你需要掌握Java的图形库,如JavaFX或Swing,来创建游戏的用户界面。这包括绘制图形、动画制作以及交互式元素的设计。理解坐标系统、颜色模型和图像处理将帮助...

    使用java开发青鸟迷你游戏平台

    使用Java Swing或JavaFX库可以创建图形用户界面,而Spring框架可以用于后端服务的开发。 2. **游戏进程与晋级系统**: 当用户选择并开始游戏时,平台需要处理游戏逻辑和玩家的进度。这可能涉及到状态机的设计,...

    java游戏开发大全图书

    《Java游戏开发大全》是一本全面探讨使用Java语言进行游戏开发的专业书籍,旨在为读者提供一个深入了解游戏开发的平台。本书覆盖了从基础概念到高级技术的广泛领域,旨在帮助初学者和有经验的开发者提升在Java游戏...

    “运指如飞”打字游戏,2020-2021学年第一学期Java课程设计.zip

    《“运指如飞”打字游戏——2020-2021学年第一学期Java课程设计》 这是一款基于Java编程语言的打字练习游戏,旨在帮助用户提高打字速度和准确性,实现“运指如飞”的打字技巧。在2020-2021学年的第一学期,作为Java...

Global site tag (gtag.js) - Google Analytics