坦克大戰【1】 筆記目錄:(https://www.cnblogs.com/wenjie2000/p/16378441.html) 坦克大戰游戲演示 為什麼寫這個項目 ✔好玩 ✔涉及到java各個方面的技術 java面向對象編程 多線程 文件i/o操作 資料庫 ✔鞏固舊知識,學習新知識 寫項目前的提 ...
坦克大戰【1】
筆記目錄:(https://www.cnblogs.com/wenjie2000/p/16378441.html)
坦克大戰游戲演示
為什麼寫這個項目
✔好玩
✔涉及到java各個方面的技術
- java面向對象編程
- 多線程
- 文件i/o操作
- 資料庫
✔鞏固舊知識,學習新知識
寫項目前的提醒
-
編寫坦克大戰游戲,你需要有一定的java基礎,是完全可以聽懂的,最核心的部分一起完成。
-
記住一點:成為一個編程高手的秘訣就是:思考------編程-----思考------編程
如何講解這個項目,授課的原則:
-
努力做到通俗易懂。
-
寧肯羅嗦一點,也不遺漏細節。
-
項目是從小到大的過程,每個完整的項目被分解成不同的版本,從1.0到1.1.….最後版,隨版本的增加,將新的功能和新的知識點融入到項目中,整個過程是循序漸進的。讓大家輕鬆的學習,高效的掌握java技術。
java繪圖坐標體系
●坐標體系-介紹
下圖說明瞭Java坐標系。坐標原點位於左上角,以像素為單位。在Java坐標系中,第一個是x坐標,表示當前位置為水平方向,距離坐標原點x個像素;第二個是y坐標,表示當前位置為垂直方向,距離坐標原點y個像素。
坐標體系-像素
- 繪圖還必須要搞清一個非常重要的概念-像素個個像素等於多少釐米?
- 電腦在屏幕上顯示的內容都是由屏幕上的每一個像素組成的。例如,電腦顯示器的解析度是800×600,表示電腦屏幕上的每一行由800個點組成,共有600行,整個電腦屏幕共有480 000個像素。像素是一個密度單位,而釐米是長度單位,兩者無法比較
java繪圖技術
介紹-快速入門
先給大家寫一個小案例,在面板上畫一個小圓,然後借這個案例,來講解java繪圖技術原理。
import javax.swing.*;
import java.awt.*;
public class DrawCircle extends JFrame {//JFrame對應視窗,可以理解成是一個畫框
//定義一個面板
private MyPanel mp = null;
public static void main(String[] args) {
new Te();
System.out.println("退出程式...");
}
public DrawCircle() {//構造器
//初始化面板
mp = new MyPanel();
//把面板放入到視窗(畫框)
this.add(mp);
//設置視窗的大小
this.setSize(400,300);
///當點擊視窗的小x,程式完全退出.
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);//可以顯示
}
}
//1.先定義一個MyPanel,繼承JPanel類,畫圖形,就在面板上畫
class MyPanel extends JPanel {
//說明:
//1.MyPanel對象就是一個畫板
//2.Graphics g把g理解成一支畫筆
//3.Graphics提供了很多繪圖的方法
//Graphics g
@Override
public void paint(Graphics g) {//繪圖方法
super.paint(g);//調用父類的方法完成初始化
System.out.println("調用了paint方法");
//畫出一個圓形.
g.drawOval(10, 10, 100, 100);
}
}
繪圖原理
✔Component類提供了兩個和繪圖相關最重要的方法:
-
paint(Graphics g)繪製組件的外觀
-
repaint()刷新組件的外觀。
✔當組件第一次在屏幕顯示的時候,程式會自動的調用paint()方法來繪製組件。
✔在以下情況paint()將會被調用:
- 視窗最小化再最大化
- 視窗的大小發生變化
- repaint方法被調用
✔思考題:如何證明上面的三種情況,會調用paint()方法
Graphics類
Graphics類你可以理解就是畫筆,為我們提供了各種繪製圖形的方法:[參考jdk幫助文檔]
-
畫直線drawLine(int x1,int y1,int x2,int y2)
-
畫矩形邊框drawRect(int x, int y, int width, int height)
-
畫橢圓邊框drawOval(int x, int y, int width, int height)
-
填充矩形 fillRect(int x, int y, int width, int height)
-
填充橢圓fillOval(int x, int y, int width, int height)
-
畫圖片drawlmage(lmage img, int x, int y, ..)
-
畫字元串drawString(String str, int x, int y)
-
設置畫筆的字體setFont(Font font)
-
設置畫筆的顏色setColor(Color c)
import javax.swing.*;
import java.awt.*;
public class DrawCircle extends JFrame {//JFrame對應視窗,可以理解成是一個畫框
//定義一個面板
private MyPanel mp = null;
public static void main(String[] args) {
new Te();
System.out.println("退出程式...");
}
public DrawCircle() {//構造器
//初始化面板
mp = new MyPanel();
//把面板放入到視窗(畫框)
this.add(mp);
//設置視窗的大小
this.setSize(400,300);
///當點擊視窗的小x,程式完全退出.
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);//可以顯示
}
}
//1.先定義一個MyPanel,繼承JPanel類,畫圖形,就在面板上畫
class MyPanel extends JPanel {
//說明:
//1.MyPanel對象就是一個畫板
//2.Graphics g把g理解成一支畫筆
//3.Graphics提供了很多繪圖的方法
//Graphics g
@Override
public void paint(Graphics g) {//繪圖方法
super.paint(g);//調用父類的方法完成初始化
System.out.println("調用了paint方法");
//演示繪製不同的圖形..
//1. 畫直線drawLine(int x1,int y1,int x2,int y2)
// g.drawLine(10,10,100,100);
//2. 畫矩形邊框drawRect(int x, int y, int width, int height)
// g.drawRect(10,10,100,100);
//3. 畫橢圓邊框drawOval(int x, int y, int width, int height)
// g.drawOval(10, 10, 100, 100);
//4. 填充矩形 fillRect(int x, int y, int width, int height)
// g.setColor(Color.BLUE);
// g.fillRect(10,10,100,100);
//5. 填充橢圓fillOval(int x, int y, int width, int height)
// g.setColor(Color.red);
// g.fillOval(10,10,100,100);
//6. 畫圖片drawlmage(lmage img, int x, int y, ..)
// Image image = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/張文傑.jpg"));
// g.drawImage(image,10,10,150,200,this);
//7. 畫字元串drawString(String str, int x, int y)
// g.setColor(Color.red);
// g.setFont(new Font("行書",Font.BOLD,50));
// g.drawString("你好",100,50);//x,y對應字元串左下角位置
//8. 設置畫筆的字體setFont(Font font)
//9. 設置畫筆的顏色setColor(Color c)
}
}
繪出坦克
坦克大戰游戲中,我們會用到坦克,現在我們就利用java繪圖技術來畫出一個小坦克,完成我們的坦克大戰游戲1.0版本!
Tank//坦克位置
public class Tank {
//坦克左上角坐標
private int x;
private int y;
public Tank(int x, int y) {
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;
}
}
Hero//玩家坦克
public class Hero extends Tank{
public Hero(int x, int y) {
super(x, y);
}
}
MyPanel//面板
import javax.swing.*;
import java.awt.*;
public class MyPanel extends JPanel {
Hero hero=null;//定義我的坦克
public MyPanel(){
hero=new Hero(100,100);//初始化自己的坦克位置
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.fillRect(0,0,1000,750);//黑色背景
//畫出坦克
drawTank(hero.getX(),hero.getY(),g,0,1);
}
/**
*
* @param x 坦克左上角x坐標
* @param y 坦克左上角y坐標
* @param g 畫筆
* @param direct 坦克方向(上下左右)
* @param type 坦克類型
*/
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);
break;
}
//根據坦克方向,繪製坦克
switch (direct){
case 0://向上
g.fill3DRect(x,y,10,60,false);//畫出坦克左邊輪子
g.fill3DRect(x+30,y,10,60,false);//畫出坦克右邊輪子
g.fill3DRect(x+10,y+10,20,40,false);//畫出坦克蓋子
g.fillOval(x+10,y+20,20,20);//畫出圓形蓋子
g.drawLine(x+20,y+30,x+20,y);//畫出炮筒
break;
case 1:
case 2:
case 3:
}
}
}
HspTankGame01//窗體
import javax.swing.*;
public class HspTankGame01 extends JFrame {
MyPanel mp=null;
public static void main(String[] args) {
new HspTankGame01();
}
public HspTankGame01() {
mp=new MyPanel();
this.add(mp);
this.setSize(1000,750);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
java事件處理機制
事件處理機制-看個問題
請大家看一個小程式。(BallMove.java)怎樣讓小球受到鍵盤的控制,上下左右移動.
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class BallMove extends JFrame{//視窗
MyPanel mp=null;
public static void main(String[] args) {
new BallMove();
}
public BallMove(){
mp=new MyPanel();
this.add(mp);
this.setSize(400,300);
//視窗JFrame對象可以監聽鍵盤事,即可以監聽到面板發生的鍵盤事件
this.addKeyListener(mp);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
//面板,可以畫出小球
//KeyListener是監聽器,可以監聽鍵盤事件
class MyPanel extends JPanel implements KeyListener {
//為了讓小球可以移動,把他的左上角的坐標(x,y)設置變數
int x = 10;
int y =10;
@Override
public void paint(Graphics g) {
super.paint(g);
g.fillOval(x,y,20,20);
}
//有字元輸出,該方法就會觸發
@Override
public void keyTyped(KeyEvent e) {
}
//當某個鍵按下,該方法觸發
@Override
public void keyPressed(KeyEvent e) {
//System.out.println((char)e.getKeyCode()+"被按下");
//根據用戶按下的不同鍵,來處理小球的移動(上下左右)
//在java中,會給每一個鍵,分配一個值(int)
if(e.getKeyCode()==KeyEvent.VK_DOWN){//KeyEvent.VK_DOWN就是向下的箭頭對應的code
y++;
}else if (e.getKeyCode()==KeyEvent.VK_UP){
y--;
}else if(e.getKeyCode()==KeyEvent.VK_RIGHT){
x++;
}else if(e.getKeyCode()==KeyEvent.VK_LEFT){
x--;
}
//讓面板重繪
this.repaint();
}
//當某個鍵鬆開,被觸發
@Override
public void keyReleased(KeyEvent e) {
}
}
基本說明
java事件處理是採取"委派事件模型"。當事件發生時,產生事件的對象,會把此"信息”傳遞給"事件的監聽者"(例:KeyListener)處理,這裡所說的“信息"實際上就是java.awt.event事件類庫里某個類所創建的對象,把它稱為"事件的對象"(例:KeyEvent)。
請大家看一個示意圖:
事件處理機制深入理解
-
前面我們提到幾個重要的概念事件源,事件,事件監聽器我們下麵來全面的介紹它們。
-
事件源:事件源是一個產生事件的對象,比如按鈕,窗回等。
-
事件:事件就是承載事件源狀態改變時的對象,比如當鍵盤事件、滑鼠事件、視窗事件等等,會生成一個事件對象,該對象保存著當前事件很多信息,比如KeyEvent對象有含義被按下鍵的Code值。java.awt.event包和javax.swing.event包中定義了各種事件類型
-
事件類型:查閱jdk文檔
-
事件監聽器介面:
(1)當事件源產生一個事件,可以傳送給事件監聽者處理
(2)事件監聽者實際上就是一個類,該類實現了某個事件監聽器介面比如前面我們案例中的MyPanle就是一個類,它實現了KeyListener介面,它就可以作為一個事件監聽者,對接受到的事件進行處理
(3)事件監聽器介面有多種,不同的事件監聽器介面可以監聽不同的事件,一個類可以實現多個監聽介面
(4)這些介面在java.awt.event包和javax.swing.event包中定義。列出常用的事件監聽器介面,查看jdk文檔聚集了.
坦克大戰游戲(1.0版)
繪製己方坦克(能夠使用WASD移動)
繪製敵方坦克(顏色有差別,至少3個)//要想敵人的坦克移動,需要下一節的線程知識
Tank//坦克
package tankgame02;
public class Tank {
//坦克左上角坐標
private int x;
private int y;
private int direct;//坦克方向 0上 1右 2下 3左
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
private int speed=1;//坦克速度
//上右下左移動方法
public void moveUp(){
y-=speed;
}
public void moveDown(){
y+=speed;
}
public void moveLeft(){
x-=speed;
}
public void moveRight(){
x+=speed;
}
public int getDirect() {
return direct;
}
public void setDirect(int direct) {
this.direct = direct;
}
public Tank(int x, int y) {
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;
}
}
Hero//己方坦克
package tankgame02;
public class Hero extends Tank {
public Hero(int x, int y) {
super(x, y);
}
}
EnemyTank//敵方坦克
package tankgame02;
public class EnemyTank extends Tank{
public EnemyTank(int x, int y) {
super(x, y);
}
}
MyPanel//面板
package tankgame02;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Hashtable;
import java.util.Vector;
////為了監聽鍵盤事件,實現KeyListener
public class MyPanel extends JPanel implements KeyListener {
Hero hero = null;//定義我的坦克
Vector<EnemyTank> enemyTanks = new Vector<>();//定義敵人坦克
int enemyTankSize = 3;
public MyPanel() {
hero = new Hero(100, 100);//初始化自己的坦克位置
for (int i = 0; i < enemyTankSize; i++) {//初始化敵人的坦克位置
enemyTanks.add(new EnemyTank(100 * (i + 1), 0));
}
// hero.setSpeed(5);
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.fillRect(0, 0, 1000, 750);//黑色背景
//畫出坦克
drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 0);
//畫出敵人坦克
for (int i = 0; i < enemyTankSize; i++) {
//取出坦克
EnemyTank enemyTank = enemyTanks.get(i);
enemyTank.setDirect(2);
drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 1);
}
}
/**
* @param x 坦克左上角x坐標
* @param y 坦克左上角y坐標
* @param g 畫筆
* @param direct 坦克方向(上下左右)
* @param type 坦克類型
*/
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);
break;
}
//根據坦克方向,繪製坦克
switch (direct) {
case 0://向上
g.fill3DRect(x, y, 10, 60, false);//畫出坦克左邊輪子
g.fill3DRect(x + 30, y, 10, 60, false);//畫出坦克右邊輪子
g.fill3DRect(x + 10, y + 10, 20, 40, false);//畫出坦克蓋子
g.fillOval(x + 10, y + 20, 20, 20);//畫出圓形蓋子
g.drawLine(x + 20, y + 30, x + 20, y);//畫出炮筒
break;
case 1://右
g.fill3DRect(x - 10, y + 10, 60, 10, false);//畫出坦克左邊輪子
g.fill3DRect(x - 10, y + 40, 60, 10, false);//畫出坦克右邊輪子
g.fill3DRect(x, y + 20, 40, 20, false);//畫出坦克蓋子
g.fillOval(x + 10, y + 20, 20, 20);//畫出圓形蓋子
g.drawLine(x + 20, y + 30, x + 50, y + 30);//畫出炮筒
break;
case 2://下
g.fill3DRect(x, y, 10, 60, false);//畫出坦克左邊輪子
g.fill3DRect(x + 30, y, 10, 60, false);//畫出坦克右邊輪子
g.fill3DRect(x + 10, y + 10, 20, 40, false);//畫出坦克蓋子
g.fillOval(x + 10, y + 20, 20, 20);//畫出圓形蓋子
g.drawLine(x + 20, y + 30, x + 20, y + 60);//畫出炮筒
break;
case 3://左
g.fill3DRect(x - 10, y + 10, 60, 10, false);//畫出坦克左邊輪子
g.fill3DRect(x - 10, y + 40, 60, 10, false);//畫出坦克右邊輪子
g.fill3DRect(x, y + 20, 40, 20, false);//畫出坦克蓋子
g.fillOval(x + 10, y + 20, 20, 20);//畫出圓形蓋子
g.drawLine(x + 20, y + 30, x + -10, y + 30);//畫出炮筒
break;
}
}
@Override
public void keyTyped(KeyEvent e) {
}
//處理WDSA鍵按下情況
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_W) {
//改變坦克方向
hero.setDirect(0);
//修改坦克坐標
hero.moveUp();
} else if (e.getKeyCode() == KeyEvent.VK_D) {
hero.setDirect(1);
hero.moveRight();
} else if (e.getKeyCode() == KeyEvent.VK_S) {
hero.setDirect(2);
hero.moveDown();
} else if (e.getKeyCode() == KeyEvent.VK_A) {
hero.setDirect(3);
hero.moveLeft();
}
this.repaint();
}
@Override
public void keyReleased(KeyEvent e) {
}
}
HspTankGame02//窗體
package tankgame02;
import javax.swing.*;
public class HspTankGame02 extends JFrame {
MyPanel mp=null;
public static void main(String[] args) {
new HspTankGame02();
}
public HspTankGame02() {
mp=new MyPanel();
this.add(mp);
this.setSize(1000,750);
this.addKeyListener(mp);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}