用OGRE1.74搭建游戏框架(一)

新版的OGRE出来了,不知什么原因抛弃了CEGUI。国内的教程好像也更新比较少了,在官网上还是发现不少资料的,现在参考官网上的一些资料来搭建一个游戏的框架。

参考的资料:

http://www.ogre3d.org/tikiwiki/Advanced+Ogre+Framework&structure=Tutorials

首先要先一个能启动OGRE的类(OgreFramework),把OGRE的初始化的相关工作放入其中,大体有如下几个东西:

  • Root
  • RenderWindow
  • Viewport
  • Log
  • Timer
  • InputManager / Keyboard / Mouse
  • SDKTrays Manager

OgreFramework.h

/********************************************************************

created: 2012/02/25

created: 25:2:2012 11:31

filename: E:\Ogre\Project\Ogre_Project\Game_Demo\OgreFramework.h

file path: E:\Ogre\Project\Ogre_Project\Game_Demo

file base: OgreFramework

file ext: h

author: Star purpose: ogre framework

*********************************************************************/ #ifndef _ZH_OGREFRAMEWORK_H_

#define _ZH_OGREFRAMEWORK_H_ #pragma once #include <Ogre.h>

#include <ois/OIS.h>

#include <SdkTrays.h> class OgreFramework: public Ogre::Singleton<OgreFramework>, OIS::KeyListener, OIS::MouseListener

{

public:

OgreFramework();

~OgreFramework(); bool InitOgre(Ogre::String wndTitle, OIS::KeyListener* pKeyListener = , OIS::MouseListener* pMouseListener = );

void UpdateOgre(double timeSinceLastFrame); // for key event

bool keyPressed(const OIS::KeyEvent& evt);

bool keyReleased(const OIS::KeyEvent& evt); // for mouse event

bool mouseMoved(const OIS::MouseEvent& evt);

bool mousePressed(const OIS::MouseEvent& evt, OIS::MouseButtonID id);

bool mouseReleased(const OIS::MouseEvent& evt, OIS::MouseButtonID id); public:

Ogre::Root* m_pRoot;

Ogre::RenderWindow* m_pRenderWnd;

Ogre::Viewport* m_pViewport;

Ogre::Log* m_pLog;

Ogre::Timer* m_pTimer; OIS::InputManager* m_pInputMgr;

OIS::Keyboard* m_pKeyboard;

OIS::Mouse* m_pMouse; OgreBites::SdkTrayManager* m_pTrayMgr; private:

OgreFramework(const OgreFramework&);

OgreFramework& operator= (const OgreFramework&); }; #endif //_ZH_OGREFRAMEWORK_H_

主要还是要看InitOgre的实现:

bool OgreFramework::InitOgre(Ogre::String wndTitle, OIS::KeyListener* pKeyListener /* = 0 */, OIS::MouseListener* pMouseListener /* = 0 */)

{

Ogre::LogManager* logMgr = new Ogre::LogManager(); m_pLog = Ogre::LogManager::getSingleton().createLog("OgreLogfile.log", true, true, flase);

m_pLog->setDebugOutputEnabled(true); m_pRoot = new Ogre::Root(); if (!m_pRoot->showConfigDialog())

return false; m_pRenderWnd = m_pRoot->initialise(true, wndTitle); m_pViewport = m_pRenderWnd->addViewport();

m_pViewport->setBackgroundColour(ColourValue(0.5f, 0.5f, 0.5f, 1.0f)); m_pViewport->setCamera(); size_t hWnd = ;

OIS::ParamList paramList;

m_pRenderWnd->getCustomAttribute("WINDOW", &hWnd); paramList.insert(OIS::ParamList::value_type("WINDOW", Ogre::StringConverter::toSgring(hWnd))); m_pInputMgr = OIS::InputManager::createInputSystem(paramList); m_pKeyboard = static_cast<OIS::Keyboard*>(m_pInputMgr->createInputObject(OIS::OISKeyboard, true));

m_pMouse = static_cast<OIS::Mouse*>(m_pInputMgr->createInputObject(OIS::OISMouse, true)); m_pMouse->getMouseState().height = m_pRenderWnd->getHeight();

m_pMouse->getMouseState().width = m_pRenderWnd->getWidth(); if (pKeyListener == NULL)

m_pKeyboard->setEventCallback(this);

else

m_pKeyboard->setEventCallback(pKeyListener); if (pMouseListener == NULL)

m_pMouse->setEventCallback(this);

else

m_pMouse->setEventCallback(pMouseListener); // load resources

Ogre::String secName, typeName, archName;

Ogre::ConfigFile cf;

cf.load("resources.cfg"); Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();

while (seci.hasMoreElements)

{

secName = seci.peekNextKey();

Ogre::ConfigFile::SettingsMultiMap* settings = seci.getNext();

Ogre::ConfigFile::SettingsMultiMap::iterator i;

for (i = settings->begin(); i != settings->end(); ++i)

{

typeName = i->first;

archName = i->second;

Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);

}

}

Ogre::TextureManager::getSingleton().setDefaultNumMipmaps();

Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); m_pTrayMgr = new OgreBites::SdkTrayManager("OFTrayMgr", m_pRenderWnd, m_pMouse, ); m_pTimer = new Ogre::Timer();

m_pTimer->reset(); m_pRenderWnd->setActive(true); return true;

}

里边主要做了以下几个工作:

1.创建日志管理

2.创建OGRE的Root

3.创建渲染窗口(RenderWindow)和视口(Viewport)

4.启动OIS

5.设置鼠标和键盘的监听

6.载入资源

7.设置Timer

8.初始化SDKTrayManager

9.创建并显示debug overlay

注意,这里边没有像机和场景管理器,这个要到后面的状态类中才用到。

void OgreFramework::UpdateOgre(double timeSinceLastFrame)

{ }

这个函数用于在每一帧中更新和OGRE相关的一些东西,自己写的东西是要在每个状态中自己更新。

其实游戏的框架,普遍还是用的State这个设计模式。这样就可以在开始菜单,游戏画面,结束画面中自由的切换。看Android的libgdx引擎也是这样做的,分成不同的Screen来相互切换。

用OGRE1.74搭建游戏框架(二)--添加菜单

在上一节中,已经把OGRE的一个框架搭出来了,而且用的是一个单例模式,这样就意味着我们在后面的状态模式中可以很容易的就使用OGRE来帮我们进行图形绘制。

首先,写一个所有游戏状态的基类,因为我们大体可以抽象出所有游戏状态都应该有:

1.进入这个状态时应该做一些准备工作

2.退出这个状态时应该删除某些东西

3.暂停和继续时的一些动作。

4.更新

而一个游戏里有很多状态的切换,而我们又不想让一个状态知道另一个状态的存在,于是我们就要有一个统一管理这些状态的一个类,这样就能让这些状态之间解耦。(如果不这样做,比如说我想从菜单状态切换到游戏开始状态,那么我得在开始菜单中保存一个指向游戏开始状态的指针,而游戏开始状态想切到其它的状态也得这么做。)

因此我们写一个状态管理类,它实现一个状态监听接口。

状态管理用一个栈来存储所有的状态,当从当前状态切换到另一个状态时,就把栈顶的状态取出,并调用它的Exit()函数,并Pop出去,然后再初始化新的状态,并调用新状态的Enter()函数。

void CGameStateManager::ChangeGameState(CGameState* state)
{
if (!m_ActiveStateStack.empty())
{
m_ActiveStateStack.back()->Exit();
m_ActiveStateStack.pop_back();
} m_ActiveStateStack.push_back(state);
Init(state);
m_ActiveStateStack.back()->Enter();
}

GameState.h文件如下:

/********************************************************************
created: 2012/02/25
created: 25:2:2012 15:05
filename: E:\Ogre\Project\Ogre_Project\Game_Demo\GameState.h
file path: E:\Ogre\Project\Ogre_Project\Game_Demo
file base: GameState
file ext: h
author: Star purpose: the parent of all the game state
*********************************************************************/ #ifndef _ZH_GAMESTATE_H_
#define _ZH_GAMESTATE_H_ #pragma once #include "OgreFramework.h" class CGameState; class CGameStateListener
{
public:
CGameStateListener(){};
virtual ~CGameStateListener(){}; virtual void ManageGameState(Ogre::String stateName, CGameState* state) = ; virtual CGameState* FindByName(Ogre::String stateName) = ;
virtual void ChangeGameState(CGameState* state) = ;
virtual bool PushGameState(CGameState* state) = ;
virtual void PopGameState() = ;
virtual void PauseCurGameState() = ;
virtual void Shutdown() = ;
virtual void PopAllAndPushGameState(CGameState* state) = ;
}; class CGameState : public OIS::KeyListener,public OIS::MouseListener, public OgreBites::SdkTrayListener
{
public:
static void Create(CGameStateListener* parent, const Ogre::String name) {}; void destroy() { delete this; } virtual void Enter() = ;
virtual void Exit() = ;
virtual bool Pause() { return true;}
virtual void Resume() {};
virtual void Update(double timeSinceLastFrame) = ; protected:
CGameState(){}; CGameState* FindByName(Ogre::String stateName) {return m_pListener->FindByName(stateName); }
void ChangeGameState(CGameState* state) { m_pListener->ChangeGameState(state); }
bool PushGameState(CGameState* state) { return m_pListener->PushGameState(state);}
void PopGameState() {m_pListener->PopGameState(); }
void Shutdown() { m_pListener->Shutdown(); }
void PopAllAndPushGameState(CGameState* state) { m_pListener->PopAllAndPushGameState(state); } CGameStateListener* m_pListener; Ogre::Camera* m_pCamera;
Ogre::SceneManager* m_pSceneMgr;
Ogre::FrameEvent m_FrameEvent;
}; // macro define
#define DECLARE_GAMESTATE_CLASS(T) \
static void Create(CGameStateListener* pListener, const Ogre::String name) \
{ \
T* newState = new T(); \
newState->m_pListener = pListener; \
pListener->ManageGameState(name, newState); \
} \ #endif //_ZH_GAMESTATE_H_

上面代码中最后有一个宏定义,它的做用就是定义每个状态,并把它自己注册进状态管理类里。这是为了让你少写一些代码,不然你每定义一个状态类就得写一遍这个函数,有这个宏就方便多了。

可以看一下类图:

GameStateManager.h

/********************************************************************
created: 2012/02/25
created: 25:2:2012 16:05
filename: E:\Ogre\Project\Ogre_Project\Game_Demo\GameStateManager.h
file path: E:\Ogre\Project\Ogre_Project\Game_Demo
file base: GameStateManager
file ext: h
author: Star purpose: Manage all the game states
*********************************************************************/ #ifndef _ZH_GAMESTATEMANAGER_H_
#define _ZH_GAMESTATEMANAGER_H_ #pragma once
#include "GameState.h" class CGameStateManager : public CGameStateListener
{
public:
typedef struct
{
Ogre::String name;
CGameState* state;
} SState_info; CGameStateManager();
~CGameStateManager(); void ManageGameState(Ogre::String stateName, CGameState* state); CGameState* FindByName(Ogre::String stateName); void Start(CGameState* state);
void ChangeGameState(CGameState* state);
bool PushGameState(CGameState* state);
void PopGameState();
void PauseCurGameState();
void Shutdown();
void PopAllAndPushGameState(CGameState* state); protected:
void Init(CGameState* state); std::vector<CGameState*> m_ActiveStateStack;
std::vector<SState_info> m_States;
bool m_bShutdown;
}; #endif //_ZH_GAMESTATEMANAGER_H_

这个就是状态管理类,这里边的Start函数,就是程序消息循环的位置了。状态的切换也都在这里边发生。

这些函数的实现我就不复制,粘贴了,到时最后会发一个代码链接。

有了这些状态定义,我们现在就来试一下,先做一个MenuState。

MenuState.h

/********************************************************************
created: 2012/02/27
created: 27:2:2012 11:40
filename: E:\Ogre\Project\Ogre_Project\Game_Demo\MenuState.h
file path: E:\Ogre\Project\Ogre_Project\Game_Demo
file base: MenuState
file ext: h
author: Star purpose: the menu of the game
*********************************************************************/ #ifndef _ZH_MENUSTATE_H_
#define _ZH_MENUSTATE_H_ #pragma once #include "GameState.h" class CMenuState : public CGameState
{
public:
CMenuState(); DECLARE_GAMESTATE_CLASS(CMenuState) void Enter();
void CreateScene();
void Exit(); bool keyPressed(const OIS::KeyEvent &evt);
bool keyReleased(const OIS::KeyEvent &evt); bool mouseMoved( const OIS::MouseEvent &evt);
bool mousePressed( const OIS::MouseEvent &evt, OIS::MouseButtonID id );
bool mouseReleased( const OIS::MouseEvent &evt, OIS::MouseButtonID id ); void buttonHit(OgreBites::Button* button); void Update(double timeSinceLastFrame); private:
bool m_bQuit; }; #endif //_ZH_MENUSTATE_H_

主要讲一下Enter函数,这里边就要创建一下菜单界面了,还有Camera和SceneManager的创建,用的是OGRE现在带的SDKTray。然后也可以创建场景,这样就会有比较动感的开始菜单界面了等。

void CMenuState::Enter()
{
Ogre::FontManager::getSingleton().getByName("SdkTrays/Caption")->load();
COgreFramework::getSingletonPtr()->m_pLog->logMessage("Entering MenuState.h."); m_pSceneMgr = COgreFramework::getSingletonPtr()->m_pRoot->createSceneManager(ST_GENERIC, "MenuSceneMgr");
m_pSceneMgr->setAmbientLight(Ogre::ColourValue(0.7f, 0.7f, 0.7f)); m_pCamera = m_pSceneMgr->createCamera("MenuCam");
m_pCamera->setPosition(Vector3(, , -));
m_pCamera->lookAt(Vector3(, , ));
m_pCamera->setNearClipDistance(); m_pCamera->setAspectRatio(Real(COgreFramework::getSingletonPtr()->m_pViewport->getActualWidth())/
Real(COgreFramework::getSingletonPtr()->m_pViewport->getActualHeight())); COgreFramework::getSingletonPtr()->m_pViewport->setCamera(m_pCamera); COgreFramework::getSingletonPtr()->m_pTrayMgr->destroyAllWidgets();
COgreFramework::getSingletonPtr()->m_pTrayMgr->showFrameStats(OgreBites::TL_BOTTOMLEFT);
COgreFramework::getSingletonPtr()->m_pTrayMgr->showLogo(OgreBites::TL_BOTTOMRIGHT);
COgreFramework::getSingletonPtr()->m_pTrayMgr->showCursor();
COgreFramework::getSingletonPtr()->m_pTrayMgr->createButton(OgreBites::TL_CENTER, "EnterBtn", "Enter GameState", );
COgreFramework::getSingletonPtr()->m_pTrayMgr->createButton(OgreBites::TL_CENTER, "ExitBtn", "Exit OgreFramework", );
COgreFramework::getSingletonPtr()->m_pTrayMgr->createLabel(OgreBites::TL_TOP, "MenuLbl","Menu mode", ); CreateScene();
}

这边有一个注意项:

如果没有这句的话

 Ogre::FontManager::getSingleton().getByName("SdkTrays/Caption")->load();

我这边顶上的那个Label里是不显示文字的,在他的论坛里找到这么一个解决方案。

最后的效果截图:

通过这样的框架就可以搭建自己的游戏了,只要继承GameState,实现自己的场景绘制和UI,就好了。期待你的游戏的产生。

资源下载:

http://download.csdn.net/detail/sunstar1989/4094433

用OGRE1.74搭建游戏框架(三)--加入人物控制和场景

有了前面的状态机,我们就可以很方便的扩展出自己的游戏场景状态的类。

现在我们要写一个RunState的类,这个就是游戏的主场景所在的地方,从MenuState可以跳转过来。

一、加入第三人称控制器

对于人物的控制,新版的OGRE已经给出了一个示例,就是那个Sample_Charater。

里边是对一个OGRE新模型的控制,操作起来感觉不错,就是向前跑动的时候没法看身后的东西,得停下来,Camera才会回到自由模式。

这个地方主要用到两个类:

SdkCameraMan:封装了OGRE的像机,可以比较自由的控制像机。

SinbadCharacterController:对于Sinbad的角色的控制以及动画的播放。

只要声明并定义好这两个类就能快速的实现第三人称的控制。

CRunState.h

class CRunState : public CGameState
{
public:
CRunState(); DECLARE_GAMESTATE_CLASS(CRunState) void Enter();
void CreateScene();
void Exit();
bool Pause();
void Resume(); bool keyPressed(const OIS::KeyEvent &evt);
bool keyReleased(const OIS::KeyEvent &evt); bool mouseMoved( const OIS::MouseEvent &evt);
bool mousePressed( const OIS::MouseEvent &evt, OIS::MouseButtonID id );
bool mouseReleased( const OIS::MouseEvent &evt, OIS::MouseButtonID id ); void Update(double timeSinceLastFrame); protected:
OgreBites::SdkCameraMan* m_pCameraMan; bool m_bIsQuit; SinbadCharacterController* m_pChara;
};

在Enter函数中初始化:

void CRunState::Enter()
{
COgreFramework::getSingletonPtr()->m_pLog->logMessage("Entering RunState.h."); m_pSceneMgr = COgreFramework::getSingletonPtr()->m_pRoot->createSceneManager(ST_GENERIC, "RunSceneMgr");
m_pSceneMgr->setAmbientLight(Ogre::ColourValue(0.3f, 0.3f, 0.3f)); m_pCamera = m_pSceneMgr->createCamera("MainCam");
m_pCamera->setNearClipDistance(5); m_pCamera->setAspectRatio(Real(COgreFramework::getSingletonPtr()->m_pViewport->getActualWidth())/
Real(COgreFramework::getSingletonPtr()->m_pViewport->getActualHeight())); COgreFramework::getSingletonPtr()->m_pViewport->setCamera(m_pCamera); m_pCameraMan = new OgreBites::SdkCameraMan(m_pCamera);
m_pCameraMan->setStyle(OgreBites::CS_MANUAL); m_pChara = new SinbadCharacterController(m_pCamera); COgreFramework::getSingletonPtr()->m_pTrayMgr->destroyAllWidgets();
COgreFramework::getSingletonPtr()->m_pTrayMgr->hideCursor(); CreateScene(); }

在那些键盘和鼠标消息中响应人物和摄像机的事件。最后要在Update中更新动画。

void CRunState::Update(double timeSinceLastFrame)
{
if (m_bIsQuit)
{
Shutdown();
return;
} if (m_pChara)
m_pChara->addTime(timeSinceLastFrame/1000); // from miliseconds to seconds }

这边注意,因为我们前面用的是毫秒,这边动画更新需要的是秒为单位,所以要除,否则画面不会动。

二、载入.Scene场景文件

如果要用代码加入物体,不仅麻烦(得算坐标),而且不易修改(修改后得重新编译)。于是就有了场景文件的出现,而且也有了开源的场景编辑器(Ogitor)。

Ogitor是一个基于QT的OGRE场景的编辑器,可以到官网上下载:

http://www.ogitor.org/HomePage

在我们的工程中要用到的就是三个文件(在Ogitor的安装目录的/SampleApp_Source/下):

DotSceneLoader.h

DotSceneLoader.cpp

rapidxml.h

把他们拷进我们的工程里,我们将要使用他们来载入场景。

这时,会发现程序有错,DotSceneLoader.cpp里要引用到PagedGeometry的一些东西,这是一个用来植树造林的工具,我们也可以去下载。

http://www.ogre3d.org/tikiwiki/PagedGeometry+Engine

官方没有提供已经编译好的,所以需要自己编译,要配置OGRE的头文件和库的路径。

新的OGRE中的material的一个方法改了,所以编译会有错误:

需要将:

bestTechnique = material->getBestTechnique(material->getLodIndexSquaredDepth(parent->minDistanceSquared));

转换为:

bestTechnique = getLodIndex(parent->minDistanceSquared)

这样就可以编译出LIB库了。

回到我们的工程:

在CreateScene函数中载入场景:

void CRunState::CreateScene()
{
DotSceneLoader* pDotSceneLoader = new DotSceneLoader();
pDotSceneLoader->parseDotScene("CubeScene.xml", "General", m_pSceneMgr, m_pSceneMgr->getRootSceneNode());
delete pDotSceneLoader; // add a bright light above the scene
Light* light = m_pSceneMgr->createLight();
light->setType(Light::LT_POINT);
light->setPosition(-10, 40, 20);
light->setSpecularColour(ColourValue::White); // create a floor mesh resource
MeshManager::getSingleton().createPlane("floor", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Plane(Vector3::UNIT_Y, 0), 100, 100, 10, 10, true, 1, 10, 10, Vector3::UNIT_Z); // create a floor entity, give it a material, and place it at the origin
Entity* floor = m_pSceneMgr->createEntity("Floor", "floor");
floor->setMaterialName("Examples/Rockwall");
floor->setCastShadows(false);
m_pSceneMgr->getRootSceneNode()->attachObject(floor);
}

这边要注意在资源文件(resource.cfg)中加入CubeScene.xml和Cube模型的资源路径,否则OGRE不会载入他们,就找不到这些资源。

最后就可以看到结果了:

尝试着载入了Ogitor自带的Sample文件,SampleScene3.scene。注意要把资源路径配好。

人缩小一倍还比房子大。。。有点像绿巨人,人物的位置要根据地形高低来设置好。

 
 
 
 

用用OGRE1.74搭建游戏框架(转载)的更多相关文章

  1. 使用Html5+C#+微信 开发移动端游戏详细教程 :(三)使用html5引擎搭建游戏框架

    教程里的案例我们是通过H5游戏引擎开发,目前H5的游戏引擎比较好用的是白鹭,不过对于新手来说白鹭的开发环境和工具使用过于复杂,这里推荐一个国内大神编写的游戏引擎:lufylegend. 直接在页面引入 ...

  2. Unity 游戏框架搭建 (六) 关于框架的一些好文和一些思考

      在进行项目架构阶段,游戏框架可以解决一部分问题.剩下的架构问题还需要根据不同的项目解决.总之游戏框架是游戏架构的一部分. 关于锤子和钉子:   最近又拿起了<代码大全>和<暗时间 ...

  3. Unity 游戏框架搭建 2018 (一) 架构、框架与 QFramework 简介

    约定 还记得上版本的第二十四篇的约定嘛?现在出来履行啦~ 为什么要重制? 之前写的专栏都是按照心情写的,在最初的时候笔者什么都不懂,而且文章的发布是按照很随性的一个顺序.结果就是说,大家都看完了,都还 ...

  4. Unity 游戏框架搭建 (十七) 静态扩展GameObject实现链式编程

    本篇本来是作为原来 优雅的QChain的第一篇的内容,但是QChain流产了,所以收录到了游戏框架搭建系列.本篇介绍如何实现GameObject的链式编程. 链式编程的实现技术之一是C#的静态扩展.静 ...

  5. Unity 游戏框架搭建 (十六) v0.0.1 架构调整

    背景: 前段时间用Xamarin.OSX开发一些工具,遇到了两个问题. QFramework的大部分的类耦合了Unity的API,这样导致不能在其他CLR平台使用QFramework. QFramew ...

  6. Unity 游戏框架搭建 (十三) 无需继承的单例的模板

    之前的文章中介绍的Unity 游戏框架搭建 (二) 单例的模板和Unity 游戏框架搭建 (三) MonoBehaviour单例的模板有一些问题. 存在的问题: 只要继承了单例的模板就无法再继承其他的 ...

  7. Unity 游戏框架搭建 (十) QFramework v0.0.2小结

    从框架搭建系列的第一篇文章开始到现在有四个多月时间了,这段时间对自己来说有很多的收获,好多小伙伴和前辈不管是在评论区还是私下里给出的建议非常有参考性,在此先谢过各位. 说到是一篇小节,先列出框架的概要 ...

  8. 凉鞋:我所理解的框架 【Unity 游戏框架搭建】

    前言 架构和框架这些概念听起来很遥远,让很多初学者不明觉厉.会产生"等自己技术牛逼了再去做架构或者搭建框架"这样的想法.在这里笔者可以很肯定地告诉大家,初学者是完全可以去做这些事情 ...

  9. [Android游戏开发]游戏框架的搭建

    通常情况下,游戏开发的基本框架中,一般包括以下模块: 窗口管理(Window management):该模块负责在Android平台上创建.运行.暂停.恢复游戏界面等功能. 输入模块(Input):该 ...

随机推荐

  1. 非常easy学习的JQuery库 : (二) 选择器

    作用 选择器同意您对元素组或单个元素进行操作. 在前面的章节中,我们介绍了一些有关怎样选取 HTML 元素的实例. 关键点是学习 jQuery 选择器是怎样准确地选取您希望应用效果的元素. jQuer ...

  2. atititi.soa  微服务 区别 联系 优缺点.doc

    atititi.soa  微服务 区别 联系 优缺点.doc 1. 应用微服务的动机,跟传统巨石应用的比较1 2. 面向服务架构(SOA)  esb2 3. 微服务架构(Microservices)2 ...

  3. Sqlserver建立Oracle的鏈接服務器

    --建立数据库链接服务器 EXEC sp_addlinkedserver @server =N'TestOracle', --要创建的链接服务器别名 @srvproduct=N'Oracle', -- ...

  4. 尽管是一个CS专业的学生,小B的数学基础很好并对数值计算有着特别的兴趣,喜欢用计算机程序来解决数学问题。现在,她正在玩一个数值变换的游戏。她发现计算机中经常用不同的进制表示同一个数,如十进制数123表达为16进制时只包含两位数7、11(B),用八进制表示时为三位数1、7、3。按不同进制表达时,各个位数的和也不同,如上述例子中十六进制和八进制中各位数的和分别是18和11。

    include "stdafx.h" #include<iostream> #include<vector> #include <algorithm& ...

  5. 【Mac系统】之Mysql数据库遇到修改数字密码的问题(SQL语法错误:ERROR 1064 (42000),密码策略等问题:ERROR 1819 (HY000))

    安装完Mysql也进行了第一次初始化密码以及修改密码规则(请参考文章),但是我想后续再改密码,出现了下面几个问题: #SQL语句错误问题 ERROR 1064 (42000): You have an ...

  6. 11 Memcached 缓存雪崩现象

    一:Memcached 缓存雪崩现象(1)造成原因:一般是由某个节点失效,导致其他的节点的缓存命中率下降,缓存中缺失的数据查询,短时间内造成的数据库服务器奔溃.重启DB,短期内又被压垮,但缓存的数据增 ...

  7. 写shader注意的一些报错

    1.Shader warning in 'Custom/1': Both vertex and fragment programs must be present in a CGPROGRAM. Ex ...

  8. redis-windows和linux下安装

    Window 下安装 下载地址:https://github.com/dmajkic/redis/downloads. 下载到的Redis支持32bit和64bit.根据自己实际情况选择,将64bit ...

  9. [Sdoi2013]直径(树的直径)

    //36分 #include<cstdio> #include<cstdlib> #include<cstring> #include<ctime> # ...

  10. 第二课 创建http server

    nodejs 不需要单独安装服务器软件 tomcat .apache. iis 看下面的代码创建了http服务器,并输出一些简单的响应内容 //引入http 模块 var http = require ...