一个java写的游戏

一个java游戏
学习了一段时间的java萌生了用java写一个游戏的念头,希望通过写游戏的过程熟练java语法,在编写的过程中也遇到了诸多的问题,还好都克服了,也作出了一个相对比较完整的闯关类游戏(虽然游戏中还有很多的问题),在编写的过程中也对一些java的知识有了更多的理解。游戏中写了两类敌人,一类在空中飞,一类是地上走的,都能对英雄造成伤害,游戏界面中也加入了血条,蓝条,释放大招和发射魔法球都会消耗蓝条,打死敌人会增加蓝条。下面我说一下游戏的主要部分。(游戏中用到的素材大都来自于爱给网,如有侵权立即删除)
游戏结构
程序一共分了五个包
1.Main包------包含GameFrame类,是主界面的实现
2.Animals包---------包含Animal Tiger Boar Bird AnimalsFactory类,其中的游戏中的动物元素都继承自Animal类重写了一些方法,Tiger和AnimalsFactory都是单例模式,保证了只能生成一个对象,在AnimalsFactory中有一个Animal类型的对象容器用来盛放游戏场景中的动物元素,因为是Animal类型的所以继承自Animal的动物实体都可以向上转型并加入到容器中。并且AnimalsFactory中提供了对动物生死的观测。
3.Menus包 包含开始界面的实现类,(本来想在游戏界面上写几个菜单,但是因为各种原因还没有搞)
4.Tools包 有Bullet、Bbullet(野猪子弹)、 Ibullet(鸟子弹) 、MagicBall(魔法球)、 MagicBullet(魔法球释放的子弹)、 Tbullet(老虎的子弹) 、Tool 类,Tool作为所有的工具的基类,所有的子弹都继承自Bullet类。,并重写了Tool中的部分方法。
5.Map包Map类和Scene场景类。
游戏部分截图
(1)开始菜单界面
在这里插入图片描述
(嗯,没错,这个开始界面有点水。。。因为不想把太多的时间花费在ps上,不过游戏名字还是很霸气)
下面是开始界面的实现代码,用的JFrame,又添加了两个按钮。

package Menus;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

import Main.GameFrame;
public class StartFrame extends JFrame{
	private Toolkit tk=Toolkit.getDefaultToolkit();
	private ImageIcon backGround=new ImageIcon("image/start.png");
    private Image screenImage=null;
	private StartFrame() {
	}
	private void drawStart() {
		Font f=new Font("华文行楷",Font.BOLD,20);
		JLabel label=new JLabel(backGround);
		Button startButton=new Button("开始游戏");
		Button ruleButton=new Button("游戏说明");
		JPanel jp=new JPanel();
		//jp.add(label);
		jp.setBounds(0, 0, 600,800);
		startButton.setBounds(250,200,110,50);
		startButton.setBackground(Color.yellow);
		startButton.setFont(f);
		startButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				GameFrame game=new GameFrame();
				close();
				game.init();
			}
		});
		ruleButton.setBackground(Color.yellow);
		ruleButton.setBounds(250,300,110,50);
		ruleButton.setFont(f);
		label.setBounds(0, 0,600,800);
		this.add(startButton);
		this.add(ruleButton);
		jp.add(label);
		this.add(jp);
		this.setLayout(null);
		this.setBackground(Color.blue);
		this.setResizable(false);
		this.setLocation(650,150);
		this.setSize(600,800);
		this.setVisible(true);
	}
	private void close() {
		this.setVisible(false);
	}
	public static void main(String[] args) {
		StartFrame sf=new StartFrame();
		sf.drawStart();
	}
}

(2)游戏界面

主界面代码

package Main;
import Animals.Tiger;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import Map.Map;
import java.awt.Color;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
public class GameFrame extends Frame{
	private static final long serialVersionUID = 1L;
	public static int frameWidth=1400;
	public static int frameHeight=800;
	private Map map=new Map();
    private Image screenImage = null;
	public void init(){
		this.setSize(frameWidth,frameHeight);
		this.setLocation(260,120);
		this.setTitle("动物世界");
	    this.setVisible(true);
	    this.setResizable(false);
		this.addWindowListener(new WindowAdapter() { // 窗口关闭监听
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		screenImage=this.createImage(frameWidth,frameHeight);
		this.addKeyListener(new KeyMonitor());
		new Thread(new PaintThread()).start(); 
	}
	public void update(Graphics g){
		Graphics gc=screenImage.getGraphics();
		gc.setColor(Color.BLUE);
		gc.fillRect(0, 0, frameWidth, frameHeight);
		map.drawMap(gc);
		drawInfo(gc);
		g.drawImage(screenImage,0,0, null);//双缓冲
	}
	private void drawInfo(Graphics g) {
		g.setFont(new Font("华文行楷",Font.BOLD,40));
		g.drawString("魔法:",30,100);
		g.fillRect(150,70,Tiger.magic,30);
		g.setColor(Color.RED);
		g.drawString("生命:",30,150);
		g.fillRect(150,130,Tiger.life,30);
	}
	private class PaintThread implements Runnable{
		public void run() {
			while(Tiger.getTiger().ifPrint){
				repaint();
				try {
					Thread.sleep(40);
				}catch(InterruptedException  e) {
						e.printStackTrace();
				}
			}
		}
	}
	private class KeyMonitor extends KeyAdapter{
		public void keyReleased(KeyEvent e) {
			Tiger.getTiger().key_Released(e);
		}
		public void keyPressed(KeyEvent e) {
			Tiger.getTiger().key_Pressed(e);
		}
	}
}

敌人随机产生的代码*

	private void random(){
		time++;
		if(time%100==0){
			int randY=random.nextInt(250)+400;
			animals.add(new Boar(1400,randY));
			if(randY>=550) 
				randY=400;
			animals.add(new Boar(1400,randY+50+random.nextInt(50)));
			Bird bird=new Bird(1400,30);
			if(time%200==0)
				animals.add(bird);
			
		}
	}

因为所有的动物都是继承自Animal,所以直有接建立一个Animal的对象容器,其中time就像是一个计时器,100个时间单位后会产生两只野猪,200个时间单位后就会产生一只鸟。并且野猪的产生位置是随机的,
而两只野猪相距要有一定距离否则会重合,所以r第二只野猪的y坐标是:randY+50+random.nextInt(50)
Scene实现场景的移动

    public void drawScene(Graphics g,String direction,int x,int y) {
    	if(x>380&&direction.equals("Forward_go")&&scene_x<9700){
    		scene_x=scene_x+50;
    	}
    	if(scene_x==9700){
    		Tiger.getTiger().go=true;
    		if(x>1200) {
    			GameFrame.win=true;
    		}
    	}
       g.drawImage(scene,0,0,GameFrame.frameWidth,GameFrame.frameHeight,scene_x,scene_y,scene_x+1400,scene_y+800,null);    	
    }
}

(3)英雄大招
在这里插入图片描述
(事实上大招的伤害还没有写。。。因为写大招伤都是重复算坐标的工作,所以没有写。。。)
这里是大招特效的部分实现

	public void drawBullet(Graphics g) {
		if(number==0) {
			g.drawImage(magicBullet[0],x,y,null);
			y-=15;
		}
		if(number==1) {
			g.drawImage(magicBullet[1],x,y,null);
			x+=15;
			y-=15;
		}
		if(number==2) {
			g.drawImage(aperture[3],x-100,y-120,null);
			g.drawImage(magicBullet[2],x,y,null);
			x+=15;
		}
		if(number==3) {
			g.drawImage(magicBullet[3],x,y,null);
			x+=15;
			y+=15;
		}
		if(number==4) {
			g.drawImage(magicBullet[4],x,y,null);
			y+=15;
		}
		if(number==5) {
			g.drawImage(magicBullet[5],x,y,null);
			x-=15;
			y+=15;
		}
		if(number==6) {
			g.drawImage(magicBullet[6],x,y,null);
			x-=15;
		}
		if(number==7) {
			g.drawImage(magicBullet[7],x,y,null);
			x-=15;
			y-=15;
		}
	}

一共有八个方向的子弹,分别标注0-7,不同的方向要展示不同的图片。、

public void observation(Graphics gc) {
		for(int i=0;i<tiger.bullets.size();i++){//老虎的子弹打到敌人
			for(int j=0;j<animals.size();j++){
			 if(animals.get(j) instanceof Boar) {
				if(animals.get(j).ifHit(tiger.bullets.get(i).x, tiger.bullets.get(i).y)) {
					animals.get(j).dead(gc);
					animals.get(j).bomb(gc);
					if(animals.get(j).life==0&&animals.get(j).bomb){
						animals.remove(j);
					    tiger.bullets.get(i).live=false;
					    tiger.magic+=10;
					}
				}
			   }
			}
		}
		for(int i=0;i<tiger.magicBall.magicBullets.size();i++)
			for(int j=0;j<animals.size();j++) {
				if(animals.get(j) instanceof Bird)
					try {
					if(tiger.magicBall.magicBullets.get(i).number==1) {
						if(tiger.magicBall.magicBullets.get(i).judge(animals.get(j))) {
							animals.remove(j);
							tiger.magic+=10;
							tiger.magicBall.magicBullets.remove(i);
						}
					}
					}catch(IndexOutOfBoundsException e) {
						System.out.println("数组越界了");
					}
			}
		for(int i=0;i<animals.size();i++){	//子弹打老虎对老虎造成伤害		
			for(int j=0;j<animals.get(i).getBullet().size();j++) {//这里出现了一个错误,居然是忘记了重写父类中的getBullet方法
				if(animals.get(i) instanceof Boar) {
					int c=animals.get(i).getBullet().get(j).x+20;
					int d=animals.get(i).getBullet().get(j).y+20;
					if(c>tiger.x+256&&c<tiger.x+280&&d<tiger.y+255&&d>tiger.y+210){
						Tiger.life-=3;
						animals.get(i).getBullet().remove(j);
					}
				}else{
					if(tiger.getRect().intersects(animals.get(i).getBullet().get(j).getRect())) {
						Tiger.life-=4;
						animals.get(i).getBullet().remove(j);
					}
				}
			}	
		}	
	}	

AnimalFactory类中的observation()方法是对地图中的子弹和对象进行监控,控制子弹的打中,这里写的比较差。。。到这里基本就差不多了最后再看一下老虎类的控制:
通过控制方向标记控制图片的展示:

public void key_Released(KeyEvent e){
		int key=e.getKeyCode();
		switch(key) {
			case KeyEvent.VK_UP:
				direction="Left";
				break;
			case KeyEvent.VK_DOWN:
				direction="Right";
				break;
			case KeyEvent.VK_LEFT:
				direction="Behind";
				break;
			case KeyEvent.VK_RIGHT:
				direction="Forward";
				break;
		}
	}
	public Rectangle getRect() {
		return new Rectangle(x+256,y+220,60,60);
	}
	public void key_Pressed(KeyEvent e) {
		int key=e.getKeyCode();
		switch(key) {
			case KeyEvent.VK_UP:
				direction="Left_go";
				y=y-20;
				break;
			case KeyEvent.VK_DOWN:
				direction="Right_go";
				y=y+20;
				break;
			case KeyEvent.VK_LEFT:
				direction="Behind_go";
				x=x-15;
				break;
			case KeyEvent.VK_RIGHT:
				direction="Forward_go";
				if(x<400||go)
				   x=x+15;
				break;
			case KeyEvent.VK_Q:
				if(magic<0)
					break;
				magic-=3;
				fire=true;
				if(direction.equals("Forward_go")||direction.equals("Forward")||direction.equals("Forward_fire")){
					direction="Forward_fire";
					bullets.add(new Tbullet(x+tigerImageWidth/2+15,y+tigerImageHeight/3+45,direction));
				}
				if(direction.equals("Behind_go")||direction.equals("Behind")||direction.equals("Behind_fire")) {
					direction="Behind_fire";
					bullets.add(new Tbullet(x+110,y+tigerImageHeight/2-40,direction));
				}
				break;
			case KeyEvent.VK_E:
				if(magic<0)
					break;
				magic-=3;
				magicBall.e_Fire=true;
				break;
			case KeyEvent.VK_W:
				if(magic<0)
					break;
				magic-=20;
				magicBall.magicFire=true;
				break;
		}
	}

这里是老虎的画图方法:

	public void drawTiger(Graphics g) {
		limitXY();
		if(life<=0) {		
		dead(g);
		return;
	    }
		if(direction.equals("Right")){
			if(step>=tiger_R.length)
				step=0;
			g.drawImage(tiger_R[step],x,y,null);
			step++;
		}
		if(direction.equals("Left")){
			if(step>=tiger_L.length)
				step=0;
			g.drawImage(tiger_L[step],x,y,null);
			step++;
		}
		if(direction.equals("Forward")){
			if(step>=tiger_F.length)
				step=0;
			g.drawImage(tiger_F[step],x,y,null);
			step++;
		}
		if(direction.equals("Behind")){
			if(step>=tiger_B.length)
				step=0;
			g.drawImage(tiger_B[step],x,y,null);
			step++;
		}
		if(direction.equals("Forward_go")){
			if(step>=tiger_Fgo.length)
				step=0;
			g.drawImage(tiger_Fgo[step],x,y,null);
			step++;
		}
		if(direction.equals("Right_go")){
			if(step>=tiger_Rgo.length)
				step=0;
			g.drawImage(tiger_Rgo[step],x,y,null);
			step++;
		}
		if(direction.equals("Behind_go")) {
			if(step>=tiger_Bgo.length)
				step=0;
			g.drawImage(tiger_Bgo[step],x,y,null);
			step++;
		}
		if(direction.equals("Left_go")){
			if(step>=tiger_Lgo.length)
				step=0;
			g.drawImage(tiger_Lgo[step],x,y,null);
			step++;
		}
		if(direction.equals("Forward_fire")){
			if(step>=tiger_Ffire.length)
				step=0;
			g.drawImage(tiger_Ffire[step],x,y,null);
			step++;
		}
		if(direction.equals("Behind_fire")){
			if(step>=tiger_Bfire.length)
				step=0;
			g.drawImage(tiger_Bfire[step],x,y,null);
			step++;
		}
	}

以上就是这个游戏的基本实现,代码中还有诸多的问题,欢迎大家指出,虽然awt Swing已经不太有人用了,但是写写小游戏还是可以的,这样既能提高兴趣又能训练自己的java基本语法。学习本来就应该是一件快乐有成就感的事情。
需要源码请评论联系我

`

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值