持球人带球行走示例(球与人保持一定距离)

来源:互联网 发布:js typedarray 编辑:程序博客网 时间:2024/04/27 21:57

package runball;

 

import java.applet.Applet;

import java.awt.Color;

import java.awt.Dimension;

import java.awt.Graphics;

import java.awt.Image;

import java.util.Random;

 

/**

 * 用户模仿球员带球跑动的运动过程

 * 球员梯到球后球便会离开持球人脚下,并一开始

 * 会以一个最大速度进行,随着摩擦力的增大,球速

 * 会慢慢的降下来,此时持球人又追到球,然后踢出,

 * 从而达到球一停一走的感觉。

 * 要注意的是当球离开持球人的时候此时持球人并没有

 * 发生改变;只有在其他球员抢到球后才会更改持球人

 *

 * 另外假如要实现球始终在持球人的脚下效果,则直接

 * 根据持球人当前跑动的方向调整相应的坐标即可。

 * @author Administrator

 *

 */

public class TakeBallRun extends Applet {

 

    private Image offScreen;

    private Graphics drawOffScreen;

    private int appWidth, appHeight;

   

    private Ball ball;

    private Rect rect;

   

    public void init() {

       appWidth = 400;

       appHeight = 300;

       setSize(new Dimension(400, 300));

       offScreen = this.createImage(appWidth, appHeight);

       drawOffScreen = offScreen.getGraphics();

      

       ball = new Ball(90, 160, 25, 25, appWidth, appHeight);

       ball.dir = Entity.RIGHT;                             //这个方向是测试

       rect = new Rect(30, 150, 30, 40, appWidth, appHeight);

      

       new Thread(new PaintThread()).start();

    }

 

    public void paint(Graphics g) {

       drawOffScreen.setColor(Color.BLACK);

       drawOffScreen.fillRect(0, 0, appWidth, appHeight);

      

       rect.draw(drawOffScreen);

       ball.draw(drawOffScreen);

      

       ball.move(rect);

       rect.move(ball);

      

       g.drawImage(offScreen, 0, 0, this);

    }

 

    public void update(Graphics g) {

       paint(g);

    }

 

    class PaintThread implements Runnable {

       @Override

       public void run() {

           while (true) {

              try {

                  Thread.sleep(41);

              } catch (InterruptedException e) {

                  e.printStackTrace();

              }

              repaint();

           }

       }

    }

}

 

/**充当人物*/

class Rect extends Entity{

 

    public Rect(int x, int y, int width, int height, int appWidth, int appHeight){

       super(x, y, width, height, appWidth, appHeight);

       speed = 4;

    }

   

    @Override

    public void draw(Graphics g) {

       //绘制人物的宽高

       g.setColor(Color.RED);

       g.fillRect((int)x, (int)y, width, height);

      

       //绘制人物的脚,用于作碰撞检测

       g.setColor(Color.GREEN);

       g.drawRect((int)x + width / 4, (int)y + height / 4 * 2, width / 2, height / 2);  //把宽高分成4等分

    }

   

    public void move(Entity entity){

       Ball ball = (Ball)entity;

       if(ball.isRun()){

           return;

       }

       double spaceX = entity.x - x;

       double spaceY = entity.y - y;

       double radian = Math.atan2(spaceY, spaceX);          //弧度

       double angle = Math.abs(radian * 180 / Math.PI);    //角度

       if(entity.x >= x && entity.y <= y){                  //第1象限

           getBearing(angle, 7, 7, 1);

       }else if(entity.y <= y && entity.x <= x){        //第2象限

           getBearing(angle, 5, 5, 1);

       }else if(entity.y >= y && entity.x <= x){        //第3象限

           getBearing(180-angle,3,6,2);

       }else if(entity.y >= y && entity.x >= x){        //第4象限

           getBearing(angle,4,8,2);

       }

 

       vx = Math.cos(radian) * speed;           

       vy = Math.sin(radian) * speed;

       boolean flag = isCollide(this, entity);

 

       if(flag){

//         System.out.println("人碰到了球,球开始移动");

          

           //这里是测试, 随机一个开球方向

//         int[] dirs = new int[]{1,2,3,4,5,6,7,8};

//         int temp = new Random(System.currentTimeMillis()).nextInt(dirs.length - 1);

//         ball.setDir(temp);

           ball.initDir();

       }else{

           x += vx;

           y += vy;

//         System.out.println("x: " + x + ",y: " + y);

       }

    }

   

    private boolean isCollide(Entity e1, Entity e2){

       if(e1.x + width / 4 < e2.x + e2.width && e1.x + width / 4 + e1.width / 2 > e2.x

           && e1.y + height / 4 * 2 < e2.y + e2.height && e1.y + height / 4 * 2 + e1.height / 2 > e2.height){

           return true;

       }

       return false;

    }

   

    /**

     * 把象限分成3分:23,23~68,68~90,都是跟X轴为起始旋转的角度

     */

    private void getBearing(double angle,int a, int b, int c){

       if(angle < 23){

           dir = a;

       }else if(angle >= 23 && angle < 68){

           dir = b;

       }else if(angle >= 68){

           dir = c;

       }

    }

   

}

 

/**Ball球*/

class Ball extends Entity{

   

    private double friction;           //摩擦力

    private boolean isRun;                 //是否可以运动

   

    public Ball(int x, int y, int width, int height, int appWidth, int appHeight){

       super(x, y, width, height, appWidth, appHeight);

       friction = 0.95;

       speed = 8;

       isRun = true;

       changeDir();      //为vx、vy赋值

    }

   

    @Override

    public void draw(Graphics g) {

       g.setColor(Color.BLUE);

       g.fillOval((int)x, (int)y, width, height);

    }

 

    @Override

    public void move(Entity entity) {

       vx *= friction;

       vy *= friction;

       x += vx;

       y += vy;

      

       if(vx < 1 && vy < 1){

           isRun = false;

       }else{

           isRun = true;

       }

      

       boolean flag = isCollideBorder();

       if(flag){

           changeDir();

           System.out.println("改变方向");

       }

    }

   

    /**玩家碰到球后,将向量重置为

     * 之前的状态, 还是朝之前的方向走

     * 因为人碰到球后,只是朝球原来的方向行走即可

     */

    public void initDir(){

       isRun = false;

       changeDir();

    }

   

    private void changeDir(){

       switch(dir){

       case UP:

           vx = 0;

           vy = -speed;

           break;

       case DOWN:

           vx = 0;

           vy = speed;

           break;

       case LEFT:

           vx = -speed;

           vy = 0;

           break;

       case RIGHT:

           vx = speed;

           vy = 0;

           break;

       case LEFT_UP:

           vx = -speed;

           vy = -speed;

           break;

       case LEDT_DOWN:

           vx = -speed;

           vy = speed;

           break;

       case RIGHT_UP:

           vx = speed;

           vy = -speed;

           break;

       case RIGHT_DOWN:

           vx = speed;

           vy = speed;

           break;

       }

    }

   

    /**

     * 检测是否碰到边界,如果碰到则反弹

     * @return

     */

    private boolean isCollideBorder(){

       System.out.println("x: "+ x);

       if(x <= 0){

           dir = RIGHT;

           return true;

       }else if(x + width >= appWidth){

           dir = LEFT;

           return true;

       }

      

       if(y <= 0){

           dir = DOWN;

           return true;

       }else if(y + height >= appHeight){

           dir = UP;

           return true;

       }

       return false;

    }

 

    public void setDir(int dir){

       this.dir = dir;

    }

   

    public final boolean isRun() {

       return isRun;

    }

 

    public final void setRun(boolean isRun) {

       this.isRun = isRun;

    }

   

    public void setVXY(int vx, int vy){

       this.vx = vx;

       this.vy = vy;

    }

   

}

 

abstract class Entity{

   

    public static final int LEFT = 3;

    public static final int RIGHT = 4;

    public static final int UP = 1;

    public static final int DOWN = 2;

    public static final int RIGHT_UP = 7;

    public static final int RIGHT_DOWN = 8;

    public static final int LEFT_UP = 5;

    public static final int LEDT_DOWN = 6;

   

    protected int dir = RIGHT;

    protected double x, y, speed, maxSpeed;

    protected int width, height;

    protected double vx, vy;                         //速度向量

    protected int appWidth, appHeight;                   //显示区域的宽度和高度

   

    public Entity(int x, int y, int width, int height, int appWidth, int appHeight){

       this.x = x;

       this.y = y;

       this.width = width;

       this.height = height;

       this.appWidth = appWidth;

       this.appHeight = appHeight;

    }

   

    abstract public void draw(Graphics g);

    abstract public void move(Entity entity);

}