首页 / 操作系统 / Linux / J2SE坦克大战(Demo学习总结)
( 纯手绘版坦克大战)1:制作出显示应用程序窗口 定义好窗口的大小,布局和背景颜色 这里主要覆写了父类的paint()和update()方法,在update方法中加入了双缓冲机制具体代码如下: Image offScreenImage = null;public void update(Graphics g) { if(offScreenImage == null) { offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT); } Graphics gOffScreen = offScreenImage.getGraphics(); Color c = gOffScreen.getColor(); gOffScreen.setColor(Color.GREEN); gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT); gOffScreen.setColor(c); paint(gOffScreen); //调用paint方法 g.drawImage(offScreenImage, 0, 0, null); } 其次在重绘和按键监听的时候,定义了两个内部类:/**重绘内部类*/ private class PaintThread implements Runnable{ @Override public void run() { while(true){ repaint(); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } } /**事件监听内部类*/ private class KeyMonitor extends KeyAdapter{ public void keyReleased(KeyEvent e){ myTank.keyReleased(e); } public void keyPressed(KeyEvent e){ myTank.keyPressed(e); } } this.addKeyListener(new KeyMonitor());new Thread(new PaintThread()).start(); 这里在按键的时候,定义了八个方向。代码如下所示:private boolean bL=false, bU=false, bR=false, bD = false;enum Direction {L, LU, U, RU, R, RD, D, LD, STOP}; public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); switch(key) { case KeyEvent.VK_F2 : if(!this.live) { this.live = true; this.life = 100; } break; case KeyEvent.VK_LEFT : bL = true; break; case KeyEvent.VK_UP : bU = true; break; case KeyEvent.VK_RIGHT : bR = true; break; case KeyEvent.VK_DOWN : bD = true; break; } locateDirection(); } void locateDirection() { if(bL && !bU && !bR && !bD) dir = Direction.L; else if(bL && bU && !bR && !bD) dir = Direction.LU; else if(!bL && bU && !bR && !bD) dir = Direction.U; else if(!bL && bU && bR && !bD) dir = Direction.RU; else if(!bL && !bU && bR && !bD) dir = Direction.R; else if(!bL && !bU && bR && bD) dir = Direction.RD; else if(!bL && !bU && !bR && bD) dir = Direction.D; else if(bL && !bU && !bR && bD) dir = Direction.LD; else if(!bL && !bU && !bR && !bD) dir = Direction.STOP; } 在区分敌方坦克和自己的坦克的时候,通过一个Boolean变量来区分。创建敌方坦克的时候,默认给他一个方向,然后通过一个random数值来随机敌方坦克的方向, 放弹也是根据一个随机数来获得。 下面是示例代码: private static Random r = new Random(); //定义成静态的,使内存区中只存在一个该实例对象。 private int step = r.nextInt(12) + 3; 然后在move()方法中,开始监听这个变量if(!good) { //如果不是好的坦克(说明是敌方) Direction[] dirs = Direction.values(); if(step == 0) { step = r.nextInt(12) + 3; int rn = r.nextInt(dirs.length); dir = dirs[rn]; } step --; //根据step数值来改变敌方玩家的方向 if(r.nextInt(40) > 38) this.fire(); } 在和其他物体作碰撞检测的时候,如果碰到某个物体的话,则该坦克不允许再移动,这里解决这个问题的办法是定义另外两个变量oldX, oldY来保存之前的x, y变量。如果碰到物体不可行走则将oldX ,oldY 再付给x,y坐标。 2:在制作爆炸物特效的时候用到了这样一个判断:int[] diameter = {4, 7, 12, 18, 26, 32, 49, 30, 14, 6}; //爆破物的直径(由小到大,然后再由大到小,爆破物逐渐消失)private boolean live = true; public void draw(Graphics g) { if(!live) { tc.explodes.remove(this); return; } if(step == diameter.length) { live = false; step = 0; return; } Color c = g.getColor(); g.setColor(Color.ORANGE); g.fillOval(x, y, diameter[step], diameter[step]); g.setColor(c); step ++; }这样通过一个数组,就可以不通过线程来控制,以后这种方法值得借鉴 而下面的血块也是借用了上面一种写法,知识稍微改动了点地方: int step = 0; private boolean live = true; //指明血块运动的轨迹,由pos中各个点构成.(目的是让血块按指定的路线动起来) private int[][] pos = { {350, 300}, {360, 300}, {375, 275}, {400, 200}, {360, 270}, {365, 290}, {340, 280} }; private void move() { step ++; if(step == pos.length){ step = 0; } x = pos[step][0]; y = pos[step][1]; } 这个也是给明了运动轨迹,只不过是循环多次,直到为死亡状态时循环才结束.