Android模拟小球自由落体2(重力感应并添加z轴)

这次改进了昨天那个例子,添加了重力感应,并添加了z轴。这样算3D了吧(笑)。小球往屏幕里面落时会不断变小。改进了下绘图线程的控制,surfaceCreated时绘图线程启动,surfaceDestroyed时 绘图线程停止。还有极小概率会出现程序崩溃,不知道是不是不同线程同时读取KCList造成的,你们可以给KCList加个同步锁试试,概率太小了不好测试。

下面是代码。

package com.example.sft;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

public class TestSurfaceView extends SurfaceView implements SurfaceHolder.Callback{
    
    private Paint cp;
    private List<KCircle> KCList;
    private Random r;
    private SensorManager sm;
    private MyThread mt;

    public TestSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
        getHolder().addCallback(this);
        cp=new Paint();
        cp.setColor(Color.BLACK);
        KCList=new ArrayList<KCircle>();
        r=new Random();
        sm=(SensorManager)context.getSystemService(context.SENSOR_SERVICE);
        Sensor sensor=sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        sm.registerListener(new SensorEventListener() {
            
            @Override
            public void onSensorChanged(SensorEvent event) {
                // TODO Auto-generated method stub
                KCircle.ax=-event.values[0]/16;
                KCircle.ay=event.values[1]/16;
                KCircle.az=-event.values[2]/16;
                
            }
            
            @Override
            public void onAccuracyChanged(Sensor sensor, int accuracy) {
                // TODO Auto-generated method stub
                
            }
        }, sensor, SensorManager.SENSOR_DELAY_GAME);
    
        
    }
    
    

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
        // TODO Auto-generated method stub
        
    }

    private int getRandomColor(){
        return r.nextInt()%0xff000000;
    }
    @Override
    public void surfaceCreated(SurfaceHolder arg0) {
        // TODO Auto-generated method stub
        if(mt==null||!mt.isRunning()){
            mt=new MyThread();
            mt.start();
        }
        
    }
    

    @Override
    public void surfaceDestroyed(SurfaceHolder arg0) {
        // TODO Auto-generated method stub
        mt.stopThread();
        
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub
        

        KCList.add(new KCircle(getRandomColor(),(int)event.getX(),(int)event.getY()));
        return true;
    }
    
    class MyThread extends Thread{
        
        private boolean runningTag=true;
        @Override
        public void run() {
            // TODO Auto-generated method stub
            runningTag=true;
            while(runningTag){
            Canvas c=getHolder().lockCanvas();
            if(c!=null){
            c.drawPaint(cp);
            for(int i=0;i<KCList.size();i++){
                
                if(KCList.get(i).isShouldRemove()){
                    KCList.remove(i);
                }else
                    KCList.get(i).drawAndMove(c);
            }
            
            getHolder().unlockCanvasAndPost(c);
            
            }
            
            
            try {
                sleep(15);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            }
            
            Log.i("kagami", "stop");
            
        }
        
        
        public void stopThread(){
            runningTag=false;
        }
        
        public boolean isRunning(){
            return runningTag;
        }
    }
    
    
}
package com.example.sft;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.util.Log;


public class KCircle {
    
    private int color;
    public int x;
    public int y;
    public int z;
    private Paint p;
    private int radius;
    float vx;
    float vy;
    float vz;
    static float ax=0;
    static float ay=0;
    static float az=0;
    
    
    public KCircle(int color){
        this.color=color;
        x=0;
        y=0;
        z=0;
        vx=0;
        vy=0;
        vz=0;
        radius=25;
        p=new Paint();
        p.setColor(color);
        RadialGradient rg=new RadialGradient(x+10, y-10, radius,color+(0xffffffff-color)/2, color, Shader.TileMode.CLAMP);
        
        p.setShader(rg);
        p.setAntiAlias(true);
    }
    
    public KCircle(int colcr,int x,int y){
        this(colcr);
        this.x=x;
        this.y=y;
    }
    
    public void drawAndMove(Canvas c){
        
        draw(c);
        x+=vx;
        y+=vy;
        z+=vz;
        vy+=ay;
        vx+=ax;
        vz+=az;
    }
    
    public void moveTo(int x,int y){
        this.x=x;
        this.y=y;
    }
    
    public void draw(Canvas c){
        RadialGradient rg=new RadialGradient(x+(25+z/100)/2, y-(25+z/100)/2, 25+z/100,0xffdddddd, color, Shader.TileMode.CLAMP);
        p.setShader(rg);
        c.drawCircle(x, y, 25+z/100, p);

    }
    
    public boolean isShouldRemove(){
        if(x<-1000||x>1000||y>1000||y<-1000||(25+z/100)<=0||(25+z/100)>150)
            return true;
        else
            return false;
    }
    

}

上面的图片效果和真实效果有些不同。。。  可能是DDMS的图片抓取机制的问题  看起来有断层,实际是没有的。

原文地址:https://www.cnblogs.com/kagami/p/3011882.html