Java游戏程序设计教程 4.5打砖块游戏

4.5打砖块游戏

在这里插入图片描述
在这里插入图片描述

package view;

import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Panel;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
    
public class GameFrame {
	public GameFrame(){
		Frame f=new Frame("Block Game");
		GamePanel gp=new GamePanel();
		Thread t=new Thread(gp);
		t.start();
		f.setLocation(100,100);
		f.setSize(500,500);
		f.add(gp);
		f.setVisible(true);
	}
	public static void main(String args[]){
		new GameFrame();
	}
}
class GamePanel extends Panel implements KeyListener,Runnable{
	private Pad p;
	private Block bl;
	private Ball bal;
	int width=500;
	int height=500;
	public boolean padMoveRight;
	public boolean padMoveLeft;
	public boolean ballMove;
	public GamePanel(){
		p=new Pad(this);
		bl=new Block(this);
		bal=new Ball(this,p,bl);
		addKeyListener(this);
	}
	public void gameUpdate(){
		p.update();
		bl.update();
		bal.update();
	}
	public void paint(Graphics g){
		p.draw(g);
		bl.draw(g);
		bal.draw(g);
	}
	@Override
	public void keyTyped(KeyEvent e) {
		// TODO 自动生成的方法存根
		
	}
	@Override
	public void keyPressed(KeyEvent e) {
		// TODO 自动生成的方法存根
		int keycode=e.getKeyCode();
		if(keycode==KeyEvent.VK_LEFT){
			padMoveLeft=true;
		}
		if(keycode==KeyEvent.VK_RIGHT){
			padMoveRight=true;
		}
	}
	@Override
	public void keyReleased(KeyEvent e) {
		// TODO 自动生成的方法存根
		int keycode=e.getKeyCode();
		if(keycode==KeyEvent.VK_RIGHT){
			padMoveRight=false;
		}
		if(keycode==KeyEvent.VK_LEFT){
			padMoveLeft=false;
		}
	}
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		while(true){
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			gameUpdate();//游戏刷新
			repaint();//重绘
		}
		
	}
}
class Pad{
	public Point location;//挡板坐标
	public Point size;//挡板尺寸
	private GamePanel gameP;
	public Pad(GamePanel gp){
		gameP=gp;
		size=new Point(100,20);
		location =new Point((gp.width-size.x)/2,gp.height-size.y);
		//初始位置位于屏幕正下方
	}
	public void update(){
		if(gameP.padMoveRight){					//如果玩家按下右键
			if(location.x+size.x<gameP.width){  //如果右边沿没有出界
				location.x+=10;					//挡板向右移动
			}//if
		}//if
		if(gameP.padMoveLeft){
			if(location.x>0){
				location.x-=10;
			}
		}
	}//update
	public void draw(Graphics g){
		g.setColor(Color.BLACK);
		g.fillRoundRect(location.x,location.y,size.x,size.y,10,10);
	}
}
class Block{
	private GamePanel gameP;
	private Point allocation; //存放砖块的分布,行数*列数
	public Point location[];  //存放每个砖块的坐标
	public Point size;		  //存放砖块的尺寸,长*宽
	public int num;			  //存放砖块的数量
	public boolean exist[];    //标识砖块是否被敲击
	public Block(GamePanel gp){
		gameP=gp;
		num=20;
		allocation=new Point(4,5);//砖块分布为4行*5列
		size=new Point(50,20);
		location=new Point[num];
		for(int i=0;i<allocation.y;i++){
			for(int j=0;j<allocation.x;j++){
				//初始化各砖块的坐标值,让每个砖块均匀的分布在屏幕上部区域
				location[i*allocation.x+j]=new Point((gp.width/allocation.x
						-size.x)/2+j*(gp.width/allocation.x),(i*2+1)*size.y);
			}
		}
		exist=new boolean[num];//初始化exsit数组
		for(int i=0;i<num;i++){
			exist[i]=true;
		}
	}
	public void update(){
		for(int i=0;i<num;i++){
			if(exist[i]==false){
				//如果砖块被敲击,将其坐标设置在程序窗口范围之外
				location[i].setLocation(gameP.width+1,gameP.height+1);
			}
		}
	}
	public void draw(Graphics g){
		g.setColor(Color.gray);
		for(int i=0;i<num;i++){
			if(exist[i]==true){
				g.fillRect(location[i].x,location[i].y,size.x,size.y);
			}
		}
	}			
}
class Ball{
	private GamePanel gameP;
	private Block blk;
	private Pad pd;
	private Point location;//小球的坐标
	private int diameter;
	private int dx;
	private int dy;
	public Ball(GamePanel gp,Pad p,Block bk){
		gameP=gp;
		blk=bk;
		pd=p;
		location=new Point(pd.location.x+(pd.size.x-diameter)/2,
				pd.location.y-pd.size.y);//小球初始值位于挡板正中央
		dx=10;
		dy=-5;
		diameter=20;
	}
	public void update(){
		if(gameP.ballMove){//若小球处于运动状态
			location.x+=dx;
			location.y+=dy;
			wallBounced();//小球与墙壁碰撞检测
			blockBounced();//小球与砖块碰撞检测
			padBounced();//小球与挡板碰撞检测	
		}else{			//若小球停止运动,回到挡板正中央
			location.setLocation(pd.location.x+(pd.size.x-diameter)/2,
					pd.location.y-pd.size.y);
		}
	}
	public void draw(Graphics g){
		g.setColor(Color.blue);
		g.fillOval(location.x, location.y, diameter, diameter);
	}
	
private boolean Bounce(Point bk_location,Point bk_size){
		if((location.x>bk_location.x-diameter) && 
				(location.x<bk_location.x+bk_size.x) &&
				(location.y>bk_location.y-diameter) &&
				(location.y<bk_location.y+bk_size.y)){
			return true;
		}else{
			return false;
		}
	}
private void padBounced() {
		// TODO 自动生成的方法存根
		Point local1,local2,local3,size1,size2,size3;
		//水平方向按1:5:1的比例分割挡板,垂直方向只取挡板高度的1/4
		local1=pd.location;
		size1=new Point(pd.size.x*1/7,pd.size.y/4);
		local2=new Point(pd.location.x+pd.size.x*1/7,pd.location.y);
		size2=new Point(pd.size.x*5/7,pd.size.y/4);
		local3=new Point(pd.location.x+pd.size.x*6/7,pd.location.y);
		size3=new Point(pd.size.x*1/7,pd.size.y/4);
			if(Bounce(local2,size2)){
				dy=-dy;
			}else if(Bounce(local1,size1)){
				if(dx>0){
					dx=-dx;
				}
				dy=-dy;
			}else if(Bounce(local3,size3)){
				if(dx<0){
					dx=-dx;
				}
				dy=-dy;
			}
	}
private void blockBounced() {
		// TODO 自动生成的方法存根
		Point local1,local2,local3,size1,size2,size3;
		for(int i=0;i<blk.num;i++){
			//按照1:8:1的比例将每个砖块划分为三个区域R1、R2、R3
			local1=blk.location[i];
			size1=new Point(blk.size.x*1/10,blk.size.y);
			local2=new Point(blk.location[i].x+blk.size.x*1/10,blk.location[i].y);
			size2=new Point(blk.size.x*8/10,blk.size.y);
			local3=new Point(blk.location[i].x+blk.size.x*9/10,blk.location[i].y);
			size3=new Point(blk.size.x*1/10,blk.size.y);
			
			//分别对三个区域进行碰撞检测
			if(Bounce(local2,size2)){//若碰撞发生在R2区
				dy=-dy;				
				blk.exist[i]=false;
			}else if(Bounce(local1,size1)){
				if(dx>0){
					dx=-dx;
				}else {
					dy=-dy;
				}
				blk.exist[i]=false;
			}else if(Bounce(local3,size3)){
				if(dx<0){
					dx=-dx;
				}else{
					dy=-dy;
				}
				blk.exist[i]=false;
			}
		}
	}
	private void wallBounced() {
		// TODO 自动生成的方法存根
		if((location.x>gameP.width-diameter)||(location.x<0)){
			//小球碰撞到左边或右边墙壁,改变水平运动方向
			dx=-dx;
		}
		if(location.y<0){//小球碰到上方墙壁,改变垂直运动方向
			dy=-dy;
		}
		if(location.y>gameP.height){//小球落出窗口下边界,让小球停止运动
			gameP.ballMove=false;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值