Tutorial 4: Movement (Bewegung)(übersetzt von Ba'el, orig. eng. Von irrlicht.sourceforge.net)
Dieses Tutorial zeigt wie man SceneNodes bewegt und animiert. Das Grundkonzept von SceneNodeAnimators zeigt ebenso manuelle Bewegungen von Knoten (node) sowie das Benutzen der Tastatur.
Das Programm was hier beschrieben wird wird so aussehen:
Los gehts!
Wie immer warden die header files includet, benutze die irr namespace, und linke die .lib file.
Code:
#include <stdio.h>
#include <wchar.h>
#include <irrlicht.h>
using namespace irr;
#pragma comment(lib, "Irrlicht.lib")
Eines der Ziele dieses Tutorial ist das Bewegen der “scene node“ durch nutzen der Tastatur. Wir speichern einen pointer auf die “scene nodeâ€, welchen wir für das Bewegen mit den Tasten benötigen.
Der andere pointer ist ein pointer auf das Irrlicht Device, welchen wir in EventReceiver zum manipulieren der „scene node“ und für die aktive Kamera benötigen..
Code:
scene::ISceneNode* node = 0;
IrrlichtDevice* device = 0;
Für die Maus- und Tastatureingabe, oder GUI-Ereignissen wie "die OK-Taste wurde gedrückt", brauchen wir ein Object welches vom IEventReceiver-Object stammt. Dort ist nur eine Methode welche überschrieben warden muss: OnEvent. Diese Methode wird von der Engine aufgerufen wenn ein Ereignis stattfindet. Wir wollen zum Bewegen der „scene node†die Tasten W und S nutzen..
Code:
class MyEventReceiver : public IEventReceiver
{
public:
virtual bool OnEvent(SEvent event)
{
Wenn die Tasten 'W' oder 'S' gedrückt wurden bekommen wir die Position der „scene node“, und modifizieren die Y-Koordinate ein kleines bisschen. Also wenn wir 'W' drücken bewegt sich der Knoten nach oben, und wenn du 'S' drückst nach unten .
Code:
if (node != 0 && event.EventType == irr::EET_KEY_INPUT_EVENT &&
!event.KeyInput.PressedDown)
{
switch(event.KeyInput.Key)
{
case KEY_KEY_W:
case KEY_KEY_S:
{
core::vector3df v = node->getPosition();
v.Y += event.KeyInput.Key == KEY_KEY_W ? 2.0f : -2.0f;
node->setPosition(v);
}
return true;
}
}
return false;
}
};
Die Funktion zum erkennen von Bewegungen der „scene node“ ist nun bereit. Lass uns nun eine Irrlicht Device erstellen und die „scene node“ die wir zum Bewegen brauchen. Wir erzeugen auch noch andere zusätzliche “scene nodesâ€, um zu zeigen das es noch verschiedene Möglichkeiten, zum bewegen und animieren von „scene nodes“ .
Code:
int main()
{
MyEventReceiver receiver;
device = createDevice(video::EDT_OPENGL, core::dimension2d<s32>(640, 480),
16, false, false, false, &receiver);
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
Erstelle den Knoten zun Bewegen mit den Tasten 'W' und 'S'. Wir erstellen einen Testknoten, welcher eine Kugel zu Testzwecken in die Engine einbaut. Wir platzieren den Knoten an (0,0,30) und teile ihm eine Textur zu, damit es etwas interessanter aussieht.
Code:
node = smgr->addSphereSceneNode ();
node->setPosition(core::vector3df(0,0,30));
node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
node->setMaterialFlag(video::EMF_LIGHTING, false);
Nun erstellen wir einen anderen Knoten zu dessen Bewegung benutzen wir einen „scene node animator“. „Scene node animators†modifizieren “scene nodes†und können bei jeder möglichen “scene node“ angeheftet werden, z.B.
“mesh scene nodes“, „billboards“, „lights“ und sogar „camera scene nodes“. „Scene node animators†sind nicht allein zum modifizieren der Position eines “scene nodeâ€, er kann z.B. auch Texturen von Objekten animieren. Wir erstellen noch einen Test-„scene node†und heften ihn einer freikreisenden ('fly circle') „scene node“ an, schreibe noch diesen Knoten und fliege in deiner ersten „scene node“ rum.
Code:
scene::ISceneNode* n = smgr->addCubeSceneNode ();
if(n)
{
n->setMaterialTexture(0, driver->getTexture("../../media/t351sml.jpg"));
n->setMaterialFlag(video::EMF_LIGHTING, false);
scene::ISceneNodeAnimator* anim =
smgr->createFlyCircleAnimator(core::vector3df(0,0,30), 20.0f);
n->addAnimator(anim);
anim->drop();
}
Der letzte “scene node†den wir einfügen zeigt Möglichkeiten eines “scene node animators†bei .md2 Modellen, welcher einen gradlinigen ('fly straight') Animator benutzt um zwischen zwei Punkten zu laufen.
Code:
scene::IAnimatedMeshSceneNode* anms = smgr->addAnimatedMeshSceneNode(
smgr->getMesh("../../media/sydney.md2"));
if (anms)
{
scene::ISceneNodeAnimator* anim =
smgr- >createFlyStraightAnimator(core::vector3df(100,0,60),
core::vector3df(-100,0,60), 2500, true);
anms->addAnimator(anim);
anim->drop();
Damit das Modell besser aussieht müssen wir das Licht abschalten (wir haben keine Lichter implementiert und so würde das Modell Schwarz erscheinen), setze die Frames zwischen den die Animation in einer Schleife läuft, rotiere das Modell um 180°, und passe die Animationsgeschwindigkeit und die Textur an.
Um die Animation richtig einzustellen (Frames und Geschwindigkeit), können wir "anms->setMD2Animation(scene::EMAT_RUN)" aufrufen für die 'lauf'-Animation müssen wir sattdessen "setFrameLoop" und "setAnimationSpeed" aufrufen, aber diese funktionieren nur mit MD2-Animationen, und so weist du wie man andere Animations startet.
Code:
anms->setMaterialFlag(video::EMF_LIGHTING, false);
anms->setFrameLoop(320, 360);
anms->setAnimationSpeed(30);
anms->setRotation(core::vector3df(0,180.0f,0));
anms->setMaterialTexture(0, driver->getTexture("../../media/sydney.BMP"));
}
Um zu sehen wie wir uns im der “scene†herumbewegen müssen wir eine “first person shooter style camera“ erstellen und den Mauszeiger unsichtbar machen.
Code:
smgr->addCameraSceneNodeFPS(0, 100.0f, 100.0f);
device->getCursorControl()->setVisible(false);
Das hätten wir geschaft jetzt muss nur noch alles gezeichnet werden. Also schreiben wir die aktuellen Frames pro Sekunde und den Treibernamen in die Ãœberschrift des Fensters.
Code:
int lastFPS = -1;
while(device->run())
{
driver->beginScene(true, true, video::SColor(255,90,90,156));
smgr->drawAll();
driver->endScene();
int fps = driver->getFPS();
if (lastFPS != fps)
{
wchar_t tmp[1024];
swprintf(tmp, 1024, L"Movement Example - Irrlicht Engine (%s)(fps:%d)",
driver->getName(), fps);
device->setWindowCaption(tmp);
lastFPS = fps;
}
}
device->drop();
return 0;
}
Das war's, Kompiliere es und probier etwas rum.[/img]