Der letzte Blog-Beitrag „Java Mini Game Implementation“: Die Panzerschlacht führte lediglich die Möglichkeit ein, einen Panzer so zu steuern, dass er sich in vier Richtungen bewegt. Heute werden wir auf dieser Grundlage weiterhin kleine Funktionen nacheinander abschließen.
Abgeschlossene Funktion: Steuern Sie einen Panzer so, dass er sich entsprechend den Tastaturtasten in 8 Richtungen bewegt
Um diese Funktion abzuschließen, müssen wir ein paar Dinge tun
1 Der Tastendruckstatus der Tastatur besteht darin, die Überwachungsereignisse beim Drücken und Anheben der Tastatur neu zu schreiben
<code>采用4个boolean变量来记录,按下为true,抬起为false </code>
Der spezifische Implementierungscode lautet wie folgt:
<code class="hljs java"> //定义四个布尔类型变量来记录按键的情况,默认状态下为false,表示没有键按下 private boolean b_L,b_U,b_R,b_D; //记录键盘的按键情况 public void keyMonitor(KeyEvent e){ int key=e.getKeyCode(); switch(key){ case KeyEvent.VK_LEFT: b_L=true; break; case KeyEvent.VK_UP: b_U=true; break; case KeyEvent.VK_RIGHT: b_R=true; break; case KeyEvent.VK_DOWN: b_D=true; break; } //根据上面的按键情况,确定坦克即将要运行的方向,即第二步要完成的内容,具体实现看博文下面 moveDirection(); } //键盘按键松下时,也要进行记录 public void keyReleased(KeyEvent e) { int key=e.getKeyCode(); switch(key){ case KeyEvent.VK_LEFT: b_L=false; break; case KeyEvent.VK_UP: b_U=false; break; case KeyEvent.VK_RIGHT: b_R=false; break; case KeyEvent.VK_DOWN: b_D=false; break; } }</code>
2. Gemäß den Aufzeichnungen in 1 Bestimmen Sie die Laufrichtung des Tanks durch Drücken der Tasten
<code class="hljs dos">8个运行方向采用一个枚举类型来保存。即 private enum Direction{ L,LU,U,RU,R,RD,D,LD,STOP } //例如:如果键盘的左键和下键被按下,则运行方向dir=Direction.LD. //定义一个变量来表示坦克要运行的方向,初始状态为STOP private Direction dir = Direction.STOP; //根据键盘的按键情况来确定坦克的运行方向 private void moveDirection() {//L,LU,U,RU,R,RD,D,LD,STOP if(b_L&&!b_U&&!b_R&&!b_D){ dir = Direction.L; } else if(b_L&&b_U&&!b_R&&!b_D){ dir = Direction.LU; } else if(!b_L&&b_U&&!b_R&&!b_D){ dir = Direction.U; } else if(!b_L&&b_U&&b_R&&!b_D){ dir = Direction.RU; } else if(!b_L&&!b_U&&b_R&&!b_D){ dir = Direction.R; } else if(!b_L&&!b_U&&b_R&&b_D){ dir = Direction.RD; } else if(!b_L&&!b_U&&!b_R&&b_D){ dir = Direction.D; } else if(b_L&&!b_U&&!b_R&&b_D){ dir = Direction.LD; } else{//其它所有情况,都是不动 dir = Direction.STOP; } } </code>
3. Bestimmen Sie die spezifische Laufgeschwindigkeit entsprechend der Bewegungsrichtung in 2. Wenn er sich beispielsweise in die linke untere Richtung bewegt, wird die aktuelle Position des Tanks (x,y) –->(x-XSPEED,y+YSPEED);wobei XSPEED und YSPEED die Laufgeschwindigkeiten der x- und y-Achsen sind.
<code class="hljs rust"> //上面有运行方向,但是还缺少具体的运行细节,例如:假设是按下了右键,则应该横坐标x+=XSPEED; private void move(){ if(dir==Direction.L){//L,LU,U,RU,R,RD,D,LD,STOP x -= XSPEED; } else if(dir==Direction.LU){ x -= XSPEED; y -= YSPEED; } else if(dir==Direction.U){ y -= YSPEED; } else if(dir==Direction.RU){ x += XSPEED; y -= YSPEED; } else if(dir==Direction.R){ x += XSPEED; } else if(dir==Direction.RD){ x += XSPEED; y += YSPEED; } else if(dir==Direction.D){ y += YSPEED; } else if(dir==Direction.LD){ x -= XSPEED; y += YSPEED; } else if(dir==Direction.STOP){ //... nothing } }</code>
Der vollständige Code für die oben genannten drei Schritte lautet wie folgt:
<code class="hljs java"> public class Tank { //坦克所在的位置坐标 private int x; private int y; //定义两个常量,表示运动的速度 private static final int XSPEED = 5; private static final int YSPEED = 5; //定义四个布尔类型变量来记录按键的情况,默认状态下为false,表示没有键按下 private boolean b_L,b_U,b_R,b_D; //定义一个枚举类型来表示运行的方向 private enum Direction{ L,LU,U,RU,R,RD,D,LD,STOP } //定义一个变量来表示坦克要运行的方向,初始状态为STOP private Direction dir = Direction.STOP; public Tank(int x, int y) { super(); this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public void draw(Graphics g){ Color c = g.getColor(); g.setColor(Color.RED); g.fillOval(x, y, 30, 30); g.setColor(c); move();//根据键盘按键的结果改变坦克所在的位置 } //记录键盘的按键情况 public void keyMonitor(KeyEvent e){ int key=e.getKeyCode(); switch(key){ case KeyEvent.VK_LEFT: b_L=true; break; case KeyEvent.VK_UP: b_U=true; break; case KeyEvent.VK_RIGHT: b_R=true; break; case KeyEvent.VK_DOWN: b_D=true; break; } //根据上面的按键情况,确定坦克即将要运行的方向 moveDirection(); } //键盘按键松下时,也要进行记录 public void keyReleased(KeyEvent e) { int key=e.getKeyCode(); switch(key){ case KeyEvent.VK_LEFT: b_L=false; break; case KeyEvent.VK_UP: b_U=false; break; case KeyEvent.VK_RIGHT: b_R=false; break; case KeyEvent.VK_DOWN: b_D=false; break; } } //根据键盘的按键情况来确定坦克的运行方向 private void moveDirection() {//L,LU,U,RU,R,RD,D,LD,STOP if(b_L&&!b_U&&!b_R&&!b_D){ dir = Direction.L; } else if(b_L&&b_U&&!b_R&&!b_D){ dir = Direction.LU; } else if(!b_L&&b_U&&!b_R&&!b_D){ dir = Direction.U; } else if(!b_L&&b_U&&b_R&&!b_D){ dir = Direction.RU; } else if(!b_L&&!b_U&&b_R&&!b_D){ dir = Direction.R; } else if(!b_L&&!b_U&&b_R&&b_D){ dir = Direction.RD; } else if(!b_L&&!b_U&&!b_R&&b_D){ dir = Direction.D; } else if(b_L&&!b_U&&!b_R&&b_D){ dir = Direction.LD; } else{//其它所有情况,都是不动 dir = Direction.STOP; } } //上面有运行方向,但是还缺少具体的运行细节,例如:假设是按下了右键,则应该横坐标x+=XSPEED; private void move(){ if(dir==Direction.L){//L,LU,U,RU,R,RD,D,LD,STOP x -= XSPEED; } else if(dir==Direction.LU){ x -= XSPEED; y -= YSPEED; } else if(dir==Direction.U){ y -= YSPEED; } else if(dir==Direction.RU){ x += XSPEED; y -= YSPEED; } else if(dir==Direction.R){ x += XSPEED; } else if(dir==Direction.RD){ x += XSPEED; y += YSPEED; } else if(dir==Direction.D){ y += YSPEED; } else if(dir==Direction.LD){ x -= XSPEED; y += YSPEED; } else if(dir==Direction.STOP){ //... nothing } } }</code>
Die Hauptänderung in der Datei TarkClient.java besteht darin, eine Button-Lift-Methode neu zu schreiben.
<code class="hljs java"> private class KeyMonitor extends KeyAdapter{ @Override public void keyPressed(KeyEvent e) { tk.keyMonitor(e); } @Override public void keyReleased(KeyEvent e) { tk.keyReleased(e); } }</code>
Damit ist die Steuerung des Tanks in 8 Richtungen abgeschlossen.
Abgeschlossene Funktion: Panzer können Kugeln abfeuern
Da es sich um eine Panzerschlacht handelt, muss es doch auch Kugeln abfeuern können, oder?
Zuerst erstellen wir eine Aufzählungsklasse. Die Aufzählungsklasse sollte auch Positions- und Richtungsattribute sowie Zeichen- und Bewegungsmethoden haben.
Der Code lautet wie folgt:
<code class="hljs java"> public class Missile { //定义两个常量,表示运动的速度 private static final int XSPEED = 20; private static final int YSPEED = 20; //子弹所在的位置 private int x; private int y; //子弹的运行方向 private Direction dir; public Missile(int x, int y, Direction dir) { this.x = x; this.y = y; this.dir = dir; } public void draw(Graphics g){ Color c = g.getColor(); g.setColor(Color.YELLOW); g.fillOval(x, y, 5, 5); g.setColor(c); move(); } private void move() { if(dir==Direction.L){//L,LU,U,RU,R,RD,D,LD,STOP x -= XSPEED; } else if(dir==Direction.LU){ x -= XSPEED; y -= YSPEED; } else if(dir==Direction.U){ y -= YSPEED; } else if(dir==Direction.RU){ x += XSPEED; y -= YSPEED; } else if(dir==Direction.R){ x += XSPEED; } else if(dir==Direction.RD){ x += XSPEED; y += YSPEED; } else if(dir==Direction.D){ y += YSPEED; } else if(dir==Direction.LD){ x -= XSPEED; y += YSPEED; } } } </code>
Dann testen wir ihn, indem wir eine unkontrollierte Kugel in die Schnittstelle zeichnen.
In der TankClient-Klasse gibt es eine Rakete Objekt, und rufen Sie dann Missiles Draw in Paint auf, um es zu zeichnen.
<code class="hljs java"> public class TankClient extends Frame{ //....无关代码没有显示 private Missile ms =new Missile(50,50,Direction.D);//一个子弹对象 @Override public void paint(Graphics g) { //直接调用坦克至圣的draw方法 tk.draw(g); if(ms!=null){ ms.draw(g); } } //....无关代码没有显示 }</code>
Jetzt müssen wir erkennen, dass durch Drücken der Strg-Taste Kugeln aus dem Panzer abgefeuert werden. Da ein Panzer eine Kugel abfeuert, sollte es in der Panzerklasse eine Methode zum Abfeuern von Kugeln mit dem Namen fire() geben, und der Rückgabewert ist ein Bullet-Objekt. Das Geschossobjekt wird mit der aktuellen Position und Richtung des Panzers initialisiert.
<code class="hljs cs"> public Missile fire(){ Missile ms = new Missile(x,y,dir); return ms; } </code>
Wir wollen eine Kugel abfeuern, wenn die Strg-Taste gedrückt wird.
Fügen Sie also in der keyPressed-Methode in der Tank-Klasse den Fall hinzu, in dem der Schlüsselwert Strg ist. Weil das von fire() zurückgegebene Missile-Objekt zum Initialisieren der Missile-Referenz in der TankClient-Klasse verwendet werden muss. Daher müssen Sie in der Tank-Klasse eine Referenz auf TankClient halten, um auf die Missile-Referenz in TankClient zuzugreifen.
<code class="hljs cs"> private TankClient tc; public Tank(int x, int y) { this.x = x; this.y = y; } public Tank(int x, int y, TankClient tc) { this(x,y); this.tc = tc; } //记录键盘的按键情况 public void keyPressed(KeyEvent e){ int key=e.getKeyCode(); //System.out.println(key); switch(key){ case 17: //按下Ctrl键时的处理情况,tc是一个TankClient对象,里面有一个子弹的引用 tc.setMs(fire()); break; case KeyEvent.VK_LEFT: b_L=true; break; case KeyEvent.VK_UP: b_U=true; break; case KeyEvent.VK_RIGHT: b_R=true; break; case KeyEvent.VK_DOWN: b_D=true; break; } //根据上面的按键情况,确定坦克即将要运行的方向 moveDirection();
Der Code in der TankClient.java-Klasse lautet wie folgt:
<code class="hljs java"> public class TankClient extends Frame{ private final static int GAME_WIDTH=600; private final static int GAME_HEIGHT=600; private Tank tk=new Tank(50,50,this);//将this穿进去初始化TankClient private Missile ms ;//持有一个Missile的引用 public Missile getMs() { return ms; } public void setMs(Missile ms) { this.ms = ms; } private Image offScreenImage = null; public static void main(String[] args) { new TankClient().launchFrame(); } @Override 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.darkGray); goffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT); goffScreen.setColor(c); paint(goffScreen); g.drawImage(offScreenImage, 0, 0, null); } @Override public void paint(Graphics g) { //直接调用坦克至圣的draw方法 tk.draw(g); if(ms!=null){ ms.draw(g); } } public void launchFrame(){ this.setTitle("坦克大战"); this.setLocation(300, 400); this.setSize(GAME_WIDTH, GAME_HEIGHT); this.setBackground(Color.GRAY); //为关闭窗口添加响应 this.addWindowListener(new WindowAdapter(){ @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); //设置是否允许用户改变窗口的大小,这里限制下,不允许 this.setResizable(false); this.setVisible(true); new Thread(new MyRepaint()).start(); this.addKeyListener(new KeyMonitor()); } private class MyRepaint implements Runnable{ @Override public void run() { while(true){ //每50ms重画一次 repaint(); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } } private class KeyMonitor extends KeyAdapter{ @Override public void keyPressed(KeyEvent e) { tk.keyPressed(e); } @Override public void keyReleased(KeyEvent e) { tk.keyReleased(e); } } } </code>
Das Obige implementiert einen Panzer, der durch Drücken der Strg-Taste eine Kugel abfeuert.
Noch nicht fertig! ! !
Das Obige ist der Inhalt von „Java Mini Game Implementation“: Tank Battle (Fortsetzung). Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn)!