在上一节课程中,我们学习了在JavaFX中绘制游戏地图。这一节课,我们将会创建我们的游戏角色。
首先,同样的,我们创建一个简单的基类。
import javafx.scene.canvas.GraphicsContext; /** * 游戏物体基类 * @author Wing Mei */ public abstract class BaseObject { protected double x, y; protected double width,height; protected boolean isVisible; public abstract void draw(GraphicsContext gContext); public abstract void update(); public void moveX(double x){ setX(getX() + x); } public void moveY(double y){ setY(getY() + y); } public void move(double x,double y){ moveX(x); moveY(y); } public void setLocation(double x,double y){ setX(x); setY(y); } public double getX() { return x; } public void setX(double x) { this.x = x; } public double getY() { return y; } public void setY(double y) { this.y = y; } public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } public double getHeight() { return height; } public void setHeight(double height) { this.height = height; } public boolean isCollisionWith(double x,double y){ if(x > getX() && y > getY() && x < getX() + getWidth() && y < getY() + getHeight()){ return true; } return false; } public boolean isVisible() { return isVisible; } public void setVisible(boolean isVisible) { this.isVisible = isVisible; } }
注意了,通常JavaFX中的类的变量,最好采用JavaFX的Property(javafx.bean.property),在后期很多处理上通过绑定机制会很方便,在我本人的JavaFX游戏开发库中都是采用的这个机制。不过在这里,由于赶工,并未使用。只是在此说明一下。
基类中,只是基本的坐标,大小的属性和基本的碰撞函数。
下面看看我们的角色类:
import java.util.List; import java.util.Random; import javafx.scene.canvas.GraphicsContext; import javafx.scene.image.Image; import javafx.scene.paint.Color; public class BasePlayer extends BaseObject { //角色分组 玩家 敌人 中立(暂未用到) public enum Group { Player, Enemy, Normal } private String name = "默认"; private int lv = 1; private int attack = 3; private int defense = 1; private int hp = 6; private int hp_max = 6; private int exp = 0; private int gold = 1; private int move = 4; private Random random = new Random(); private Image image; private Group group = Group.Player; //是否被选择 private boolean isChoose = false; //是否正在等待攻击(已显示攻击范围) private boolean isWaitToAttack = false; //是否正在等待移动(已显示移动范围) private boolean isWaitToMove = false; //是否能够行动 private boolean isCanAction = true; //是否能够移动 private boolean isCanMove = true; //是否能够攻击 private boolean isCanAttack = true; //下面是被攻击后的属性(本想做成闪烁,后来图简单没搞,名称未改) private int flashCount = 10; private int startCount = 0; private boolean isFlash = false; /** * 等级提升 */ public void levelUp() { attack += random.nextInt(3); defense += random.nextInt(2); hp += random.nextInt(3); lv++; } /** * 获取经验证 * @param ex 经验值 */ public void getExp(int ex){ exp += ex; if(exp >= 100){ levelUp(); exp = 0; } } /** * 攻击 * @param player 被攻击的角色 */ public void attack(BasePlayer player) { player.hp -= Math.max(0, attack - player.defense); } public void draw(GraphicsContext gc) { gc.save(); if (image != null) { if (isCanAction) { //如果行动未结束 if (isFlash) { //如果被攻击,绘制红色填充矩形,并等待计数结束 if (startCount < flashCount) { gc.setGlobalAlpha(0.3f); gc.setFill(Color.RED); gc.fillRect(getX(), getY(), width, height); startCount ++ ; } else { startCount = 0; isFlash = false; } } gc.setGlobalAlpha(1.0f); gc.drawImage(image, x, y); } else { //行动结束 透明度变为0.5 gc.setGlobalAlpha(0.5f); gc.drawImage(image, x, y); } gc.setGlobalAlpha(1.5f); if (isChoose) { // 当被选择时,显示边框 gc.strokeRect(x, y, 32, 32); } } gc.restore(); } /* * 被攻击 效果 */ public void flash() { isFlash = true; startCount = 0; } /** * 是否附近有Players里的角色 * * @param players * 角色集合 * @return 是否附近有Players里的角色 */ public boolean isHasNearBP(List<BasePlayer> players) { int mx = (int) (getX() / width); int my = (int) (getY() / height); for (BasePlayer bp : players) { int x = (int) (bp.getX() / width); int y = (int) (bp.getY() / height); if ((x == mx && y == my + 1) || (x == mx - 1 && y == my) || (x == mx + 1 && y == my) || (x == mx && y == my - 1)) { return true; } } return false; } /** * 寻找离自己最近的角色 * * @param players * 角色集合 * @return 最近的角色 */ public BasePlayer getNearestBP(List<BasePlayer> players) { BasePlayer basePlayer = players.get(0); for (int i = 0; i < players.size(); i++) { BasePlayer player = players.get(i); if (Math.abs(getX() - basePlayer.getX()) + Math.abs(getY() - basePlayer.getY()) > Math.abs(getX() - player.getX()) + Math.abs(getY() - player.getY())) { basePlayer = player; } } return basePlayer; } @Override public void update() { } /** * 重置所有状态 */ public void reset() { isChoose = false; isWaitToAttack = false; isWaitToMove = false; isCanAction = true; isCanMove = true; isCanAttack = true; } /** * 判断是否与某个点碰撞 */ public boolean isCollisionWith(double x, double y) { if (x > getX() && y > getY() && x < getX() + getWidth() && y < getY() + getHeight()) { return true; } return false; } public int getLv() { return lv; } public void setLv(int lv) { this.lv = lv; } public int getAttack() { return attack; } public void setAttack(int attack) { this.attack = attack; } public int getDefense() { return defense; } public void setDefense(int defense) { this.defense = defense; } public int getHp() { return hp; } public void setHp(int hp) { this.hp = hp; } public int getExp() { return exp; } public void setExp(int exp) { this.exp = exp; } public int getGold() { return gold; } public void setGold(int gold) { this.gold = gold; } public Image getImage() { return image; } public void setImage(Image image) { this.image = image; setWidth(image.getWidth()); setHeight(image.getHeight()); } public boolean isChoose() { return isChoose; } public void setChoose(boolean isChoose) { this.isChoose = isChoose; } public int getMove() { return move; } public void setMove(int move) { this.move = move; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isWaitToAttack() { return isWaitToAttack; } public void setWaitToAttack(boolean isWaitToAttack) { this.isWaitToAttack = isWaitToAttack; } public boolean isWaitToMove() { return isWaitToMove; } public void setWaitToMove(boolean isWaitToMove) { this.isWaitToMove = isWaitToMove; } public Group getGroup() { return group; } public void setGroup(Group group) { this.group = group; } public boolean isCanAction() { return isCanAction; } public void setCanAction(boolean isCanAction) { this.isCanAction = isCanAction; } public boolean isCanMove() { return isCanMove; } public void setCanMove(boolean isCanMove) { this.isCanMove = isCanMove; } public boolean isCanAttack() { return isCanAttack; } public void setCanAttack(boolean isCanAttack) { this.isCanAttack = isCanAttack; } public boolean isFlash() { return isFlash; } public void setFlash(boolean isFlash) { this.isFlash = isFlash; } public int getHpMax() { return hp_max; } public void setHpMax(int hp_max) { this.hp_max = hp_max; } }
在我的角色类中,定义了基本游戏角色的基本属性,名称,等级,攻击力,防御力,HP,经验值,金钱,移动力等。有一些暂时没有用到,不过没关系,都有注释。
另外定义几个方法,等级上升,获取经验值,攻击敌人,判断周边四个是否有角色(用于攻击判断),获取最近的角色(用于敌方移动目标确定)。
下面开始添加我们的角色了:
在Canvas的定义里增加我方角色和敌方角色的列表。
// 我方角色 private List<BasePlayer> players = new ArrayList<>(); // 敌方角色 private List<BasePlayer> enemys = new ArrayList<BasePlayer>();
初始化我方角色和敌人角色:
/** * 初始化我方角色 */ private void initPlayers() { Image player1Image = new Image(getClass().getResourceAsStream("player1.png")); BasePlayer player1 = new BasePlayer(); player1.setName("茉妍"); player1.setImage(player1Image); player1.setLocation(10 * tileWidth, 8 * tileHeight); Image player2Image = new Image(getClass().getResourceAsStream("player2.png")); BasePlayer player2 = new BasePlayer(); player2.setName("张达"); player2.setImage(player2Image); player2.setLocation(12 * tileWidth, 8 * tileHeight); Image player3Image = new Image(getClass().getResourceAsStream("player3.png")); BasePlayer player3 = new BasePlayer(); player3.setName("燕鱈"); player3.setImage(player3Image); player3.setLocation(8 * tileWidth, 8 * tileHeight); players.add(player1); players.add(player2); players.add(player3); } /** * 初始化敌方角色 */ private void initEnemy() { Image orc = new Image(getClass().getResourceAsStream("enemy1.png")); int[][] locations = { { 3, 3 }, { 3, 5 }, { 5, 3 } }; for (int i = 0; i < 3; i++) { BasePlayer enemy = new BasePlayer(); enemy.setImage(orc); enemy.setName("信(克隆)"); enemy.setAttack(3); enemy.setDefense(1); enemy.setHp(5); enemy.setHpMax(5); enemy.setGroup(Group.Enemy); enemy.setMove(3); enemy.setExp(50); enemy.setLocation(locations[i][0] * tileWidth, locations[i][1] * tileHeight); enemys.add(enemy); } }
注意这两个初始化方法要放入构造函数。另外,角色的Group分类一定要明确。
还有图片资源放入Src下和java文件的同级目录中。
接着开始绘制:
/** * 绘制角色 */ public void drawPlayer() { for (BasePlayer player : players) { player.draw(gContext); } for (BasePlayer enemy : enemys) { enemy.draw(gContext); } }
drawPlayer方法同样的在draw方法中调用。
这样以来,我们的角色和敌方角色也都创建完成了。
下面是效果图:
这样,我们的角色就创建完成了。
这一节课也到此结束了,下一节课,我们将会创建我们的行动菜单,属性菜单等。
本文章为个人原创,版权所有,转载请注明出处:http://blog.csdn.net/ml3947。另外我的个人博客:http://www.wjfxgame.com.
JavaFX战旗类游戏开发 第三课 创建游戏角色
时间: 2024-10-10 14:42:56