在cocos的坐标系、cocos与Android之间遇到一些事情,做个笔记。


首先是坐标系,Cocos的一个node,其rotation,是基于其父节点坐标的。例如layer里面添加一个camera,那么旋转camera的xyz,例如setRotation3d(Vec3(0,180,90)),并不是让camera绕自身y转180后,再绕自身z轴转90。而是camera绕layer的x转180,再绕layer的z转90。脑补一下就知道,实际上两个方式的z旋转,因为y上已经转了180,所以方向是相反的了。清楚了一点,有助于处理比较麻烦的坐标系相对旋转问题。camera是与精灵们在同一个layer,还是不同layer,取决于要不要观察相机后方而维持正常的Z旋转。


然后就是独立于layer之外的camera,如何在小地图屏幕还原sprite的二维坐标?如果相机与sprite在同一layer,只需要相机矩阵简单一句mat.getInversed().transformVector(&pos)即可。但是当camera与layer分离时,又会有诸多情况,嘿嘿。这部分,贴一段看起来貌似OK但是实际会有问题的代码:

Vec3 bosspos = boss_i->getPosition3D();
Vec2 PosAfterRotate = Vec2(bosspos.x,bosspos.z).rotateByAngle(Vec2(0,0),CC_degrees_TO_radians(-_layer3D->getRotation3D().y));//X与Z绕Y还原至垂直相机的平面
Vec4 pos;
pos.x = PosAfterRotate.x; pos.y = bosspos.y; pos.z = PosAfterRotate.y;
pos.w = 1;
Mat4 mat = _CameraBird->getNodetoWorldTransform();
mat.getInversed().transformVector(&pos);//使用相机矩阵,取得boss在屏幕的投射坐标
Vec2 bossposAbs = Vec2(pos.x,pos.y) / (curPos.distance(bosspos));


这段代码看似无误,实际运用中却会发现还原出的bossposAbs与boss显示位置存在偏差,原因是什么,自己想吧,哈哈,就不说破了。正确的计算方式是什么?想明白了为什么这个会错,正确的自然也就呼之欲出了。



然后是cocos与android的surfaceview的问题。android的surfaceview是在游戏被推入后台时,会被自动destroy的。然后程序再被唤醒时,它又会被oncreate。这涉及了诸多线程的问题,也就会产生一堆的怪事。

首先,使用的是在主程序中创建一个新的surfaceview,通过其回调启动相机的方式。

if(mPreviewSV==null){
<span style="white-space:pre">	</span>mPreviewSV = new SurfaceView(JniDoIt.this);
<span style="white-space:pre">	</span>addContentView(mPreviewSV,new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,FrameLayout.LayoutParams.MATCH_PARENT)); // keep old views
<span style="white-space:pre">	</span>Log.i("SHOW_AR","mPreviewSV is null and Now it is added");
}
else{
<span style="white-space:pre">	</span>Log.i("SHOW_AR","mPreviewSV already exist......");<span style="white-space:pre">					</span>
}
if(mySurfaceHolder==null){
<span style="white-space:pre">	</span>mySurfaceHolder = mPreviewSV.getHolder();
<span style="white-space:pre">	</span>mySurfaceHolder.setFormat(PixelFormat.TRANSPARENT);
<span style="white-space:pre">	</span>Log.i("SHOW_AR","mySurfaceHolder is null and Now it is defined to mPreviewSV.getHolder()......."+mySurfaceHolder);<span style="white-space:pre">					</span>
}
else{
<span style="white-space:pre">	</span>Log.i("SHOW_AR","mySurfaceHolder already exist......"+mySurfaceHolder);<span style="white-space:pre">					</span>
}

回调定义:

private class ArSurfaceHolderCallBack implements SurfaceHolder.Callback{}


在游戏推入后台时,释放相机,并且删除surfaceview的回调,唤醒时重建一次surfaceview。如此做的结果是相机预览是恢复了,但是把cocos主界面也覆盖了,下面是其log




log那一行onenGL错误曾经误导了很久,那是一个在UI线程之外更新UI而产生的错误,结合cocos界面被覆盖的实际情况,感觉非常非常像是surfaceview进程与UI进程冲突,但是暂且忽略吧,因为后来发现完全注释掉surfaceview相关代码,这个错照样存在,而且在我最终的解决方案中,这个错虽然仍旧存在,但是可以做到正常唤醒。这个错应该是程序中某些其他位置导致的,暂且不理它。


那么不使用回调方式,直接使用surfaceview类内部取得自身handler,在游戏推入后台时,释放相机,并且删除surfaceview,唤醒时重建一次surfaceview,重新启动回调和相机如何呢?

呼叫方式:

mPreviewSV = new ArSV(JniDoIt.getContext());
mPreviewSV.setId(100);
JniDoIt.this.addContentView(mPreviewSV,FrameLayout.LayoutParams.MATCH_PARENT)); // keep old views

类定义:
private class ArSV extends SurfaceView implements SurfaceHolder.Callback{
 <span style="white-space:pre">	</span>private SurfaceHolder mySurfaceHolder = null;
  <span style="white-space:pre">	</span>private Camera myCamera = null;
  <span style="white-space:pre">	</span>
  <span style="white-space:pre">	</span>@SuppressWarnings("deprecation")
<span style="white-space:pre">		</span>public ArSV(Context context) {
<span style="white-space:pre">			</span>super(context);
<span style="white-space:pre">			</span>// Todo Auto-generated constructor stub
<span style="white-space:pre">			</span>mySurfaceHolder = getHolder();// 获得surfaceHolder引用
<span style="white-space:pre">			</span>mySurfaceHolder.addCallback(this);
<span style="white-space:pre">			</span>// Todo Auto-generated constructor stub
<span style="white-space:pre">		</span>}


  <span style="white-space:pre">	</span>public void surfaceCreated(SurfaceHolder holder){}
..........
}

情况照旧,唤醒时,把cocos主界面也覆盖了。下面是其log。



log中可注意到一件小事,destroy发生在remove之前,而remove是主程序在PushBackground时使用如下代码进行的。

case PushBackground:
	if(null != compass){
		compass.stop();
		Log.i("PushBackground","Compass stopped....");
}
else{
	Log.i("PushBackground","Compass not exist....");
}

if(mPreviewSV!=null){
	ViewGroup vg = (ViewGroup)mPreviewSV.getParent();  
    Log.i("PushBackground","child count=" + vg.getChildCount());  
    View viewCamera = null;
    for(int i=0; i<vg.getChildCount(); i++){ 
        View view = vg.getChildAt(i); 
        Log.i("PushBackground","index=" + i +":view = " + view+"   id="+view.getId());
        if(view.getId()==100){
        	viewCamera=view;
			vg.removeView(viewCamera);
			mPreviewSV=null;
			Log.i("PushBackground","Remove view = "+viewCamera+"  id="+view.getId());
        }
    }
    for(int i=0; i<vg.getChildCount(); i++){ 
        View view = vg.getChildAt(i); 
        Log.i("PushBackground","after clean------->index=" + i +":view = " + view+"   id="+view.getId());
        view.layout(120,120,250,250);
    }
}


也就是说for循环都还没list到mPreviewSV,它就已经destroy了。不过在后续循环中它仍旧被remove了。


分别在新线程中创建surfaceview,或者runonUIthread,没有什么区别,都存在surface在唤醒时,抢占顶层z序的问题。尝试使用bringToFront()将cocos的framelayout调到顶层,但是没什么作用。


ok,ok,看起来,应该是surfaceview太强大了,要不然就是新线程中运行的绘屏surface会永远在最上层吧。

cocos2dx 3D战斗类游戏制作:【四】——一些零散笔记,3D小地图,android surfaceview等的更多相关文章

  1. ios – 如何使用blender和PowerVR SDK为cocos3d创建一个简单的3d球体

    我是cocos3d的新手.我想创建一个简单的项目–旋转的3d球体.我用搅拌机设计了一个3d球体.所以我想要帮助创建collada文件和pod文件.使用blender和PowerVRSDK创建这个简单的3d对象时应该注意什么.谢谢解决方法如何在搅拌机中制作简单的球体,然后使用JeffLamarche的Blender-to-iOSscript将其导出?这甚至不需要Cocos或PowerVR,但这是一个良好的开端.由于您可以在iOS中轻松地将Cocos与非Cocos类集成,因此可能会有所帮助.你可以更进一步,利

  2. android – 从自定义SurfaceView获取位图

    我在一个扩展表面视图并实现runnable的类中有这个代码我能够使用该类基本上允许您使用不同的颜色等绘制到画布.我正在尝试获得一种方法,允许我在绘制图像后保存图像,这是方法.无论我做什么,我只是得到一个黑色的图像,没有任何东西.有任何想法吗?

  3. Android在相机预览上绘制

    如何在不分层SurfaceView的情况下执行此操作?解决方法你不能在具有Type.PUSH_BUFFERS的SurfaceView上进行locK和绘图.您必须在Z方向上创建原始视图上方的另一个视图,并在该视图中的SurfaceView上绘制.因此,在main.xml中,在FrameLayout中的原始视图下创建一个自定义视图.在活动视图中创建和处理SurfaceView.将此视图添加到相机预览显示中.通过SurfaceHolder启动自定义视图.在此视图中可以在画布上锁定和绘制.

  4. Android Surfaceview线程和内存泄漏

    我在android中创建一个游戏,我注意到游戏有内存泄漏.我设法将内存泄漏隔离到一个较小的应用程序,以便我可以看到很好的尝试和解决,如何解决它.该应用程序使用一个surfaceview作为其视图,并附加一个线程,以便完成所有绘图到屏幕.当我开始一个新活动并关闭我当前正在使用的活动时,会发生内存泄漏.当我在我的测试应用程序上执行内存转储时,我可以看到这一点,因为它只是打开并关闭一个活动(活动a–>活

  5. android – 在SurfaceView加载Camera Preview时显示我的布局

    我在BG线程中创建Cameraview的解决方案解决了无响应问题.但未能在SurfaceView中显示Camera输出.解决方案是从xml中删除SurfaceView.这将立即启动您的活动.加载新的“活动”布局后,可以以编程方式将新的SurfaceView添加到屏幕上.当然,这也需要时间,但您的UI会快速切换到新活动,并且您可以在SurfaceView和Camera加载时显示加载程序!

  6. android – 设置Surface View的背景颜色

    我想将表面视图的背景颜色设置为我的相机表面视图.我使用this来实现相同的功能.但这个例子并不完整.任何人都可以帮助我一些其他有用的链接.谢谢解决方法有一个解决方法来做到这一点.>为surfaceview添加父视图组,将背景颜色设置为此视图组而不是surfaceview;>为SurfaceView实例添加以下内容;现在你得到你想要的背景颜色,而surfaceview是tanslucent.

  7. Media Recorder在Android摄像头启动失败

    我正在制作视频录制应用程序,我想在其中显示预览,当用户点击录制按钮时,它开始录制,当用户点击停止按钮时,它停止录制.我在我的表面上进行了视频预览,但是当我按下开始按钮时,它会出现错误“MEDIA.RECORDER.START(NativeMEthod)”.这是我的代码请帮帮我们.}记录是解决方法我发现这个解决方案和它的工作正常,我解决了这个问题:)对于2.3android:只是改变:至:

  8. android – surfaceView.getHolder没有返回SurfaceHolder

    我正在尝试编写使用相机的应用程序.在尝试获取我最终传递给启动摄像头的surfaceCreated()的surfaceHolder时,我得到一个NullPointerException.getHolder()返回NULL时有什么情况吗?谢谢.解决方法开始一个新的答案,希望更清楚.同样,我认为根本问题是你在onCreate和onResume上做的事情的数量.我认为您遇到的根本问题是视图/活动生命周期的

  9. android – SurfaceView使用自定义相机缩放IN和OUT功能

    我已经编写了使用CustomCamera的代码,为此我使用的是SurfaceView,现在我想知道如果我需要实现ZoomIN和OUT功能,我从未使用过这种应用程序.我的代码,我用来创建自定义相机,见下文:MainActivity.java:-activity_main.xml中:–解决方法下面是缩放功能的示例代码.请尝试它是否可以帮助您:

  10. android – TextureView中的抗锯齿

    我尝试使用SurfaceView和TextureView播放相同的视频,并注意到使用TextureView渲染的图像比使用SurfaceView更具别名.这是什么原因?有没有办法配置TextureView的渲染看起来更好?TextureView的用法如下:而对于SurfaceView:解决方法好吧,似乎在TextureView上应用缩放就可以实现我正在寻找的“平滑”效果.这听起来像是一个奇怪的黑客……但它确实有效.挖掘改变渲染方面的缩放比例会很有趣……

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部