坦克大战
Java绘图坐标体系
坐标原点位于左上角,以像素为单位。在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。
计算机在屏幕上显示的内容都是由屏幕上的每一个像素组成的,例如,计算机显示器的分辨率是800*600,表示计算机屏幕上的每一行由800个点组成,共有600行,整个计算机屏幕共有480000个像素,像素是一个密度单位,而厘米是长度单位,两者无法比较。
package oop.draw;
import javax.swing.*;
import java.awt.*;
public class Draw01 extends JFrame{//JFrame对应一个窗口,可以理解一个画框
private MyPanel myPanel = null;
public static void main(String[] args) {
new Draw01();
}
public Draw01(){
myPanel = new MyPanel();//初始化面板
this.add(myPanel);//将面板放入窗口(画框)
this.setSize(400,300);//窗口大小
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//当点击窗口的小叉程序真正退出
this.setVisible(true);//可以显示
}
}
/*
* MyPanel对象---画板
* Graphics g---画笔
* Graphics 提供了很多绘图的方法*/
class MyPanel extends JPanel{
@Override
public void paint(Graphics g) {//绘图方法
super.paint(g);//调用父类的方法完成初始化
g.drawOval(10,10,300,300);
}
}
Java绘图技术
绘图原理
- Component类提供了两个和绘图相关最重要的方法:
-
- paint(Graphics g)绘制组件的外观
- repaint()刷新组件的外观
- 当组件第一次在屏幕显示的时候,程序会自动的调用paint()方法来绘制组件
- 在以下情况paint()将会被调用
-
- 窗口最小化,再最大化
- 窗口的大小发生变化
- repaint方法被调用
Graphics类
画笔,提供了各种绘制图形的方法
public class DrawCircle extends JFrame { //JFrame对应窗口,可以理解成是一个画框
//定义一个面板
private MyPanel mp = null;
public static void main(String[] args) {
new DrawCircle();
System.out.println("退出程序~");
}
public DrawCircle() {//构造器
//初始化面板
mp = new MyPanel();
//把面板放入到窗口(画框)
this.add(mp);
//设置窗口的大小
this.setSize(400, 300);
//当点击窗口的小×,程序完全退出.
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);
//演示绘制不同的图形..
//画直线 drawLine(int x1,int y1,int x2,int y2)
//g.drawLine(10, 10, 100, 100);
//画矩形边框 drawRect(int x, int y, int width, int height)
//g.drawRect(10, 10, 100, 100);
//画椭圆边框 drawOval(int x, int y, int width, int height)
//填充矩形 fillRect(int x, int y, int width, int height)
//设置画笔的颜色
// g.setColor(Color.blue);
// g.fillRect(10, 10, 100, 100);
//填充椭圆 fillOval(int x, int y, int width, int height)
// g.setColor(Color.red);
// g.fillOval(10, 10, 100, 100);
//画图片 drawImage(Image img, int x, int y, ..)
//1. 获取图片资源, /bg.png 表示在该项目的根目录去获取 bg.png 图片资源
// Image image = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bg.png"));
// g.drawImage(image, 10, 10, 175, 221, this);
//画字符串 drawString(String str, int x, int y)//写字
//给画笔设置颜色和字体
g.setColor(Color.red);
g.setFont(new Font("隶书", Font.BOLD, 50));
//这里设置的 100, 100, 是 "北京你好"左下角
g.drawString("北京你好", 100, 100);
//设置画笔的字体 setFont(Font font)
//设置画笔的颜色 setColor(Color c)
}
}
Java事件处理机制
Java事件处理是采用“委派事件模型”。当事件发生时,产生事件的对象,会把此“信息”传递给“事件的监听者”处理,这里所说的“信息”实际上就是java.awt.event事件类库里某个类所创建的对象,把它称为“事件的对象”。
深入理解
- 事件源:事件源是一个产生事件的对象,比如按钮,窗口等
- 事件:事件就是承载事件源状态改变时的对象,比如当键盘事件、鼠标事件、窗口事件等等,会生成一个事件对象,该对象保存着当前事件很多信息,比如KeyEvent对象有含义被按下键的Code值。java.awt.event包和javax.swing.event包中定义了各种事件类型。
- 事件类型
-
- ActionEvent:按下按钮,双击一个列表项或选中某个菜单
- AdjustmentEvent:操作一个滚动条
- ComponentEvent:当一个组件隐藏,移动,改变大小
- ContainerEvent:当一个组件从容器中加入或者删除
- FocusEvent:当一个组件获得或者失去焦点
- ItemEvent:当一个复选框或是列表项被选中,当一个选择框或选择菜单被选中
- KeyEvent:当从键盘的按键被按下,松开时
- MouseEvent:当鼠标被拖动,移动,点击,按下
- TextEvent:当文本区和文本域的文本发生改变时发生
- WindowEvent:当一个窗口激活,关闭,失效,恢复,最小化
- 事件监听器接口
-
- 当事件源产生一个事件,可以传送给事件监听者处理
- 事件监听者实际上就是一个类,该类实现了某个事件监听器接口,MyPanel实现了KeyListener接口,它就可以作为一个事件监听者,对接受到的事件进行处理
- 事件监听器接口有多种,不同的事件监听器接口可以监听不同的事件,一个类可以实现多个监听接口
- 这些接口在java.awt.event包和javax.swing.event包中定义
/* 演示小球通过键盘控制上下左右的移动-> 讲解Java的事件控制
*/
public class BallMove extends JFrame { //窗口
MyPanel mp = null;
public static void main(String[] args) {
BallMove ballMove = 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_LEFT) {
x--;
} else if(e.getKeyCode() == KeyEvent.VK_RIGHT) {
x++;
}
//让面板重绘
this.repaint();
}
//当某个键释放(松开),该方法会触发
@Override
public void keyReleased(KeyEvent e) {
}
}
1.0版
package oop.draw;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Vector;
public class DrawTank extends JFrame{
MyPanel_ mp = null;
public static void main(String[] args) {
DrawTank drawTank = new DrawTank();
}
public DrawTank(){
mp = new MyPanel_();
this.add(mp);
this.setSize(1000,750);
this.addKeyListener(mp);//////////重要监听
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}
}
class MyPanel_ extends JPanel implements KeyListener {
Hero hero = null;
Vector<Enemy> enemies = new Vector<>();
int enemyNumber = 3;
public MyPanel_(){
hero = new Hero(100,100);
for (int i = 0; i < enemyNumber; i++) {
Enemy enemy = new Enemy(100 * (i + 1),0);
enemy.setDirection(1);
enemies.add(enemy);
}
}
@Override
public void paint(Graphics g) {
super.paint(g);
g.fillRect(0,0,1000,750);
drawTank(hero.getX(), hero.getY(), g, hero.getDirection(), 1);
for (int i = 0; i < enemies.size(); i++) {
drawTank(enemies.get(i).getX(), enemies.get(i).getY(), g, enemies.get(i).getDirection(), 0);
}
}
public void drawTank(int x,int y,Graphics g,int direction,int type){
switch (type){
case 0:
g.setColor(Color.PINK);
break;
case 1:
g.setColor(Color.YELLOW);
break;
}
switch (direction){
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, x + 20, y + 30);
break;
case 1://下
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 2://左
g.fill3DRect(x, y, 60, 10, false);
g.fill3DRect(x, y + 30, 60, 10, false);
g.fill3DRect(x + 10, y + 10, 40, 20, false);
g.fillOval(x + 20, y + 10, 20, 20);
g.drawLine(x + 30, y + 20, x, y + 20);
break;
case 3://右
g.fill3DRect(x, y, 60, 10, false);
g.fill3DRect(x, y + 30, 60, 10, false);
g.fill3DRect(x + 10, y + 10, 40, 20, false);
g.fillOval(x + 20, y + 10, 20, 20);
g.drawLine(x + 30, y + 20, x + 60, y + 20);
break;
default:
System.out.println("不处理");
}
}
//某个键按下触发
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_DOWN){
hero.setDirection(1);
hero.moveDown();
}else if(e.getKeyCode() == KeyEvent.VK_UP){
hero.setDirection(0);
hero.moveUp();
}else if(e.getKeyCode() == KeyEvent.VK_LEFT){
hero.setDirection(2);
hero.moveLeft();
}else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
hero.setDirection(3);
hero.moveRight();
}
this.repaint();////////////重要重绘
}
//某个键释放触发
@Override
public void keyReleased(KeyEvent e) {
}
//有字符输出触发
@Override
public void keyTyped(KeyEvent e) {
}
}
class Enemy extends Tank{
public Enemy(int x, int y) {
super(x, y);
}
}
class Hero extends Tank{
public Hero(int x, int y) {
super(x, y);
}
}
class Tank{
private int x;
private int y;
private int direction = 0;
private int speed = 3;
public Tank(int x, int y) {
this.x = x;
this.y = y;
}
public void moveUp(){
y-=speed;
}
public void moveDown(){
y+=speed;
}
public void moveLeft(){
x-=speed;
}
public void moveRight(){
x+=speed;
}
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 int getDirection() {
return direction;
}
public void setDirection(int direction) {
this.direction = direction;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
}