diff --git a/core.js b/core.js deleted file mode 100644 index a08eb00..0000000 --- a/core.js +++ /dev/null @@ -1,224 +0,0 @@ -/* Thanks to http://phrogz.net/js/classes/OOPinJS2.html */ -Function.prototype.inheritsFrom = function(parentObject) -{ - if(parentObject.constructor == Function) - { - /* Normal Inheritance */ - this.prototype = new parentObject; - this.prototype.constructor = this; - this.prototype.parent = parentObject.prototype; - } - else - { - /* Pure Virtual Inheritance */ - this.prototype = parentObject; - this.prototype.constructor = this; - this.prototype.parent = parentObject; - } - - return this; -} - -/*Class*/ RadiumEngine = function() -{ - this.version = "1.0"; - - var /*Exception*/ Exception = this.Exception = function(message) - { - this.message = message; - } - - var /*Exception*/ Warning = this.Warning = function(message) - { - this.message = message; - } - - var /*Exception*/ ResourceException = this.ResourceException = function(message, resource, action) - { - this.resource = resource; - this.message = message; - this.action = action; - } - ResourceException.inheritsFrom(Exception); - - var /*Exception*/ ResourceWarning = this.ResourceWarning = function(message, resource, action) - { - this.resource = resource; - this.message = message; - this.action = action; - } - ResourceWarning.inheritsFrom(Warning); - - var /*Class*/ Player = this.Player = function() - { - this.credits = 0; /* Integer */ - this.health = 1; /* Fraction */ - this.resources = {}; /* Associative array -> Resource */ - - this.InitializeResource = function(resource, negative_allowed, min, max) - { - var resource_object = new Resource(); - resource_object.name = resource; - - if(negative_allowed !== undefined) - { - resource_object.negative_allowed = negative_allowed; - } - - if(min !== undefined) - { - resource_object.minimum = min; - } - - if(min !== undefined) - { - resource_object.maximum = max; - } - - if(min != null && min > 0) - { - /* Set current amount of units to minimum boundary. */ - resource_object.value = min; - } - - this.resources[resource] = resource_object; - } - - this.TakeResource = function(resource, amount) - { - if(this.resources[resource]) - { - resource_object = this.resources[resource]; - - if(resource_object.value - amount < 0 && resource_object.negative_allowed == false) - { - throw new ResourceException("There are not enough units of this resource available.", resource, "take"); - } - else if(resource_object.minimum != null && resource_object.value - amount < resource_object.minimum) - { - throw new ResourceException("Taking away this many units will violate the lower resource boundary.", resource, "take"); - } - else - { - resource_object.value -= amount; - } - } - else - { - throw new ResourceException("This resource does not exist.", resource, "take"); - } - } - - this.GiveResource = function(resource, amount) - { - if(this.resources[resource]) - { - resource_object = this.resources[resource]; - - if(resource_object.maximum != null && resource_object.value + amount > resource_object.maximum) - { - resource_object.value = resource_object.maximum; - throw new ResourceWarning("The upper boundary of the resource was reached.", resource, "give"); - } - else - { - resource_object.value += amount; - } - } - else - { - throw new ResourceException("This resource does not exist.", resource, "give"); - } - } - - this.SetResource = function(resource, amount) - { - if(this.resources[resource]) - { - resource_object = this.resources[resource]; - - if(resource_object.minimum != null && amount < resource_object.minimum) - { - throw new ResourceException("The specified amount is lower than the lower boundary of the resource.", resource, "set"); - } - else if(resource_object.maximum != null && amount > resource_object.maximum) - { - throw new ResourceException("The specified amount is lower than the lower boundary of the resource.", resource, "set"); - } - else if(resource_object.negative_allowed === false && amount < 0) - { - throw new ResourceException("This resource cannot be set to a negative amount.", resource, "set"); - } - else - { - resource_object.value = amount; - } - } - else - { - throw new ResourceException("This resource does not exist.", resource, "set"); - } - } - } - - var /*Class*/ Resource = this.Resource = function() - { - this.name = "Unnamed resource"; - this.negative_allowed = false; - this.minimum = null; - this.maximum = null; - this.value = 0; - } - - var /*Static Class*/ Point = RadiumEngine.Point = function(x, y) - { - this.x = x; - this.y = y; - - this.Add = function() - { - var new_point = new RadiumEngine.Point(this.x, this.y); - - for (i in arguments) - { - new_point.x += arguments[i].x; - new_point.y += arguments[i].y; - } - - return new_point; - } - - this.Subtract = function() - { - var new_point = new RadiumEngine.Point(this.x, this.y); - - for (i in arguments) - { - new_point.x -= arguments[i].x; - new_point.y -= arguments[i].y; - } - - return new_point; - } - } - - var /*Static*/ point_distance = RadiumEngine.point_distance = function(x1, y1, x2, y2) - { - var xL = x1 - x2; - var yL = y1 - y2; - return Math.sqrt((xL * xL) + (yL * yL)); - } - - RadiumEngine.dot_product = function(a, b) - { - var n = 0; - var lim = Math.min(a.length, b.length); - - for (var i = 0; i < lim; i++) - { - n += a[i] * b[i]; - } - - return n; - } -} diff --git a/docs/api/draw.html b/docs/api/draw.html new file mode 100644 index 0000000..44015cc --- /dev/null +++ b/docs/api/draw.html @@ -0,0 +1,168 @@ + + + + + + +

Engine.Draw

The Draw library provides functions to draw shapes, text, and sprites on a scene.

Table of contents

Engine.Draw.Line(x1, y1, x2, y2, options)
Engine.Draw.Rectangle(x1, y1, x2, y2, options)
Draws a rectangle.
x1
The X coordinate of the top left corner.
y1
The Y coordinate of the top left corner.
x2
The X coordinate of the right bottom corner.
y2
The Y coordinate of the right bottom corner.
options
Optional. Options for drawing the rectangle.
width
Width of the outline in pixels.
linecolor
The color of the outline.
cap
The type line cap for the outline.
rx
The horizontal radius of the corners of the rectangle.
ry
The vertical radius of the corners of the rectangle.
radius
A short-hand option that sets both rx and ry.
color
The fill color of the rectangle.
alpha
The alpha value of the rectangle.
Example: Draw a blue rectangle with a yellow outline, rounded borders and at 70% opacity
Code:
Engine.Draw.Rectangle(20, 30, 150, 180, {
+	linecolor: "yellow",
+	color: "blue",
+	radius: 8,
+	alpha: 0.7
+});
+ + diff --git a/docs/api/draw.zpy b/docs/api/draw.zpy new file mode 100644 index 0000000..4a32670 --- /dev/null +++ b/docs/api/draw.zpy @@ -0,0 +1,94 @@ +# Engine.Draw + +The Draw library provides functions to draw shapes, text, and sprites on a scene. + +{TOC} + +^ Engine.Draw.Line(**x1**, **y1**, **x2**, **y2**, **options**) + + Draws a line. + + x1:: + The X coordinate of the starting position. + + y1:: + The Y coordinate of the starting position. + + x2:: + The X coordinate of the ending position. + + y2:: + The Y coordinate of the ending position. + + options:: + **Optional.** Options for drawing the line. + + width:: + Width of the line in pixels. + + color:: + The line {>../drawing}(color). + + cap:: + The type of {>../drawing}(line cap). + + alpha:: + The alpha value of the line. + + @ Draw a blue line + + $ Engine.Draw.Line(10, 10, 120, 120, { + color: "blue" + }); + +^ Engine.Draw.Rectangle(**x1**, **y1**, **x2**, **y2**, **options**) + + Draws a rectangle. + + x1:: + The X coordinate of the top left corner. + + y1:: + The Y coordinate of the top left corner. + + x2:: + The X coordinate of the right bottom corner. + + y2:: + The Y coordinate of the right bottom corner. + + options:: + **Optional.** Options for drawing the rectangle. + + width:: + Width of the outline in pixels. + + linecolor:: + The {>../drawing}(color) of the outline. + + cap:: + The type {>../drawing}(line cap) for the outline. + + rx:: + The horizontal radius of the corners of the rectangle. + + ry:: + The vertical radius of the corners of the rectangle. + + radius:: + A short-hand option that sets both `rx` and `ry`. + + color:: + The fill color of the rectangle. + + alpha:: + The alpha value of the rectangle. + + @ Draw a blue rectangle with a yellow outline, rounded borders and at 70% opacity + + $ Engine.Draw.Rectangle(20, 30, 150, 180, { + linecolor: "yellow", + color: "blue", + radius: 8, + alpha: 0.7 + }); diff --git a/docs/api/math.html b/docs/api/math.html new file mode 100644 index 0000000..5092aa8 --- /dev/null +++ b/docs/api/math.html @@ -0,0 +1,162 @@ + + + + + + +

Engine.Math

The Math library provides several functions to do mathematical operations or calculations. Most of these functions are simply aliases of the functions built into JavaScript.

Table of contents

Engine.Math.Absolute(x)
Engine.Math.Abs(x)
Returns the absolute value of x.
This is an alias of the standard Math.abs function in JavaScript.
x
The number.
Example: Get the absolute value of a positive number
Code:
Engine.Math.Absolute(16);
Output:
16
Example: Get the absolute value of a negative number
Code:
Engine.Math.Absolute(-23);
Output:
23
Engine.Random.Sum(item [, item [, item ...]])
Engine.Random.Sum(itemarray)
Returns the sum of all supplied numbers.
item
An individual number. itemarray:: An array of numbers.
Example: Sum several numbers using individual arguments
Code:
Engine.Math.Sum(42, 6, 17, 2, 7);
Output:
74
Example: Sum several numbers using an array
Code:
var numbers = [42, 6, 17, 2, 7];
+Engine.Math.Sum(numbers);
Output:
74
Engine.Math.Round(x)
Rounds x to the nearest integer.
This is an alias of the standard Math.round function in JavaScript.
x
The value to round.
Example: Rounding a number in the upper half
Code:
Engine.Math.Ceiling(82.62);
Output:
83
Example: Rounding a number in the lower half
Code:
Engine.Math.Ceiling(82.13);
Output:
82
Engine.Math.Ceiling(x)
Engine.Math.Ceil(x)
Rounds up x.
This is an alias of the standard Math.ceil function in JavaScript.
x
The value to round up.
Example: Rounding up a number
Code:
Engine.Math.Ceiling(614.2162);
Output:
615
Engine.Math.Floor(x)
Rounds down x.
This is an alias of the standard Math.floor function in JavaScript.
x
The value to round down.
Example: Rounding down a number
Code:
Engine.Math.Floor(7.612);
Output:
7
Engine.Math.Tangent(x)
Engine.Math.Tan(x)
Returns the tangent of angle x.
This is an alias of the standard Math.tan function in JavaScript.
x
The value.
Example: Calculating the tangent
Code:
Engine.Math.Tangent(84.15);
Output:
-0.7971515163204654
Engine.Math.Cosine(x)
Engine.Math.Cos(x)
Returns the cosine of x.
This is an alias of the standard Math.cos function in JavaScript.
x
The value (in radians).
Example: Calculating the cosine
Code:
Engine.Math.Cosine(162.54);
Output:
0.6801581420388815
Engine.Math.Sine(x)
Engine.Math.Sin(x)
Returns the sine of x.
This is an alias of the standard Math.sin function in JavaScript.
x
The value (in radians).
Example: Calculating the sine
Code:
Engine.Math.Sine(62.4);
Output:
-0.41855446451842543
+ + diff --git a/docs/api/math.zpy b/docs/api/math.zpy new file mode 100644 index 0000000..8ae3568 --- /dev/null +++ b/docs/api/math.zpy @@ -0,0 +1,150 @@ +# Engine.Math + +The Math library provides several functions to do mathematical operations or calculations. Most of these functions are simply aliases of the functions built into JavaScript. + +{TOC} + +^ Engine.Math.Absolute(**x**) + Engine.Math.Abs(**x**) + + Returns the absolute value of `x`. + + **This is an alias of the standard Math.abs function in JavaScript.** + + x:: + The number. + + @ Get the absolute value of a positive number + + $ Engine.Math.Absolute(16); + + > 16 + + @ Get the absolute value of a negative number + + $ Engine.Math.Absolute(-23); + + > 23 + +^ Engine.Random.Sum(**item** [, **item** [, **item** ...]]) + Engine.Random.Sum(**itemarray**) + + Returns the sum of all supplied numbers. + + item:: + An individual number. + itemarray:: + An array of numbers. + + @ Sum several numbers using individual arguments + + $ Engine.Math.Sum(42, 6, 17, 2, 7); + + > 74 + + @ Sum several numbers using an array + + $ var numbers = [42, 6, 17, 2, 7]; + Engine.Math.Sum(numbers); + + > 74 + +^ Engine.Math.Round(**x**) + + Rounds `x` to the nearest integer. + + **This is an alias of the standard Math.round function in JavaScript.** + + x:: + The value to round. + + @ Rounding a number in the upper half + + $ Engine.Math.Ceiling(82.62); + + > 83 + + @ Rounding a number in the lower half + + $ Engine.Math.Ceiling(82.13); + + > 82 + +^ Engine.Math.Ceiling(**x**) + Engine.Math.Ceil(**x**) + + Rounds up `x`. + + **This is an alias of the standard Math.ceil function in JavaScript.** + + x:: + The value to round up. + + @ Rounding up a number + + $ Engine.Math.Ceiling(614.2162); + + > 615 + +^ Engine.Math.Floor(**x**) + + Rounds down `x`. + + **This is an alias of the standard Math.floor function in JavaScript.** + + x:: + The value to round down. + + @ Rounding down a number + + $ Engine.Math.Floor(7.612); + + > 7 + +^ Engine.Math.Tangent(**x**) + Engine.Math.Tan(**x**) + + Returns the tangent of angle `x`. + + **This is an alias of the standard Math.tan function in JavaScript.** + + x:: + The value. + + @ Calculating the tangent + + $ Engine.Math.Tangent(84.15); + + > -0.7971515163204654 + +^ Engine.Math.Cosine(**x**) + Engine.Math.Cos(**x**) + + Returns the cosine of `x`. + + **This is an alias of the standard Math.cos function in JavaScript.** + + x:: + The value (in radians). + + @ Calculating the cosine + + $ Engine.Math.Cosine(162.54); + + > 0.6801581420388815 + +^ Engine.Math.Sine(**x**) + Engine.Math.Sin(**x**) + + Returns the sine of `x`. + + **This is an alias of the standard Math.sin function in JavaScript.** + + x:: + The value (in radians). + + @ Calculating the sine + + $ Engine.Math.Sine(62.4); + + > -0.41855446451842543 diff --git a/docs/api/random.html b/docs/api/random.html new file mode 100644 index 0000000..555f7c1 --- /dev/null +++ b/docs/api/random.html @@ -0,0 +1,163 @@ + + + + + + +

Engine.Random

The Random library provides several functions to pick random numbers or items.

Table of contents

Engine.Random.Number(min, max, precision)
Selects a random number between min and max, excluding max itself.
min
Optional: The minimum number. Defaults to 0.
max
Optional: The maximum number (itself excluded). Defaults to 1.
precision
Optional: The precision; this is what the result will be rounded to. Defaults to 0.00000001.
Example: Get a whole number from 0 to 9
Code:
Engine.Random.Number(0, 10, 1);
Output:
7
Example: Get a one-tenth-precision number from 0 to 9.9
Code:
Engine.Random.Number(0, 10, 0.1);
Output:
3.7
Example: Get a one-fifth-precision number from 5 to 9.8:
Code:
Engine.Random.Number(5, 10, 0.2);
Output:
6.4
Engine.Random.Choose(item [, item [, item ...]])
Engine.Random.Choose(itemarray)
Selects a random item from the supplied items.
item
An item to choose from.
itemarray
An array of items to choose from.
Example: Select a random color from a list using multiple arguments
Code:
Engine.Random.Choose("blue", "green", "red", "yellow");
Output:
"green"
Example: Select a random day from a list using an array
Code:
var days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
+Engine.Random.Choose(days);
Output:
"Thursday"
Engine.Random.Pick(amount, item [, item [, item ...]])
Engine.Random.Pick(amount, itemarray)
Selects amount unique random items from the supplied items. Each item can only appear in the result once.
Important: The amount argument must always be equal to or higher than the amount of supplied items!
amount
The amount of items to select.
item
An item to choose from.
itemarray
An array of items to choose from.
Example: Select three random colors from a list using multiple arguments
Code:
Engine.Random.Pick(3, "red", "green", "blue", "yellow", "purple", "brown", "black", "white", "orange");
Output:
["blue", "orange", "red"]
Example: Select two vegetables from a list using an array
Code:
var vegetables = ["celery", "potato", "tomato", "coleslaw", "onion"];
+Engine.Random.Pick(2, vegetables);
Output:
["tomato", "onion"]
Engine.Random.String(length [, alphabet])
Generates a random string with the specified length, and optionally a custom alphabet.
length
The length of the string that has to be generated.
alphabet
Optional: The alphabet (set of characters) to choose from. Defaults to a-z, A-Z, 0-9.
Example: Generate a random string with the default alphabet
Code:
Engine.Random.String(14);
Output:
"NCm2Y7lEleCTa5"
Example: Generate a random string with a custom alphabet
Code:
Engine.Random.String(10, "abcde");
Output:
"baeddebaca"
+ + diff --git a/docs/api/random.zpy b/docs/api/random.zpy new file mode 100644 index 0000000..d9fa2f3 --- /dev/null +++ b/docs/api/random.zpy @@ -0,0 +1,123 @@ +# Engine.Random + +The Random library provides several functions to pick random numbers or items. + +{TOC} + +^ Engine.Random.Number(**min**, **max**, **precision**) + + Selects a random number between `min` and `max`, excluding `max` itself. + + + min:: + **Optional:** The minimum number. **Defaults to 0.** + + max:: + **Optional:** The maximum number (itself excluded). **Defaults to 1.** + + precision:: + **Optional:** The precision; this is what the result will be rounded to. **Defaults to 0.00000001.** + + + @ Get a whole number from 0 to 9 + + $ Engine.Random.Number(0, 10, 1); + + > 7 + + + @ Get a one-tenth-precision number from 0 to 9.9 + + $ Engine.Random.Number(0, 10, 0.1); + + > 3.7 + + + @ Get a one-fifth-precision number from 5 to 9.8: + + $ Engine.Random.Number(5, 10, 0.2); + + > 6.4 + + +^ Engine.Random.Choose(**item** [, **item** [, **item** ...]]) + Engine.Random.Choose(**itemarray**) + + Selects a random item from the supplied items. + + + item:: + An item to choose from. + + itemarray:: + An array of items to choose from. + + + @ Select a random color from a list using multiple arguments + + $ Engine.Random.Choose("blue", "green", "red", "yellow"); + + > "green" + + + @ Select a random day from a list using an array + + $ var days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]; + Engine.Random.Choose(days); + + > "Thursday" + + +^ Engine.Random.Pick(**amount**, **item** [, **item** [, **item** ...]]) + Engine.Random.Pick(**amount**, **itemarray**) + + Selects `amount` unique random items from the supplied items. Each item can only appear in the result once. + + ! The `amount` argument must always be equal to or higher than the amount of supplied items! + + + amount:: + The amount of items to select. + + item:: + An item to choose from. + + itemarray:: + An array of items to choose from. + + + @ Select three random colors from a list using multiple arguments + + $ Engine.Random.Pick(3, "red", "green", "blue", "yellow", "purple", "brown", "black", "white", "orange"); + + > ["blue", "orange", "red"] + + + @ Select two vegetables from a list using an array + + $ var vegetables = ["celery", "potato", "tomato", "coleslaw", "onion"]; + Engine.Random.Pick(2, vegetables); + + > ["tomato", "onion"] + +^ Engine.Random.String(**length** [, **alphabet**]) + + Generates a random string with the specified `length`, and optionally a custom alphabet. + + length:: + The length of the string that has to be generated. + + alphabet:: + **Optional:** The alphabet (set of characters) to choose from. **Defaults to a-z, A-Z, 0-9.** + + @ Generate a random string with the default alphabet + + $ Engine.Random.String(14); + + > "NCm2Y7lEleCTa5" + + @ Generate a random string with a custom alphabet + + $ Engine.Random.String(10, "abcde"); + + > "baeddebaca" diff --git a/lib/engine.js b/lib/engine.js new file mode 100644 index 0000000..686598b --- /dev/null +++ b/lib/engine.js @@ -0,0 +1,1462 @@ +/* Prototype modifications of standard types go here. */ + +HTMLCanvasElement.prototype.relativeCoordinates = function(event) +{ + var totalOffsetX = 0; + var totalOffsetY = 0; + var canvasX = 0; + var canvasY = 0; + var currentElement = this; + + do { + if(!$(currentElement).is('body')) + { + totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft; + totalOffsetY += currentElement.offsetTop - currentElement.scrollTop; + } + } while(currentElement = currentElement.offsetParent) + + canvasX = event.pageX - totalOffsetX; + canvasY = event.pageY - totalOffsetY; + + return {x:canvasX, y:canvasY} +} + +/* Save the engine path for later use. */ +var script_elements = document.getElementsByTagName('script'); +var this_element = script_elements[script_elements.length - 1]; +var script_path = this_element.src; +var engine_path = script_path.substr(0, script_path.lastIndexOf( '/' )+1 ); + +/* Core engine constructor. */ +function Engine(settings) +{ + this.resources = {}; + this.sprites = {}; + this.sounds = {}; + this.objects = {}; + this.scenes = {}; + this.canvas = null; + this.settings = settings; + this.loader_created = false; + this.instance_increment = 10000; + + _engine = this; + + /**--------------------------------------**/ + /** PRELOADER **/ + /**--------------------------------------**/ + + this.Preloader = function() + { + this._engine = _engine; + this.queue = []; + this.resources_left = 0; + this.resources_done = 0; + this.resources_total = 0; + this.resources_failed = 0; + this.images_total = 0; + this.scripts_total = 0; + this.sounds_total = 0; + this.sound_enabled = false; + this.sound_ignore_failure = false; + + if(this._engine.loader_created == false) + { + /* This is the first Preloader that is being created. Load scripts that are needed by the engine. */ + this._engine.loader_created = true; + + if(typeof this._engine.settings !== "undefined") + { + if(this._engine.settings["enable_sound"]) + { + this.AddScript(engine_path + "soundmanager2.js", "SoundManager2"); + + this.AddFunction(function(){ + soundManager.setup({ + url: 'static/', + onready: this._HandleSM2Ready.bind(this), + ontimeout: this._HandleSM2Failed.bind(this), + useHighPerformance: true, + preferFlash: false + }); + + return false; + }, "Initializing SoundManager2"); + } + else + { + this._engine.sound_enabled = false; + } + } + } + } + + /* Add function */ + this.Preloader.prototype.AddFunction = function(func, description) + { + this.queue.push({ + type: "function", + func: func.bind(this), + desc: description + }); + + this.resources_left++; + this.resources_total++; + } + + /* Add image */ + this.Preloader.prototype.AddImage = function(name, path) + { + this.queue.push({ + type: "image", + name: name, + path: path + }); + + this.resources_left++; + this.resources_total++; + } + + /* Add a dictionary of items */ + this.Preloader.prototype.AddItems = function(items) + { + if(typeof items.images != "undefined") + { + for(name in items.images) + { + this.AddImage(name, items.images[name]); + } + } + + if(typeof items.sounds != "undefined") + { + for(name in items.sounds) + { + this.AddSound(name, items.sounds[name]); + } + } + + if(typeof items.scripts != "undefined") + { + for(name in items.scripts) + { + this.AddScript(name, items.scripts[name]); + } + } + + if(typeof items.functions != "undefined") + { + for(name in items.functions) + { + this.AddFunction(name, items.functions[name]); + } + } + + } + + /* Add script file */ + this.Preloader.prototype.AddScript = function(path, description) + { + this.queue.push({ + type: "script", + path: path, + desc: description + }); + + this.resources_left++; + this.resources_total++; + } + + /* Add sound file */ + this.Preloader.prototype.AddSound = function(name, path) + { + this.queue.push({ + type: "sound", + name: name, + path: path + }); + + this.resources_left++; + this.resources_total++; + } + + /* Start the preloading sequence. */ + this.Preloader.prototype.Run = function(callbacks) + { + if(typeof callbacks == "undefined") + { + this.callbacks = {}; + } + else + { + this.callbacks = callbacks; + } + + this.RunCycle(); + } + + /* Process one item in the preloading sequence. */ + this.Preloader.prototype.RunCycle = function() + { + if(this.queue.length > 0) + { + current_object = this.queue.shift(); + + if(current_object.type == "image") + { + this._DoCallback(this.callbacks.onstagechange, { + type: "image", + description: current_object.path + }); + + current_image = new Image(); + current_image.onload = this._ReportResourceFinished.bind(this); + current_image.src = current_object.path; + + this.images_total++; + this._engine.resources[current_object.name] = current_image; + } + else if(current_object.type == "sound") + { + this._DoCallback(this.callbacks.onstagechange, { + type: "sound", + description: current_object.path + }); + + if(this._engine.sound_enabled == true) + { + if(soundManager.canPlayURL(current_object.path)) + { + var sound = soundManager.createSound({ + id: current_object.name, + url: current_object.path, + autoLoad: true, + autoPlay: false, + onload: this._ReportResourceFinished.bind(this) + }); + + this.sounds_total++; + this._engine.resources[current_object.name] = sound; + } + else + { + throw { + "name": "SoundError", + "message": "The sound format is not supported." + } + } + } + else if(this._engine.sound_ignore_failure == true) + { + /* TODO: Log error */ + } + else + { + throw { + "name": "SoundError", + "message": "Cannot add audio file because sound support is not enabled in the engine." + } + } + } + else if(current_object.type == "script") + { + this._DoCallback(this.callbacks.onstagechange, { + type: "script", + description: current_object.desc + }); + + $.getScript(current_object.path, this._ReportResourceFinished.bind(this)); + + this.scripts_total++; + } + else if(current_object.type == "function") + { + this._DoCallback(this.callbacks.onstagechange, { + type: "function", + description: current_object.desc + }); + + var result = current_object.func(this.callbacks); + + if(result == true) + { + this._ReportResourceFinished(); + } + } + } + else + { + this._DoCallback(this.callbacks.onfinish) + } + } + + /* Check if the preloading sequence is finished and take appropriate action. */ + this.Preloader.prototype._CheckIfDone = function() + { + if(this.resources_left <= 0) + { + this._DoCallback(this.callbacks.onfinish); + } + else + { + this.RunCycle(); + } + } + + /* Do a pre-specified callback if it exists. */ + this.Preloader.prototype._DoCallback = function(callback, data) + { + if(typeof callback != "undefined") + { + callback(data); + } + } + + /* Handle successful finishing of the SoundManager2 loading process. */ + this.Preloader.prototype._HandleSM2Ready = function() + { + this._engine.sound_enabled = true; + this._ReportResourceFinished(); + } + + /* Handle failure of the SoundManager2 loading process. */ + this.Preloader.prototype._HandleSM2Failed = function() + { + this._engine.sound_enabled = false; + this._ReportResourceFinished(); + } + + /* Mark the currently preloading resource as finished. */ + this.Preloader.prototype._ReportResourceFinished = function() + { + this.resources_left--; + this.resources_done++; + + this._DoCallback(this.callbacks.onprogress, { + done: this.resources_done, + total: this.resources_total, + left: this.resources_left, + failures: this.resources_failed + }); + + this._CheckIfDone(); + } + + /* Mark the currently preloading resource as failed. */ + this.Preloader.prototype._ReportResourceFailed = function() + { + /* TODO: Implement. */ + this.resources_left--; + this.resources_failed++; + } + + + /**--------------------------------------**/ + /** BASE PROPERTIES AND METHODS **/ + /**--------------------------------------**/ + + this.Base = { + timers: {}, + SetTimer: function(duration, func) + { + setTimeout((function(self, f){ return f.call.bind(f, self); })(this, func), duration); + }, + SetInterval: function(name, interval, func) + { + this.timers[name] = setInterval((function(self, f){ return f.call.bind(f, self); })(this, func), interval); + }, + CancelInterval: function(name) + { + clearInterval(this.timers[name]); + }, + CallEvent: function(func, data) + { + if(typeof func !== "undefined") + { + return func.call(this, data); + } + }, + _BubbleEvent: function(func, eventdata, instances) + { + list = instances.slice().reverse(); + + var hit_event = false; + + for(item in list) + { + var object = list[item]; + var result = object.CallEvent(object[func], eventdata); + + if(typeof result != "undefined") + { + if(result == false) + { + break; + } + else if(result == true) + { + hit_event = true; + } + } + } + + return hit_event; + } + } + + + /**--------------------------------------**/ + /** SCENES **/ + /**--------------------------------------**/ + + this.Scene = function(name, options) + { + if(typeof _engine.scenes[name] !== "undefined") + { + throw { + name: "NameError", + message: "A scene with the given name already exists." + } + } + + this._engine = _engine; + this.canvas = null; + this.instances = []; + this.dirty = true; + this.width = 640; + this.height = 480; + this.fps = 45; + this.name = name; + this.cached_selectors = {}; + this.mouse_coordinates = {x: 0, y: 0}; + this.step_counter = 0; + this.draw_counter = 0; + this.current_fps = 0; + this.date = new Date; + + $.extend(true, this, options, this._engine.Base); + + this._engine.scenes[name] = this; + } + + this.Scene.prototype.Add = function(object) + { + if(typeof object == "string") + { + if(typeof this._engine.objects[object] !== "undefined") + { + var instance = this._engine.CreateInstance(object); + } + else + { + throw { + "name": "ObjectError", + "message": "The specified object does not exist." + } + } + } + else + { + var instance = object; + } + + instance.scene = this; + this.instances.push(instance); + this.dirty = true; + } + + this.Scene.prototype.Attach = function(canvas) + { + if(typeof $(canvas).data("current-scene") !== "undefined") + { + /* A different scene was previously attached to this canvas. + * Let's detach it first. */ + var previous_scene = $(canvas).data("current-scene"); + this._engine.scenes[previous_scene].Detach(); + } + + this.canvas = canvas; + this._engine.canvas = canvas; + canvas.width = this.width; + canvas.height = this.height; + $(canvas).data("current-scene", this.name); + + $(canvas).click(this._ProcessClickEvent.bind(this)); + $(canvas).mousemove(this._ProcessMouseMoveEvent.bind(this)); + + this.CallEvent(this.OnLoad); + this._Initialize(); + } + + this.Scene.prototype.Detach = function() + { + $(this.canvas).unbind('click'); + $(this.canvas).unbind('mousemove'); + $(this.canvas).removeData("current-scene"); + this.canvas = null; + } + + this.Scene.prototype.DrawText = function(text, options) + { + var type = "fill", color = "#000000", x = 0, y = 0; + + if(typeof options.outline != "undefined" && options.outline) + { + type = "outline"; + } + + if(typeof options.color != "undefined") + { + color = options.color; + } + + if(typeof options.x != "undefined") + { + x = options.x; + } + + if(typeof options.y != "undefined") + { + y = options.y; + } + + ctx = this._GetTextContext(options); + + if(type == "fill") + { + ctx.fillStyle = color; + ctx.fillText(text, x, y); + } + else if(type == "outline") + { + ctx.strokeStyle = color; + ctx.outlineText(text, x, y); + } + + ctx.restore(); + } + + this.Scene.prototype.DrawTextCentered = function(text, options) + { + var x = 0, scale = 1, width = this.GetTextWidth(text, options); + + if(typeof options.x != "undefined") + { + x = options.x; + } + + if(typeof options.scale != "undefined") + { + scale = options.scale; + } + + x = x - ((width / 2) * scale * scale); + + options.x = x; + + this.DrawText(text, options); + } + + this.Scene.prototype.GetTextWidth = function(text, options) + { + ctx = this._GetTextContext(options); + var width = ctx.measureText(text).width; + ctx.restore(); + + return width; + } + + this.Scene.prototype.Redraw = function() + { + this.dirty = true; + } + + this.Scene.prototype.$ = function(selector) + { + if(typeof this.cached_selectors[selector] != "undefined") + { + return this.cached_selectors[selector]; + } + else + { + list = this._SelectInstances(this, this.instances, selector); + this.cached_selectors[selector] = list; + return list; + } + } + + this.Scene.prototype._Draw = function() + { + this.draw_count += 1; + + if(this.canvas !== null) + { + var ctx = this.canvas.getContext("2d"); + ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); + + for(i in this.instances) + { + this.instances[i]._Draw(); + } + } + } + + this.Scene.prototype._GetTextContext = function(options) + { + var weight = "normal", style = "normal", font = "sans-serif", size = 16, alpha = 1, scale = 1; + + if(typeof options.bold != "undefined" && options.bold) + { + weight = "bold"; + } + + if(typeof options.italic != "undefined" && options.italic) + { + style = "italic"; + } + + if(typeof options.size != "undefined") + { + size = options.size; + } + + if(typeof options.font != "undefined") + { + font = options.font; + } + + if(typeof options.alpha != "undefined") + { + alpha = options.alpha; + } + + if(typeof options.scale != "undefined") + { + scale = options.scale; + } + + var ctx = this.canvas.getContext("2d"); + + ctx.save(); + + ctx.font = weight + " " + style + " " + size + "px '" + font + "'"; + ctx.globalAlpha = alpha; + ctx.scale(scale, scale); + + return ctx; + } + + this.Scene.prototype._Initialize = function(event) + { + this.last_timestamp = this.date.getTime(); + this.SetInterval("_step", (1000/this.fps), this._Step); + } + + this.Scene.prototype._ProcessClickEvent = function(event) + { + var coordinates = this.canvas.relativeCoordinates(event); + + var changed = this._BubbleEvent("_HandleClickEvent", { + x: coordinates.x, + y: coordinates.y, + button: event.which + }, this.$("/" + coordinates.x + "," + coordinates.y)); + + if(changed == true) + { + this.dirty = true; + } + } + + this.Scene.prototype._ProcessMouseMoveEvent = function(event) + { + var coordinates = this.canvas.relativeCoordinates(event); + this.mouse_coordinates = coordinates; + this.mouse_moved = true; + } + + this.Scene.prototype._SelectInstances = function(context, items, selector) + { + var segments = selector.split("/"); + segments.shift(); + + methods = { + "coordinate": { + "regex": /^(!?)([0-9]+),([0-9]+)$/i, + "action": function(context, items, match){ + var inverted = (match[1] == "!"); + var x = match[2]; + var y = match[3]; + + return items.filter(function(object){ + var hit = false; + + if(object.draw_self === true) + { + var sprite = this._engine.GetSprite(object.sprite); + + if(x >= object.x && x < (object.x + sprite.width) && y > object.y && y < (object.y + sprite.height)) + { + /* Initial region test succeeded. + * TODO: Add bounding rectangles. */ + var relative_x = x - object.x; + var relative_y = y - object.y; + + if(object.precise_collision == false) + { + hit = true; + } + else + { + alpha = sprite.GetAlpha(relative_x, relative_y) / 255; + + if(alpha > object.collision_tolerance) + { + /* Alpha hit. */ + hit = true; + } + } + } + } + + if(inverted == true) + { + return !hit; + } + else + { + return hit; + } + }); + } + }, + "object": { + "regex": /^(!?)([a-z_][a-z0-9_+-]*)$/i, + "action": function(context, items, match){ + inverted = (match[1] == "!"); + name = match[2]; + + return items.filter(function(object){ + if(inverted) + { + return !(name == object.name); + } + else + { + return (name == object.name); + } + }); + } + } + } + + for(i in segments) + { + var segment = segments[i]; + + for(m in methods) + { + var method = methods[m]; + var match = method.regex.exec(segment); + + if(match != null) + { + items = method.action(context, items, match); + break; + } + } + } + + return items; + } + + this.Scene.prototype._Step = function(event) + { + this.step_counter++; + + if(this.step_counter == this.fps) + { + this.step_counter = 0; + + var date = new Date; + var current_timestamp = date.getTime() + this.current_fps = (1000 / (current_timestamp - this.last_timestamp)) * this.fps; + this.last_timestamp = current_timestamp; + } + + if(this.mouse_moved == true) + { + this.dirty = this.CallEvent(this.OnMouseMove, this.mouse_coordinates) ? true : this.dirty; + + var select = function(prefix, coordinates) + { + var selector = "/" + prefix + coordinates.x + "," + coordinates.y; + return this.$(selector); + }.bind(this); + + this.dirty = this._BubbleEvent("_HandleMouseOutEvent", this.mouse_coordinates, select("!", this.mouse_coordinates)) ? true : this.dirty; + this.dirty = this._BubbleEvent("_HandleMouseOverEvent", this.mouse_coordinates, select("", this.mouse_coordinates)) ? true : this.dirty; + this.dirty = this._BubbleEvent("_HandleMouseMoveEvent", this.mouse_coordinates, this.$("/")) ? true : this.dirty; + + this.mouse_moved = false; + } + + if(this.CallEvent(this.OnStep, {}) == true) + { + this.dirty = true; + } + + if(this._BubbleEvent("_HandleStepEvent", {}, this.instances) == true) + { + this.dirty = true; + } + + if(this.dirty == true) + { + this.dirty = false; + this.cached_selectors = {}; + this._Draw(); + } + } + + + /**--------------------------------------**/ + /** SOUNDS **/ + /**--------------------------------------**/ + + this.Sound = function(name, source) + { + if(typeof _engine.sounds[name] !== "undefined") + { + throw { + name: "NameError", + message: "A sound with the given name already exists." + } + } + + if(typeof _engine.resources[source] === "undefined") + { + throw { + name: "ResourceError", + message: "The specified resource does not exist." + } + } + + this._engine = _engine; + this.source = this._engine.resources[source]; + this.name = name; + + this._engine.sounds[name] = this; + } + + this.Sound.prototype.Play = function(options) + { + if(this._engine.sound_enabled == true) + { + this.source.play(options); + } + } + + + /**--------------------------------------**/ + /** OBJECTS **/ + /**--------------------------------------**/ + + this.Object = function(name, proto) + { + if(typeof _engine.objects[name] !== "undefined") + { + throw { + name: "NameError", + message: "An object with the given name already exists." + } + } + + /* Base settings */ + this._engine = _engine; + this.name = ""; + + /* Metrics */ + this.x = 0; + this.y = 0; + this.width = 0; + this.height = 0; + this.alpha = 1; + + /* Collision handling */ + this.collision_tolerance = 0.2; + this.precise_collision = false; + + /* Internal variables */ + this.draw_self = (typeof proto.sprite !== "undefined"); + this.scene = null; + this.last_moused_over = false; + + /* Create a constructor for the object. */ + var skeleton = new Function(); + $.extend(true, skeleton.prototype, this, this._engine.Base, proto); + skeleton.prototype.name = name; + + /* Store constructor and return prototype. */ + this._engine.objects[name] = skeleton; + return skeleton.prototype; + } + + this.Object.prototype.CreateInstance = function(vars) + { + return this._engine.CreateInstance(this, vars); + } + + this.Object.prototype.Destroy = function() + { + this.CallEvent(this.OnDestroy); + + if(this.scene != null) + { + var index = this.scene.instances.indexOf(this); + + if(index != -1) + { + this.scene.instances.splice(index, 1); + } + } + } + + this.Object.prototype._Draw = function() + { + if(this.draw_self == true && typeof this.sprite !== "undefined") + { + if(typeof this._engine.sprites[this.sprite] === "undefined") + { + throw { + name: "SpriteError", + message: "The specified sprite does not exist." + } + } + + this._engine.sprites[this.sprite].Draw(this.scene.canvas, this); + } + + this.CallEvent(this.OnDraw, {canvas: this.scene.canvas}); + } + + this.Object.prototype._HandleClickEvent = function(event) + { + var relative_x = event.x - this.x; + var relative_y = event.y - this.y; + + events = { + 1: this.OnClick, + 2: this.OnMiddleClick, + 3: this.OnRightClick + } + + func = events[event.button]; + + this.CallEvent(func, { + x: event.x, + y: event.y, + button: event.button, + relative_x: relative_x, + relative_y: relative_y + }); + + return true; + } + + this.Object.prototype._HandleMouseMoveEvent = function(event) + { + this.CallEvent(this.OnMouseMove, { + x: event.x, + y: event.y + }); + return true; + } + + this.Object.prototype._HandleMouseOutEvent = function(event) + { + if(this.last_moused_over == true) + { + this.last_moused_over = false; + + this.CallEvent(this.OnMouseOut, { + x: event.x, + y: event.y + }); + + return true; + } + } + + this.Object.prototype._HandleMouseOverEvent = function(event) + { + if(this.last_moused_over == false) + { + var relative_x = event.x - this.x; + var relative_y = event.y - this.y; + + this.last_moused_over = true; + + this.CallEvent(this.OnMouseOver, { + x: event.x, + y: event.y, + relative_x: relative_x, + relative_y: relative_y + }); + + return true; + } + } + + this.Object.prototype._HandleStepEvent = function(event) + { + if(typeof this.sprite != "undefined") + { + var sprite = this._engine.sprites[this.sprite]; + this.width = sprite.width; + this.height = sprite.height; + } + + return this.CallEvent(this.OnStep, event); + } + + /**--------------------------------------**/ + /** SPRITES **/ + /**--------------------------------------**/ + + this.Sprite = function(name, source, options) + { + if(typeof _engine.sprites[name] !== "undefined") + { + throw { + name: "NameError", + message: "A sprite with the given name already exists." + } + } + + if(typeof _engine.resources[source] === "undefined") + { + throw { + name: "ResourceError", + message: "The specified resource does not exist." + } + } + + this._engine = _engine; + this.source = this._engine.resources[source]; + this.name = name; + + if(typeof options.tile_x !== "undefined" && typeof options.tile_y !== "undefined" && typeof options.tile_w !== "undefined" && typeof options.tile_h !== "undefined") + { + this.tile_x = options.tile_x; + this.tile_y = options.tile_y; + this.tile_w = options.tile_w; + this.tile_h = options.tile_h; + this.tile = true; + } + else if(typeof options.tile_x !== "undefined" || typeof options.tile_y !== "undefined" || typeof options.tile_w !== "undefined" || typeof options.tile_h !== "undefined") + { + throw { + name: "SpriteError", + message: "Only a part of the tile parameters were specified." + } + } + else + { + this.tile = false; + } + + /* Store image data for click events and collision detection. */ + var collision_canvas = document.createElement("canvas"); + var width, height; + + if(this.tile == false) + { + width = this.source.width; + height = this.source.height; + } + else if(this.tile == true) + { + width = this.tile_w; + height = this.tile_h; + } + + collision_canvas.width = this.width = width; + collision_canvas.height = this.height = height; + + this.Draw(collision_canvas, null, {x: 0, y: 0, alpha: 1}); + + ctx = collision_canvas.getContext("2d"); + this.image_data = ctx.getImageData(0, 0, width, height); + + delete collision_canvas; + + /* Store in engine. */ + this._engine.sprites[name] = this; + } + + this.Sprite.prototype.Draw = function(canvas, object, options) + { + ctx = canvas.getContext("2d"); + + if((typeof object == "undefined" || object == null) && (typeof options == "undefined" || typeof options.x == "undefined" || typeof options.y == "undefined")) + { + throw { + name: "DrawError", + message: "No drawing coordinates were specified." + } + } + else if(typeof object == "undefined" || object == null) + { + var x = options.x; + var y = options.y; + } + else + { + var x = object.x; + var y = object.y; + } + + if(typeof options != "undefined" && typeof options.alpha != "undefined") + { + var alpha = options.alpha; + } + else if(typeof object != "undefined" && object != null) + { + var alpha = object.alpha; + } + else + { + throw { + name: "DrawError", + message: "No alpha value was specified." + } + } + + ctx.globalAlpha = alpha; + + if(this.tile == true) + { + ctx.drawImage(this.source, this.tile_x, this.tile_y, this.tile_w, this.tile_h, x, y, this.tile_w, this.tile_h); + } + else + { + ctx.drawImage(this.source, x, y); + } + } + + this.Sprite.prototype.GetAlpha = function(x, y) + { + var key = (((y * this.width) + x) * 4) + 3; + return this.image_data.data[key]; + } + + /**--------------------------------------**/ + /** ENGINE FUNCTIONS **/ + /**--------------------------------------**/ + + this.AddItems = function(items) + { + if(typeof items.sprites != "undefined") + { + + for(name in items.sprites) + { + if(typeof items.sprites[name] == "string") + { + /* Stand-alone sprite. */ + new _engine.Sprite(name, items.sprites[name], {}); + } + else + { + /* Probably a tileset. */ + new _engine.Sprite(name, items.sprites[name], { + tile_x: items.sprites[name].tile_x, + tile_y: items.sprites[name].tile_y, + tile_w: items.sprites[name].tile_w, + tile_h: items.sprites[name].tile_h, + }); + } + } + } + + if(typeof items.sounds != "undefined") + { + for(name in items.sounds) + { + new _engine.Sound(name, items.sounds[name]); + } + } + + if(typeof items.objects != "undefined") + { + for(name in items.objects) + { + new _engine.Object(name, items.objects[name]); + } + } + + if(typeof items.scenes != "undefined") + { + for(name in items.scenes) + { + new _engine.Scene(name, items.scenes[name]); + } + } + } + + this.CreateInstance = function(object, vars) + { + this.instance_increment++; + + if(typeof data == "undefined") + { + var data = {id: this.instance_increment}; + } + else + { + data.id = this.instance_increment; + } + + if(typeof object == "string") + { + var instance = new this.objects[object](); + } + else + { + var skeleton = new Function(); + skeleton.prototype = object; + var instance = new skeleton(); + } + + $.extend(true, instance, vars); + + /* Call creation event. */ + instance.CallEvent(instance.OnCreate, {}); + + return instance; + } + + this.GetObject = function(name) + { + return this.objects[name].prototype; + } + + this.GetScene = function(name) + { + return this.scenes[name]; + } + + this.GetSound = function(name) + { + return this.sounds[name]; + } + + this.GetSprite = function(name) + { + return this.sprites[name]; + } + + /**--------------------------------------**/ + /** STANDARD LIBRARY **/ + /**--------------------------------------**/ + + this.Math = {}; + + this.Math.Abs = Math.abs; + this.Math.Absolute = Math.abs; + this.Math.Acos = Math.acos; + this.Math.Arccosine = Math.acos; + this.Math.Asin = Math.asin; + this.Math.Arcsine = Math.asin; + this.Math.Atan = Math.atan; + this.Math.Arctangent = Math.atan; + this.Math.Atan2 = Math.atan2; + this.Math.Arctangent2 = Math.atan2; + this.Math.Ceil = Math.ceil; + this.Math.Ceiling = Math.ceil; + this.Math.Cos = Math.cos; + this.Math.Cosine = Math.cos; + this.Math.Exp = Math.exp; + this.Math.Floor = Math.floor; + this.Math.Log = Math.log; + this.Math.Logarithm = Math.log; + this.Math.Min = Math.min; + this.Math.Minimum = Math.min; + this.Math.Max = Math.max; + this.Math.Maximum = Math.max; + this.Math.Pow = Math.pow; + this.Math.Power = Math.pow; + this.Math.Round = Math.round; + this.Math.Sin = Math.sin; + this.Math.Sine = Math.sin; + this.Math.Sqrt = Math.sqrt; + this.Math.SquareRoot = Math.sqrt; + this.Math.Tan = Math.tan; + this.Math.Tangent = Math.tan; + + this.Random = {}; + + this.Random.Choose = function() + { + if(arguments.length == 0) + { + /* The user passed in nothing. Bail out. */ + throw { + name: "ArgumentError", + message: "No arguments were specified." + } + } + else if(arguments.length == 1 && typeof arguments[0].length != "undefined") + { + /* The user passed in an array. */ + arguments = arguments[0]; + } + + return arguments[Math.floor(Math.random() * arguments.length)]; + } + + this.Random.Number = function(floor, ceiling, precision) + { + var floor = (typeof floor == "undefined") ? 0 : floor; + var ceiling = (typeof ceiling == "undefined") ? 1 : ceiling; + var precision = (typeof ceiling == "undefined") ? 0.00000001 : precision; + + var base_number = Math.random(); + var width = Math.abs(ceiling - floor); + var rounding_factor = 1 / precision; + + var multiplied = floor + (base_number * width); + return Math.floor(multiplied * rounding_factor) / rounding_factor; + } + + this.Random.Pick = function() + { + var chosen = []; + var results = []; + var _arguments = Array.prototype.slice.call(arguments); + var count = _arguments.shift(); + + if(arguments.length == 0) + { + /* The user passed in nothing. Bail out. */ + throw { + name: "ArgumentError", + message: "No arguments were specified." + } + } + else if(_arguments.length == 1 && typeof _arguments[0].length != "undefined") + { + /* The user passed in an array. */ + _arguments = _arguments[0]; + } + + if(count > _arguments.length) + { + /* The user requested more items than exist in the arguments. */ + throw { + name: "ArgumentError", + message: "Not enough arguments were specified. The amount of specified items must be equal to or larger than the requested amount." + } + } + + for(var i = 0; i < count; i++) + { + var id = 0; + + do + { + id = Math.floor(Math.random() * _arguments.length); + } while (chosen.indexOf(id) != -1) + + chosen.push(id); + results.push(_arguments[id]); + } + + return results; + } + + this.Random.String = function(length, alphabet) + { + if(typeof alphabet == "undefined") + { + alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + } + + rand = ""; + + for(i = 0; i < length; i++) + { + rand += alphabet[Math.floor(Math.random() * alphabet.length)]; + } + + return rand; + } + + this.Draw = {}; + + this.Draw.Text = function(x, y, text, options) + { + + } + + this.Draw.Rectangle = function(x1, y1, x2, y2, options) + { + + } + + this.Draw.Line = function(x1, y1, x2, y2, options) + { + + } + + this.Draw.BoxEllipse = function(x1, y1, x2, y2, options) + { + var x = (x1 + x2) / 2; + var y = (y1 + y2) / 2; + var rx = (x2 - x1) / 2; + var ry = (y2 - y1) / 2; + + this.RadiusEllipse(x, y, rx, ry, options); + } + + this.Draw.RadiusEllipse = function(x, y, rx, ry, options) + { + var canvas = $("#gamecanvas")[0]; + var ctx = canvas.getContext("2d"); + ctx.beginPath(); + + if(rx == ry) + { + /* Circle. */ + ctx.arc(x, y, rx, 0, 2 * Math.PI, false); + } + else + { + /* Ellipse. */ + var step = 0.1 + + ctx.moveTo(x + rx, y); + + for (var i = 0; i < Math.PI * 2 + step; i += step) + { + ctx.lineTo(x + Math.cos(i) * rx, y + Math.sin(i) * ry); + } + } + + ctx.lineWidth = 1; + ctx.strokeStyle = 'black'; + ctx.stroke(); + } + + this.Draw.BoxPolygon = function(x1, y1, x2, y2, sides, options) + { + + } + + this.Draw.RadiusPolygon = function(x, y, radius, sides, options) + { + + } +} diff --git a/lib/soundmanager2.js b/lib/soundmanager2.js new file mode 100755 index 0000000..1c28af1 --- /dev/null +++ b/lib/soundmanager2.js @@ -0,0 +1,78 @@ +/** @license + * + * SoundManager 2: JavaScript Sound for the Web + * ---------------------------------------------- + * http://schillmania.com/projects/soundmanager2/ + * + * Copyright (c) 2007, Scott Schiller. All rights reserved. + * Code provided under the BSD License: + * http://schillmania.com/projects/soundmanager2/license.txt + * + * V2.97a.20130101 + */ +(function(i,g){function R(R,fa){function S(b){return c.preferFlash&&A&&!c.ignoreFlash&&c.flash[b]!==g&&c.flash[b]}function m(b){return function(c){var d=this._s;return!d||!d._a?null:b.call(this,c)}}this.setupOptions={url:R||null,flashVersion:8,debugMode:!0,debugFlash:!1,useConsole:!0,consoleOnly:!0,waitForWindowLoad:!1,bgColor:"#ffffff",useHighPerformance:!1,flashPollingInterval:null,html5PollingInterval:null,flashLoadTimeout:1E3,wmode:null,allowScriptAccess:"always",useFlashBlock:!1,useHTML5Audio:!0, +html5Test:/^(probably|maybe)$/i,preferFlash:!0,noSWFCache:!1};this.defaultOptions={autoLoad:!1,autoPlay:!1,from:null,loops:1,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onposition:null,onstop:null,onfailure:null,onfinish:null,multiShot:!0,multiShotEvents:!1,position:null,pan:0,stream:!0,to:null,type:null,usePolicyFile:!1,volume:100};this.flash9Options={isMovieStar:null,usePeakData:!1,useWaveformData:!1,useEQData:!1,onbufferchange:null,ondataerror:null}; +this.movieStarOptions={bufferTime:3,serverURL:null,onconnect:null,duration:null};this.audioFormats={mp3:{type:['audio/mpeg; codecs="mp3"',"audio/mpeg","audio/mp3","audio/MPA","audio/mpa-robust"],required:!0},mp4:{related:["aac","m4a","m4b"],type:['audio/mp4; codecs="mp4a.40.2"',"audio/aac","audio/x-m4a","audio/MP4A-LATM","audio/mpeg4-generic"],required:!1},ogg:{type:["audio/ogg; codecs=vorbis"],required:!1},wav:{type:['audio/wav; codecs="1"',"audio/wav","audio/wave","audio/x-wav"],required:!1}};this.movieID= +"sm2-container";this.id=fa||"sm2movie";this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.versionNumber="V2.97a.20130101";this.altURL=this.movieURL=this.version=null;this.enabled=this.swfLoaded=!1;this.oMC=null;this.sounds={};this.soundIDs=[];this.didFlashBlock=this.muted=!1;this.filePattern=null;this.filePatterns={flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.features={buffering:!1,peakData:!1,waveformData:!1,eqData:!1,movieStar:!1};this.sandbox={};this.html5={usingFlash:null}; +this.flash={};this.ignoreFlash=this.html5Only=!1;var Ga,c=this,Ha=null,h=null,T,q=navigator.userAgent,ga=i.location.href.toString(),l=document,ha,Ia,ia,k,r=[],J=!1,K=!1,j=!1,s=!1,ja=!1,L,t,ka,U,la,B,C,D,Ja,ma,V,na,W,oa,E,pa,M,qa,X,F,Ka,ra,La,sa,Ma,N=null,ta=null,v,ua,G,Y,Z,H,p,O=!1,va=!1,Na,Oa,Pa,$=0,P=null,aa,Qa=[],u=null,Ra,ba,Q,y,wa,xa,Sa,n,db=Array.prototype.slice,w=!1,ya,A,za,Ta,x,ca=q.match(/(ipad|iphone|ipod)/i),Ua=q.match(/android/i),z=q.match(/msie/i),eb=q.match(/webkit/i),Aa=q.match(/safari/i)&& +!q.match(/chrome/i),Ba=q.match(/opera/i),Ca=q.match(/(mobile|pre\/|xoom)/i)||ca||Ua,Va=!ga.match(/usehtml5audio/i)&&!ga.match(/sm2\-ignorebadua/i)&&Aa&&!q.match(/silk/i)&&q.match(/OS X 10_6_([3-7])/i),Da=l.hasFocus!==g?l.hasFocus():null,da=Aa&&(l.hasFocus===g||!l.hasFocus()),Wa=!da,Xa=/(mp3|mp4|mpa|m4a|m4b)/i,Ea=l.location?l.location.protocol.match(/http/i):null,Ya=!Ea?"http://":"",Za=/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,$a="mpeg4 aac flv mov mp4 m4v f4v m4a m4b mp4v 3gp 3g2".split(" "), +fb=RegExp("\\.("+$a.join("|")+")(\\?.*)?$","i");this.mimePattern=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.useAltURL=!Ea;var Fa;try{Fa=Audio!==g&&(Ba&&opera!==g&&10>opera.version()?new Audio(null):new Audio).canPlayType!==g}catch(hb){Fa=!1}this.hasHTML5=Fa;this.setup=function(b){var e=!c.url;b!==g&&(j&&u&&c.ok()&&(b.flashVersion!==g||b.url!==g||b.html5Test!==g))&&H(v("setupLate"));ka(b);e&&(M&&b.url!==g)&&c.beginDelayedInit();!M&&(b.url!==g&&"complete"===l.readyState)&&setTimeout(E,1);return c}; +this.supported=this.ok=function(){return u?j&&!s:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(b){return T(b)||l[b]||i[b]};this.createSound=function(b,e){function d(){a=Y(a);c.sounds[a.id]=new Ga(a);c.soundIDs.push(a.id);return c.sounds[a.id]}var a,f=null;if(!j||!c.ok())return H(void 0),!1;e!==g&&(b={id:b,url:e});a=t(b);a.url=aa(a.url);if(p(a.id,!0))return c.sounds[a.id];ba(a)?(f=d(),f._setup_html5(a)):(8=b)return!1;for(b-=1;0<=b;b--)c=j[b],!c.fired&&a.position>=c.position&&(c.fired=!0,n++,c.method.apply(c.scope,[c.position]));return!0};this._resetOnPosition=function(a){var b,c;b=j.length;if(!b)return!1;for(b-=1;0<=b;b--)c=j[b],c.fired&&a<=c.position&&(c.fired=!1,n--);return!0};u=function(){var b=a._iO,c=b.from,e=b.to,d,f;f=function(){a.clearOnPosition(e,f);a.stop()};d=function(){if(null!==e&&!isNaN(e))a.onPosition(e, +f)};null!==c&&!isNaN(c)&&(b.position=c,b.multiShot=!1,d());return b};m=function(){var b,c=a._iO.onposition;if(c)for(b in c)if(c.hasOwnProperty(b))a.onPosition(parseInt(b,10),c[b])};s=function(){var b,c=a._iO.onposition;if(c)for(b in c)c.hasOwnProperty(b)&&a.clearOnPosition(parseInt(b,10))};l=function(){a.isHTML5&&Na(a)};I=function(){a.isHTML5&&Oa(a)};f=function(b){b||(j=[],n=0);q=!1;a._hasTimer=null;a._a=null;a._html5_canplay=!1;a.bytesLoaded=null;a.bytesTotal=null;a.duration=a._iO&&a._iO.duration? +a._iO.duration:null;a.durationEstimate=null;a.buffered=[];a.eqData=[];a.eqData.left=[];a.eqData.right=[];a.failures=0;a.isBuffering=!1;a.instanceOptions={};a.instanceCount=0;a.loaded=!1;a.metadata={};a.readyState=0;a.muted=!1;a.paused=!1;a.peakData={left:0,right:0};a.waveformData={left:[],right:[]};a.playState=0;a.position=null;a.id3={}};f();this._onTimer=function(b){var c,f=!1,g={};if(a._hasTimer||b){if(a._a&&(b||(0opera.version()?new Audio(null):new Audio,e=a._a,e._called_load=!1,w&&(Ha=e);a.isHTML5=!0;a._a=e;e._s=a;ab();a._apply_loop(e,b.loops);b.autoLoad||b.autoPlay?a.load():(e.autobuffer=!1,e.preload="auto");return e};ab=function(){if(a._a._added_events)return!1;var b;a._a._added_events=!0;for(b in x)x.hasOwnProperty(b)&& +a._a&&a._a.addEventListener(b,x[b],!1);return!0};i=function(){var b;a._a._added_events=!1;for(b in x)x.hasOwnProperty(b)&&a._a&&a._a.removeEventListener(b,x[b],!1)};this._onload=function(b){b=!!b||!a.isHTML5&&8===k&&a.duration;a.loaded=b;a.readyState=b?3:2;a._onbufferchange(0);a._iO.onload&&a._iO.onload.apply(a,[b]);return!0};this._onbufferchange=function(b){if(0===a.playState||b&&a.isBuffering||!b&&!a.isBuffering)return!1;a.isBuffering=1===b;a._iO.onbufferchange&&a._iO.onbufferchange.apply(a);return!0}; +this._onsuspend=function(){a._iO.onsuspend&&a._iO.onsuspend.apply(a);return!0};this._onfailure=function(b,c,e){a.failures++;if(a._iO.onfailure&&1===a.failures)a._iO.onfailure(a,b,c,e)};this._onfinish=function(){var b=a._iO.onfinish;a._onbufferchange(0);a._resetOnPosition(0);a.instanceCount&&(a.instanceCount--,a.instanceCount||(s(),a.playState=0,a.paused=!1,a.instanceCount=0,a.instanceOptions={},a._iO={},I(),a.isHTML5&&(a.position=0)),(!a.instanceCount||a._iO.multiShotEvents)&&b&&b.apply(a))};this._whileloading= +function(b,c,e,d){var f=a._iO;a.bytesLoaded=b;a.bytesTotal=c;a.duration=Math.floor(e);a.bufferLength=d;a.durationEstimate=!a.isHTML5&&!f.isMovieStar?f.duration?a.duration>f.duration?a.duration:f.duration:parseInt(a.bytesTotal/a.bytesLoaded*a.duration,10):a.duration;a.isHTML5||(a.buffered=[{start:0,end:a.duration}]);(3!==a.readyState||a.isHTML5)&&f.whileloading&&f.whileloading.apply(a)};this._whileplaying=function(b,c,e,d,f){var h=a._iO;if(isNaN(b)||null===b)return!1;a.position=Math.max(0,b);a._processOnPosition(); +!a.isHTML5&&8opera.version()?new Audio(null):new Audio:null,d,a,f={},h;h=c.audioFormats;for(d in h)if(h.hasOwnProperty(d)&&(a="audio/"+d,f[d]=b(h[d].type),f[a]=f[d],d.match(Xa)?(c.flash[d]=!0,c.flash[a]= +!0):(c.flash[d]=!1,c.flash[a]=!1),h[d]&&h[d].related))for(a=h[d].related.length-1;0<=a;a--)f["audio/"+h[d].related[a]]=f[d],c.html5[h[d].related[a]]=f[d],c.flash[h[d].related[a]]=f[d];f.canPlayType=e?b:null;c.html5=t(c.html5,f);return!0};na={};v=function(){};Y=function(b){8===k&&(1k)&&(c.flashVersion=k=9);c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":9===k?" (AS3/Flash 9)":" (AS2/Flash 8)");8'}if(J&&K)return!1;if(c.html5Only)return ma(),c.oMC=T(c.movieID),ia(),K=J=!0,!1;var a=e||c.url,f=c.altURL||a,h=qa(),i=G(),k=null,k=l.getElementsByTagName("html")[0],j,n,m,k=k&&k.dir&&k.dir.match(/rtl/i),b=b===g?c.id:b;ma();c.url=Ma(Ea?a:f);e=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;if(null!==c.wmode&&(q.match(/msie 8/i)||!z&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i))Qa.push(na.spcWmode), +c.wmode=null;h={name:b,id:b,src:e,quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:Ya+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};c.debugFlash&&(h.FlashVars="debug=1");c.wmode||delete h.wmode;if(z)a=l.createElement("div"),n=['',d("movie",e),d("AllowScriptAccess",c.allowScriptAccess),d("quality",h.quality),c.wmode?d("wmode",c.wmode):"",d("bgcolor",c.bgColor),d("hasPriority","true"),c.debugFlash?d("FlashVars",h.FlashVars):"",""].join("");else for(j in a=l.createElement("embed"),h)h.hasOwnProperty(j)&&a.setAttribute(j,h[j]);ra();i=G();if(h=qa())if(c.oMC=T(c.movieID)||l.createElement("div"),c.oMC.id)m=c.oMC.className,c.oMC.className= +(m?m+" ":"movieContainer")+(i?" "+i:""),c.oMC.appendChild(a),z&&(j=c.oMC.appendChild(l.createElement("div")),j.className="sm2-object-box",j.innerHTML=n),K=!0;else{c.oMC.id=c.movieID;c.oMC.className="movieContainer "+i;j=i=null;c.useFlashBlock||(c.useHighPerformance?i={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"}:(i={position:"absolute",width:"6px",height:"6px",top:"-9999px",left:"-9999px"},k&&(i.left=Math.abs(parseInt(i.left,10))+"px")));eb&&(c.oMC.style.zIndex= +1E4);if(!c.debugFlash)for(m in i)i.hasOwnProperty(m)&&(c.oMC.style[m]=i[m]);try{z||c.oMC.appendChild(a),h.appendChild(c.oMC),z&&(j=c.oMC.appendChild(l.createElement("div")),j.className="sm2-object-box",j.innerHTML=n),K=!0}catch(p){throw Error(v("domError")+" \n"+p.toString());}}return J=!0};W=function(){if(c.html5Only)return X(),!1;if(h||!c.url)return!1;h=c.getMovie(c.id);h||(N?(z?c.oMC.innerHTML=ta:c.oMC.appendChild(N),N=null,J=!0):X(c.id,c.url),h=c.getMovie(c.id));"function"===typeof c.oninitmovie&& +setTimeout(c.oninitmovie,1);return!0};D=function(){setTimeout(Ja,1E3)};Ja=function(){var b,e=!1;if(!c.url||O)return!1;O=!0;n.remove(i,"load",D);if(da&&!Da)return!1;j||(b=c.getMoviePercent(),0b&&(e=!0));setTimeout(function(){b=c.getMoviePercent();if(e)return O=!1,i.setTimeout(D,1),!1;!j&&Wa&&(null===b?c.useFlashBlock||0===c.flashLoadTimeout?c.useFlashBlock&&ua():B({type:"ontimeout",ignoreInit:!0}):0!==c.flashLoadTimeout&&sa(!0))},c.flashLoadTimeout)};V=function(){if(Da||!da)return n.remove(i, +"focus",V),!0;Da=Wa=!0;O=!1;D();n.remove(i,"focus",V);return!0};L=function(b){if(j)return!1;if(c.html5Only)return j=!0,C(),!0;var e=!0,d;if(!c.useFlashBlock||!c.flashLoadTimeout||c.getMoviePercent())j=!0,s&&(d={type:!A&&u?"NO_FLASH":"INIT_TIMEOUT"});if(s||b)c.useFlashBlock&&c.oMC&&(c.oMC.className=G()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error")),B({type:"ontimeout",error:d,ignoreInit:!0}),F(d),e=!1;s||(c.waitForWindowLoad&&!ja?n.add(i,"load",C):C());return e};Ia=function(){var b,e= +c.setupOptions;for(b in e)e.hasOwnProperty(b)&&(c[b]===g?c[b]=e[b]:c[b]!==e[b]&&(c.setupOptions[b]=c[b]))};ia=function(){if(j)return!1;if(c.html5Only)return j||(n.remove(i,"load",c.beginDelayedInit),c.enabled=!0,L()),!0;W();try{h._externalInterfaceTest(!1),Ka(!0,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||h._disableDebug(),c.enabled=!0,c.html5Only||n.add(i,"unload",ha)}catch(b){return F({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),sa(!0),L(),!1}L();n.remove(i,"load",c.beginDelayedInit); +return!0};E=function(){if(M)return!1;M=!0;Ia();ra();!A&&c.hasHTML5&&c.setup({useHTML5Audio:!0,preferFlash:!1});Sa();c.html5.usingFlash=Ra();u=c.html5.usingFlash;!A&&u&&(Qa.push(na.needFlash),c.setup({flashLoadTimeout:1}));l.removeEventListener&&l.removeEventListener("DOMContentLoaded",E,!1);W();return!0};xa=function(){"complete"===l.readyState&&(E(),l.detachEvent("onreadystatechange",xa));return!0};pa=function(){ja=!0;n.remove(i,"load",pa)};oa=function(){if(Ca&&(c.setupOptions.useHTML5Audio=!0,c.setupOptions.preferFlash= +!1,ca||Ua&&!q.match(/android\s2\.3/i)))ca&&(c.ignoreFlash=!0),w=!0};oa();za();n.add(i,"focus",V);n.add(i,"load",D);n.add(i,"load",pa);l.addEventListener?l.addEventListener("DOMContentLoaded",E,!1):l.attachEvent?l.attachEvent("onreadystatechange",xa):F({type:"NO_DOM2_EVENTS",fatal:!0})}var fa=null;if(void 0===i.SM2_DEFER||!SM2_DEFER)fa=new R;i.SoundManager=R;i.soundManager=fa})(window); \ No newline at end of file diff --git a/lib/soundmanager2.swf b/lib/soundmanager2.swf new file mode 100755 index 0000000..b62fa6e Binary files /dev/null and b/lib/soundmanager2.swf differ diff --git a/lib/soundmanager2_debug.swf b/lib/soundmanager2_debug.swf new file mode 100755 index 0000000..3539251 Binary files /dev/null and b/lib/soundmanager2_debug.swf differ diff --git a/map_isometric.js b/map_isometric.js deleted file mode 100644 index 2b68fe0..0000000 --- a/map_isometric.js +++ /dev/null @@ -1,240 +0,0 @@ -if(RadiumEngine !== undefined) -{ - /*Class*/ RadiumEngine.prototype.IsometricMap = function(canvas) - { - this.tile_width = 32; - this.tile_height = 64; - this.width = 6; - this.height = 6; - this.mouse_tile = undefined; - this.mouse_over = false; - this.mouse_in = false; - this.fill_screen = false; - - this.canvas = canvas - this.context = canvas.getContext("2d"); - - $(this.canvas).bind('mouseenter', {'self': this}, function(event){ - self.mouse_over = true; - }); - - $(this.canvas).bind('mouseleave', {'self': this}, function(event){ - self.mouse_over = false; - }); - - $(this.canvas).bind('mousemove', {'self': this}, function(event){ - self = event.data.self; - - var rect = self.canvas.getBoundingClientRect(); - var root = document.documentElement; - var mouse_x = event.clientX - rect.top - root.scrollTop; - var mouse_y = event.clientY - rect.left - root.scrollLeft; - var coords = event.data.self.TileFromPosition(mouse_x, mouse_y); - - self.mouse_tile = coords; - - if(coords.x >= 0 && coords.x < self.width && coords.y >= 0 && coords.y < self.height) - { - self.mouse_in = true; - } - else - { - self.mouse_in = false; - } - - self.Redraw(); - }); - - var Configure = this.Configure = function(tile_width, tile_height) - { - this.tile_width = tile_width; - this.tile_height = tile_height; - } - - this.SetFill = function(enabled) - { - if(enabled === true) - { - $(this.canvas).css({ - 'position': "absolute", - 'left': "0px", - 'top': "0px" - }); - - $('body').css({ - 'overflow': "hidden" - }); - } - - this.fill_screen = enabled; - this.UpdateSize(); - } - - this.UpdateSize = function() - { - if(this.fill_screen === false) - { - this.canvas.width = $(this.canvas).width(); - this.canvas.height = $(this.canvas).height(); - } - else - { - this.canvas.width = window.innerWidth; - this.canvas.height = window.innerHeight; - - $(this.canvas).css({ - 'width': window.innerWidth + "px", - 'height': window.innerHeight + "px" - }); - } - } - - var Redraw = this.Redraw = function() - { - this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); - - for(var i = 0; i < this.height; i++) - { - for(var r = 0; r < this.width; r++) - { - this.DrawTile(r, i); - /*pos = this.GetTilePosition(r, i); - this.context.fillRect(pos.x, pos.y, 1, 1);*/ - } - } - } - - this.DrawTile = function(tile_x, tile_y) - { - var pos_x = tile_x * this.tile_width; - var pos_y = tile_y * this.tile_height; - - var t1 = this.GetTileOrigin(tile_x, tile_y); - var t2 = t1.Add(new RadiumEngine.Point(this.tile_width / 2, this.tile_height / 2)); - var t3 = t1.Add(new RadiumEngine.Point(0, this.tile_height)); - var t4 = t1.Add(new RadiumEngine.Point(0 - (this.tile_width / 2), this.tile_height / 2)); - - this.context.beginPath(); - - this.context.moveTo(t1.x, t1.y); - this.context.lineTo(t2.x, t2.y); - this.context.lineTo(t3.x, t3.y); - this.context.lineTo(t4.x, t4.y); - this.context.lineTo(t1.x, t1.y); - - switch(tile_y) - { - case 0: - this.context.lineWidth = 1; - break; - case 1: - this.context.lineWidth = 2; - break; - case 2: - this.context.lineWidth = 3; - break; - case 3: - this.context.lineWidth = 4; - break; - case 4: - this.context.lineWidth = 5; - break; - case 5: - this.context.lineWidth = 6; - break; - } - - switch(tile_x) - { - case 0: - this.context.strokeStyle = "blue"; - break; - case 1: - this.context.strokeStyle = "purple"; - break; - case 2: - this.context.strokeStyle = "green"; - break; - case 3: - this.context.strokeStyle = "red"; - break; - case 4: - this.context.strokeStyle = "maroon"; - break; - case 5: - this.context.strokeStyle = "black"; - break; - } - - if(this.mouse_tile !== undefined && tile_x == this.mouse_tile.x && tile_y == this.mouse_tile.y) - { - this.context.fillStyle = "#D9FFB4"; - this.context.fill(); - } - - this.context.stroke(); - } - - this.GetBasePoint = function() - { - return new RadiumEngine.Point((this.width * this.tile_width) / 2, 0); - } - - this.GetTileOrigin = function(tile_x, tile_y) - { - /* Determine base point (0,0) of the isometric diamond. */ - base_point = this.GetBasePoint(); - - /* Determine offset for determining starting point for the current row (tile_y coordinate). */ - row_offset = new RadiumEngine.Point(0 - ((this.tile_width / 2) * tile_y), (this.tile_height / 2) * tile_y); - - /* Determine specific offset of the specified tile_x coordinate on the tile_y row. */ - tile_offset = new RadiumEngine.Point((this.tile_width / 2) * tile_x, (this.tile_height / 2) * tile_x); - - /* Return the sum of the above to determine the actual tile position on the canvas. */ - return base_point.Add(row_offset, tile_offset); - } - - this.GetTilePosition = function(tile_x, tile_y) - { - origin = this.GetTileOrigin(tile_x, tile_y); - - return origin.Add(new RadiumEngine.Point(0 - (this.tile_width / 2), 0)); - } - - this.GetRangePosition = function(start, size) - { - x = this.GetTilePosition(start.x, start.y + size.y - 1).x; - y = this.GetTilePosition(start.x, start.y).y; - - return new RadiumEngine.Point(x, y); - } - - this.TileFromPosition = function(x, y) - { - p = new RadiumEngine.Point(x, y); - a = self.GetBasePoint(); - b = a.Add(new RadiumEngine.Point(0 - (this.tile_width / 2), this.tile_height / 2)); - c = a.Add(new RadiumEngine.Point(this.tile_width / 2, this.tile_height / 2)); - - /* Compute vectors. */ - v0 = c.Subtract(a); - v1 = b.Subtract(a); - v2 = p.Subtract(a); - - /* Compute dot products. */ - dot00 = RadiumEngine.dot_product([v0.x, v0.y], [v0.x, v0.y]); - dot01 = RadiumEngine.dot_product([v0.x, v0.y], [v1.x, v1.y]); - dot02 = RadiumEngine.dot_product([v0.x, v0.y], [v2.x, v2.y]); - dot11 = RadiumEngine.dot_product([v1.x, v1.y], [v1.x, v1.y]); - dot12 = RadiumEngine.dot_product([v1.x, v1.y], [v2.x, v2.y]); - - /* Compute tile. */ - inv_denom = 1 / (dot00 * dot11 - dot01 * dot01); - tile_x = (dot11 * dot02 - dot01 * dot12) * inv_denom; - tile_y = (dot00 * dot12 - dot01 * dot02) * inv_denom; - - return new RadiumEngine.Point(Math.floor(tile_x), Math.floor(tile_y)); - } - } -}