热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何用SceneForm实现子弹射击并绘制子弹运行轨迹

本篇文章为大家展示了如何用SceneForm实现子弹射击并绘制子弹运行轨迹,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍

本篇文章为大家展示了如何用SceneForm实现子弹射击并绘制子弹运行轨迹,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

基于 SceneForm 实现的子弹射击(绘制子弹运行轨迹)

Sceneform 框架很强大,不了解 Sceneform 的时候,觉得要想做 3D 场景需要会 OpenGL,而 OpenGL 的学习曲线很陡;接触到这个框架之后觉得小白也可以很快上手,甚至可以实现第一人称射击的效果

注:自己学习 SceneForm 有一段时间了,不过没有发现模拟重力场的接口,不知道是不是自己漏掉了

模拟射击效果的思路其实很简单

1、加载一个子弹模型2、规划子弹由近及远的轨迹3、绘制子弹的运行轨迹

子弹运行轨迹的逻辑代码;代码中涉及的 CleanArFragment 在之前的《ARCore 的 SceneForm 框架在没有 Plane 情况下的绘制 3D 模型》已经给出;另外需要自行提供一个纹理图片,即代码中的 R.drawable.texture。

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)}

界面布局

上述内容就是如何用SceneForm实现子弹射击并绘制子弹运行轨迹,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程笔记行业资讯频道。


推荐阅读
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 展开全部下面的代码是创建一个立方体Thisexamplescreatesanddisplaysasimplebox.#Thefirstlineloadstheinit_disp ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 有没有一种方法可以在不继承UIAlertController的子类或不涉及UIAlertActions的情况下 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
author-avatar
落叶听声
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有