j2me学习十一_jsr256的应用

 jsr256是感应器的api,现在手机中比较常见是中立感应Sensor,有了这个api之后,我们可以多了很多玩法,这次,我要用它来完成一个利用重力感应控制的小球。
开发环境:javaME Platform SDK3.0(Eclipse存在ClassDefNotFound错误,至今未解决。。。。)
四个java文件,
主midlet,画布,小球,辅助向量。下面是每个类得代码:

主midlet,主要用于控制游戏进度,接受传感器信息

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import javax.microedition.io.Connector;
import java.io.IOException;
import java.util.Vector;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.sensor.ChannelInfo;
import javax.microedition.sensor.Data;
import javax.microedition.sensor.DataListener;
import javax.microedition.sensor.SensorConnection;
import javax.microedition.sensor.SensorInfo;
import javax.microedition.sensor.SensorManager;
/**
 * @author Administrator
 */
public class BallMidlet extends MIDlet  implements DataListener{

    private BallCanvas ballCanvas;
    private SensorConnection sensor;
    private String[] channelNames;
    private boolean sensorSelected;
    private SensorInfo[] sensorInfos;
    public BallMidlet() throws IOException {
        
        if (System.getProperty("microedition.sensor.version") == null) {
            Display.getDisplay(this).setCurrent(
                    new Alert("JSR256 is not supported!"),
                    new TextBox("ERROR", "JSR256 is not supported!", 255, 0));
            return;
            // throw new IllegalArgumentException("JSR256 is not supported!");
        }
        ballCanvas = new BallCanvas();
        sensorInfos = getSensorInfos();
        System.out.println("sensorInfos.length:  "+sensorInfos.length);
        if (sensorInfos == null) {
            Display.getDisplay(this).setCurrent(
                    new Alert("Valid accelerometer sensor not found"),
                    new TextBox("ERROR",
                            "Valid accelerometer sensor not found", 255, 0));
            return;
        }
     
    new Thread() {
                    public void run() {

                        channelNames =
                                getSensorInfoChannelsNames(sensorInfos[0]);

                        try {
                            sensor =
                                    (SensorConnection) Connector
                                            .open(sensorInfos[0].getUrl());
                            ballCanvas.start();
                            sensor.setDataListener(BallMidlet.this, 1);
                            sensorSelected = true;
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
}
                }.start();
    }
private SensorInfo[] getSensorInfos() {
        // Find all device accelerometers
        SensorInfo[] sensorInfos = SensorManager.findSensors("acceleration", null);
        Vector validInfos = new Vector();
        for (int i = 0; i < sensorInfos.length; i++) {
            if (getSensorInfoChannelsNames(sensorInfos[i]).length > 2) {
                validInfos.addElement(sensorInfos[i]);
            }
        }
        SensorInfo[] ret = null;
        if (validInfos.size() > 0) {
            ret = new SensorInfo[validInfos.size()];
            validInfos.copyInto(ret);
        }
        return ret;
    }
private String[] getSensorInfoChannelsNames(SensorInfo sensorInfo) {
        Vector channelNames = new Vector();
        ChannelInfo[] channelInfos = sensorInfo.getChannelInfos();
        // Accelerometer must support at least 3 channels
        if (channelInfos.length > 2) {
            for (int i = 0; i < channelInfos.length; i++) {
                // The channel type must be double
                if (ChannelInfo.TYPE_DOUBLE == channelInfos[i].getDataType()
                        || ChannelInfo.TYPE_INT == channelInfos[i]
                                .getDataType()) {
                    channelNames.addElement(channelInfos[i].getName());
                }
            }
            // We found at least 3 double channels
            if (channelNames.size() > 2) {
                String[] names = new String[3];
                names[0] = (String) channelNames.elementAt(0);
                names[1] = (String) channelNames.elementAt(1);
                names[2] = (String) channelNames.elementAt(2);
                return names;
            }
        }
        return new String[0];
    }
public void dataReceived(SensorConnection sensor, Data[] data,
            boolean isDataLost) {
        double[] accel = new double[3];
        for (int i = 0; i < data.length; i++) {
            for (int c = 0; c < 3; c++) {
                if (channelNames[c].equals(data[i].getChannelInfo().getName())) {
                    double val;
                    switch (data[i].getChannelInfo().getDataType()) {
                    case ChannelInfo.TYPE_DOUBLE:
                        val = data[i].getDoubleValues()[0];
                        break;
                    case ChannelInfo.TYPE_INT:
                        val = data[i].getIntValues()[0];
                        break;
                    default:
                        val = 0;
                    }
                    accel[c] =
                            unscaleValue(val, data[i].getChannelInfo()
                                    .getScale());
                    break;
                }
            }

        }
        ballCanvas.accelerate(accel[0], accel[1], accel[2]);
    }
   private final double unscaleValue(double scaledValue, int scale) {
        double mult = 1.0;
        for (int i = 0; i < Math.abs(scale); i++) {
            mult *= 10.0;
        }
        return (scale > 0) ? scaledValue * mult : scaledValue / mult;
    }
  public void startApp() {
            ballCanvas.resetBoard();   
            Display.getDisplay(BallMidlet.this).setCurrent(ballCanvas);
            //sensor.setDataListener(BallMidlet.this, 1);
             System.out.println("Come here~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
    }

    public void pauseApp() {
        sensor.removeDataListener();
    }

    public void destroyApp(boolean unconditional) {
        if (sensor != null) {
            try {
                sensor.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        notifyDestroyed();
    }
   
}

小球类:

import java.io.IOException;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
public class Ball {

        private Image img;
        private Vector lastPos;
        private Vector pos;
        private Vector speed;
        final static double ROLLING_FRICTION = 0.001;
        private double bounceFriction;
        private double radius;

        public Ball() throws IOException {
            this(0, 0);
        }

        public Ball(double x, double y) throws IOException {
            img = Image.createImage("/black_marble.png");
            pos = new Vector(x, y);
            lastPos = new Vector(x, y);
            speed = new Vector(0, 0);
            radius = img.getWidth() / 2.0;
            bounceFriction = 0.5;
        }

        public void resetPosition(double x, double y) {
            speed = new Vector(0, 0);
            pos.setX(x - getRadius());
            pos.setY(y - getRadius());
        }

        public void paint(Graphics g) {
            lastPos = new Vector(pos);
            g.drawImage(img, (int) pos.getX(), (int) pos.getY(),
                    Graphics.HCENTER | Graphics.VCENTER);
        }

        public void clear(Graphics g) {
            g.setColor(0xbbbbff);
            g.fillRect((int) (lastPos.getX() - getRadius()), (int) (lastPos
                    .getY() - getRadius()), (int) (getRadius() * 2),
                    (int) (getRadius() * 2));
        }

        public void accelerate(double accelX, double accelY, double accelZ) {
            double frictionF = (Math.max(0, accelZ) * ROLLING_FRICTION * 2);
            speed.add(accelX, accelY);
            if (frictionF > 0 && speed.getLen2() > 0) {
                Vector friction = speed.inv().norm().mul(Math.sqrt(frictionF));
                speed.add(friction);
            }
        }

        public void calcNewPosition() {
            pos.add(speed);
        }

        public double getRadius() {
            return radius;
        }

        public void collideBorders(Canvas canvas) {
            Vector newPos = Vector.add(pos, speed);
            if (newPos.getY() - getRadius() < 0) {
                speed.setY(speed.getY() * (bounceFriction - 1));
                pos.setY(getRadius());
            } else if (newPos.getY() + getRadius() > canvas.getHeight()) {
                speed.setY(speed.getY() * (bounceFriction - 1));
                pos.setY(canvas.getHeight() - getRadius());
            }
            if (newPos.getX() - getRadius() < 0) {
                speed.setX(speed.getX() * (bounceFriction - 1));
                pos.setX(getRadius());
            } else if (newPos.getX() + getRadius() > canvas.getWidth()) {
                speed.setX(speed.getX() * (bounceFriction - 1));
                pos.setX(canvas.getWidth() - getRadius());
            }
        }

}

主Canvas,继承的是Canvas,实现Runnable接口

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Administrator
 */
import java.io.IOException;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
public class BallCanvas extends Canvas implements Runnable {
      private static final double PPCM = 80 * 100; // pixels per meter
    public static final long TICK_SLEEP_MILLIS = 5;
    /**
     * Marble mass in kg. This demo is optimized for marbles with equal masses.
     */
    final static double MARBLE_MASS = 0.000742179;

    /**
     * Multipliers convert m/s^2 to pixel/tick^2.
     */
    private final double accelMultX;
    private final double accelMultY;
    private final double accelMultZ;

    private Ball ball;
    private volatile boolean stop;

    private double accelX;
    private double accelY;
    private double accelZ;
    volatile boolean firstPaint = true;
        public BallCanvas() throws IOException {
       
        // Tick cycles per s^2
         setFullScreenMode(true);
        double d = (1000 / TICK_SLEEP_MILLIS) * (1000 / TICK_SLEEP_MILLIS);
        accelMultX = -1.0 * PPCM / d;
        accelMultY = 1.0 * PPCM / d;
        accelMultZ = -1.0 * PPCM / d;

        ball = new Ball();
    }
    public synchronized void resetBoard() {
        accelX = 0;
        accelY = 0;
        ball.resetPosition(getWidth() * 0.5, getHeight() * 0.5);
        firstPaint = true;
    }

    public void start() {
        stop = false;
        resetBoard();
         System.out.println("this.isDoubleBuffered()~~~~~~~~~~~~~~~~~~~~~~~~~~~~"+this.isDoubleBuffered());
        new Thread(this).start();
    }

    public void stop() {
        stop = true;
    }

    public void run() {
        long st=0,et=0,diff=0;
        int rate=50;//16-17 frame per second
            while (!stop)
            {
                st=System.currentTimeMillis();
                calculatePositions();
                repaint();
                et=System.currentTimeMillis();
                diff=et-st;
                if(diff<rate){
        //System.out.println("Sleep "+(rate-diff));
        try {
          Thread.sleep(rate - diff);
        }
        catch (InterruptedException ex) {}

        }
        }
       
       
    }
    public void paint(Graphics g) {
        if (firstPaint) {
            g.setColor(0xbbbbff);
            g.fillRect(0, 0, getWidth(), getHeight());
            firstPaint = false;
        }
            ball.clear(g);
            ball.paint(g);
    }
    private static final int SMOOTH_CNT = 2;
    double avgX[] = new double[SMOOTH_CNT];
    double avgY[] = new double[SMOOTH_CNT];
    double avgZ[] = new double[SMOOTH_CNT];
    public synchronized void accelerate(double x, double y, double z) {
        double xx = x;
        double yy = y;
        double zz = z;
        for (int i = 0; i < avgX.length - 1; i++) {
            xx += avgX[i];
            yy += avgY[i];
            zz += avgZ[i];
            avgX[i] = avgX[i + 1];
            avgY[i] = avgY[i + 1];
            avgZ[i] = avgZ[i + 1];
        }
        avgX[avgX.length - 1] = x;
        avgY[avgY.length - 1] = y;
        avgZ[avgZ.length - 1] = z;
        xx /= avgX.length + 1;
        yy /= avgY.length + 1;
        zz /= avgZ.length + 1;

        accelX = xx * accelMultX;
        accelY = yy * accelMultY;
        accelZ = zz * accelMultZ;
    }
        private synchronized void calculatePositions() {
           ball.accelerate(accelX, accelY, accelZ);
           System.out.println("calculatePositions~~~~~~~~~~~~~~~~");
            ball.collideBorders(this);
           ball.calcNewPosition();

    }
}

向量类,类似辅助计算:

public class Vector {

    private double x;
    private double y;

    public Vector(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public Vector(Vector v) {
        this(v.getX(), v.getY());
    }

    public static Vector add(Vector a, Vector b) {
        return new Vector(a.getX() + b.getX(), a.getY() + b.getY());
    }

    public static Vector mul(Vector v, double d) {
        return new Vector(v.getX() * d, v.getY() * d);
    }

    public static double dot(Vector a, Vector b) {
        return a.getX() * b.getX() + a.getY() * b.getY();
    }

    public static Vector sub(Vector v1, Vector v2) {
        return new Vector(v1.getX() - v2.getX(), v1.getY() - v2.getY());
    }

    public Vector inv() {
        return new Vector(getX() * -1.0, getY() * -1.0);
    }

    public Vector norm() {
        double l = Math.sqrt(getX() * getX() + getY() * getY());
        return new Vector(getX() / l, getY() / l);
    }

    public double getY() {
        return y;
    }

    public double getX() {
        return x;
    }

    public Vector mul(double d) {
        return new Vector(getX() * d, getY() * d);
    }

    public void add(Vector vector) {
        add(vector.x, vector.y);
    }

    public void add(double d) {
        add(d, d);
    }

    public void add(double x, double y) {
        this.x += x;
        this.y += y;
    }

    public void setX(double x) {
        this.x = x;
    }

    public void setY(double y) {
        this.y = y;
    }

    public double getLen2() {
        return getX() * getX() + getY() * getY();
    }

    public double getLen() {
        return Math.sqrt(getLen2());
    }

    public String toString() {
        return "[" + getX() + ";" + getY() + "]";
    }
}

 

你可能感兴趣的:(vector,String,null,j2me,textbox,templates)