当前位置:  编程技术>移动开发
本页文章导读:
    ▪rt-thread线程调试器获取现阶段最高优先级线程算法分析        rt-thread线程调试器获取当前最高优先级线程算法分析上一章大概分析了rt-thread操作系统的线程调试器的源码,此文具体来讲讲rt-thread在调试时,是如何获取获得当前最高优先级线程的算法过.........
    ▪ 漫话QML        漫谈QML                               漫谈 QML/Qt Quick        QML是从Qt 4.7开始引入的,QML是一种声明语言,使得可以像设计师思考的一样编码,并且Qt Quick元素就是应用程序的编译单元,.........
    ▪ 基于WiEngine游戏发动机的Sample       基于WiEngine游戏引擎的Sample转发,请保持地址:http://blog.csdn.net/stalendp/article/details/8589324 最近在开发一款游戏,做demo的时候,使用了Cocos2d和WiEngine游戏引擎。我先做了Cocos2d端的demo,然后移植.........

[1]rt-thread线程调试器获取现阶段最高优先级线程算法分析
    来源: 互联网  发布时间: 2014-02-18
rt-thread线程调试器获取当前最高优先级线程算法分析

上一章大概分析了rt-thread操作系统的线程调试器的源码,此文具体来讲讲rt-thread在调试时,是如何获取获得当前最高优先级线程的算法过程。

之前已提到过,rt-thread采用了一个位图来实现此过程,在具体分析此过程之前,我们首先来看看此位图的结构及相关的一些参数变量。

1 位图结构及相关参数 1.1 位图结构

在rt-thread的源码文件scheduler.c中在一位图,如下定义:

const rt_uint8_t rt_lowest_bitmap[] =
{
    /* 00 */ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 10 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 20 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 30 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 40 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 50 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 60 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 70 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 80 */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 90 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* A0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* B0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* C0 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* D0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* E0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* F0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};

从这里暂时我们看不出什么名堂出来,暂且跳过,且再看些与此位图相关的一些参数.

1.2 与位图相关的参数

还是在scheduler.c源文件中有一些全局变量,如下定义:

rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];//线程就绪表,上一篇文章已有介绍
struct rt_thread *rt_current_thread;//当前正在运行的线程

rt_uint8_t rt_current_priority;//保存当前正在运行的线程的优先级

#if RT_THREAD_PRIORITY_MAX > 32//最多优先级大于32时
/* Maximum priority level, 256 */
rt_uint32_t rt_thread_ready_priority_group;//暂且叫做就绪优先级组
rt_uint8_t rt_thread_ready_table[32];//暂且叫做就绪表
#else
/* Maximum priority level, 32 */
rt_uint32_t rt_thread_ready_priority_group;//就绪优先级组
#endif

由上源码可知,不管用户设置定义最大优先级是多少,都存在全局变量就绪优先级组,而只有当最大优先级大于32个优先级时,才会存在另一个全局变量就就绪表,它是一个数组,含义暂先不管,接着看后述内容。

1.3 线程控制块中与位图相关的参数

之前已有介绍有关线程控制块包含的成员变量,但对其部分有关位图操作的参数并未做详情介绍,如下:

//...    
/* priority */
    rt_uint8_t  current_priority;                       /**< current priority */
    rt_uint8_t  init_priority;                          /**< initialized priority */
#if RT_THREAD_PRIORITY_MAX > 32
    rt_uint8_t  number;
    rt_uint8_t  high_mask;
#endif
    rt_uint32_t number_mask;
//...

从上述源码可知,线程控制块中,只有当用户定义的最大优先级大于32个时,才会存在number和high_mask两个成员变量,这两个成员变量及另一个成员变量number_mask都是用来作位图运算用的,只不过后面那个成员变量number_mask不管用户定义的优先级个数大于32还是在32个优先级以内都会存在。它们的含义暂且看后述内容解说.

2 参数在初始化时的变化

在thread.c源文件中的_rt_thread_init函数中:

//...
thread->init_priority    = priority;
thread->current_priority = priority;
//...
得知在线程初始化时,已经将线程的当前优先级设为初始优先级.

在启动线程函数rt_thread_startup中有如下代码:

//...
    /* calculate priority attribute */
#if RT_THREAD_PRIORITY_MAX > 32
    thread->number      = thread->current_priority >> 3;            /* 5bit */
    thread->number_mask = 1L << thread->number;
    thread->high_mask   = 1L << (thread->current_priority & 0x07);  /* 3bit */
#else
    thread->number_mask = 1L << thread->current_priority;
#endif
//...

从上述代码可知,初次启动后的线程的成员number取当前优先级右移三位所得的值,即取高5位的值.

而将1左移number次所得的值做为number_mask的值,而high_mask的值取将1左移thread->current_priority &0x07后的值,即左称当前优先级低三位所代表的值.

由此可见,当用户定义的优先级等级多于32个时,优先级的高5位和低3位是表示不同含义的,看来优先级只是与位图掩码相关而已.

3 参数在线程调试过程中的变化

在线程rt_thread_startup后,系统会调用rt_thread_resume函数将线程立即运行,而在rt_thread_resume函数中,系统会调用rt_schedule_insert_thread函数将线程加入到调试器中,接着在rt_schedule_insert_thread函数中,系统会操作线程就绪表rt_thread_ready_table和线程就绪优先级组rt_thread_ready_priority_group,如下代码所示:

//...
#if RT_THREAD_PRIORITY_MAX > 32
    rt_thread_ready_table[thread->number] |= thread->high_mask;
#endif
    rt_thread_ready_priority_group |= thread->number_mask;
//...
由上可见,系统以thread->number值作为下标,在线程就绪表rt_thread_ready_table中对应的值或上thread->high_mask,而线程就绪优先级组th_thread_ready_priority_group的值或上thread->number_mask.

4 调试中获取当前最高优先级线程过程

接下来当然是最重要的,也就是本文的核心内容啦,之前那么多内容其实都是讲相关参数是如何变化的,因为这些参数在获取最高优先级的过程中将会使用到,因此有必要对其变化过程作个说明.

在线程调试函数rt_schedule,系统使用如下代码来获取当前最高优先级线程,代码如下:

//...
        register rt_ubase_t highest_ready_priority;

#if RT_THREAD_PRIORITY_MAX == 8
        highest_ready_priority = rt_lowest_bitmap[rt_thread_ready_priority_group];//如果用户设置优先级总共为8个时最简单
#else
        register rt_ubase_t number;//number为一中间参数
        /* find out the highest priority task */
        if (rt_thread_ready_priority_group & 0xff)//以rt_thread_ready_priority_group的取值人条件,然后在位图中找到number这一中间参数的值
        {
            number = rt_lowest_bitmap[rt_thread_ready_priority_group & 0xff];
        }
        else if (rt_thread_ready_priority_group & 0xff00)
        {
            number = rt_lowest_bitmap[(rt_thread_ready_priority_group >> 8) & 0xff] + 8;
        }
        else if (rt_thread_ready_priority_group & 0xff0000)
        {
            number = rt_lowest_bitmap[(rt_thread_ready_priority_group >> 16) & 0xff] + 16;
        }
        else
        {
            number = rt_lowest_bitmap[(rt_thread_ready_priority_group >> 24) & 0xff] + 24;
        }
//接着再以number为因数,在位图和线程就绪表中经过一算法得到最高就绪优先级,这种算法有点怪,不是太明白为什么要这样做
//其实这并不妨碍我们理解,只要理解这是一种已经做好的算法即可
#if RT_THREAD_PRIORITY_MAX > 32 
highest_ready_priority = (number << 3) + rt_lowest_bitmap[rt_thread_ready_table[number]];
#else 
highest_ready_priority = number;
#endif
#endif 
/* get switch to thread */ 
to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,//最终从优先级算法系统中对应的就绪队列中得到相应的线程 
struct rt_thread, tlist);
//...

5 线程失去占用CPU时的参数变化

有以下几种方式线程将失去CPU:

主动失去CPU:

        1:源码中调用sleep,delay函数使用线程放弃CPU.

         2:源码中调用suspend使线程挂起.

被动失去CPU:

        1:线程的时间片耗尽,被迫放弃CPU.

         2:系统产生中断,线程暂时失去CPU,一旦中断例程执行完,还是会还原,这些是由硬件自动完成的.

在线程主动失去CPU时,程序最终会执行rt_schedule_remove_thread函数,将当前线程从调试器中移除.而在被动失去CPU中(这里指第一种,第二种完全由硬件来完成,不需要软件干预),程序会执行rt_list_remove(&(thread->tlist));同样将当前线程从调度器中移除,然后再执行: rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),&(thread->tlist));将当前线程加入到调试器中对应队列末尾,紧接着执行rt_schedule();重新调试线程.

     由此可见,在被动失去CPU的过程中,程序并未操作与获取线程最高优先级算法相关的几个参数,接上来看看rt_schedule_remove_thread函数:

/*
 * This function will remove a thread from system ready queue.
 *
 * @param thread the thread to be removed
 *
 * @note Please do not invoke this function in user application.
 */
void rt_schedule_remove_thread(struct rt_thread *thread)
{
    register rt_base_t temp;

    RT_ASSERT(thread != RT_NULL);

    /* disable interrupt */
    temp = rt_hw_interrupt_disable();

#if RT_THREAD_PRIORITY_MAX <= 32
    RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("remove thread[%s], the priority: %d\n", 
                                      thread->name, thread->current_priority));
#else
    RT_DEBUG_LOG(RT_DEBUG_SCHEDULER,
                 ("remove thread[%s], the priority: %d 0x%x %d\n", 
                  thread->name,
                  thread->number,
                  thread->number_mask,
                  thread->high_mask));
#endif

    /* remove thread from ready list */
    rt_list_remove(&(thread->tlist));//将当前线程从就绪队列中移除
    if (rt_list_isempty(&(rt_thread_priority_table[thread->current_priority])))
    {
#if RT_THREAD_PRIORITY_MAX > 32//之前参数操作的逆操作
        rt_thread_ready_table[thread->number] &= ~thread->high_mask;
        if (rt_thread_ready_table[thread->number] == 0)
        {
            rt_thread_ready_priority_group &= ~thread->number_mask;
        }
#else
        rt_thread_ready_priority_group &= ~thread->number_mask;
#endif
    }

    /* enable interrupt */
    rt_hw_interrupt_enable(temp);
}

由上述源码可见,在rt_schedule_remove_thread函数中,程序对与线程调试器获取最高优先级相关的几个参数做了逆操作.


6 后记

整个算法过程分析完毕,其实在目前为止,这里并没有对这个位图原理做出解释,个人认为,这并没多大关系,我们只需要知道,正是这么一个操作流程,结合这个位图,才得到一个与时间无关的算法.这个就是rt-thread操作系统线程调试的核心.




 

    
[2] 漫话QML
    来源: 互联网  发布时间: 2014-02-18
漫谈QML
                               漫谈 QML/Qt Quick

       QML是从Qt 4.7开始引入的,QML是一种声明语言,使得可以像设计师思考的一样编码,并且Qt Quick元素就是应用程序的编译单元,每一帧的故事板被声明为元素树中的一个分支,每一个视觉方面的分支元素的属性被声明为一帧,每帧之间的过渡可装饰各种动画和特效。

       Qt Quick运行时实现了UI并且提供直接访问本地API的功能,并且在适当的时候可以使用C++扩展获取更好的性能。由于Qt Quick的运行时也是在Qt内部实现的,所以可以十分简单的做到跨平台。

       Qt是为现代产品开发方式所构建的。核心的逻辑部分由开发者编码并优化,用户界面由设计师通过可视化工具完成。Qt也集成了工具,支持这种方式的迭代开发。

       Qt Quick是构建在强大的Qt之上。QML可以用来扩展已经存在的应用或者是构建全新的应用。QML是完全从C++扩展而来的。

      QML文档在硬盘或者是网络资源上生成纯文本文件,但是也可以通过文本数据构造。

      我们来看看一个简单的QML文件的格式:


        再来看看效果:


          其实QML只是一种语言,它主要是定义了QML文件的语法,以及QML语言的基本实现。而Qt Quick内置很多常用的元素,使得我们可以很方便的使用。我个人将QML和Qt Quick的关系类比编程语言和编程框架(或者函数库)。

        Qt Quick内置了很多常用的可视化元素,主要如下图:


         Qt Quick也提供了对动画,以及模型/视图编程,以及数据存储等方面的支持。

         下面我们来看看Qt 提供的文档对QML和Qt Quick的介绍。

首先是QML:

        Qt QML模块为使用QML语言开发应用程序提供了框架和库。它定义并实现了语言以及引擎,并且提供了API使得应用程序开发者可以使用自定义类型扩展QML语言,并且将QML代码和JavaScript,C++集成。

        Qt QML模块提供了QtQml QML模块,该模块提供了一系列核心的QML类型,用于创建QML应用;也提供了QtQml C++模块,该模块提供了一系列的C++ API用于使用自定义类型扩展QML应用,并且将C++实现集成到QML应用程序中。

         QML模块提供的QML类型:


         QML模块提供的C++ API:


        注意:Qt QML模块只提供语言以及QML的基本实现,并不提供一个可视化的画布或者渲染引擎用于创建用户界面。这两个部分都是由Qt Quick提供的Qt Quick提供了许多组件,模型/视图支持,动画框架并且许多用于创建用户界面的QML细节。

再来看看Qt Quick:

        Qt Quick是用于创建QML应用程序的标准库。Qt QML模块提供QML的引擎以及语言基础,Qt Quick模块提供QML创建基本用户界面的常用元素。它提供了可视化的画布用于创建和绘制可视化组件,接受用户输入,创建数据模型,视图以及代理。

        Qt Quick模块提供了QtQuick QML模块,该模块提供了一系列用于创建用户界面的QML类型;也提供QtQuick C++模块,该模块提供一系列C++ API用于集成用户界面和QtQuick QML模块

        Qt Quick提供的基本QML类型:


          Qt Quick提供的C++ API:




    
[3] 基于WiEngine游戏发动机的Sample
    来源: 互联网  发布时间: 2014-02-18
基于WiEngine游戏引擎的Sample

转发,请保持地址:http://blog.csdn.net/stalendp/article/details/8589324

最近在开发一款游戏,做demo的时候,使用了Cocos2d和WiEngine游戏引擎。我先做了Cocos2d端的demo,然后移植到android端。在移植的过程中,我使用了WiEngine,由于WiEngine提供了和Cocos2d很相似的API,所以能够很快地从cocos2d迁移。

下面的demo的截图(申明:demo使用的图片资源来源于网络,只是用于学习,如果有版权问题,请联系我:stalendp@gmail.com)



本例子中只是简单地用到了Sprite和SpriteBatchNode等概念,使用TexturePacker进行了图片的处理。WiEngine中读取TexturePacker信息的类为wyZwoptexManager, 代码如下:

wyZwoptexManager* zm = wyZwoptexManager::getInstance();
wyTexture2D* tex = wyTexture2D::makePNG(RES("R.drawable.renzhet"));
zm->addZwoptex("renzhet", RES("R.raw.renzhet"), tex);

这样整个plist文件通过XML解析,被加载到内存(frame对象),就可以生成sprite了(关于引擎的原理性方面,以后有机会再写文章深入吧)。

如果用Cocos2d,类似的代码为:

CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:@"renzhet.plist"];

使用方法如下:

wyZwoptexManager* zm = wyZwoptexManager::getInstance();
wySprite* sprite = zm->makeSprite("boy1.png");

相应的Cocos2d代码:

 if(self=[super initWithSpriteFrameName:@"boy1.png"]) //别的写法可能更合适

其他请参考完整代码吧。

下面是完整的C++代码:

#ifndef SAMPLE_H_
#define SAMPLE_H_

#include "com_wiyun_engine_skeleton_Skeleton.h"
#include "FirstScene.h"
#include <cstdlib>

#include <android/log.h>

#define  LOG_TAG    "SkeletonProject"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)

void runSample();

class CloudCache;
class ttCloud;
class Background;
class BoyAndDog;

void log(const char* msg);

float genRand() {
	return rand() % 10000 / 10000.0f;
}

wyLabel* m_hint;


class Cloud: public wyLayer {
private:

	wySprite* cloud;
	float speed;

public:
	Cloud() {
		buildCloud();
	}

	virtual ~Cloud() {

	}

	void buildCloud() {
		wyZwoptexManager* zm = wyZwoptexManager::getInstance();

		char buf[50];
		sprintf(buf, "cloud_%d.png", 1);
		cloud = zm->makeSprite(buf);

		cloud->setScale(0.5f);
		addChildLocked(cloud);
		this->setVisible(false);

		wyTimer* timer = wyTimer::make(
				wyTargetSelector::make(this, SEL(Cloud::onUpdateSprite)));
		scheduleLocked(timer);
	}

	void spawn() {
		LOGI("Cloud#spawn");
		this->setVisible(true);
		speed = genRand() * 0.3f + 0.2f;

		cloud->setPosition(wyDevice::winWidth + getContentSize().width / 2,
				genRand() * wyDevice::winHeight / 3 + wyDevice::winHeight / 2);

		char msg[50];
		sprintf(msg, "posy: %f", cloud->getPositionY());
		LOGI(msg);

	}

	void onUpdateSprite(wyTargetSelector* ts) {

		if (cloud->isVisible()) {

			cloud->setPosition(cloud->getPositionX() - speed,
					cloud->getPositionY());
			if (cloud->getPositionX() < 0) {
				this->setVisible(false);
				cloud->stopAllActions(true);
			}
		}

	}
};
class CloudCache: public wyLayer {
private:
	Cloud* clouds[10];
public:
	CloudCache() {
		for (int i = 0; i < 10; i++) {
			clouds[i] = new Cloud();
			clouds[i]->setVisible(false);
			addChildLocked(clouds[i]);
		}
		clouds[0]->spawn();
		wyTimer* timer = wyTimer::make(
				wyTargetSelector::make(this, SEL(CloudCache::onUpdateSprite)));
		scheduleLocked(timer);
	}
	virtual ~CloudCache() {

	}

	void spawn() {

		for (int i = 0; i < 10; i++) {
			Cloud* cloud = clouds[i];
			if (!cloud->isVisible()) {
				cloud->spawn();
				break;
			}
		}

	}

	void onUpdateSprite(wyTargetSelector* ts) {
		float rr = genRand();
		if (rr < 0.001) {
			spawn();
		}
	}
};

class Background: public wyLayer {
private:
	wySprite* bg[4];
public:
	Background() {
		buildbg1();
		buildbg2();
	}

	virtual ~Background() {

	}

	void buildbg1() {
		wySprite* bg = wySprite::make(
				wyTexture2D::makeJPG(RES("R.drawable.bg1")));
		bg->setPosition(wyDevice::winWidth / 2, wyDevice::winHeight / 2 + 50);
		bg->setScale(0.5f);
		addChildLocked(bg);
	}

	void buildbg2() {
		wyZwoptexManager* zm = wyZwoptexManager::getInstance();
		for (int i = 0; i < 4; i++) {
			int id = i / 2;
			char sn[20];
			sprintf(sn, "bg%d.png", id + 2);
			bg[i] = zm->makeSprite(sn);
			bg[i]->setPosition(bg[i]->getContentSize().width * (i%2),
					bg[i]->getContentSize().height / 2);
			addChildLocked(bg[i]);
		}

		// start to update
		wyTimer* timer = wyTimer::make(
				wyTargetSelector::make(this, SEL(Background::onUpdateSprite)));
		scheduleLocked(timer);
	}

	void onUpdateSprite(wyTargetSelector* ts) {
		for (int i = 0; i < 4; i++) {
			if (bg[i]->getPositionX() < -bg[i]->getContentSize().width) {
				bg[i]->setPosition(bg[i]->getContentSize().width-0.3,
						bg[i]->getPositionY());
			}
			int id = i / 2;
			bg[i]->setPosition(bg[i]->getPositionX() - 0.1f - 0.7f * id,
					bg[i]->getPositionY());

		}
	}
};

class BoyAndDog: public wyLayer {
public:
	BoyAndDog() {
		wySprite* boy = buildBoy();
		wySprite* dog = buildDog();
		boy->setPosition(wyDevice::winWidth / 2,
				boy->getContentSize().height / 2);
		dog->setPosition(wyDevice::winWidth / 2 - 80,
				dog->getContentSize().height / 2 - 10);

		addChildLocked(boy);
		addChildLocked(dog);
	}

	virtual ~BoyAndDog() {
	}

	wySprite* buildBoy() {
		wyZwoptexManager* zm = wyZwoptexManager::getInstance();

		// add sprite
		wySprite* sprite = zm->makeSprite("boy1.png");

		// create animation and add it to atlas sprite
		char buf[128];
		wyAnimation* anim = wyAnimation::make(0);
		for (int i = 1; i <= 4; i++) {
			sprintf(buf, "boy%d.png", i);
			wySpriteFrame* f = zm->getSpriteFrame(buf);
			f->setDuration(0.15f);
			anim->addFrame(f);
		}

		wyAnimate* a = wyAnimate::make(anim);
		wyRepeatForever* rp = wyRepeatForever::make(a);
		sprite->runAction(rp);
		return sprite;
	}
	wySprite* buildDog() {
		wyZwoptexManager* zm = wyZwoptexManager::getInstance();

		// add sprite
		wySprite* sprite = zm->makeSprite("0.png");
		sprite->setFlipX(true);

		// create animation and add it to atlas sprite
		char buf[128];
		wyAnimation* anim = wyAnimation::make(0);
		int si = 3 * 4;
		for (int i = si; i < 4 + si; i++) {
			sprintf(buf, "%d.png", i);
			wySpriteFrame* f = zm->getSpriteFrame(buf);
			f->setDuration(0.1f);
			anim->addFrame(f);
		}

		wyAnimate* a = wyAnimate::make(anim);
		wyRepeatForever* rp = wyRepeatForever::make(a);
		sprite->runAction(rp);
		return sprite;
	}
};

void log(const char* msg) {
	if (m_hint != NULL) {
		m_hint->setText(msg);
	}
}

//
void runSample() {

	// init the texture

	wyZwoptexManager* zm = wyZwoptexManager::getInstance();
	wyTexture2D* tex = wyTexture2D::makePNG(RES("R.drawable.renzhet"));
	zm->addZwoptex("renzhet", RES("R.raw.renzhet"), tex);
	tex = wyTexture2D::makePNG(RES("R.drawable.dog"));
	zm->addZwoptex("dog", RES("R.raw.dog"), tex);

	// setup the texture
	wyDirector* director = wyDirector::getInstance();
	director->setShowFPS(true);

	// create scene
	wyScene* scene = new wyScene();

	m_hint = wyLabel::make("display some information here", SP(20));
	m_hint->setPosition(wyDevice::winWidth / 2,
			wyDevice::winHeight - m_hint->getContentSize().height / 2);

	scene->addChildLocked(new Background());
	scene->addChildLocked(new BoyAndDog());
	scene->addChildLocked(new CloudCache());

	scene->addChildLocked(m_hint);

	// run with it
	director->runWithScene(scene);

	// release, the scene and action will be hold by others
	// so this won't destory them
	wyObjectRelease(scene);
}

说明:本例子中没有对内存进行考虑,所以有内存溢出的bug,细心的读者如果能指出来,感激不尽。


====

最后,记录一个android截图的技巧,防止忘记:

使用Android SDK文件夹下tool文件夹下的ddms,然后点击菜单Device=>Screen Capture..或者直接按组合键,ctrl+S,会再弹出一个对话框,也就是截图的对话框,这个时候,你可以刷新,旋转,保存或者复制手机的截图了



    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3