Java实现warcraft java版游戏的示例代码

目录
  • 前言
  • 主要需求
  • 功能截图
  • 代码实现
    • 启动入口
    • ModelAttacker类
    • ModelUnit类
  • 总结

前言

致敬经典的warcraft,《warcraft java版》是一款即时战略题材单机游戏,采用魔兽原味风格和机制。收集资源,建造防御工事,消灭所有敌军。

人类:洛丹伦人类联盟自兽人首次穿过黑暗之门时便告成立。他们坚韧不拔,勇敢无畏,身穿坚甲,手握利刃,英勇迎敌。

兽人:兽人是一个粗犷而坚韧的种族,他们身穿简单的皮毛和带有尖刺的皮甲,以肆意凶狠的战斗风格而闻名。

用java语言实现,采用了swing技术进行了界面化处理,设计思路用了面向对象思想。

主要需求

1、玩家可以自己选择阵营:人类(Human)和兽人(Orc)两个阵营可以挑。

2、主要资源:

黄金:黄金在Warcraft 中是主要的资源。黄金被用来建造新的建筑物,训练单位和研究升级。黄金在中立的建筑物也被用来购买雇佣兵,英雄物品,或启用特殊的服务。

木材:木材和黄金类似,也是主要活动的消耗资源之一。所有种族都使用木材生产战争所需的许多不同的结构的武器和机器。

3、建筑系统:

不同建筑的建造成本、时间和目的各不相同。城镇大厅可以训练工人和存放资源,有些建筑可以训练战斗单位,还有的可以让玩家完成科技升级或解锁不同类型的单位。

4、操作系统:

择和移动:使用鼠标左键点击一个单位或建筑,就可以查看相应的状态以及可以下达的指令。选择单位之后,玩家可以通过点击鼠标右键下达移动指令,或者点击界面底部指令面板上的按钮(或按下相应的快捷键)来指挥该单位。

按住鼠标左键并拖拽即可拉出一个矩形的方框,玩家可以通过这种方式选择多个单位,这也被称之为“框选”。选择多个单位之后,玩家可以一次性向所有选中的单位下达指令。玩家还可以按下Tab键来循环切换查看各个单位的指令面板。

编队:选择多个单位或建筑后,玩家可以按下Ctrl+任意数字键,以此将选中的单位编为一队。编队之后,玩家只需要按下该数字键就可以再次选中相应的编队。

功能截图

启动游戏:

配置:

启动游戏界面:

游戏主界面:

开始一个新游戏:

开局一个人,开启种田模式

森林和金矿:

建设防御工事:

属性:

代码实现

启动入口

public class Main {

    public static final String PROGRAM = "Warcraft java版";
    public static final String VERSION = "1.0.0";
    private static final long serialVersionUID = 1L;

    private Main() {
    }

    public static Initializer initialize(boolean jar) {
        if (jar) {
            Media.loadFromJar(Main.class);
        }
        Engine.start(PROGRAM, VERSION, "ressources", true, Theme.SYSTEM);
        return ENGINE.createInitializer(320, 200, 32, 60);
    }

    public static void main(String[] args) {
        boolean jar = false;
        try {
            jar = Boolean.parseBoolean(args[0]);
        } catch (Exception e) {
        }
        Launcher launcher = new Launcher(null, initialize(jar));
        launcher.start();
    }
}

ModelAttacker类

/**
 * Main abstraction representing any unit with the ability of attacking.
 */
public abstract class ModelAttacker extends ModelUnit implements AttackerAbility<Tile, ModelSkill, Attributes> {

    private final List<AbstractEntry<Tile, ModelSkill, Attributes>> guards;
    private int orderX, orderY;
    private boolean assault, riposte;
    private boolean defend;
    private long guardTimer;

    public ModelAttacker(Map map, RessourcesHandler rsch, MediaRessource<BufferedImage> rsc) {
        super(map, rsch, rsc.file, rsc.ressource);
        this.guards = new ArrayList<AbstractEntry<Tile, ModelSkill, Attributes>>(1);
        this.damages.setMin(this.getDataInt("DMG_MIN"));
        this.damages.setMax(this.getDataInt("DMG_MAX"));
        this.riposte = true;
        this.assault = false;
        this.defend = false;
        this.orderX = -1;
        this.orderY = -1;
    }

    public void setDamages(int min, int max) {
        this.damages.setMin(min);
        this.damages.setMax(max);
    }

    @Override
    public void update(Keyboard keyboard, Mouse mouse, float extrp) {
        super.update(keyboard, mouse, extrp);
        this.updateAttack(extrp);
        if (this.isAlive() && (!this.hasTarget() || this.isMoving())) {
            // Reset defense state when its over
            if (this.isDefending() && !this.isAttacking()) {
                this.defend = false;
                this.assault = false;
            }
            // Check guard area when not defending & attacking or assault
            if (!this.isDefending() && (this.assault || (!this.isAttacking() && !this.isMoving()))) {
                if (Maths.time() - this.guardTimer > 500) {
                    if (this.player instanceof AI) {
                        this.guard();
                    } else {
                        if (!this.isMoving()) {
                            this.guard();
                        }
                    }
                    this.guardTimer = Maths.time();
                }
            }
        }
    }

    @Override
    public boolean assignDestination(int tx, int ty) {
        boolean found = super.assignDestination(tx, ty);
        if (this.orderX == -1 && this.assault) {
            this.orderX = tx;
            this.orderY = ty;
        }
        return found;
    }

    public void reAssignDestination() {
        if (this.orderX != -1 && this.orderY != -1) {
            this.stopAttack();
            this.setTarget(null);
            super.assignDestination(this.orderX, this.orderY);
        } else {
            this.stopAttack();
            this.stopMoves();
        }
    }

    @Override
    public void stop() {
        this.stopAttack();
        super.stop();
    }

    protected void guard() {
        int fov = this.getFieldOfView() - 1;
        for (int v = this.getYInTile() - fov; v <= this.getYInTile() + fov; v++) {
            for (int h = this.getXInTile() - fov; h <= this.getXInTile() + fov; h++) {
                try {
                    int eid = this.map.getRef(v, h);
                    if (eid > 0 && eid != this.id) {
                        AbstractEntry<Tile, ModelSkill, Attributes> e = ModelUnit.get(eid);
                        if (e == null) {
                            e = ModelBuilding.get(eid);
                        }
                        if (e.isAlive() && e.isVisible() && e.getOwnerID() != this.getOwnerID() && e.getOwnerID() > 0 && e.isActive()) {
                            this.guards.add(e);
                        }
                    }
                } catch (ArrayIndexOutOfBoundsException e) {
                    continue;
                }
            }
        }
        int min = Integer.MAX_VALUE;
        AbstractEntry<Tile, ModelSkill, Attributes> closest = null;
        for (AbstractEntry<Tile, ModelSkill, Attributes> e : this.guards) {
            int dist = this.getDistance(e);
            // Priority to unit
            if (closest instanceof AbstractBuilding && e instanceof AbstractUnit) {
                min = dist;
                closest = e;
            } else if (!(closest instanceof AbstractUnit && e instanceof AbstractBuilding) || closest == null) {
                if (dist < min) {
                    min = dist;
                    closest = e;
                }
            }
        }
        this.guards.clear();
        if (closest != null) {
            this.guardAction(closest);
        }
    }

    protected void guardAction(AbstractEntry<Tile, ModelSkill, Attributes> e) {
        // Priority to attacker model
        if (this.getTarget() instanceof ModelAttacker && !(e instanceof ModelAttacker)) {
            return;
        }
        this.attack(e);
    }

    @Override
    public void onHit(AbstractEntry<Tile, ModelSkill, Attributes> attacker) {
        super.onHit(attacker);
        if (this.isAlive() && this.riposte) {
            // AI gives priority to unit riposte
            if (attacker instanceof AbstractUnit && this.getTarget() instanceof AbstractBuilding && this.player instanceof AI) {
                this.attack(attacker);
                return;
            }
            // Keep closest target only
            boolean closest = false;
            if (this.hasTarget()) {
                closest = this.getDistance(attacker) < this.getDistance(this.getTarget());
            }
            if ((this.hasTarget() || closest) && this.getOwnerID() != attacker.getOwnerID()) {
                this.attack(attacker);
            }
        }
    }

    @Override
    public void onKilled(AbstractEntry<Tile, ModelSkill, Attributes> attacker) {
        if (this.assault) {
            this.reAssignDestination();
        }
    }

    public void setRiposte(boolean state) {
        this.riposte = state;
    }

    public void setAssault(boolean state) {
        this.assault = state;
    }

    public boolean getAssault() {
        return this.assault;
    }

    public void setDefend(boolean state) {
        this.defend = state;
    }

    public boolean isDefending() {
        return this.defend;
    }

    @Override
    public boolean isPassive() {
        return super.isPassive() && !this.isAttacking();
    }

    public boolean hasTarget() {
        return this.getTarget() != null;
    }
}

ModelUnit类

public abstract class ModelUnit extends AbstractUnit<Tile, ModelSkill, Attributes> {

    private static final TreeMap<Integer, ModelUnit> ENTRYS = new TreeMap<Integer, ModelUnit>();

    public static ModelUnit get(int id) {
        return ENTRYS.get(id);
    }

    public static void clear() {
        ENTRYS.clear();
    }

    public static List<ModelUnit> getByOwner(int ownerID) {
        List<ModelUnit> list = new ArrayList<ModelUnit>(1);
        Collection<ModelUnit> c = ENTRYS.values();
        for (ModelUnit u : c) {
            if (u.getOwnerID() == ownerID) {
                list.add(u);
            }
        }
        return list;
    }

    private void manage() {
        ENTRYS.put(this.id, this);
    }
    private static final int CORPSE_TIME = 5000;
    private static final int CORPSE_NUMBER = 3;
    private static final int CORPSE_OFFSET = 8;
    private static final Orientation[] orientations = Orientation.values();
    public final Map map;
    public final UnitType type;
    public final Race faction;
    protected Player player;
    private boolean isOnScreen;
    private TiledSprite corpse;
    private long deadTimer, angleTimer, nextAngleTimer;
    private boolean dead;
    private int deadIndex, deadOffset;

    public ModelUnit(Map map, RessourcesHandler rsch, String data, BufferedImage surface) {
        super(data, map, surface, new Attributes());
        this.map = map;
        this.type = UnitType.valueOf(this.getDataString("TYPE").toUpperCase());
        this.setFieldOfView(this.getDataInt("FOV"));
        this.setFrame(this.getDataInt("DEFAULT_FRAME"));
        this.setSkipLastFrameOnReverse(true);
        this.faction = Race.valueOf(this.getDataString("FACTION").toLowerCase());
        this.life.setMax(this.getDataInt("MAX_LIFE"));
        this.life.set(this.life.getMax());
        this.addSkill(new Move(0, this));
        this.addSkill(new Stop(1, this));
        this.setSpeed(1.5f, 1.5f);
        this.setLayer(2);
        this.corpse = Drawable.DRAWABLE.loadTiledSprite(rsch.get("CORPSE").ressource, 32, 32);
        this.corpse.load(false);
        this.deadTimer = -1L;
        this.dead = false;
        this.deadIndex = 0;
        if (this.faction == Race.orcs) {
            this.deadOffset = 8;
        } else {
            this.deadOffset = 0;
        }
        this.map.fogOfWar.updateEntryFOV(this);
        this.angleTimer = Maths.time();
        this.nextAngleTimer = Maths.random(0, 2000) + 5000L;
        this.manage();
    }

    @Override
    public void place(int tx, int ty) {
        super.place(tx, ty);
        this.map.fogOfWar.updateEntryFOV(this);
    }

    @Override
    public void update(Keyboard keyboard, Mouse mouse, float extrp) {
        int otx = this.getXInTile();
        int oty = this.getYInTile();

        super.update(keyboard, mouse, extrp);

        // Apply mirror depending of the orientation
        Orientation o = this.getOrientation();
        if (o.ordinal() > 4) {
            if (!this.getMirror()) {
                this.mirror(true);
            }
        } else {
            if (this.getMirror()) {
                this.mirror(false);
            }
        }
        if (!this.isAlive()) {
            // Handle dead corps effect
            if (!this.dead) {
                if (this.deadTimer == -1L) {
                    this.deadTimer = Maths.time();
                }
                if (Maths.time() - this.deadTimer > CORPSE_TIME) {
                    this.setVisibility(false);
                    this.dead = true;
                    this.deadIndex = 0;
                    this.deadTimer = Maths.time();
                }
            } else {
                if (this.deadIndex <= CORPSE_NUMBER && Maths.time() - this.deadTimer > CORPSE_TIME) {
                    this.deadIndex++;
                    this.deadTimer = Maths.time();
                }
            }
            if (this.deadIndex > CORPSE_NUMBER) {
                this.remove();
            }
        } else {
            // Update fog when unit moved
            if (otx != this.getXInTile() || oty != this.getYInTile()) {
                this.map.fogOfWar.updateEntryFOV(this);
            }
            // Apply a random angle unit entry is still idle too much time
            if (this.isPassive() && Maths.time() - this.angleTimer > this.nextAngleTimer) {
                this.setAnimation("IDLE");
                this.setOrientation(orientations[Maths.random(0, orientations.length - 1)]);
                this.angleTimer = Maths.time();
                this.nextAngleTimer = Maths.random(0, 2000) + 5000L;
            }
        }
        if (this.animName != null) {
            CollisionArea area = this.getCollArea(this.animName);
            this.updateCollision(area.getX(), area.getY(), area.getWidth(), area.getHeight());
        } else {
            this.updateCollision(16, 16, 0, 0);
        }
    }

    @Override
    public void render(Graphics2D g, Camera camera) {
        super.render(g, camera);
        if (this.dead && this.deadIndex <= CORPSE_NUMBER) {
            int o = 0;
            if (this.getOrientation().ordinal() > 0) {
                o = 4;
            }
            this.corpse.render(g, this.deadIndex + this.deadOffset + o, this.getX() - camera.getX() - CORPSE_OFFSET,
                    this.getY() - camera.getY() - CORPSE_OFFSET);
        }
        if (this.getX() >= camera.getX() && this.getX() <= camera.getX() + 320 && this.getY() >= camera.getY() && this.getY() <= camera.getY() + 200) {
            this.isOnScreen = true;
        } else {
            this.isOnScreen = false;
        }
    }

    @Override
    public void setOwnerID(int id) {
        super.setOwnerID(id);
        if (id > 0) {
            this.player = (Player) AbstractPlayer.get(id);
        }
    }

    public Player player() {
        return this.player;
    }

    @Override
    public void stop() {
        super.stop();
        this.clearIgnoredID();
        this.angleTimer = Maths.time();
    }

    @Override
    public void onStartMove() {
        this.setAnimation("MOVE");
    }

    @Override
    public void onMove() {
        if (!this.animName.equals("MOVE")) {
            this.setAnimation("MOVE");
        }
    }

    @Override
    public void onArrived() {
        this.setAnimation("IDLE");
        this.angleTimer = Maths.time();
    }

    @Override
    public void onDied() {
        if (this.getOrientation().ordinal() < 4) {
            this.setOrientation(Orientation.NORTH);
        } else {
            this.setOrientation(Orientation.NORTH_EAST);
        }
        this.setAnimation("DIE");
        this.player.removeUnit(this);
        if (this.isOnScreen()) {
            ControlPanel.playSfx(0, this.faction, SFX.die);
        }
    }

    @Override
    public void onSelection() {
        ControlPanel.playSfx(this.getOwnerID(), this.faction, SFX.select);
    }

    @Override
    public void onOrderedFail(ModelSkill skill) {
    }

    @Override
    public void onKilled(AbstractEntry<Tile, ModelSkill, Attributes> attacker) {
    }

    public boolean isPassive() {
        return !this.isMoving();
    }

    public boolean isOnScreen() {
        return this.isOnScreen;
    }
}

总结

通过此次的《warcraft java版》游戏实现,让我对swing的相关知识有了进一步的了解,对java这门语言也有了比以前更深刻的认识。

java的一些基本语法,比如数据类型、运算符、程序流程控制和数组等,理解更加透彻。java最核心的核心就是面向对象思想,对于这一个概念,终于悟到了一些。

以上就是Java实现warcraft java版游戏的示例代码的详细内容,更多关于Java warcraft游戏的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java实现贪吃蛇游戏的示例代码

    目录 项目演示 项目实战 1. 游戏的主启动类 2. 游戏的面板 3. 数据中心 4. 绘制静态面板 5. 绘制静态小蛇 6. 绘制动态小蛇 7. 设置游戏状态 8. 让蛇动起来 9. 绘制食物布局 10. 游戏失败判定 11. 积分获取系统 12. 游戏优化 项目演示 项目演示地址 项目实战 1. 游戏的主启动类 作为贪吃蛇游戏的主启动类,构建了顶级窗口,可以容纳各种面板, package Snake; import javax.swing.*; /** * 游戏的主启动类 */ public

  • Java跳跃游戏实例真题解决思路详解

    目录 变式题—跳跃游戏 I 一.题目描述 二.思路 三.代码 变式题—跳跃游戏 II 一.题目描述 二.思路 三.代码 变式题—跳跃游戏 I 一.题目描述 给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 .数组中的每个元素代表你在该位置可以跳跃的最大长度.判断你是否能够到达最后一个下标. 来源:https://leetcode.cn/problems/jump-game/ 示例: 二.思路 本题可以使用贪心法解决,对每个能到达的位置(可覆盖到的位置),计算其每次能覆盖的最大长度,

  • Java实现扑克牌游戏的示例代码

    目录 一.三人扑克 二.具体实现 Card类 生成52张牌 打乱顺序 发牌 三.完整代码 一.三人扑克 想不想带上好朋友来上一局三人扑克呢. 二.具体实现 Card类 定义一个花色color变量和一个大小rank变量. public class Card { public int rank; public String color; @Override public String toString() { return String.format("[%s,%d]",color,ran

  • Java实现warcraft java版游戏的示例代码

    目录 前言 主要需求 功能截图 代码实现 启动入口 ModelAttacker类 ModelUnit类 总结 前言 致敬经典的warcraft,<warcraft java版>是一款即时战略题材单机游戏,采用魔兽原味风格和机制.收集资源,建造防御工事,消灭所有敌军. 人类:洛丹伦人类联盟自兽人首次穿过黑暗之门时便告成立.他们坚韧不拔,勇敢无畏,身穿坚甲,手握利刃,英勇迎敌. 兽人:兽人是一个粗犷而坚韧的种族,他们身穿简单的皮毛和带有尖刺的皮甲,以肆意凶狠的战斗风格而闻名. 用java语言实现,

  • Java实现泡泡堂对战版游戏的示例代码

    目录 前言 主要设计 功能截图 代码实现 游戏启动类 核心监听类 核心线程类 总结 前言 <泡泡堂II>是一个基于java的自制游戏,使用了MVC模式,分离了模型.视图和控制器,使得项目结构清晰易于扩展,使用配置文件来设置游戏基本配置,扩展地图人物道具等.同时,该程序编写期间用了单例模式.工厂模式.模板模式等设计模式.为了游戏的可玩性,特意设计了平滑碰撞以及机器人. 主要设计 设计游戏界面,用swing实现 绘制游戏启动界面.结束界面.地图.主角.道具 实现泡泡爆炸 为了尽量复原泡泡堂游戏,初

  • Java实现经典捕鱼达人游戏的示例代码

    目录 前言 主要设计 功能截图 代码实现 游戏窗体 鱼 鱼池类继承自Jpanel 总结 前言 <捕鱼达人>是一款以深海狩猎为题材的休闲竞技游戏.这是一场海底世界的远征,享受捕获大鱼的乐趣,但不是所有的鱼都是友善的,它们会用自己的方式保护自己,保卫属于自己的海底世界.当然,这里也是冒险与机遇共存的地方,诸多埋藏于海底的宝藏等待着被探寻. 游戏是用java语言实现,采用了swing技术进行了界面化处理,设计思路用了面向对象思想. 主要需求 在鱼池中有很多鱼,鱼各自游动. 有一张渔网,随鼠标移动,点

  • Java实现英文猜词游戏的示例代码

    目录 前言 主要设计 功能截图 代码实现 游戏启动类 处理 单词判断 总结 前言 <英文猜词游戏>代码行数没有超过200行,是之前为了背英语单词,特意研发的小游戏. 主要设计 1.事先准备单词文本. 2.为了让玩家能与程序互动,使用下面这个命令可达效果 Scanner sc = new Scanner(System.in); 3.运行WordleMaster里的main方法 4.在Wordle中输入第一个单词(默认第一个单词是abort,会显示在console中.可在代码中修改) 5.将Wor

  • Java实现接月饼小游戏的示例代码

    目录 前言 主要设计 功能截图 代码实现 游戏启动类 核心类 画面绘制 总结 前言 <接月饼小游戏>是一个基于java的自制游戏,不要被月亮砸到,尽可能地多接月饼. 此小项目可用来巩固JAVA基础语法,swing的技巧用法. 主要设计 设计游戏界面,用swing实现 设计背景 设计得分物体-月饼,碰到加一分 设计障碍物-月亮,碰到会死亡 监听鼠标的左右键,用来控制篮子左右移动 设计积分系统 将resource文件夹设为resource(Project Manage中可以设置),因为要用里面的图

  • Java实现蓝桥杯数独游戏的示例代码

    你一定听说过"数独"游戏. 如图,玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个同色九宫内的数字均含1-9,不重复. 数独的答案都是唯一的,所以,多个解也称为无解. 本图的数字据说是芬兰数学家花了3个月的时间设计出来的较难的题目.但对会使用计算机编程的你来说,恐怕易如反掌了. 本题的要求就是输入数独题目,程序输出数独的唯一解.我们保证所有已知数据的格式都是合法的,并且题目有唯一的解. 格式要求: 输入9行,每行9个数字,0代表未知,其它数字为

  • Java实现贪吃蛇大作战小游戏的示例代码

    目录 效果展示 项目介绍 项目背景 总体需求 实现过程 代码展示 项目结构 总结 大家好,今天尝试用swing技术写一个贪吃蛇大作战小游戏,供大家参考. 效果展示 效果展示 一.游戏界面 二.得分情况 项目介绍 项目背景 “贪吃蛇大作战”游戏是一个经典的游戏,它因操作简单.娱乐性强,自从计算机实现以来,深受广大电脑玩家的喜爱,本项目基于Java技术,开发了一个 操作简单.界面美观.功能较齐全 的“贪吃蛇”游戏.通过本游戏的开发,达到学习Java技术和熟悉软件开发流程的目的. 总体需求  本系统主

  • Java实现萝卜勇者游戏的示例代码

    目录 前言 主要设计 功能截图 代码实现 启动类 键盘监听 核心算法 总结 前言 <萝卜勇者>是由国内玩家自制的一款独立游戏,玩家扮演萝卜勇士闯关,打败各种邪恶的敌人,获得最后的胜利. <萝卜勇者>游戏是用java语言实现,采用了swing技术进行了界面化处理,设计思路用了面向对象思想. 主要需求 参考<萝卜勇者>的剧情,实现JAVA版本的单机游戏. 主要设计 1. 用Swing库做可视化界面 2.键盘监听,用WSAD可以控制光标移动,J是确定,K是取消,游戏中,WSA

  • JAVA实现经典扫雷游戏的示例代码

    目录 前言 主要设计 功能截图 代码实现 总结 前言 windows自带的游戏<扫雷>是陪伴了无数人的经典游戏,本程序参考<扫雷>的规则进行了简化,用java语言实现,采用了swing技术进行了界面化处理,设计思路用了面向对象思想. 主要需求 1.要有难度等级,初级,中级,高级 2.由玩家逐个翻开方块,以找出所有地雷为最终游戏目标.如果玩家翻开的方块有地雷,则游戏结束 3.游戏主区域由很多个方格组成.使用鼠标左键随机点击一个方格,方格即被打开并显示出方格中的数字:方格中数字则表示其

  • Java+Swing实现五子棋游戏的示例代码

    目录 一.系统介绍 1.开发环境 2.技术选型 3.系统功能 二.系统展示 三.部分代码 AI.java Chess.java Gobang.java GobangListener.java 一.系统介绍 1.开发环境 开发工具:Eclipse2021 JDK版本:jdk1.8 Mysql版本:8.0.13 2.技术选型 Java+Swing 3.系统功能 实现五子棋游戏,开始游戏,悔棋,认输,退出功能. 二.系统展示 1.首页 2.黑棋走 3.白棋走 三.部分代码 AI.java packag

随机推荐