基于SceneForm实现子弹射击(绘制子弹运行轨迹)
基于SceneForm实现的子弹射击(绘制子弹运行轨迹)
Sceneform框架很强大,不了解Sceneform的时候,觉得要想做3D场景需要会OpenGL,而OpenGL的学习曲线很陡;接触到这个框架之后觉得小白也可以很快上手,甚至可以实现第一人称射击的效果
注:自己学习SceneForm有一段时间了,不过没有发现模拟重力场的接口,不知道是不是自己漏掉了
模拟射击效果的思路其实很简单
1、加载一个子弹模型
2、规划子弹由近及远的轨迹
3、绘制子弹的运行轨迹
子弹运行轨迹的逻辑代码;代码中涉及的CleanArFragment在之前的《ARCore的SceneForm框架在没有Plane情况下的绘制3D模型》已经给出;另外需要自行提供一个纹理图片,即代码中的R.drawable.texture。
classMainActivity:AppCompatActivity(){ vararFragment:CleanArFragment?=null varcamera:Camera?=null varsize=Point();//屏幕尺寸,控制子弹发射的初始位置 varbullet:ModelRenderable?=null varscene:Scene?=null valSHOT=0x1101//绘制过程轨迹信号 valSHOT_OVER=0x1102//清除子弹模型信号 varhandler=object:Handler(){ overridefunhandleMessage(msg:Message) { if(msg.what==SHOT){//绘制移动过程中的轨迹 varcurrentStatus=msg.objasCurrentStatus currentStatus.node.worldPosition=currentStatus.status }elseif(msg.what==SHOT_OVER){//一次射击完成,清除屏幕的子弹 varnode=msg.objasNode scene!!.removeChild(node) } } } overridefunonCreate(savedInstanceState:Bundle?){ super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) //获取屏幕尺寸 valdisplay=windowManager.defaultDisplay display.getRealSize(size) arFragment=this.supportFragmentManager.findFragmentById(R.id.arFragment)asCleanArFragment arFragment!!.arSceneView.planeRenderer.isEnabled=false//禁止sceneform框架的平面绘制 scene=arFragment!!.arSceneView.scene camera=scene!!.camera initbullet() shootButton.setOnClickListener(listener) } varlistener:View.OnClickListener=object:View.OnClickListener{ overridefunonClick(v:View?){ shoot() } } @TargetApi(Build.VERSION_CODES.N) //初始化子弹模型 privatefuninitbullet(){ Texture.builder().setSource(this@MainActivity,R.drawable.texture).build() .thenAccept( {texture-> MaterialFactory.makeOpaqueWithTexture(this@MainActivity,texture) .thenAccept{material-> //设置子弹模型为球体 bullet=ShapeFactory.makeSphere(0.1f,Vector3(0f,0f,0f),material)} } ) } privatefunshoot(){ //从屏幕发出的射线,对应子弹的运行轨迹 varray=camera!!.screenPointToRay(size.x/2f,size.y/2f); varnode=Node()//子弹节点 node.renderable=bullet//子弹节点加载子弹模型 scene!!.addChild(node) Thread(object:Runnable{ overridefunrun(){ //子弹射击过程中的轨迹,子线程处理轨迹事件,主线程改变轨迹位置 for(iin1..200){//子弹射程20m varstepLen=i; varcurrentPoint=ray.getPoint(stepLen*0.1f) varmsg=handler.obtainMessage() msg.what=SHOT msg.obj=CurrentStatus(node,currentPoint) handler.sendMessage(msg) } //子弹超出距离后,从屏幕清除掉 varmsg=handler.obtainMessage() msg.what=SHOT_OVER msg.obj=node handler.sendMessage(msg) } }).start() } //子线程和主线程穿点的数据类 dataclassCurrentStatus(varnode:Node,varstatus:Vector3) }
界面布局
实现效果如下,因为动图的偏差,子弹不是很清晰,子弹由中心的红色十字向远处射击
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。