首页 > 代码库 > JavaFX战旗类游戏开发 第三课 创建游戏角色

JavaFX战旗类游戏开发 第三课 创建游戏角色

  在上一节课程中,我们学习了在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.