Virtual Reality class project
About
A goal of the project is to create a virtual world - 3D web game for kids in a virtual mart environment as a Virtual Reality - NPGR012 class project.
Main game features are called nuts. A nut is an interactive object which kid (or any other operator) should play with to achieve game points.
Authors
Technical background
We use Virtual Reality Modeling Language (VRML) to design the web game. You have to get a VRML plugin to run it.
We are planning to create X3D version of the game with a support of haptic technology using H3D API (see Haptic API survey).
Links
Virtual-E-Mart
Nuts
- Jack in the box (Martin) - box with a handle, the handle is clickable, makes sounds. The goal is to turn the handle around few times to get PING sound and then click the box to get the Jack out of it!
- Rack with toys (Martin) - all but one are the same kind. The goal is to reveal the one that doesn't belong there and grab it.
- Empties (Petr) - the goal is to grab proper empties to reverse vending machines of two types - glass and PET empties.
- Ball game (Petr) - grab the right ball and throw it to the basket
Scripts
# ---------------------------------------------------------
# Defined in toyrack.wrl, upon touching the steam engine
# touch sensor removes its geometry and emits nut id one
# level up
DEF CompletionScript Script {
eventIn SFTime touchTime
eventOut SFInt32 completed IS completed
directOutput TRUE
field SFInt32 id IS id
field SFNode steamEngine USE steamEngineGrp
field SFNode engine USE Engine
url "javascript:
function touchTime() {
completed = id;
steamEngine.removeChildren = engine;
}
"
}
# ---------------------------------------------------------
# Defined in toyrack.wrl, upon receiving event generated
# by previous script, this one disables the helper arrow
# and emits id through the prototype head as a completed
# event caught by master script. Upon showIt event shows
# or hides the helper arrow
DEF HelperScript Script {
eventIn SFInt32 inCompleted
eventIn SFBool showIt IS showIt
eventOut SFInt32 completed IS completed
directOutput TRUE
field SFNode arrow USE navArrow
field SFInt32 id IS id
field SFBool isCompleted FALSE
url "javascript:
function inCompleted(value, time) {
if(value == id) {
isCompleted = true;
completed = id;
arrow.whichChoice = 0;
}
}
function showIt(value, time) {
if(isCompleted == false && value == true) {
arrow.whichChoice = 1;
}
else {
arrow.whichChoice = 0;
}
}
"
}
#----------------------------------------------------------
# Defined in jack-in-the-box.wrl, its main purpose was to
# disable the touch sensor once it was clicked, thus dis-
# allowing further clicking and reloading of the animation.
# Its functionality has been extended, so now it emits id
# to signal completion to the master script and also is
# responsible for showing and hiding the helper arrow.
DEF boxTSdisableScript Script {
eventIn SFFloat fraction_changed
eventIn SFBool showIt IS showIt
eventOut SFBool enabled
eventOut SFInt32 completed IS completed
field SFInt32 id IS id
field SFBool isCompleted FALSE
directOutput TRUE
field SFNode arrow USE navArrow
url "javascript:
function initialize() {
enabled = true;
}
function fraction_changed(value, time) {
if(value > 0.0) {
enabled = false;
completed = id;
isCompleted = true;
arrow.whichChoice = 0;
}
}
function showIt(value, time) {
if(isCompleted == false && value == true) {
arrow.whichChoice = 1;
}
else {
arrow.whichChoice = 0;
}
}
"
}
#----------------------------------------------------------
# Defined in jack-in-the-box.wrl, this script is respon-
# sible for priming the jack, once the handle has been
# sufficiently rotated in any direction. It also de-
# activates itself.
DEF handleScript Script {
eventIn SFFloat totalAngle # total handle rotation
eventIn SFRotation rotation # rotation of the handle - we need just the time
eventOut SFBool isPrimed # sets the jack to primed state
eventOut SFTime rotateET # event time for controlling the sound
eventOut SFTime primedET # event time for controlling the sound
field SFBool isActive TRUE
url "javascript:
function initialize() {
isActive = true;
isPrimed = false;
}
function rotation(value, time) {
rotateET = time;
}
function totalAngle(value, time) {
if(isActive == true && Math.abs(value) >= 6.28) {
isActive = false; // deactivate the script
isPrimed = true; // prime the jack
primedET = time;
}
}
"
}
#----------------------------------------------------------
# Defined in environment.wrl, serves as a custom sinus
# function position interpolator for helper arrow animation
DEF ArrowInterpolator Script {
eventIn SFFloat fraction_changed
eventOut SFVec3f value_changed
url "javascript:
function fraction_changed(value, time) {
y = 0.5 * Math.sin(value * 2 * Math.PI);
value_changed = new SFVec3f(0, y, 0);
}
"
}
#----------------------------------------------------------
# Defined in main.wrl, this is the master script that is
# responsible for actually running the game. It updates the
# scene timer (in HUD), registers helper arrow requests and
# sends events to show/hide them and finally counts all
# completed nuts and starts off the outro once all nuts
# have been completed.
DEF MasterScript Script {
eventIn SFTime cycleTime # sent by main timer
eventIn SFInt32 nutCompleted # sent by each nut upon completition
eventIn SFTime helpTouchTime # sent by HelpTS
eventOut SFBool showIt
eventOut SFTime gameOver
eventOut SFBool isOver
directOutput TRUE
field SFNode timer USE TimeText # node displaying the text
field SFInt32 sceneTime 0 # time in seconds
field SFNode counter USE NutCounter # node displaying the text
field SFInt32 numNuts 12
field SFInt32 completed 0
field MFInt32 nuts [] # boolean flags determining completed nuts
field SFBool showHelp FALSE
url "javascript:
function initialize() {
for(i = 0; i < numNuts; ++i)
nuts[i] = 0;
counter.string = new MFString(': ' + completed + '/' + numNuts);
}
function cycleTime() {
timer.string = new MFString('Time: ' + sceneTime++);
}
function nutCompleted(value, time) {
if(value >= 0 && value < numNuts && nuts[value] == 0) {
nuts[value] = 1;
completed++;
counter.string = new MFString(': ' + completed + '/' + numNuts);
if(completed >= numNuts) {
gameOver = time;
isOver = true;
}
}
}
function helpTouchTime(value, time) {
if(showHelp == false) {
showHelp = true;
}
else {
showHelp = false;
}
showIt = showHelp;
}
"
}
#----------------------------------------------------------
# Defined in main.wrl, this script is used to "hide" the
# outro text once it almost reached its destination
DEF OutroEnd Script {
eventIn SFFloat set_fraction
directOutput TRUE
field SFNode text USE EndText
url "javascript:
function set_fraction(value, time) {
if(1.0 - value < 0.05) {
text.string = new String('');
}
}
"
}
#----------------------------------------------------------
# Defined in tincan.wrl, this script controls the whole
# "nut script" mechanism.
#
# Function in_TinPosition checks whether the object is
# in the reverse vending machine by calculating distance
# from its center defined by relative translation
# vector bigTin and bigBottle.
#
# Function in_TimeCheck is called in a cycle
# by a time sensor and checks if correct object
# is in correct reverse vending machine
# (i.e. glass bottle in glass, tincan in tincan r.v.m.)
#
# As all nut scripts - showIt and completed events
# are present.
#
DEF NutScript Script {
eventIn SFVec3f in_TinPosition
eventIn SFTime in_TimeCheck
eventIn SFVec3f tinPos
eventIn SFBool showIt IS showIt
eventOut SFVec3f out_TinPosition
eventOut SFTime out_Time
eventOut SFInt32 completed IS completed
field SFVec3f relP IS relPosition
field SFVec3f bigTin -55 -15 0
field SFVec3f bigBottle -14 35 0
field SFBool inTin FALSE
field SFBool inBottle FALSE
field SFInt32 complItems 0
field SFNode arrow USE navArrow
field SFInt32 id IS id
field SFBool isCompleted FALSE
directOutput TRUE
url "javascript:
function in_TinPosition(value, tm)
{
if (
(value[0] - relP[0] - bigTin[0])*(value[0] - relP[0] - bigTin[0]) +
(value[1] - relP[1] - bigTin[1])*(value[1] - relP[1] - bigTin[1]) < 30.0
)
{
inTin = TRUE;
out_Time = tm;
}
else
{
inTin = FALSE;
}
if (
(value[0] - relP[0] - bigBottle[0])*(value[0] - relP[0] - bigBottle[0]) +
(value[1] - relP[1] - bigBottle[1])*(value[1] - relP[1] - bigBottle[1]) < 15.0
)
{
inBottle = TRUE;
out_Time = tm;
}
else
{
inBottle = FALSE;
}
}
function showIt(value, time) {
if(isCompleted == false && value == true) {
arrow.whichChoice = 1;
}
else {
arrow.whichChoice = 0;
}
}
function in_TimeCheck(value)
{
if (value && inBottle)
{
out_TinPosition[0] = bigBottle[0] + relP[0];
out_TinPosition[1] = bigBottle[1] + relP[1] - 5.0;
}
if (value && inTin)
{
isCompleted = 1;
completed = id;
}
}
"
}
#----------------------------------------------------------
# Defined in basketball.wrl, this script controls the whole
# "nut script" mechanism.
#
# Function ballPos checks whether the object is
# in the correct relative position to basket and sets ballOK
# flag.
#
# Function ballActive is called by touch sensor
# and checks if the ballOK flag is TRUE and
# set completed flag.
# This makes it possible to let user jump the ball twice.
#
# As all nut scripts - showIt and completed events
# are present.
#
DEF NutScript Script {
eventIn SFVec3f ballPos
eventIn SFBool ballActive
eventIn SFBool showIt IS showIt
eventOut SFTime successTime
eventOut SFInt32 completed IS completed
field SFBool ballOK FALSE
field SFNode arrow USE navArrow
field SFInt32 id IS id
field SFBool isCompleted FALSE
directOutput TRUE
url "javascript:
function ballActive(value, time)
{
if (value)
{
if (ballOK)
{
isCompleted = TRUE;
completed = id;
successTime = time;
}
}
}
function ballPos(value)
{
if (value[0] > -1 && value[0] < 1 && value[1] < -4 && value[1] > -6)
{
ballOK = TRUE;
}
}
function showIt(value, time) {
if(isCompleted == false && value == true) {
arrow.whichChoice = 1;
}
else {
arrow.whichChoice = 0;
}
}
"
ROUTE BallPlaner.translation_changed TO NutScript.ballPos
ROUTE Ball1TouchSensor.isActive TO NutScript.ballActive
ROUTE NutScript.successTime TO successSound.startTime
}
Flowcharts of dynamics
Ball and basket dynamics
Tincan and bottle dynamics
Jack in the box dynamics
ToyRack dynamics
Prototypes
# ---------------------------------------------------------
# PROTO First possible head for the Jack
#
# parameters:
# - texture - Head texture
# - noseAppearance - appearance of the cown nose
# - hatAppearance - appearance of the cown hat
# - LOD - turn on/turn off level of detail
# ---------------------------------------------------------
EXTERNPROTO Clown [
exposedField SFNode texture
exposedField SFNode noseAppearance
exposedField SFNode hatAppearance
exposedField SFInt32 lod
] "jack-in-the-box.wrl#Clown"
# ---------------------------------------------------------
# PROTO JackInTheBox
#
# parameters:
# - boxAppearance - appearance of the box
# - coverAppearance - appearance of the box cover
# - springAppearance - appearance of the spring
# - children - appearance of the spring
# - LOD - turn on/turn off level of detail
# ---------------------------------------------------------
EXTERNPROTO JackInTheBox [
exposedField SFNode boxAppearance
exposedField SFNode coverAppearance
exposedField SFNode springAppearance
exposedField MFNode children
exposedField SFInt32 lod
] "jack-in-the-box.wrl#JackInTheBox"
# ---------------------------------------------------------
# PROTO ToyRack
#
# parameters:
# - color1 - Steam engine bed color
# - color2 - Steam engine boiler color
# - color3 - Steam engine cabin color
# - color4 - Steam engine features color
# - LOD - turn on/turn off level of detail
# ---------------------------------------------------------
EXTERNPROTO ToyRack [
exposedField SFNode color1
exposedField SFNode color2
exposedField SFNode color3
exposedField SFNode color4
exposedField SFInt32 lod
] "toyrack.wrl#ToyRack"
# ---------------------------------------------------------
# TinCan
#
# parameters:
# - scaleFactor - scale factor of the tincan
# - textureUrl - path to the tincan texture
# - LOD - turn on/turn off level of detail
# ---------------------------------------------------------
EXTERNPROTO TinCan [
exposedField SFVec3f scaleFactor
exposedField MFString textureUrl
exposedField SFInt32 lod
] "tincan.wrl#TinCan"
# ---------------------------------------------------------
# PROTO Bottle
#
# parameters:
# - scaleFactor - scale factor of the bottle
# - textureUrl - path to the bottle texture
# - LOD - turn on/turn off level of detail
# ---------------------------------------------------------
EXTERNPROTO Bottle [
exposedField SFVec3f scaleFactor
exposedField MFString textureUrl
exposedField SFInt32 lod
] "bottle.wrl#Bottle"
# ---------------------------------------------------------
# PROTO BasketBall
#
# parameters:
# - textureUrl - path to the baset texture
# - LOD - turn on/turn off level of detail
# ---------------------------------------------------------
EXTERNPROTO BasketBall [
exposedField MFString textureUrl
exposedField SFInt32 lod
] "basketball.wrl#BasketBall"
# ---------------------------------------------------------
# PROTO Infotable
#
# parameters:
# - textureUrl - path to the infotable texture
# - LOD - turn on/turn off level of detail
# ---------------------------------------------------------
EXTERNPROTO Infotable [
exposedField MFString textureUrl
exposedField SFInt32 lod
] "infotable.wrl#Infotable"
# ---------------------------------------------------------
# PROTO Ball1, Ball2
#
# parameters:
# - LOD - turn on/turn off level of detail
# ---------------------------------------------------------
EXTERNPROTO Ball1 [ exposedField SFInt32 lod ] "basketball.wrl#Ball1"
EXTERNPROTO Ball2 [ exposedField SFInt32 lod ] "basketball.wrl#Ball2"
# ---------------------------------------------------------
# PROTO Girder
#
# parameters:
# - LOD - turn on/turn off level of detail
# ---------------------------------------------------------
EXTERNPROTO Girder [ exposedField SFInt32 lod ] "environment.wrl#Girder"
# ---------------------------------------------------------
# PROTO extinguisher
#
# parameters:
# - LOD - turn on/turn off level of detail
# ---------------------------------------------------------
EXTERNPROTO Extinguisher [ exposedField SFInt32 lod ] "environment.wrl#Extinguisher"
# ---------------------------------------------------------
# PROTO Companion cubes
#
# parameters:
# - Appearance - appearance of the companion cubes from Portal game
# - LOD - turn on/turn off level of detail
# ---------------------------------------------------------
PROTO Cubes [ exposedField SFNode appearance ] "envionrment.wrl#Cubes"
# ---------------------------------------------------------
# PROTO GenericRack
#
# parameters:
# - LOD - turn on/turn off level of detail
# ---------------------------------------------------------
EXTERNPROTO GenericRack [ exposedField SFInt32 lod ] "environment.wrl#GenericRack"