做了个乒乓球,发现人眼睛是自带运动趋势预判的...
代码如下,就是画了个小球,给定速度,大小和初始运动角度,在一个方框内弹来弹去。单开个线程,每隔一段时间计算一次小球的坐标和角度变化。初稿设置小球的每帧运动距离远大于球半径,结果面临一个靠近边角时需要计算先撞上哪个边的问题+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 }

浙公网安备 33010602011771号