JAVA implements the game "warcraft java version"

foreword

Paying tribute to the classic warcraft, "warcraft java version" is a real-time strategy theme stand-alone game, using the original Warcraft style and mechanics. Gather resources, build fortifications and destroy all enemy troops.
Humans: The Human Alliance of Lordaeron has been formed since the orcs first passed through the Dark Portal. They are tenacious, brave and fearless, wearing strong armor and holding sharp blades, they face the enemy bravely.
Orcs: Orcs are a rugged and tough race known for their reckless and ferocious fighting style, wearing simple fur and spiked leather armor.

It is implemented in java language, using swing technology for interface processing, and the design idea uses object-oriented thinking.

main needs

1. Players can choose their own camps: Humans and Orcs can choose from two camps.
2. Main resources:

  • Gold: Gold is the primary resource in Warcraft. Gold is used to build new buildings, train units and research upgrades. Gold in neutral buildings is also used to buy mercenaries, hero items, or to enable special services.
  • Wood: Similar to gold, wood is also one of the consuming resources for major activities. All races use wood to produce weapons and machines of many different structures required for warfare.

3. Building systems:
Buildings vary in cost, time and purpose. Town halls can train workers and store resources, some buildings can train combat units, and others can allow players to complete technology upgrades or unlock different types of units.

3. Operating system:

Select and move: Click on a unit or building with the left mouse button to view the corresponding status and commands that can be given. After selecting a unit, the player can command the unit by clicking the right mouse button to issue a movement command, or by clicking the button on the command panel at the bottom of the interface (or pressing the corresponding shortcut key).
Hold down the left mouse button and drag to pull out a rectangular box. Players can select multiple units in this way, which is also called "box selection". After selecting multiple units, the player can issue orders to all selected units at once. Players can also press the Tab key to cycle through the command panels for each unit.
Formation: After selecting multiple units or buildings, players can press Ctrl+any number key to form the selected units into a team. After the formation, the player only needs to press the number key to select the corresponding formation again.

Functional screenshot

Start the game:
insert image description here

Configuration:
insert image description here
start the game interface:
insert image description here

Game main interface:
insert image description here

Start a new game:
insert image description here

Start alone, start farming mode
insert image description here
Forest and Gold Mine:
insert image description here
Build Fortifications:
insert image description here
insert image description here
Attributes:
insert image description here

Code

Start the entry:


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 class:



/**
 * 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 class:



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;
    }
}

Summarize

Through the implementation of the "warcraft java version" game, I have a further understanding of the relevant knowledge of swing, and a deeper understanding of the java language than before.

Some basic grammars of java, such as data types, operators, program flow control and arrays, are more thoroughly understood. The core of java is the object-oriented idea, and finally realized something about this concept.

Source code acquisition

After following the blogger, you can privately chat with the blogger to get it for free. If
you need technical guidance, write project programs, and more services, please contact the blogger

Today is the 33rd /100th day of continuous writing .
You can follow me, like me, comment me, bookmark me.

рекомендация

отblog.csdn.net/qq_40869977/article/details/127040239