基于 SceneForm 实现的子d射击(绘制子d运行轨迹)
SceneForm 框架很强大,不了解 SceneForm 的时候,觉得要想做 3D 场景需要会 OpenGL,而 OpenGL 的学习曲线很陡;接触到这个框架之后觉得小白也可以很快上手,甚至可以实现第一人称射击的效果
注:自己学习 SceneForm 有一段时间了,不过没有发现模拟重力场的接口,不知道是不是自己漏掉了
模拟射击效果的思路其实很简单
1、加载一个子d模型
2、规划子d由近及远的轨迹
3、绘制子d的运行轨迹
子d运行轨迹的逻辑代码;代码中涉及的 CleanArFragment 在之前的《ARCore 的 SceneForm 框架在没有 Plane 情况下的绘制 3D 模型》已经给出;另外需要自行提供一个纹理图片,即代码中的 R.drawable.texture。
class MainActivity : AppCompatActivity() { var arFragment : CleanArFragment? = null var camera : Camera? = null var size = Point(); //屏幕尺寸,控制子d发射的初始位置 var bullet : ModelRenderable? = null var scene : Scene? = null val SHOT = 0x1101 //绘制过程轨迹信号 val SHOT_OVER = 0x1102 //清除子d模型信号 var handler = object : Handler() { overrIDe fun handleMessage(msg : Message) { if (msg.what == SHOT) { //绘制移动过程中的轨迹 var currentStatus = msg.obj as CurrentStatus currentStatus.node.worldposition = currentStatus.status } else if (msg.what == SHOT_OVER) { //一次射击完成,清除屏幕的子d var node = msg.obj as Node scene!!.removeChild(node) } } } overrIDe fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentVIEw(R.layout.activity_main) // 获取屏幕尺寸 val display = windowManager.defaultdisplay display.getRealSize(size) arFragment = this.supportFragmentManager.findFragmentByID(R.ID.arFragment) as CleanArFragment arFragment!!.arSceneVIEw.planeRenderer.isEnabled = false //禁止 SceneForm 框架的平面绘制 scene = arFragment!!.arSceneVIEw.scene camera = scene!!.camera initbullet() shootbutton.setonClickListener(Listener) } var Listener : VIEw.OnClickListener = object : VIEw.OnClickListener{ overrIDe fun onClick(v: VIEw?) { shoot() } } @TargetAPI(Build.VERSION_CODES.N) //初始化子d模型 private fun initbullet() { Texture.builder().setSource(this@MainActivity,R.drawable.texture).build() .thenAccept( { texture -> MaterialFactory.makeOpaqueWithTexture(this@MainActivity,texture) .thenAccept { material -> // 设置子d模型为球体 bullet = ShapeFactory.makeSphere(0.1f,Vector3(0f,0f,0f),material) } } ) } private fun shoot() { //从屏幕发出的射线,对应子d的运行轨迹 var ray = camera!!.screenPointToRay(size.x / 2f,size.y / 2f); var node = Node() //子d节点 node.renderable = bullet //子d节点加载子d模型 scene!!.addChild(node) Thread(object : Runnable{ overrIDe fun run() { //子d射击过程中的轨迹,子线程处理轨迹事件,主线程改变轨迹位置 for (i in 1 .. 200 ) { //子d射程 20 m var stepLen = i; var currentPoint = ray.getPoint(stepLen * 0.1f) var msg = handler.obtainMessage() msg.what = SHOT msg.obj = CurrentStatus(node,currentPoint) handler.sendMessage(msg) } //子d超出距离后,从屏幕清除掉 var msg = handler.obtainMessage() msg.what = SHOT_OVER msg.obj = node handler.sendMessage(msg) } }).start() } // 子线程和主线程穿点的数据类 data class CurrentStatus(var node : Node,var status : Vector3)}
界面布局
<?xml version="1.0" en@R_419_5563@="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" tools:context=".MainActivity"> <fragment androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:ID="@+ID/arFragment" androID:name="com.hosh.shootapplication.CleanArFragment"/> <VIEw androID:layout_wIDth="35dp" androID:layout_height="2dp" androID:background="#ff0000" androID:layout_centerInParent="true" /> <VIEw androID:layout_wIDth="2dp" androID:layout_height="35dp" androID:background="#ff0000" androID:layout_centerInParent="true" /> <button androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:ID="@+ID/shootbutton" androID:layout_alignParentBottom="true" androID:layout_centerHorizontal="true" androID:layout_marginBottom="8dp" androID:text="@string/shoot" /></relativeLayout>
实现效果如下,因为动图的偏差,子d不是很清晰,子d由中心的红色十字向远处射击
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
总结以上是内存溢出为你收集整理的基于SceneForm实现子d射击(绘制子d运行轨迹)全部内容,希望文章能够帮你解决基于SceneForm实现子d射击(绘制子d运行轨迹)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)