大唐豪侠论坛出的四连影响上乘心法和附加密籍的修练么?

大唐豪侠二级心法秘笈_百度知道
大唐豪侠二级心法秘笈
可是打到25级了都只有经验拿积分完全没有是怎么回事啊?!怎么才能弄到一都说是去长安试炼官那里打积分
提问者采纳
二,三,四级心法秘笈在各门派秘籍弟子那就有卖的你哪个区呀楼主刚玩的大唐吧
大唐豪侠很经典啊积分好像得群体试炼才有吧 太久没玩 也不太确定了不过 确定的是一
提问者评价
其他类似问题
大唐豪侠的相关知识
其他2条回答
1 2心法在各个门派秘笈弟子那里有的买
试练好象老早没积分了啊..心法秘籍1-5心么,秘籍弟子有得卖的.招式提升秘籍么,就要打怪了..或者问别人买
您可能关注的推广
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁礼物:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵) - 推酷
礼物:《红孩儿引擎内功心法修练与Cocos2d-x》之结点系统(场景,层,精灵)
另:好吧,我彻底被Cocos2d-x版本的更新速度打败了!我决定停止再对2.0.2版本再做深入分析讲解。本博文实为新书的节选,做为礼物送给大家,望各位仔细阅读后提出批评!
& & & 另:本周末工具箱会更新到0.1.1版本,欢迎下载并到官方论坛提出BUG反馈和使用建议。
本节的学习目标:
(1)&&&&了解结点系统,学会自行构建结点系统。
(2)&&&&了结场景,层,精灵的组织关系与各自功能
2.1 结点系统原理入门
2.1.1 结点启蒙:
在介绍Cocos2d-x的结点系统之前,我们需要首先做一些启蒙,什么是树?
一棵树(tree)是由n(n&0)个元素组成的有限集合,其中:
(1)每个元素称为结点(node);
(2)有一个特定的结点,称为根结点或根(root);
(3)除根结点外,其余结点被分成m(m&=0)个互不相交的有限集合,而每个子集又都是一棵树(称为原树的子树)
对于树结构有几个概念要记一下:
:树的度——也即是宽度,简单地说,就是结点的分支数。以组成该树各结点中最大的度作为该树的度,如上图的树,其度为3;树中度为零的结点称为叶结点或终端结点。树中度不为零的结点称为分枝结点或非终端结点。除根结点外的分枝结点统称为内部结点。
:树的深度——组成该树各结点的最大层次,如上图,其深度为4;
:根结点的层次为1,其他结点的层次等于它的父结点的层次数加1.
&&&&&&&& 请仔细观察上图这棵树,这里A是根结点,其余结点均是属于A的不同层级的子结点。我们由此图进一步进行想像,人的身体其实也是一棵树。
&&&&&&&& 上图详细表现了人体树结构的组织结构,左边是人形的结构,右边是层级关系展开。它作为骨骼动画的基础理论被广泛的应用于各类游戏动画中。
&&&&&&&& 我们看一下这张图,首先有一个根骨(脊椎),这个根骨即是树结构中的根结点。根骨下有三根子骨骼(左胯,右胯,颈背),这三根子骨骼也各自有属于自已的子骨骼树结构,同时它们由父骨骼牵引并牵引着子骨骼,与父骨骼和第一层子骨骼保持着固定的距离。
&&&&&&&& 试想一下:
&&&&&&&& 当我们想把这个人移动到一个位置点时,只需要把根骨移动到相应位置,即这个人的所有骨骼都会被这种牵引关系移动到这个世界位置的相对骨骼位置。但如果我们把左胯这根骨骼去掉的话,则在移动根骨后,左胯仍停留在原地,它已经不再属于当前骨骼树了,而成了一棵独立的骨骼树。
&&&&&&&& 看完这张图,已经比较接近我们所要讲述的内容了,对于骨骼结构的理解将有助于我们掌握远大于骨骼动画本身的结构模式,因为由此理论基础我们将学会一切基于结点树结构的系统。
&&&&&&&& 下面我们来用C++的代码构建这样一套系统。
首先,我们创建一个基类,称之为结点。
class CNode
virtual ~CNode();
inline void Update();
inline void Draw();
//设置当前结点名称
void SetName(const char* szName);
//取得当前结点名称
const string& GetName();
//加入一个子结点类
void AddChild(CNode* pChildNode);
//取得子结点
CNode* GetFirstChild();
//加入一个兄弟结点类
void AddBorther(CNode* pBortherNode);
//取得兄弟结点
CNode* GetFirstBorther();
//删除一个结点
bool DelNode(CNode* pNode);
//清空所有子结点
void DelAllChild();
//清空所有兄弟结点
void DelAllBorther();
//查询某个子结点-- 纵向查询
CNode* QueryChild(const char* szName);
//查询某个兄弟结点-- 横向查询
CNode* QueryBorther(const char* szName);
//为了方便检测结点树系统的创建结果,这里增加了一个保存结点树到XML文件的函数。
bool SaveNodeToXML(const char* szXMLFile);
protected:
//设置父结点
void SetParent(CNode* pParentNode);
//取得父结点
CNode* GetParent();
//保存结点树到XML文件,这个函数是只生成本结点的信息。
bool SaveNodeToXML(FILE* hFile);
//当前结点名称
string m_strNodeN
CNode* m_pParentN
//第一个子结点
CNode* m_pFirstC
//第一个兄弟结点
对应的实现:
#include &Node.h&
CNode::CNode()
m_strNodeName[0] = '\0';
m_pParentNode = NULL;
m_pFirstChild = NULL;
m_pFirstBorther = NULL;
CNode::~CNode()
DelAllChild();
void CNode::Update()
if(m_pFirstChild)
m_pFirstChild-&Update();
//在这里增加你更新结点的处理
if(m_pFirstBorther)
m_pFirstBorther-&Update();
//直接渲染
void CNode::Draw()
if(m_pFirstChild)
m_pFirstChild-&Draw();
//在这里增加你渲染图形的处理
if(m_pFirstBorther)
m_pFirstBorther-&Draw();
//设置当前结点名称
void CNode::SetName(const char* szName)
m_strNodeName = szN
//取得当前结点名称
const string& CNode::GetName()
return m_strNodeN
//加入一个子结点类
void CNode::AddChild(CNode* pChildNode)
if(pChildNode)
if(m_pFirstChild)
m_pFirstChild-&AddBorther(pChildNode);
m_pFirstChild = pChildN
m_pFirstChild-&SetParent(this);
//取得子结点
CNode* CNode::GetFirstChild()
return m_pFirstC
//加入一个兄弟结点类
void CNode::AddBorther(CNode* pBortherNode)
if(pBortherNode)
if(m_pFirstBorther)
m_pFirstBorther-&AddBorther(pBortherNode);
m_pFirstBorther = pBortherN
m_pFirstBorther-&SetParent(m_pParentNode);
//取得兄弟结点
CNode* CNode::GetFirstBorther()
return m_pFirstB
//删除一个子结点类
bool CNode::DelNode(CNode* pTheNode)
if(pTheNode)
if(m_pFirstChild)
if(m_pFirstChild == pTheNode)
m_pFirstChild = pTheNode-&GetFirstBorther();
delete pTheN
if(true == m_pFirstChild-&DelNode(pTheNode))
if(m_pFirstBorther)
if(m_pFirstBorther == pTheNode)
m_pFirstBorther = pTheNode-&GetFirstBorther();
delete pTheN
if(true == m_pFirstBorther-&DelNode(pTheNode))
//清空所有子结点
void CNode::DelAllChild()
if(m_pFirstChild)
CNode * pBorther = m_pFirstChild-&GetFirstBorther();
if(pBorther)
pBorther-&DelAllBorther();
pBorther = NULL;
delete m_pFirstC
m_pFirstChild = NULL;
//清空所有兄弟结点
void CNode::DelAllBorther()
if(m_pFirstBorther)
m_pFirstBorther-&DelAllBorther();
delete m_pFirstB
m_pFirstBorther = NULL;
//查询某个子结点-- 纵向查询
CNode* CNode::QueryChild(const char* szName)
if(szName)
if(m_pFirstChild)
//如果是当前子结点,返回子结点。
if(0 == strcmp(szName,m_pFirstChild-&GetName().c_str()))
return m_pFirstC
//如果不是,查询子结点的子结点。
CNode* tpChildChild = m_pFirstChild-&QueryChild(szName);
if(tpChildChild)
return tpChildC
//如果还没有,查询子结点的兄弟结点。
return m_pFirstChild-&QueryBorther(szName);
return NULL;
//查询某个兄弟结点-- 横向查询
CNode* CNode::QueryBorther(const char* szName)
if(szName)
if(m_pFirstBorther)
if(0 == strcmp(szName,m_pFirstBorther-&GetName().c_str()))
return m_pFirstB
//如果不是,查询子结点的子结点。
CNode* tpChildChild = m_pFirstBorther-&QueryChild(szName);
if(tpChildChild)
return tpChildC
return m_pFirstBorther-&QueryBorther(szName);
return NULL;
//设置父结点
void CNode::SetParent(CNode* pParentNode)
m_pParentNode = pParentN
//取得父结点
CNode* CNode::GetParent()
return m_pParentN
//保存结点树到XML
bool CNode::SaveNodeToXML(const char* szXMLFile)
hFile = fopen(szXMLFile,&wt&);
if(!hFile)
fprintf(hFile,TEXT(&&?xml version=\&1.0\& encoding=\&UTF-8\&?&\n&));
fprintf(hFile,TEXT(&&!DOCTYPE plist PUBLIC \&-//Apple Computer//DTD PLIST 1.0//EN\& \&/DTDs/PropertyList-1.0.dtd\&&\n&));
fprintf(hFile,TEXT(&&!--Honghaier Game Tutorial --&\n&));
fprintf(hFile,TEXT(&&plist version=\&1.0\&&\n&));
fprintf(hFile,TEXT(&&dict&\n&));
//========================================================
fprintf(hFile,TEXT(&&key&NodeTree&/key&&));
fprintf(hFile,TEXT(&&dict&&));
if(false == SaveNodeToXML(hFile))
fclose(hFile);
fprintf(hFile,TEXT(&&/dict&&));
//========================================================
fprintf(hFile,TEXT(&&/dict&&));
fprintf(hFile,TEXT(&&/plist&\n&));
fclose(hFile);
//保存结点树到XML
bool CNode::SaveNodeToXML(FILE* hFile)
//========================================================
//fprintf(hFile,TEXT(&&key&NodeName&/key&&));
//fprintf(hFile,TEXT(&&string&%s&/string&&),m_strNodeName.c_str());
fprintf(hFile,TEXT(&&key&%s&/key&&),m_strNodeName.c_str());
//========================================================
fprintf(hFile,TEXT(&&dict&&));
if(m_pFirstChild)
if(false == m_pFirstChild-&SaveNodeToXML(hFile))
fclose(hFile);
fprintf(hFile,TEXT(&&/dict&&));
if(m_pFirstBorther)
if(false == m_pFirstBorther-&SaveNodeToXML(hFile))
fclose(hFile);
& & & & &这样,一个最基本的结点就建立起来了,我们将可以由它来建立一棵树,比如下图这样一个程序:我们有一个TreeCtrl。初始情况下只有一个Root结点,通过在树控件上右键弹出菜单中进行选项操作来增加或删除子结点和兄弟结点。当我们创建了一个结点树后可以调用
SaveNodeToXML
函数来讲结点树保存下来。
保存的XML文件打开后:
& & & & 学到这里,您已经掌握了一个结点系统的基本设计思想,它将在日后成为一个强大的武器来帮助您在游戏开发过程中解决一些相关的设计问题。
2.1.1结点的位置:
上面的结点系统代码中,只有结点的父子关系,并不能实现父结点移动同时带动子结点移动。这又是怎么做到的呢?
这里有一个关键的核心算法:即一个结点的位置,由本结点相对于父结点位置加上父结点的世界位置来取得,而父结点又会通过父结点与其父结点(即爷爷结点)的相对位置加上其父结点(即爷爷结点)的世界位置来取得。这里有一个层层回溯的思想在里面。
我们在代码中加入一个表示空间位置的结构。
struct stVec3
float m_fX;
float m_fY;
float m_fZ;
stVec3(float x,float y,float z)
//重载赋值操作符
stVec3& stVec3::operator = (const stVec3& tVec3)
m_fX = tVec3.m_fX;
m_fY = tVec3.m_fY;
m_fZ = tVec3.m_fZ;
//重载加法操作符
stVec3 stVec3::operator + (const stVec3& tVec3)
stVec3 tResultV
tResultVec.m_fX = m_fX + tVec3.m_fX;
tResultVec.m_fY = m_fY + tVec3.m_fY;
tResultVec.m_fZ = m_fZ + tVec3.m_fZ;
return tResultV
//重载加等操作符
stVec3& stVec3::operator += (const stVec3& tVec3)
m_fX += tVec3.m_fX;
m_fY += tVec3.m_fY;
m_fZ += tVec3.m_fZ;
//重载减法操作符
stVec3 stVec3::operator - (const stVec3& tVec3)
stVec3 tResultV
tResultVec.m_fX = m_fX - tVec3.m_fX;
tResultVec.m_fY = m_fY - tVec3.m_fY;
tResultVec.m_fZ = m_fZ - tVec3.m_fZ;
return tResultV
//重载减等操作符
stVec3& stVec3::operator -= (const stVec3& tVec3)
m_fX -= tVec3.m_fX;
m_fY -= tVec3.m_fY;
m_fZ -= tVec3.m_fZ;
然后在结点中加入相应接口:
//设置当前结点相对于父结点位置
void SetPos(float x,float y,float z);
void SetPos_X(float x);
void SetPos_Y(float y);
void SetPos_Z(float z);
//取得当前结点相对于父结点位置
float GetPos_X();
float GetPos_Y();
float GetPos_Z();
//取得当前结点的世界坐标位置
stVec3 GetWorldPos();
//当前结点相对于父结点的位置
stVec3 m_sP
对应的实现:
//设置当前结点相对于父结点位置
void CNode::SetPos(float x,float y,float z)
m_sPos.m_fX =
m_sPos.m_fY =
m_sPos.m_fZ =
void CNode::SetPos_X(float x)
m_sPos.m_fX =
void CNode::SetPos_Y(float y)
m_sPos.m_fY =
void CNode::SetPos_Z(float z)
m_sPos.m_fZ =
//取得当前结点相对于父结点位置
float CNode::GetPos_X()
return m_sPos.m_fX;
float CNode::GetPos_Y()
return m_sPos.m_fY;
float CNode::GetPos_Z()
return m_sPos.m_fZ;
//取得当前结点的世界坐标位置
stVec3 CNode::GetWorldPos()
stVec3 tResultPos = m_sP
//使用回溯法取得最终的世界位置,这一步是结点系统中父结点固定子结点的关健。
if(m_pParentNode)
tResultPos += m_pParentNode-&GetWorldPos();
return tResultP
& & & & &经过这些代码的建立,我们就可以取得一个受父结点位置固定的子结点的世界位置了。同样,缩放和旋转的关系也可以由此建立,在此就不一一赘述了,有兴趣的同学可以在本节作用中完成它。
2.2 精灵,层,场景
2.2.1魂斗罗的场景:
&&&&&&&& 在Cocos2d-x中,大量的物体都是基于结点系统的,这些类均是由最基本的结点类CCNode来派生的。其中最为重要的是精灵-CCSprite,层-CCLayer,场景- CCScene。
&&&&&&&& 一个游戏的一个关卡,可以想象为一棵树,其中场景是树干,层是树枝,精灵是树叶。一棵树只有一个树干,树干上有多个树枝,树枝上又有多个树叶。从功能性上来讲,树干的作用是管理树枝,树枝的作用是固定其上长出的树叶,树叶的作用是吸收阳光…NO,不是这个意思,树叶的作用是表现力,是观赏,是用来看的。表现在Cocos2d-x的游戏中,场景用来管理所有的层,而层则是用来区分具有不同排序分类的精灵集合,并能响应触屏事件,而精灵就是显示图片和动画的。当游戏要切换场景时,就像是换一棵树。作为一个游戏设计师,要能够很好的设计游戏的这些树。当然,我们要很清楚的知道如何来种下一棵树,这很重要!
&&&&&&&& 首先,我们先要确定游戏都需要哪些场景。作为树的根结点,它构成了游戏的骨架。比如我们小时候玩的FC游戏-《魂斗罗》。
我们可以将开始界面和后面每一个关卡都当作是一个场景。那简单来说这个游戏是由两类场景构成的。第一类场景就是开始界面,如下图:
&&&&&&&& 这个开始界面做为一个场景是简单了点,但很清晰。游戏开始时首先要运行的场景就是它。我们以三级树形结点来表示这个场景。
& & & & &在这个三级树形结点图示中,“开始界面”即为场景,“界面层”即为层,再下面的四个结点可以算为界面层下的精灵,当然,菜单其实也可以分为几个精灵构成。
&&&&&&&& 第二类场景就是关卡了。如图:
& & & & &这是熟悉的第一关,我们仍以三级树形结点来表示这个场景。
& & & & &在这里,“第一关”即为场景,为了区分具有不同排序分类的精灵集合。我将游戏中的层由远及近观看,由先及后绘制,划分为“远景层”,“近景层”,“人物层”,“效果层”,“界面层”等五个层,再将各种精灵分布到这些层中。
&&&&&&&& 继续这样子分析,我们可以得出所有的关卡树:
& & & & &在这里“Root”代表了游戏程序。它共种有十棵树。分别为“开始界面”,“第一关”…“通关界面”,每完成一个关卡,就将进行场景的切换,也就是显示一棵新树。
&&&&&&&& 到这里,精灵,层与场景的结点关系原理已经讲解完成。我们现在来看一下Cocos2d-x中是如何具体实现和应用的。
&&&&&&&& 以开始界面为例,咱们接着上一节中所讲的节点类来进行扩展,为了更好的讲述理论,这部分内容完全不涉及任何渲染引擎的使用,我们只使用VS创建一个简单的WIN32窗口程序,并使用GDI来进行绘制。
&&&&&&&& 我们将创建的工程命名为ShowNodeTree,编译运行只有一个空白窗口,它工作的很好。OK,现在我们创建一个工程筛选目录NodoTree,并将之前创建的Node放入其中,并依次创建好Scene,Layer,Spriet及Director等类。
顾名思义,上面这些文件分别为:
&&&&&&&& Director.h/cpp:win32绘制管理类CDirector,绘图用。
&&&&&&&& Node.h/cpp:结点基类CNode,用于构建结点树。
& & & & &Layer.h/cpp: 层类CLayer。
&&&&&&&& Scene.h/cpp:场景类CScene。
&&&&&&&& Sprite.h/cpp:精灵类CSprite。
我们来看一下具体实现:
首先是win32绘制管理类CDirector:
Director.h:
#pragma once
#include &windows.h&
//==================================================================
//File:Director.h
//Desc:显示设备类,用于绘制
//==================================================================
class CDirector
~CDirector();
//获取单件实例指针
CDirector* GetInstance();
void Init(HWND hWnd);
//绘制矩形
void FillRect(int x,int y,int width,int height,COLORREF rgb);
//绘制图像
void DrawBitMap(int x,int y,int width,int height,HBITMAP hBitmap);
CDirector(){}
//单件实例指针
CDirector* m_pThisI
//WINDOWS 窗口句柄
//WINDOWS GDI 绘图所用的设备上下文
可以看到,CDirector类是一个单例,我们为其创建了两个函数来进行绘制指定色的矩形和绘制位图的功能。没错,足够用了。
Director.cpp:
#include &Director.h&
CDirector* CDirector::m_pThisInst = NULL;
CDirector* CDirector::GetInstance()
if(!m_pThisInst)
m_pThisInst = new CD
if(!m_pThisInst)return NULL;
m_pThisInst-&Init(NULL);
return m_pThisI
CDirector::~CDirector()
if(m_pThisInst)
delete m_pThisI
m_pThisInst = NULL;
void CDirector::Init(HWND hWnd)
m_HWnd = hW
m_HDC = ::GetDC(m_HWnd) ;
void CDirector::FillRect(int x,int y,int width,int height,COLORREF rgb)
HBRUSH hBrush = ::CreateSolidBrush(rgb);
tRect.left
tRect.right
tRect.bottom = y +
::FillRect(m_HDC,&tRect,hBrush);
::DeleteObject(hBrush);
void CDirector::DrawBitMap(int x,int y,int width,int height,HBITMAP hBitmap)
HDC hTempHDC = CreateCompatibleDC(m_HDC);
HGDIOBJ hOldObj = SelectObject(hTempHDC,hBitmap);
BitBlt(m_HDC,x,y,width, height,hTempHDC,0,0,SRCCOPY);
DeleteDC(hTempHDC);
&&&&&&&& 都是最基本的GDI绘制操作,这样我们的设备就建立好了。下面我们来创建场景。
#pragma once
#include &Node.h&
//==================================================================
//File:Scene.h
//Desc:场景类,用于管理所有的层
//==================================================================
class CScene : public CNode
CScene(const char* szName);
其对应的CPP:
#include &Scene.h&
CScene::CScene(const char* szName)
SetName(szName);
& & & & &没什么可解释的,就是一个结点类。然后是层:
#pragma once
#include &Node.h&
//==================================================================
//File:Layer.h
//Desc:层类,用于存放精灵
//==================================================================
class CLayer : public CNode
CLayer(const char* szName);
inline void Update();
//直接渲染
inline void Draw();
//设置颜色
SetColor(COLORREF color);
//取得颜色
COLORREF GetColor();
SetWidth(int vWidth);
GetWidth();
SetHeight(int vHeight);
GetHeight();
//设置颜色
COLORREF m_LayerC
可以看到,层有了宽高和颜色的设置,对应的Layer.cpp:
#include &Layer.h&
#include &Director.h&
CLayer::CLayer(const char* szName):
m_nWidth(0),
m_nHeight(0)
SetName(szName);
m_LayerColor = RGB(255,255,255);
void CLayer::Update()
CNode::Update();
//直接渲染
void CLayer::Draw()
stVec3 tPos = GetWorldPos();
CDirector::GetInstance()-&FillRect(tPos.m_fX,tPos.m_fY,m_nWidth,m_nHeight,m_LayerColor);
CNode::Draw();
//设置颜色
void CLayer::SetColor(COLORREF color)
m_LayerColor =
//取得颜色
CLayer::GetColor()
return m_LayerC
void CLayer::SetWidth(int vWidth)
m_nWidth = vW
CLayer::GetWidth()
return m_nW
void CLayer::SetHeight(int vHeight)
m_nHeight = vH
CLayer::GetHeight()
return m_nH
&&&&&&&& 层已经可以显示了,通过取得设备并调用FillRect来显示一个色块矩形。最后我们来看一下精灵:
#pragma once
#include &Node.h&
//==================================================================
//File:Sprite.h
//Desc:精灵类,用于显示图片
//==================================================================
class CSprite : public CNode
CSprite(const char* szName);
inline void Update();
//直接渲染
inline void Draw();
//设置位图句柄
void SetBitmap(HBITMAP vhBitmap);
//设置位图句柄
void SetBitmap(HBITMAP vhBitmap,int vWidth,int vHeight);
//所用位图句柄
HBITMAP m_hB
//位图宽度
m_nBitmapW
//位图高度
m_nBitmapH
& & & & &我们为精灵增加了位图句柄,以使它可以绘制相应的位图。
Sprite.cpp:
#include &Sprite.h&
#include &Director.h&
CSprite::CSprite(const char* szName):
m_hBitmap(NULL),
m_nBitmapWidth(0),
m_nBitmapHeight(0)
SetName(szName);
void CSprite::Update()
CNode::Update();
//直接渲染
void CSprite::Draw()
if(m_hBitmap)
stVec3 tPos = GetWorldPos();
CDirector::GetInstance()-&DrawBitMap(tPos.m_fX,tPos.m_fY,m_nBitmapWidth,m_nBitmapHeight,m_hBitmap);
CNode::Draw();
//设置位图句柄
void CSprite::SetBitmap(HBITMAP vhBitmap)
GetObject(vhBitmap, sizeof(BITMAP), &bmp);
//得到一个位图对象
m_hBitmap = vhB
m_nBitmapWidth = bmp.bmW
m_nBitmapHeight = bmp.bmH
//设置位图句柄
void CSprite::SetBitmap(HBITMAP vhBitmap,int vWidth,int vHeight)
m_hBitmap = vhB
m_nBitmapWidth = vW
m_nBitmapHeight = vH
&&&&&&&& OK,就这样,我们就建立了一套可以进行场景,层,精灵管理和绘制的类。现在我们来具体的实现一下开始界面。我将开始界面分为
&&&&&&&& 这里共有一个层和八个精灵。层嘛,就是一纯黑背景色块,八个精灵嘛,就如上图所示分别用来显示不同的位图:
&我们现在打开程序的主源文件ShowNodeTree.cpp,在文件顶部加入:
#include &Sprite.h&
#include &Layer.h&
#include &Scene.h&
#include &Director.h&
//唯一使用的场景
g_pMyScene = NULL;
并在InitInstance函数的尾部加入:
//初始化设备
CDirector::GetInstance()-&Init(hWnd);
CLayer* pNewLayer = new CLayer(&Layer1&);
pNewLayer-&SetPos(100,40,0);
pNewLayer-&SetColor(RGB(0,0,0));
pNewLayer-&SetWidth(497);
pNewLayer-&SetHeight(434);
//增加精灵
szCurrDir[_MAX_PATH];
::GetCurrentDirectory(_MAX_PATH,szCurrDir);
szImagePathName[_MAX_PATH];
wsprintf(szImagePathName,&%s\\knm.bmp&,szCurrDir);
hbmp = (HBITMAP)LoadImage(NULL,szImagePathName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
CSprite* pNewSprite = new CSprite(&knm&);
pNewSprite-&SetBitmap(hbmp);
pNewSprite-&SetPos(130,40,0);
//将精灵放入到层
pNewLayer-&AddChild(pNewSprite);
wsprintf(szImagePathName,&%s\\logo.bmp&,szCurrDir);
hbmp = (HBITMAP)LoadImage(NULL,szImagePathName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
CSprite* pNewSprite2 = new CSprite(&logo&);
pNewSprite2-&SetBitmap(hbmp);
pNewSprite2-&SetPos(90,100,0);
//将精灵放入到层
pNewLayer-&AddChild(pNewSprite2);
wsprintf(szImagePathName,&%s\\player.bmp&,szCurrDir);
hbmp = (HBITMAP)LoadImage(NULL,szImagePathName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
CSprite* pNewSprite3 = new CSprite(&player&);
pNewSprite3-&SetBitmap(hbmp);
pNewSprite3-&SetPos(260,230,0);
//将精灵放入到层
pNewLayer-&AddChild(pNewSprite3);
wsprintf(szImagePathName,&%s\\menu_title.bmp&,szCurrDir);
hbmp = (HBITMAP)LoadImage(NULL,szImagePathName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
CSprite* pNewSprite4 = new CSprite(&menu_title&);
pNewSprite4-&SetBitmap(hbmp);
pNewSprite4-&SetPos(40,270,0);
//将精灵放入到层
pNewLayer-&AddChild(pNewSprite4);
wsprintf(szImagePathName,&%s\\menu_1.bmp&,szCurrDir);
hbmp = (HBITMAP)LoadImage(NULL,szImagePathName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
CSprite* pNewSprite5 = new CSprite(&menu_1&);
pNewSprite5-&SetBitmap(hbmp);
pNewSprite5-&SetPos(100,310,0);
//将精灵放入到层
pNewLayer-&AddChild(pNewSprite5);
wsprintf(szImagePathName,&%s\\menu_2.bmp&,szCurrDir);
hbmp = (HBITMAP)LoadImage(NULL,szImagePathName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
CSprite* pNewSprite6 = new CSprite(&menu_2&);
pNewSprite6-&SetBitmap(hbmp);
pNewSprite6-&SetPos(100,350,0);
//将精灵放入到层
pNewLayer-&AddChild(pNewSprite6);
wsprintf(szImagePathName,&%s\\menu_cursor.bmp&,szCurrDir);
hbmp = (HBITMAP)LoadImage(NULL,szImagePathName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
CSprite* pNewSprite7 = new CSprite(&menu_cursor&);
pNewSprite7-&SetBitmap(hbmp);
pNewSprite7-&SetPos(60,310,0);
//将精灵放入到层
pNewLayer-&AddChild(pNewSprite7);
wsprintf(szImagePathName,&%s\\copyright.bmp&,szCurrDir);
hbmp = (HBITMAP)LoadImage(NULL,szImagePathName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
CSprite* pNewSprite8 = new CSprite(&copyright&);
pNewSprite8-&SetBitmap(hbmp);
pNewSprite8-&SetPos(120,390,0);
//将精灵放入到层
pNewLayer-&AddChild(pNewSprite8);
//将层放入场景
g_pMyScene = new CScene(&HDL&);
g_pMyScene-&AddChild(pNewLayer);
//设定每毫秒刷新一帧
::SetTimer(hWnd,1,20,NULL);
&&& 看,经过上面的代码之后,我们就创建了相应的层,精灵和场景。最后创建一个定时器来进行屏幕重绘,FPS嘛,就设为50好了。
&&& 我们在窗口消息处理函数中加入:
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码..
if(g_pMyScene)
//更新和绘制场景
g_pMyScene-&Update();
g_pMyScene-&Draw();
EndPaint(hWnd, &ps);
case WM_TIMER:
//让场景的Layer1层不断向右移动,到像素时重置。
if(g_pMyScene)
CNode* pLayer = g_pMyScene-&QueryChild(&Layer1&);
= pLayer-&GetWorldPos();
tPos.m_fX += 1;
if(tPos.m_fX & 400)
tPos.m_fX = 0;
pLayer-&SetPos_X(tPos.m_fX);
//响应刷新
::InvalidateRect(hWnd,NULL,TRUE);
case WM_KEYDOWN:
if(wParam == VK_UP)
{//按上时选人菜单光标置在第一项前面。
if(g_pMyScene)
CSprite* pNewSprite7 = (CSprite*)g_pMyScene-&QueryChild(&menu_cursor&);
if(pNewSprite7)
pNewSprite7-&SetPos(60,310,0);
if(wParam == VK_DOWN)
{//按下时选人菜单光标置在第二项前面。
if(g_pMyScene)
CSprite* pNewSprite7 = (CSprite*)g_pMyScene-&QueryChild(&menu_cursor&);
if(pNewSprite7)
pNewSprite7-&SetPos(60,350,0);
case WM_DESTROY:
//当窗口销毁时也一并删除定时器并释放场景。
::KillTimer(hWnd,1);
if(g_pMyScene)
//会调用CNode的虚析构函数释放所有子结点。所以不会造成内存泄漏。
delete g_pMyS
g_pMyScene = NULL;
PostQuitMessage(0);
& &&这样我们的开始界面就算完成了,编译运行一下吧:
& & & & 怎么样?不错吧。一个开始界面层展现在我们面前,所有精灵做为层的子结点而随着层保持运动。虽然这种方式还有一些闪屏,但,那并不是重点,关键是你彻彻底底的理解了结点系统对于引擎架构的作用和设计思想。好了,喝口水歇一会儿开始进入到Cocos2d-x中去看看。
2.1.2 Cocos2d-x中的精灵,层,场景与结点:
& & & & &在Cocos2d-x中,结点的基类是CCNode,它的实现远远超越了上面结点代码的复杂度,不过没关系,随着后面相关代码接触的加深,你可以很明白它的全部接口函义,但现在,你所需要的只是明白它就不过是个结点,它不过是咱们上面结点类的演变,说的通俗点:不要以为你穿个马甲哥就认不出你了!
&&&&&&&& 在CCNode中,有一个指针容器成员m_pChildren ,它存放了当前结点下的所有子结点,我们通过addChild来增加子结点到其中。我们并没有发现所谓的兄弟结点,为什么呢?那时因为兄弟结点被“扁平化”处理了。为了提升效率,减少递归调用的次数,可以将所有子结点的指针都存放在当前结点的容器中,所以子结点的兄弟结点就不必出现了。
&&&&&&&& 有了结点CCNode,我们来看一下精灵CCSprite,它在libcocos2d的sprite_nodes分类下。
打开CCSprite.h:
CCSprite :
CCTextureProtocol,
CCRGBAProtocol
&&&&&&&& 很明显,精灵是由结点CCNode派生出来的子类。它的主要功能就是显示图形。在其函数中,涉及纹理加载和OpenGL相关的顶点和颜色,纹理寻址的操作。
&&&&&&&& 层CCLayer和场景CCScene是被存放在libcocos2d的layers_scenes_transitions_nodes分类下。
&&&&&&&& 打开CCLayer.h:
CC_DLLCCLayer :
CCTouchDelegate,
CCAccelerometerDelegate,
CCKeypadDelegate
&&&&&&&& 可以看到,CCLayer除了由结点CCNode派生外,还增加了用户输入事件的响应接口。如
CCTouchDelegate
是触屏事件响应接口类,
CCAccelerometerDelegate
是加速键消息事件响应接口类,
CCKeypadDelegate
是软键盘消息事件响应接口类。
&&& 打开CCScene.h:
CC_DLL CCScene :
&&&&&&&& 好吧,真是简单明了,场景就是专门管理子结点的,或者说就是专门管理层结点的。
&&&&&&&& 现在我们来看一些它们的具体应用。
&&&&&&&& 打开HelloCpp工程。在Classes下我们看到有两个类:
1 . AppDelegate:由CCApplication派生,即Cocos2d-x的程序类。可以把它当作上面图示中的”Root”。它的作用就是启动一个程序,创建主窗口并初始化游戏引擎并进入消息循环。
2 . HelloWorld:由CCLayer派生,即Cocos2d-x的层。对应上面图示中“开始界面”场景中的“界面层”。它的作用是显示背景图和菜单及退出按钮等精灵。在这个类里有一个静态函数HelloWorld::scene()创建了所用到的场景并创建HelloWorld这个层放入到场景中。
&&&&&&&& 在程序的main函数中创建了AppDelegate类的实例对象并调用run运行。&&&&&&&&& 之后会在AppDelegate的函数applicationDidFinishLaunching(代表程序启动时的处理)中结尾处调用HelloWorld::scene()创建了场景。
&&&&&&&& 游戏运行起来是个什么样子呢?没错,我看跟魂斗罗的“开始界面”也差不到哪去嘛。当然,只是指组织关系。
& & & & &嗯,到此,本节的知识算是讲述完毕!做为一个有上进心的程序员,咱们来做些课后题吧?
2.3 课后题目
1.在2.1.1结中为结点增加缩放,旋转(当然,如果没有好的数学知识就算了,也可以用一些第三方数学库)的处理,使取得一个子结点在世界坐标系中的大小时会受到其父结点的影响。
2. &将《魂斗罗》之外你玩过的游戏选几个做一个树型分析。
已发表评论数()
&&登&&&陆&&
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见

我要回帖

更多关于 大唐豪侠 的文章

 

随机推荐