在文章最后有源代码,需要的小伙cai伴niao自取——参考文献 韩顺平《java从入门到精通》
public class Tankwar extends JFrame{
MyPanel mp=new MyPanel();
public static void main(String args[])
{
Tankwar T=new Tankwar();
}
public Tankwar()
{
this.add(mp);
//注册键盘监听
this.addKeyListener(mp);
this.setSize(400,300);
this.setVisible(true);
}
}
接下来我要写的是tank类,作为坦克,我首先考虑的就是他一定要有一个横坐标以及纵坐标,另外,他还得有方向。在坦克大战里,坦克分两种,一种是我方坦克,一种是敌方坦克,不管是那种坦克,他都有横纵坐标,以及方向,以及移动和开火功能,所以我将其封装在一个类里面。
class Tank {
int x;//坦克横坐标
int y;
int direct;
//设置方向
public void setdirect(int direct){
this.direct =direct;
}
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;
}
void moveup(){ //向y的上移动(实际上在我们的电脑上看是向下)
if(y<300)
y++;
}
void movedown(){ //屏幕上显示向上移动
if(y>0)
y--;
}
void moveright(){ 屏幕上显示右移动
if(x<400)
x++;
}
void moveleft(){ 屏幕上显示左移动
if(x>0)
x--;
}
}
那有了坦克类,现在就要区分敌人的坦克和我的坦克了。
//敌人的坦克,敌人的坦克将在接下来的文章中解释,水平暂时不够哈哈哈
class Army extends Tank{
public Army(int x,int y){
super(x,y);
}
}
//我的坦克
class Hero extends Tank{
//定义一颗子弹
shot s=null;
public Hero(int x,int y)
{
super(x,y);
}
//开火
//因为子弹要时刻判断是否撞到障碍物,所以我觉得应该把子弹做成一个线程
public void ShotTarget(){
//System.out.println(x);
//System.out.println(y);
//首先判断开火方向
switch(this.direct)
{
case 0:{
s=new shot(x+8,y+30,direct);break;
}
case 1:{
s=new shot(x+8,y,direct);break;
}
case 2:{
s=new shot(x+30,y+8,direct);break;
}
case 3:{
s=new shot(x,y+8,direct);break;
}
}
//启动线程
Thread S1=new Thread(s);
S1.start();
}
}
然后是我的子弹
//子弹
class shot implements Runnable{
int x,y;//子弹的坐标
int direct;//子弹的方向
int speed=4;//子弹的速度
boolean islive=true;//子弹是否还存在
public shot(int x,int y,int direct){
this.x=x;
this.y=y;
this.direct=direct;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true)
{
try {
Thread.sleep(50);//让其休眠一会,如果一直在循环内存开销太大
//即可能我按下开火键,但每隔50ms判断一次我是否该开火了
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//通过开火的方向判断坐标
switch(direct)
{
case 0:y+=speed;break;
case 1:y-=speed;break;
case 2:x+=speed;break;
case 3:x-=speed;break;
}
//判断子弹何时死亡,如果飞出了面板,则其死亡
if(x<0||x>400||y<0||y>300)
{
this.islive=false;
break;
}
//判断子弹是否碰到敌人坦克
}
}
}
MyPanel是我定义的一个画板,为了做一个简单的页面。自己看java的时候一直搞不太懂this的用法,包括考试时也是一知半解的,这次总算理解透了,this即可看作此类的对象,为了方便我们调用。
接下来是我的MyPanel类,我的所有目的基本都要通过画板表现出来:
首先继承了JPanel,那么时一定要重写Paint()函数的。作为新手,其实还是不太理解super.paint(g)这句话的目的。
//主要有KeyListener,MouseListener,ActionListener
//KeyListener是用来监听键盘,MouseListener是用来监听鼠标,ActionListener监听按钮等
class MyPanel extends JPanel implements KeyListener,Runnable{
//定义我的tank
Hero hero=new Hero(10,10);
//敌人的tank
Army army=new Army(100,10);
//static int direct=1;
public void paint(Graphics g)
{
super.paint(g);
g.fillRect(0, 0, 400, 300);
//this.paint_tank(hero.getX(),hero.getY(),0,1,g);
//画出我的tank
this.paint_tank(hero.x,hero.y,hero.direct,1,g);
//画敌人的坦克
this.paint_tank(army.x,army.y,army.direct,0,g);
}
然后就是画出坦克了
void paint_tank(int x,int y,int direct,int type,Graphics g)
{
//判断敌我坦克
switch(type)
{
//敌人的tank画成蓝色
case 0:{
g.setColor(Color.CYAN);
break;
}
//我的tank画成黄色
case 1:{
g.setColor(Color.yellow);
break;
}
}
//判断方向,画出tank的不同形态
switch(direct){
case 0:{
g.fill3DRect(x, y, 5, 30,false);
g.drawOval(x+5, y+10,10, 10);
g.fill3DRect(x+5, y+5, 10, 20,false);
g.fill3DRect(x+15, y, 5, 30,false);
g.drawLine(x+9, y+15, x+9, y+30);
break;
}
case 1:{
g.fill3DRect(x, y, 5, 30,false);
g.drawOval(x+5, y+10,10, 10);
g.fill3DRect(x+5, y+5, 10, 20,false);
g.fill3DRect(x+15, y, 5, 30,false);
g.drawLine(x+9, y, x+9, y+15);
break;
}
case 2:{
g.fill3DRect(x, y, 30, 5,false);
g.drawOval(x+5, y+5,10, 10);
g.fill3DRect(x+5, y+5, 20, 10,false);
g.fill3DRect(x, y+15, 30, 5,false);
g.drawLine(x+15, y+9, x+30, y+9);
break;
}
case 3:{
g.fill3DRect(x, y, 30, 5,false);
g.drawOval(x+5, y+5,10, 10);
g.fill3DRect(x+5, y+5, 20, 10,false);
g.fill3DRect(x, y+15, 30, 5,false);
g.drawLine(x, y+9, x+15, y+9);
break;
}
}
//画我的子弹
if(hero.s!=null&&hero.s.islive==true)
{
g.setColor(Color.gray);
g.drawOval(hero.s.x, hero.s.y, 2, 2);
}
this.repaint();//一定要重绘!因为他是动态的图形
}
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
接下来就是对于键盘的监听了
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
//按下上键
if(e.getKeyCode()==KeyEvent.VK_DOWN)
{
hero.setdirect(0); //则将方向设置成0
hero.moveup();//调用向上移动的函数
}
//以下同上
if(e.getKeyCode()==KeyEvent.VK_UP)
{
hero.setdirect(1);
hero.movedown();
}
if(e.getKeyCode()==KeyEvent.VK_RIGHT)
{
hero.setdirect(2);
hero.moveright();
}
if(e.getKeyCode()==KeyEvent.VK_LEFT)
{
hero.setdirect(3);
hero.moveleft();
}
//开火
if(e.getKeyCode()==KeyEvent.VK_J)
{
this.hero.ShotTarget();
}
//重绘
this.repaint();
}
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.repaint();
}
}
以上就是我的坦克大战1.0版,只是单纯实现了移动以及开火,对于让敌人的坦克动起来并且也可以开火还有待我的学习。
以下是源代码:
package tank_war;
import java.util.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
public class Tankwar extends JFrame{
MyPanel mp=new MyPanel();
public static void main(String args[])
{
Tankwar T=new Tankwar();
}
public Tankwar()
{
this.add(mp);
//注册键盘监听
this.addKeyListener(mp);
this.setSize(400,300);
this.setVisible(true);
}
}
//主要有KeyListener,MouseListener,ActionListener
class MyPanel extends JPanel implements KeyListener,Runnable{
//定义我的tank
Hero hero=new Hero(10,10);
Army army=new Army(100,10);
//static int direct=1;
public void paint(Graphics g)
{
super.paint(g);
g.fillRect(0, 0, 400, 300);
//this.paint_tank(hero.getX(),hero.getY(),0,1,g);
//画出我的tank
this.paint_tank(hero.x,hero.y,hero.direct,1,g);
//画敌人的坦克
this.paint_tank(army.x,army.y,army.direct,0,g);
}
void paint_tank(int x,int y,int direct,int type,Graphics g)
{
//判断敌我坦克
switch(type)
{
case 0:{
g.setColor(Color.CYAN);
break;
}
case 1:{
g.setColor(Color.yellow);
break;
}
}
//判断方向
switch(direct){
case 0:{
g.fill3DRect(x, y, 5, 30,false);
g.drawOval(x+5, y+10,10, 10);
g.fill3DRect(x+5, y+5, 10, 20,false);
g.fill3DRect(x+15, y, 5, 30,false);
g.drawLine(x+9, y+15, x+9, y+30);
break;
}
case 1:{
g.fill3DRect(x, y, 5, 30,false);
g.drawOval(x+5, y+10,10, 10);
g.fill3DRect(x+5, y+5, 10, 20,false);
g.fill3DRect(x+15, y, 5, 30,false);
g.drawLine(x+9, y, x+9, y+15);
break;
}
case 2:{
g.fill3DRect(x, y, 30, 5,false);
g.drawOval(x+5, y+5,10, 10);
g.fill3DRect(x+5, y+5, 20, 10,false);
g.fill3DRect(x, y+15, 30, 5,false);
g.drawLine(x+15, y+9, x+30, y+9);
break;
}
case 3:{
g.fill3DRect(x, y, 30, 5,false);
g.drawOval(x+5, y+5,10, 10);
g.fill3DRect(x+5, y+5, 20, 10,false);
g.fill3DRect(x, y+15, 30, 5,false);
g.drawLine(x, y+9, x+15, y+9);
break;
}
}
//画我的子弹
if(hero.s!=null&&hero.s.islive==true)
{
g.setColor(Color.gray);
//System.out.print(hero.s.x);
g.drawOval(hero.s.x, hero.s.y, 2, 2);
}
this.repaint();
}
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if(e.getKeyCode()==KeyEvent.VK_DOWN)
{
hero.setdirect(0);
hero.moveup();
}
if(e.getKeyCode()==KeyEvent.VK_UP)
{
hero.setdirect(1);
hero.movedown();
}
if(e.getKeyCode()==KeyEvent.VK_RIGHT)
{
hero.setdirect(2);
hero.moveright();
}
if(e.getKeyCode()==KeyEvent.VK_LEFT)
{
hero.setdirect(3);
hero.moveleft();
}
if(e.getKeyCode()==KeyEvent.VK_J)
{
this.hero.ShotTarget();
}
//重绘
this.repaint();
}
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.repaint();
}
}
class Tank {
int x;//坦克横坐标
int y;
int direct;
Tank(int direct){
this.direct=direct;
}
public void setdirect(int direct){
this.direct =direct;
}
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;
}
void moveup(){
if(y<300)
y++;
}
void movedown(){
if(y>0)
y--;
}
void moveright(){
if(x<400)
x++;
}
void moveleft(){
if(x>0)
x--;
}
}
class Army extends Tank{
public Army(int x,int y){
super(x,y);
}
}
class Hero extends Tank{
shot s=null;
//int direct;
public Hero(int x,int y)
{
super(x,y);
//System.out.println(x);
}
//开火
public void ShotTarget(){
//System.out.println(x);
//System.out.println(y);
Thread S=new Thread();
switch(this.direct)
{
case 0:{
s=new shot(x+8,y+30,direct);break;
}
case 1:{
s=new shot(x+8,y,direct);break;
}
case 2:{
s=new shot(x+30,y+8,direct);break;
}
case 3:{
s=new shot(x,y+8,direct);break;
}
}
Thread S1=new Thread(s);
S1.start();
}
}
//子弹
class shot implements Runnable{
int x,y;
int direct;
int speed=4;
boolean islive=true;
public shot(int x,int y,int direct){
this.x=x;
this.y=y;
this.direct=direct;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true)
{
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
switch(direct)
{
case 0:y+=speed;break;
case 1:y-=speed;break;
case 2:x+=speed;break;
case 3:x-=speed;break;
}
//判断子弹何时死亡
//判断子弹是否碰到敌人坦克
if(x<0||x>400||y<0||y>300)
{
this.islive=false;
break;
}
}
}
}