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
Wrap
Text File
|
1995-11-14
|
13KB
|
466 lines
/**********************************************************************
*
* File : knight.c
*
* Abstract : Handle knight behaviour and animation control
*
**********************************************************************
*
* This file is a product of Criterion Software Ltd.
*
* This file is provided as is with no warranties of any kind and is
* provided without any obligation on Criterion Software Ltd. or
* Canon Inc. to assist in its use or modification.
*
* Criterion Software Ltd. will not, under any
* circumstances, be liable for any lost revenue or other damages arising
* from the use of this file.
*
* Copyright (c) 1995 Criterion Software Ltd.
* All Rights Reserved.
*
* RenderWare is a trademark of Canon Inc.
*
************************************************************************/
#define INCLUDE_SHELLAPI_H
#include <windows.h>
#include <mmsystem.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "rwlib.h"
#include "rwwin.h"
#include "common.h"
#include "animate.h"
#include "knight.h"
#include "knight.rwh"
#define CAM_FLY_STEPS 30
int CamFlyStepDelta;
int CamFlyStep;
void SetBackdrop(RwCamera *cam)
{
RwRaster *r;
RwV3d v;
RwV3d xz;
RwInt32 ox, oy;
RwInt32 vp_h;
double theta;
r = RwGetCameraBackdrop(cam);
if (r)
{
RwGetCameraViewport(cam,
(RwInt32 *)NULL, (RwInt32 *)NULL, (RwInt32 *)NULL, &vp_h);
RwGetCameraLookAt(cam, &v);
xz.x = v.x;
xz.z = v.z;
xz.y = CREAL(0.0);
RwNormalize(&xz);
if (xz.x > CREAL(1.0))
xz.x = CREAL(1.0);
if (xz.x < CREAL(-1.0))
xz.x = CREAL(-1.0);
theta = acos(REAL2FL(xz.x));
ox = (int)((double)RwGetRasterWidth(r) * theta/6.2832);
if (xz.z < 0.0)
ox = -ox;
oy = -vp_h/2 + (int)((double)RwGetRasterHeight(r)/2.0 * (1.0 - REAL2FL(v.y)));
if (oy > RwGetRasterHeight(r) - vp_h)
oy = RwGetRasterHeight(r) - vp_h;
if (oy < 0)
oy = 0;
RwSetCameraBackdropOffset(cam, ox + RwGetRasterWidth(r)/2, oy);
}
}
void SetCameraState(HWND window, EnCameraState state)
{
if (state == CAM_MAIN)
{
Camera = MainCamera;
SetBackdrop(MainCamera);
}
else if (((state == CAM_FLY1) || (state == CAM_FLY2)) &&
((CameraState == CAM_MAIN) || (CameraState == CAM_KNIGHT1) || (CameraState == CAM_KNIGHT2)))
{
if (CameraState == CAM_MAIN)
{
Camera = FlyCamera;
CamFlyStepDelta = 1;
CamFlyStep = 1;
}
else
{
CamFlyStepDelta = -1;
CamFlyStep = CAM_FLY_STEPS -1;
}
}
if (CameraState != state)
{
if ((state == CAM_KNIGHT1) || (state == CAM_KNIGHT2))
RwRemoveClumpFromScene((state == CAM_KNIGHT1) ? Knight1 : Knight2);
if ((CameraState == CAM_KNIGHT1) || (CameraState == CAM_KNIGHT2))
RwAddClumpToScene(Scene, (CameraState == CAM_KNIGHT1) ? Knight1 : Knight2);
}
CameraState = state;
CheckMenuItem(GetMenu(window), ID_MODE_KNIGHT1, (MF_BYCOMMAND|MF_UNCHECKED));
CheckMenuItem(GetMenu(window), ID_MODE_KNIGHT2, (MF_BYCOMMAND|MF_UNCHECKED));
CheckMenuItem(GetMenu(window), ID_MODE_OBSERVER, (MF_BYCOMMAND|MF_UNCHECKED));
switch (CameraState)
{
case CAM_MAIN:
CheckMenuItem(GetMenu(window), ID_MODE_OBSERVER, (MF_BYCOMMAND|MF_CHECKED));
break;
case CAM_KNIGHT1:
CheckMenuItem(GetMenu(window), ID_MODE_KNIGHT1, (MF_BYCOMMAND|MF_CHECKED));
break;
case CAM_KNIGHT2:
CheckMenuItem(GetMenu(window), ID_MODE_KNIGHT2, (MF_BYCOMMAND|MF_CHECKED));
break;
}
}
void DoFlyCamera(HWND window)
{
RwClump *clump;
RwV3d dest_at, dest_up, dest_pos;
RwV3d src_at, src_up, src_pos;
RwReal delta;
clump = RwFindTaggedClump((CameraState == CAM_FLY1) ? Knight1 : Knight2, TAG_head);
RwGetClumpLTM(clump, RwScratchMatrix());
delta = FL2REAL((float)CamFlyStep/(float)(CAM_FLY_STEPS));
RwGetCameraPosition(MainCamera, &src_pos);
RwGetCameraLookAt(MainCamera, &src_at);
RwGetCameraLookUp(MainCamera, &src_up);
dest_pos.x = CREAL(0.0);dest_pos.y = CREAL(0.0); dest_pos.z = CREAL(0.0);
dest_up.x = CREAL(0.0); dest_up.y = CREAL(0.0); dest_up.z = CREAL(1.0);
dest_at.x = CREAL(0.0); dest_at.y = CREAL(-1.0); dest_at.z = CREAL(0.0);
RwTransformPoint(&dest_pos, RwScratchMatrix());
RwTransformVector(&dest_up, RwScratchMatrix());
RwTransformVector(&dest_at, RwScratchMatrix());
dest_pos.x = RAdd(dest_pos.x,
RMul((CameraState == CAM_FLY1) ? CREAL(-4.0): CREAL(4.0),
RSub(CREAL(1.0), delta)));
RwSetCameraPosition(FlyCamera,
RAdd(src_pos.x, RMul(delta, RSub(dest_pos.x,src_pos.x))),
RAdd(src_pos.y, RMul(delta, RSub(dest_pos.y,src_pos.y))),
RAdd(src_pos.z, RMul(delta, RSub(dest_pos.z,src_pos.z))));
RwPointCamera(FlyCamera, CREAL(0.0), CREAL(0.0), CREAL(0.0));
RwSetCameraLookUp(FlyCamera, CREAL(0.0), CREAL(1.0), CREAL(0.0));
CamFlyStep += CamFlyStepDelta;
if ((CamFlyStepDelta > 0) && (CamFlyStep == CAM_FLY_STEPS))
{
SetCameraState(window, (CameraState == CAM_FLY1) ? CAM_KNIGHT1 : CAM_KNIGHT2);
}
else if (CamFlyStep == 0)
{
SetCameraState(window, CAM_MAIN);
}
SetBackdrop(FlyCamera);
}
void KnightCamera(void)
{
RwClump *clump;
if ((CameraState == CAM_KNIGHT1) || (CameraState == CAM_KNIGHT2))
{
clump = RwFindTaggedClump((CameraState == CAM_KNIGHT1) ? Knight1 : Knight2, TAG_head);
RwGetClumpLTM(clump, RwScratchMatrix());
RwTransformCamera(FlyCamera, RwScratchMatrix(), rwREPLACE);
RwTiltCamera(FlyCamera, CREAL(90.0));
}
SetBackdrop(FlyCamera);
}
void AnimateCamera(HWND window)
{
static int Frame = 0;
static long Duration = 200;
Frame++;
if (!InterActive)
{
RwSetCameraPosition(MainCamera, CREAL(0.0), CREAL(0.0), CREAL(0.0));
#if 0
RwVCMoveCamera(MainCamera, CREAL(0.0), CREAL(0.0), -CAMERA_DISTANCE);
#endif
RwPanCamera(MainCamera, CREAL(2.0));
RwVCMoveCamera(MainCamera, CREAL(0.0), CREAL(0.0), CAMERA_DISTANCE);
if (CameraState == CAM_MAIN)
SetBackdrop(MainCamera);
if (!(Frame % Duration))
{
switch(CameraState)
{
case CAM_MAIN:
SetCameraState(window, (Duration & 0x01) ? CAM_FLY1: CAM_FLY2);
break;
case CAM_KNIGHT1:
case CAM_KNIGHT2:
SetCameraState(window, (CameraState == CAM_KNIGHT1) ? CAM_FLY1 : CAM_FLY2);
break;
}
Duration = RANDOM_INT(100, 500);
}
}
switch (CameraState)
{
case CAM_MAIN:
break;
case CAM_KNIGHT1:
case CAM_KNIGHT2:
KnightCamera();
break;
case CAM_FLY1:
case CAM_FLY2:
DoFlyCamera(window);
break;
}
}
void RenderKnight(void)
{
RwClump *clump;
/* this is a cheat to force quick rendering when viewing from a knights eye point */
if ((CameraState == CAM_KNIGHT1) || (CameraState == CAM_KNIGHT2))
{
RwRemoveLightFromScene(Light); /* put in the default scene */
clump = (CameraState == CAM_KNIGHT1) ? Knight1 : Knight2;
RwRenderClump(RwFindTaggedClump(clump, TAG_Object));
RwRenderClump(RwFindTaggedClump(clump, TAG_SHIELD));
RwRenderClump(RwFindTaggedClump(clump, TAG_lefthand));
RwRenderClump(RwFindTaggedClump(clump, TAG_left4arm));
RwAddLightToScene(Scene, Light); /* put it back in the scene */
}
}
RwClump *RemoveTexture(RwClump *c)
{
RwForAllPolygonsInClumpPointer(c, (RwPolygon3dFuncPointer)RwSetPolygonTexture, NULL);
return(c);
}
int LoadKnight(HWND window, HINSTANCE inst, RwScene *scene)
{
char buffer[64];
int i;
GetModuleFileName(inst, buffer, sizeof(buffer));
i = strlen(buffer);
while(buffer[i] != '\\')
i--;
Knight1 = LoadClump(window, "knight.rwx");
if (!Knight1)
return FALSE;
RwAddClumpToScene(scene, Knight1);
RwRotateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(1.0), CREAL(0.0), CREAL(90.0), rwREPLACE);
RwTransformClumpJoint(Knight1, RwScratchMatrix(), rwREPLACE);
RwTranslateMatrix(RwScratchMatrix(), CREAL(-1.3), CREAL(0.4), CREAL(0.0), rwREPLACE);
RwTransformClump(Knight1, RwScratchMatrix(), rwREPLACE);
Knight2 = RwDuplicateClump(Knight1);
if (!Knight2)
return FALSE;
RwForAllClumpsInHierarchy(Knight2, RemoveTexture);
RwAddClumpToScene(scene, Knight2);
RwRotateMatrix(RwScratchMatrix(), CREAL(0.0), CREAL(1.0), CREAL(0.0), CREAL(-90.0), rwREPLACE);
RwTransformClumpJoint(Knight2, RwScratchMatrix(), rwREPLACE);
RwTranslateMatrix(RwScratchMatrix(), CREAL(1.3), CREAL(0.4), CREAL(0.0), rwREPLACE);
RwTransformClump(Knight2, RwScratchMatrix(), rwREPLACE);
buffer[i+1] = 0;
strcat(buffer, "KNIGHT.RWV");
RwForAllClumpsInHierarchyLong(Knight1, (RwClumpFuncLong)RwSetClumpHints, 0L);
RwForAllClumpsInHierarchyLong(Knight2, (RwClumpFuncLong)RwSetClumpHints, 0L);
LoadAnimation(Knight1, buffer);
LoadAnimation(Knight2, buffer);
DefineAnimation(Knight1, "BOB1", 0, 10, 5);
DefineAnimation(Knight1, "SLASH", 10, 35, 12);
DefineAnimation(Knight1, "BOB2", 35, 45, 40);
DefineAnimation(Knight1, "PARRY", 45, 60, 48);
DefineAnimation(Knight1, "BOB3", 60, 70, 65);
DefineAnimation(Knight1, "HIT", 70, 85, 85);
DefineAnimation(Knight2, "BOB1", 0, 10, 5);
DefineAnimation(Knight2, "SLASH", 10, 35, 12);
DefineAnimation(Knight2, "BOB2", 35, 45, 40);
DefineAnimation(Knight2, "PARRY", 45, 60, 50);
DefineAnimation(Knight2, "BOB3", 60, 70, 65);
DefineAnimation(Knight2, "HIT", 70, 85, 85);
return TRUE;
}
char *RandomKnight(RwClump *clump)
{
long i;
/* if the other knight isn`t doing anything then don`t attack */
if (((clump == Knight1) && (GetAnimationState(Knight2) != A_ON)) ||
((clump == Knight2) && (GetAnimationState(Knight1) != A_ON)))
return "BOB1";
i = RANDOM_INT(0, 1);
switch(i)
{
case 0:
return "SLASH";
default:
return "BOB1";
}
}
int CheckKnightAnimation(RwClump *clump)
{
TyAnimationData *ad;
ad = RwGetClumpData(clump);
if (ad)
{
if (ad->current_animation)
{
return (ad->current_animation->end - ad->current_frame);
}
}
return (0);
}
#ifdef WITH_SOUND
static char *Sound = NULL;
static int SoundDelay = 0;
void DelaySound(char *wav, int delay)
{
char buffer[128];
if (!Sound)
{
sprintf (buffer, "open %s", wav);
mciSendString(buffer, NULL, 0, 0);
Sound = wav;
SoundDelay = delay;
}
}
void PlaySound(void)
{
char buffer[128];
if (Sound)
{
SoundDelay--;
if (!SoundDelay)
{
sprintf (buffer, "play %s from 0", Sound);
mciSendString(buffer, NULL, 0, 0);
Sound = NULL;
}
}
}
#endif
void ReactKnight(RwClump *clump, TyAnimation *a)
{
char *response;
long i;
if (!strcmp(a->name, "HIT"))
{
SetAnimationState(clump, A_DISSOLVE);
return;
}
else if (!strcmp(a->name, "SLASH"))
{
i = RANDOM_INT(0, 10);
if (i == 7)
{
response = "HIT";
#ifdef WITH_SOUND
DelaySound("scream.wav", 12);
#endif
}
else
{
response = "PARRY";
#ifdef WITH_SOUND
DelaySound("thunk.wav", 12);
#endif
}
}
else
{
i = RANDOM_INT(0, 5);
switch (i)
{
case 0:
case 1:
response = "SLASH";
break;
case 2:
response = "BOB1";
break;
case 3:
response = "BOB2";
break;
default:
response = "BOB3";
break;
}
}
if (clump == Knight1)
{
if (CheckKnightAnimation(Knight2) < 15)
StartAnimation(Knight2, response);
}
else
{
if (CheckKnightAnimation(Knight1) < 15)
StartAnimation(Knight1, response);
}
}
void AnimateKnight(int knight, char *name)
{
SetAnimationState(Knight1, A_ON);
SetAnimationState(Knight2, A_ON);
switch (knight)
{
case 1: StartAnimation(Knight1, name); break;
case 2: StartAnimation(Knight2, name); break;
}
}