home *** CD-ROM | disk | FTP | other *** search
/ Learn 3D Graphics Programming on the PC / Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso / rwwin / knight.c_ / knight.bin
Text File  |  1995-11-14  |  13KB  |  466 lines

  1. /**********************************************************************
  2.  *
  3.  * File :     knight.c
  4.  *
  5.  * Abstract : Handle knight behaviour and animation control
  6.  *
  7.  **********************************************************************
  8.  *
  9.  * This file is a product of Criterion Software Ltd.
  10.  *
  11.  * This file is provided as is with no warranties of any kind and is
  12.  * provided without any obligation on Criterion Software Ltd. or
  13.  * Canon Inc. to assist in its use or modification.
  14.  *
  15.  * Criterion Software Ltd. will not, under any
  16.  * circumstances, be liable for any lost revenue or other damages arising
  17.  * from the use of this file.
  18.  *
  19.  * Copyright (c) 1995 Criterion Software Ltd.
  20.  * All Rights Reserved.
  21.  *
  22.  * RenderWare is a trademark of Canon Inc.
  23.  *
  24.  ************************************************************************/
  25. #define INCLUDE_SHELLAPI_H
  26.  
  27. #include <windows.h>
  28. #include <mmsystem.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #include <math.h>
  33.  
  34. #include "rwlib.h"
  35. #include "rwwin.h"
  36.  
  37. #include "common.h"
  38.  
  39. #include "animate.h"
  40. #include "knight.h"
  41. #include "knight.rwh"
  42.  
  43. #define CAM_FLY_STEPS 30
  44. int CamFlyStepDelta;
  45. int CamFlyStep;
  46.  
  47. void SetBackdrop(RwCamera *cam)
  48. {
  49.     RwRaster *r;
  50.     RwV3d v;
  51.     RwV3d xz;        
  52.     RwInt32 ox, oy;
  53.     RwInt32 vp_h;
  54.     double theta;
  55.  
  56.    r = RwGetCameraBackdrop(cam);
  57.    if (r)
  58.   {
  59.       RwGetCameraViewport(cam, 
  60.                           (RwInt32 *)NULL, (RwInt32 *)NULL, (RwInt32 *)NULL, &vp_h);
  61.       RwGetCameraLookAt(cam, &v);
  62.  
  63.       xz.x = v.x;
  64.       xz.z = v.z;
  65.       xz.y = CREAL(0.0);
  66.       RwNormalize(&xz);
  67.       if (xz.x > CREAL(1.0))
  68.         xz.x = CREAL(1.0);
  69.       if (xz.x < CREAL(-1.0))
  70.         xz.x = CREAL(-1.0);
  71.               
  72.       theta = acos(REAL2FL(xz.x));
  73.       ox = (int)((double)RwGetRasterWidth(r) * theta/6.2832);
  74.       if (xz.z < 0.0)
  75.         ox = -ox;
  76.  
  77.       oy = -vp_h/2 + (int)((double)RwGetRasterHeight(r)/2.0 * (1.0 - REAL2FL(v.y)));
  78.       if (oy > RwGetRasterHeight(r) - vp_h)
  79.         oy = RwGetRasterHeight(r) - vp_h;
  80.       if (oy < 0)
  81.         oy = 0;
  82.       RwSetCameraBackdropOffset(cam, ox + RwGetRasterWidth(r)/2, oy);
  83.   }              
  84. }
  85.  
  86. void SetCameraState(HWND window, EnCameraState state)
  87. {
  88.     if (state == CAM_MAIN)
  89.     {
  90.         Camera = MainCamera;
  91.         SetBackdrop(MainCamera);
  92.     }
  93.     else if (((state == CAM_FLY1) || (state == CAM_FLY2)) &&
  94.              ((CameraState == CAM_MAIN) || (CameraState == CAM_KNIGHT1) || (CameraState == CAM_KNIGHT2)))
  95.     {
  96.        if (CameraState == CAM_MAIN)
  97.        {
  98.            Camera = FlyCamera;
  99.            CamFlyStepDelta = 1;
  100.            CamFlyStep = 1;
  101.        }
  102.        else
  103.        {
  104.            CamFlyStepDelta = -1;
  105.            CamFlyStep = CAM_FLY_STEPS -1;
  106.        }
  107.    }
  108.    if (CameraState != state)
  109.    {
  110.        if ((state == CAM_KNIGHT1) || (state == CAM_KNIGHT2))
  111.             RwRemoveClumpFromScene((state == CAM_KNIGHT1) ? Knight1 : Knight2);
  112.        if ((CameraState == CAM_KNIGHT1) || (CameraState == CAM_KNIGHT2))
  113.             RwAddClumpToScene(Scene, (CameraState == CAM_KNIGHT1) ? Knight1 : Knight2);
  114.    }
  115.    CameraState = state;
  116.  
  117.    CheckMenuItem(GetMenu(window), ID_MODE_KNIGHT1, (MF_BYCOMMAND|MF_UNCHECKED));
  118.    CheckMenuItem(GetMenu(window), ID_MODE_KNIGHT2, (MF_BYCOMMAND|MF_UNCHECKED));
  119.    CheckMenuItem(GetMenu(window), ID_MODE_OBSERVER, (MF_BYCOMMAND|MF_UNCHECKED));
  120.    switch (CameraState)
  121.    {
  122.         case CAM_MAIN: 
  123.            CheckMenuItem(GetMenu(window), ID_MODE_OBSERVER, (MF_BYCOMMAND|MF_CHECKED));
  124.            break;
  125.         case CAM_KNIGHT1: 
  126.            CheckMenuItem(GetMenu(window), ID_MODE_KNIGHT1, (MF_BYCOMMAND|MF_CHECKED));
  127.            break;
  128.         case CAM_KNIGHT2: 
  129.            CheckMenuItem(GetMenu(window), ID_MODE_KNIGHT2, (MF_BYCOMMAND|MF_CHECKED));
  130.            break;
  131.    }
  132. }
  133.  
  134. void DoFlyCamera(HWND window)
  135. {
  136.    RwClump *clump;
  137.    RwV3d dest_at, dest_up, dest_pos;
  138.    RwV3d src_at, src_up, src_pos;
  139.    RwReal delta;
  140.  
  141.    clump = RwFindTaggedClump((CameraState == CAM_FLY1) ? Knight1 : Knight2, TAG_head);
  142.    RwGetClumpLTM(clump, RwScratchMatrix());
  143.  
  144.    delta = FL2REAL((float)CamFlyStep/(float)(CAM_FLY_STEPS));
  145.  
  146.    RwGetCameraPosition(MainCamera, &src_pos);
  147.    RwGetCameraLookAt(MainCamera, &src_at);
  148.    RwGetCameraLookUp(MainCamera, &src_up);   
  149.                
  150.    dest_pos.x = CREAL(0.0);dest_pos.y = CREAL(0.0); dest_pos.z = CREAL(0.0);
  151.    dest_up.x = CREAL(0.0); dest_up.y = CREAL(0.0); dest_up.z = CREAL(1.0);
  152.    dest_at.x = CREAL(0.0); dest_at.y = CREAL(-1.0); dest_at.z = CREAL(0.0);       
  153.    RwTransformPoint(&dest_pos, RwScratchMatrix());
  154.    RwTransformVector(&dest_up, RwScratchMatrix());
  155.    RwTransformVector(&dest_at, RwScratchMatrix());
  156.  
  157.    dest_pos.x = RAdd(dest_pos.x,
  158.                      RMul((CameraState == CAM_FLY1) ? CREAL(-4.0): CREAL(4.0),
  159.                           RSub(CREAL(1.0), delta)));
  160.  
  161.    RwSetCameraPosition(FlyCamera,
  162.                            RAdd(src_pos.x, RMul(delta, RSub(dest_pos.x,src_pos.x))),
  163.                            RAdd(src_pos.y, RMul(delta, RSub(dest_pos.y,src_pos.y))),
  164.                            RAdd(src_pos.z, RMul(delta, RSub(dest_pos.z,src_pos.z))));
  165.  
  166.    RwPointCamera(FlyCamera, CREAL(0.0), CREAL(0.0), CREAL(0.0));
  167.    RwSetCameraLookUp(FlyCamera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
  168.    CamFlyStep += CamFlyStepDelta;
  169.  
  170.    if ((CamFlyStepDelta > 0) && (CamFlyStep == CAM_FLY_STEPS))
  171.    {
  172.        SetCameraState(window, (CameraState == CAM_FLY1) ? CAM_KNIGHT1 : CAM_KNIGHT2);
  173.    }
  174.    else if (CamFlyStep == 0)
  175.    {
  176.        SetCameraState(window, CAM_MAIN);
  177.    }
  178.    SetBackdrop(FlyCamera);
  179. }
  180.  
  181. void KnightCamera(void)
  182. {
  183.    RwClump *clump;
  184.  
  185.    if ((CameraState == CAM_KNIGHT1) || (CameraState == CAM_KNIGHT2))
  186.    {
  187.        clump = RwFindTaggedClump((CameraState == CAM_KNIGHT1) ? Knight1 : Knight2, TAG_head);
  188.        RwGetClumpLTM(clump, RwScratchMatrix());
  189.        RwTransformCamera(FlyCamera, RwScratchMatrix(), rwREPLACE);
  190.        RwTiltCamera(FlyCamera, CREAL(90.0));
  191.    }
  192.    SetBackdrop(FlyCamera);
  193. }
  194.  
  195. void AnimateCamera(HWND window)
  196. {
  197.     static int Frame = 0;
  198.     static long Duration = 200;
  199.  
  200.     Frame++;
  201.     if (!InterActive)
  202.     {
  203.         RwSetCameraPosition(MainCamera, CREAL(0.0), CREAL(0.0), CREAL(0.0));
  204. #if 0
  205.         RwVCMoveCamera(MainCamera, CREAL(0.0), CREAL(0.0), -CAMERA_DISTANCE);
  206. #endif
  207.         RwPanCamera(MainCamera, CREAL(2.0));
  208.         RwVCMoveCamera(MainCamera, CREAL(0.0), CREAL(0.0), CAMERA_DISTANCE);
  209.         if (CameraState == CAM_MAIN)
  210.             SetBackdrop(MainCamera);
  211.  
  212.         if (!(Frame % Duration))
  213.         {
  214.             switch(CameraState)
  215.             {
  216.                 case CAM_MAIN:
  217.                   SetCameraState(window, (Duration & 0x01) ? CAM_FLY1: CAM_FLY2);
  218.                   break;
  219.                 case CAM_KNIGHT1:
  220.                 case CAM_KNIGHT2:
  221.                   SetCameraState(window, (CameraState == CAM_KNIGHT1) ? CAM_FLY1 : CAM_FLY2);
  222.                   break;
  223.                     
  224.             }
  225.             Duration = RANDOM_INT(100, 500);
  226.         }
  227.     }
  228.        
  229.     switch (CameraState)
  230.     {
  231.         case CAM_MAIN:
  232.            break;
  233.         case CAM_KNIGHT1: 
  234.         case CAM_KNIGHT2:
  235.            KnightCamera();
  236.            break;
  237.            
  238.         case CAM_FLY1:
  239.         case CAM_FLY2:
  240.            DoFlyCamera(window);
  241.            break;
  242.     }
  243. }
  244.  
  245. void RenderKnight(void)
  246. {
  247.   RwClump *clump;
  248.  
  249.   /* this is a cheat to force quick rendering when viewing from a knights eye point */
  250.   if ((CameraState == CAM_KNIGHT1) || (CameraState == CAM_KNIGHT2))
  251.   {
  252.       RwRemoveLightFromScene(Light); /* put in the default scene */
  253.  
  254.       clump = (CameraState == CAM_KNIGHT1) ? Knight1 : Knight2;
  255.  
  256.       RwRenderClump(RwFindTaggedClump(clump, TAG_Object));  
  257.       RwRenderClump(RwFindTaggedClump(clump, TAG_SHIELD));  
  258.       RwRenderClump(RwFindTaggedClump(clump, TAG_lefthand));  
  259.       RwRenderClump(RwFindTaggedClump(clump, TAG_left4arm));  
  260.  
  261.       RwAddLightToScene(Scene, Light); /* put it back in the scene */
  262.   }
  263. }
  264.  
  265. RwClump *RemoveTexture(RwClump *c)
  266. {
  267.    RwForAllPolygonsInClumpPointer(c, (RwPolygon3dFuncPointer)RwSetPolygonTexture, NULL);
  268.    return(c);
  269.  
  270.  
  271. int LoadKnight(HWND window, HINSTANCE inst, RwScene *scene)
  272. {
  273.    char buffer[64];
  274.    int i;        
  275.     
  276.    GetModuleFileName(inst, buffer, sizeof(buffer));
  277.    i = strlen(buffer);
  278.    while(buffer[i] != '\\')
  279.    i--;
  280.  
  281.    Knight1 = LoadClump(window, "knight.rwx");
  282.    if (!Knight1)
  283.        return FALSE;        
  284.    RwAddClumpToScene(scene, Knight1);
  285.    RwRotateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(1.0), CREAL(0.0), CREAL(90.0), rwREPLACE);
  286.    RwTransformClumpJoint(Knight1, RwScratchMatrix(), rwREPLACE);
  287.    RwTranslateMatrix(RwScratchMatrix(), CREAL(-1.3), CREAL(0.4), CREAL(0.0), rwREPLACE);
  288.    RwTransformClump(Knight1, RwScratchMatrix(), rwREPLACE);
  289.  
  290.    Knight2 = RwDuplicateClump(Knight1);
  291.    if (!Knight2)
  292.        return FALSE;
  293.  
  294.    RwForAllClumpsInHierarchy(Knight2, RemoveTexture);
  295.            
  296.    RwAddClumpToScene(scene, Knight2);
  297.    RwRotateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(1.0), CREAL(0.0), CREAL(-90.0), rwREPLACE);
  298.    RwTransformClumpJoint(Knight2, RwScratchMatrix(), rwREPLACE);
  299.    RwTranslateMatrix(RwScratchMatrix(), CREAL(1.3), CREAL(0.4), CREAL(0.0), rwREPLACE);
  300.    RwTransformClump(Knight2, RwScratchMatrix(), rwREPLACE);
  301.  
  302.    buffer[i+1] = 0;
  303.    strcat(buffer, "KNIGHT.RWV");
  304.  
  305.     RwForAllClumpsInHierarchyLong(Knight1, (RwClumpFuncLong)RwSetClumpHints, 0L);
  306.     RwForAllClumpsInHierarchyLong(Knight2, (RwClumpFuncLong)RwSetClumpHints, 0L);
  307.  
  308.    LoadAnimation(Knight1, buffer);
  309.    LoadAnimation(Knight2, buffer);
  310.    
  311.    DefineAnimation(Knight1, "BOB1", 0, 10, 5);
  312.    DefineAnimation(Knight1, "SLASH", 10, 35, 12);
  313.    DefineAnimation(Knight1, "BOB2", 35, 45, 40);
  314.    DefineAnimation(Knight1, "PARRY", 45, 60, 48);
  315.    DefineAnimation(Knight1, "BOB3", 60, 70, 65);
  316.    DefineAnimation(Knight1, "HIT", 70, 85, 85);
  317.  
  318.    DefineAnimation(Knight2, "BOB1", 0, 10, 5);
  319.    DefineAnimation(Knight2, "SLASH", 10, 35, 12);
  320.    DefineAnimation(Knight2, "BOB2", 35, 45, 40);
  321.    DefineAnimation(Knight2, "PARRY", 45, 60, 50);
  322.    DefineAnimation(Knight2, "BOB3", 60, 70, 65);
  323.    DefineAnimation(Knight2, "HIT", 70, 85, 85);
  324.  
  325.    return TRUE;
  326. }
  327.  
  328. char *RandomKnight(RwClump *clump)
  329. {
  330.      long i;
  331.  
  332.      /* if the other knight isn`t doing anything then don`t attack */        
  333.      if (((clump == Knight1) && (GetAnimationState(Knight2) != A_ON)) ||
  334.          ((clump == Knight2) && (GetAnimationState(Knight1) != A_ON)))
  335.          return "BOB1";        
  336.      
  337.      i = RANDOM_INT(0, 1);
  338.      switch(i)
  339.      {
  340.           case 0:
  341.              return "SLASH";
  342.           default:
  343.              return "BOB1";
  344.      } 
  345. }
  346.  
  347. int CheckKnightAnimation(RwClump *clump)
  348. {
  349.     TyAnimationData *ad;
  350.  
  351.     ad = RwGetClumpData(clump);
  352.     if (ad)
  353.     {
  354.         if (ad->current_animation)
  355.         {
  356.             return (ad->current_animation->end - ad->current_frame);
  357.         }
  358.     }
  359.     return (0);
  360. }
  361.  
  362. #ifdef WITH_SOUND
  363. static char *Sound = NULL;
  364. static int SoundDelay = 0;
  365.  
  366. void DelaySound(char *wav, int delay)
  367. {  
  368.     char buffer[128];
  369.     if (!Sound)
  370.     {                
  371.         sprintf (buffer, "open %s", wav);
  372.         mciSendString(buffer, NULL, 0, 0);
  373.         Sound = wav;
  374.         SoundDelay = delay;
  375.     }
  376.         
  377. }
  378.  
  379. void PlaySound(void)
  380. {
  381.     char buffer[128];
  382.     if (Sound)
  383.     {
  384.         SoundDelay--;
  385.         if (!SoundDelay)
  386.         {            
  387.             sprintf (buffer, "play %s from 0", Sound);
  388.             mciSendString(buffer, NULL, 0, 0);
  389.             Sound = NULL;
  390.         }
  391.     }
  392. }
  393. #endif
  394.  
  395. void ReactKnight(RwClump *clump, TyAnimation *a)
  396. {
  397.    char *response;
  398.    long i;
  399.    
  400.    if (!strcmp(a->name, "HIT"))
  401.    {
  402.        SetAnimationState(clump, A_DISSOLVE);
  403.        return;   
  404.    }
  405.    else if (!strcmp(a->name, "SLASH"))
  406.    {
  407.        i = RANDOM_INT(0, 10);
  408.        if (i == 7) 
  409.        {
  410.            response = "HIT";
  411. #ifdef WITH_SOUND
  412.             DelaySound("scream.wav", 12);
  413. #endif
  414.         }
  415.        else
  416.        {
  417.           response = "PARRY";
  418. #ifdef WITH_SOUND
  419.           DelaySound("thunk.wav", 12);
  420. #endif
  421.        }
  422.    }
  423.    else
  424.    {
  425.       i = RANDOM_INT(0, 5);
  426.       switch (i)
  427.       {
  428.           case 0:
  429.           case 1:
  430.               response = "SLASH";
  431.               break;
  432.           case 2:
  433.               response = "BOB1";
  434.               break;
  435.           case 3:
  436.               response = "BOB2";
  437.               break;
  438.           default:
  439.               response = "BOB3";
  440.               break;
  441.       }
  442.    }
  443.    if (clump == Knight1)
  444.    {
  445.        if (CheckKnightAnimation(Knight2) < 15)
  446.            StartAnimation(Knight2, response);
  447.    }
  448.    else
  449.    {
  450.        if (CheckKnightAnimation(Knight1) < 15)
  451.            StartAnimation(Knight1, response);
  452.    }
  453. }
  454.  
  455. void AnimateKnight(int knight, char *name)
  456. {
  457.    SetAnimationState(Knight1, A_ON);
  458.    SetAnimationState(Knight2, A_ON);
  459.    switch (knight)
  460.    {
  461.        case 1: StartAnimation(Knight1, name); break;
  462.        case 2: StartAnimation(Knight2, name); break;
  463.    }
  464. }
  465.