squash_0_00.x3d source
<?xml version="1.0" encoding="UTF-8"?>
<X3D>
<Scene>
<WorldInfo title='Squash rackets'/>

<Viewpoint position='0 1.7 10' description='initial'/>
<Viewpoint position='0 7.8 9.7' orientation='-1 0 0 0.68' description='Bird'/>

<NavigationInfo headlight='FALSE'
type='
"EXAMINE"'
/>

<Background
skyAngle='1.57 1.571'
skyColor='
0 0.2 1
0.5 0.8 1
0.6 0.3 0'
/>

<PointLight location='1 2.5 6'/>
<PointLight location='-1 2.5 6'/>

<!-- floor -->
<Transform translation='0 -0.005 0'>
<Shape>
<Appearance>
<Material diffuseColor='1 0.7 0.3'/>
</Appearance>
<Box size='5 0.01 10'/>
</Shape>
</Transform>

<!-- ceiling -->
<Transform translation='0 3.05 0'>
<Shape>
<Appearance>
<Material diffuseColor='1 0.9 0.7' emissiveColor='0.3 0.3 0.27' transparency='0.7'/>
</Appearance>
<Box size='5 0.1 10'/>
</Shape>
</Transform>

<!-- back wall -->
<Transform translation='0 1.5 -5.05'>
<Shape>
<Appearance DEF='Court-Ap'>
<Material diffuseColor='0.2 0.9 0.7'/>
</Appearance>
<Box size='5.2 3.2 0.1'/>
</Shape>
</Transform>

<!-- left wall -->
<Transform translation='-2.55 1.55 0'>
<Shape DEF='SideWall-Sp'>
<Appearance USE='Court-Ap'/>
<Box size='0.1 3.1 10'/>
</Shape>
</Transform>

<!-- right wall -->
<Transform translation='2.55 1.55 0'>
<Shape USE='SideWall-Sp'/>
</Transform>

<!-- ball -->
<Transform DEF='Ball-Tf'>
<Shape>
<Appearance>
<Material diffuseColor='1 0 0'/>
</Appearance>
<Sphere DEF='Ball' radius='0.2'/>
</Shape>
<TouchSensor DEF='Ball-ThS'/>
</Transform>

<!-- ball's shadow -->
<Transform DEF='BallShadow-Tf' scale='1 0.01 1'>
<Shape>
<Appearance>
<Material diffuseColor='0 0 0'/>
</Appearance>
<Sphere USE='Ball'/>
</Shape>
</Transform>

<!-- racket -->
<Transform DEF='Racket-Tf' translation='0 1 5.2'>
<Shape>
<Appearance>
<Material diffuseColor='1 1 0' transparency='0.3'/>
</Appearance>
<Box size='1 1 0.1'/>
</Shape>
<PlaneSensor DEF='Racket-PlS' maxPosition='2 2.5' minPosition='-2 0.5' offset='0 1 5.2'/>
</Transform>

<!-- racket's shadow -->
<Transform DEF='RacketShadow-Tf' translation='0 0 5.2'>
<Shape>
<Appearance>
<Material diffuseColor='0 0 0'/>
</Appearance>
<Box size='1 0.001 0.1'/>
</Shape>
</Transform>

<TimeSensor DEF='TiS' loop='TRUE'/>

<Script DEF='Sc'>
<field accessType='inputOnly' type='SFTime' name='touchTime_Ball'/>
<field accessType='inputOnly' type='SFFloat' name='set_fraction'/>
<field accessType='inputOnly' type='SFVec3f' name='translation_Racket'/>
<field accessType='outputOnly' type='SFVec3f' name='posBall'/>
<field accessType='outputOnly' type='SFVec3f' name='posBallShadow'/>
<field accessType='outputOnly' type='SFVec3f' name='posRacketShadow'/>
<field accessType='initializeOnly' type='SFVec3f' name='moveVec' value='0 0 0'/>
<field accessType='initializeOnly' type='SFFloat' name='oldF' value='0'/>
<field accessType='initializeOnly' type='SFVec3f' name='posRacket' value='0 0 0'/>
<field accessType='initializeOnly' type='SFBool' name='active' value='FALSE'/>
<field accessType='initializeOnly' type='SFFloat' name='speed' value='5'/>
<field accessType='initializeOnly' type='SFBool' name='isCortona' value='FALSE'/>
<![CDATA[ecmascript:

function initialize () {

// ボールとその影の位置をセットする。
posBall.x = 2 * Math.random() - 1;
posBall.y = 2 * Math.random() + 0.5;
posBall.z = 5;

posBallShadow.x = posBall.x;
posBallShadow.y = 0;
posBallShadow.z = posBall.z;

// 実行中のブラウザーが Cortona か調べる。
isCortona = (Browser.getName() == 'Cortona VRML Client');

}

function touchTime_Ball () {

// 既に active が true (ボールが動いている)ならば、この関数を終える。
if (active) return;

// active を true にセットする。(ボールを動かす)
active = true;

// ボールの移動ベクトルをセットする。
moveVec.x = Math.random() * 2 - 1;
moveVec.y = Math.random() * 2 - 1;
moveVec.z = -1;

// ボールのスピードを 5.0 とする。
speed = 5.0;
moveVec = moveVec.normalize().multiply(speed);

}

function set_fraction (f) {

// fraction の変化量を得る。
var df = f - oldF;
if ( df < 0 ) df++;
oldF = f;

// ブラウザーがCortonaならば、df にフレームレートの逆数を入れる。
if (isCortona) {
var fps = Browser.getCurrentFrameRate();
if ( fps > 0.0 ) df = 1 / fps;
}

// active が false ならば、この関数を終えてボールを動かさないようにする。
if ( !active ) return;

// ボールを移動させる。
posBall = moveVec.multiply(df).add(posBall);

// ボールがコートからはみ出ているならば、
// ボールの進行方向を変えて、ボールをコートの内側に置く。
if ( posBall.x < -2.3 || posBall.x > 2.3 ) {

moveVec.x = -moveVec.x;
posBall.x = Math.max( -2.3, Math.min( 2.3 , posBall.x ));

}

if ( posBall.y < 0.2 || posBall.y > 2.8 ) {

moveVec.y = -moveVec.y;
posBall.y = Math.max( 0.2, Math.min( 2.8 , posBall.y ));

}

if ( posBall.z < -4.8 ) {

moveVec.z = -moveVec.z;
posBall.z = Math.max( -4.8 , posBall.z );

}

// ボールが手前に帰ってきたならば、ラケットにボールが当たっているか判断させる。
if ( posBall.z > 5.0 ) {

judgeCollisionWithRacket ();
posBall.z = 5.0;

}

// ボールの影の位置をセットする。
posBallShadow.x = posBall.x;
posBallShadow.y = 0;
posBallShadow.z = posBall.z;

}

function judgeCollisionWithRacket () {

// ボールとラケットの中心位置との距離をx成分とy成分について得る。
var dx = Math.abs ( posRacket.x - posBall.x );
var dy = Math.abs ( posRacket.y - posBall.y );

if ( dx < 0.7 && dy < 0.7 ) {

// ボールがラケットに当たっているならば、ボールの進行方向を変える。
moveVec.z = -moveVec.z;

// ボールがラケットに当たる度に、ボールのスピードを少しずつ上げる。
speed += 0.2;
moveVec = moveVec.normalize().multiply(speed);

}

// ボールがラケットから外れているならば、 active を false にしてボールを止める。
else active = false;

}

function translation_Racket (val) {

// ラケットの位置を得る。
posRacket = val;

// ラケットの影の位置をセットする。
posRacketShadow.x = val.x;
posRacketShadow.y = 0;
posRacketShadow.z = val.z;

}

]]>
</Script>

<ROUTE fromNode='Racket-PlS' fromField='translation_changed' toNode='Racket-Tf' toField='translation'/>
<ROUTE fromNode='Sc' fromField='posRacketShadow' toNode='RacketShadow-Tf' toField='translation'/>
<ROUTE fromNode='Ball-ThS' fromField='touchTime' toNode='Sc' toField='touchTime_Ball'/>
<ROUTE fromNode='TiS' fromField='fraction_changed' toNode='Sc' toField='set_fraction'/>
<ROUTE fromNode='Sc' fromField='posBall' toNode='Ball-Tf' toField='translation'/>
<ROUTE fromNode='Sc' fromField='posBallShadow' toNode='BallShadow-Tf' toField='translation'/>
<ROUTE fromNode='Racket-PlS' fromField='translation_changed' toNode='Sc' toField='translation_Racket'/>
</Scene>
</X3D>