一、控制我方坦克移动
1.在MyTank中定义一个内部类keyContral实现键盘控制MyTank
public class KeyContral extends KeyAdapter {//按下方向改变
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_UP:
dir = Direction.U;
break;
case KeyEvent.VK_DOWN:
dir = Direction.D;
break;
case KeyEvent.VK_LEFT:
dir = Direction.L;
break;
case KeyEvent.VK_RIGHT:
dir = Direction.R;
break;
default:
dir = Direction.Stop;
}
}
@Override
public void keyReleased(KeyEvent e) {//释放恢复
super.keyReleased(e);
int key = e.getKeyCode();
if(key==KeyEvent.VK_UP||key==KeyEvent.VK_DOWN||key==KeyEvent.VK_LEFT||key==KeyEvent.VK_RIGHT){
dir = Direction.Stop;
}
}
}
2.重写move函数,并控制不越界
@Override
public void move() {//实现移动,并控制不越界
if (dir == Direction.U) {
if (local_y - speed >= 0)
setLocal_y(local_y -= speed);
} else if (dir == Direction.D) {
if (local_y + speed <= TankFrame.Frame_Height - (height * 2 + height / 3))
setLocal_y(local_y += speed);
} else if (dir == Direction.L) {
if (local_x - speed >= 0)
setLocal_x(local_x -= speed);
} else if (dir == Direction.R) {
if (local_x + speed <= TankFrame.Frame_Width - (width + width / 3))
setLocal_x(local_x += speed);
} else {
}
}
3.TankPanel类实现runna接口,实现线程操作
重写run函数,每隔100ms重绘
@Override
public void run() {
while(true){
repaint();//每隔100ms重绘
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4.在绘制坦克后添加move()函数,实现绘制后移动,在TankFrame中添加键盘控制
addKeyListener(TP.mtank.kc);
启动线程
new Thread(TP).start();//启动线程
效果如下:
此时只是生硬的移动,没有根据移动方向改变坦克指向
二、添加更多的不同方向的图片
重构draw()函数
@Override
public void draw() {
switch (pdir) {
case U:// 注意不能用Direction.U
setTankImage(Toolkit.getDefaultToolkit().getImage("p2tankU.gif"));
break;
case D:
setTankImage(Toolkit.getDefaultToolkit().getImage("p2tankD.gif"));
break;
case L:
setTankImage(Toolkit.getDefaultToolkit().getImage("p2tankL.gif"));
break;
case R:
setTankImage(Toolkit.getDefaultToolkit().getImage("p2tankR.gif"));
break;
default:
setTankImage(Toolkit.getDefaultToolkit().getImage("p2tankU.gif"));
}
}
重构KeyContral,每次按键要考虑坦克指向
public class KeyContral extends KeyAdapter {//按下方向改变
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_UP:
pdir=dir = Direction.U;
break;
case KeyEvent.VK_DOWN:
pdir=dir = Direction.D;
break;
case KeyEvent.VK_LEFT:
pdir=dir = Direction.L;
break;
case KeyEvent.VK_RIGHT:
pdir=dir = Direction.R;
break;
default:
pdir=dir = Direction.Stop;
}
}
@Override
public void keyReleased(KeyEvent e) {//释放移动方向改变恢复,指向不改变
super.keyReleased(e);
int key = e.getKeyCode();
if(key==KeyEvent.VK_UP||key==KeyEvent.VK_DOWN||key==KeyEvent.VK_LEFT||key==KeyEvent.VK_RIGHT){
dir = Direction.Stop;
}
}
}
效果如下:
完整源码如下:
TankFrame类:
public class TankFrame extends JFrame{
/**
*
*/
private static final long serialVersionUID = 1L;
public static int Frame_Width = 500;
public static int Frame_Height = 500;
TankPanel TP = new TankPanel();
public void launchFrame() {
//窗口大小及位置
setSize(Frame_Width, Frame_Height);
setLocation(1000, 100);
add(TP);
addKeyListener(TP.mtank.kc);//添加键盘控制
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
setResizable(false);
new Thread(TP).start();//启动线程
}
public static void main(String[] args) {
new TankFrame().launchFrame();
}
}
TankPanel类:
public class TankPanel extends JPanel implements Runnable{
/**
*
*/
private static final long serialVersionUID = 1L;
MyTank mtank = new MyTank(100, 100, false);
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.fillRect(0, 0, TankFrame.Frame_Width, TankFrame.Frame_Height);
//绘制我方坦克
mtank.draw();
g.drawImage(mtank.getTankImage(), mtank.getLocal_x(), mtank.getLocal_y(), mtank.getWidth(), mtank.getHeight(),
this);
mtank.move();//我方坦克移动
}
@Override
public void run() {
while(true){
repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Tank类:
public abstract class Tank {
// 位置
int local_x;
int local_y;
// 大小
int width = 20;
int height = 20;
// 速度
int speed=5;
// 运动方向
Direction dir;
// 炮筒方向
Direction pdir;
// 坦克图片
Image tankImage;
//敌我
boolean is_enemy;
//死亡
boolean is_Dead;
public int getLocal_x() {
return local_x;
}
public void setLocal_x(int local_x) {
this.local_x = local_x;
}
public int getLocal_y() {
return local_y;
}
public void setLocal_y(int local_y) {
this.local_y = local_y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public Direction getDir() {
return dir;
}
public void setDir(Direction dir) {
this.dir = dir;
}
public Direction getPdir() {
return pdir;
}
public void setPdir(Direction pdir) {
this.pdir = pdir;
}
public Image getTankImage() {
return tankImage;
}
public void setTankImage(Image tankImage) {
this.tankImage = tankImage;
}
public boolean isIs_enemy() {
return is_enemy;
}
public void setIs_enemy(boolean is_enemy) {
this.is_enemy = is_enemy;
}
public boolean isIs_Dead() {
return is_Dead;
}
public void setIs_Dead(boolean is_Dead) {
this.is_Dead = is_Dead;
}
public Tank(int local_x, int local_y, boolean is_enemy) {
super();
this.local_x = local_x;
this.local_y = local_y;
this.is_enemy = is_enemy;
}
public abstract void draw();//绘制相关函数(获取图片)
public abstract void move();//移动函数
public abstract Rectangle getRec();//获取当前位置,返回对应矩形
public abstract Rectangle getNextRec();//获取移动后的位置,返回对应矩形
}
MyTank类:
public class MyTank extends Tank {
// 坦克移动方向
Direction dir = Direction.Stop;
// 坦克炮筒方向
Direction pdir = Direction.U;
public KeyContral kc = new KeyContral();
public MyTank(int local_x, int local_y, boolean is_enemy) {
super(local_x, local_y, is_enemy);
// TODO Auto-generated constructor stub
}
@Override
public void draw() {
switch (pdir) {
case U:// 注意不能用Direction.U
setTankImage(Toolkit.getDefaultToolkit().getImage("p2tankU.gif"));
break;
case D:
setTankImage(Toolkit.getDefaultToolkit().getImage("p2tankD.gif"));
break;
case L:
setTankImage(Toolkit.getDefaultToolkit().getImage("p2tankL.gif"));
break;
case R:
setTankImage(Toolkit.getDefaultToolkit().getImage("p2tankR.gif"));
break;
default:
setTankImage(Toolkit.getDefaultToolkit().getImage("p2tankU.gif"));
}
}
@Override
public void move() {//实现移动,并控制不越界
if (dir == Direction.U) {
if (local_y - speed >= 0)
setLocal_y(local_y -= speed);
} else if (dir == Direction.D) {
if (local_y + speed <= TankFrame.Frame_Height - (height * 2 + height / 3))
setLocal_y(local_y += speed);
} else if (dir == Direction.L) {
if (local_x - speed >= 0)
setLocal_x(local_x -= speed);
} else if (dir == Direction.R) {
if (local_x + speed <= TankFrame.Frame_Width - (width + width / 3))
setLocal_x(local_x += speed);
} else {
}
}
@Override
public Rectangle getRec() {
return null;
}
@Override
public Rectangle getNextRec() {
return null;
}
public class KeyContral extends KeyAdapter {//按下方向改变
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_UP:
pdir=dir = Direction.U;
break;
case KeyEvent.VK_DOWN:
pdir=dir = Direction.D;
break;
case KeyEvent.VK_LEFT:
pdir=dir = Direction.L;
break;
case KeyEvent.VK_RIGHT:
pdir=dir = Direction.R;
break;
default:
pdir=dir = Direction.Stop;
}
}
@Override
public void keyReleased(KeyEvent e) {//释放移动方向改变恢复,指向不改变
super.keyReleased(e);
int key = e.getKeyCode();
if(key==KeyEvent.VK_UP||key==KeyEvent.VK_DOWN||key==KeyEvent.VK_LEFT||key==KeyEvent.VK_RIGHT){
dir = Direction.Stop;
}
}
}
}
enum类:
public enum Direction {
U,D,L,R,Stop
}