This code:
main.cpp:
Code: Select all
#include <irrlicht.h>
#include "cam/3DP.h"
//#include "terrain/ShTlTerrainSceneNode.h"
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
enum {UP, PRESSED, DOWN, RELEASED};
int keyState[KEY_KEY_CODES_COUNT] = {0};
bool paused = false;
bool quitGame = false;
IrrlichtDevice *Device=createDevice(EDT_OPENGL, dimension2d<u32>(1024, 768), 32, true, false, false, 0);
IVideoDriver *Driver=Device->getVideoDriver();
ISceneManager *SceneManager=Device->getSceneManager();
IGUIEnvironment *Gui=Device->getGUIEnvironment();
scene::IAnimatedMeshSceneNode* playerNode = NULL;
scene::EMD2_ANIMATION_TYPE playerAnim;
void resetKeys() {
for (int i = 0 ; i < KEY_KEY_CODES_COUNT ; ++i)
keyState[i] = UP;
}
void updateKeys() {
for(int i = 0 ; i < KEY_KEY_CODES_COUNT ; ++i)
if (keyState[i] == RELEASED)
keyState[i] = UP;
else if (keyState[i] == PRESSED)
keyState[i] = DOWN;
}
class MyEventReceiver : public IEventReceiver {
public:
virtual bool OnEvent(const SEvent& event) {
if (event.EventType == EET_KEY_INPUT_EVENT) {
// update keyStates
if (event.KeyInput.PressedDown) {
// If key was not down before
if (keyState[event.KeyInput.Key] != DOWN)
keyState[event.KeyInput.Key] = PRESSED; // Set to Pressed
else
// if key was down before
keyState[event.KeyInput.Key] = DOWN; // Set to Down
} else {
// if the key is down
if (keyState[event.KeyInput.Key] != UP)
keyState[event.KeyInput.Key] = RELEASED; // Set to Released
}
switch(event.KeyInput.Key) {
case KEY_ESCAPE: {
if (!event.KeyInput.PressedDown) {
quitGame = true;
return true;
}
break;
}
case KEY_KEY_P: {
if (!event.KeyInput.PressedDown) {
// Pause the scene
paused = !paused;
// if (pausedText) pausedText->setVisible(paused);
if (Device)
if (paused) // Freezes animators
Device->getTimer()->setSpeed(0);
else // Unfreezes animators
Device->getTimer()->setSpeed(1);
return true;
}
break;
}
}
}
return false;
}
};
void processKeys(int elapsedTime) {
bool turning = false;
bool walking = false;
if (keyState[KEY_KEY_W] == PRESSED || keyState[KEY_KEY_W] == DOWN) {
// Move forward
core::vector3df move = core::vector3df(5,0,0);
core::matrix4 mat;
mat.setRotationDegrees(playerNode->getRotation());
mat.transformVect(move);
move *= 0.1f * elapsedTime;
playerNode->setPosition(playerNode->getPosition() + move);
if (playerAnim != scene::EMAT_RUN) {
playerNode->setMD2Animation(scene::EMAT_RUN);
playerAnim = scene::EMAT_RUN;
}
walking = true;
}
if(keyState[KEY_KEY_S] == PRESSED || keyState[KEY_KEY_S] == DOWN) {
// Move backward
core::vector3df move = core::vector3df(5,0,0);
core::matrix4 mat;
mat.setRotationDegrees(playerNode->getRotation());
mat.transformVect(move);
move *= 0.1f * elapsedTime;
playerNode->setPosition(playerNode->getPosition() - move);
if (playerAnim != scene::EMAT_RUN) {
playerNode->setMD2Animation(scene::EMAT_RUN);
playerAnim = scene::EMAT_RUN;
}
walking = true;
}
if(keyState[KEY_KEY_A] == PRESSED || keyState[KEY_KEY_A] == DOWN) {
// Turn left
core::vector3df rot = core::vector3df(0,10,0) * 0.1f * (f32)elapsedTime;
playerNode->setRotation(playerNode->getRotation() - rot);
if (!walking && playerAnim != scene::EMAT_STAND) {
playerNode->setMD2Animation(scene::EMAT_STAND);
playerAnim = scene::EMAT_STAND;
}
turning = true;
}
if(keyState[KEY_KEY_D] == PRESSED || keyState[KEY_KEY_D] == DOWN) {
// Turn right
core::vector3df rot = core::vector3df(0,10,0) * 0.1f * (f32)elapsedTime;
playerNode->setRotation(playerNode->getRotation() + rot);
if (!walking && playerAnim != scene::EMAT_STAND) {
playerNode->setMD2Animation(scene::EMAT_STAND);
playerAnim = scene::EMAT_STAND;
}
turning = true;
}
if (!walking && !turning && playerAnim != scene::EMAT_STAND) {
// Stand still
playerNode->setMD2Animation(scene::EMAT_STAND);
playerAnim = scene::EMAT_STAND;
}
}
int main(int argc, char** argv)
{
MyEventReceiver receiver;
Device->setEventReceiver(&receiver);
//ShTlTerrainSceneNode* terrain;
scene::IAnimatedMesh* mesh = SceneManager->getMesh("data/avatar/sydney.md2");
if (!mesh) printf("couldn't load player mesh\n");
playerNode = SceneManager->addAnimatedMeshSceneNode(mesh);
if (!playerNode) printf("couldn't create player node\n");
playerNode->setMaterialFlag(video::EMF_LIGHTING, false);
playerNode->setMD2Animation(scene::EMAT_STAND);
playerAnim = scene::EMAT_STAND;
playerNode->setMaterialTexture(0, Driver->getTexture("data/avatar/sydney.jpg"));
playerNode->OnAnimate(0);
playerNode->setPosition(vector3df(-1200,-50,-1400));
core::aabbox3d<f32> box = playerNode->getTransformedBoundingBox();
playerNode->setPosition(box.MaxEdge - box.getCenter());
scene::ICameraSceneNode* camera = SceneManager->addCameraSceneNode(playerNode);
if (!camera) printf("Failed camera creation\n");
camera->setPosition(((box.MaxEdge - box.getCenter())*2.0f)+core::vector3df(-100,25,0));
camera->setTarget(playerNode->getPosition());
float Distanciaance3= 30;
CScene3PCamera *camAnim = new CScene3PCamera(SceneManager,Device->getCursorControl(),
playerNode,Distanciaance3,-90,-30,false,irr::core::vector3df(0,0,0),10);
camera->addAnimator(camAnim);
scene::ITerrainSceneNode* terrain = SceneManager->addTerrainSceneNode(
"data/world/111.bmp",
0, // parent node
-1, // node id
core::vector3df(0.f, 0.f, 0.f), // position
core::vector3df(0.f, 0.f, 0.f), // rotation
core::vector3df(40.f, 4.4f, 40.f), // scale
video::SColor ( 255, 255, 255, 255 ), // vertexColor
5, // maxLOD
scene::ETPS_17, // patchSize
4 // smoothFactor
);
terrain->setMaterialFlag(video::EMF_LIGHTING, false);
terrain->setMaterialTexture(0,
Driver->getTexture("data/world/terrain-texture.jpg"));
terrain->setMaterialTexture(1,
Driver->getTexture("data/world/detail_grass.jpg"));
terrain->setMaterialType(video::EMT_DETAIL_MAP);
terrain->scaleTexture(1.0f, 20.0f);
scene::ISceneNode* skydome=SceneManager->addSkyDomeSceneNode(Driver->getTexture("data/world/skyd1.jpg"),16,8,0.95f,2.0f);
int startTime = Device->getTimer()->getTime();
int elapsedTime = 0;
while(Device->run())
{
elapsedTime = Device->getTimer()->getTime() - startTime;
startTime = Device->getTimer()->getTime();
processKeys(elapsedTime);
// Update third person cam
camera->setTarget(playerNode->getPosition());
Driver->beginScene(true, true, SColor(0,200,200,200));
SceneManager->drawAll();
Gui->drawAll();
Driver->endScene();
}
Device->drop();
return 0;
}
Code: Select all
/*Particular Zlib License /LIBRARY(C).
3DP.h
3DP.cpp
Licenзa ZLIB/LIBPNG
Disponнvel, no original, em: http://www.opensource.org/licenses/zlib-license.php
Versгo 1.01
Licenзa ZLIB/LIBPNG
Direitos autorais Copyright (C) 2008 Lucian. 2009 Lucian,cуdigo original encontrado em um forum.
Este programa de computador й fornecido "como estб",
sem garantias de qualquer espйcie, expressas ou tбcitas.
Em nenhuma hipуtese os autores serгo responsбveis por
quaisquer danos decorrentes do uso deste programa de computador.
Outorga-se permissгo para qualquer um usar este programa de
computador para quaisquer fins, incluindo utilizaзхes comerciais,
e para o modificar e redistribuir livremente, sujeita аs seguintes restriзхes:
1. A origem deste programa de computador nгo pode ser apresentada
de forma errфnea; vocк nгo pode reivindicar ter escrito o programa
de computador original. Se vocк usar esse programa de computador em
um produto, um reconhecimento de crйditos na documentaзгo do produto
seria apreciada, mas nгo й exigida.
2. Versхes alteradas do cуdigo-fonte devem estar marcadas como tais,
e nгo podem ser apresentadas forma errфnea, como sendo o programa de
computador original.
3. Este aviso nгo pode ser alterado ou removido de qualquer distribuiзгo de cуdigo fonte.*/
#ifndef _3DP_h_
#define _3DP_h_
#include <irrlicht.h>
#define EPSILON 0.001f
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
class CScene3PCamera : public irr::scene::ISceneNodeAnimator,public irr::IEventReceiver
{
public:
//! Construtor
//! player: Objeto a Seguir
//! Distanciaancia: The initial Distanciaance from the player
//! initAngleY: The initial horizontal rotatation
//! initAngleZ: The initial vertical rotation
//! targetOffset: The offset from the object's center at which the camera looks
//! minDistancia/maxDistancia: Distanciaance bounding
//! minAngle/maxAngle: Rotation bounding. -89 ==> looking up at player, 89 ==> looking down
//! boxSize: The size of the box in which mouse movements do not result in camera movements
CScene3PCamera(
irr::scene::ISceneManager *manager,
irr::gui::ICursorControl *cursor,
irr::scene::ISceneNode *player,
irr::f32 Distanciaancia = 50.0f,
irr::f32 initAngleY = 180.0f,
irr::f32 initAngleZ = 10.0f,
bool RotatePlayer = false,
irr::core::vector3df targetOffset = irr::core::vector3df(0,0,0),
irr::f32 minDistancia = 20.0f,
irr::f32 maxDistancia = 200.0f,
irr::f32 minAngle = -45.0f,
irr::f32 maxAngle = 89.0f,
irr::f32 boxSize = 0.0f,
irr::f32 rotationSpeed = 60.0f);
//! Destructor
virtual ~CScene3PCamera(void);
//! animates the scene node
virtual void animateNode(ISceneNode* node, u32 timeMs);
//! Process an input event
virtual ISceneNodeAnimator* createClone (ISceneNode *node, ISceneManager *newManager=0)
{
return new CScene3PCamera(Manager,Cursor,Player,Distancia,AngleY,
AngleZ,false,TargetOffset,MinDistancia,MaxDistancia,MinAngle,
MaxAngle,BoxSize,RotationSpeed);
}
// virtual bool OnEvent(irr::SEvent event);
virtual bool OnEvent(const SEvent& event);
//! Get/set active status
int isActive();
void setActive(bool status);
virtual ESCENE_NODE_ANIMATOR_TYPE getType(void) const
{
return ESNAT_UNKNOWN;
}
virtual bool isEventReceiverEnabled(void) const
{
return false;
}
//! Get/set box size
irr::f32 getBoxSize();
void setBoxSize(irr::f32 newSize);
//! Map zoom in/zoom out buttons
//! Access the camera's current orientation
irr::f32 getOrientation();
bool XRotatePlayer;
// current states
irr::f32 Distancia;
irr::f32 AngleY;
irr::f32 AngleZ;
private:
int Active;//bool Active;
/*
// current states
irr::f32 Distancia;
irr::f32 AngleY;
irr::f32 AngleZ;
*/
// boundaries
irr::core::vector3df TargetOffset;
irr::f32 MinDistancia;
irr::f32 MaxDistancia;
irr::f32 MinAngle;
irr::f32 MaxAngle;
irr::f32 BoxSize;
// Motion
irr::f32 RotationSpeed;
//! Node to follow
irr::scene::ISceneNode *Player;
irr::scene::ISceneManager *Manager;
irr::gui::ICursorControl *Cursor;
//! Puts the cursor back in the box
void updateCursorPosition();
};
#endif
Code: Select all
#include "3DP.h"
CScene3PCamera::CScene3PCamera(
irr::scene::ISceneManager *manager,
irr::gui::ICursorControl *cursor,
irr::scene::ISceneNode *player,
irr::f32 Distanciaancia,irr::f32 initAngleY,
irr::f32 initAngleZ,
bool RotatePlayer,
irr::core::vector3df targetOffset,
irr::f32 minDistancia,
irr::f32 maxDistancia,
irr::f32 minAngle,
irr::f32 maxAngle,
irr::f32 boxSize,
irr::f32 rotationSpeed)
: Active(true), Manager(manager), Cursor(cursor), Player(player),
Distancia(Distanciaancia),AngleY(initAngleY),AngleZ(initAngleZ),XRotatePlayer(RotatePlayer),
TargetOffset(targetOffset),
MinDistancia(minDistancia), MaxDistancia(maxDistancia), MinAngle(-maxAngle), MaxAngle(-minAngle),
BoxSize(boxSize), RotationSpeed(rotationSpeed)
{
Cursor->setPosition(0.5f,0.5f);
// Ensure Distanciaance is bounded correctly
if(Distancia < MinDistancia) Distancia = MinDistancia;
else if(Distancia > MaxDistancia) Distancia = MaxDistancia;
// Bound MinAngle/MaxAngle to avoid problematic areas
if(MinAngle < -89.0f) MinAngle = -89.0f;
if(MinAngle > 89.0f) MinAngle = 89.0f;
if(MaxAngle < -89.0f) MaxAngle = -89.0f;
if(MaxAngle > 89.0f) MaxAngle = 89.0f;
if(minAngle > maxAngle) MaxAngle = MinAngle+1.0f;
// Ensure Vertical Rotation Angle is bounded correctly
if(AngleZ < MinAngle) AngleZ = MinAngle;
else if(AngleZ > MaxAngle) AngleZ = MaxAngle;
}
//! Destructor
CScene3PCamera::~CScene3PCamera(void)
{
}
//! Puts the cursor back in the box
void CScene3PCamera::updateCursorPosition()
{
irr::core::position2d<irr::f32> pos = Cursor->getRelativePosition();
if(pos.X < (0.5f-BoxSize)) pos.X = (0.5f-BoxSize);
if(pos.X > (0.5f+BoxSize)) pos.X = (0.5f+BoxSize);
if(pos.Y < (0.5f-BoxSize)) pos.Y = (0.5f-BoxSize);
if(pos.Y > (0.5f+BoxSize)) pos.Y = (0.5f+BoxSize);
Cursor->setPosition(pos);
}
//! Process an input event
bool CScene3PCamera::OnEvent(const irr::SEvent& event)
{
if(!Active)
{
return false;
}
if(event.EventType == irr::EET_KEY_INPUT_EVENT)
{
}
return false;
}
//! Get/set active status
int CScene3PCamera::isActive()
{
return Active;
}
void CScene3PCamera::setActive(bool status)
{
// reset the cursor only if we are switching back to active from inactive
if(!Active && status)
{
updateCursorPosition();
}
Active = status;
}
//! Get/set box size
irr::f32 CScene3PCamera::getBoxSize()
{
return BoxSize;
}
void CScene3PCamera::setBoxSize(irr::f32 newSize)
{
BoxSize = newSize;
updateCursorPosition();
}
//! Access the camera's current orientation
irr::f32 CScene3PCamera::getOrientation()
{
return AngleY;
}
//! animates the scene node
void CScene3PCamera::animateNode(irr::scene::ISceneNode *node, irr::u32 timeMs)
{
// make sure you don't go attaching this animator to anything other than a camera
irr::scene::ICameraSceneNode *camera = (irr::scene::ICameraSceneNode*)node;
if(Manager->getActiveCamera() != camera)
{
return;
}
if(Active)
{
// Camera is active, rotate as necessary
irr::core::position2d<irr::f32> pos = Cursor->getRelativePosition();
if(pos.X < 0.5f-BoxSize-EPSILON)
{
AngleY -= (pos.X-(0.5f-BoxSize))*RotationSpeed;//Decrement of this statement gives the correct movement to the mouse.... by smartwhiz
}
if(pos.X > 0.5f+BoxSize+EPSILON)
{
AngleY -= (pos.X-(0.5f+BoxSize))*RotationSpeed;//Decrement of this statement gives the correct movement to the mouse.... by smartwhiz
}
// So we don't get huge rotation numbers
if(AngleY > 360.0f)
{
AngleY += 360.0f;
}
if(AngleY < 0.0f)
{
AngleY -= 360.0f;
}
if(pos.Y < 0.5f-BoxSize-EPSILON)
{
AngleZ -= (pos.Y-(0.5f-BoxSize))*RotationSpeed;
}
if(pos.Y > 0.5f+BoxSize+EPSILON)
{
AngleZ -= (pos.Y-(0.5f+BoxSize))*RotationSpeed;
}
// Ensure Vertical Rotation Angle is bounded correctly
if(AngleZ < MinAngle) AngleZ = MinAngle;
else if(AngleZ > MaxAngle) AngleZ = MaxAngle;
//keep the player in the view angle that of the camera, this is the change made......... by smartwhiz
if (XRotatePlayer == true){
Player->setRotation(irr::core::vector3df(0,-(AngleY+180),0));
}
updateCursorPosition();
}
// Create translation vector
irr::core::vector3df translation(Distancia,0,0);
translation.rotateXYBy(-AngleZ,irr::core::vector3df(0,0,0));
translation.rotateXZBy(AngleY,irr::core::vector3df(0,0,0));
// Assumes the camera is *not* a child of the player node
camera->setTarget(Player->getPosition()+TargetOffset);
camera->setPosition(Player->getPosition()+translation+TargetOffset);
}