做了个乒乓球,发现人眼睛是自带运动趋势预判的...

 


代码如下,就是画了个小球,给定速度,大小和初始运动角度,在一个方框内弹来弹去。单开个线程,每隔一段时间计算一次小球的坐标和角度变化。初稿设置小球的每帧运动距离远大于球半径,结果面临一个靠近边角时需要计算先撞上哪个边的问题+y轴经常超界+如果不插入额外帧小球经常撞不到边轨迹就弹回了。所以第二稿改为每帧运动距离等于球半径。结果就发现了一个新问题
考虑一种情况,小球在某一帧时候距离某边界(假设为右边界)距离小于其半径*cos(运动角度),则下一帧时为了不穿透墙体其x轴平移量应小于预设值。相应的,y轴位移也应该等比例减少。
但是实际做出来发现小球撞墙时明显会有一个偏离运动轨迹的抖动(例如,往右上角运动撞墙时明显可以看到球向下抖了一下,同理,左下方向撞墙时,会向上抖。)人眼睛似乎可以分辨出来小球运动速度的突然变化,但是却不是体现在运动方向上,而是其中一个分量方向(不知道为什么,但是分量方向相对运动方向固定,一直是在往右抖)。
原计算方法已注释掉(未删除),新算法里无论撞墙(右)前x轴偏移多小,y轴都使用预计的完整偏移量。结果观察几分钟时间内无明显抖动。
新学乍练,代码写的很脏,行家勿喷。有兴致的话可以大家来找碴,帮我指点下错误,感激不尽。
下一步可能看看怎么在开始/暂停/失败时候弹出对应窗口。失败后重置为初始状态。
  1 package com.mycompany.myapp;
  2  
  3 
  4 import android.app.*;
  5 import android.os.*;
  6 import android.view.View;
  7 import android.content.Context;
  8 import android.graphics.*;
  9 import android.view.*;
 10 
 11 public class MainActivity extends Activity 
 12 {
 13     @Override
 14     protected void onCreate(Bundle savedInstanceState)
 15     {
 16         super.onCreate(savedInstanceState);
 17         setContentView(new myview(this));
 18     }
 19  public class myview extends View
 20  {
 21   public myview(Context context)
 22   {
 23    super(context);
 24    new Thread(new mythread()).start();
 25   }
 26   WindowManager wm=(WindowManager)getContext().getSystemService(WINDOW_SERVICE);
 27   private float screenh=wm.getDefaultDisplay().getHeight();
 28   private float screenw=wm.getDefaultDisplay().getWidth();
 29   private final float FRAMELEFT=screenw*0.1f;
 30   private final float FRAMERIGHT=screenw*0.9f;
 31   private final float FRAMETOP=screenh*0.1f;
 32   private final float FRAMEBOTTOM=screenh*0.8f; 
 33   private final long TIME_IN_FRAME=2;
 34   private final float BALLR=15;
 35   private final float BALL_MOVE_IN_FRAME=BALLR;
 36   private float balljiao=325;
 37   private float ballx=screenw*0.5f;
 38   private float bally=FRAMEBOTTOM-BALLR;
 39 
 40   @Override
 41   protected void onDraw(Canvas canvas)
 42   {
 43    super.onDraw(canvas);
 44    Paint ballpaint=new Paint();
 45    ballpaint.setColor(Color.RED);
 46    drawball(canvas,ballpaint);
 47    Paint textpaint=new Paint();
 48    textpaint.setColor(Color.BLACK);
 49    textpaint.setStyle(Paint.Style.STROKE);
 50    canvas.drawRect(FRAMELEFT,FRAMETOP,FRAMERIGHT,FRAMEBOTTOM,textpaint);
 51   }
 52   public void drawball(Canvas Canvas,Paint ballpaint)
 53   {
 54    Canvas.drawCircle(ballx,bally,BALLR,ballpaint);
 55   }
 56   private Handler myhandler=new Handler(){
 57    @Override
 58    public void handleMessage(Message msg)
 59    {
 60     super.handleMessage(msg);
 61     if(msg.what==1)
 62     {
 63      update_ball_state();
 64      invalidate();
 65     }
 66    }
 67   };
 68   public void update_ball_state()
 69   {
 70    float xmove=BALL_MOVE_IN_FRAME*(float)Math.cos(balljiao*Math.PI/180);
 71    float ymove=BALL_MOVE_IN_FRAME*(float)Math.sin(balljiao*Math.PI/180);
 72    if(ballx+xmove+BALLR>=FRAMERIGHT){
 73     //bally=bally+(FRAMERIGHT-BALLR-ballx)*ymove/xmove;
 74     bally=bally+ymove;
 75     ballx=FRAMERIGHT-BALLR;
 76     balljiao=180-balljiao;
 77     //invalidate();
 78    }
 79    else if(ballx+xmove-BALLR<=FRAMELEFT){
 80     //bally=bally+(ballx-FRAMELEFT-BALLR)*ymove/xmove;
 81     bally=bally+ymove;
 82     ballx=FRAMELEFT+BALLR;
 83     balljiao=180-balljiao;
 84     //invalidate();
 85    }
 86    else if(bally+ymove-BALLR<=FRAMETOP){
 87     //ballx=ballx+(bally-FRAMETOP-BALLR)*xmove/ymove;
 88     ballx=ballx+xmove;
 89     bally=FRAMETOP+BALLR;
 90     balljiao=360-balljiao;
 91     //invalidate();
 92    }
 93    else if(bally+ymove+BALLR>=FRAMEBOTTOM){
 94     //ballx=ballx+(FRAMEBOTTOM-bally-BALLR)*xmove/ymove;
 95     ballx=ballx+xmove;
 96     bally=FRAMEBOTTOM-BALLR;
 97     balljiao=360-balljiao;
 98     //invalidate();
 99    }
100    else{
101     ballx=ballx+xmove;
102     bally=bally+ymove;
103    }
104   }
105   private class mythread implements Runnable
106   {
107    @Override
108    public void run()
109    {
110     while(!Thread.currentThread().isInterrupted())
111     {
112      try
113      {
114       Thread.sleep(TIME_IN_FRAME);
115       Message m=new Message();
116       m.what=1;
117       myhandler.sendMessage(m);
118      }catch(InterruptedException e){
119       
120      }
121     }
122    }
123   }
124  }
125 }

 

 

posted on 2016-02-26 22:36  刘政buct  阅读(258)  评论(0)    收藏  举报

导航