Java之详解坦克大战游戏(二)
2016-07-21 11:55
639 查看
上一篇,我们已经画出了一辆坦克,但是我们的坦克不会动,本篇(看起来长实际内容不多的),我们就来实现如何让坦克移动,(最好再建一个包存放复制原来的java文件),因为我们是一步步更新的,一乱可能连原来的文件都改回不了…
首先我们要做的是事件监听和事件处理,给MyPanel类添加一个接口KeyListener,并实现方法
!!!要实现监听,还要注册监听事件
其中 public void keyPressed(KeyEvent e){…}是我们主要操作的方法,下面四个if语句是添加上去的,用于判断是按了哪个键,按这个节奏,if语句里面是不是该填写坐标移动来实现坦克的移动呢(y–,x++,…),但是考虑到之后的修改问题,我们还是把移动这一方法封装起来(好处后面会提到)。在Tank类定义一个变量 int speed=1;作为坦克的速度,再回到Hero类添加移动的方法,由于 Hero继承Tank类,所以Hero类也能访问speed。
(如果是y++,x++那样的形式控制速度,那要修改速度就会显得很麻烦,连续改几个,而定义speed的话修改速度只需修改speed的数值。)接着再到刚才if语句那里添加移动方法
这个时候,运行效果是这样的(页面被我放大来拍摄做gif的)
我们看到它可以移动,但左右移动跟螃蟹走一样,所以下一步是做出它向下还是向左向右,绘出坦克整体向哪个方向的图。
在Tank类中定义坦克方向,并添加setter和getter方法
再往回添加添加代码和修改
再修改代码(上篇我们初始化是0,方向向上),由于我们要改变方向,灵活一点就改为this.hero.direct
接下来看方向改变后坦克如何画
有两种方式,一种还是以最左边矩形左上角为参照点画,但是可能效果不是令人特别满意,转动的变化略大,而如果以圆形中间的点为参照点,转动起来就比较自然了,不过坐标要计算得更精确哦,可以试试..这里我们
还是以左上角的点为参照点画向右的坦克
事实上画出向右的方向,向左的就容易画了,因为算对称,而上篇画了向上的坦克,画向下的只要改动直线就行了,改后效果如图
最后为了更好的阅读代码,我们把Tank类和Hero类剪切到一个Members.java文件,分为两个文件,最后附上完整代码:
Members.java
TankGame2.java
本篇看来篇幅长了点,实则内容不多,旨在详细描述步骤,下节继续分解
首先我们要做的是事件监听和事件处理,给MyPanel类添加一个接口KeyListener,并实现方法
class MyPanel extends Panel implements KeyListener { //省略部分代码...... /*实现KeyListener接口的方法*/ //键入某个键时调用此方法。 public void keyTyped(KeyEvent e) { } //释放某个键时调用此方法 public void keyReleased(KeyEvent e) { } //按下某个键时调用此方法: A代表向左,W代表向上,D代表向右,S代表向下 public void keyPressed(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_W)//向上 { } else if(e.getKeyCode() == KeyEvent.VK_D)//向下 { } else if(e.getKeyCode() == KeyEvent.VK_S)//向下 { } else if(e.getKeyCode() == KeyEvent.VK_A)//向左 { } //没有这行代码即使实现了移动操作页面也不会动的 this.repaint();//调用repaint()函数,来重绘页面 } }
!!!要实现监听,还要注册监听事件
public class TankGame2 extends JFrame{ public TankGame2(){ //... this.addKeyListener(mp);//注册监听事件 } }
其中 public void keyPressed(KeyEvent e){…}是我们主要操作的方法,下面四个if语句是添加上去的,用于判断是按了哪个键,按这个节奏,if语句里面是不是该填写坐标移动来实现坦克的移动呢(y–,x++,…),但是考虑到之后的修改问题,我们还是把移动这一方法封装起来(好处后面会提到)。在Tank类定义一个变量 int speed=1;作为坦克的速度,再回到Hero类添加移动的方法,由于 Hero继承Tank类,所以Hero类也能访问speed。
class Hero extends Tank { public Hero(int x,int y) { super(x,y); } //坦克向上移动 public void moveUp() { y-=speed; } //坦克向右移动 public void moveRight() { x+=speed; } //坦克向下移动 public void moveDown() { y+=speed; } //坦克向左移动 public void moveLeft() { x-=speed; } }
(如果是y++,x++那样的形式控制速度,那要修改速度就会显得很麻烦,连续改几个,而定义speed的话修改速度只需修改speed的数值。)接着再到刚才if语句那里添加移动方法
class MyPanel extends Panel implements KeyListener {//省略部分代码...... public void keyPressed(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_W)//向上 { this.hero.moveUp(); } else if(e.getKeyCode() == KeyEvent.VK_D)//向下 { this.hero.moveRight(); } else if(e.getKeyCode() == KeyEvent.VK_S)//向下 { this.hero.moveDown(); } else if(e.getKeyCode() == KeyEvent.VK_A)//向左 { this.hero.moveLeft(); }
这个时候,运行效果是这样的(页面被我放大来拍摄做gif的)
我们看到它可以移动,但左右移动跟螃蟹走一样,所以下一步是做出它向下还是向左向右,绘出坦克整体向哪个方向的图。
在Tank类中定义坦克方向,并添加setter和getter方法
class Tank {//省略部分代码...... //坦克方向 //0表示上,1表示右,2表示下,3表示左 int direct=0; public int getDerect() { return direct; } public void setDerect(int derect) { this.direct = derect; } //... }
再往回添加添加代码和修改
public void keyPressed(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_W)//向上 { this.hero.setDirect(0); this.hero.moveUp(); } else if(e.getKeyCode() == KeyEvent.VK_D)//向右 { this.hero.setDirect(1); this.hero.moveRight(); } else if(e.getKeyCode() == KeyEvent.VK_S)//向下 { this.hero.setDirect(2); this.hero.moveDown(); } else if(e.getKeyCode() == KeyEvent.VK_A)//向左 { this.hero.setDirect(3); this.hero.moveLeft(); } this.repaint();//调用repaint()函数,来重绘页面 }
再修改代码(上篇我们初始化是0,方向向上),由于我们要改变方向,灵活一点就改为this.hero.direct
class MyPanel extends Panel implements KeyListener{ public void paint(Graphics g){ //... this.drawTank(hero.getX(), hero.getY(), g, this.hero.direct, 1); } }
接下来看方向改变后坦克如何画
有两种方式,一种还是以最左边矩形左上角为参照点画,但是可能效果不是令人特别满意,转动的变化略大,而如果以圆形中间的点为参照点,转动起来就比较自然了,不过坐标要计算得更精确哦,可以试试..这里我们
还是以左上角的点为参照点画向右的坦克
//画出坦克的函数 public void drawTank(int x,int y,Graphics g,int direct,int type) {//省略.... case 0://.... case 1://炮筒向右 //画出上面矩形 g.fill3DRect(x, y, 30, 5,false); //2.画出右边矩形 g.fill3DRect(x, y+15, 30, 5,false); //3.画出中间矩形 g.fill3DRect(x+5, y+5, 20, 10,false); //4.画出圆形 g.fillOval(x+10, y+5, 10, 10); //5.画直线 g.drawLine(x+15, y+10, x+30, y+10); break; case 2://炮筒向下 //画出上面矩形 g.fill3DRect(x, y, 5, 30,false); //2.画出右边矩形 g.fill3DRect(x+15, y, 5, 30,false); //3.画出中间矩形 g.fill3DRect(x+5, y+5, 10, 20,false); //4.画出圆形 g.fillOval(x+5, y+10, 10, 10); //5.画直线 g.drawLine(x+10, y+15, x+10, y+30); break; case 3://炮筒向左 //画出上面矩形 g.fill3DRect(x, y, 30, 5,false); //2.画出右边矩形 g.fill3DRect(x, y+15, 30, 5,false); //3.画出中间矩形 g.fill3DRect(x+5, y+5, 20, 10,false); //4.画出圆形 g.fillOval(x+10, y+5, 10, 10); //5.画直线 g.drawLine(x+15, y+10, x, y+10); break; } }
事实上画出向右的方向,向左的就容易画了,因为算对称,而上篇画了向上的坦克,画向下的只要改动直线就行了,改后效果如图
最后为了更好的阅读代码,我们把Tank类和Hero类剪切到一个Members.java文件,分为两个文件,最后附上完整代码:
Members.java
package com.TankGame1;
//坦克类
class Tank
{
//表示坦克的横坐标
int x=0;
//表示坦克的纵坐标
int y=0;
//坦克方向
//0表示上,1表示右,2表示下,3表示左
int direct=0;
public int getDirect() {
return direct;
}
public void setDirect(int derect) {
this.direct = derect;
}
//坦克速度
int speed=1;
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 Tank(int x,int y)
{
this.x=x;
this.y=y;
}
}
//我的坦克
class Hero extends Tank { public Hero(int x,int y) { super(x,y); } //坦克向上移动 public void moveUp() { y-=speed; } //坦克向右移动 public void moveRight() { x+=speed; } //坦克向下移动 public void moveDown() { y+=speed; } //坦克向左移动 public void moveLeft() { x-=speed; } }
TankGame2.java
package com.TankGame1;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
/*
* */
public class TankGame2 extends JFrame
{
MyPanel mp =null;
public static void main(String[] args)
{
TankGame2 tankgame1 = new TankGame2();
}
public TankGame2()
{
mp=new MyPanel();
this.addKeyListener(mp);
this.setVisible(true);
this.setSize(400, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(mp);
}
}
//我的面板
class MyPanel extends Panel implements KeyListener
{
//定义一个我的坦克
Hero hero =null;
public MyPanel()
{
hero =new Hero(100,100); //坦克的初始位置(10,10)
}
//重新paint
public void paint(Graphics g)
{
super.paint(g);
g.fillRect(0, 0, 1200, 900); //填充使背景变为黑色
this.drawTank(hero.getX(), hero.getY(), g, this.hero.direct, 1);
}
//画出坦克的函数
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:
//画出我的坦克(到时再封装成一个函数)
//1.画出左边的矩形
g.fill3DRect(x, y, 5, 30,false);
//2.画出右边矩形
g.fill3DRect(x+15, y, 5, 30,false);
//3.画出中间矩形
g.fill3DRect(x+5, y+5, 10, 20,false);
//4.画出圆形
g.fillOval(x+5, y+10, 10, 10);
//5.画直线
g.drawLine(x+10, y+15, x+10, y);
break;
case 1://炮筒向右
//画出上面矩形
g.fill3DRect(x, y, 30, 5,false);
//2.画出右边矩形
g.fill3DRect(x, y+15, 30, 5,false);
//3.画出中间矩形
g.fill3DRect(x+5, y+5, 20, 10,false);
//4.画出圆形
g.fillOval(x+10, y+5, 10, 10);
//5.画直线
g.drawLine(x+15, y+10, x+30, y+10);
break;
case 2://炮筒向下
//画出上面矩形
g.fill3DRect(x, y, 5, 30,false);
//2.画出右边矩形
g.fill3DRect(x+15, y, 5, 30,false);
//3.画出中间矩形
g.fill3DRect(x+5, y+5, 10, 20,false);
//4.画出圆形
g.fillOval(x+5, y+10, 10, 10);
//5.画直线
g.drawLine(x+10, y+15, x+10, y+30);
break;
case 3://炮筒向左
//画出上面矩形
g.fill3DRect(x, y, 30, 5,false);
//2.画出右边矩形
g.fill3DRect(x, y+15, 30, 5,false);
//3.画出中间矩形
g.fill3DRect(x+5, y+5, 20, 10,false);
//4.画出圆形
g.fillOval(x+10, y+5, 10, 10);
//5.画直线
g.drawLine(x+15, y+10, x, y+10);
break;
}
}
/*实现KeyListener接口的方法*/
//键入某个键时调用此方法。
public void keyTyped(KeyEvent e) {
}
//释放某个键时调用此方法
public void keyReleased(KeyEvent e) {
}
//按下某个键时调用此方法: a代表向左,w代表向上,d代表向右,s代表向下
public void keyPressed(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_W)//向上 { this.hero.setDirect(0); this.hero.moveUp(); } else if(e.getKeyCode() == KeyEvent.VK_D)//向右 { this.hero.setDirect(1); this.hero.moveRight(); } else if(e.getKeyCode() == KeyEvent.VK_S)//向下 { this.hero.setDirect(2); this.hero.moveDown(); } else if(e.getKeyCode() == KeyEvent.VK_A)//向左 { this.hero.setDirect(3); this.hero.moveLeft(); } this.repaint();//调用repaint()函数,来重绘页面 }
}
本篇看来篇幅长了点,实则内容不多,旨在详细描述步骤,下节继续分解
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树