Bullet shooting based on sceneform (drawing bullet trajectory)
Bullet shooting based on sceneform (drawing bullet trajectory)
The sceneform framework is very powerful. When you don't understand sceneform, you think you need to know OpenGL to make 3D scenes, and the learning curve of OpenGL is very steep; After contacting this framework, I think Xiaobai can also get started quickly, and even achieve the effect of first person shooting
Note: I have studied sceneform for some time, but I haven't found the interface to simulate gravity field. I don't know if I missed it
The idea of simulating shooting effect is actually very simple
1. Load a bullet model 2. Plan the trajectory of the bullet from near to far 3. Draw the trajectory of the bullet
Logic code of bullet trajectory; The cleanarfragment involved in the code has been given in the previous drawing 3D model of the sceneform framework of arcore without plane; In addition, you need to provide a texture image by yourself, that is, r.drawable.texture in the code.
class MainActivity : AppCompatActivity() { var arFragment : CleanArFragment? = null var camera : Camera? = null var size = Point(); //屏幕尺寸,控制子弹发射的初始位置 var bullet : ModelRenderable? = null var scene : Scene? = null val SHOT = 0x1101 //绘制过程轨迹信号 val SHOT_OVER = 0x1102 //清除子弹模型信号 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) { //一次射击完成,清除屏幕的子弹 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) //初始化子弹模型 private fun initbullet() { 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) } } ) } private fun shoot() { //从屏幕发出的射线,对应子弹的运行轨迹 var ray = camera!!.screenPointToRay(size.x / 2f,size.y / 2f); var node = Node() //子弹节点 node.renderable = bullet //子弹节点加载子弹模型 scene!!.addChild(node) Thread(object : Runnable{ override fun run() { //子弹射击过程中的轨迹,子线程处理轨迹事件,主线程改变轨迹位置 for (i in 1 .. 200 ) { //子弹射程 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) } //子弹超出距离后,从屏幕清除掉 var msg = handler.obtainMessage() msg.what = SHOT_OVER msg.obj = node handler.sendMessage(msg) } }).start() } // 子线程和主线程穿点的数据类 data class CurrentStatus(var node : Node,var status : Vector3) }
Interface layout
<?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" 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>
The effect is as follows: because of the deviation of the moving picture, the bullet is not very clear, and the bullet shoots from the Red Cross in the center to the distance
The above is the whole content of this article. I hope it will help you in your study, and I hope you will support us a lot.