java小试牛刀(一):碰撞吧,小球

我时常想象人生就是一颗颗不同颜色的球,我们在特定的空间里面做自由的运动,偶尔会与另一颗美丽或者平凡的小球碰撞在一起,然后我们仍走向截然不同的道路。

生命如此,每个人都是独立的个体。也许有一天吧,你遇到了比你强大,比你包容的另一个生命,他或者她会告诉你,来我的怀里吧;于是乎你毅然决然的放弃了所有,奋不顾身的投入了他的怀抱,两颗不同的心,不同的生命也能融为一体。

于是我们终于知道,生命可以是坚硬的碰撞,也可以是温柔的拥抱。在碰撞与拥抱之间,整个宇宙中的生命得以延续,文明才能得到继续。

在这里作为java初步学习的小结,下面是我所做的小球碰撞以及包容(吞噬)的多线程程序。

以下:
我们用一个黑色的界面来代表整个宇宙,在其中放入五颜六色的形状不一的小球(代表生命),这些球在遇到界面的边界时会发生反弹,在遇到其他球时则会发生吞噬或者碰撞的随机过程。

将小球定义为Ball类,每次在黑色界面上的鼠标点击都会在点击处生成一个颜色随机,大小随机(有上限),速度随机(大小和方向随机,但x,y方向的速度不会同时为0)。将所有小球存放在Arraylist中,然后利用多线程对Arraylist进行操作。其中主要实现的是小球的碰撞以及吞噬的 功能。此外还引入暂停,继续,停止等功能。

下面是小球类

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Random;

/*
 * 这里定义的小球类
 * 属性有坐标x,y;大小size;速度xspeed,yspeed;颜色color。全部定义为private型
 * 各属性都有他们的setters和getters
 * 方法有move方法来控制其移动
 * 
 */
public class Ball {
    private int x,y,size;
    private int xspeed;
    private int yspeed;
    private Color color;
    public int getXspeed() {
        return xspeed;
    }

    public void setXspeed(int xspeed) {
        this.xspeed = xspeed;
    }

    public int getYspeed() {
        return yspeed;
    }

    public void setYspeed(int yspeed) {
        this.yspeed = yspeed;
    }

    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 int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

//move是小球的移动方法。
    public void move(BallGame BG,Graphics2D g2d){
        //判断是否碰撞到左右边界,如果碰撞到则x方向的速度取反
        if(x<=0||(x+this.size)>=BG.getWidth()){
            int tempspeed=-this.xspeed;
            this.xspeed =tempspeed; 
        }
        //判断是否碰撞到上下边界,如果碰撞到则y方向的速度取反
        if(y<=20||((y+this.size)>=BG.getHeight())){
            int tempspeed =-this.yspeed;
            this.yspeed =tempspeed;
        }
        /*
         * 下面是小球的移动过程:将小球之间所在位置用界面背景色填充,
         * 在新的位置上画出小球
         */

        //用界面背景色填充小球位置
        g2d.setColor(BG.getBackground());
        g2d.fillOval(x, y, this.size+5, this.size+5);

        //改变小球的x和y方向上的小球都会移动xpeed和yspeed的距离,然后得到新的位置坐标
        this.x +=this.xspeed;
        this.y +=this.yspeed;

        //再用小球颜色在新的坐标上画出小球
        g2d.setColor(this.color);       
        g2d.fillOval(x, y, this.size, this.size);

    }

下面是整个界面的实现以及主线程的实现

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;


public class BallGame extends JFrame {

private Image img;  
private ArrayList list =new ArrayList();

public static void main(String []Args){
    BallGame BG= new BallGame();
    BG.unitUI();
}


//这里是黑色的界面
public void unitUI(){
    this.setTitle("老九的小球游戏");
    this.setSize(1200,700);

    this.setLocationRelativeTo(null);
    this.setBackground(Color.black);    
    this.setDefaultCloseOperation(3);

    this.setResizable(false);
    this.setVisible(true);


/*
 * 这里加入的监听机制有两个功能
 *  1.MouseLIstener用以实现鼠标点击出现小球的功能。
 *  2.KeyListener用以实现暂停继续动画的功能
 * 
 */
    BallListener BL =new BallListener(this,this.getGraphics(),list);
    this.addMouseListener(BL);
    this.addKeyListener(BL);

//引入多线程
    Thread t =new Thread(BL);
    t.start();
}


public void paint(Graphics g) {

//次画布img实现双缓冲,用g2d来绘制图形
    img = this.createImage(this.getWidth(), this.getHeight());
    Graphics2D g2d = (Graphics2D) img.getGraphics();
//引入画笔抗锯齿
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);


/*
 * 将小球存放在Arraylist数组队列中
 * 在下面的循环中将实现小球的吞噬和撞击功能
 */
    for (int i = 0; i < list.size(); i++) {
        /*
         * 小球已被定义为Ball类
         * 将取出的小球放在变量ball中
         */
        Ball ball = (Ball) list.get(i);
        //这里取出相遇的小球存放在tempb中
        for(int j =0 ;j//i=j时说明取出的是ball自己
            if(i!=j){

/*
再次判断是否发生吞噬,if中判断两球是否重叠,所用公式是,两球的圆心坐标(x1,y1),(x2,y2)以及两球的大小size1,size2应满足以下条件:x1x2+size2,y1+size1>y2+size2。
*/
                if(ball.getX()(tempb.getX()+tempb.getSize())
                        &&(ball.getY()+ball.getSize())>(tempb.getY()+tempb.getSize())){
                    //如果相遇则发生吞噬,在Arraylist中取出temp对应的小球
                    list.remove(j);
                    //吞噬后新的小球体积是相遇小球的中的较大者体积加一
                    if(ball.getSize()<100){
                    int tempsize =ball.getSize();
                    ball.setSize(tempsize+1);
                    }
                }

/*
再次判断是否相遇,if中判断两球是否相遇,所用公式是,两球的圆心坐标(x1,y1),(x2,y2)以及两球的大小size1,size2应满足以下条件:(x1-x2)^2+(y1-y2)^2<(size1-size2)^2
*/
                if(((ball.getX()-tempb.getX())*(ball.getX()-tempb.getX())
                        +(ball.getY()-tempb.getY())*(ball.getY()-tempb.getY()))
                        <=(ball.getSize()-tempb.getSize())){
                //碰撞后两球都会反弹
                    ball.setXspeed(-ball.getXspeed());
                    ball.setYspeed(-ball.getYspeed());
                    tempb.setXspeed(-tempb.getXspeed());
                    tempb.setYspeed(-tempb.getYspeed());
                }
            }
        }
        //在画布g2d上重新绘制所有小球的运动状态
        ball.move(this,g2d);
    }
    //用g绘制次画布
    g.drawImage(img, 0, 0, this);
}
}

需要说明的是paint会在run的重载方法中调用,用多线程的思路实现小球的运动过程。

下面是界面的监听机制类

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Random;


//利用鼠标监听实现小球的生成,利用按键监听实现整个程序的暂停和继续
public class BallListener implements MouseListener,KeyListener,Runnable{
    private int x,y;
    private BallGame BG;
    Graphics g;
    private ArrayList list;
    //stopFlag为停止功能键
    private   boolean stopFlag=true;
    //pauseFlag为 暂停/继续 功能键
    private volatile boolean pauseFlag=true;

//BallListener方法实现参数的传递:BallGame类界面BG,BG的画笔g,存放小球的数组队列list
    public BallListener(BallGame BG,Graphics g,ArrayList list){
        this.BG =BG;
        this.g =g;
        this.list =list;
    }

//在此方法中生成小球
    public void mousePressed(MouseEvent e) {

        //得到鼠标的x,y坐标
        x =e.getX();
        y =e.getY();

        //将得到的坐标赋给小球对象ball
        Ball b =new Ball();
        b.setX(x);
        b.setY(y);

        //为小球生成随机颜色,但和界面的背景色不同
        Random rand = new Random();
        do{
        b.setColor( new Color(  (new Double(Math.random()*128)).intValue()+128,
                (new Double(Math.random()*128)).intValue()+128,
                (new Double(Math.random()*128)).intValue()+128));
        }while(b.getColor()==BG.getBackground());

        //为小球生成随机的大小但大小不能小于等于10
        do{
        b.setSize(rand.nextInt(50));
        }while(b.getSize()<=10);

        //为小球生成随机的速度但x,y的速度不能同时为0
        do{
        b.setXspeed(rand.nextInt(8)-4);
        b.setYspeed(rand.nextInt(8)-4);
        }while(b.getXspeed()==0&&b.getYspeed()==0);

        //将生成的小球加入数组队列list中
        list.add(b);
        }

//在此方法中实现暂停,继续等功能
    public void keyPressed(KeyEvent e) {
        //得到按键的值
        int key =e.getKeyCode();

        //switch实现不同的功能
        switch(key){

        //空格键时界面暂停,再次空格则会继续
        case 32:
            pauseFlag =!pauseFlag;
            break;

        //Esc键时界面停止,多线程结束
        case 27:
            stopFlag =false;
            break; 
        case 10:
            stopFlag =true;
            pauseFlag=true;
            list.clear();
            BG.repaint();
            this.run();
            break;
        }
    }


    //在run方法中每隔10ms调用一次BG的重写方法来实现之前所述功能
    public void run() {
        //外层的while循环保证多线程一直执行知道stopFlag变为false
        while(stopFlag){
            /*pauseFlag实现暂停功能,需要说明的是如果为声明pauseFlag为volatile型,
            则pauseFlag在计算机中存放在内存,而多线程在寄存器中执行,数据会无法交换*/
            if(pauseFlag){
                BG.repaint();

                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void keyTyped(KeyEvent e) {}

    public void mouseReleased(MouseEvent e) {}

    public void mouseEntered(MouseEvent e) {}

    public void mouseExited(MouseEvent e) {}

    public void mouseClicked(MouseEvent e) {}

    public void keyReleased(KeyEvent e) {}

}

以上就实现了小球的随机生成,碰撞,吞噬功能。

你可能感兴趣的:(java-web)