Android--碰撞效果--JBox2d实现
来源:互联网 发布:桌面录屏软件 编辑:程序博客网 时间:2024/06/17 23:08
效果如下:录制的时候有点卡,实际没有卡顿哈。(基于JBox2d 2.3开发的)
代码结构:
代码:
package com.bmob.im.demo.mobaianimation.widget;import android.view.View;import com.bmob.im.demo.mobaianimation.R;import org.jbox2d.collision.shapes.CircleShape;import org.jbox2d.collision.shapes.PolygonShape;import org.jbox2d.collision.shapes.Shape;import org.jbox2d.common.Vec2;import org.jbox2d.dynamics.Body;import org.jbox2d.dynamics.BodyDef;import org.jbox2d.dynamics.BodyType;import org.jbox2d.dynamics.FixtureDef;import org.jbox2d.dynamics.World;import java.util.Random;/**jbox2d 2.3.1 * Created by Administrator--沈斌 on 2017/10/23. */public class JboxImp { private static final String TAG = JboxImp.class.getSimpleName(); private World mWorld; private float dt = 1f/ 30f; //运动的频率 private int mVelocityIterations = 5; //每一帧迭代次数 private int mPosiontionIterations = 20; //每一帧计算的位置点 private int mWidth,mHeight; //刚体的边界,宽高 private float mDesity = 0.5f; //刚体密度 private float mRatio = 20; //坐标比率,模拟和真实的映射比率,碰撞的速度以及幅度 private final Random mRandom = new Random(); //随机数 /** * 设置密度 * @param desity */ public JboxImp(float desity){ this.mDesity = desity; } /** * 设置边界(弹力墙的边界) * @param width * @param height */ public void setWorldSize(int width,int height){ this.mWidth = width; this.mHeight = height; } public void createWorld(){ if (mWorld == null){ mWorld = new World(new Vec2(0,10.0f)); updateVerticalBounds(); updateHorzontalBounds(); } } /** * 竖直方向的弹力墙(上和下) */ private void updateVerticalBounds(){ //创建静态刚体 BodyDef bodyDef = new BodyDef(); bodyDef.type = BodyType.STATIC; //静态 PolygonShape box = new PolygonShape(); float boxWidth = switchPositionToBody(mWidth); float boxHeight = 1; //因为垂直,所以高度为1 box.setAsBox(boxWidth,boxHeight); FixtureDef fixtureDef = new FixtureDef(); fixtureDef.shape = box; fixtureDef.density = mDesity; fixtureDef.friction = 0.8f; //摩擦系数 fixtureDef.restitution = 0.5f; //补偿系数 //底部body bodyDef.position.set(0,-boxHeight); //底部弹力墙 Body bottomBody = mWorld.createBody(bodyDef); bottomBody.createFixture(fixtureDef); //顶部body bodyDef.position.set(0,switchPositionToBody(mHeight)+boxHeight); //顶部弹力墙 Body topBody = mWorld.createBody(bodyDef); topBody.createFixture(fixtureDef); } /** * 水平方向的弹力墙(左边和右边) */ private void updateHorzontalBounds(){ //创建静态刚体 BodyDef bodyDef = new BodyDef(); bodyDef.type = BodyType.STATIC; //静态 PolygonShape box = new PolygonShape(); float boxWidth = 1; float boxHeight = switchPositionToBody(mHeight); //因为垂直,所以高度为1 box.setAsBox(boxWidth,boxHeight); FixtureDef fixtureDef = new FixtureDef(); fixtureDef.shape = box; fixtureDef.density = mDesity; fixtureDef.friction = 0.8f; //摩擦系数 fixtureDef.restitution = 0.5f; //补偿系数 //左边body bodyDef.position.set(-boxWidth,0); //左边弹力墙 Body leftBody = mWorld.createBody(bodyDef); leftBody.createFixture(fixtureDef); //右边body bodyDef.position.set(switchPositionToBody(mWidth)+boxWidth,0); //右边弹力墙 Body rightBody = mWorld.createBody(bodyDef); rightBody.createFixture(fixtureDef); } /** * view坐标映射为物理的坐标 * @param viewPosition * @return */ public float switchPositionToBody(float viewPosition){ return viewPosition / mRatio; } /** * 物理坐标映射为view的坐标 * @param bodyPosition * @return */ public float switchPositionToView(float bodyPosition){ return bodyPosition * mRatio; } public float radiansToDegrees(float radians) { return radians / 3.14f * 180f; } public boolean isBodyView(View view){ Body body = (Body) view.getTag(R.id.shenbin_body_view_tag); return body != null; } /** * 创建模拟事件的刚体(运动的小圆球) * @param view */ public void createBody(View view){ //创建动态刚体 BodyDef bodyDef = new BodyDef(); bodyDef.type = BodyType.DYNAMIC; //动态 Shape shape = null; boolean isCircle = (boolean) view.getTag(R.id.shenbin_circle_view_tag); bodyDef.position.set(switchPositionToBody(view.getX() + view.getWidth() / 2), switchPositionToBody(view.getY() + view.getHeight() / 2)); if(isCircle){ shape = createCircleShape(switchPositionToBody(view.getWidth()/2)); } FixtureDef fixtureDef = new FixtureDef(); fixtureDef.shape = shape; fixtureDef.density = mDesity; fixtureDef.friction = 0.8f; //摩擦系数 fixtureDef.restitution = 0.5f; //补偿系数 Body body = mWorld.createBody(bodyDef); body.createFixture(fixtureDef); view.setTag(R.id.shenbin_body_view_tag,body); //线性加速约束 body.setLinearVelocity(new Vec2(mRandom.nextFloat(),mRandom.nextFloat())); } /** * 得到圆形刚体 * @param radius * @return */ private Shape createCircleShape(float radius){ CircleShape circleShape = new CircleShape(); circleShape.setRadius(radius); return circleShape; } public void startWorld(){ if(mWorld != null){ mWorld.step(dt,mVelocityIterations,mPosiontionIterations); } } /** * 通过调用这个方法,使刚体运动起来 * @param x * @param y * @param view */ public void applyLinearImpulse(float x ,float y,View view){ Body body = (Body) view.getTag(R.id.shenbin_body_view_tag); Vec2 impluse = new Vec2(x,y); //这两个参数,可以控制刚体碰撞的范围 body.applyLinearImpulse(impluse,body.getPosition(),true); }}
package com.bmob.im.demo.mobaianimation.widget;import android.content.Context;import android.graphics.Canvas;import android.util.AttributeSet;import android.view.View;import android.widget.FrameLayout;import com.bmob.im.demo.mobaianimation.R;import org.jbox2d.dynamics.Body;/** * Created by Administrator--沈斌 on 2017/10/23. */public class CollisionView extends FrameLayout { private JboxImp jboxImp; public CollisionView(Context context) { this(context, null); } public CollisionView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CollisionView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setWillNotDraw(false); initView(); } private void initView(){ jboxImp = new JboxImp(getResources().getDisplayMetrics().density); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); jboxImp.createWorld(); int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View view = getChildAt(i); Body body = (Body) view.getTag(R.id.shenbin_body_view_tag); if(body == null || changed){ jboxImp.createBody(view); } } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); jboxImp.startWorld();//也可以放到onLayout里面 int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View view = getChildAt(i); Body body = (Body) view.getTag(R.id.shenbin_body_view_tag); if(view != null && jboxImp.isBodyView(view)){ view.setX(jboxImp.switchPositionToView(body.getPosition().x) - view.getWidth() / 2); view.setY(jboxImp.switchPositionToView(body.getPosition().y) - view.getHeight() / 2); view.setRotation(jboxImp.radiansToDegrees(body.getAngle() % 360)); } } invalidate(); } public void onSensorChanged(float x,float y){ int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View view = getChildAt(i); if(view != null && jboxImp.isBodyView(view)){ jboxImp.applyLinearImpulse(x,y,view); } } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); jboxImp.setWorldSize(w,h); }}
package com.bmob.im.demo.mobaianimation;import android.app.Activity;import android.content.Context;import android.hardware.Sensor;import android.hardware.SensorEvent;import android.hardware.SensorEventListener;import android.hardware.SensorManager;import android.os.Bundle;import android.view.Gravity;import android.widget.FrameLayout;import android.widget.ImageView;import com.bmob.im.demo.mobaianimation.widget.CollisionView;import java.util.Random;public class MainActivity extends Activity implements SensorEventListener{ CollisionView myView; private SensorManager sensorManager; private int[] imgs = { R.drawable.share_fb, R.drawable.share_kongjian, R.drawable.share_pyq, R.drawable.share_qq, R.drawable.share_tw, R.drawable.share_wechat, R.drawable.share_weibo, R.mipmap.ic_launcher }; private Sensor defaultSensor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public void onContentChanged() { super.onContentChanged(); sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); defaultSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); myView = (CollisionView) findViewById(R.id.myView); initViews(); } @Override protected void onResume() { super.onResume(); sensorManager.registerListener( this,defaultSensor,SensorManager.SENSOR_DELAY_UI); } @Override protected void onPause() { super.onPause(); sensorManager.unregisterListener(this); } private void initViews() { FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT); layoutParams.gravity = Gravity.CENTER; for(int i = 0; i < imgs.length ; i ++){ ImageView imageView = new ImageView(this); imageView.setImageResource(imgs[i]); imageView.setTag(R.id.shenbin_circle_view_tag,true); myView.addView(imageView,layoutParams); } } private final Random mRandom = new Random(); /** * 使用传感器,因为这个会一直回调,一直运行,所以可以使刚体不停的碰撞。 * @param sensorEvent */ @Override public void onSensorChanged(SensorEvent sensorEvent) { if(sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER){ float x = sensorEvent.values[0]; float y = sensorEvent.values[1] * 2.0f; myView.onSensorChanged(mRandom.nextInt(200) - 100, mRandom.nextInt(1000) - 500); //这两个参数传递下去,可以控制刚体碰撞的范围 } } @Override public void onAccuracyChanged(Sensor sensor, int i) { }}
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorAccent" tools:context="com.bmob.im.demo.mobaianimation.MainActivity"> <com.bmob.im.demo.mobaianimation.widget.CollisionView android:layout_width="match_parent" android:layout_height="300dp" android:id="@+id/myView" android:background="#fff"/></RelativeLayout>
阅读全文
0 0
- Android--碰撞效果--JBox2d实现
- android JBOX2D实现粒子碰撞特效实例
- JBox2D学习 - 小球碰撞
- JBox2D学习 - 小球碰撞实例 .
- android加入jbox2d
- android JBox2D 框架
- jbox2d
- ListView 实现类似电话薄标题碰撞效果
- CSS 使用 贝塞尔曲线 碰撞效果实现
- android的jbox2d的使用!
- JBox2D For Android - hello box2d
- JBox2D 引擎 for Android 详解
- JBox2D For Android - hello box2d
- android 游戏学习(jbox2d)
- Android 打飞机 小游戏 的实现 - 画面移动 对象封装 碰撞效果
- JBox2D For Android - 用canvas绘制shape
- android jbox2d学习笔记一 滑轮关节
- 原生js实现红球碰撞篮球效果
- 如何查看sourceTree下工程远程地址
- 面向对象程序设计上机练习三(有默认参数的函数)
- spring框架(一)——Spring核心框架体系结构(jar包引用分析)
- Linux查看进程和终止进程的技巧
- 数据库添加函数查询经伟度距离
- Android--碰撞效果--JBox2d实现
- Mac OSX ffmpeg 硬件加速
- Python学习之旅第一课--安装各种模块包
- 根文件系统分区制作
- zookeeper的日常运维
- 5个人分13个苹果类似的算法问题
- 试验3
- java多线程学习——(3)认识yield,join,sleep方法
- Websphere Application Server (WAS) 中应用的哪一个 web.xml 在起作用