#VRML V2.0 utf8
WorldInfo {
title "Squash rackets"
}
# 視点
Viewpoint {
position 0.0 1.7 10
description "initial"
}
Viewpoint {
position 0 7.8 9.7
orientation -1 0 0 .68
description "Bird"
}
#Inline { url "getVp.wrl"}
# ナビゲーション情報
NavigationInfo {
type "EXAMINE"
headlight FALSE
}
# 背景
Background {
skyAngle [ 1.57 1.571 ]
skyColor [ 0.0 0.2 1.0, 0.5 0.8 1.0, 0.6 0.3 0.0 ]
}
# 照明
PointLight {
location 1 2.5 6
}
PointLight {
location -1 2.5 6
}
# コート床
Transform {
translation 0 -0.005 0
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 1.0 0.7 0.3
}
}
geometry Box {
size 5 0.01 10
}
}
]
}
# コート天井
Transform {
translation 0 3.05 0
children [
Shape {
appearance Appearance {
material Material {
emissiveColor 0.3 0.3 0.27
diffuseColor 1.0 0.9 0.7
transparency 0.7
}
}
geometry Box {
size 5 0.1 10
}
}
]
}
# コート壁(奥)
Transform {
translation 0 1.5 -5.05
children [
Shape {
appearance DEF Court-Ap Appearance {
material Material {
diffuseColor 0.2 0.9 0.7
}
}
geometry Box {
size 5.2 3.2 0.1
}
}
]
}
# コート壁(左)
Transform {
translation -2.55 1.55 0
children [
DEF SideWall-Sp Shape {
appearance USE Court-Ap
geometry Box {
size 0.1 3.1 10
}
}
]
}
# コート壁(右)
Transform {
translation 2.55 1.55 0
children USE SideWall-Sp
}
# ボール
DEF Ball-Tf Transform {
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 1 0 0
}
}
geometry DEF Ball Sphere {
radius 0.2
}
}
DEF Ball-ThS TouchSensor {}
]
}
# ボールの影
DEF BallShadow-Tf Transform {
scale 1 0.01 1
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 0 0 0
}
}
geometry USE Ball
}
]
}
# ラケット
DEF Racket-Tf Transform {
translation 0 1 5.2
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 1 1 0
transparency 0.3
}
}
geometry Box {
size 1 1 0.1
}
}
DEF Racket-PlS PlaneSensor {
offset 0 1 5.2
minPosition -2 0.5
maxPosition 2 2.5
}
]
}
# ラケットの影
DEF RacketShadow-Tf Transform {
translation 0 0 5.2
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 0 0 0
}
}
geometry Box {
size 1 0.001 0.1
}
}
]
}
# タイムセンサー
DEF TiS TimeSensor {
loop TRUE
}
# スクリプト
DEF Sc Script {
eventIn SFTime touchTime_Ball
eventIn SFFloat set_fraction
eventIn SFVec3f translation_Racket
eventOut SFVec3f posBall # ボールの位置
eventOut SFVec3f posBallShadow # ボールの影の位置
eventOut SFVec3f posRacketShadow # ラケットの影の位置
field SFVec3f moveVec 0 0 0 # ボールの移動ベクトル
field SFFloat oldF 0 # 前回イベント時の fraction_changed の値
field SFVec3f posRacket 0 0 0 # ラケットの位置
field SFBool active FALSE # ボールを動かすか否か
field SFFloat speed 5.0 # ボールのスピード
field SFBool isCortona FALSE # 実行しているブラウザーが Cortona か否か
url "javascript:
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;
}
"
}
# ラケットとその影の移動
ROUTE Racket-PlS.translation_changed TO Racket-Tf.translation
ROUTE Sc.posRacketShadow TO RacketShadow-Tf.translation
# ボールをクリックしたことをスクリプトに知らせる
ROUTE Ball-ThS.touchTime TO Sc.touchTime_Ball
# タイムセンサーの経過をスクリプトへ送る
ROUTE TiS.fraction_changed TO Sc.set_fraction
# ボールとその影の位置の移動
ROUTE Sc.posBall TO Ball-Tf.translation
ROUTE Sc.posBallShadow TO BallShadow-Tf.translation
# ラケットの位置をスクリプトに送る
ROUTE Racket-PlS.translation_changed TO Sc.translation_Racket