cococs2d-x 封装CCLOG(类 Android 多级日志系统应用)【亲测成功】

本文出自[无间落叶](转载请保留出处):http://blog.leafsoar.com/archives/2013/05-15-17.html

在 cocos2d-x 中实现类 Android 多级日志系统!写程序,免不了调试打印 Log ,而一个方便的日志系统,可以提高不少开发的效率,写过 Android 应用的朋友应该了解在 Android 中的日志包含很多等级,查看日志的时候可以指定日志的级别,从而过滤一些无用的信息,能够更为快速的定位问题的所在。而在 cocos2d-x 的开发中,统一使用CCLog,只能算是最基本的功能,既然有好的思想可以借鉴,何乐而不为呢~

先看看最终实现的效果,我们使用简单封装过的方法调用打印日志系统(Leafsoar Log:LSLog):

LSLog::verbose("博客名称: %s","无间落叶");
LSLog::debug("博客地址: %s", "http://blog.leafsoar.com");
LSLog::info("基本信息: %s", "吾名 一叶");
LSLog::warn("多出警告: %s %s", "警告一", "警告二");
LSLog::error("坐标错误: (%f, %f)", 800.0f, 600.0f);

// Linux 系统下打印信息 (非 Android)
cocos2d-x debug info [(verbose)  :博客名称: 无间落叶]
cocos2d-x debug info [(debug)        :博客地址: http://blog.leafsoar.com]
cocos2d-x debug info [(info)         :基本信息: 吾名 一叶]
cocos2d-x debug info [(warn)         :多出警告: 警告一 警告二]
cocos2d-x debug info [(error)        :坐标错误: (800.000000, 600.000000)]

在 Android 的 Logcat 下显示效果:图片

在 Android 平台,可以打印所有信息,并且通过 LogCat 过滤信息,还有相应的高亮显示。而这些都已经在 LSLog 内部通过 Jni 调用实现,如需如上所示的调用即可。

通过日志的等级划分过滤,可以让我们在调试某一个功能时只关注某一类调试信息,比如只显示警告信息和错误信息,而不是哗啦啦所有的日志都打印出来,然后一行一行读,查看,排错。

而在非 Android 平台,并没有如 LogCat 这样的工具,其它平台我不知晓,但我所在的 Linux 平台显然之用默认的日志打印,所以在 LSLog 的内部实现之中,通过一个开关控制显示哪些级别的日志信息,这个级别可以任意的定义。 看下面实现源码获取

// LSLog.h

#ifndef LSLOG_H_
#define LSLOG_H_

#include "cocos2d.h"

// 日志级别,也可根据自己需要修改添加类别
enum{
    LSLOG_VERBOSE = 0,
    LSLOG_DEBUG,
    LSLOG_INFO,
    LSLOG_WARN,
    LSLOG_ERROR,
    LSLOG_COUNT,
};

// 打印日志类别前缀
const std::string lsLog_name[LSLOG_COUNT] = {
        "(verbose)\t",
        "(debug)\t\t",
        "(info)\t\t",
        "(warn)\t\t",
        "(error)\t\t"
};

// 不同级别对应的 Android Jni 实现方法名称
const std::string lsLog_androidMethod[LSLOG_COUNT] = {
        "v",
        "d",
        "i",
        "w",
        "e"
};

/**
 @brief 自定义日志系统,前期使用,以后可以扩展优化
 */
class LSLog: public cocos2d::CCObject {
public:
    /// verbose 详细日志,一般常用的打印信息
    static void verbose(const char * pszFormat, ...);
    /// debug 调试 ,调试过程所注意的信息
    static void debug(const char * pszFormat, ...);
    /// info 一般信息,
    static void info(const char * pszFormat, ...);
    ///  warn 警告信息
    static void warn(const char * pszFormat, ...);
    /// error 错误信息
    static void error(const char * pszFormat, ...);
private:
    // 需要显示的日志级别定义
    static const int LOG_VALUE;
    // 打印日志方法
    static void printLog(int type, const char* format, va_list ap);
    // Android 平台日志打印
    static void printAndroidLog(const char* methodName, const char* log);
};

#endif /* LSLOG_H_ */

// LSLog.cpp

#include "LSLog.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

#include "platform/android/jni/JniHelper.h"
#include "platform/android/jni/Java_org_cocos2dx_lib_Cocos2dxHelper.h"
#include <jni.h>

#endif

USING_NS_CC;

#define kMaxStringLen (1024*100)
#define LOG_V 1
#define LOG_D 2
#define LOG_I 4
#define LOG_W 8
#define LOG_E 16

/// 需要打印的日志级别,根据 LOG_VALUE 的设置打印不同级别的日志
//const int LSLog::LOG_VALUE = LOG_V | LOG_D | LOG_I | LOG_W | LOG_E;
//const int LSLog::LOG_VALUE = LOG_D | LOG_I | LOG_W | LOG_E;
const int LSLog::LOG_VALUE = LOG_I | LOG_W | LOG_E;
//const int LSLog::LOG_VALUE = LOG_W | LOG_E;
//const int LSLog::LOG_VALUE = LOG_E;
//const int LSLog::LOG_VALUE = 0;

// 这里灵活控制,可以只打印某一个级别
//const int LSLog::LOG_VALUE = LOG_D;

void LSLog::verbose(const char * pszFormat, ...) {
    if (LOG_V & LOG_VALUE) {
        va_list ap;
        va_start(ap, pszFormat);
        LSLog::printLog(LSLOG_VERBOSE, pszFormat, ap);
        va_end(ap);
    }
}

void LSLog::debug(const char* pszFormat, ...) {
    if (LOG_D & LOG_VALUE) {
        va_list ap;
        va_start(ap, pszFormat);
        LSLog::printLog(LSLOG_DEBUG, pszFormat, ap);
        va_end(ap);
    }
}

void LSLog::info(const char* pszFormat, ...) {
    if (LOG_I & LOG_VALUE) {
        va_list ap;
        va_start(ap, pszFormat);
        LSLog::printLog(LSLOG_INFO, pszFormat, ap);
        va_end(ap);
    }
}

void LSLog::warn(const char* pszFormat, ...) {
    if (LOG_W & LOG_VALUE) {
        va_list ap;
        va_start(ap, pszFormat);
        LSLog::printLog(LSLOG_WARN, pszFormat, ap);
        va_end(ap);
    }
}

void LSLog::error(const char* pszFormat, ...) {
    if (LOG_E & LOG_VALUE) {
        va_list ap;
        va_start(ap, pszFormat);
        LSLog::printLog(LSLOG_ERROR, pszFormat, ap);
        va_end(ap);
    }
}

void LSLog::printLog(int type, const char* format, va_list ap) {
    char* pBuf = (char*) malloc(kMaxStringLen);
    std::string mstr;
    if (pBuf != NULL) {
        vsnprintf(pBuf, kMaxStringLen, format, ap);
        mstr = pBuf;
        free(pBuf);
    }
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    printAndroidLog(lsLog_androidMethod[type].c_str(), mstr.c_str());
#else
    CCLog("%s :%s", lsLog_name[type].c_str(), mstr.c_str());
#endif
}

void LSLog::printAndroidLog(const char* methodName, const char* log) {
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    JniMethodInfo t;
    bool isHave = JniHelper::getStaticMethodInfo(t,
            "android/util/Log",
            methodName,
            "(Ljava/lang/String;Ljava/lang/String;)I");
    if (isHave)
    {
        jstring jTitle = t.env->NewStringUTF("cocos2d-x");
        jstring jMsg = t.env->NewStringUTF(
                log);
        t.env->CallStaticVoidMethod(t.classID, t.methodID, jTitle,
                jMsg);
        t.env->DeleteLocalRef(jTitle);
        t.env->DeleteLocalRef(jMsg);
    }
    else
    {
        CCLog("the jni method is not exits");
    }
#endif
}

这使前期开发方便了许多,而使用自定义的日志系统,另一个好处就是后期扩展,比如我们想将日志保存文本,收集错误信息等,都可以只通过修改日志内部方法的实现即可完成 ~

源码下载:

https://github.com/leafsoar/ls-cocos2d-x/tree/master/Learn/Classes

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Cocos 3D是一个用于开发3D游戏和应用程序的框架,它基于Cocos2d-x引擎。在Cocos 3D中,坐标系可以分为世界坐标系、模型坐标系和观察坐标系。 要将3D坐标转换为2D坐标,我们首先需要确定摄像机的位置和观察方向。通过设置摄像机的位置和方向,可以确定观察坐标系。然后,我们可以使用透视投影或正交投影来将3D场景投射到2D平面上。 在Cocos 3D中,可以使用Viewport(视口)和Camera(摄像机)来控制3D到2D的转换。视口决定了渲染的区域,而摄像机则定义了观察坐标系。 在代码中,可以通过以下步骤将3D坐标转换为2D坐标: 1. 创建一个Viewport,并设置它的大小和位置。 2. 创建一个Camera,并设置它的位置、观察目标和投影方式(透视或正交)。 3. 将需要转换的3D坐标传递给Camera的unproject方法。 unproject方法可以将3D坐标转换为在视口中的2D坐标。它将返回一个Vec3对象,其中包含在视口中的2D坐标。 以下是一个简单的示例代码,展示如何将3D坐标转换为2D坐标: ```cpp // 创建一个Viewport auto viewport = Viewport::create(0, 0, screenWidth, screenHeight); // 创建一个Camera auto camera = Camera::createPerspective(60, screenWidth / screenHeight, 0.1f, 1000); // 设置Camera的位置和观察目标 camera->setPosition3D(Vec3(0, 0, 10)); camera->lookAt(Vec3(0, 0, 0)); // 将3D坐标(1, 1, 1)转换为2D坐标 Vec3 worldPosition(1, 1, 1); Vec3 screenPosition = camera->unproject(viewport, worldPosition); // 打印转换后的2D坐标 CCLOG("2D坐标:(%f, %f)", screenPosition.x, screenPosition.y); ``` 通过以上步骤,我们可以将3D坐标转换为2D坐标,并将结果保存在screenPosition变量中。在示例中,我们将3D坐标(1, 1, 1)转换为2D坐标,并打印结果。 需要注意的是,3D坐标转换为2D坐标需要在渲染之前进行,因此最好在update或draw函数中进行转换。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值