先做分析,需求分析?不就是简单的一些想法实现。  dota有英雄,有小兵,我的游戏也要有英雄,还有一大堆的比如商人,动物之类的东西。我可不想每一个都写一个类。所以提取共性,创造父类。Unit 代表所有单位,他们有坐标,必须要有显示在窗口的能力。然后英雄有比单位多一些什么,比如技能,属性,可以***别人,可以操控移动……而敌人也有一堆属性,但他们都是单位,都有单位必须有的方法。

      看下面的代码:(因为懒得写一些特殊的敌人,所以就没有将Unit完全抽象出来,而是直接作为敌人来表示。)

package demo01;

import java.awt.event.*;
import java.awt.*;
import java.util.*;
public class Unit implements ShowElem, Runnable {//ShowElem 是一个定义的接口,只有一个方法show用来提醒我必须写show方法。当然也有其它用处
    public int health = 100;//一些属性都有初始值这样你就可以为这个类用main方法测试,看看得到的数据是不是符合自己预期。
    public int id = 0;
    public String s = "not define";
    int x = 0, y = 0;
    private int width=30,height=30;
    private int cd = 1000;
    private int speedx=10,speedy=10;//速度分为x和y为了计算方便。
    public void setxspeed(int i){
        this.speedx=i;
    }
    public int getxspeed(){
        return this.speedx;
    }
    public int getyspeed(){
        return this.speedy;
    }
    public void setyspeed(int i){
        this.speedy=i;
    }
    private boolean islive = true;//后来添加的,判断单位是否挂了。
    public boolean islive(){
        return this.islive;
    }
    public int getw() {
        return this.width;
    }
    public int geth(){
        return this.height;
    }
    private Gun gun = new Ak47();//枪类,这个其实就是一个技能接口,枪的涉及难道和白虎的穿云箭不像吗?
    private DataBank dataBank = DataBank.init();
    Thread t = new Thread(this);//线程,除非游戏结束要不然这个单位还是要不停在屏幕上运动的
    Random rnd = new Random();
    Unit() {
        t.start();
        this.dataBank.add(this);
        this.id = this.dataBank.uSize() - 1;
    }
    Unit(int x, int y) {
        t.start();
        this.x = x;
        this.y = y;
        this.dataBank.add(this);
        this.id = this.dataBank.uSize() - 1;
    }
    Unit(String s, int x, int y) {
        t.start();
        this.s = s;
        this.x = x;
        this.y = y;
        this.dataBank.add(this);
        this.id = this.dataBank.uSize() - 1;
    }
    public void setGun(Gun gun) {
        this.gun = gun;
    }
    public Gun getGun() {
        return this.gun;
    }
    public void action() {
        ActionType.move(this);
    }
    public int getx() {
        return x;
    }
    public int gety() {
        return y;
    }
    public void show(Graphics g) {//这里可以换成贴图,但是我懒的找图,就画个圆吧,带个血条。
        if(this.islive){
        g.setColor(Color.blue);
        g.drawRect(x, y-5, width, 5);
        g.fillRect(x, y-5, width*health/100, 5);
        g.drawOval(x, y, width, height);
        }
    }
    public void run() {//我的run()写的不好,应该将里面的代码集合成一个action函数的,但是这是beta版能用就行了。
        while (this.islive) {
            if(this.health<0){this.islive=false;break;}
            try {
                Thread.sleep(100);
                this.action();
                this.cd -= 100;
                for (int i = 0; i < DataBank.data.uSize(); i++) {
                    if (DataBank.data.uGet(i) != this) {
                        if(this.cd<=0){
                        this.getGun().shoot(this, DataBank.data.uGet(i));
                        this.cd=1000;
                        }
                    }
                }
            } catch (InterruptedException e) {
            }
        }
    }
    public static void main(String[] args) {//每一个类里面都写main方法测试,这是一个好习惯,除非你完全确定自己写的类的效果。
        Unit a = new Unit();
        Unit b = new Unit("b", 20, 30);
        Unit c = new Unit("c", 30, 30);
        c.setGun(new Ak47());
        DataBank db = DataBank.init();//DataBank  是什么?这个后面说
        System.out.println(db.uSize());
        System.out.println(db.uGet(0).x);
        System.out.println(a.id + " ," + b.id + " ," + c.id
                + c.getGun().getName());
        try {
            Thread.sleep(2000);
            System.out.println(db.uGet(a.id).x + db.uGet(a.id).s);
            System.out.println(db.uGet(b.id).x + db.uGet(b.id).s);
            System.out.println(db.uGet(c.id).x + db.uGet(c.id).s);
        } catch (Exception e) {//里面没有操作,懒得写。运行结果符合自己预期。
        }
    }
}

Unit类有了看Hero类

package demo01;

import java.awt.*;
import java.awt.event.*;
public class  Hero extends Unit implements KeyListener, MouseListener {//这个英雄其实就是添加一个控制能力
    Thread t = new Thread(this);
    Hero() {
        super();
        t.start();
    }
    Hero(String s, int x, int y) {
        super(s, x, y);
        t.start();
    }
    public void show(Graphics g) {//方块显示英雄,既然是框架自然先将所有东西组合起来,我的设想里显示要有一个单独的模块的。这个只是凑合用。
        g.setColor(Color.darkGray);
        g.fillRect(this.getx(), this.gety(), this.getw(), this.geth());
    }
    public void keyPressed(KeyEvent e) {//按键移动
        if (e.getKeyChar() == 'w') {
            this.y -= 10;
        }
        if (e.getKeyChar() == 's') {
            this.y += 10;
        }
        if (e.getKeyChar() == 'a') {
            this.x -= 10;
        }
        if (e.getKeyChar() == 'd') {
            this.x += 10;
        }
    }
    public void keyReleased(KeyEvent e) {
    }
    public void keyTyped(KeyEvent e) {
    }
    public void run() {
    }
    public void mouseClicked(MouseEvent e) {
        int mods = e.getModifiers();
        if ((mods & InputEvent.BUTTON1_MASK) != 0) {//鼠标左键射击
            this.getGun().shoot(this, e.getX(), e.getY());
        }
        if ((mods & InputEvent.BUTTON3_MASK) != 0) {//鼠标右键移动
            if ((e.getX() - this.x) > 0) {
                this.x += 10;
            } else {
                this.x -= 10;
            }
            if ((e.getY() - this.y) > 0) {
                this.y += 10;
            } else {
                this.y -= 10;
            }
        }
    }
    public void mouseExited(MouseEvent e) {
    }
    public void mouseEntered(MouseEvent e) {
    }
    public void mousePressed(MouseEvent e) {
    }
    public void mouseReleased(MouseEvent e) {
    }
}
英雄方法没有写测试很短都不用测试了。

我们能够获得了一个可以用作敌人的unit类和自己控制的hero类。但是一个动画里面有很多敌人,一个可以操控的英雄,我们怎么弄他们到手呢?它们在干什么?我必须用一个东西可以方便我找到所有的Unit。

DataBank:我来用来储存所有创建的需要显示的对象,它是一个类,但是必须是单例的,单例模式。其实就是静态数组啦。

package demo01;

import java.util.*;
public class DataBank {
    static DataBank data = null;
    static int windowWidth=500;//定义一些常量,这样显得高端。
    static int windowheight=500;
    List unitList = new ArrayList();//单位对象储存在表里
    List bulletList = new ArrayList();
    private DataBank() {//单例模式就是将构造函数似有化这样别人就不能新一个类了。
    }
    public int add(Unit a) {
        this.unitList.add(a);
        return this.uSize();
    }
    public int add(Bullet a) {
        this.bulletList.add(a);
        return this.bSize();
    }
    public Unit uGet(int i) {
        return (Unit) this.unitList.get(i);
    }
    public void uDel(int i) {
        this.unitList.remove(i);
    }
    public Bullet bGet(int i) {
        return (Bullet) this.bulletList.get(i);
    }
    public int bSize() {
        return this.bulletList.size();
    }
    public int uSize() {
        return this.unitList.size();
    }
    public Object bRemove(int i) {
        return this.bulletList.remove(i);
    }
    public Object uRemove(int i) {
        return this.unitList.remove(i);
    }
    public static DataBank init() {//单例模式关键在这里,无论怎么干你只能获得一个对象。
        if (data == null) {
            data = new DataBank();
            return data;
        } else {
            return data;
        }
    }
}

Ok 既然有了枪就要有×××,其实和白虎的那个穿云箭的效果 一样。

package demo01;

import java.awt.*;
public class Bullet implements ShowElem, Runnable {
    private int x = 0, y = 0, width=10, height=10;
    private int destx, desty;
    private int speed=15;
    private int range = 20;
    private boolean islive = false;
    private double degrees;
    private int un;
    public void setun(Unit a) {
        this.un = a.id;
    }
    Thread t = new Thread(this);
    Bullet() {
    }
    public void setSpeed(int s) {
        this.speed = s;
    }
    public void setrange(int s) {
        this.range = s;
    }
    public void show(Graphics g) {//这个是普通×××的显示,其实就是一个圈
        if (this.islive) {
            g.setColor(Color.red);
            g.drawOval(this.x,this.y, this.width,this.height);
        }
    }
    public void setbullet(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }
    public int getx() {
        return this.x;
    }
    public int gety() {
        return this.y;
    }
    public int getw() {
        return this.width;
    }
    public int geth(){
        return this.height;
    }
    public void setlive() {
        this.islive = true;
    }
    public void setdie() {//×××生命周期是必须有的,要不然到最后就会创建一大堆的对象,然后挤占内存。
        this.islive = false;
    }
    public void setdest(int x, int y) {
        this.setlive();
        this.destx = x;
        this.desty = y;
        this.degrees = Math.atan((0.0 + this.desty - this.y)
                / (this.destx - this.x));
        if(this.destx<this.x){
            this.degrees+=Math.PI;
        }
    }
    public boolean islive() {
        return this.islive;
    }
    public void flyPoint() {// 计算×××飞行100毫秒后的位置。
        this.range--;
        this.x = this.x +(int) (speed * Math.cos(this.degrees));
        this.y = this.y + (int) (speed * Math.sin(this.degrees));
    }
    public void run() {
        try {
            while (this.islive()) {// 如果×××存在 执行。
                Thread.sleep(100);
                for (int i = 0; i < DataBank.data.uSize(); i++) {
                    if (MyCheck.crash(this, DataBank.data.uGet(i))) {
                        if (DataBank.data.uGet(i).id != this.un){
                            DataBank.data.uGet(i).health-=5;
                            this.setdie();break;}
                    }
                }
                this.flyPoint();
                if (this.range <= 0) {// 射程到达
                    this.setdie();break;// ×××标记消失
                }
            }
        } catch (InterruptedException e) {
         System.out.print("bullet is no running");
        }
    }
    public static void main(String[] args){//×××测试类,每一个有稍微一点复杂算法的类我都测试一下。
        Bullet db=new Bullet();
        db.setbullet(50, 50, 50, 50);
        try{
            System.out.println(db.getx());
            Thread.sleep(1000);
            System.out.println(db.getx());
            Thread.sleep(1000);
            System.out.println(db.getx());
        }catch(Exception e){
            System.out.println("mistake");
        }
    }
}
顺便贴出他的子类。

package demo01;

import java.awt.*;
public class BulletP47 extends Bullet {
    Thread t = new Thread(this);
    BulletP47() {
        super();//这个其实没必要。
        t.start();
        DataBank.data.add(this);//创建一个×××就将他放到表里。
    }
    public void show(Graphics g) {
        if (super.islive()) {
            g.setColor(Color.red);
            g.drawOval(super.getx(), super.gety(), 10, 10);
            g.drawOval(super.getx() + 2, super.gety(), 10, 10);
        }
    }
    public void run() {
        super.run();
    }
}

上面就不解释了,就是换个方法。

下面是枪类:

package demo01;

public abstract class Gun {//抽象方法 帅气
    String name = "gun";
    int bulletnum=1000;
    Gun(String a){
        this.name=a;
    }
    public void setnum(int x) {
        this.bulletnum = x;
    }
    public String getName(){
        return this.name;
    }
    abstract public void shoot(Unit a);//方法重构,这个可以用做自动射击,不同方法不同表现,具体实现在子类。
    abstract public Bullet shoot(Unit a,Unit b);
    abstract public Bullet shoot(Unit a,int x,int y);
}
package demo01;
public class Ak47 extends Gun {
    // Bullet bullet = new BulletP47();
    Ak47() {
        super("Ak47");
    }
    public void shoot(Unit a) {
        // this.bullet.setbullet(a.getx(), a.gety(), 10, 10);
    }
    public Bullet shoot(Unit a, Unit b) {
        this.bulletnum--;
        Bullet sb = new BulletP47();
        if (bulletnum > 0) {
            sb.setun(a);
            sb.setbullet(a.getx(), a.gety(), 10, 10);
            sb.setdest(b.getx(), b.gety());
        }
        return sb;
    }
    public Bullet shoot(Unit a,int x,int y){
        this.bulletnum--;
        Bullet sb=new BulletP47();
        if(this.bulletnum>0){
            sb.setun(a);
            sb.setbullet(a.getx(),a.gety(),10,10);
            sb.setdest(x, y);
        }
        return sb;
    }
}
枪类我是最喜欢的,因为用抽象更帅,不过其实是因为枪类简单,我就注意一下它的结构,最开始我只是要拿个能用的,现在慢慢的经过一部分测试,所以就注意形式了。

ok 我把所有方法能静态的静态掉,这样不同类里都可以调用,这样省点事。

package demo01;

import java.util.*;
public class ActionType {
    public static Random rnd = new Random();
    public static int[][] rndfill(int[][] map,int max){//这个是我的随即地图生成,只是测试我的地图的,地图类贴上去还要改单位的action 还要写A*算法那就算了。
        for(int i=0;i<map.length;i++){
            for(int j=0;j<map[i].length;j++){
                map[i][j]=rnd.nextInt(max);
            }
        }
        return map;
    }
    public static void movernd(Unit u) {// 随即移动动作。其实被我改了,变成边界碰撞,主要是随即移动像抽风。不过这一部分都是可以重写的。
        int flag;
        int speedx, speedy;
        flag = rnd.nextInt(10);
        // System.out.println(flag);
        speedx = rnd.nextInt(20);
        speedy = rnd.nextInt(20);
        if (MyCheck.xTouchEdge(u, 500)) {
            u.x += speedx;
        } else {
            u.x -= speedx;
        }
        if (MyCheck.xTouchEdge(u, 500)) {
            u.y += speedy;
        } else {
            u.y -= speedy;
        }
    }
public static Stack findRoad(int x,int y,int destx,int desty){//寻路,这就是了,没完成。
    return null;
}
    public static void move(Unit a) {//移动,
        if (MyCheck.xTouchEdge(a, 500)) {
            a.setxspeed(-a.getxspeed());
        }
        a.x +=a.getxspeed();
        if (MyCheck.yTouchEdge(a, 500)) {
            a.setyspeed(-a.getyspeed());
        }
        a.y += a.getyspeed();
    }
}

好了最后一个窗口,将所有东西显示出来并初步测试;

package demo01;

import java.awt.*;
import java.awt.event.*;
import java.util.Arrays;
import javax.swing.*;
class Cshow {
    public void paint(Graphics g){
        g.setColor(Color.red);
        g.drawOval(30, 30, 30, 30);
    }
}

class Mypanel extends JPanel implements Runnable{
    Thread t=new Thread(this);//一直没解释这个东西,就是线程,和Timer类差不多功效,但我是抄编程思想里面的写法。Timer类那时还不知道呢。
    int x=100,y=100;
    //DElements d;
    DataBank db=DataBank.init();//其实db 和DataBank。static方法一样,但是这样后面可以剩写点东西。都一样
    Cshow c;
    Mypanel(){
        t.start();
        c=new Cshow();
    }
    public void paint(Graphics g){
        //c.paint(g);
        g.setColor(this.getBackground());
        g.fillRect(0, 0, this.getWidth(), this.getHeight());
        MyMap.show(g);//其实我还有map地图实现,不过半成品,所有没贴上。
        for(int i=0;i<db.uSize();i++){//迭代显示所有单位
            db.uGet(i).show(g);
            if (db.uGet(i).health<0)db.uRemove(i);
        }
        for(int i=0;i<db.bSize();i++){//迭代显示所有×××。
            db.bGet(i).show(g);
            if(!db.bGet(i).islive())db.bRemove(i);//×××挂了就消除,其实不一定要在这里调用的
            //g.drawOval(i, i, i, i);
        }
    }
    public void run(){
        while(true){//这个while()不停循环真是常用。
        repaint();
        try{
            Thread.sleep(100);
        }catch(Exception e){
            System.out.println("found a mistake");
        }
        }
    }
}

public class Demo {
    public static void main(String[] args){//Demo 就是测试,自己随便试试可不可以用,正在写载入配置文件和存档文件,自动初始游戏,还有任务模式的实现,等到时候就将框架都写好了,那个时候就有时间关注细节了。
        DataBank db=DataBank.init();
        Bullet sb;
        int[][] democell=new int[10][10];
        democell=ActionType.rndfill(democell, 4);
        MyMap.setcell(democell);
        Unit a=new Unit("a",100,40);
        Unit b=new Unit("b",30,30);
        Unit c=new Unit("c",100,130);
        Hero hero=new Hero("hero",100,300);
        db.add(sb=a.getGun().shoot(b, c));
        try{
            JFrame w=new JFrame("demo");
            w.setSize(500,500);
            w.setLocationRelativeTo(null);
            w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            Mypanel mp=new Mypanel();
            MyButton mb=new MyButton();
            mp.add(mb);
            mp.setLayout(null);
            mp.setSize(500, 500);
            w.add(mp);
//            w.addKeyListener(hero);//这一部分巧合遇到藏老师将focus然后就稍微改了改,但是有一个问题其实一直没解决,focus在setvisable方法后面会丢失键盘事件,奇怪,但没解释。真到想问问题的时候,总是找不到人。
//            //mp.requestFocus();
//            w.addMouseListener(hero);
            //mp.requestFocus();
        w.setVisible(true);
        mp.addKeyListener(hero);
        mp.addMouseListener(hero);
        mp.requestFocus();
            //w.show();//我喜欢原始版本的show 简单方便。
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }

PS:这个框架其实还是有很多问题,比如线程之间的并发,线程安全,需要设置标志位,或者其它之类的东西,但是能用了,那就有成就感,以后这些细节再处理。

而如果自己想写,那么就必须将Unit抽象化,而且很多东西必须添加,比如Unit的AI 我的AI是所有单位互相射击,你们可以自己写咯。比如都***英雄,比如英雄只可以向上射击,(这就是打飞机了!)比如死亡后创建一个战利品的对象,里面暴装备。OK 就到这里。希望大家给与修正建议。