サンプルプログラム工場

AAKAKA Appで使われているプログラムのサンプルコードをそのまま公開!

サンプルプログラム工場 > android > GLSurfaceViewで画像をスライドするサンプル#tryGLES2005
Google Play AAKAKAxSOFTへ

GLSurfaceViewで画像をスライドするサンプル#tryGLES2005

実行ファイル(APK)やサンプル(zip)をダウンロードする
tryGLES2005の実行イメージtryGLES2005の実行イメージ

XMLレイアウト内に埋め込んだ拡張したGLSurfaceViewを使ってフリックすると画像がスライドする様にする。
GLSurfaceViewにタッチ処理埋め込む。
SurfaceView版はできたけどフレームレートが安定しないのでこちらで再挑戦。
ただし、VBOを使うのでAndroindのバージョンは2.3.3からになる。そこはちょっと惜しい。

大事なところ
 main.xmlに追加したGLSurfaceViewをカスタマイズしたGLSurfaceViewに置き換える
  例えばtrial.sample.trygles2005.GLSurfaceViewExtの様に。
 カスタマイズしたGLSurfaceViewのコンストラクタは3種類とも用意する。
 画像のファイル名に大文字は使えない trySurfaceView00GB.pngとかはだめ
  try_surface_view_00_bg.pngとかにする(小文字の0-9とa-zに_.だけ使える)
 画像の解像度を2の累乗にしないと、エラーは出ないのに表示はされないのでハマル。
 VBOを使っているのでAndroidのバージョンは2.3.3以上が必要。
 2.1で同じ事しようと思ったらC言語でちょこっと作らないといけない部分がある。

検索した事
 Android GLES20 テクスチャを貼り付ける
 GLES20.glUniform1i テクスチャ
 GLES20 テクスチャ解像度

開発環境
 Eclipse IDE バージョン: 3.7 Indigo Service Release 2
 ターゲットプラットフォーム: 2.3.3
 API レベル: 10

package trial.sample.trygles2005;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;




import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.os.Bundle;
import android.test.suitebuilder.annotation.Smoke;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.View.OnTouchListener;

public class TryGLES2005Activity extends Activity {
    @Override
	protected void onPause() {
		// TODO 自動生成されたメソッド・スタブ
		super.onPause();
	}

	@Override
	protected void onResume() {
		// TODO 自動生成されたメソッド・スタブ
		super.onResume();
	}

	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}




// ////////////////////////////////////////////////////////////
// GLSurfaceViewの拡張
class GLSurfaceViewExt extends GLSurfaceView implements GestureDetector.OnGestureListener, OnTouchListener {

	private GestureDetector	mGestureDetector;
	private GLSurfaceViewExtRenderer mRenderer;
	public GLSurfaceViewExt(Context context, AttributeSet attrs) {
		super(context, attrs);

		this.initGLSurfaceView(context);
	}

	public GLSurfaceViewExt(Context context) {
		super(context);

		this.initGLSurfaceView(context);
	}

	public void initGLSurfaceView(Context contex) {
		this.setEGLContextClientVersion(2);
		// レンダラ―の設定
		this.mRenderer = new GLSurfaceViewExtRenderer(contex);
		this.setRenderer(this.mRenderer);
		// これがないとGestureDetectorが動かないよ!
		this.setClickable(true);
		// タッチリスナーをセットする
		this.setOnTouchListener(this);
		// ジェスチャー処理
		this.mGestureDetector = new GestureDetector(this);
	}
	
	// ////////////////////////////////////////////////////////////
	// タッチされた
	public boolean onTouch(View view, MotionEvent ev) {
		return this.mGestureDetector.onTouchEvent(ev);
	}

// ////////////////////////////////////////////////////////////
// Detector
// ////////////////////////////////////////////////////////////
	public boolean onDown(MotionEvent arg0) {
		// TODO 自動生成されたメソッド・スタブ
		return false;
	}

	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		
		this.mRenderer.setBoxVelocity(-(velocityX / 16000.0f));
		return false;
	}

	public void onLongPress(MotionEvent arg0) {
		// TODO 自動生成されたメソッド・スタブ
		
	}

	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		// TODO 自動生成されたメソッド・スタブ
		return false;
	}

	public void onShowPress(MotionEvent e) {
		// TODO 自動生成されたメソッド・スタブ
		
	}

	public boolean onSingleTapUp(MotionEvent e) {
		// TODO 自動生成されたメソッド・スタブ
		return false;
	}
}




// ////////////////////////////////////////////////////////////
// レンダラー
class GLSurfaceViewExtRenderer implements GLSurfaceView.Renderer {

	private Context mContext;
	private ValueSlot	mValueSlot;
	
	// 頂点内容のインデックス をこちらから指定する
	public static final int ATTRIBUTE_POSITION_LOCATION = 0;
	public static final int ATTRIBUTE_COLOR_LOCATION = 1;
	public static final int ATTRIBUTE_UV0_LOCATION = 2;
	public static final String ATTRIBUTE_POSITION = "a_position";
	public static final String ATTRIBUTE_COLOR = "a_color";
	public static final String ATTRIBUTE_UV0 = "a_uv";
	
	public static final String UNIFORM_MODELVIEWMATRIX = "u_modelViewMatrix";
	public static final String UNIFORM_PROJECTIONMATRIX = "u_projectionMatrix";
	public static final String UNIFORM_COLOR = "u_color";
	public static final String UNIFORM_TEXTURE0 = "u_texture0";
	public static final String VARYING_COLOR = "v_color";
	public static final String VARYING_UV0 = "v_uv0";

	private float mAspect;	// アスペクト比
	private float mModelRot; // モデルの回転

	// 描画するためのもの
	private int mVertexShaderID;	// 頂点シェーダーID
	private int mFragmentShaderID;	// フラグメントシェーダーID
	private int mProgramID; // プログラムオブジェクトID

	// シェーダーに値を送るためのハンドル
	private int mLocModelView;
	private int mLocProj;
	private int mLocColor;	// 色
	private int mLocTexture;	// テクスチャ

	// VBO の管理番号
	private int mVertexBufferID; // 頂点バッファ
	private int mIndexBufferID; // インデックスバッファ


	// 各行列
	private float[] mModelView = new float[16];	// モデルビュー
	private float[] mProj = new float[16];	// プロジェクション
	
	// テクスチャ
	private int[] mTextureIdList = new int[8];

	// ////////////////////////////////////////////////////////////
	// コンストラクタ
	public GLSurfaceViewExtRenderer(final Context context) {
		this.mContext = context;
	}

	
	public void setBoxVelocity(float vel) {
		this.mValueSlot.setVelocity(vel);
	}
	
	
	///////////////////////////////////////////////////////////////////////////
	/** 最初に呼ばれる */
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {

		// シェーダーを初期化する
		this.initShader();

		// こちから指定した 頂点内容のインデックス を有効にする
		// 頂点配列を有効にする
		GLES20.glEnableVertexAttribArray(ATTRIBUTE_POSITION_LOCATION);
		// 頂点カラー を有効にする
		//GLES20.glEnableVertexAttribArray(ATTRIBUTE_COLOR_LOCATION);
		// テクスチャ座標を有効にする
		GLES20.glEnableVertexAttribArray(ATTRIBUTE_UV0_LOCATION);

		// デプスバッファを有効にする
		GLES20.glEnable(GLES20.GL_DEPTH_TEST);
		GLES20.glEnable(GLES20.GL_TEXTURE_2D);
		
        
		// VBO を初期化する
		this.initVBO();
		
		// テクスチャを全部ロードする
		this.loadAllTextures();
		
		this.mValueSlot = new ValueSlot();
		this.mValueSlot.setMaxValue(10);
	}

	private void loadAllTextures() {
		this.mTextureIdList[0] = this.loadTexture(R.drawable.try_gles2005_img00);
		this.mTextureIdList[1] = this.loadTexture(R.drawable.try_gles2005_img01);
		this.mTextureIdList[2] = this.loadTexture(R.drawable.try_gles2005_img02);
		this.mTextureIdList[3] = this.loadTexture(R.drawable.try_gles2005_img03);
		this.mTextureIdList[4] = this.loadTexture(R.drawable.try_gles2005_img04);
		this.mTextureIdList[5] = this.loadTexture(R.drawable.try_gles2005_img05);
		this.mTextureIdList[6] = this.loadTexture(R.drawable.try_gles2005_img06);
		this.mTextureIdList[7] = this.loadTexture(R.drawable.try_gles2005_img07);
	}
	
	// ////////////////////////////////////////////////////////////
	// テクスチャをロードする
	private int loadTexture(int id) {
		int[] texId = {-1};
		GLES20.glGenTextures(1, texId, 0);
		GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
		GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId[0]);

		// Bitmapのロード(glBindTextureのものに関連づけられる)
		final Bitmap bitmap = BitmapFactory.decodeResource(this.mContext.getResources(), id);
		int w = bitmap.getWidth();
		int h = bitmap.getHeight();
		GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
		//テクスチャフィルタの指定
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
            GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
            GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
		
		bitmap.recycle();

		return texId[0];
	}
	
	
	// /////////////////////////////////////////////////////////////////////////
	// VBOを登録する
	private void initVBO() {

		// 頂点座標 + 頂点カラー
		// 頂点バッファから VBO を作る
		float[] vertices = {
				// 座標(x, y, z)  UV0
				-0.5f,  0.5f,  0.0f, 0.0f, 0.0f,
				-0.5f, -0.5f,  0.0f, 0.0f, 0.888f,
				 0.5f,  0.5f,  0.0f, 1.0f, 0.0f,
				 0.5f, -0.5f,  0.0f, 1.0f, 0.888f,
		};
		FloatBuffer vertexBuffer = this.makeFloatBuffer(vertices);
		// 頂点データ(座標、法線、色、テクスチャ座標)には
		// GL_ARRAY_BUFFERを指定する
		this.mVertexBufferID = this.makeVBO(
				vertexBuffer, 4, GLES20.GL_ARRAY_BUFFER);
		
		// インデックスバッファから VBO を作る
		byte[] indices = {
				0,1,2,3,
		};
		ByteBuffer indexBuffer = this.makeByteBuffer(indices);
		// インデックスの登録には
		// GL_ELEMENT_ARRAY_BUFFERを使う
		this.mIndexBufferID = this.makeVBO(
				indexBuffer, 1, GLES20.GL_ELEMENT_ARRAY_BUFFER);
	}

	// /////////////////////////////////////////////////////////////////////////
	// 各バッファから VBO へ変換する
	private int makeVBO(Buffer buffer, int size, int target) {

		int[] hardwareIDContainer= { -1 };

		// ハードウェア側の準備
		GLES20.glGenBuffers(1, hardwareIDContainer, 0);
		GLES20.glBindBuffer(target, 
				hardwareIDContainer[0]);
		GLES20.glBufferData(target,
				buffer.capacity() * size, buffer, GLES20.GL_STATIC_DRAW);

		return hardwareIDContainer[0];
	}

	// /////////////////////////////////////////////////////////////////////////
	// シェーダーを初期化する
	private void initShader() {
		// 頂点カラー 付き頂点シェーダーのコンパイル
		String vertexCode = 
				"uniform mat4  " + UNIFORM_MODELVIEWMATRIX + ";"+    
				"uniform mat4 " + UNIFORM_PROJECTIONMATRIX + ";"+
				"uniform vec4 " + UNIFORM_COLOR + ";" +
				"attribute vec4 " + ATTRIBUTE_POSITION + ";"+
				"attribute vec2 " + ATTRIBUTE_UV0 + ";"+
				"varying vec4 " + VARYING_COLOR + ";" +
				"varying vec2 " + VARYING_UV0 + ";" +
				"void main(){"+       
				"    gl_Position = " + UNIFORM_PROJECTIONMATRIX + " * " + UNIFORM_MODELVIEWMATRIX + " * " + ATTRIBUTE_POSITION + ";"+  
				"    " + VARYING_COLOR + " = " + UNIFORM_COLOR + ";" +
				"    " + VARYING_UV0 + " = " + ATTRIBUTE_UV0 + ";" +
				"}";
		this.mVertexShaderID = this.compileShader(
				GLES20.GL_VERTEX_SHADER, vertexCode);

		// 頂点カラー 付きフラグメントシェーダーのコンパイル
		String fragmentCode = 
				"precision mediump float;"+
				"uniform sampler2D " + UNIFORM_TEXTURE0 + ";\n" +
				"varying vec4  " + VARYING_COLOR + ";" +
				"varying mediump vec2  " + VARYING_UV0 + ";" +
				"void main(){"+
				"    gl_FragColor = texture2D(" + UNIFORM_TEXTURE0 + ", " + VARYING_UV0 + ");" + 
				"}";
		this.mFragmentShaderID = this.compileShader(
				GLES20.GL_FRAGMENT_SHADER, fragmentCode);

		// プログラムオブジェクトを作る
		this.mProgramID = GLES20.glCreateProgram();
		GLES20.glAttachShader(this.mProgramID, this.mVertexShaderID);
		GLES20.glAttachShader(this.mProgramID, this.mFragmentShaderID);

		// 頂点内容のインデックス をシェーダー変数と関連付ける
		GLES20.glBindAttribLocation(this.mProgramID, ATTRIBUTE_POSITION_LOCATION, ATTRIBUTE_POSITION);
		GLES20.glBindAttribLocation(this.mProgramID, ATTRIBUTE_UV0_LOCATION, ATTRIBUTE_UV0);
		//GLES20.glEnableVertexAttribArray(ATTRIBUTE_POSITION_LOCATION);
		//GLES20.glEnableVertexAttribArray(ATTRIBUTE_UV0_LOCATION);


		GLES20.glLinkProgram(this.mProgramID);

		// シェーダーに値を送るためのハンドルを取り出す
		this.mLocModelView = GLES20.glGetUniformLocation(
				this.mProgramID, UNIFORM_MODELVIEWMATRIX);
		this.mLocProj = GLES20.glGetUniformLocation(
				this.mProgramID, UNIFORM_PROJECTIONMATRIX);
		this.mLocColor = GLES20.glGetUniformLocation(
				this.mProgramID, UNIFORM_COLOR);
		this.mLocTexture = GLES20.glGetUniformLocation(
				this.mProgramID, UNIFORM_TEXTURE0);

		// プログラムオブジェクトを使い始める
		GLES20.glUseProgram(this.mProgramID);
	}


	///////////////////////////////////////////////////////////////////////////
	/** サーフェイスのサイズ変更時とかに呼ばれる */
	public void onSurfaceChanged(GL10 gl, int width, int height) {

		// ビューポートの再設定
		GLES20.glViewport(0, 0, width, height);

		// アスペクト比
		this.mAspect = (float)width / (float)height;
	}

	// ////////////////////////////////////////////////////////////
	// 
	public void drawSquare(float[] mv, float x, float y, float z, int texture) {

		float[] m = {
				1.2f, 0, 0, 0,
				0, 2, 0, 0,
				0, 0, 1, 0,
				x, y, z, 1,
		};
		Matrix.multiplyMM(m, 0, mv, 0, m, 0);
		
		// シェーダーにモデルビュー行列を送信
		GLES20.glUniformMatrix4fv(this.mLocModelView, 1, false, m, 0);
		
		GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
		GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
		GLES20.glUniform1i(this.mLocTexture, 0);

		// 面を描く
		GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, 4,
				GLES20.GL_UNSIGNED_BYTE, 0);

	}

	///////////////////////////////////////////////////////////////////////////
	/** マイフレーム呼ばれるやつ */
	public void onDrawFrame(GL10 gl) {
		
		this.mValueSlot.frameMove();
		
		// 画面をクリア
		GLES20.glClearColor(0.4f, 0.4f, 0.4f, 1.f);
		GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

		// プロジェクション行列
		Matrix.setIdentityM(this.mProj, 0);
		this.Perspective(this.mProj, 45.f, this.mAspect, 1.0f, 100.f);
		// シェーダーに送信
		GLES20.glUniformMatrix4fv(this.mLocProj, 1, false, this.mProj, 0);


		// ビュー行列
		Matrix.setIdentityM(this.mModelView, 0);
		Matrix.setLookAtM(this.mModelView, 0,
				0.0f, 0.0f, 1.0f,
				0.0f, 0.0f, 0.0f,
				0.0f, 1.0f, 0.0f);


		// VBO での描画
		// 頂点バッファのセット
		GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.mVertexBufferID);
		
		// 頂点内容のインデックス で、各値の場所を指定する
		int vertexSize = 4 * 5;	// 4バイトが5つ
		GLES20.glVertexAttribPointer(ATTRIBUTE_POSITION_LOCATION, 3, GLES20.GL_FLOAT, false, vertexSize, 0);
		GLES20.glVertexAttribPointer(ATTRIBUTE_UV0_LOCATION, 2, GLES20.GL_FLOAT, false, vertexSize, 4 * 3);


		// インデックスバッファの指定
		GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.mIndexBufferID);


		
		float sliderCursor = this.mValueSlot.getCursor();
		int boxCount = this.mValueSlot.getBoxCount();

		// 中心のボックスの番号を取り出す
		int mainBoxNo = (int)(sliderCursor);
		if (mainBoxNo < 0)
			mainBoxNo += boxCount;
		if (boxCount <= mainBoxNo)
			mainBoxNo -= boxCount;
		float slideValue = (sliderCursor - mainBoxNo) * 1.2f;

		// 左側に来るボックスのインデックスを取り出す
		int leftBoxNo = mainBoxNo - 1;
		if (leftBoxNo < 0)
			leftBoxNo += boxCount;
		// 右側に来るボックスを取り出す
		int rightBoxNo = mainBoxNo + 1;
		if (boxCount <= rightBoxNo) {
			rightBoxNo -= boxCount;
		}

		// 適当にスケールしないと画面サイズいっぱいにならないから
		float boxWidth = 1.2f;
		float center = boxWidth / 2.0f;
		// 四角形を書く
		try {
			this.drawSquare(this.mModelView, -slideValue - boxWidth + center, 0.f, 0.f, this.mTextureIdList[leftBoxNo % 8]);
			this.drawSquare(this.mModelView, -slideValue + center, 0.f, 0.f, this.mTextureIdList[mainBoxNo % 8]);
			this.drawSquare(this.mModelView, -slideValue + boxWidth + center, 0.f, 0.f, this.mTextureIdList[rightBoxNo % 8]);
			
		} catch (Exception e) {
			Log.e("表示ミス", e.getMessage());
		}
		
	}


	// /////////////////////////////////////////////////////////////////////////
	// プロジェクション行列を作る
	private void Perspective(float[] out, float fov, float aspect, 
			float near, float far) {
		float top = near * (float)Math.tan(Math.toRadians(fov));
		float bottom = -top;
		float left = bottom * aspect;
		float right = top * aspect;
		Matrix.frustumM(out, 0, left, right, bottom, top, near, far);
	}



	///////////////////////////////////////////////////////////////////////////
	// FloatBufferを作って値をセットする
	private FloatBuffer makeFloatBuffer(float[] values) {
		// バッファを作る
		FloatBuffer fb = ByteBuffer.allocateDirect(values.length * 4)
				.order(ByteOrder.nativeOrder())
				.asFloatBuffer();
		// 作ったバッファに値をセットしておく
		fb.put(values)
		.position(0);
		return fb;
	}


	///////////////////////////////////////////////////////////////////////////
	// ByteBufferを作って値をセットする
	private ByteBuffer makeByteBuffer(byte[] values) {
		ByteBuffer buf = ByteBuffer.allocateDirect(values.length)
				.order(ByteOrder.nativeOrder());
		buf.put(values)
		.position(0);
		return buf;
	}


	///////////////////////////////////////////////////////////////////////////
	// シェーダーのソースコードをコンパイルする
	private int compileShader(int type, String code) {
		final int shaderId = GLES20.glCreateShader(type);
		if (shaderId == 0) {
			// シェーダーの領域確保に失敗した
			Log.d("compileShader", "領域確保に失敗");
			return -1;
		}
		// シェーダーをコンパイル
		GLES20.glShaderSource(shaderId, code);
		GLES20.glCompileShader(shaderId);

		// コンパイルが成功したか調べる
		int[] res = new int[1];
		GLES20.glGetShaderiv(shaderId, GLES20.GL_COMPILE_STATUS, res, 0);
		if (res[0] == 0) {
			// 失敗してる
			Log.d("compileShader", GLES20.glGetShaderInfoLog(shaderId));
			return -1;
		}
		return shaderId;
	}
}







// ////////////////////////////////////////////////////////////
// 値をスロットの様に回転させる
class ValueSlot {
	
	public enum SliderState {
		SLIDER_STOP,	// 停止中
		SLIDER_MOVE,	// 値の開店中
		SLIDER_SNAP,	// 一番近い値の中心にスナップする
	}
	
	private float mCursor;	// 今の場所的
	private float mVelocity;	// 速度
	private float mBoxW;	// ボックスの幅
	private int mMaxValue;	// スライダー
	private SliderState mSliderState;	// 今のスライダーの状態
	private float mSnapPos;	// スナップする位置
	
	
	// ////////////////////////////////////////////////////////////
	// コンストラクタ
	ValueSlot() {
		this.mBoxW = 1.0f;
		this.mMaxValue = 1;
		this.mCursor = this.mBoxW / 2.0f;
		this.mVelocity = 0.0f;
		this.mSliderState = SliderState.SLIDER_STOP;
	}
	
	// ////////////////////////////////////////////////////////////
	// スライダーの最大値をセットする
	public void setMaxValue(int value) {
		this.mMaxValue = value;
	}
	
	// ////////////////////////////////////////////////////////////
	// 速度を設定する
	public void setVelocity(float speed) {
		this.mVelocity = speed;
		this.mSliderState = SliderState.SLIDER_MOVE;
	}
	
	// ////////////////////////////////////////////////////////////
	// カーソル位置を取り出す
	public float getCursor() {
		// 範囲内で値を回転させる
		return this.roundValue(this.mCursor);
	}
	
	// ////////////////////////////////////////////////////////////
	// BOXの数を返す
	public int getBoxCount() {
		return this.mMaxValue;
	}
	
	
	// ////////////////////////////////////////////////////////////
	// 値を範囲内で回転させる(0以下ならmaxValue以下に変換、maxValue以上なら0以上に変換)
	private float roundValue(float currValue) {
		// スクリーンがすべてマイナス範囲に入っているときは右端にカーソルを移動させる
		if (currValue < 0) {
			return currValue + this.mMaxValue;
		
		// スクリーンが全部の画像のサイズを合わせた位置より大きくなってる場合は左端に戻す
		} else if (this.mMaxValue < this.mCursor) {
			return currValue - this.mMaxValue;
		}
		return currValue;
	}
	
	// ////////////////////////////////////////////////////////////
	// 更新処理
	void frameMove() {

		// スライダーの状態によって処理分ける
		switch (this.mSliderState) {
		case SLIDER_STOP:
			{
				// 範囲内で値を回転させる
				this.mCursor = this.roundValue(this.mCursor);
			}
			break;
		case SLIDER_MOVE:
			{
				// カーソルを移動させる
				this.mCursor += this.mVelocity;
				this.mVelocity *= 0.99f;
				
				// スナップ開始まで速度が落ちていた
				if (Math.abs(this.mVelocity) < 0.01f) {
					
					float center = this.mBoxW / 2.0f;
					float nearSnapLeft = 0.0f;
					float nearSnapRight = 0.0f;
					
					// マイナスにいってしまっている(-1.0-0.0の間でスナップする様に)
					if (this.mCursor < 0.f) {
						nearSnapLeft = -this.mBoxW + center;
						nearSnapRight = center;
					} else {
						nearSnapLeft = ((int)(this.mCursor / this.mBoxW)) * this.mBoxW + center;
						nearSnapRight = (int)((this.mCursor / this.mBoxW) + 1) * this.mBoxW + center;
					}
					
					// 近い方へスナップする
					if (Math.abs(nearSnapLeft - this.mCursor) < Math.abs(nearSnapRight - this.mCursor)) {
						this.mSnapPos = nearSnapLeft;
					} else {
						this.mSnapPos = nearSnapRight;
					}
					
					// スナップ速度を設定
					this.mVelocity += (this.mSnapPos - this.mCursor) / 40;
					
					// スナップへ移動する
					this.mSliderState = SliderState.SLIDER_SNAP;
				} else {
					// 値を回転させる
					this.mCursor = this.roundValue(this.mCursor);
				}
			}
			break;
		case SLIDER_SNAP:
			{
				// カーソルを移動させる
				this.mCursor += this.mVelocity;
				this.mVelocity *= 0.94f;
				
				// 速度を作る
				this.mVelocity += (this.mSnapPos - this.mCursor) / 40;

				// ほとんど動かなくなったらぴったりくっつけて終了
				if (Math.abs(this.mVelocity) < 0.002f && Math.abs(this.mSnapPos - this.mCursor) < 0.002f) {
					this.mCursor = this.mSnapPos;
					this.mVelocity = 0.0f;
					this.mSliderState = SliderState.SLIDER_STOP;
				}
			}
			break;
		}
	}
}
サンプルプロジェクトをダウンロード APKファイルをダウンロード

, , , , ,

画像をスライドするサンプル#trySurfaceView01 プリファレンス(Preferences)でデータの読み込み、保存#tryPreferences00

2 Responses to “GLSurfaceViewで画像をスライドするサンプル#tryGLES2005”

  • 山崎 より:


    実行ファイル(APK)やサンプル(zip)をダウンロードしたいのですが、
    やり方がわかりませんでした。

  • 山崎 より:


    ダウンロードできました。
    コメントの上のバナーをクリックですね。

    ありがとうございます。^^

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です


*

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>