当前位置 : 主页 > 编程语言 > java >

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

来源:互联网 收集:自由互联 发布时间:2023-01-30
目录 前言 主要需求 功能截图 代码实现 启动入口 ModelAttacker类 ModelUnit类 总结 前言 致敬经典的warcraft,《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游戏的资料请关注自由互联其它相关文章!

    上一篇:详解如何在Java中加密和解密zip文件
    下一篇:没有了
    网友评论