#include <iostream>
#include <irr/irrlicht.h>
#include <stdio.h>
#include <time.h>
#include "perso_config.h"
using namespace std;
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
enum { /* On définit les états de la machine à état d'animation */
ST_IDLE_0,
ST_WALK_1,
ST_JUMP_2,
ST_ATTAK_3,
ST_TAKE_4,
ST_GIVE_5};
static uint8_t next_state = ST_IDLE_0, state = ST_IDLE_0; /* Initialize next & current states ........................... */
void fsm_state(uint16_t old_anim_end, uint16_t new_anim_start, uint16_t new_anim_end, uint16_t new_anim_speed);
void fsm_goNextState(uint8_t newState);
void fsm_perso_manage_anim(void);
irr::scene::IAnimatedMesh* ePlayer;
IAnimatedMeshSceneNode* NodePlayer; /* Le node du player .......................................... */
irr::scene::IAnimatedMesh* eBox;
IAnimatedMeshSceneNode* NodeBox;
irr::scene::IAnimatedMesh* eTerrain;
IAnimatedMeshSceneNode* NodeTerrain;
int frameEnCour = 0;
bool anim_working = false;
int KEY_SAVED_STATE[KEY_KEY_CODES_COUNT ] = {0};
static void keypad_KEY_SAVED_STATE_control(uint8_t AskingState, irr::EKEY_CODE key)
{
int KEY_CURRENT_STATE = KEY_SAVED_STATE[key];
switch(AskingState)
{
case RESET:
if(KEY_CURRENT_STATE == SET)
{
KEY_SAVED_STATE[key] = RESET;
}
break;
case SET:
if(KEY_CURRENT_STATE == RESET)
{
KEY_SAVED_STATE[key] = SET;
}
break;
default:
break;
}
}
static void key_event_test(const SEvent& event)
{
if(event.KeyInput.PressedDown) // si la touche est appuyée
{
keypad_KEY_SAVED_STATE_control(SET, event.KeyInput.Key);
}else{ // si la touche est relachée
keypad_KEY_SAVED_STATE_control(RESET, event.KeyInput.Key);
}
}
class MyEventReceiver : public IEventReceiver
{
public:
MyEventReceiver(){}
bool OnEvent(const SEvent& event)
{
// si l'événement et une touche du clavier
if (event.EventType == irr::EET_KEY_INPUT_EVENT)
{
key_event_test(event);
}
return false;
}
private:
};
void animation_bind_idle(EKEY_CODE key)
{
if((KEY_SAVED_STATE[key] == 0) && anim_working == false)
{
NodePlayer->setAnimationSpeed(IDLE_ANIM_SPEED);
NodePlayer->setFrameLoop(START_IDLE_ANIM_FRAME,ENDED_IDLE_ANIM_FRAME);
NodePlayer->setLoopMode(true);
fsm_goNextState(ST_IDLE_0);
}
}
void animation_bind_single(uint16_t new_anim_start, uint16_t new_anim_end, uint16_t new_anim_speed, EKEY_CODE key, uint8_t newState)
{
if(KEY_SAVED_STATE[key] == 1 )
{
anim_working = true;
NodePlayer->setAnimationSpeed(new_anim_speed);
NodePlayer->setFrameLoop(new_anim_start,new_anim_end);
fsm_goNextState(newState);
}
}
void animation_bind_ended(uint16_t new_anim_end)
{
if((NodePlayer->getFrameNr())> (new_anim_end - ANIM_OFFSET))
{
anim_working = false;
NodePlayer->setLoopMode(false);
}
}
void animation_bind_looped(uint16_t new_anim_start, uint16_t new_anim_end, uint16_t new_anim_speed, EKEY_CODE key, uint8_t newState)
{
if(KEY_SAVED_STATE[key] == 1)
{
NodePlayer->setAnimationSpeed(new_anim_speed);
NodePlayer->setFrameLoop(new_anim_start,new_anim_end);
NodePlayer->setLoopMode(true);
fsm_goNextState(newState);
}
}
/* ******************************************************************************************************************************** */
/* GO TO NEXT STATE */
/* ******************************************************************************************************************************** */
void fsm_goNextState(uint8_t newState) /* Function for going to next state automatically ............. */
{
next_state = newState; /* Stay to actual state : leds flashing ....................... */
}
/* ******************************************************************************************************************************** */
/* FSM */
/* ******************************************************************************************************************************** */
void fsm_perso_manage_anim(void)
{
/// On relève le numero de la frame en cours
frameEnCour = NodePlayer->getFrameNr();
switch(state)
{
case ST_IDLE_0: // Etat Idle
animation_bind_single(START_ATTACK_ANIM_FRAME , ENDED_ATTACK_ANIM_FRAME , ATCK_ANIM_SPEED, KEY_ATTK, ST_ATTAK_3);
animation_bind_single(START_JUMP_ANIM_FRAME , ENDED_JUMP_ANIM_FRAME , JUMP_ANIM_SPEED, KEY_JUMP, ST_JUMP_2);
animation_bind_single(START_TAKE_ANIM_FRAME , ENDED_TAKE_ANIM_FRAME , TAKE_ANIM_SPEED, KEY_TAKE, ST_TAKE_4);
animation_bind_single(START_GIVE_ANIM_FRAME , ENDED_GIVE_ANIM_FRAME , GIVE_ANIM_SPEED, KEY_GIVE, ST_GIVE_5);
animation_bind_looped(START_WALK_ANIM_FRAME , ENDED_WALK_ANIM_FRAME , WALK_ANIM_SPEED, KEY_WALK, ST_WALK_1);
break;
case ST_WALK_1:
animation_bind_single(START_ATTACK_ANIM_FRAME , ENDED_ATTACK_ANIM_FRAME , ATCK_ANIM_SPEED, KEY_ATTK, ST_ATTAK_3);
animation_bind_single(START_JUMP_ANIM_FRAME , ENDED_JUMP_ANIM_FRAME , JUMP_ANIM_SPEED, KEY_JUMP, ST_JUMP_2);
animation_bind_idle(KEY_WALK);
break;
case ST_JUMP_2:
animation_bind_ended(ENDED_JUMP_ANIM_FRAME);
animation_bind_idle(KEY_JUMP);
break;
case ST_ATTAK_3:
animation_bind_ended(ENDED_ATTACK_ANIM_FRAME);
animation_bind_idle(KEY_ATTK);
break;
case ST_TAKE_4:
animation_bind_ended(ENDED_TAKE_ANIM_FRAME);
if(NodeBox)NodePlayer->addChild(NodeBox);
NodeBox -> setScale(vector3df(0.1f,0.1f,0.1f));
NodeBox -> setPosition(vector3df(0.0f,-0.1f,0.0f));
animation_bind_idle(KEY_TAKE);
break;
case ST_GIVE_5:
animation_bind_ended(ENDED_GIVE_ANIM_FRAME);
if(NodeBox)NodeTerrain -> addChild(NodeBox);
if(NodeBox)NodePlayer->removeChild(NodeBox);
NodeBox -> setScale(vector3df(0.5f,0.5f,0.5f));
NodeBox -> setPosition(vector3df(0.0f,10.1f,0.0f));
animation_bind_idle(KEY_GIVE);
break;
default :
break;
}
state = next_state;
}
int main( int argc, char** argv )
{
/// Initialisation
IrrlichtDevice *device = createDevice( EDT_OPENGL, dimension2d<u32>(1024,768), 32, false, false, false,0); //EDT_SOFTWARE
if (!device) return 1;
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();
/// Charge le node du player
ePlayer = (IAnimatedMesh*)smgr->getMesh("media/ninja.b3d");
NodePlayer = smgr->addAnimatedMeshSceneNode(ePlayer);
NodePlayer->setMaterialTexture(0, driver->getTexture("media/nskinbl.jpg"));
NodePlayer->setMaterialFlag(EMF_LIGHTING, false);
NodePlayer->setScale(vector3df(0.05f,0.05f,0.05f));
NodePlayer->setPosition(vector3df(-0.4f,1.1f,0.0f));
NodePlayer->setRotation(vector3df(0.0f,-240.0f,-90.0f));
NodePlayer->setAnimationSpeed(IDLE_ANIM_SPEED);
NodePlayer->setFrameLoop(START_IDLE_ANIM_FRAME,ENDED_IDLE_ANIM_FRAME); // ATTENDRE
/// Charge le node de l'accessoire
eBox = (IAnimatedMesh*)smgr->getMesh("media/box2.X");
NodeBox = smgr->addAnimatedMeshSceneNode(eBox);
NodeBox -> setMaterialTexture(0, driver->getTexture("media/box3.jpg"));
NodeBox -> setMaterialFlag(EMF_LIGHTING, false);
NodeBox -> setScale(vector3df(0.01f,0.01f,0.01f));
NodeBox -> setPosition(vector3df(-0.4f,1.1f,0.4f));
NodeBox -> setRotation(vector3df(0.0f,-240.0f,-90.0f));
NodeBox -> setLoopMode(false);
/// Charge le node du terrain
eTerrain = (IAnimatedMesh*)smgr->getMesh("media/box2.X");
NodeTerrain = smgr->addAnimatedMeshSceneNode(eTerrain);
NodeTerrain -> setMaterialTexture(0, driver->getTexture("media/box1.jpg"));
NodeTerrain -> setMaterialFlag(EMF_LIGHTING, false);
NodeTerrain -> setPosition(vector3df(-0.4f,1.1f,0.0f));
NodeTerrain -> setRotation(vector3df(0.0f,-240.0f,-90.0f));
NodeTerrain -> setScale(vector3df(0.01f,0.01f,0.01f));
NodeTerrain -> setLoopMode(false);
/// Crée la camera
ICameraSceneNode *cam = smgr->addCameraSceneNode(0, vector3df(0,0,0), vector3df(0,5,0));
cam->setFarValue(1000.0f);
cam->setNearValue (0.0001f);
/// Crée le receveur d'événements.
MyEventReceiver receiver;
device->setEventReceiver(&receiver);
while(device->run())
{
driver->beginScene(true, true, SColor(255,100,101,140));
fsm_perso_manage_anim();/// La FSM est dans un état d'attente
smgr->drawAll();
guienv->drawAll();
driver->endScene();
}
device->drop();
return 0;
}