Virtual-E-Mart

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



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





Sounds

FilenameDisk size
ball_hit.wav 141KB
balloon.wav 109KB
bottle_cling.wav 90KB
creak.wav 24KB
ding.wav 141KB
tin_can_smash.wav 71KB
success.wav 36KB
TOTAL: ~535KB

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"

Textures

FilenameDisk sizeMemory sizeImage preview
ball1.png 139KB 256x256x32b = 256KB
ball2.png 37KB 256x256x32b = 256KB
ball.png 795B 256x256x32b = 256KB
basket.png 54KB 256x256x32b = 256KB
bottle-transp.png 54KB 256x256x32b = 256KB
bricks.jpg 91KB 508x787x24b = 1171KB
cube.jpg 10.4KB 256x256x24b = 192KB
fire.png 2.1KB 256x256x32b = 256KB
jack-in-the-box1.png 26KB 128x128x32b = 64KB
nuts2.png 222KB 512x512x32b = 1024KB
nuts.png 222KB 512x512x32b = 1024KB
sandstone.jpg 32KB 512x512x24b = 768KB
tincan.jpg 63KB 512x512x24b = 768KB
wood-texture.jpg 120KB 512x512x24b = 768KB
TOTAL: 7251KB ~ 7MB 



Progress

12.10.2010 - Project started

19.10.2010 - Basic ideas of nuts designed

26.10.2010 - 1st assignment deadline!

09.11.2010 - 2nd assignment deadline!

23.11.2010 - 3rd assignment deadline!

14.12.2010 - 4rd assignment deadline!