Witam. Staram się zaprogramować kamerę dla mojej gry. Kamera ma być w stylu RTS, czyli widok z lotu ptaka.
Napisałem już prototyp ale nie wiadomo w którym miejscu obraca mi kamerę o 90 stopni. Próbowałem to naprawić funkcjami cam->setRotation();, ale rotacja nie zadziałała.
#include <irrlicht.h>
using namespace irr; // I don't want to use it irr::
using namespace core; // also ( irr::core:: )
using namespace scene; // also ( irr::scene::)
using namespace video; // also ...
using namespace io; // ...
using namespace gui; // ...
#include<iostream>
#include<set>
// device
int screenWidth = 1080;
int screenHeight = 720;
int bitsPerPixel = 32;
bool fullscreen = false;
bool stencilbuffer = false; // Specifies if we want to use the stencil buffer (for drawing shadows)
bool vsync = false; // Specifies if we want to have vsync enabled, this is only useful in fullscreen mode.
int eventReceiver = 0; // An object to receive events.We do not want to use this parameter here, and set it to 0.
int cam_x, cam_z;
// clearing screen colors
int clear_r = 48; int clear_g = 48; int clear_b = 48; int clear_a = 256;
// Basic things
IrrlichtDevice* device;
IVideoDriver* driver;
ISceneManager* sceneManager;
IGUIEnvironment* GUI;
// Fonts
IGUIFont* basicFont;
IGUIFont* boldFont;
// Textures
ITexture* TWTexture;
// Model pathfiles
std::string modelPathfile = "Media/TT_RTS_Demo_Character.obj";
std::string modelTexturePathfile = "Media/TT_RTS_Units_blue.png";
// Meshes
IAnimatedMesh* modelMesh; // mesh
// Animators
IAnimatedMeshSceneNode* animModel1; // model1
IAnimatedMeshSceneNode* animModel2; // model2
IAnimatedMeshSceneNode* animModel3; // model3
// Textures
ITexture* modelTexture;
// Buttons ID's
enum
{
// World
GUI_ID_CREATEWORLD, GUI_ID_LOADWORLD, GUI_ID_SAVEWORLD, GUI_ID_GENERATEWORLD,
// Help
GUI_ID_TUTORIAL, GUI_ID_INFO
};
float outerRadius = 10.0f;
float innerRadius = outerRadius * 0.866025404f;
class HexTile : public scene::ISceneNode
{
core::aabbox3d<f32> Box;
video::S3DVertex Vertices[8];
video::SMaterial Material;
public:
HexTile(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id)
: scene::ISceneNode(parent, mgr, id)
{
Material.Wireframe = false;
Material.Lighting = false;
//Material.setTexture(0,driver->getTexture("Media/grass.png"));
// verticves of hexagons
Vertices[0] = video::S3DVertex(0, 0, 0, 0, 0, 0, video::SColor(255, 48, 48, 48), 0, 0); // CENTER OF HEXTILE
Vertices[1] = video::S3DVertex(0.0f, 0, outerRadius, 0, 0, 0, video::SColor(255, 128, 48, 48), 0, 0);
Vertices[2] = video::S3DVertex(innerRadius, 0, outerRadius * 0.5f, 0, 0, 0, video::SColor(255, 128, 48, 48), 0, 0);
Vertices[3] = video::S3DVertex(innerRadius, 0, -outerRadius * 0.5f, 0, 0, 0, video::SColor(255, 128, 48, 48), 0, 0);
Vertices[4] = video::S3DVertex(0.0f, 0, -outerRadius, 0, 0, 0, video::SColor(255, 128, 48, 48), 0, 0);
Vertices[5] = video::S3DVertex(-innerRadius, 0, -outerRadius * 0.5f, 0, 0, 0, video::SColor(255, 128, 48, 48), 0, 0);
Vertices[6] = video::S3DVertex(-innerRadius, 0, outerRadius * 0.5f, 0, 0, 0, video::SColor(255, 128, 48, 48), 0, 0);
Vertices[7] = video::S3DVertex(0.0f, 0, outerRadius, 0, 0, 0, video::SColor(255, 128, 48, 48), 0, 0);
Box.reset(Vertices[0].Pos);
for (s32 i = 1; i < 7; ++i)
Box.addInternalPoint(Vertices[i].Pos);
}
virtual void OnRegisterSceneNode()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}
virtual void render()
{
u16 indices[] = { 0, 1, 2, /**/ 0, 2, 3, /**/ 0, 3, 4, /**/ 0, 4, 5, /**/ 0, 5, 6, /**/ 0, 6, 7 };
IVideoDriver* driver = SceneManager->getVideoDriver();
driver->setMaterial(Material);
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
driver->drawVertexPrimitiveList(&Vertices[0], 3, &indices[0], 6, video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
}
virtual const core::aabbox3d<f32>& getBoundingBox() const
{
return Box;
}
virtual u32 getMaterialCount() const
{
return 1;
}
virtual video::SMaterial& getMaterial(u32 i)
{
return Material;
}
};
class HexMap
{
public:
std::set < HexTile* > tiles;
HexMap();
~HexMap();
void addTile(HexTile*);
};
HexMap::HexMap()
{
tiles.clear();
}
HexMap::~HexMap()
{
}
void HexMap::addTile(HexTile* tile)
{
tiles.insert(tile);
}
void thisIsNotBuildYet()
{
int rectWidth = 300;
int rectHeight = 300;
int x1 = (screenWidth - rectWidth) / 2;
int x2 = (screenWidth + rectWidth) / 2;
int y1 = (screenHeight - rectHeight) / 2;
int y2 = (screenHeight + rectHeight) / 2;
rect<s32> rectangle = rect<s32>(x1, y1, x2, y2);
IGUIWindow* window = GUI->addWindow(rectangle);
const wchar_t* t = L"This section is not build yed";
IGUIStaticText* text = GUI->addStaticText(t, rect<s32>(0, 20, rectWidth, rectHeight), true, true, window, -1, true);
text->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);
}
void createWorld()
{
std::cout << "created new world" << std::endl;
thisIsNotBuildYet();
}
void loadWorld()
{
std::cout << "load world" << std::endl;
thisIsNotBuildYet();
}
void saveWorld()
{
std::cout << "save world" << std::endl;
thisIsNotBuildYet();
}
void generateWorld()
{
std::cout << "generate world" << std::endl;
thisIsNotBuildYet();
}
void tutorial()
{
std::cout << "tutorial" << std::endl;
thisIsNotBuildYet();
}
void info()
{
std::cout << "info" << std::endl;
int rectWidth = 300;
int rectHeight = 300;
int x1 = (screenWidth - rectWidth) / 2;
int x2 = (screenWidth + rectWidth) / 2;
int y1 = (screenHeight - rectHeight) / 2;
int y2 = (screenHeight + rectHeight) / 2;
rect<s32> rectangle = rect<s32>(x1, y1, x2, y2);
IGUIWindow* window = GUI->addWindow(rectangle);
const wchar_t* t = L"Program created by tBane";
IGUIStaticText* text = GUI->addStaticText(t, rect<s32>(0, 20, rectWidth, rectHeight), true, true, window, -1, true);
text->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);
}
class MyEventReceiver : public IEventReceiver
{
public:
bool KeyIsDown[KEY_KEY_CODES_COUNT];
MyEventReceiver();
virtual bool OnEvent(const SEvent&);
virtual bool IsKeyDown(EKEY_CODE);
bool OnMenuItemSelected(IGUIContextMenu* menu);
};
MyEventReceiver::MyEventReceiver()
{
for (u32 i = 0; i < KEY_KEY_CODES_COUNT; ++i)
KeyIsDown[i] = false;
}
bool MyEventReceiver::OnEvent(const SEvent& event)
{
// Remember whether each key is down or up
if (event.EventType == irr::EET_KEY_INPUT_EVENT)
{
KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
return true;
}
if (event.EventType == EET_GUI_EVENT)
{
switch (event.GUIEvent.EventType)
{
case EGET_MENU_ITEM_SELECTED: // main menu events
{
IGUIContextMenu* menu = (IGUIContextMenu*)event.GUIEvent.Caller;
s32 id = menu->getItemCommandId(menu->getSelectedItem());
if (id == GUI_ID_CREATEWORLD)
createWorld();
if (id == GUI_ID_LOADWORLD)
loadWorld();
if (id == GUI_ID_SAVEWORLD)
saveWorld();
if (id == GUI_ID_GENERATEWORLD)
generateWorld();
if (id == GUI_ID_TUTORIAL)
tutorial();
if (id == GUI_ID_INFO)
info();
}
break;
default:
break;
}
}
return false;
}
bool MyEventReceiver::IsKeyDown(EKEY_CODE keyCode)
{
return KeyIsDown[keyCode];
}//#include "HexTile.hpp"
int main()
{
MyEventReceiver receiver;
// CREATE DEVICE ( OpenGL )
device = createDevice(EDT_SOFTWARE, dimension2d<u32>(screenWidth, screenHeight), bitsPerPixel, fullscreen, stencilbuffer, vsync, &receiver);
if (!device) // if no Device then error
return 1;
// GET THE BASIC THINGS
driver = device->getVideoDriver(); // get the Video Driver
sceneManager = device->getSceneManager(); // get the Scene
GUI = device->getGUIEnvironment(); // get the GUI Manager
// LOAD THE FONTS
basicFont = device->getGUIEnvironment()->getBuiltInFont(); // get the Default Font
boldFont = device->getGUIEnvironment()->getFont("media/fonthaettenschweiler.bmp"); // get the Bold Font
// STYLES FOR GUI
IGUISkin* GUIskin = GUI->getSkin();
GUIskin->setFont(boldFont);
for (s32 i = 0; i < gui::EGDC_COUNT; ++i)
{
GUIskin->setColor((EGUI_DEFAULT_COLOR)i, SColor(255, 96, 96, 96)); // coloring the Background
GUIskin->setColor(EGDC_BUTTON_TEXT, SColor(255, 224, 224, 224)); // coloring the Text
GUIskin->setColor(EGDC_HIGH_LIGHT_TEXT, SColor(255, 128, 48, 48)); // coloring the Highlighed Text
}
// CREATE MAIN MENU
IGUIContextMenu* menu = GUI->addMenu();
menu->addItem(L"World", -1, true, true);
menu->addItem(L"Help", -1, true, true);
// Create World Menu
IGUIContextMenu* worldMenu = menu->getSubMenu(0);
worldMenu->addItem(L"Create World", GUI_ID_CREATEWORLD);
worldMenu->addItem(L"Load World", GUI_ID_LOADWORLD);
worldMenu->addItem(L"Save world", GUI_ID_SAVEWORLD);
worldMenu->addItem(L"Generate World", GUI_ID_GENERATEWORLD);
// Create Help Menu
IGUIContextMenu* helpMenu = menu->getSubMenu(1);
helpMenu->addItem(L"Tutorial", GUI_ID_TUTORIAL);
helpMenu->addItem(L"Info", GUI_ID_INFO);
// LOAD THE "TW Editor Logo"
TWTexture = driver->getTexture("Media/TW.png");
// ADD CAMERA
cam_x = 0;
cam_z = -40;
ICameraSceneNode* cam = sceneManager->addCameraSceneNode(0, vector3df(cam_x, 30, cam_z), vector3df(0, 5, 0));
cam->setFOV(1);
cam->setTarget(vector3df(cam_x, 30, cam_z));
// CURSOR IS HIDDEN
device->getCursorControl()->setVisible(true);
// LOAD THE MODEL
modelMesh = sceneManager->getMesh(modelPathfile.c_str());
if (!modelMesh)
device->drop();
animModel1 = sceneManager->addAnimatedMeshSceneNode(modelMesh); // Add Model1
animModel1->setScale(vector3df(10, 10, 10));
animModel1->setPosition(vector3df(0, 0, 0));
animModel1->setRotation(vector3df(0, 180, 0));
animModel1->setMaterialFlag(EMF_LIGHTING, false);
animModel1->setMD2Animation(scene::EMAT_STAND);
animModel1->setMaterialTexture(0, driver->getTexture(modelTexturePathfile.c_str()));
animModel2 = sceneManager->addAnimatedMeshSceneNode(modelMesh); // Add Model2
animModel2->setScale(vector3df(10, 10, 10));
animModel2->setPosition(vector3df(20, 0, 0));
animModel2->setRotation(vector3df(0, 180, 0));
animModel2->setMaterialFlag(EMF_LIGHTING, false);
animModel2->setMD2Animation(scene::EMAT_STAND);
animModel2->setMaterialTexture(0, driver->getTexture(modelTexturePathfile.c_str()));
animModel3 = sceneManager->addAnimatedMeshSceneNode(modelMesh); // Add Model3
animModel3->setScale(vector3df(10, 10, 10));
animModel3->setPosition(vector3df(40, 0, 0));
animModel3->setRotation(vector3df(0, 180, 0));
animModel3->setMaterialFlag(EMF_LIGHTING, false);
animModel3->setMD2Animation(scene::EMAT_STAND);
animModel3->setMaterialTexture(0, driver->getTexture(modelTexturePathfile.c_str()));
// Create HexMap
HexMap* hexMap = new HexMap();
float xpos, zpos;
for( int z=0; z<20; z++)
for (int x = 0; x < 20; x++)
{
HexTile* tile = new HexTile(sceneManager->getRootSceneNode(), sceneManager, 666);
xpos = float(x) * 2.0f * innerRadius + (z%2)*innerRadius;
zpos = float(z) * 1.5f * outerRadius;
tile->setPosition(vector3df(xpos, 0, zpos));
hexMap->addTile(tile);
}
// MAIN "TW Editor" LOOP
while (device->run())
{
if (device->isWindowActive())
{
// UPDATE
if (receiver.IsKeyDown(irr::KEY_ESCAPE)) // if press ESCAPE then exit
{
device->drop();
return 0;
}
if (receiver.IsKeyDown(irr::KEY_KEY_A)) cam_x -= 1.0f;
if (receiver.IsKeyDown(irr::KEY_KEY_D)) cam_x += 1.0f;
if (receiver.IsKeyDown(irr::KEY_KEY_W)) cam_z += 1.0f;
if (receiver.IsKeyDown(irr::KEY_KEY_S)) cam_z -= 1.0f;
cam->setPosition(vector3df(cam_x, 200, cam_z));
cam->setTarget(vector3df(cam_x, 30, cam_z));
// RENDER
driver->beginScene(true, true, SColor(clear_a, clear_r, clear_g, clear_b)); // clear screen
sceneManager->drawAll(); // render scene
driver->draw2DImage(TWTexture, position2d<s32>(0, screenHeight - 128 - 20), rect<s32>(0, 0, 128, 128)); // render TW Logo
boldFont->draw(L"TW World Editor v0.1", recti(20, screenHeight - 20, 100, screenHeight), SColor(256, 128, 48, 48), true, true); // render text on bottom
GUI->drawAll(); // render GUI
position2d<s32> m = device->getCursorControl()->getPosition(); // render cursor
driver->endScene(); // render submit
// FPS
int currentFPS = driver->getFPS();
core::stringw str = L"FPS: ";
str += currentFPS;
device->setWindowCaption(str.c_str());
}
else
device->yield(); // if window is inactive not use CPU
}
// In the end, delete the Irrlicht device.
device->drop();
return 0;
}