
// KeyBehavior.java
// Andrew Davison, April 2005, ad@fivedots.coe.psu.ac.th

/* Pomocí stisků kláves pohybuje výhledem a střílí ze zbraně.
   Pohyb je omezen na: dopředu, dozadu, přesun vlevo,
   přesun vravo, rotace vlevo, rotace vpravo, nahoru a dolů.

   Chování se připojuje k výhledu uživatele.
   Rozšiřuje třídu ViewPlatformBehavior, takže má k dispozici uzel
   targetTG, což je instance transformačního uzlu typu ViewPlatform.
*/

import java.awt.AWTEvent;
import java.awt.event.*;
import java.util.Enumeration;

import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.behaviors.vp.*;



public class KeyBehavior extends ViewPlatformBehavior
{
  private static final double ROT_AMT = Math.PI / 36.0;   // 5 stupňů
  private static final double MOVE_STEP = 0.2;

  // pevně dané pohybové vektory
  private static final Vector3d FWD = new Vector3d(0,0,-MOVE_STEP);
  private static final Vector3d BACK = new Vector3d(0,0,MOVE_STEP);
  private static final Vector3d LEFT = new Vector3d(-MOVE_STEP,0,0);
  private static final Vector3d RIGHT = new Vector3d(MOVE_STEP,0,0);
  private static final Vector3d UP = new Vector3d(0,MOVE_STEP,0);
  private static final Vector3d DOWN = new Vector3d(0,-MOVE_STEP,0);

  // názvy kláves
  private int forwardKey = KeyEvent.VK_UP;
  private int backKey = KeyEvent.VK_DOWN;
  private int leftKey = KeyEvent.VK_LEFT;
  private int rightKey = KeyEvent.VK_RIGHT;
  private int fireKey = KeyEvent.VK_F;   // tláčítko pro střelbu

  private WakeupCondition keyPress;
  private AmmoManager ammoMan;

  // pro opakované výpočty
  private Transform3D t3d = new Transform3D();
  private Transform3D toMove = new Transform3D();
  private Transform3D toRot = new Transform3D();


  public KeyBehavior(AmmoManager am)
  { ammoMan = am;
    keyPress = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED);
  } // konec metody: KeyBehavior()


  public void initialize()
  {  wakeupOn( keyPress );  }


  public void processStimulus(Enumeration criteria)
  // reaguje na stisky kláves
  {
    WakeupCriterion wakeup;
    AWTEvent[] event;

    while( criteria.hasMoreElements() ) {
      wakeup = (WakeupCriterion) criteria.nextElement();
      if( wakeup instanceof WakeupOnAWTEvent ) {
        event = ((WakeupOnAWTEvent)wakeup).getAWTEvent();
        for( int i = 0; i < event.length; i++ ) {
          if( event[i].getID() == KeyEvent.KEY_PRESSED )
            processKeyEvent((KeyEvent)event[i]);
        }
      }
    }
    wakeupOn( keyPress );
  } // konec metody: processStimulus()


  private void processKeyEvent(KeyEvent eventKey)
  {
    int keyCode = eventKey.getKeyCode();
    // System.out.println(keyCode);    

    if(eventKey.isAltDown())   // klávesa + <alt>
      altMove(keyCode);
    else
      standardMove(keyCode);
  } // konec metody: processKeyEvent()


  private void standardMove(int keycode)
  /* Způsobí pohyb pozorovatele dopředu nebo dozadu,
     otočení vlevo či vpravo a vystřelení ze zbraně. */
  { if(keycode == forwardKey)
      doMove(FWD);
    else if(keycode == backKey)
      doMove(BACK);
    else if(keycode == leftKey)
      rotateY(ROT_AMT);
    else if(keycode == rightKey)
      rotateY(-ROT_AMT);
    else if (keycode == fireKey)
      ammoMan.fireBeam();
  } // konec metody: standardMove()


  private void altMove(int keycode)
  // pohyb pozorovatele nahoru nebo dolů, doprava či doleva
  { if(keycode == forwardKey)
      doMove(UP);
    else if(keycode == backKey)
      doMove(DOWN);
    else if(keycode == leftKey)
      doMove(LEFT);
    else if(keycode == rightKey)
      doMove(RIGHT);
  }  // konec metody: altMove()


  private void rotateY(double radians)
  // otoření o radians radiánů kolem osy y
  { targetTG.getTransform(t3d);   // targetTG je transformační uzel typu ViewPlatform
    toRot.rotY(radians);
    t3d.mul(toRot);
    targetTG.setTransform(t3d);
  } // konec metody: rotateY()


  private void doMove(Vector3d theMove)
  { targetTG.getTransform(t3d);
    toMove.setTranslation(theMove);
    t3d.mul(toMove);
    targetTG.setTransform(t3d);
  } // konec metody: doMove()


}  // konec třídy: KeyBehavior
