一唉窃、任務(wù)需求
添加hero坦克子彈并且發(fā)射窟蓝。
二、思路
1.創(chuàng)建子彈類
1.由于每顆子彈都是一個獨立的線程篮绿,會不斷變換子彈坐標孵延,所以子彈類要實現(xiàn)Runnable接口。
2.子彈需要坐標x,y以及方向亲配,所以構(gòu)造函數(shù)有三個參數(shù)尘应。
3.實現(xiàn)Runnable接口后惶凝,要覆蓋run方法:
????1.如果不讓線程sleep,子彈飛出去很快犬钢,快到在屏幕如上瞬間消失苍鲜。
????2.所以增加一個sleep()
????3.另外,子彈需要判斷四個方向玷犹,增加switch語句
????4.子彈跑出屏幕需要死亡混滔,增加變量islive判斷是否存活。否則無限制飛行歹颓,不斷占用內(nèi)存空間坯屿。
2.hero坦克類中加入shotEnemy()方法,表示發(fā)射子彈
1.新建子彈變量s
????Shot s = null;
2.判斷開火的方向巍扛,增加switch語句领跛。
3.開火后,啟動線程撤奸。
Thread t =newThread(s);
????t.start();
3.完成子彈實現(xiàn)過程吠昭,接著要在屏幕中讓子彈顯示,即畫出子彈
1.paintComponent方法里加入寂呛,畫出子彈
????判斷子彈是否存活
????hero.s!=null很重要怎诫,游戲剛開始沒有發(fā)射子彈,hero.s=null贷痪,此時進入if去畫子彈會出現(xiàn)異常。
????if(hero.s!=null&&hero.s.isLive==true){
????????g.setColor(Color.red);
????????g.draw3DRect(hero.s.x, hero.s.y, 1, 1, false);
????}
2.在KeyPressed監(jiān)聽器處添加蹦误,按下J鍵發(fā)射一顆子彈
????if(e.getKeyCode()==KeyEvent.VK_J){
????????hero.shotEnemy();
????}
4.MyPanel實現(xiàn)Runnable接口
1.由于子彈打出去后劫拢,需要不斷讓它顯示,屏幕每隔一段時間需要repaint()
????所以重載run()方法强胰,讓MyPanel每隔一段時間repaint()一次
????publicvoidrun() {
????while(true){
????????try{
????????????Thread.sleep(100);//休息100ms舱沧,重畫一次MyPanel
????????} catch(Exception e) {
????????????e.printStackTrace();
????????}
????????repaint();
????}
5.由于MyPanel實現(xiàn)了Runnable接口,所以讓該線程跑起來
1.在MyTankGame方法中啟動線程即可
????p1 = newMyPanel();
????????Thread t = newThread(p1);
????????t.start();
三偶洋、代碼如下
MyTankGame.java
<?喎?"https://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;">?/** * 功能:坦克游戲的2.0 * 1.畫出坦克 * 2.坦克的移動 * 3.坦克發(fā)射子彈 */ package Tank_03; import java.awt.Color; import java.awt.Graphics; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.Vector; import javax.swing.JFrame; import javax.swing.JPanel; @SuppressWarnings("serial") public class MyTankGame2 extends JFrame{ MyPanel p1 = null; public MyTankGame2(){ p1 = new MyPanel(); Thread t = new Thread(p1); t.start(); add(p1); setSize(400, 300); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); addKeyListener(p1);//注冊監(jiān)聽 } public static void main(String[] args) { new MyTankGame2(); } } //畫圖 @SuppressWarnings("serial") class MyPanel extends JPanel implements KeyListener,Runnable{ Hero hero = null; Vector?ets = new Vector(); int enSize = 3; public MyPanel(){ hero = new Hero(100,100);//設(shè)置坦克出現(xiàn)的位置(10熟吏,10) // 初始化敵人的坦克 for(int i=0;i坦克的顏色(類型:敵方坦克,我方坦克)玄窝,方向牵寺,出現(xiàn)的坐標 * * 如果type是default 則默認顏色為畫出黑色坦克 * * 封裝性:將坦克封裝到方法中。 * */ public void drawTank(int x,int y,Graphics g,int direct,int type){ switch (type) { case 0: g.setColor(Color.cyan); break; case 1: g.setColor(Color.yellow); default: break; } switch (direct) { case 0: //向上 g.fill3DRect(x , y , 5 , 30, false); g.fill3DRect(x+15, y , 5 , 30, false); g.fill3DRect(x+5 , y+5 , 10, 20, false); g.fillOval(x+4, y+10, 10 , 10); g.drawLine(x+9, y+15, x+9, y ); break; case 1: //向下w g.fill3DRect(x , y , 5 , 30, false); g.fill3DRect(x+15, y , 5 , 30, false); g.fill3DRect(x+5 , y+5 , 10, 20, false); g.fillOval(x+4, y+10, 10 , 10); g.drawLine(x+9, y+15, x+9, y+30 ); break; case 2: //向左 g.fill3DRect(x , y , 30, 5 , false); g.fill3DRect(x , y+15 , 30, 5 , false); g.fill3DRect(x+5 , y+5 , 20, 10, false); g.fillOval(x+9 , y+4, 10 , 10 ); g.drawLine(x+5, y+9, x-4, y+9); break; case 3: //向右 g.fill3DRect(x , y , 30, 5 , false); g.fill3DRect(x , y+15 , 30, 5 , false); g.fill3DRect(x+5 , y+5 , 20, 10, false); g.fillOval(x+9 , y+4, 10 , 10 ); g.drawLine(x+15, y+9, x+30, y+9); break; default: break; } //repaint(); 因為監(jiān)聽器里面有repaint() 所以不用在加repaint()了 } @Override public void keyTyped(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) {//實現(xiàn)接口 根據(jù)按鍵上下左右移動 可以控制速度和移動 if(e.getKeyCode()==KeyEvent.VK_W){ hero.setDirect(0); hero.moveUp(); }else if(e.getKeyCode()==KeyEvent.VK_S){ hero.setDirect(1); hero.moveDown(); }else if(e.getKeyCode()==KeyEvent.VK_A){ hero.setDirect(2); hero.moveLeft(); }else if(e.getKeyCode()==KeyEvent.VK_D){ hero.setDirect(3); hero.moveRight(); } if(e.getKeyCode()==KeyEvent.VK_J){ //開火 hero.shotEnemy(); } //判斷玩家是否按下J攻擊鍵 repaint(); } @Override public void keyReleased(KeyEvent e) { } //@Override public void run() { //每隔100毫秒 重新畫圖 while(true){ try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } repaint(); } } }
members.java
packageTank_03;
//坦克父類? 可以設(shè)置坦克出現(xiàn)位置(x恩脂,y)
classTank {
????intx = 0;
????inty = 0;
????intspeed = 10;
????intDirect = 0;
????intcolor;
????publicintgetColor() {
????????returncolor;
????}
????publicvoidsetColor(intcolor) {
????????this.color = color;
????}
????publicintgetDirect() {
????????returnDirect;
????}
????publicvoidsetDirect(intdirect) {
????????Direct = direct;
????}
????publicintgetSpeed() {
????????returnspeed;
????}
????publicvoidsetSpeed(intspeed) {
????????this.speed = speed;
????}
????publicTank (intx,inty){
????????this.x = x;
????????this.y = y;
????}
????publicintgetX() {
????????returnx;
????}
????publicvoidsetX(intx) {
????????this.x = x;
????}
????publicintgetY() {
????????returny;
????}
????publicvoidsetY(inty) {
????????this.y = y;
????}
????//視頻中是把移動放在hero類中
}
//敵方坦克
classEnemyTank extendsTank{
????publicEnemyTank(intx, inty) {
????????super(x, y);
????}
}
//我的英雄坦克
classHero extendsTank{
????//子彈
????Shot s = null;
????publicHero(intx,inty){
????????super(x, y);
????}
????//開火
????publicvoidshotEnemy(){
????????switch(Direct) {
????????case0:
????????????s = newShot(x+8,y-4,0);
????????????break;
????????case1:
????????????s = newShot(x+9,y+32,1);
????????????break;
????????case2:
????????????s = newShot(x-8,y+8,2);
????????????break;
????????case3:
????????????s = newShot(x+32,y+9,3);
????????????break;
????????default:
????????????break;
????????}
????????Thread t =newThread(s);
????????t.start();
????}
????publicvoidmoveUp(){
????????y-=speed;
????}
????publicvoidmoveDown(){
????????y+=speed;
????}
????publicvoidmoveLeft(){
????????x-=speed;
????}
????publicvoidmoveRight(){
????????x+=speed;
????}
}
//子彈類
classShot implementsRunnable{
????intx;
????inty;
????intDirect;
????intspeed = 5;
????booleanisLive = true;
????publicShot(intx,inty,intDirect){
????????this.x=x;
????????this.y=y;
????????this.Direct = Direct;
????}
????@Override
????publicvoidrun() {
????????while(true){
????????????try{
????????????????Thread.sleep(50);
????????????} catch(Exception e) {
????????????????// TODO: handle exception
????????????}
????????????switch(Direct){
????????????case0:
????????????????y-=speed;
????????????????break;
????????????case1:
????????????????y+=speed;
????????????????break;
????????????case2:
????????????????x-=speed;
????????????????break;
????????????case3:
????????????????x+=speed;
????????????????break;
????????????default:
????????????????break;
????????????}
//????????? System.out.println(""+x+" "+y);
????????????//子彈何時死亡
????????????if(x<0||x>400||y<0||y>300){
????????????????isLive = false;
????????????????break;
????????????}
????????}
????}
}
四帽氓、效果圖