JAVA 实现《warcraft java版》游戏

Posted 毅慎

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA 实现《warcraft java版》游戏相关的知识,希望对你有一定的参考价值。

前言

致敬经典的warcraft,《warcraft java版》是一款即时战略题材单机游戏,采用魔兽原味风格和机制。收集资源,建造防御工事,消灭所有敌军。
人类:洛丹伦人类联盟自兽人首次穿过黑暗之门时便告成立。他们坚韧不拔,勇敢无畏,身穿坚甲,手握利刃,英勇迎敌。
兽人:兽人是一个粗犷而坚韧的种族,他们身穿简单的皮毛和带有尖刺的皮甲,以肆意凶狠的战斗风格而闻名。

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

主要需求

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

  • 黄金:黄金在Warcraft 中是主要的资源。黄金被用来建造新的建筑物,训练单位和研究升级。黄金在中立的建筑物也被用来购买雇佣兵,英雄物品,或启用特殊的服务。
  • 木材:木材和黄金类似,也是主要活动的消耗资源之一。所有种族都使用木材生产战争所需的许多不同的结构的武器和机器。

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

3、操作系统:

择和移动:使用鼠标左键点击一个单位或建筑,就可以查看相应的状态以及可以下达的指令。选择单位之后,玩家可以通过点击鼠标右键下达移动指令,或者点击界面底部指令面板上的按钮(或按下相应的快捷键)来指挥该单位。
按住鼠标左键并拖拽即可拉出一个矩形的方框,玩家可以通过这种方式选择多个单位,这也被称之为“框选”。选择多个单位之后,玩家可以一次性向所有选中的单位下达指令。玩家还可以按下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;<

以上是关于JAVA 实现《warcraft java版》游戏的主要内容,如果未能解决你的问题,请参考以下文章

《游戏学习》Java实现的开心农场简易版源码以及素材

《游戏学习》Java实现的开心农场简易版源码以及素材

Java版2048

求PC单机版RPG游戏

基于《仙剑奇侠传柔情版》利用Java的简单实现

使用win api模拟鼠标点击warcraft3按钮