咱们须要画出一个圆,那么可使用fillOval方法ide
fillOval(int x,int y ,int width ,int height)
参数的X 和 Y是矩形框的左上角的坐标,width和height是宽和高。this
而咱们重写paint方法进行画出坦克的圆spa
@Override public void paint(Graphics g) { //获取默认的颜色Color Color c = g.getColor(); //将坦克颜色为红色 g.setColor(Color.red); //画一个圆 g.fillOval(50,50,30,30); //将原颜色填充回 g.setColor(c); }
固然也能够在lauchFrame方法里添加背景填充色,显得更外显眼一些线程
//添加设置背景颜色 this.setBackground(Color.GREEN);
咱们使用fillOval方法画出了圆的实现,那么怎么让这个圆改变位置?code
//画一个圆 g.fillOval(50,50,30,30);
咱们发现x和y的作标都是50,他们是固定的!图片
若改变成变量的方式?是否是也是同样能够呢?get
int x = 50;//坦克的x坐标 int y = 50;//坦克的y坐标 @Override public void paint(Graphics g) { //获取默认的颜色Color Color c = g.getColor(); //将坦克颜色为红色 g.setColor(Color.red); //画一个圆 g.fillOval(x,y,30,30); //将原颜色填充回 g.setColor(c); }
若咱们每次原有的基础上进行改动,是否是就动起来了?it
咱们采用repaint重绘方法,每隔多少毫秒刷新最新的圆点信息坐标io
private class PaintThread implements Runnable { @Override public void run() { while (true) { repaint();//重绘方法 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }
//定义窗口方法 public void lauchFrame() { //省略其余关键性代码..... //添加设置背景颜色 this.setBackground(Color.GREEN); //使用线程重绘最新圆点信息坐标 new Thread(new PaintThread()).start(); } @Override public void paint(Graphics g) { //省略其余关键性代码..... //刷新圆点位置 x += 5;//x坐标 y += 5;//y坐标 }
这时咱们在main方法运行起来就发现每一个100毫秒就会移动圆点位置了class
为何使用线程重面,而不是每按下一个键进行一次重画?
咱们的显示器通常都是多少hz、多少hz的刷新率,而刷新速度太快,paint方法还没完成,没跟上致使会出现闪烁的问题
那么怎么解决呢?
1.逐条显示
2.将全部东西画在虚拟图片上,一次性显示出来
Image offScreenImage = null;//虚拟图片 @Override public void update(Graphics g){ if(offScreenImage == null){ //若为null,则建立一张图片 offScreenImage = this.createImage(800,600); } //获取到虚拟图片的画笔 Graphics gOffScreen = offScreenImage.getGraphics(); //使用虚拟图片的画笔画圆 paint(gOffScreen); //将虚拟图片画下来 g.drawImage(offScreenImage,0,0,null); }
可是运行起来会发现,圆动起来后慢慢变成了一条线
这是怎么回事呢?
由于当咱们不重写update方法时,它会本身用背景颜色刷一遍,刷完再画
而为何会一条线呢,由于背景没刷,以前画出来的圆还在那
因此咱们用虚拟图片的画笔画出一个方框出来代替以前的背景
@Override public void update(Graphics g){ if(offScreenImage == null){ //若为null,则建立一张图片 offScreenImage = this.createImage(800,600); } //获取到虚拟图片的画笔 Graphics gOffScreen = offScreenImage.getGraphics(); //默认黑色,因此须要与效果背景一致获取原色 Color c = gOffScreen.getColor(); gOffScreen.setColor(Color.green);//与原背景色一致 //使用画笔画出一个实现的方框代替原画的背景效果 gOffScreen.fillRect(0,0,800,600); gOffScreen.setColor(c);//设置原回来 //使用虚拟图片的画笔画圆 paint(gOffScreen); //将虚拟图片画下来 g.drawImage(offScreenImage,0,0,null); }
这时再运行就便可
因为咱们的虚拟图片、框框、以及一些尺寸大小都是固定的值,当须要修改变化的时候,若只有几个地方,那还比较容易改动
如有几百个地方、几千个地方,这就改动的很繁琐而且很杂乱
public class TankClient extends Frame { public static final int GAME_WINDTH = 800;//宽度常量 public static final int GAME_HEIGHT = 600;//高度常量 @Override public void update(Graphics g){ if(offScreenImage == null){ //若为null,则建立一张图片 offScreenImage = this.createImage(GAME_WINDTH,GAME_HEIGHT); } //省略其余关键性代码...... } //定义窗口方法 public void lauchFrame() { //设置窗口出现的位置 this.setLocation(400, 300); //设置窗口的宽度高度 this.setSize(GAME_WINDTH, GAME_HEIGHT); //省略其余关键性代码...... } }
✧将之后可能须要多处改变的量定义为常量
✧Frame的宽度和高度
✧常量名通常大写
尚学堂:坦克大战(马士兵老师)