Пожалуйста, обратитесь к примечаниям за подробностями. Я не буду вдаваться в ерунду, просто поймите классику детства.
Кровь.java
package com.hkm.TankWar;import java.awt.*;/** * Класс сгустка крови, наш танк может восстановить кровь, съев ее * @author Hekangmin * */public class Blood { Private int x,y,w, h; //Положение, ширина и высота сгустка крови; Private TankWarClient tc; Private int Step=0; //Запишите количество шагов, на которые движется сгусток крови; Private boolean live=true; public boolean isLive() { return live; } public void setLive(boolean live) { this.live = live } /** * Запишите местоположение тромба */ Private int[][] pos={{400,300},{400,320},{420,320},{440,300},{440,330},{480,400},{520,400},{540,400}} { x=pos[0][0]; y=pos[0][1]; ш=ч=18; } Public void draw(Graphics g) { if(!live) return; Color c=g.getColor(); g.setColor(Color.CYAN); g.fillOval(x, y, w, h); (c); move(); } /** * Переместить тромб*/ public void move() { Step++; if(step>=pos.length) else{ x=pos[step][0); ]; y=pos[step][1]; } } public Rectangle getRect() { return new Rectangle(x,y,w,h) };
Взорвать.java
package com.hkm.TankWar;import java.awt.*;/** * Explode class* @author Hekangmin * */public class Explode { Private int x,y;//Место, где произошел взрыв Private Boolean Live=true ; int Dia[]={4,8,12,16,32,40,20,14,4} // Используйте симуляцию круга для представления диаметра круга; Step=0;//Разница переносится на диаметр Private TankWarClient tc;//Удерживает ссылку public Explode(int x,int y,TankWarClient tc) { this.x=x; this.y=y; =tc; } public void draw(Graphics g) { if(!Live) { tc.explodes.remove(this return); if(step==dia.length)//Если он достигнет последнего диаметра, он взорвется и умрет { Live=false; шаг=0; return; g.getColor(); .YELLOW); g .fillOval(x, y, диаметр[шаг], диаметр[шаг]); g.setColor(c } };
Ракета.java
пакет com.hkm.TankWar;импортировать java.awt.*;импортировать java.awt.Event.*;импортировать java.awt.event.KeyEvent;импортировать java.util.List;/** * Класс маркера* @author Hekangmin * */ public class Missile { Private int x,y;//Положение пули Private Tank.Direction dir;//Направление танка Private static Final int XSPEED=10;//Скорость движения танка в направлении x, Private static Final int YSPEED=10;//Скорость движения танка в направлении y, public static Final int WIDTH=10; HEIGHT=10; Private boolean Live= true; // Определить, жива ли пуля. Private boolean Good // Отличить вражеские пули от наших. Private TankWarClient tc; public Missile(int x, int y, Tank.Direction; dir) { this.x = x; this.y = y; this.dir = dir; } public Missile(int x,int y,boolean Good,Tank.Direction dir,TankWarClient tc) { this(x,y,dir) ); this.good=good;//Устанавливаем одинаковые хорошие и плохие атрибуты танка и атрибут возврата урона пули this.tc=tc; } /** * Рисовать пули* @param; g — кисть*/ public void draw(Graphics g) { if(!Live) { tc.missiles.remove(this); Color c=g.getColor(); if(good) { g.setColor( Color .BLUE); } else g.setColor(Color.ORANGE); g.fillOval(x, y, WIDTH, HEIGHT); g.setColor(c); } /** * Перемещаем пулю в соответствии с направлением движения танка */ Private void move() { switch(dir) { case L: x-=XSPEED; case LU: x-=XSPEED; ; перерыв; случай U: y-=YSPEED; перерыв; случай RU: x+=XSPEED; перерыв; случай R: x+=XSPEED; y+=YSPEED; перерыв; случай D: y+=YSPEED; случай LD: x-=XSPEED; y+=YSPEED; перерыв } if(x<0||y<0||x>TankWarClient.GAME_WIDTH||y >TankWarClient.GAME_HEIGHT)//Если пуля пересекает границу, пусть она умрет { Live=false; } } public boolean isLive() { return; Live; } public Rectangle getRect() // Получить прямоугольную область пули { return new Rectangle(this.x, this.y, this.WIDTH, this.HEIGHT); пуля сталкивается с танком; * @param t — танк* @return возвращает true, чтобы указать на столкновение, в противном случае столкновения нет */ public boolean hitTank(Tank t) {; if(this.Live&&this.getRect().intersects(t.getRect())&&t.isLive()&&this.good!=t.isGood()) { if(t.isGood()) { t.setLife(t. getLife()-10); if(t.getLife()<=0) t.setLive(false); }else { t.setLive(false); this.Live=false;///Уничтожьте пулю; Explode e=new Explode(x,y,tc);//Происходит взрыв; tc.explodes.add(e); return true; } /** * Определить, столкнулась ли пуля с вражеским танком; * @param Tanks вражеский танк* @returntrue означает столкновение, false не сталкивается */ public boolean hitTanks(List<Tank> Tanks) { for(int i=0;i<tanks.size();i++) { if(hitTank(tc.tanks.get(i))) { return true; } } return false } /** * Определить, попала ли пуля попадает в стену * @param w wall* @returntrue, hit, false, not hit */ public boolean hitsWall(Wall w) { if(this.Live&&this.getRect().intersects(w.getRect())) { Live=false; return true; return false; } }
Танк.java
package com.hkm.TankWar;import java.awt.*;import java.awt.event.KeyEvent;import java.util.*;/** * Tank class* @author Hekangmin * */public class Tank { public static Final int XSPEED=5;//скорость танка в направлении x public static Final int YSPEED=5 public static Final int WIDTH=30; public static Final int HEIGHT=30; BloodBar bb=new BloodBar();//полоска крови Private int life=100; public int getLife() { return life; } public void setLife(int life) { this.life = life } Private static Random r=new Random (); Private static int Step=r.nextInt(12)+3;//Определите число, обозначающее количество шагов, которые вражеский танк делает для случайного перемещения. Private boolean; bL=false,bU=false,bR=false,bD=false; enum Direction{L,LU,U,RU,R,RD,D,LD,STOP};//Используйте тип перечисления для определения частного направления; int x,y; Private int oldX,oldY;//записываем положение резервуара на предыдущем шаге; Private boolean live=true;//определяем, жив ли он public boolean isLive() { return live } public void setLive; (логическое значение live) { this.live = live; } Private boolean Good;//Танк хороший или плохой? public boolean isGood() { return Good; } Private Direction ptDir=Direction.D;//Добавляем направление ствола; TankWarClient tc ;//Чтобы сохранить ссылку другой стороны для облегчения доступа к ее переменным-членам; Direction dir=Direction.STOP;//Установить направление остановки танка в начале public Tank(int x, int y, логическое значение хорошо, направление dir,TankWarClient tc) { this.x=x; this.oldX=x; this.good=good; this.tc=tc;// Удерживайте ссылку другой стороны; } public void draw(Graphics g) { if(!live)//Если он умрет, он больше не будет рисоваться; { if(!good) { tc.tanks.remove(this); if(tc.tanks.size()<5)//Добавляем танки, если их меньше 5 { for(int i=0;i<10;i++) { int posX=r.nextInt(800); posY =r.nextInt(600); tc.tanks.add(new Tank(posX,posY,false,Direction.D,tc));//Сделаем расположение танка случайным} } } return; } Color c=g.getColor(); if(good) { g.setColor(Color.RED); } else g.setColor(Color.BLACK); x, y, WIDTH, HEIGHT); g.setColor(c); switch(ptDir) // Нарисуйте направление ствола { case L: g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x-10, y+Tank.HEIGHT/2); //Нарисуйте ствол орудия и вместо него нарисуйте прямую линию; : g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x-7, y-7 разрыв; g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH/2, y-10; разрыв; регистр RU: g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH+7, y-7); g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH+10, y+Tank.HEIGHT/2); разрыв; случай RD: g.drawLine(x+Tank. WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH+7, y+Tank.HEIGHT+7); разрыв; g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH/2, y+Tank.HEIGHT+10); разрыв регистра LD: g.drawLine(x+Tank. WIDTH/2, y+Tank.HEIGHT/2, x-7, y+HEIGHT+7 } move() } public void move() {; oldX=x;//Запишите предыдущее положение резервуара oldY=y; switch(dir) { case L: x-=XSPEED; case LU: x-=XSPEED; y-=YSPEED; y -=YSPEED; случай RU: x+=XSPEED; y-=YSPEED; случай R: x+=XSPEED; случай RD: x+=XSPEED; y+=YSPEED; случай D: y+=YSPEED; случай LD: x-=XSPEED; перерыв; случай STOP: перерыв } if(this.dir!=Direction.STOP) this.ptDir= this.dir; /** * Запретить танкам пересекать границу */ if(x<0) x=0 if(y<25) y=25; if(x+Tank.WIDTH>TankWarClient.GAME_WIDTH) x=TankWarClient.GAME_WIDTH-30; if(y+Tank.HEIGHT>TankWarClient.GAME_HEIGHT) y=TankWarClient.GAME_HEIGHT-30 if(!good) { Direction[] dirs; =Direction.values();//Преобразуем тип перечисления в массив; if(step==0) {step=r.nextInt(12)+3; int rn=r.nextInt(dirs.length);//Сгенерируем случайное целое число в пределах длины; dir=dirs[rn]; -; if(r.nextInt(40)>20) this.fire(); // Заставляем вражеский танк стрелять пулями; } } /** * Обработка нажатия клавиш* @param e Keyboard event; public void KeyPressed(KeyEvent e) { int key=e.getKeyCode(); switch(key) {case KeyEvent.VK_LEFT: bL=true; case KeyEvent.VK_RIGHT: bR=true; case KeyEvent.VK_UP: bU = true; перерыв; случай KeyEvent.VK_DOWN: bD = true; перерыв} locationDir (); keyReleased(KeyEvent e) { int key=e.getKeyCode(); switch(key) { случай KeyEvent.VK_CONTROL: fire(); перерыв; случай KeyEvent.VK_LEFT: bL=false; случай KeyEvent.VK_RIGHT: bR=false ; перерыв; случай KeyEvent.VK_UP: bU=false; случай KeyEvent.VK_DOWN: bD=false;break;case KeyEvent.VK_A: superFire();break;case KeyEvent.VK_F2: reBorn();break; } locationDir(); } /** * Выстрелить* @return Возвращает тип пули*/ public Missile fire() { if(!live) return null int; mx=this.x+Tank.WIDTH/2-Missile.WIDTH/2;//Рассчитать положение запуска пули; int my=this.y+Tank.HEIGHT/2-Missile.HEIGHT/2; new Missile (mx,my,good,ptDir,this.tc);////Запускаем пули в соответствии с направлением ствола tc.missiles.add(m); return m; public Missile fire(Direction dir) { if(!live) return null; int mx=this.x+Tank.WIDTH/2-Missile.WIDTH/2; int my=this.y+Tank.HEIGHT/2-Missile.HEIGHT/2; new Missile(mx,my,good,dir,this.tc);//Запускаем пули в соответствии с направлением танка; tc.missiles.add(m); return m; public void superFire() { Direction[] dirs=Direction.values(); for(int i=0;i<8;i++) { fire(dirs[i]); } public void locationDir() { if(bL&&!bU&&!bR&&!bD ) dir=Direction.L; иначе if(bL&&bU&&!bR&&!bD) dir=Direction.LU; 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; !bU&&bR&&bD) dir=Direction.RD; 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 } public Rectangle getRect() //Получаем прямоугольную площадь резервуара{ return new Rectangle(this.x,this.y,this.WIDTH,this.HEIGHT); } /** * Танк врезался в стену* @param w wall* @returntrue hit, false не попал; */ public booleancolliedsWithWall( Стена w) { if(this.live&&this.getRect().intersects(w.getRect())) { this.stay(); return false } /** * Обработка столкновений танков, чтобы они не пересекали друг друга; * @param Tanks вражеские танки; * @return true, если они сталкиваются, false, если нет */ public booleancolliedsWithTanks(java.util.List< Tank> Tanks) { for(int i=0;i<tanks.size();i++) { Tank t=tanks.get(i); if(this!=t) { if(this.live&&this.isLive()&&this.getRect().intersects(t.getRect()))) { this.stay();//Вернемся к позиции предыдущего шага t.stay();// //Вернем позицию предыдущего шага return true; } } return false } Private void Stay() { x=oldX; y=oldY; Это внутренний класс Tank; полоса крови отображается в верхней части головы нашего танка * @author Hekangmin * */ Private class BloodBar { public void draw(Graphics g) { Color c=g.getColor(); .setColor( Color.RED); g.drawRect(x,y-10,WIDTH,10); int w=WIDTH*life/100; g.fillRect(x,y-10,w,10); } } /** * Съедать сгустки крови и добавлять кровь; * @param b сгустки крови* @returntrue, если съедены, false, если не съедены */ public boolean eat; (Кровь b) { if(this.live&&b.isLive()&&this.getRect().intersects(b.getRect()))) { this.life=100; b.setLive(false); return true; } return false; } /** * Наш танк воскреснет после смерти; */ public void reBorn() { if(this.isGood()&&!this.isLive()) { this.setLive(true); this.setLife(100);
TankWarClient.java
package com.hkm.TankWar;import java.awt.*;import java.awt.event.*;import java.util.List;import java.util.ArrayList; /** * Это рабочее окно игры; * @ автор Hekangmin * */public class TankWarClient расширяет Frame{/** * Ширина игрового окна */ public static Final int GAME_WIDTH=800; Высота игрового окна; */ public static Final int GAME_HEIGHT=600; Tank MyTank=new Tank(700,400,true,Tank.Direction.STOP,this); List<Tank> Tanks=new ArrayList<Tank>(); List< Explode> взрывы = новый ArrayList<Explode>(); List<Missile> ракеты = новый ArrayList<Missile>(); Wall(300,200,20,200,this); Wall w2=new Wall(600,300,30,150,this); Blood b=new Blood(); /** * Рисуем виртуальную картинку; */ Image OffScreenImage=null; name)//Set text { super(name) } /** * Выполнить окно */ public void launchFrame() { for(int) i=0;i<10;i++)//Добавляем десять вражеских танков { Tanks.add(new Tank(50+40*(i+1),50,false,Tank.Direction.D,this } this)); .setBounds(200,100,GAME_WIDTH,GAME_HEIGHT); this.setBackground(Color.GREEN); this.addWindowListener(новый); WindowAdapter()//Анонимный класс { public void windowClosing(WindowEvent e) { System.exit(0 } }); this.addKeyListener(new KeyMonitor());//Добавить монитор клавиатуры; this.setResizable(false) ; //Размер окна изменить нельзя; this.setVisible(true); new Thread(new PaintThread()).start();//Создаем новый поток } public void; Paint(Graphics g) { g.drawString("Количество ракет: "+missiles.size(), 10, 50); //Отображение строки; g.drawString("Количество взрывов: "+explodes.size(),10 , 70); g.drawString("Количество танков: "+tanks.size(),10,90); g.drawString("Жизнь моего танка: "+MyTank.getLife(),10,110); /** * Рисуем стену; */ w1.draw(g); w2.draw(g); /** * Обнаруживаем пули и различные события; */ for (int i=0;i<missiles.size();i++) { Ракета m=missiles.get(i); m.hitsWall(w1); m.hitsWall(w2); m.hitTanks(tanks); m.hitTank(MyTank); m.draw(g); //if(!m.isLive()) //missiles.remove(m); //иначе m.draw(g) ; } /** * Рисовать взрывы; */ for(int i=0;i<explodes.size();i++) { Explode e=explodes.get(i); e.draw(g); for(int i=0;i<tanks.size();i++) { Tank t=tanks.get(i); t.colliedsWithWall(w1); t.colliedsWithWall(w2); t.colliedsWithTanks(tanks); .draw(г); } b.draw(г); MyTank.eat(b); * Используйте технологию двойной буферизации, чтобы устранить явление мерцания танка */ public void update(Graphics g) //g — нарисованная на экране кисть { if(OffScreenImage==null) OffScreenImage=this.createImage(GAME_WIDTH, GAME_HEIGHT; ); Графика gOffScreen=OffScreenImage.getGraphics();//gOffScreen — кисть OffScreenImage; Color c=gOffScreen.getColor(); gOffScreen.setColor(Color.GREEN); gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT); gOffScreen.setColor(c); Paint(gOffScreen);//Рисуем на виртуальном изображении; g.drawImage(OffScreenImage,0,0,null);//Используем кисть g, чтобы рисовать объекты на виртуальном изображении на экране} частный класс PaintThread реализует Runnable{ public void run() { while(true) { repaint(); //Метод перерисовки здесь — это попытка { класса Frame Thread.sleep(100); }catch(InterruptedException e){e.printStackTrace(); } } } } частный класс KeyMonitor расширяет KeyAdapter { public void keyReleased(KeyEvent e) { MyTank.keyReleased(e); public void keyPressed( KeyEvent e) { MyTank.KeyPressed(e} } public static void); main(String[] args) { new TankWarClient("Мой танковый мир").launchFrame() } };
Стена.java
package com.hkm.TankWar;import java.awt.*;/** * Создать класс стены с препятствиями * @author Hekangmin * */ public class Wall { /** * x, y — положение стены, w; , h — ширина и высота; */ int x,y,w,h; /** * содержит ссылку*/ TankWarClient tc; public Wall(int x, int y, int w, int h, TankWarClient tc) { this.x = x; this.w = w; this.tc = tc } public void draw(Graphics g) { Color c=g.getColor() ; g.setColor(Color.GRAY); g.fillRect(x,y,w,h); g.setColor(c); } /** * Получить прямоугольную область стены; общественный Rectangle getRect() { return new Rectangle(x,y,w,h) };
Выше приведено все содержание этой статьи, надеюсь, она вам всем понравится.