Pokemon/Zelda keyboard key management

From CatchChallenger wiki
Jump to: navigation, search

This page show how you can do a keyboard key management to have move like Pokemon/Zelda. It's done via Qt, but can be translated into other languages. That's mean:

  • Change texture during the move, and exact position when the full step is done
  • Quick arrow key press into other direction, just look
  • Long arrow key press into other direction, look and move after 200ms if the arrow key continue to be pressed
  • Quick arrow key press into same direction, just move
  • At the final step, look is the move key continue to be pressed, if yes, continue the walk, else enter into looking (stopped).

Texture and position

The tileset for the player texture is like:

Player skin simple.png

Where the tile number is:

0 1 2
3 4 5
6 7 8
9 10 11

The move is defined with initial position (0%), 2 intermediate position (33% and 66%) and the final position (100%).

The full source

The full source is used into map visualiser for the projet: https://github.com/alphaonex86/CatchChallenger/blob/master/tools/map-visualiser-qt/map-visualiser-qt.cpp

The code

void MapVisualiserQt::keyPressEvent(QKeyEvent * event)
{
    //ignore the repeated event
    if(event->isAutoRepeat())
        return;
 
     //add to pressed key list
    keyPressed << event->key();

    //apply the key
    keyPressParse();
}

void MapVisualiserQt::keyPressParse()
{
    //ignore is already in move
    if(inMove)
        return;

    if(keyPressed.contains(16777234))
    {
        //already turned on this direction, then try move into this direction
        if(direction==CatchChallenger::Direction_look_at_left)
        {
            if(!CatchChallenger::MoveOnTheMap::canGoTo(CatchChallenger::Direction_move_at_left,&logicalMap,xPerso,yPerso,true))
                return;//Can't do at the left!
            //the first step
            direction=CatchChallenger::Direction_move_at_left;
            inMove=true;
             moveStep=1;
             moveStepSlot();
         }
         //look in this direction
        else
        {
            playerMapObject->setTile(playerTileset->tileAt(10));
            direction=CatchChallenger::Direction_look_at_left;
            lookToMove.start();
        }
    }
    else if(keyPressed.contains(16777236))
    {
        //already turned on this direction, then try move into this direction
        if(direction==CatchChallenger::Direction_look_at_right)
        {
            if(!CatchChallenger::MoveOnTheMap::canGoTo(CatchChallenger::Direction_move_at_right,&logicalMap,xPerso,yPerso,true))
                return;//Can't do at the right!
            //the first step
            direction=CatchChallenger::Direction_move_at_right;
            inMove=true;
             moveStep=1;
             moveStepSlot();
         }
         //look in this direction
        else
        {
            playerMapObject->setTile(playerTileset->tileAt(4));
            direction=CatchChallenger::Direction_look_at_right;
            lookToMove.start();
        }
    }
    else if(keyPressed.contains(16777235))
    {
        //already turned on this direction, then try move into this direction
        if(direction==CatchChallenger::Direction_look_at_top)
        {
            if(!CatchChallenger::MoveOnTheMap::canGoTo(CatchChallenger::Direction_move_at_top,&logicalMap,xPerso,yPerso,true))
                return;//Can't do at the top!
            //the first step
            direction=CatchChallenger::Direction_move_at_top;
            inMove=true;
             moveStep=1;
             moveStepSlot();
         }
         //look in this direction
        else
        {
            playerMapObject->setTile(playerTileset->tileAt(1));
            direction=CatchChallenger::Direction_look_at_top;
            lookToMove.start();
        }
    }
    else if(keyPressed.contains(16777237))
    {
        //already turned on this direction, then try move into this direction
        if(direction==CatchChallenger::Direction_look_at_bottom)
        {
            if(!CatchChallenger::MoveOnTheMap::canGoTo(CatchChallenger::Direction_move_at_bottom,&logicalMap,xPerso,yPerso,true))
                return;//Can't do at the bottom!
            //the first step
            direction=CatchChallenger::Direction_move_at_bottom;
            inMove=true;
             moveStep=1;
             moveStepSlot();
         }
         //look in this direction
        else
        {
            playerMapObject->setTile(playerTileset->tileAt(7));
            direction=CatchChallenger::Direction_look_at_bottom;
            lookToMove.start();
        }
    }

    //do it here only because it's one player, then max 3 call by second
    viewport()->update();
}

void MapVisualiserQt::moveStepSlot(bool justUpdateTheTile)
{
    int baseTile=1;
     //move the player for intermediate step and define the base tile (define the stopped step with direction)
    switch(direction)
    {
        case CatchChallenger::Direction_move_at_left:
        baseTile=10;
         switch(moveStep)
        {
            case 1:
             case 2:
             playerMapObject->setX(playerMapObject->x()-0.33);
            break;
         }
         break;
         case CatchChallenger::Direction_move_at_right:
        baseTile=4;
         switch(moveStep)
        {
            case 1:
             case 2:
             playerMapObject->setX(playerMapObject->x() 0.33);
            break;
         }
         break;
         case CatchChallenger::Direction_move_at_top:
        baseTile=1;
         switch(moveStep)
        {
            case 1:
             case 2:
             playerMapObject->setY(playerMapObject->y()-0.33);
            break;
         }
         break;
         case CatchChallenger::Direction_move_at_bottom:
        baseTile=7;
         switch(moveStep)
        {
            case 1:
             case 2:
             playerMapObject->setY(playerMapObject->y() 0.33);
            break;
         }
         break;
         default:
         qDebug() << QString("moveStepSlot(): moveStep: %1, justUpdateTheTile: %2, wrong direction").arg(moveStep).arg(justUpdateTheTile);
        return;
     }
 
     //apply the right step of the base step defined previously by the direction
    switch(moveStep)
    {
        //stopped step
        case 0:
         playerMapObject->setTile(playerTileset->tileAt(baseTile 0));
        break;
         //transition step
        case 1:
         playerMapObject->setTile(playerTileset->tileAt(baseTile-1));
        break;
         case 2:
         playerMapObject->setTile(playerTileset->tileAt(baseTile 1));
        break;
         //stopped step
        case 3:
         playerMapObject->setTile(playerTileset->tileAt(baseTile 0));
        break;
     }
 
     moveStep  ;
 
     //if have finish the step
    if(moveStep>3)
    {
        //set the final value (direction, position, ...)
        switch(direction)
        {
            case CatchChallenger::Direction_move_at_left:
            direction=CatchChallenger::Direction_look_at_left;
            xPerso-=1;
             break;
             case CatchChallenger::Direction_move_at_right:
            direction=CatchChallenger::Direction_look_at_right;
            xPerso =1;
             break;
             case CatchChallenger::Direction_move_at_top:
            direction=CatchChallenger::Direction_look_at_top;
            yPerso-=1;
             break;
             case CatchChallenger::Direction_move_at_bottom:
            direction=CatchChallenger::Direction_look_at_bottom;
            yPerso =1;
             break;
             default:
             qDebug() << QString("moveStepSlot(): moveStep: %1, justUpdateTheTile: %2, wrong direction when moveStep>2").arg(moveStep).arg(justUpdateTheTile);
            return;
         }
         //move to the final position (integer), y 1 because the tile lib start y to 1, not 0
        playerMapObject->setPosition(QPoint(xPerso,yPerso 1));

	//check if one arrow key is pressed to continue to move into this direction
        if(keyPressed.contains(16777234))
        {
            //if can go, then do the move
            if(!CatchChallenger::MoveOnTheMap::canGoTo(CatchChallenger::Direction_move_at_left,&logicalMap,xPerso,yPerso,true))
            {
                direction=CatchChallenger::Direction_look_at_left;
                playerMapObject->setTile(playerTileset->tileAt(10));
                inMove=false;
             }
             //can go into this direction, then just look into this direction
            else
            {
                direction=CatchChallenger::Direction_move_at_left;
                moveStep=0;
                 moveStepSlot(true);
            }
        }
        else if(keyPressed.contains(16777236))
        {
            //if can go, then do the move
            if(!CatchChallenger::MoveOnTheMap::canGoTo(CatchChallenger::Direction_move_at_right,&logicalMap,xPerso,yPerso,true))
            {
                direction=CatchChallenger::Direction_look_at_right;
                playerMapObject->setTile(playerTileset->tileAt(4));
                inMove=false;
             }
             //can go into this direction, then just look into this direction
            else
            {
                direction=CatchChallenger::Direction_move_at_right;
                moveStep=0;
                 moveStepSlot(true);
            }
        }
        else if(keyPressed.contains(16777235))
        {
            //if can go, then do the move
            if(!CatchChallenger::MoveOnTheMap::canGoTo(CatchChallenger::Direction_move_at_top,&logicalMap,xPerso,yPerso,true))
            {
                direction=CatchChallenger::Direction_look_at_top;
                playerMapObject->setTile(playerTileset->tileAt(1));
                inMove=false;
             }
             //can go into this direction, then just look into this direction
            else
            {
                direction=CatchChallenger::Direction_move_at_top;
                moveStep=0;
                 moveStepSlot(true);
            }
        }
        else if(keyPressed.contains(16777237))
        {
            //if can go, then do the move
            if(!CatchChallenger::MoveOnTheMap::canGoTo(CatchChallenger::Direction_move_at_bottom,&logicalMap,xPerso,yPerso,true))
            {
                direction=CatchChallenger::Direction_look_at_bottom;
                playerMapObject->setTile(playerTileset->tileAt(7));
                inMove=false;
             }
             //can go into this direction, then just look into this direction
            else
            {
                direction=CatchChallenger::Direction_move_at_bottom;
                moveStep=0;
                 moveStepSlot(true);
            }
        }
        //now stop walking, no more arrow key is pressed
        else
        {
            playerMapObject->setPosition(QPoint(xPerso,yPerso 1));
            inMove=false;
         }
     }
     else
        moveTimer.start();

    //do it here only because it's one player, then max 3 call by second
    if(!justUpdateTheTile)
        viewport()->update();
}

//have look into another direction, if the key remain pressed, apply like move
void MapVisualiserQt::transformLookToMove()
{
    if(inMove)
        return;
 
     switch(direction)
    {
        case CatchChallenger::Direction_look_at_left:
        if(keyPressed.contains(16777234) && CatchChallenger::MoveOnTheMap::canGoTo(CatchChallenger::Direction_move_at_left,&logicalMap,xPerso,yPerso,true))
        {
            direction=CatchChallenger::Direction_move_at_left;
            inMove=true;
             moveStep=1;
             moveStepSlot();
         }
         break;
         case CatchChallenger::Direction_look_at_right:
        if(keyPressed.contains(16777236) && CatchChallenger::MoveOnTheMap::canGoTo(CatchChallenger::Direction_move_at_right,&logicalMap,xPerso,yPerso,true))
        {
            direction=CatchChallenger::Direction_move_at_right;
            inMove=true;
             moveStep=1;
             moveStepSlot();
         }
         break;
         case CatchChallenger::Direction_look_at_top:
        if(keyPressed.contains(16777235) && CatchChallenger::MoveOnTheMap::canGoTo(CatchChallenger::Direction_move_at_top,&logicalMap,xPerso,yPerso,true))
        {
            direction=CatchChallenger::Direction_move_at_top;
            inMove=true;
             moveStep=1;
             moveStepSlot();
         }
         break;
         case CatchChallenger::Direction_look_at_bottom:
        if(keyPressed.contains(16777237) && CatchChallenger::MoveOnTheMap::canGoTo(CatchChallenger::Direction_move_at_bottom,&logicalMap,xPerso,yPerso,true))
        {
            direction=CatchChallenger::Direction_move_at_bottom;
            inMove=true;
             moveStep=1;
             moveStepSlot();
         }
         break;
         default:
         qDebug() << QString("transformLookToMove(): wrong direction");
        return;
     }
 }
 
 void MapVisualiserQt::keyReleaseEvent(QKeyEvent * event)
{
    //ignore the repeated event
    if(event->isAutoRepeat())
        return;
 
     //remove from the key list pressed
    keyPressed.remove(event->key());

    if(keyPressed.size()>0)//another key pressed, repeat
        keyPressParse();
}