以前写过一个立方体的主界面,感觉酷酷的,现在分享给大家,效果是这样子的(截图):
因为当初做的时候要求只能左右滚动,好让立方体图片正的显示出来,所以我把随手势滑动改成左右滑动,每次显示3个面,每个面都可以点击,中间高亮,这样你就可以选择某个面进入你的页面。
废话少活,来看下项目和代码吧:
项目很简单就一个自定义view,一个判断滑动的java文件,然后剩下三个只是为了传值用的观察者模式,你嫌麻烦的话可以直接用handle。
一、先将jpct-ae.jar 复制到libs,右键add as lib那个。
jpce-ae地址:http://www.jpct.net/jpct-ae/
来看一下代码:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.cube.MainActivity">
<com.example.cube.Cube
android:id="@+id/cube"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:background="#000"/>
</RelativeLayout>
xml没什么好说的就是一个自定义view。
mainActivity.java:
package com.example.cube;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements CubeObserverListener{
private Cube cube;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_main);
cube = (Cube) findViewById(R.id.cube);
CubeObserverManager.getInstance().add(this);
}
@Override
public void sendMsg(int msg) {
switch (msg) {
case 1:
Toast.makeText(getApplicationContext(), "点击数学", Toast.LENGTH_SHORT).show();
break;
case 2:
Toast.makeText(getApplicationContext(), "点击主页", Toast.LENGTH_SHORT).show();
break;
case 3:
Toast.makeText(getApplicationContext(), "点击消息", Toast.LENGTH_SHORT).show();
break;
case 4:
Toast.makeText(getApplicationContext(), "点击历史", Toast.LENGTH_SHORT).show();
break;
case 5:
Toast.makeText(getApplicationContext(), "点击语文", Toast.LENGTH_SHORT).show();
break;
case 6:
Toast.makeText(getApplicationContext(), "点击设置", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
}
就是用了观察者模式判断了点击了立方体哪个面做了处理。
主要看一下Render.java和Cube.java这两个
Render.java:
package com.example.cube;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;
import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Interact2D;
import com.threed.jpct.Light;
import com.threed.jpct.Matrix;
import com.threed.jpct.Object3D;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.BitmapHelper;
import com.threed.jpct.util.MemoryHelper;
public class Rander implements Renderer{
public MainActivity mActivity = null;
private FrameBuffer fb = null;
private World world = null;
Camera cam = null;
// 立方体
public Object3D cube = null;
private Object3D a,b,c,d,e,f;
// 光照类
private Light sun = null;
private RGBColor back = new RGBColor(255,228,196);
// 旋转
public float touchTurn = 0.28f;
public float touchTurnUp = 0.9f;
public float touchTurnRight = 3.8f;
public boolean isRotate = false;
public String gride = "none";
public Rander(Context context) {
mActivity = (MainActivity) context;
}
float m = 0.1f;
public boolean isTranslation = false;
public Matrix m1,m2;
int first = 0;
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
if(Cube.isStart){
long nowTime = System.currentTimeMillis();
long deltaTime = nowTime - Cube.startTime;
long animationInterval=600;
if(deltaTime>=animationInterval-30 ){
if(!isTranslation){
cube.setRotationMatrix(m2);
isTranslation = true;
}else{
cube.setRotationMatrix(m1);
isTranslation = false;
}
Cube.isStart=false;
}else{
float deltaAngle = 0;
if(gride == "left"){
deltaAngle=(float) ((float)((float)deltaTime/animationInterval)*(double)Math.PI);
}else{
deltaAngle=(float) -((float)((float)deltaTime/animationInterval)*(double)Math.PI);
}
Matrix toMatrix = Cube.startRotationMatrix.cloneMatrix();
toMatrix.rotateY(deltaAngle);
cube.setRotationMatrix(toMatrix);
}
}
fb.clear(back);
world.renderScene(fb);
world.draw(fb);
fb.display();
}
@Override
public void onSurfaceChanged(GL10 gl, int w, int h) {
// TODO Auto-generated method stub
if (fb != null) {
fb.dispose();
}
// 创建一个宽度为w,高为h的FrameBuffer
fb = new FrameBuffer(gl, w, h);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
world = new World();
world.setAmbientLight(150, 150, 150); //内部光源
sun = new Light(world);
sun.setIntensity(255, 255, 255);
sun.setPosition( GetPoint( 0, 0, -150));
sun.setDiscardDistance( 500);
// 纹理
CreateTextures();
// 立方体
CreateBox();
// 摄像机
cam = world.getCamera();
cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
cam.lookAt(cube.getTransformedCenter());
SimpleVector sv = new SimpleVector();
sv.set(cube.getTransformedCenter());
sv.x = -1.0f;//外部光源
sv.y = 1.2f;
sv.z = -18;
sun.setPosition(sv);
MemoryHelper.compact();
Roate();
}
private void Roate() {
// TODO Auto-generated method stub
cube.rotateY(touchTurn);
cube.rotateX(touchTurnUp);
cube.rotateZ(touchTurnRight);
m1 = cube.getRotationMatrix();
m2 = m1.cloneMatrix();
m2.rotateY((float)Math.PI);
}
private SimpleVector GetPoint(int i, int j, int k) {
// TODO Auto-generated method stub
SimpleVector sv = new SimpleVector();
sv.x = i;
sv.y = j;
sv.z = k;
return sv;
}
/**
* 创建纹理
*/
private void CreateTextures() {
Texture texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mActivity.getResources().getDrawable(R.drawable.f)), 128, 128));
TextureManager.getInstance().addTexture("a", texture);
texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mActivity.getResources().getDrawable(R.drawable.a)), 128, 128));
TextureManager.getInstance().addTexture("b", texture);
texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mActivity.getResources().getDrawable(R.drawable.c)), 128, 128));
TextureManager.getInstance().addTexture("c", texture);
texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mActivity.getResources().getDrawable(R.drawable.d)), 128, 128));
TextureManager.getInstance().addTexture("d", texture);
texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mActivity.getResources().getDrawable(R.drawable.e)), 128, 128));
TextureManager.getInstance().addTexture("e", texture);
texture = new Texture(BitmapHelper.rescale(BitmapHelper.convert(mActivity.getResources().getDrawable(R.drawable.b)), 128, 128));
TextureManager.getInstance().addTexture("f", texture);
}
/**
* 创建立方体
*/
private void CreateBox() {
cube = new Object3D(0);
// 前
a = new Object3D(2);
a.addTriangle(GetPoint(-30, -30, 30), 0.0f, 0.0f,
GetPoint(30, -30, 30), 1.0f, 0.0f, GetPoint(-30, 30, 30), 0.0f,
1.0f, TextureManager.getInstance().getTextureID("a"));
a.addTriangle(GetPoint(30, -30, 30), 1.0f, 0.0f,
GetPoint(30, 30, 30), 1.0f, 1.0f, GetPoint(-30, 30, 30), 0.0f,
1.0f, TextureManager.getInstance().getTextureID("a"));
cube.addChild(a);
world.addObject(a);
a.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);
// 上
b = new Object3D(2);
b.addTriangle(GetPoint(-30, 30, 30), 0.0f, 0.0f,
GetPoint(30, 30, 30), 1.0f, 0.0f, GetPoint(-30, 30, -30), 0.0f,
1.0f, TextureManager.getInstance().getTextureID("b"));
b.addTriangle(GetPoint(30, 30, 30), 1.0f, 0.0f,
GetPoint(30, 30, -30), 1.0f, 1.0f, GetPoint(-30, 30, -30),
0.0f, 1.0f, TextureManager.getInstance().getTextureID("b"));
cube.addChild(b);
world.addObject(b);
b.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);
// 后
c = new Object3D(2);
c.addTriangle(GetPoint( -30, 30, -30), 0.0f, 0.0f,
GetPoint(30, 30, -30), 1.0f, 0.0f, GetPoint(-30, -30, -30),
0.0f, 1.0f, TextureManager.getInstance().getTextureID("c"));
c.addTriangle(GetPoint(30, 30, -30), 1.0f, 0.0f,
GetPoint(30, -30, -30), 1.0f, 1.0f, GetPoint(-30, -30, -30),
0.0f, 1.0f, TextureManager.getInstance().getTextureID("c"));
cube.addChild(c);
world.addObject(c);
c.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);
// 下
d = new Object3D(2);
d.addTriangle(GetPoint(-30, -30, -30), 0.0f, 0.0f,
GetPoint(30, -30, -30), 1.0f, 0.0f, GetPoint(-30, -30, 30),
0.0f, 1.0f, TextureManager.getInstance().getTextureID("d"));
d.addTriangle(GetPoint(30, -30, -30), 1.0f, 0.0f,
GetPoint(30, -30, 30), 1.0f, 1.0f, GetPoint( -30, -30, 30), 0.0f,
1.0f, TextureManager.getInstance().getTextureID("d"));
cube.addChild(d);
world.addObject(d);
d.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);
// 左
e = new Object3D(2);
e.addTriangle(GetPoint( -30, -30, -30), 0.0f, 0.0f,
GetPoint(-30, -30, 30), 1.0f, 0.0f, GetPoint(-30, 30, -30),
0.0f, 1.0f, TextureManager.getInstance().getTextureID("e"));
e.addTriangle(GetPoint( -30, -30, 30), 1.0f, 0.0f,
GetPoint(-30, 30, 30), 1.0f, 1.0f, GetPoint(-30, 30, -30),
0.0f, 1.0f, TextureManager.getInstance().getTextureID("e"));
cube.addChild(e);
world.addObject(e);
e.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);
// 右
f = new Object3D(2);
f.addTriangle(GetPoint(30, -30, 30), 0.0f, 0.0f,
GetPoint(30, -30, -30), 1.0f, 0.0f, GetPoint(30, 30, 30), 0.0f,
1.0f, TextureManager.getInstance().getTextureID("f"));
f.addTriangle(GetPoint(30, -30, -30), 1.0f, 0.0f,
GetPoint(30, 30, -30), 1.0f, 1.0f, GetPoint(30, 30, 30), 0.0f,
1.0f, TextureManager.getInstance().getTextureID("f"));
cube.addChild(f);
world.addObject(f);
f.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);
cube.strip();
cube.build();
world.addObject(cube);
cube.setCulling(false);
cube.scale( 0.25f);
cube.rotateZ( 100);
cube.setCollisionMode( Object3D.COLLISION_CHECK_OTHERS);
}
/**
* 拾取点击事件
* @param fX
* @param fY
* @return
*/
public int Pickint( int fX, int fY){
//fY = fb.getHeight() - fY;
SimpleVector dir = Interact2D.reproject2D3DWS( cam, fb, fX, fY).normalize();
Object[] res=world.calcMinDistanceAndObject3D(cam.getPosition(), dir, 10000 );
Object3D picked = (Object3D)res[1];
if( picked == null)
return -1;
if( picked.getID() == a.getID()) {
CubeObserverManager.getInstance().notifyObserver(1);
return 1;
}
else if( picked.getID() == b.getID()) {
CubeObserverManager.getInstance().notifyObserver(2);
return 2;
}
else if( picked.getID() == c.getID()) {
CubeObserverManager.getInstance().notifyObserver(3);
return 3;
}
else if( picked.getID() == d.getID()) {
CubeObserverManager.getInstance().notifyObserver(4);
return 4;
}
else if( picked.getID() == e.getID()) {
CubeObserverManager.getInstance().notifyObserver(5);
return 5; }
else if( picked.getID() == f.getID()) {
CubeObserverManager.getInstance().notifyObserver(6);
return 6;
}
return -1;
}
/**
* 清除纹理
*/
public void clearTexture() {
TextureManager.getInstance().removeTexture("a");
TextureManager.getInstance().removeTexture("b");
TextureManager.getInstance().removeTexture("c");
TextureManager.getInstance().removeTexture("d");
TextureManager.getInstance().removeTexture("e");
TextureManager.getInstance().removeTexture("f");
}
}
在onSurfaceCreated的时候绘制立方体及它的纹理,然后就是相机的位置,灯光位置,然后用roate方法设置默认旋转的角度。
在onDrawFrame判断立方体滑动状态,如果滑动到某个时间滑动还没结束就停止滑动,滑动到我预设的那个位置。
Cube.java:
package com.example.cube;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import com.threed.jpct.Matrix;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
public class Cube extends GLSurfaceView {
private float xpos = -1;
private float ypos = -1;
public static long downTime = 0;
public static long moveTime = 0;
public static long startTime = 0;
public static long rotatedTime = 0;
public static boolean isStart = false;
public static Matrix startRotationMatrix=new Matrix();
private Rander mRander;
public Cube(Context context, AttributeSet attrs) {
super(context);
// TODO Auto-generated constructor stub
// 使用自己实现的 EGLConfigChooser,该实现必须在setRenderer(renderer)之前
// 如果没有setEGLConfigChooser方法被调用,则默认情况下,视图将选择一个与当前android.view.Surface兼容至少16位深度缓冲深度EGLConfig。
setEGLConfigChooser(new EGLConfigChooser() {
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
int[] attributes = new int[] { EGL10.EGL_DEPTH_SIZE, 16,
EGL10.EGL_NONE };
EGLConfig[] configs = new EGLConfig[1];
int[] result = new int[1];
egl.eglChooseConfig(display, attributes, configs, 1, result);
return configs[0];
}
});
mRander = new Rander(context);
setRenderer(mRander);
}
public boolean onTouchEvent(MotionEvent me) {
if (me.getAction() == MotionEvent.ACTION_DOWN) {
mRander.Pickint( (int)me.getX(), (int)me.getY());
downTime = System.currentTimeMillis();
xpos = me.getX();
ypos = me.getY();
mRander.isRotate = false;
return true;
}
if (me.getAction() == MotionEvent.ACTION_UP) {
mRander.isRotate = false;
xpos = -1;
ypos = -1;
return true;
}
if (me.getAction() == MotionEvent.ACTION_MOVE) {
mRander.isRotate = true;
float xd = me.getX() - xpos;
float yd = me.getY() - ypos;
xpos = me.getX();
ypos = me.getY();
if(xd >30){//右
mRander.gride = "right";
startRotationMatrix=mRander.cube.getRotationMatrix();
startTime = System.currentTimeMillis();
isStart = true;
}else if(xd<-30){//左
mRander.gride = "left";
startRotationMatrix=mRander.cube.getRotationMatrix();
startTime = System.currentTimeMillis();
isStart = true;
}
Cube.this.setEnabled(false);
Cube.this.clearFocus();
return true;
}
try {
Thread.sleep(15);
} catch (Exception e) {
// No need for this...
}
return super.onTouchEvent(me);
}
public void clearTexture() {
if(mRander != null){
mRander.clearTexture();
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
clearTexture();
}
}
处理一下滑动。
CubeObserverManager.java:
package com.example.cube;
import java.util.ArrayList;
import java.util.List;
/**
* Created by wanghk on 2018-09-27.
*/
public class CubeObserverManager implements CubeSubjectListener {
private static CubeObserverManager manager;
private List<CubeObserverListener> list = new ArrayList<>();
public static CubeObserverManager getInstance(){
if(null == manager){
synchronized (CubeObserverManager.class){
if(null == manager)
manager = new CubeObserverManager();
}
}
return manager;
}
@Override
public void add(CubeObserverListener observerListener) {
list.add(observerListener);
}
@Override
public void notifyObserver(int msg) {
for (CubeObserverListener observerListener : list){
observerListener.sendMsg(msg);
}
}
@Override
public void remove(CubeObserverListener observerListener) {
if(list.contains(observerListener))
list.remove(observerListener);
}
}
CubeSubjectListener.java:
package com.example.cube;
/**
* Created by wanghk on 2018-09-27.
*/
public interface CubeSubjectListener {
void add(CubeObserverListener observerListener);
void notifyObserver(int msg);
void remove(CubeObserverListener observerListener);
}
CubeObserverListener.java:
package com.example.cube;
/**
* Created by wanghk on 2018-09-27.
* 观察者接口
*/
public interface CubeObserverListener {
void sendMsg(int msg);
}
这三个java只是为了传递点击哪个面而已。
就是这些了,代码里几乎都有注释。效果就是左右滑动的立方体。有什么问题欢迎询问QQ:1398169857。
项目链接:https://pan.baidu.com/s/14JgzwiCktc5nlzrxTH9SXA
提取码:x9dw