JavaFX战旗类游戏开发 第四课 属性框和菜单的创建
来源:互联网 发布:摩拜单车在上海的数据 编辑:程序博客网 时间:2024/05/16 12:35
上一课中,我们创建了游戏角色。这节课中,我们将会创建菜单,以便后面使用。
由于只是Demo,我创建的是最简单的形式,如下图所示:
基于游戏开发中的UI控件通常需要有事件(比如图中的移动,攻击,待机,是有事件处理的),我们应该首先创建自己的文字控件。
文字控件代码如下:
import com.sun.javafx.tk.FontMetrics;import com.sun.javafx.tk.Toolkit;import javafx.scene.canvas.GraphicsContext;import javafx.scene.paint.Color;import javafx.scene.paint.Paint;import javafx.scene.text.Font;/** * 文字物件 * @author Wing Mei */@SuppressWarnings("restriction")public class TextObject extends BaseObject { private String text; private Font font = Font.getDefault(); private double fontSize = Font.getDefault().getSize(); private Paint color = Color.BLACK; public TextObject() {} public TextObject(String text){ this.text = text; } @Overridepublic void draw(GraphicsContext gContext) {gContext.save();gContext.setFont(font);gContext.setFill(color);if (text != null) {gContext.fillText(text, getX(), getY());}gContext.restore();}@Overridepublic void update() {}@Override public boolean isCollisionWith(double x,double y){ if(x > getX() && y > getY() - getHeight() && x < getX() + getWidth() && y < getY() - getHeight() + getHeight()){ return true; } return false; }@Overridepublic double getWidth(){ FontMetrics fm = Toolkit.getToolkit().getFontLoader().getFontMetrics(font); return fm.computeStringWidth(text);}@Overridepublic double getHeight(){ FontMetrics fm = Toolkit.getToolkit().getFontLoader().getFontMetrics(font); return fm.getLineHeight();}public String getText() {return text;}public void setText(String text) {this.text = text;}public Font getFont() {return font;}public void setFont(Font font) {this.font = font;}public Paint getColor() {return color;}public void setColor(Paint color) {this.color = color;} public double getFontSize() { return fontSize; } public void setFontSize(double fontSize) { this.fontSize = fontSize; this.font = new Font(font.getFamily(), fontSize); }}由于JavaFX的文字坐标貌似是从左下角开始的,所以碰撞的方法进行了处理。这里,我们使用了FontMetrics来获取文字的宽度和高度(感觉高度不是很准确的样子,先凑合着使用)。
有了文字控件,属性框和操作菜单就要简单很多。其实就是一个背景+N个文字控件而已。
下面是属性框的代码:
import javafx.scene.canvas.GraphicsContext;import javafx.scene.paint.Color;import javafx.scene.paint.Paint;public class PropertyMenu extends BaseObject {private TextObject[] textObjects;private Paint color = Color.BLACK;private int spaceLine = 5;public PropertyMenu(int width, int height) {setWidth(width);setHeight(height);textObjects = new TextObject[7];for (int i = 0; i < textObjects.length; i++) {textObjects[i] = new TextObject();textObjects[i].setColor(Color.WHITE);}} /** * 初始化载入某个角色的属性 * @param player 角色 */public void initPlayer(BasePlayer player) {setProperty(textObjects[0], "姓名", player.getName());setProperty(textObjects[1], "等级", String.valueOf(player.getLv()));setProperty(textObjects[2], "攻击", String.valueOf(player.getAttack()));setProperty(textObjects[3], "防御", String.valueOf(player.getDefense()));setProperty(textObjects[4], "移动力", String.valueOf(player.getMove()));setProperty(textObjects[5], "HP", String.valueOf(player.getHp()) + "/" + player.getHpMax());setProperty(textObjects[6], "EXP", String.valueOf(player.getExp()));}private void setProperty(TextObject textObject, String propertyName, String value) {textObject.setText(propertyName + ":" + value);textObject.setFontSize(16);}@Overridepublic void draw(GraphicsContext gContext) {gContext.save();gContext.setStroke(color);gContext.setGlobalAlpha(0.8f);gContext.fillRect(x, y, width, height);if (textObjects != null) {for (int i = 0; i < textObjects.length; i++) {textObjects[i].setX((getWidth() - textObjects[i].getWidth()) / 2 + getX());textObjects[i].setY(getY() + spaceLine * (i + 1) + textObjects[i].getHeight() * (i + 1));textObjects[i].draw(gContext);}}gContext.restore();}@Overridepublic void update() {}}属性框的代码很简单,就是绘制一个背景+N个TextObject。通过传入BasePlayer来设置每个TextObject的值。由于属性框无需事件,我们在这里也不做事件处理。
另外,本Demo纯属学习使用,并未做深层次的类结构划分(在我另外的游戏开发库中有做),所以文字控件的绘制需要坐标相对于当前菜单的坐标,需要进行一定的处理。
接下来是操作菜单的代码:
import javafx.scene.canvas.GraphicsContext;import javafx.scene.input.MouseEvent;import javafx.scene.paint.Color;import javafx.scene.paint.Paint;public class ActionMenu extends BaseObject {private TextObject[] textObjects;private Paint color = Color.BLACK;private int spaceLine = 5;private OnMenuItemClickListener onMenuItemClickListener;public ActionMenu(String[] strs, int width, int height) {setWidth(width);setHeight(height);textObjects = new TextObject[strs.length];for (int i = 0; i < textObjects.length; i++) {textObjects[i] = new TextObject();textObjects[i].setText(strs[i]);textObjects[i].setColor(Color.WHITE);textObjects[i].setFontSize(16);}} /** * 鼠标事件,会执行回调 * @param e 鼠标事件 */public void onMousePressed(MouseEvent e) {if (onMenuItemClickListener != null)for (int i = 0; i < textObjects.length; i++) {if (textObjects[i].isCollisionWith(e.getX(), e.getY())) {onMenuItemClickListener.onMenuItemClick(i);}}}@Overridepublic void draw(GraphicsContext gContext) {gContext.save();gContext.setGlobalAlpha(0.8f);gContext.setStroke(color);gContext.fillRect(x, y, width, height);for (int i = 0; i < textObjects.length; i++) {textObjects[i].setX((getWidth() - textObjects[i].getWidth()) / 2 + getX());textObjects[i].setY(getY() + spaceLine * (i + 1) + textObjects[i].getHeight() * (i + 1));textObjects[i].draw(gContext);}gContext.restore();}@Overridepublic void update() {}public TextObject[] getTextObjects() {return textObjects;}public void setTextObjects(TextObject[] textObjects) {this.textObjects = textObjects;}public OnMenuItemClickListener getOnMenuItemClickListener() {return onMenuItemClickListener;}public void setOnMenuItemClickListener(OnMenuItemClickListener onMenuItemClickListener) {this.onMenuItemClickListener = onMenuItemClickListener;}public interface OnMenuItemClickListener {public void onMenuItemClick(int index);}}
在操作菜单中,我们新增加了一个OnMenuItemListener,来用于执行鼠标点击后的回调。这也是Java事件机制中很常用的做法。另外,定义了一个onMousePressed方法,注意,由于是自定义的类,这里的onMousePressed事件是不会执行的。我们需要在Canvas的鼠标事件中,调用该方法来模拟执行鼠标操作事件。主要是鼠标点击,通过遍历TextObject列表来判断点击的是哪个TextObject,然后通过OnMenuItemListener来执行回调。方便我们在其他地方做事件处理。
这样一来,我们两个菜单就都创建好了。接下来,加进我们的Canvas中看看效果吧。
在MainCanvas中加入定义:
// 操作菜单private ActionMenu actionMenu;// 属性菜单private PropertyMenu propertyMenu;
然后初始化:
// 初始化操作菜单actionMenu = new ActionMenu(new String[] { "移动", "攻击", "待机" }, 50, 100);actionMenu.setLocation(100, 50);actionMenu.setOnMenuItemClickListener(index ->{ System.out.println("你点击的是:" + index);});// 属性菜单propertyMenu = new PropertyMenu(100, 200);propertyMenu.initPlayer(players.get(0));// 鼠标事件setOnMousePressed(e ->{actionMenu.onMousePressed(e);});
在这里的两个事件都用的是Lambada表达式,不熟悉JDK8的可以自行修改。另外,PropertyMenu由于要载入Player的属性,请在Player都初始化完成后,再添加该代码。
接下来,我们需要将两个菜单绘制出来,在draw方法中添加如下代码:
actionMenu.draw(gContext);propertyMenu.draw(gContext);
然后我们可以运行看看效果了:
尝试一下事件把,点击移动,攻击,待机等等。
事件执行良好吧?
那么这一节课到此结束了。
下一节课,我们将会用到定时器的内容,将会创建一个定时器供后面使用。
本文章为个人原创,版权所有,转载请注明出处:http://blog.csdn.net/ml3947。另外我的个人博客:http://www.wjfxgame.com.
2 0
- JavaFX战旗类游戏开发 第四课 属性框和菜单的创建
- JavaFX战旗类游戏开发 第三课 创建游戏角色
- JavaFX战旗类游戏开发 第五课 定时器的应用
- JavaFX战旗类游戏开发 第二课 游戏地图绘制
- JavaFX战旗类游戏开发 第一课 概述
- JavaFX战旗类游戏开发 第六课 移动范围的获取
- JavaFX战旗游戏开发 第七课 回合逻辑(完)
- JavaFX开发的2048游戏
- JavaFX游戏开发--第一课 精灵动画
- JavaFX打砖块游戏开发 第一课
- JavaFX打砖块游戏开发 第二课
- JavaFX打砖块游戏开发 第三课
- JavaFX游戏开发--第一课 精灵动画
- JavaFX游戏开发--第二课 基础游戏框架
- 战旗类DotA游戏原代码及项目报告
- JavaFX游戏开发效率浅谈
- vc.net 游戏开发 第四章 创建Direct3D渲染和显示3D三角形
- 用Eclipse开发J2ME手机游戏 第四讲 创建经典的HelloWorld程序
- 数据去重
- hdoj.2014 青年歌手大奖赛_评委会打分 20140723
- 如何获得程序运行时间?
- 在页面上添加“QQ交谈”连接。
- mac下截屏快捷键
- JavaFX战旗类游戏开发 第四课 属性框和菜单的创建
- Java内存泄露的理解与解决
- HDOJ2007
- CAD的操作(二)
- 设置ajax完成操作后,过几秒跳转
- 保存文件的三种方法
- Ubuntu-14.04.1 desktop安装时及安装后遇到的小问题
- ios 官方例子
- 全国最大的太阳基地