Merge branch 'LLK/master'
This commit is contained in:
commit
ba40cd3396
24 changed files with 764 additions and 698 deletions
|
@ -1,9 +1,16 @@
|
||||||
Scratch HTML5 Player
|
# Scratch HTML5 Player
|
||||||
|
|
||||||
This project aims to create a Scratch Player in HTML5. Scratch is currently implemented with Actionscript 3 and requires the Flash Player version 10.2. Since Flash does not run on iOS (iPads, iPods, etc) and newer Android devices, we would like to have an HTML5 version to display (but not edit) projects on mobile devices. Scratch projects played in the HTML5 player should look and behave as closely as possible to the way they look and behave when played by the Flash player. We will not be accepting pull requests for new features that don't already exist in the Flash based Scratch project player.
|
This project aims to create a Scratch Player in HTML5. Scratch is currently implemented with Actionscript 3 and requires the Flash Player version 10.2. Since Flash does not run on iOS (iPads, iPods, etc) and newer Android devices, we would like to have an HTML5 version to display (but not edit) projects on mobile devices. Scratch projects played in the HTML5 player should look and behave as closely as possible to the way they look and behave when played by the Flash player. We will not be accepting pull requests for new features that don't already exist in the Flash based Scratch project player.
|
||||||
|
|
||||||
There are a few github issues created that represent some of the missing features. At this point, the HTML5 player is about 40% complete and can run some simple projects. Running the HTML5 player on your own website, or locally, you will need to have PHP so that the proxy.php file can be used to load assets from the same domain. This is done to be compatible with Javascript security models in today's browsers. To test the HTML5 player against the Flash player you can use the compare.html web page.
|
There are a few github issues created that represent some of the missing features. At this point, the HTML5 player is about 40% complete and can run some simple projects.
|
||||||
|
|
||||||
Unimplementable Features on iOS: Image effects for whirl, fisheye, mosaic, and pixelate. Sound and video input for loudness, video motion, and touching colors from the video.
|
Unimplementable Features on iOS: Image effects for whirl, fisheye, mosaic, and pixelate. Sound and video input for loudness, video motion, and touching colors from the video.
|
||||||
|
|
||||||
More documentation will be added as time permits. Thanks for contributing, and Scratch On!
|
More documentation will be added as time permits. Thanks for contributing, and Scratch On!
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Running the HTML5 player on your own website, or locally, you will need to have
|
||||||
|
PHP so that the `proxy.php` file can be used to load assets from the same domain. This is done to be compatible with Javascript security models in today's browsers. To test the HTML5 player against the Flash player you can use the compare.html web page.
|
||||||
|
|
||||||
|
See the file `TESTING.md` for more details.
|
45
TESTING.md
Normal file
45
TESTING.md
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
Running the HTML5 player on your own website, or locally, you will need to have
|
||||||
|
PHP so that the `proxy.php` file can be used to load assets from the same domain. This is done to be compatible with Javascript security models in today's browsers. To test the HTML5 player against the Flash player you can use the compare.html web page.
|
||||||
|
|
||||||
|
# Ubuntu
|
||||||
|
|
||||||
|
If you're using Ubuntu, you can follow the following steps to set up the proxy correctly. You'll need to type the following commands in Terminal.
|
||||||
|
|
||||||
|
Install PHP and Apache for running the proxy file:
|
||||||
|
|
||||||
|
$ sudo apt-get install apache2 php5
|
||||||
|
|
||||||
|
Fork this repository on Github, and then clone it into your home folder somewhere (replacing `<username>` with your Github username):
|
||||||
|
|
||||||
|
$ git clone https://github.com/<username>/scratch-html5
|
||||||
|
|
||||||
|
We'd like to add a new localhost domain, so that we can access the player from our web browser. Something like `scratch.localhost`. Run this command to edit the `/etc/hosts` file:
|
||||||
|
|
||||||
|
$ sudo nano /etc/hosts
|
||||||
|
|
||||||
|
Add the following line:
|
||||||
|
|
||||||
|
127.0.0.1 scratch.localhost
|
||||||
|
|
||||||
|
Use <key>Ctrl-O</key>, <key>Return</key>, <key>Ctrl-X</key> to quit.
|
||||||
|
|
||||||
|
Now we want to add a new Apache configuration for the new domain. Run the following:
|
||||||
|
|
||||||
|
$ cd /etc/apache2/sites-available/
|
||||||
|
$ sudo nano scratch
|
||||||
|
|
||||||
|
And type in the following, replacing `user` with your username, and making sure the `DocumentRoot` matches where you cloned the repository earlier:
|
||||||
|
|
||||||
|
<VirtualHost *:80>
|
||||||
|
ServerName scratch.localhost
|
||||||
|
DocumentRoot /home/user/scratch-html5
|
||||||
|
</VirtualHost>
|
||||||
|
|
||||||
|
Finally, run the following commands to enable the site:
|
||||||
|
|
||||||
|
$ sudo a2ensite scratch
|
||||||
|
$ sudo service apache2 reload
|
||||||
|
|
||||||
|
Now when you go to <http://scratch.localhost/>, the project should play. If you get a "Forbidden" error message, you may need to check the permissions of the folders that the player code is in.
|
||||||
|
|
||||||
|
Now you can go fix bugs in the HTML5 player!
|
|
@ -55,14 +55,16 @@ header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
|
||||||
};
|
};
|
||||||
|
|
||||||
// Pass in the cloud token for the project
|
// Pass in the cloud token for the project
|
||||||
if(window.getCloudToken)
|
if (window.getCloudToken) {
|
||||||
flashvars.cloud_token = encodeURIComponent(getCloudToken());
|
flashvars.cloud_token = encodeURIComponent(getCloudToken());
|
||||||
|
}
|
||||||
|
|
||||||
var params = {
|
var params = {
|
||||||
allowscriptaccess: 'always',
|
allowscriptaccess: 'always',
|
||||||
allowfullscreen: 'false',
|
allowfullscreen: 'false',
|
||||||
wmode: 'direct',
|
wmode: 'direct',
|
||||||
menu: 'false'};
|
menu: 'false'
|
||||||
|
};
|
||||||
|
|
||||||
var flashPlayer = null;
|
var flashPlayer = null;
|
||||||
//var swf_url = "http://cdn.scratch.mit.edu/scratchr2/static/Scratch.swf";
|
//var swf_url = "http://cdn.scratch.mit.edu/scratchr2/static/Scratch.swf";
|
||||||
|
@ -71,7 +73,7 @@ header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
|
||||||
"http://cdn.scratch.mit.edu/scratchr2/static/expressInstall.swf",
|
"http://cdn.scratch.mit.edu/scratchr2/static/expressInstall.swf",
|
||||||
flashvars, params, null, function(e) {
|
flashvars, params, null, function(e) {
|
||||||
$('#flashScratch').css('visibility', 'visible');
|
$('#flashScratch').css('visibility', 'visible');
|
||||||
if(e.success) flashPlayer = e.ref;
|
if (e.success) flashPlayer = e.ref;
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#trigger_green_flag, #greenSlide').click(function() {
|
$('#trigger_green_flag, #greenSlide').click(function() {
|
||||||
|
@ -104,7 +106,6 @@ header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="info">Loading...</div>
|
<div id="info">Loading...</div>
|
||||||
|
|
||||||
<button id="trigger_green_flag">Green flag</button>
|
<button id="trigger_green_flag">Green flag</button>
|
||||||
|
|
25
js/IO.js
25
js/IO.js
|
@ -33,20 +33,18 @@ var IO = function() {
|
||||||
this.asset_suffix = '/get/';
|
this.asset_suffix = '/get/';
|
||||||
this.soundbank_base = 'soundbank/';
|
this.soundbank_base = 'soundbank/';
|
||||||
this.spriteLayerCount = 0;
|
this.spriteLayerCount = 0;
|
||||||
}
|
};
|
||||||
|
|
||||||
IO.prototype.loadProject = function(project_id) {
|
IO.prototype.loadProject = function(project_id) {
|
||||||
var runningIO = this;
|
var runningIO = this;
|
||||||
$.getJSON(this.project_base + project_id + this.project_suffix,
|
$.getJSON(this.project_base + project_id + this.project_suffix, function(data) {
|
||||||
function(data) {
|
|
||||||
runningIO.data = data;
|
runningIO.data = data;
|
||||||
runningIO.makeObjects();
|
runningIO.makeObjects();
|
||||||
runningIO.loadThreads();
|
runningIO.loadThreads();
|
||||||
runningIO.loadNotesDrums();
|
runningIO.loadNotesDrums();
|
||||||
runtime.loadStart(); // Try to run the project.
|
runtime.loadStart(); // Try to run the project.
|
||||||
}
|
});
|
||||||
);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
IO.prototype.soundRequest = function(sound, sprite) {
|
IO.prototype.soundRequest = function(sound, sprite) {
|
||||||
var request = new XMLHttpRequest();
|
var request = new XMLHttpRequest();
|
||||||
|
@ -63,9 +61,9 @@ IO.prototype.soundRequest = function(sound, sprite) {
|
||||||
data[i] = samples[i];
|
data[i] = samples[i];
|
||||||
}
|
}
|
||||||
sprite.soundsLoaded++;
|
sprite.soundsLoaded++;
|
||||||
}
|
};
|
||||||
request.send();
|
request.send();
|
||||||
}
|
};
|
||||||
|
|
||||||
IO.prototype.loadNotesDrums = function() {
|
IO.prototype.loadNotesDrums = function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -81,10 +79,10 @@ IO.prototype.loadNotesDrums = function() {
|
||||||
var soundBuffer = waveData.readBytes(2 * info.sampleCount);
|
var soundBuffer = waveData.readBytes(2 * info.sampleCount);
|
||||||
Instr.samples[name] = soundBuffer;
|
Instr.samples[name] = soundBuffer;
|
||||||
Instr.wavsLoaded++;
|
Instr.wavsLoaded++;
|
||||||
}
|
};
|
||||||
request.send();
|
request.send();
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
IO.prototype.makeObjects = function() {
|
IO.prototype.makeObjects = function() {
|
||||||
// Create the stage
|
// Create the stage
|
||||||
|
@ -92,7 +90,6 @@ IO.prototype.makeObjects = function() {
|
||||||
runtime.stage.attach(runtime.scene);
|
runtime.stage.attach(runtime.scene);
|
||||||
runtime.stage.attachPenLayer(runtime.scene);
|
runtime.stage.attachPenLayer(runtime.scene);
|
||||||
runtime.stage.loadSounds();
|
runtime.stage.loadSounds();
|
||||||
|
|
||||||
// Create the sprites and watchers
|
// Create the sprites and watchers
|
||||||
$.each(this.data.children.concat(this.data.lists), function i(index, obj) {
|
$.each(this.data.children.concat(this.data.lists), function i(index, obj) {
|
||||||
var newSprite;
|
var newSprite;
|
||||||
|
@ -111,7 +108,7 @@ IO.prototype.makeObjects = function() {
|
||||||
if (!obj.cmd && !obj.listName)
|
if (!obj.cmd && !obj.listName)
|
||||||
newSprite.loadSounds();
|
newSprite.loadSounds();
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
IO.prototype.loadThreads = function() {
|
IO.prototype.loadThreads = function() {
|
||||||
var target = runtime.stage;
|
var target = runtime.stage;
|
||||||
|
@ -129,7 +126,7 @@ IO.prototype.loadThreads = function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// Returns the number sprite we are rendering
|
// Returns the number sprite we are rendering
|
||||||
// used for initial layering assignment
|
// used for initial layering assignment
|
||||||
|
@ -137,4 +134,4 @@ IO.prototype.getCount = function() {
|
||||||
var rv = this.spriteLayerCount;
|
var rv = this.spriteLayerCount;
|
||||||
this.spriteLayerCount++;
|
this.spriteLayerCount++;
|
||||||
return rv;
|
return rv;
|
||||||
}
|
};
|
||||||
|
|
|
@ -30,7 +30,7 @@ var Block = function(opAndArgs, optionalSubstack) {
|
||||||
this.nextBlock = null;
|
this.nextBlock = null;
|
||||||
this.tmp = -1;
|
this.tmp = -1;
|
||||||
interp.fixArgs(this);
|
interp.fixArgs(this);
|
||||||
}
|
};
|
||||||
|
|
||||||
var Thread = function(block, target) {
|
var Thread = function(block, target) {
|
||||||
this.nextBlock = block; // next block to run; null when thread is finished
|
this.nextBlock = block; // next block to run; null when thread is finished
|
||||||
|
@ -40,7 +40,7 @@ var Thread = function(block, target) {
|
||||||
this.tmp = null; // used for thread operations like Timer
|
this.tmp = null; // used for thread operations like Timer
|
||||||
this.tmpObj = []; // used for Sprite operations like glide
|
this.tmpObj = []; // used for Sprite operations like glide
|
||||||
this.firstTime = true;
|
this.firstTime = true;
|
||||||
}
|
};
|
||||||
|
|
||||||
var Interpreter = function() {
|
var Interpreter = function() {
|
||||||
// Interpreter state
|
// Interpreter state
|
||||||
|
@ -54,7 +54,7 @@ var Interpreter = function() {
|
||||||
this.yield = false;
|
this.yield = false;
|
||||||
this.doRedraw = false;
|
this.doRedraw = false;
|
||||||
this.opCount = 0; // used to benchmark the interpreter
|
this.opCount = 0; // used to benchmark the interpreter
|
||||||
}
|
};
|
||||||
|
|
||||||
// Utilities for building blocks and sequences of blocks
|
// Utilities for building blocks and sequences of blocks
|
||||||
Interpreter.prototype.fixArgs = function(b) {
|
Interpreter.prototype.fixArgs = function(b) {
|
||||||
|
@ -66,7 +66,7 @@ Interpreter.prototype.fixArgs = function(b) {
|
||||||
if (arg && arg.constructor == Array) {
|
if (arg && arg.constructor == Array) {
|
||||||
if ((arg.length > 0) && (arg[0].constructor == Array)) {
|
if ((arg.length > 0) && (arg[0].constructor == Array)) {
|
||||||
// if first element arg is itself an array, then arg is a substack
|
// if first element arg is itself an array, then arg is a substack
|
||||||
if(!b.substack) {
|
if (!b.substack) {
|
||||||
b.substack = this.makeBlockList(arg);
|
b.substack = this.makeBlockList(arg);
|
||||||
} else {
|
} else {
|
||||||
b.substack2 = this.makeBlockList(arg);
|
b.substack2 = this.makeBlockList(arg);
|
||||||
|
@ -80,7 +80,7 @@ Interpreter.prototype.fixArgs = function(b) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.args = newArgs;
|
b.args = newArgs;
|
||||||
}
|
};
|
||||||
|
|
||||||
Interpreter.prototype.makeBlockList = function(blockList) {
|
Interpreter.prototype.makeBlockList = function(blockList) {
|
||||||
var firstBlock = null, lastBlock = null;
|
var firstBlock = null, lastBlock = null;
|
||||||
|
@ -91,7 +91,7 @@ Interpreter.prototype.makeBlockList = function(blockList) {
|
||||||
lastBlock = b;
|
lastBlock = b;
|
||||||
}
|
}
|
||||||
return firstBlock;
|
return firstBlock;
|
||||||
}
|
};
|
||||||
|
|
||||||
// The Interpreter proper
|
// The Interpreter proper
|
||||||
Interpreter.prototype.stepThreads = function() {
|
Interpreter.prototype.stepThreads = function() {
|
||||||
|
@ -121,11 +121,11 @@ Interpreter.prototype.stepThreads = function() {
|
||||||
}
|
}
|
||||||
this.currentMSecs = this.timer.time();
|
this.currentMSecs = this.timer.time();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Interpreter.prototype.stepActiveThread = function() {
|
Interpreter.prototype.stepActiveThread = function() {
|
||||||
// Run the active thread until it yields.
|
// Run the active thread until it yields.
|
||||||
if(typeof(this.activeThread) == 'undefined') {
|
if (typeof(this.activeThread) == 'undefined') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var b = this.activeThread.nextBlock;
|
var b = this.activeThread.nextBlock;
|
||||||
|
@ -149,7 +149,7 @@ Interpreter.prototype.stepActiveThread = function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Interpreter.prototype.toggleThread = function(b, targetObj) {
|
Interpreter.prototype.toggleThread = function(b, targetObj) {
|
||||||
var newThreads = [], wasRunning = false;
|
var newThreads = [], wasRunning = false;
|
||||||
|
@ -161,15 +161,15 @@ Interpreter.prototype.toggleThread = function(b, targetObj) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.threads = newThreads;
|
this.threads = newThreads;
|
||||||
if(!wasRunning) {
|
if (!wasRunning) {
|
||||||
this.startThread(b, targetObj);
|
this.startThread(b, targetObj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Interpreter.prototype.startThread = function(b, targetObj) {
|
Interpreter.prototype.startThread = function(b, targetObj) {
|
||||||
this.activeThread = new Thread(b, targetObj);
|
this.activeThread = new Thread(b, targetObj);
|
||||||
this.threads.push(this.activeThread);
|
this.threads.push(this.activeThread);
|
||||||
}
|
};
|
||||||
|
|
||||||
Interpreter.prototype.restartThread = function(b, targetObj) {
|
Interpreter.prototype.restartThread = function(b, targetObj) {
|
||||||
// used by broadcast; stop any thread running on b, then start a new thread on b
|
// used by broadcast; stop any thread running on b, then start a new thread on b
|
||||||
|
@ -184,7 +184,7 @@ Interpreter.prototype.restartThread = function(b, targetObj) {
|
||||||
if (!wasRunning) {
|
if (!wasRunning) {
|
||||||
this.threads.push(newThread);
|
this.threads.push(newThread);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Interpreter.prototype.arg = function(block, index) {
|
Interpreter.prototype.arg = function(block, index) {
|
||||||
var arg = block.args[index];
|
var arg = block.args[index];
|
||||||
|
@ -193,11 +193,11 @@ Interpreter.prototype.arg = function(block, index) {
|
||||||
return arg.primFcn(arg); // expression
|
return arg.primFcn(arg); // expression
|
||||||
}
|
}
|
||||||
return arg;
|
return arg;
|
||||||
}
|
};
|
||||||
|
|
||||||
Interpreter.prototype.targetSprite = function() {
|
Interpreter.prototype.targetSprite = function() {
|
||||||
return this.activeThread.target;
|
return this.activeThread.target;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Timer
|
// Timer
|
||||||
Interpreter.prototype.startTimer = function(secs) {
|
Interpreter.prototype.startTimer = function(secs) {
|
||||||
|
@ -206,7 +206,7 @@ Interpreter.prototype.startTimer = function(secs) {
|
||||||
this.activeThread.tmp = this.currentMSecs + waitMSecs; // end time in milliseconds
|
this.activeThread.tmp = this.currentMSecs + waitMSecs; // end time in milliseconds
|
||||||
this.activeThread.firstTime = false;
|
this.activeThread.firstTime = false;
|
||||||
this.yield = true;
|
this.yield = true;
|
||||||
}
|
};
|
||||||
|
|
||||||
Interpreter.prototype.checkTimer = function() {
|
Interpreter.prototype.checkTimer = function() {
|
||||||
// check for timer expiration and clean up if expired. return true when expired
|
// check for timer expiration and clean up if expired. return true when expired
|
||||||
|
@ -219,11 +219,11 @@ Interpreter.prototype.checkTimer = function() {
|
||||||
this.yield = true;
|
this.yield = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Interpreter.prototype.redraw = function() {
|
Interpreter.prototype.redraw = function() {
|
||||||
this.doRedraw = true;
|
this.doRedraw = true;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Primitive operations
|
// Primitive operations
|
||||||
Interpreter.prototype.initPrims = function() {
|
Interpreter.prototype.initPrims = function() {
|
||||||
|
@ -231,14 +231,14 @@ Interpreter.prototype.initPrims = function() {
|
||||||
this.primitiveTable['whenGreenFlag'] = this.primNoop;
|
this.primitiveTable['whenGreenFlag'] = this.primNoop;
|
||||||
this.primitiveTable['whenKeyPressed'] = this.primNoop;
|
this.primitiveTable['whenKeyPressed'] = this.primNoop;
|
||||||
this.primitiveTable['whenClicked'] = this.primNoop;
|
this.primitiveTable['whenClicked'] = this.primNoop;
|
||||||
this.primitiveTable['if'] = function(b) { if (interp.arg(b, 0)) interp.startSubstack(b) };
|
this.primitiveTable['if'] = function(b) { if (interp.arg(b, 0)) interp.startSubstack(b); };
|
||||||
this.primitiveTable['doForever'] = function(b) { interp.startSubstack(b, true) };
|
this.primitiveTable['doForever'] = function(b) { interp.startSubstack(b, true); };
|
||||||
this.primitiveTable['doForeverIf'] = function(b) { if (interp.arg(b, 0)) interp.startSubstack(b, true); else interp.yield = true; };
|
this.primitiveTable['doForeverIf'] = function(b) { if (interp.arg(b, 0)) interp.startSubstack(b, true); else interp.yield = true; };
|
||||||
this.primitiveTable['doIf'] = function(b) { if (interp.arg(b, 0)) interp.startSubstack(b); };
|
this.primitiveTable['doIf'] = function(b) { if (interp.arg(b, 0)) interp.startSubstack(b); };
|
||||||
this.primitiveTable['doRepeat'] = this.primRepeat;
|
this.primitiveTable['doRepeat'] = this.primRepeat;
|
||||||
this.primitiveTable['doIfElse'] = function(b) { if (interp.arg(b, 0)) interp.startSubstack(b); else interp.startSubstack(b, false, true); };
|
this.primitiveTable['doIfElse'] = function(b) { if (interp.arg(b, 0)) interp.startSubstack(b); else interp.startSubstack(b, false, true); };
|
||||||
this.primitiveTable['doWaitUntil'] = function(b) { if (!interp.arg(b, 0)) interp.yield = true };
|
this.primitiveTable['doWaitUntil'] = function(b) { if (!interp.arg(b, 0)) interp.yield = true; };
|
||||||
this.primitiveTable['doUntil'] = function(b) { if (!interp.arg(b, 0)) interp.startSubstack(b, true) };
|
this.primitiveTable['doUntil'] = function(b) { if (!interp.arg(b, 0)) interp.startSubstack(b, true); };
|
||||||
this.primitiveTable['doReturn'] = function(b) { interp.activeThread = new Thread(null); };
|
this.primitiveTable['doReturn'] = function(b) { interp.activeThread = new Thread(null); };
|
||||||
this.primitiveTable['stopAll'] = function(b) { interp.activeThread = new Thread(null); interp.threads = []; }
|
this.primitiveTable['stopAll'] = function(b) { interp.activeThread = new Thread(null); interp.threads = []; }
|
||||||
this.primitiveTable['whenIReceive'] = this.primNoop;
|
this.primitiveTable['whenIReceive'] = this.primNoop;
|
||||||
|
@ -247,26 +247,26 @@ Interpreter.prototype.initPrims = function() {
|
||||||
this.primitiveTable['wait:elapsed:from:'] = this.primWait;
|
this.primitiveTable['wait:elapsed:from:'] = this.primWait;
|
||||||
|
|
||||||
// added by John:
|
// added by John:
|
||||||
this.primitiveTable['showBubble'] = function(b) { console.log(interp.arg(b, 1)) }
|
this.primitiveTable['showBubble'] = function(b) { console.log(interp.arg(b, 1)); };
|
||||||
this.primitiveTable['timerReset'] = function(b) {interp.timerBase = (new Date()).getTime() }
|
this.primitiveTable['timerReset'] = function(b) { interp.timerBase = Date.now(); };
|
||||||
this.primitiveTable['timer'] = function(b) {return ((new Date()).getTime() - interp.timerBase) / 1000 }
|
this.primitiveTable['timer'] = function(b) { return (Date.now() - interp.timerBase) / 1000; };
|
||||||
|
|
||||||
new Primitives().addPrimsTo(this.primitiveTable);
|
new Primitives().addPrimsTo(this.primitiveTable);
|
||||||
}
|
};
|
||||||
|
|
||||||
Interpreter.prototype.timerBase = (new Date()).getTime();
|
Interpreter.prototype.timerBase = Date.now();
|
||||||
Interpreter.prototype.lookupPrim = function(op) {
|
Interpreter.prototype.lookupPrim = function(op) {
|
||||||
var fcn = interp.primitiveTable[op];
|
var fcn = interp.primitiveTable[op];
|
||||||
if (fcn == null) fcn = function(b) { console.log('not implemented: ' + b.op) }
|
if (fcn == null) fcn = function(b) { console.log('not implemented: ' + b.op); };
|
||||||
return fcn;
|
return fcn;
|
||||||
}
|
};
|
||||||
|
|
||||||
Interpreter.prototype.primNoop = function(b) { console.log(b.op); }
|
Interpreter.prototype.primNoop = function(b) { console.log(b.op); };
|
||||||
|
|
||||||
Interpreter.prototype.primWait = function(b) {
|
Interpreter.prototype.primWait = function(b) {
|
||||||
if (interp.activeThread.firstTime) interp.startTimer(interp.arg(b, 0));
|
if (interp.activeThread.firstTime) interp.startTimer(interp.arg(b, 0));
|
||||||
else interp.checkTimer();
|
else interp.checkTimer();
|
||||||
}
|
};
|
||||||
|
|
||||||
Interpreter.prototype.primRepeat = function(b) {
|
Interpreter.prototype.primRepeat = function(b) {
|
||||||
if (b.tmp == -1) {
|
if (b.tmp == -1) {
|
||||||
|
@ -280,14 +280,14 @@ Interpreter.prototype.primRepeat = function(b) {
|
||||||
b.tmp = -1;
|
b.tmp = -1;
|
||||||
b = null;
|
b = null;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Interpreter.prototype.broadcast = function(b, waitFlag) {
|
Interpreter.prototype.broadcast = function(b, waitFlag) {
|
||||||
var pair;
|
var pair;
|
||||||
if (interp.activeThread.firstTime) {
|
if (interp.activeThread.firstTime) {
|
||||||
var receivers = [];
|
var receivers = [];
|
||||||
var msg = String(interp.arg(b, 0)).toLowerCase();
|
var msg = String(interp.arg(b, 0)).toLowerCase();
|
||||||
var findReceivers = function (stack, target) {
|
var findReceivers = function(stack, target) {
|
||||||
if ((stack.op == "whenIReceive") && (stack.args[0].toLowerCase() == msg)) {
|
if ((stack.op == "whenIReceive") && (stack.args[0].toLowerCase() == msg)) {
|
||||||
receivers.push([stack, target]);
|
receivers.push([stack, target]);
|
||||||
}
|
}
|
||||||
|
@ -310,7 +310,7 @@ Interpreter.prototype.broadcast = function(b, waitFlag) {
|
||||||
} else {
|
} else {
|
||||||
interp.yield = true;
|
interp.yield = true;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Interpreter.prototype.isRunning = function(b) {
|
Interpreter.prototype.isRunning = function(b) {
|
||||||
for (t in interp.threads) {
|
for (t in interp.threads) {
|
||||||
|
@ -319,7 +319,7 @@ Interpreter.prototype.isRunning = function(b) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
Interpreter.prototype.startSubstack = function(b, isLoop, secondSubstack) {
|
Interpreter.prototype.startSubstack = function(b, isLoop, secondSubstack) {
|
||||||
// Start the substack of a control structure command such as if or forever.
|
// Start the substack of a control structure command such as if or forever.
|
||||||
|
@ -327,9 +327,9 @@ Interpreter.prototype.startSubstack = function(b, isLoop, secondSubstack) {
|
||||||
b.isLoop = true;
|
b.isLoop = true;
|
||||||
this.activeThread.stack.push(b); // remember the block that started the substack
|
this.activeThread.stack.push(b); // remember the block that started the substack
|
||||||
}
|
}
|
||||||
if(!secondSubstack) {
|
if (!secondSubstack) {
|
||||||
this.activeThread.nextBlock = b.substack;
|
this.activeThread.nextBlock = b.substack;
|
||||||
} else {
|
} else {
|
||||||
this.activeThread.nextBlock = b.substack2;
|
this.activeThread.nextBlock = b.substack2;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
|
@ -33,7 +33,7 @@ var Reporter = function(data) {
|
||||||
this.el = null; // jQuery Element for the outer box
|
this.el = null; // jQuery Element for the outer box
|
||||||
this.valueEl = null; // jQ element containing the reporter value
|
this.valueEl = null; // jQ element containing the reporter value
|
||||||
this.slider = null; // slider jQ element
|
this.slider = null; // slider jQ element
|
||||||
}
|
};
|
||||||
|
|
||||||
Reporter.prototype.attach = function(scene) {
|
Reporter.prototype.attach = function(scene) {
|
||||||
switch (this.mode) {
|
switch (this.mode) {
|
||||||
|
@ -68,13 +68,13 @@ Reporter.prototype.attach = function(scene) {
|
||||||
this.valueEl.css('background-color', 'rgb(' + cR + ',' + cG + ',' + cB + ')');
|
this.valueEl.css('background-color', 'rgb(' + cR + ',' + cG + ',' + cB + ')');
|
||||||
this.el.css('display', this.visible ? 'inline-block' : 'none');
|
this.el.css('display', this.visible ? 'inline-block' : 'none');
|
||||||
scene.append(this.el);
|
scene.append(this.el);
|
||||||
}
|
};
|
||||||
|
|
||||||
Reporter.prototype.update = function() {
|
Reporter.prototype.update = function() {
|
||||||
this.el.css('display', this.visible ? 'inline-block' : 'none');
|
this.el.css('display', this.visible ? 'inline-block' : 'none');
|
||||||
if (!this.visible) return;
|
if (!this.visible) return;
|
||||||
|
|
||||||
var newValue ='';
|
var newValue = '';
|
||||||
var target = runtime.spriteNamed(this.target);
|
var target = runtime.spriteNamed(this.target);
|
||||||
switch (this.cmd) {
|
switch (this.cmd) {
|
||||||
case 'getVar:':
|
case 'getVar:':
|
||||||
|
@ -104,20 +104,21 @@ Reporter.prototype.update = function() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.valueEl.html(newValue);
|
this.valueEl.html(newValue);
|
||||||
if (this.mode == 3)
|
if (this.mode == 3) {
|
||||||
this.slider.val(parseInt(newValue));
|
this.slider.val(parseInt(newValue));
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Reporter.prototype.updateLayer = function() {
|
Reporter.prototype.updateLayer = function() {
|
||||||
this.el.css('z-index', this.z);
|
this.el.css('z-index', this.z);
|
||||||
}
|
};
|
||||||
|
|
||||||
Reporter.prototype.changeSlider = function() {
|
Reporter.prototype.changeSlider = function() {
|
||||||
var newValue = parseInt($(this).val());
|
var newValue = parseInt($(this).val());
|
||||||
var target = runtime.spriteNamed($(this).attr('data-target'));
|
var target = runtime.spriteNamed($(this).attr('data-target'));
|
||||||
var variable = $(this).attr('data-var');
|
var variable = $(this).attr('data-var');
|
||||||
target.variables[variable] = newValue;
|
target.variables[variable] = newValue;
|
||||||
}
|
};
|
||||||
|
|
||||||
var List = function(data) {
|
var List = function(data) {
|
||||||
this.contents = data.contents;
|
this.contents = data.contents;
|
||||||
|
@ -171,7 +172,7 @@ List.prototype.attach = function(scene) {
|
||||||
this.el.height(this.height);
|
this.el.height(this.height);
|
||||||
this.el.css('z-index', this.z);
|
this.el.css('z-index', this.z);
|
||||||
this.el.css('display', this.visible ? 'inline-block' : 'none');
|
this.el.css('display', this.visible ? 'inline-block' : 'none');
|
||||||
}
|
};
|
||||||
|
|
||||||
List.prototype.update = function(){
|
List.prototype.update = function(){
|
||||||
this.el.css('display', this.visible ? 'inline-block' : 'none');
|
this.el.css('display', this.visible ? 'inline-block' : 'none');
|
||||||
|
@ -191,4 +192,4 @@ List.prototype.update = function(){
|
||||||
|
|
||||||
List.prototype.updateLayer = function() {
|
List.prototype.updateLayer = function() {
|
||||||
this.el.css('z-index', this.z);
|
this.el.css('z-index', this.z);
|
||||||
}
|
};
|
||||||
|
|
|
@ -35,7 +35,7 @@ var Runtime = function() {
|
||||||
this.audioPlaying = [];
|
this.audioPlaying = [];
|
||||||
this.notesPlaying = [];
|
this.notesPlaying = [];
|
||||||
this.projectLoaded = false;
|
this.projectLoaded = false;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Initializer for the drawing and audio contexts.
|
// Initializer for the drawing and audio contexts.
|
||||||
Runtime.prototype.init = function() {
|
Runtime.prototype.init = function() {
|
||||||
|
@ -44,7 +44,7 @@ Runtime.prototype.init = function() {
|
||||||
this.audioContext = new AudioContext();
|
this.audioContext = new AudioContext();
|
||||||
this.audioGain = this.audioContext.createGainNode();
|
this.audioGain = this.audioContext.createGainNode();
|
||||||
this.audioGain.connect(runtime.audioContext.destination);
|
this.audioGain.connect(runtime.audioContext.destination);
|
||||||
}
|
};
|
||||||
|
|
||||||
// Load start waits for the stage and the sprites to be loaded, without
|
// Load start waits for the stage and the sprites to be loaded, without
|
||||||
// hanging the browser. When the loading is finished, we begin the step
|
// hanging the browser. When the loading is finished, we begin the step
|
||||||
|
@ -69,7 +69,7 @@ Runtime.prototype.loadStart = function() {
|
||||||
$('#info').html("Loaded!");
|
$('#info').html("Loaded!");
|
||||||
setInterval(this.step, 33);
|
setInterval(this.step, 33);
|
||||||
this.projectLoaded = true;
|
this.projectLoaded = true;
|
||||||
}
|
};
|
||||||
|
|
||||||
Runtime.prototype.greenFlag = function() {
|
Runtime.prototype.greenFlag = function() {
|
||||||
if (this.projectLoaded) {
|
if (this.projectLoaded) {
|
||||||
|
@ -78,7 +78,7 @@ Runtime.prototype.greenFlag = function() {
|
||||||
interp.primitiveTable.timerReset();
|
interp.primitiveTable.timerReset();
|
||||||
this.startGreenFlags();
|
this.startGreenFlags();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Runtime.prototype.stopAll = function() {
|
Runtime.prototype.stopAll = function() {
|
||||||
interp.activeThread = new Thread(null);
|
interp.activeThread = new Thread(null);
|
||||||
|
@ -86,10 +86,11 @@ Runtime.prototype.stopAll = function() {
|
||||||
stopAllSounds();
|
stopAllSounds();
|
||||||
// Hide reporters
|
// Hide reporters
|
||||||
for (var s = 0; s < runtime.sprites.length; s++) {
|
for (var s = 0; s < runtime.sprites.length; s++) {
|
||||||
if (typeof runtime.sprites[s].hideBubble == 'function')
|
if (typeof runtime.sprites[s].hideBubble == 'function') {
|
||||||
runtime.sprites[s].hideBubble();
|
runtime.sprites[s].hideBubble();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Step method for execution - called every 33 milliseconds
|
// Step method for execution - called every 33 milliseconds
|
||||||
Runtime.prototype.step = function() {
|
Runtime.prototype.step = function() {
|
||||||
|
@ -97,7 +98,7 @@ Runtime.prototype.step = function() {
|
||||||
for (var r = 0; r < runtime.reporters.length; r++) {
|
for (var r = 0; r < runtime.reporters.length; r++) {
|
||||||
runtime.reporters[r].update();
|
runtime.reporters[r].update();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Stack functions -- push and remove stacks
|
// Stack functions -- push and remove stacks
|
||||||
// to be run by the interpreter as threads.
|
// to be run by the interpreter as threads.
|
||||||
|
@ -106,7 +107,7 @@ Runtime.prototype.allStacksDo = function(f) {
|
||||||
var stack;
|
var stack;
|
||||||
for (var i = runtime.sprites.length-1; i >= 0; i--) {
|
for (var i = runtime.sprites.length-1; i >= 0; i--) {
|
||||||
var o = runtime.sprites[i];
|
var o = runtime.sprites[i];
|
||||||
if(typeof(o) == 'object' && o.constructor == Sprite) {
|
if (typeof(o) == 'object' && o.constructor == Sprite) {
|
||||||
$.each(o.stacks, function(index, stack) {
|
$.each(o.stacks, function(index, stack) {
|
||||||
f(stack, o);
|
f(stack, o);
|
||||||
});
|
});
|
||||||
|
@ -115,7 +116,7 @@ Runtime.prototype.allStacksDo = function(f) {
|
||||||
$.each(stage.stacks, function(index, stack) {
|
$.each(stage.stacks, function(index, stack) {
|
||||||
f(stack, stage);
|
f(stack, stage);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// Hat triggers
|
// Hat triggers
|
||||||
Runtime.prototype.startGreenFlags = function() {
|
Runtime.prototype.startGreenFlags = function() {
|
||||||
|
@ -123,7 +124,7 @@ Runtime.prototype.startGreenFlags = function() {
|
||||||
if (stack.op == 'whenGreenFlag') interp.toggleThread(stack, target);
|
if (stack.op == 'whenGreenFlag') interp.toggleThread(stack, target);
|
||||||
}
|
}
|
||||||
this.allStacksDo(startIfGreenFlag);
|
this.allStacksDo(startIfGreenFlag);
|
||||||
}
|
};
|
||||||
|
|
||||||
Runtime.prototype.startKeyHats = function(ch) {
|
Runtime.prototype.startKeyHats = function(ch) {
|
||||||
var keyName = null;
|
var keyName = null;
|
||||||
|
@ -140,30 +141,30 @@ Runtime.prototype.startKeyHats = function(ch) {
|
||||||
if (ch == 32) keyName = "space";
|
if (ch == 32) keyName = "space";
|
||||||
|
|
||||||
if (keyName == null) return;
|
if (keyName == null) return;
|
||||||
var startMatchingKeyHats = function (stack, target) {
|
var startMatchingKeyHats = function(stack, target) {
|
||||||
if ((stack.op == "whenKeyPressed") && (stack.args[0] == keyName)) {
|
if ((stack.op == "whenKeyPressed") && (stack.args[0] == keyName)) {
|
||||||
// Only start the stack if it is not already running
|
// Only start the stack if it is not already running
|
||||||
if (!interp.isRunning(stack))
|
if (!interp.isRunning(stack)) {
|
||||||
interp.toggleThread(stack, target);
|
interp.toggleThread(stack, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
runtime.allStacksDo(startMatchingKeyHats);
|
runtime.allStacksDo(startMatchingKeyHats);
|
||||||
}
|
};
|
||||||
|
|
||||||
Runtime.prototype.startClickedHats = function(sprite) {
|
Runtime.prototype.startClickedHats = function(sprite) {
|
||||||
function startIfClicked(stack, target) {
|
function startIfClicked(stack, target) {
|
||||||
if(target == sprite && stack.op == "whenClicked") {
|
if (target == sprite && stack.op == "whenClicked" && !interp.isRunning(stack)) {
|
||||||
if(!interp.isRunning(stack))
|
|
||||||
interp.toggleThread(stack, target);
|
interp.toggleThread(stack, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
runtime.allStacksDo(startIfClicked);
|
runtime.allStacksDo(startIfClicked);
|
||||||
}
|
};
|
||||||
|
|
||||||
// Returns true if a key is pressed.
|
// Returns true if a key is pressed.
|
||||||
Runtime.prototype.keyIsDown = function(ch) {
|
Runtime.prototype.keyIsDown = function(ch) {
|
||||||
return this.keysDown[ch] || false;
|
return this.keysDown[ch] || false;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Sprite named -- returns one of the sprites on the stage.
|
// Sprite named -- returns one of the sprites on the stage.
|
||||||
Runtime.prototype.spriteNamed = function(n) {
|
Runtime.prototype.spriteNamed = function(n) {
|
||||||
|
@ -176,7 +177,22 @@ Runtime.prototype.spriteNamed = function(n) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return selected_sprite;
|
return selected_sprite;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
Runtime.prototype.getTimeString = function(which) {
|
||||||
|
// Return local time properties.
|
||||||
|
var now = new Date();
|
||||||
|
switch (which) {
|
||||||
|
case 'hour': return now.getHours();
|
||||||
|
case 'minute': return now.getMinutes();
|
||||||
|
case 'second': return now.getSeconds();
|
||||||
|
case 'year': return now.getFullYear(); // four digit year (e.g. 2012)
|
||||||
|
case 'month': return now.getMonth() + 1; // 1-12
|
||||||
|
case 'date': return now.getDate(); // 1-31
|
||||||
|
case 'day of week': return now.getDay() + 1; // 1-7, where 1 is Sunday
|
||||||
|
}
|
||||||
|
return ''; // shouldn't happen
|
||||||
|
};
|
||||||
|
|
||||||
// Reassigns z-indices for layer functions
|
// Reassigns z-indices for layer functions
|
||||||
Runtime.prototype.reassignZ = function(target, move) {
|
Runtime.prototype.reassignZ = function(target, move) {
|
||||||
|
@ -193,7 +209,7 @@ Runtime.prototype.reassignZ = function(target, move) {
|
||||||
if (move == null) {
|
if (move == null) {
|
||||||
// Move to the front
|
// Move to the front
|
||||||
this.sprites.splice(this.sprites.length, 0, target);
|
this.sprites.splice(this.sprites.length, 0, target);
|
||||||
} else if (oldIndex - move >= 0 && oldIndex - move < this.sprites.length+1) {
|
} else if (oldIndex - move >= 0 && oldIndex - move < this.sprites.length + 1) {
|
||||||
// Move to the new position
|
// Move to the new position
|
||||||
this.sprites.splice(oldIndex - move, 0, target);
|
this.sprites.splice(oldIndex - move, 0, target);
|
||||||
} else {
|
} else {
|
||||||
|
@ -208,4 +224,4 @@ Runtime.prototype.reassignZ = function(target, move) {
|
||||||
sprite.updateLayer();
|
sprite.updateLayer();
|
||||||
newZ++;
|
newZ++;
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var runtime, interp, io, iosAudioActive = false;
|
var runtime, interp, io, iosAudioActive = false;
|
||||||
$(function () {
|
$(function() {
|
||||||
runtime = new Runtime();
|
runtime = new Runtime();
|
||||||
runtime.init();
|
runtime.init();
|
||||||
|
|
||||||
|
|
106
js/Sprite.js
106
js/Sprite.js
|
@ -22,12 +22,12 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var Sprite = function(data) {
|
var Sprite = function(data) {
|
||||||
if(!this.data) {
|
if (!this.data) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public variables used for Scratch-accessible data.
|
// Public variables used for Scratch-accessible data.
|
||||||
this.visible = (typeof(this.data.visible) == "undefined") ? true : data.visible;
|
this.visible = typeof(this.data.visible) == "undefined" ? true : data.visible;
|
||||||
|
|
||||||
this.scratchX = data.scratchX || 0;
|
this.scratchX = data.scratchX || 0;
|
||||||
this.scratchY = data.scratchY || 0;
|
this.scratchY = data.scratchY || 0;
|
||||||
|
@ -94,7 +94,7 @@ var Sprite = function(data) {
|
||||||
|
|
||||||
// Stacks to be pushed to the interpreter and run
|
// Stacks to be pushed to the interpreter and run
|
||||||
this.stacks = [];
|
this.stacks = [];
|
||||||
}
|
};
|
||||||
|
|
||||||
// Attaches a Sprite (<img>) to a Scratch scene
|
// Attaches a Sprite (<img>) to a Scratch scene
|
||||||
Sprite.prototype.attach = function(scene) {
|
Sprite.prototype.attach = function(scene) {
|
||||||
|
@ -109,7 +109,7 @@ Sprite.prototype.attach = function(scene) {
|
||||||
sprite.costumesLoaded += 1;
|
sprite.costumesLoaded += 1;
|
||||||
sprite.updateCostume();
|
sprite.updateCostume();
|
||||||
|
|
||||||
$(sprite.textures[c]).css('display', (sprite.currentCostumeIndex == c) ? 'inline' : 'none');
|
$(sprite.textures[c]).css('display', sprite.currentCostumeIndex == c ? 'inline' : 'none');
|
||||||
$(sprite.textures[c]).css('position', 'absolute').css('left', '0px').css('top', '0px');
|
$(sprite.textures[c]).css('position', 'absolute').css('left', '0px').css('top', '0px');
|
||||||
$(sprite.textures[c]).bind('dragstart', function(evt) { evt.preventDefault(); })
|
$(sprite.textures[c]).bind('dragstart', function(evt) { evt.preventDefault(); })
|
||||||
.bind('selectstart', function(evt) { evt.preventDefault(); })
|
.bind('selectstart', function(evt) { evt.preventDefault(); })
|
||||||
|
@ -139,21 +139,20 @@ Sprite.prototype.attach = function(scene) {
|
||||||
this.talkBubble.append(this.talkBubbleStyler);
|
this.talkBubble.append(this.talkBubbleStyler);
|
||||||
|
|
||||||
runtime.scene.append(this.talkBubble);
|
runtime.scene.append(this.talkBubble);
|
||||||
}
|
};
|
||||||
|
|
||||||
// Load sounds from the server and buffer them
|
// Load sounds from the server and buffer them
|
||||||
Sprite.prototype.loadSounds = function() {
|
Sprite.prototype.loadSounds = function() {
|
||||||
var spr = this;
|
var spr = this;
|
||||||
$.each(this.sounds, function (index, sound) {
|
$.each(this.sounds, function(index, sound) {
|
||||||
io.soundRequest(sound, spr);
|
io.soundRequest(sound, spr);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// True when all the costumes have been loaded
|
// True when all the costumes have been loaded
|
||||||
Sprite.prototype.isLoaded = function() {
|
Sprite.prototype.isLoaded = function() {
|
||||||
return (this.costumesLoaded == this.costumes.length
|
return this.costumesLoaded == this.costumes.length && this.soundsLoaded == Object.keys(this.sounds).length;
|
||||||
&& this.soundsLoaded == Object.keys(this.sounds).length);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// Step methods
|
// Step methods
|
||||||
Sprite.prototype.showCostume = function(costume) {
|
Sprite.prototype.showCostume = function(costume) {
|
||||||
|
@ -167,33 +166,33 @@ Sprite.prototype.showCostume = function(costume) {
|
||||||
this.currentCostumeIndex = costume;
|
this.currentCostumeIndex = costume;
|
||||||
}
|
}
|
||||||
this.updateCostume();
|
this.updateCostume();
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.indexOfCostumeNamed = function(name) {
|
Sprite.prototype.indexOfCostumeNamed = function(name) {
|
||||||
for(var i in this.costumes) {
|
for (var i in this.costumes) {
|
||||||
var c = this.costumes[i];
|
var c = this.costumes[i];
|
||||||
if(c['costumeName'] == name) {
|
if (c['costumeName'] == name) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.showCostumeNamed = function(name) {
|
Sprite.prototype.showCostumeNamed = function(name) {
|
||||||
var index = this.indexOfCostumeNamed(name);
|
var index = this.indexOfCostumeNamed(name);
|
||||||
if(!index) return;
|
if (!index) return;
|
||||||
this.showCostume(index);
|
this.showCostume(index);
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.updateCostume = function() {
|
Sprite.prototype.updateCostume = function() {
|
||||||
if(!this.textures[this.currentCostumeIndex]) {
|
if (!this.textures[this.currentCostumeIndex]) {
|
||||||
this.currentCostumeIndex = 0;
|
this.currentCostumeIndex = 0;
|
||||||
}
|
}
|
||||||
$(this.mesh).css('display', 'none');
|
$(this.mesh).css('display', 'none');
|
||||||
this.mesh = this.textures[this.currentCostumeIndex];
|
this.mesh = this.textures[this.currentCostumeIndex];
|
||||||
this.updateVisible();
|
this.updateVisible();
|
||||||
this.updateTransform();
|
this.updateTransform();
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.onClick = function(evt) {
|
Sprite.prototype.onClick = function(evt) {
|
||||||
// TODO - needs work!!
|
// TODO - needs work!!
|
||||||
|
@ -238,23 +237,24 @@ Sprite.prototype.onClick = function(evt) {
|
||||||
$(underElement).click();
|
$(underElement).click();
|
||||||
$(this.mesh).show();
|
$(this.mesh).show();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.setVisible = function(v) {
|
Sprite.prototype.setVisible = function(v) {
|
||||||
this.visible = v;
|
this.visible = v;
|
||||||
this.updateVisible();
|
this.updateVisible();
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.updateLayer = function() {
|
Sprite.prototype.updateLayer = function() {
|
||||||
$(this.mesh).css('z-index', this.z);
|
$(this.mesh).css('z-index', this.z);
|
||||||
if (this.talkBubble) this.talkBubble.css('z-index', this.z);
|
if (this.talkBubble) this.talkBubble.css('z-index', this.z);
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.updateVisible = function() {
|
Sprite.prototype.updateVisible = function() {
|
||||||
$(this.mesh).css('display', (this.visible) ? 'inline' : 'none');
|
$(this.mesh).css('display', this.visible ? 'inline' : 'none');
|
||||||
if (this.talkBubbleOn)
|
if (this.talkBubbleOn) {
|
||||||
this.talkBubble.css('display', (this.visible) ? 'inline-block' : 'none');
|
this.talkBubble.css('display', this.visible ? 'inline-block' : 'none');
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Sprite.prototype.updateTransform = function() {
|
Sprite.prototype.updateTransform = function() {
|
||||||
var texture = this.textures[this.currentCostumeIndex];
|
var texture = this.textures[this.currentCostumeIndex];
|
||||||
|
@ -305,7 +305,7 @@ Sprite.prototype.updateTransform = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.updateLayer();
|
this.updateLayer();
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.getTalkBubbleXY = function() {
|
Sprite.prototype.getTalkBubbleXY = function() {
|
||||||
var texture = this.textures[this.currentCostumeIndex];
|
var texture = this.textures[this.currentCostumeIndex];
|
||||||
|
@ -316,7 +316,7 @@ Sprite.prototype.getTalkBubbleXY = function() {
|
||||||
var drawX = this.scratchX + (480 / 2) - rotationCenterX;
|
var drawX = this.scratchX + (480 / 2) - rotationCenterX;
|
||||||
var drawY = -this.scratchY + (360 / 2) - rotationCenterY;
|
var drawY = -this.scratchY + (360 / 2) - rotationCenterY;
|
||||||
return [drawX + drawWidth, drawY - drawHeight / 2];
|
return [drawX + drawWidth, drawY - drawHeight / 2];
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.showBubble = function(text, type) {
|
Sprite.prototype.showBubble = function(text, type) {
|
||||||
var xy = this.getTalkBubbleXY();
|
var xy = this.getTalkBubbleXY();
|
||||||
|
@ -329,30 +329,34 @@ Sprite.prototype.showBubble = function(text, type) {
|
||||||
|
|
||||||
this.talkBubbleStyler.removeClass('bubble-say');
|
this.talkBubbleStyler.removeClass('bubble-say');
|
||||||
this.talkBubbleStyler.removeClass('bubble-think');
|
this.talkBubbleStyler.removeClass('bubble-think');
|
||||||
if (type == 'say') this.talkBubbleStyler.addClass('bubble-say');
|
if (type == 'say') {
|
||||||
else if (type == 'think') this.talkBubbleStyler.addClass('bubble-think');
|
this.talkBubbleStyler.addClass('bubble-say');
|
||||||
|
} else if (type == 'think') {
|
||||||
|
this.talkBubbleStyler.addClass('bubble-think');
|
||||||
|
}
|
||||||
|
|
||||||
if (this.visible)
|
if (this.visible) {
|
||||||
this.talkBubble.css('display', 'inline-block');
|
this.talkBubble.css('display', 'inline-block');
|
||||||
|
}
|
||||||
this.talkBubbleBox.html(text);
|
this.talkBubbleBox.html(text);
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.hideBubble = function() {
|
Sprite.prototype.hideBubble = function() {
|
||||||
this.talkBubbleOn = false;
|
this.talkBubbleOn = false;
|
||||||
this.talkBubble.css('display', 'none');
|
this.talkBubble.css('display', 'none');
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.setXY = function(x, y) {
|
Sprite.prototype.setXY = function(x, y) {
|
||||||
this.scratchX = x;
|
this.scratchX = x;
|
||||||
this.scratchY = y;
|
this.scratchY = y;
|
||||||
this.updateTransform();
|
this.updateTransform();
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.setDirection = function(d) {
|
Sprite.prototype.setDirection = function(d) {
|
||||||
var rotation;
|
var rotation;
|
||||||
d = d % 360
|
d = d % 360
|
||||||
if (d < 0) d += 360;
|
if (d < 0) d += 360;
|
||||||
this.direction = (d > 180) ? d - 360 : d;
|
this.direction = d > 180 ? d - 360 : d;
|
||||||
if (this.rotationStyle == 'normal') {
|
if (this.rotationStyle == 'normal') {
|
||||||
rotation = (this.direction - 90) % 360;
|
rotation = (this.direction - 90) % 360;
|
||||||
} else if (this.rotationStyle == 'leftRight') {
|
} else if (this.rotationStyle == 'leftRight') {
|
||||||
|
@ -367,22 +371,22 @@ Sprite.prototype.setDirection = function(d) {
|
||||||
}
|
}
|
||||||
this.rotation = rotation;
|
this.rotation = rotation;
|
||||||
this.updateTransform();
|
this.updateTransform();
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.setRotationStyle = function(r) {
|
Sprite.prototype.setRotationStyle = function(r) {
|
||||||
this.rotationStyle = r;
|
this.rotationStyle = r;
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.getSize = function() {
|
Sprite.prototype.getSize = function() {
|
||||||
return this.scale * 100;
|
return this.scale * 100;
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.setSize = function(percent) {
|
Sprite.prototype.setSize = function(percent) {
|
||||||
var newScale = percent / 100.0;
|
var newScale = percent / 100.0;
|
||||||
newScale = Math.max(0.05, Math.min(newScale, 100));
|
newScale = Math.max(0.05, Math.min(newScale, 100));
|
||||||
this.scale = newScale;
|
this.scale = newScale;
|
||||||
this.updateTransform();
|
this.updateTransform();
|
||||||
}
|
};
|
||||||
|
|
||||||
// Move functions
|
// Move functions
|
||||||
Sprite.prototype.keepOnStage = function() {
|
Sprite.prototype.keepOnStage = function() {
|
||||||
|
@ -398,7 +402,7 @@ Sprite.prototype.keepOnStage = function() {
|
||||||
if (myBox.top > edgeBox.bottom) y -= myBox.top - edgeBox.bottom;
|
if (myBox.top > edgeBox.bottom) y -= myBox.top - edgeBox.bottom;
|
||||||
this.scratchX = x - 240;
|
this.scratchX = x - 240;
|
||||||
this.scratchY = 180 - y;
|
this.scratchY = 180 - y;
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.getRect = function() {
|
Sprite.prototype.getRect = function() {
|
||||||
var cImg = this.textures[this.currentCostumeIndex];
|
var cImg = this.textures[this.currentCostumeIndex];
|
||||||
|
@ -406,7 +410,7 @@ Sprite.prototype.getRect = function() {
|
||||||
var y = 180 - this.scratchY - (cImg.height/2.0);
|
var y = 180 - this.scratchY - (cImg.height/2.0);
|
||||||
var myBox = new Rectangle(x, y, cImg.width, cImg.height);
|
var myBox = new Rectangle(x, y, cImg.width, cImg.height);
|
||||||
return myBox;
|
return myBox;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Pen functions
|
// Pen functions
|
||||||
Sprite.prototype.setPenColor = function(c) {
|
Sprite.prototype.setPenColor = function(c) {
|
||||||
|
@ -414,26 +418,29 @@ Sprite.prototype.setPenColor = function(c) {
|
||||||
this.penHue = (200 * hsv[0]) / 360 ;
|
this.penHue = (200 * hsv[0]) / 360 ;
|
||||||
this.penShade = 50 * hsv[2]; // not quite right; doesn't account for saturation
|
this.penShade = 50 * hsv[2]; // not quite right; doesn't account for saturation
|
||||||
this.penColorCache = c;
|
this.penColorCache = c;
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.setPenHue = function(n) {
|
Sprite.prototype.setPenHue = function(n) {
|
||||||
this.penHue = n % 200;
|
this.penHue = n % 200;
|
||||||
if (this.penHue < 0) this.penHue += 200;
|
if (this.penHue < 0) this.penHue += 200;
|
||||||
this.updateCachedPenColor();
|
this.updateCachedPenColor();
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.setPenShade = function(n) {
|
Sprite.prototype.setPenShade = function(n) {
|
||||||
this.penShade = n % 200;
|
this.penShade = n % 200;
|
||||||
if (this.penShade < 0) this.penShade += 200;
|
if (this.penShade < 0) this.penShade += 200;
|
||||||
this.updateCachedPenColor();
|
this.updateCachedPenColor();
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.updateCachedPenColor = function() {
|
Sprite.prototype.updateCachedPenColor = function() {
|
||||||
var c = Color.fromHSV((this.penHue * 180.0) / 100.0, 1, 1);
|
var c = Color.fromHSV((this.penHue * 180.0) / 100.0, 1, 1);
|
||||||
var shade = (this.penShade > 100) ? 200 - this.penShade : this.penShade; // range 0..100
|
var shade = this.penShade > 100 ? 200 - this.penShade : this.penShade; // range 0..100
|
||||||
if (shade < 50) {
|
if (shade < 50) {
|
||||||
this.penColorCache = Color.mixRGB(0, c, (10 + shade) / 60.0);
|
this.penColorCache = Color.mixRGB(0, c, (10 + shade) / 60.0);
|
||||||
} else {
|
} else {
|
||||||
this.penColorCache = Color.mixRGB(c, 0xFFFFFF, (shade - 50) / 60);
|
this.penColorCache = Color.mixRGB(c, 0xFFFFFF, (shade - 50) / 60);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.stamp = function(canvas, opacity) {
|
Sprite.prototype.stamp = function(canvas, opacity) {
|
||||||
var drawWidth = this.textures[this.currentCostumeIndex].width * this.scale;
|
var drawWidth = this.textures[this.currentCostumeIndex].width * this.scale;
|
||||||
|
@ -447,12 +454,13 @@ Sprite.prototype.stamp = function(canvas, opacity) {
|
||||||
canvas.drawImage(this.mesh, -drawWidth/2, -drawHeight/2, drawWidth, drawHeight);
|
canvas.drawImage(this.mesh, -drawWidth/2, -drawHeight/2, drawWidth, drawHeight);
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
canvas.globalAlpha = 1;
|
canvas.globalAlpha = 1;
|
||||||
}
|
};
|
||||||
|
|
||||||
Sprite.prototype.soundNamed = function(name) {
|
Sprite.prototype.soundNamed = function(name) {
|
||||||
if (name in this.sounds && this.sounds[name].buffer)
|
if (name in this.sounds && this.sounds[name].buffer) {
|
||||||
return this.sounds[name];
|
return this.sounds[name];
|
||||||
else if (name in runtime.stage.sounds && runtime.stage.sounds[name].buffer)
|
} else if (name in runtime.stage.sounds && runtime.stage.sounds[name].buffer) {
|
||||||
return runtime.stage.sounds[name];
|
return runtime.stage.sounds[name];
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
};
|
||||||
|
|
17
js/Stage.js
17
js/Stage.js
|
@ -35,30 +35,27 @@ var Stage = function(data) {
|
||||||
this.lineCache = this.lineCanvas.getContext('2d');
|
this.lineCache = this.lineCanvas.getContext('2d');
|
||||||
|
|
||||||
Sprite.call(this, data);
|
Sprite.call(this, data);
|
||||||
}
|
};
|
||||||
|
|
||||||
Stage.prototype = Object.create(Sprite.prototype);
|
Stage.prototype = Object.create(Sprite.prototype);
|
||||||
Stage.prototype.constructor = Stage;
|
Stage.prototype.constructor = Stage;
|
||||||
|
|
||||||
Stage.prototype.attachPenLayer = function(scene) {
|
Stage.prototype.attachPenLayer = function(scene) {
|
||||||
if (this.penLayerLoaded)
|
if (this.penLayerLoaded) return;
|
||||||
return;
|
|
||||||
this.penLayerLoaded = true;
|
this.penLayerLoaded = true;
|
||||||
$(this.lineCanvas).css('position', 'absolute');
|
$(this.lineCanvas).css('position', 'absolute');
|
||||||
$(this.lineCanvas).css('z-index', '-1');
|
$(this.lineCanvas).css('z-index', '-1');
|
||||||
scene.append(this.lineCanvas);
|
scene.append(this.lineCanvas);
|
||||||
}
|
};
|
||||||
|
|
||||||
Stage.prototype.isLoaded = function() {
|
Stage.prototype.isLoaded = function() {
|
||||||
return (this.penLayerLoaded
|
return this.penLayerLoaded && this.costumesLoaded == this.costumes.length && this.soundsLoaded == Object.keys(this.sounds).length;
|
||||||
&& this.costumesLoaded == this.costumes.length
|
};
|
||||||
&& this.soundsLoaded == Object.keys(this.sounds).length);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pen functions
|
// Pen functions
|
||||||
Stage.prototype.clearPenStrokes = function() {
|
Stage.prototype.clearPenStrokes = function() {
|
||||||
this.lineCache.clearRect(0, 0, 480, 360);
|
this.lineCache.clearRect(0, 0, 480, 360);
|
||||||
}
|
};
|
||||||
|
|
||||||
Stage.prototype.stroke = function(from, to, width, color) {
|
Stage.prototype.stroke = function(from, to, width, color) {
|
||||||
this.lineCache.lineWidth = width;
|
this.lineCache.lineWidth = width;
|
||||||
|
@ -69,4 +66,4 @@ Stage.prototype.stroke = function(from, to, width, color) {
|
||||||
this.lineCache.lineTo(to[0] + 240.5, 180.5 - to[1]);
|
this.lineCache.lineTo(to[0] + 240.5, 180.5 - to[1]);
|
||||||
this.lineCache.strokeStyle = 'rgb(' + (color >> 16) + ',' + (color >> 8 & 255) + ',' + (color & 255) + ')';
|
this.lineCache.strokeStyle = 'rgb(' + (color >> 16) + ',' + (color >> 8 & 255) + ',' + (color & 255) + ')';
|
||||||
this.lineCache.stroke();
|
this.lineCache.stroke();
|
||||||
}
|
};
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var LooksPrims = function() {}
|
var LooksPrims = function() {};
|
||||||
|
|
||||||
LooksPrims.prototype.addPrimsTo = function(primTable) {
|
LooksPrims.prototype.addPrimsTo = function(primTable) {
|
||||||
primTable["show"] = this.primShow;
|
primTable["show"] = this.primShow;
|
||||||
|
@ -47,22 +47,22 @@ LooksPrims.prototype.addPrimsTo = function(primTable) {
|
||||||
primTable["say:duration:elapsed:from:"] = function(b) { showBubbleAndWait(b, 'say'); };
|
primTable["say:duration:elapsed:from:"] = function(b) { showBubbleAndWait(b, 'say'); };
|
||||||
primTable["think:"] = function(b) { showBubble(b, 'think'); };
|
primTable["think:"] = function(b) { showBubble(b, 'think'); };
|
||||||
primTable["think:duration:elapsed:from:"] = function(b) { showBubbleAndWait(b, 'think'); };
|
primTable["think:duration:elapsed:from:"] = function(b) { showBubbleAndWait(b, 'think'); };
|
||||||
}
|
};
|
||||||
|
|
||||||
LooksPrims.prototype.primShow = function(b) {
|
LooksPrims.prototype.primShow = function(b) {
|
||||||
interp.targetSprite().setVisible(true);
|
interp.targetSprite().setVisible(true);
|
||||||
interp.redraw();
|
interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
LooksPrims.prototype.primHide = function(b) {
|
LooksPrims.prototype.primHide = function(b) {
|
||||||
interp.targetSprite().setVisible(false);
|
interp.targetSprite().setVisible(false);
|
||||||
interp.redraw();
|
interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
LooksPrims.prototype.primNextCostume = function(b) {
|
LooksPrims.prototype.primNextCostume = function(b) {
|
||||||
interp.targetSprite().showCostume(interp.targetSprite().currentCostumeIndex + 1);
|
interp.targetSprite().showCostume(interp.targetSprite().currentCostumeIndex + 1);
|
||||||
interp.redraw();
|
interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
LooksPrims.prototype.primShowCostume = function(b) {
|
LooksPrims.prototype.primShowCostume = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
|
@ -88,7 +88,7 @@ LooksPrims.prototype.primShowCostume = function(b) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s.visible) interp.redraw();
|
if (s.visible) interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
LooksPrims.prototype.primStartScene = function(b) {
|
LooksPrims.prototype.primStartScene = function(b) {
|
||||||
var s = runtime.stage;
|
var s = runtime.stage;
|
||||||
|
@ -113,55 +113,55 @@ LooksPrims.prototype.primStartScene = function(b) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s.visible) interp.redraw();
|
if (s.visible) interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
LooksPrims.prototype.primCostumeNum = function(b) {
|
LooksPrims.prototype.primCostumeNum = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
return (s == null) ? 1 : s.currentCostumeIndex + 1;
|
return s == null ? 1 : s.currentCostumeIndex + 1;
|
||||||
}
|
};
|
||||||
|
|
||||||
LooksPrims.prototype.primChangeSize = function(b) {
|
LooksPrims.prototype.primChangeSize = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s == null) return;
|
if (s == null) return;
|
||||||
s.setSize(s.getSize() + interp.arg(b, 0));
|
s.setSize(s.getSize() + interp.arg(b, 0));
|
||||||
if (s.visible) interp.redraw();
|
if (s.visible) interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
LooksPrims.prototype.primSetSize = function(b) {
|
LooksPrims.prototype.primSetSize = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s == null) return;
|
if (s == null) return;
|
||||||
s.setSize(interp.arg(b, 0));
|
s.setSize(interp.arg(b, 0));
|
||||||
if (s.visible) interp.redraw();
|
if (s.visible) interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
LooksPrims.prototype.primSize = function(b) {
|
LooksPrims.prototype.primSize = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s == null) return 100;
|
if (s == null) return 100;
|
||||||
return s.getSize();
|
return s.getSize();
|
||||||
}
|
};
|
||||||
|
|
||||||
LooksPrims.prototype.primGoFront = function(b) {
|
LooksPrims.prototype.primGoFront = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
runtime.reassignZ(s, null);
|
runtime.reassignZ(s, null);
|
||||||
if(s.visible) interp.redraw();
|
if (s.visible) interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
LooksPrims.prototype.primGoBack = function(b) {
|
LooksPrims.prototype.primGoBack = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
runtime.reassignZ(s, interp.arg(b, 0));
|
runtime.reassignZ(s, interp.arg(b, 0));
|
||||||
if(s.visible) interp.redraw();
|
if (s.visible) interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
LooksPrims.prototype.primChangeEffect = function(b) {}
|
LooksPrims.prototype.primChangeEffect = function(b) {};
|
||||||
|
|
||||||
LooksPrims.prototype.primSetEffect = function(b) {}
|
LooksPrims.prototype.primSetEffect = function(b) {};
|
||||||
|
|
||||||
LooksPrims.prototype.primClearEffects = function(b) {}
|
LooksPrims.prototype.primClearEffects = function(b) {};
|
||||||
|
|
||||||
var showBubble = function(b, type) {
|
var showBubble = function(b, type) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) s.showBubble(interp.arg(b, 0), type);
|
if (s != null) s.showBubble(interp.arg(b, 0), type);
|
||||||
}
|
};
|
||||||
|
|
||||||
var showBubbleAndWait = function(b, type) {
|
var showBubbleAndWait = function(b, type) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
|
@ -175,4 +175,4 @@ var showBubbleAndWait = function(b, type) {
|
||||||
} else {
|
} else {
|
||||||
if (interp.checkTimer()) s.hideBubble();
|
if (interp.checkTimer()) s.hideBubble();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var MotionAndPenPrims = function() {}
|
var MotionAndPenPrims = function() {};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.addPrimsTo = function(primTable) {
|
MotionAndPenPrims.prototype.addPrimsTo = function(primTable) {
|
||||||
primTable['forward:'] = this.primMove;
|
primTable['forward:'] = this.primMove;
|
||||||
|
@ -52,60 +52,59 @@ MotionAndPenPrims.prototype.addPrimsTo = function(primTable) {
|
||||||
|
|
||||||
primTable["stampCostume"] = this.primStamp;
|
primTable["stampCostume"] = this.primStamp;
|
||||||
primTable["stampTransparent"] = this.primStampTransparent;
|
primTable["stampTransparent"] = this.primStampTransparent;
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primMove = function(b) {
|
MotionAndPenPrims.prototype.primMove = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
var radians = ((Math.PI * (90 - s.direction)) / 180);
|
var radians = (90 - s.direction) * Math.PI / 180;
|
||||||
var d = interp.arg(b, 0);
|
var d = interp.arg(b, 0);
|
||||||
|
|
||||||
moveSpriteTo(s, s.scratchX + (d * Math.cos(radians)),
|
moveSpriteTo(s, s.scratchX + d * Math.cos(radians), s.scratchY + d * Math.sin(radians));
|
||||||
s.scratchY + (d * Math.sin(radians)));
|
if (s.visible) interp.redraw();
|
||||||
if(s.visible) interp.redraw();
|
};
|
||||||
}
|
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primTurnLeft = function(b) {
|
MotionAndPenPrims.prototype.primTurnLeft = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
var d = s.direction - interp.arg(b, 0);
|
var d = s.direction - interp.arg(b, 0);
|
||||||
s.setDirection(d);
|
s.setDirection(d);
|
||||||
if(s.visible) interp.redraw();
|
if (s.visible) interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primTurnRight = function(b) {
|
MotionAndPenPrims.prototype.primTurnRight = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
var d = s.direction + interp.arg(b, 0);
|
var d = s.direction + interp.arg(b, 0);
|
||||||
s.setDirection(d);
|
s.setDirection(d);
|
||||||
if(s.visible) interp.redraw();
|
if (s.visible) interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primSetDirection = function(b) {
|
MotionAndPenPrims.prototype.primSetDirection = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
s.setDirection(interp.arg(b, 0));
|
s.setDirection(interp.arg(b, 0));
|
||||||
if(s.visible) interp.redraw();
|
if (s.visible) interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primPointTowards = function(b) {
|
MotionAndPenPrims.prototype.primPointTowards = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
var p = mouseOrSpritePosition(interp.arg(b, 0));
|
var p = mouseOrSpritePosition(interp.arg(b, 0));
|
||||||
if ((s == null) || (p == null)) return;
|
if (s == null || p == null) return;
|
||||||
var dx = p.x - s.scratchX;
|
var dx = p.x - s.scratchX;
|
||||||
var dy = p.y - s.scratchY;
|
var dy = p.y - s.scratchY;
|
||||||
var angle = 90 - ((Math.atan2(dy, dx) * 180) / Math.PI);
|
var angle = 90 - Math.atan2(dy, dx) * 180 / Math.PI;
|
||||||
s.setDirection(angle);
|
s.setDirection(angle);
|
||||||
if (s.visible) interp.redraw();
|
if (s.visible) interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primGoTo = function(b) {
|
MotionAndPenPrims.prototype.primGoTo = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) moveSpriteTo(s, interp.arg(b, 0), interp.arg(b, 1));
|
if (s != null) moveSpriteTo(s, interp.arg(b, 0), interp.arg(b, 1));
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primGoToSpriteOrMouse = function(b) {
|
MotionAndPenPrims.prototype.primGoToSpriteOrMouse = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
var p = mouseOrSpritePosition(interp.arg(b, 0));
|
var p = mouseOrSpritePosition(interp.arg(b, 0));
|
||||||
if ((s == null) || (p == null)) return;
|
if (s == null || p == null) return;
|
||||||
moveSpriteTo(s, p.x, p.y);
|
moveSpriteTo(s, p.x, p.y);
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primGlide = function(b) {
|
MotionAndPenPrims.prototype.primGlide = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
|
@ -119,16 +118,15 @@ MotionAndPenPrims.prototype.primGlide = function(b) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// record state: [0]start msecs, [1]duration, [2]startX, [3]startY, [4]endX, [5]endY
|
// record state: [0]start msecs, [1]duration, [2]startX, [3]startY, [4]endX, [5]endY
|
||||||
interp.activeThread.tmpObj =
|
interp.activeThread.tmpObj = [interp.currentMSecs, 1000 * secs, s.scratchX, s.scratchY, destX, destY];
|
||||||
[interp.currentMSecs, 1000 * secs, s.scratchX, s.scratchY, destX, destY];
|
|
||||||
interp.startTimer(secs);
|
interp.startTimer(secs);
|
||||||
} else {
|
} else {
|
||||||
var state = interp.activeThread.tmpObj;
|
var state = interp.activeThread.tmpObj;
|
||||||
if (!interp.checkTimer()) {
|
if (!interp.checkTimer()) {
|
||||||
// in progress: move to intermediate position along path
|
// in progress: move to intermediate position along path
|
||||||
var frac = (interp.currentMSecs - state[0]) / state[1];
|
var frac = (interp.currentMSecs - state[0]) / state[1];
|
||||||
var newX = state[2] + (frac * (state[4] - state[2]));
|
var newX = state[2] + frac * (state[4] - state[2]);
|
||||||
var newY = state[3] + (frac * (state[5] - state[3]));
|
var newY = state[3] + frac * (state[5] - state[3]);
|
||||||
moveSpriteTo(s, newX, newY);
|
moveSpriteTo(s, newX, newY);
|
||||||
} else {
|
} else {
|
||||||
// finished: move to final position and clear state
|
// finished: move to final position and clear state
|
||||||
|
@ -136,27 +134,27 @@ MotionAndPenPrims.prototype.primGlide = function(b) {
|
||||||
interp.activeThread.tmpObj = null;
|
interp.activeThread.tmpObj = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primChangeX = function(b) {
|
MotionAndPenPrims.prototype.primChangeX = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) moveSpriteTo(s, s.scratchX + interp.arg(b, 0), s.scratchY);
|
if (s != null) moveSpriteTo(s, s.scratchX + interp.arg(b, 0), s.scratchY);
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primSetX = function(b) {
|
MotionAndPenPrims.prototype.primSetX = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) moveSpriteTo(s, interp.arg(b, 0), s.scratchY);
|
if (s != null) moveSpriteTo(s, interp.arg(b, 0), s.scratchY);
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primChangeY = function(b) {
|
MotionAndPenPrims.prototype.primChangeY = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) moveSpriteTo(s, s.scratchX, s.scratchY + interp.arg(b, 0));
|
if (s != null) moveSpriteTo(s, s.scratchX, s.scratchY + interp.arg(b, 0));
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primSetY = function(b) {
|
MotionAndPenPrims.prototype.primSetY = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) moveSpriteTo(s, s.scratchX, interp.arg(b, 0));
|
if (s != null) moveSpriteTo(s, s.scratchX, interp.arg(b, 0));
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primBounceOffEdge = function(b) {
|
MotionAndPenPrims.prototype.primBounceOffEdge = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
|
@ -164,7 +162,7 @@ MotionAndPenPrims.prototype.primBounceOffEdge = function(b) {
|
||||||
if (!turnAwayFromEdge(s)) return;
|
if (!turnAwayFromEdge(s)) return;
|
||||||
ensureOnStageOnBounce(s);
|
ensureOnStageOnBounce(s);
|
||||||
if (s.visible) interp.redraw();
|
if (s.visible) interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primSetRotationStyle = function(b) {
|
MotionAndPenPrims.prototype.primSetRotationStyle = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
|
@ -175,95 +173,94 @@ MotionAndPenPrims.prototype.primSetRotationStyle = function(b) {
|
||||||
else if (request == 'left-right') rotationStyle = 'leftRight';
|
else if (request == 'left-right') rotationStyle = 'leftRight';
|
||||||
else if (request == 'none') rotationStyle = 'none';
|
else if (request == 'none') rotationStyle = 'none';
|
||||||
s.setRotationStyle(rotationStyle);
|
s.setRotationStyle(rotationStyle);
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primXPosition = function(b) {
|
MotionAndPenPrims.prototype.primXPosition = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
return (s != null) ? s.scratchX : 0;
|
return s != null ? s.scratchX : 0;
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primYPosition = function(b) {
|
MotionAndPenPrims.prototype.primYPosition = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
return (s != null) ? s.scratchY : 0;
|
return s != null ? s.scratchY : 0;
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primDirection = function(b) {
|
MotionAndPenPrims.prototype.primDirection = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
return (s != null) ? s.direction : 0;
|
return s != null ? s.direction : 0;
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primClear = function(b) {
|
MotionAndPenPrims.prototype.primClear = function(b) {
|
||||||
runtime.stage.clearPenStrokes();
|
runtime.stage.clearPenStrokes();
|
||||||
interp.redraw();
|
interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primPenDown = function(b) {
|
MotionAndPenPrims.prototype.primPenDown = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) s.penIsDown = true;
|
if (s != null) s.penIsDown = true;
|
||||||
stroke(s, s.scratchX, s.scratchY, s.scratchX + 0.2, s.scratchY + 0.2);
|
stroke(s, s.scratchX, s.scratchY, s.scratchX + 0.2, s.scratchY + 0.2);
|
||||||
interp.redraw();
|
interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primPenUp = function(b) {
|
MotionAndPenPrims.prototype.primPenUp = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) s.penIsDown = false;
|
if (s != null) s.penIsDown = false;
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primSetPenColor = function(b) {
|
MotionAndPenPrims.prototype.primSetPenColor = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) s.setPenColor(interp.arg(b, 0));
|
if (s != null) s.setPenColor(interp.arg(b, 0));
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primSetPenHue = function(b) {
|
MotionAndPenPrims.prototype.primSetPenHue = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) s.setPenHue(interp.arg(b, 0));
|
if (s != null) s.setPenHue(interp.arg(b, 0));
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primChangePenHue = function(b) {
|
MotionAndPenPrims.prototype.primChangePenHue = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) s.setPenHue(s.penHue + interp.arg(b, 0));
|
if (s != null) s.setPenHue(s.penHue + interp.arg(b, 0));
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primSetPenShade = function(b) {
|
MotionAndPenPrims.prototype.primSetPenShade = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) s.setPenShade(interp.arg(b, 0));
|
if (s != null) s.setPenShade(interp.arg(b, 0));
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primChangePenShade = function(b) {
|
MotionAndPenPrims.prototype.primChangePenShade = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) s.setPenShade(s.penShade + interp.arg(b, 0));
|
if (s != null) s.setPenShade(s.penShade + interp.arg(b, 0));
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primSetPenSize = function(b) {
|
MotionAndPenPrims.prototype.primSetPenSize = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
var w = Math.max(0, Math.min(interp.arg(b, 0), 100));
|
var w = Math.max(0, Math.min(interp.arg(b, 0), 100));
|
||||||
if (s != null) s.penWidth = w;
|
if (s != null) s.penWidth = w;
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primChangePenSize = function(b) {
|
MotionAndPenPrims.prototype.primChangePenSize = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
var w = Math.max(0, Math.min(s.penWidth + interp.arg(b, 0), 100));
|
var w = Math.max(0, Math.min(s.penWidth + interp.arg(b, 0), 100));
|
||||||
if (s != null) s.penWidth = w;
|
if (s != null) s.penWidth = w;
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primStamp = function(b) {
|
MotionAndPenPrims.prototype.primStamp = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
s.stamp(runtime.stage.lineCache, 100);
|
s.stamp(runtime.stage.lineCache, 100);
|
||||||
}
|
};
|
||||||
|
|
||||||
MotionAndPenPrims.prototype.primStampTransparent = function(b) {
|
MotionAndPenPrims.prototype.primStampTransparent = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
var transparency = Math.max(0, Math.min(interp.arg(b, 0), 100));
|
var transparency = Math.max(0, Math.min(interp.arg(b, 0), 100));
|
||||||
var alpha = 100 - transparency;
|
var alpha = 100 - transparency;
|
||||||
s.stamp(runtime.stage.lineCache, alpha);
|
s.stamp(runtime.stage.lineCache, alpha);
|
||||||
}
|
};
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
var stroke = function(s, oldX, oldY, newX, newY) {
|
var stroke = function(s, oldX, oldY, newX, newY) {
|
||||||
runtime.stage.stroke([oldX, oldY],
|
runtime.stage.stroke([oldX, oldY], [newX, newY], s.penWidth, s.penColorCache);
|
||||||
[newX, newY], s.penWidth, s.penColorCache);
|
|
||||||
interp.redraw();
|
interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
var mouseOrSpritePosition = function(arg) {
|
var mouseOrSpritePosition = function(arg) {
|
||||||
if (arg == "_mouse_") {
|
if (arg == "_mouse_") {
|
||||||
|
@ -275,7 +272,7 @@ var mouseOrSpritePosition = function(arg) {
|
||||||
return new Point(s.scratchX, s.scratchY);
|
return new Point(s.scratchX, s.scratchY);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
};
|
||||||
|
|
||||||
var moveSpriteTo = function(s, newX, newY) {
|
var moveSpriteTo = function(s, newX, newY) {
|
||||||
var oldX = s.scratchX;
|
var oldX = s.scratchX;
|
||||||
|
@ -283,8 +280,8 @@ var moveSpriteTo = function(s, newX, newY) {
|
||||||
s.setXY(newX, newY);
|
s.setXY(newX, newY);
|
||||||
s.keepOnStage();
|
s.keepOnStage();
|
||||||
if (s.penIsDown) stroke(s, oldX, oldY, s.scratchX, s.scratchY);
|
if (s.penIsDown) stroke(s, oldX, oldY, s.scratchX, s.scratchY);
|
||||||
if ((s.penIsDown) || (s.visible)) interp.redraw();
|
if (s.penIsDown || s.visible) interp.redraw();
|
||||||
}
|
};
|
||||||
|
|
||||||
var turnAwayFromEdge = function(s) {
|
var turnAwayFromEdge = function(s) {
|
||||||
// turn away from the nearest edge if it's close enough; otherwise do nothing
|
// turn away from the nearest edge if it's close enough; otherwise do nothing
|
||||||
|
@ -298,23 +295,23 @@ var turnAwayFromEdge = function(s) {
|
||||||
var d4 = Math.max(0, 360 - r.bottom);
|
var d4 = Math.max(0, 360 - r.bottom);
|
||||||
// find the nearest edge
|
// find the nearest edge
|
||||||
var e = 0, minDist = 100000;
|
var e = 0, minDist = 100000;
|
||||||
if (d1 < minDist) { minDist = d1; e = 1 }
|
if (d1 < minDist) { minDist = d1; e = 1; }
|
||||||
if (d2 < minDist) { minDist = d2; e = 2 }
|
if (d2 < minDist) { minDist = d2; e = 2; }
|
||||||
if (d3 < minDist) { minDist = d3; e = 3 }
|
if (d3 < minDist) { minDist = d3; e = 3; }
|
||||||
if (d4 < minDist) { minDist = d4; e = 4 }
|
if (d4 < minDist) { minDist = d4; e = 4; }
|
||||||
if (minDist > 0) return false; // not touching to any edge
|
if (minDist > 0) return false; // not touching to any edge
|
||||||
// point away from nearest edge
|
// point away from nearest edge
|
||||||
var radians = ((90 - s.direction) * Math.PI) / 180;
|
var radians = (90 - s.direction) * Math.PI / 180;
|
||||||
var dx = Math.cos(radians);
|
var dx = Math.cos(radians);
|
||||||
var dy = -Math.sin(radians);
|
var dy = -Math.sin(radians);
|
||||||
if (e == 1) { dx = Math.max(0.2, Math.abs(dx)) }
|
if (e == 1) { dx = Math.max(0.2, Math.abs(dx)); }
|
||||||
if (e == 2) { dy = Math.max(0.2, Math.abs(dy)) }
|
if (e == 2) { dy = Math.max(0.2, Math.abs(dy)); }
|
||||||
if (e == 3) { dx = 0 - Math.max(0.2, Math.abs(dx)) }
|
if (e == 3) { dx = 0 - Math.max(0.2, Math.abs(dx)); }
|
||||||
if (e == 4) { dy = 0 - Math.max(0.2, Math.abs(dy)) }
|
if (e == 4) { dy = 0 - Math.max(0.2, Math.abs(dy)); }
|
||||||
var newDir = ((180 * Math.atan2(dy, dx)) / Math.PI) + 90;
|
var newDir = Math.atan2(dy, dx) * 180 / Math.PI + 90;
|
||||||
s.direction = newDir;
|
s.direction = newDir;
|
||||||
return true;
|
return true;
|
||||||
}
|
};
|
||||||
|
|
||||||
var ensureOnStageOnBounce = function(s) {
|
var ensureOnStageOnBounce = function(s) {
|
||||||
var r = s.getRect();
|
var r = s.getRect();
|
||||||
|
@ -326,4 +323,4 @@ var ensureOnStageOnBounce = function(s) {
|
||||||
if (r.bottom > 360) {
|
if (r.bottom > 360) {
|
||||||
moveSpriteTo(s, s.scratchX, s.scratchY + (r.bottom - 360));
|
moveSpriteTo(s, s.scratchX, s.scratchY + (r.bottom - 360));
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
|
@ -26,29 +26,29 @@ var Primitives = function() {}
|
||||||
|
|
||||||
Primitives.prototype.addPrimsTo = function(primTable) {
|
Primitives.prototype.addPrimsTo = function(primTable) {
|
||||||
// Math primitives
|
// Math primitives
|
||||||
primTable["+"] = function(b) { return interp.arg(b, 0) + interp.arg(b, 1) };
|
primTable["+"] = function(b) { return interp.arg(b, 0) + interp.arg(b, 1); };
|
||||||
primTable["-"] = function(b) { return interp.arg(b, 0) - interp.arg(b, 1) };
|
primTable["-"] = function(b) { return interp.arg(b, 0) - interp.arg(b, 1); };
|
||||||
primTable["*"] = function(b) { return interp.arg(b, 0) * interp.arg(b, 1) };
|
primTable["*"] = function(b) { return interp.arg(b, 0) * interp.arg(b, 1); };
|
||||||
primTable["/"] = function(b) { return interp.arg(b, 0) / interp.arg(b, 1) };
|
primTable["/"] = function(b) { return interp.arg(b, 0) / interp.arg(b, 1); };
|
||||||
primTable["%"] = function(b) { return interp.arg(b, 0) % interp.arg(b, 1) };
|
primTable["%"] = function(b) { return interp.arg(b, 0) % interp.arg(b, 1); };
|
||||||
primTable["randomFrom:to:"] = this.primRandom;
|
primTable["randomFrom:to:"] = this.primRandom;
|
||||||
primTable["<"] = function(b) { return (interp.arg(b, 0) < interp.arg(b, 1)) };
|
primTable["<"] = function(b) { return (interp.arg(b, 0) < interp.arg(b, 1)); };
|
||||||
primTable["="] = function(b) { return (interp.arg(b, 0) == interp.arg(b, 1)) };
|
primTable["="] = function(b) { return (interp.arg(b, 0) == interp.arg(b, 1)); };
|
||||||
primTable[">"] = function(b) { return (interp.arg(b, 0) > interp.arg(b, 1)) };
|
primTable[">"] = function(b) { return (interp.arg(b, 0) > interp.arg(b, 1)); };
|
||||||
primTable["&"] = function(b) { return interp.arg(b, 0) && interp.arg(b, 1) };
|
primTable["&"] = function(b) { return interp.arg(b, 0) && interp.arg(b, 1); };
|
||||||
primTable["|"] = function(b) { return interp.arg(b, 0) || interp.arg(b, 1) };
|
primTable["|"] = function(b) { return interp.arg(b, 0) || interp.arg(b, 1); };
|
||||||
primTable["not"] = function(b) { return !interp.arg(b, 0) };
|
primTable["not"] = function(b) { return !interp.arg(b, 0) };
|
||||||
primTable["abs"] = function(b) { return Math.abs(interp.arg(b, 0)) };
|
primTable["abs"] = function(b) { return Math.abs(interp.arg(b, 0)) };
|
||||||
primTable["sqrt"] = function(b) { return Math.sqrt(interp.arg(b, 0)) };
|
primTable["sqrt"] = function(b) { return Math.sqrt(interp.arg(b, 0)) };
|
||||||
|
|
||||||
primTable["\\\\"] = this.primModulo;
|
primTable["\\\\"] = this.primModulo;
|
||||||
primTable["rounded"] = function(b) { return Math.round(interp.arg(b, 0)) };
|
primTable["rounded"] = function(b) { return Math.round(interp.arg(b, 0)); };
|
||||||
primTable["computeFunction:of:"] = this.primMathFunction;
|
primTable["computeFunction:of:"] = this.primMathFunction;
|
||||||
|
|
||||||
// String primitives
|
// String primitives
|
||||||
primTable["concatenate:with:"] = function(b) { return "" + interp.arg(b, 0) + interp.arg(b, 1) };
|
primTable["concatenate:with:"] = function(b) { return "" + interp.arg(b, 0) + interp.arg(b, 1); };
|
||||||
primTable["letter:of:"] = this.primLetterOf;
|
primTable["letter:of:"] = this.primLetterOf;
|
||||||
primTable["stringLength:"] = function(b) { return interp.arg(b, 0).length };
|
primTable["stringLength:"] = function(b) { return interp.arg(b, 0).length; };
|
||||||
|
|
||||||
new VarListPrims().addPrimsTo(primTable);
|
new VarListPrims().addPrimsTo(primTable);
|
||||||
new MotionAndPenPrims().addPrimsTo(primTable);
|
new MotionAndPenPrims().addPrimsTo(primTable);
|
||||||
|
@ -60,20 +60,20 @@ Primitives.prototype.addPrimsTo = function(primTable) {
|
||||||
Primitives.prototype.primRandom = function(b) {
|
Primitives.prototype.primRandom = function(b) {
|
||||||
var n1 = interp.arg(b, 0);
|
var n1 = interp.arg(b, 0);
|
||||||
var n2 = interp.arg(b, 1);
|
var n2 = interp.arg(b, 1);
|
||||||
var low = (n1 <= n2) ? n1 : n2;
|
var low = n1 <= n2 ? n1 : n2;
|
||||||
var hi = (n1 <= n2) ? n2 : n1;
|
var hi = n1 <= n2 ? n2 : n1;
|
||||||
if(low == hi) return low;
|
if (low == hi) return low;
|
||||||
// if both low and hi are ints, truncate the result to an int
|
// if both low and hi are ints, truncate the result to an int
|
||||||
if ((Math.floor(low) == low) && (Math.floor(hi) == hi)) {
|
if (Math.floor(low) == low && Math.floor(hi) == hi) {
|
||||||
return low + Math.floor(Math.random() * ((hi + 1) - low));
|
return low + Math.floor(Math.random() * (hi + 1 - low));
|
||||||
}
|
}
|
||||||
return (Math.random() * (hi - low)) + low;
|
return Math.random() * (hi - low) + low;
|
||||||
}
|
}
|
||||||
|
|
||||||
Primitives.prototype.primLetterOf = function(b) {
|
Primitives.prototype.primLetterOf = function(b) {
|
||||||
var s = interp.arg(b, 1);
|
var s = interp.arg(b, 1);
|
||||||
var i = interp.arg(b, 0) - 1;
|
var i = interp.arg(b, 0) - 1;
|
||||||
if ((i < 0) || (i >= s.length)) return "";
|
if (i < 0 || i >= s.length) return "";
|
||||||
return s.charAt(i);
|
return s.charAt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,12 +90,12 @@ Primitives.prototype.primMathFunction = function(b) {
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case "abs": return Math.abs(n);
|
case "abs": return Math.abs(n);
|
||||||
case "sqrt": return Math.sqrt(n);
|
case "sqrt": return Math.sqrt(n);
|
||||||
case "sin": return Math.sin((Math.PI * n) / 180);
|
case "sin": return Math.sin(n * Math.PI / 180);
|
||||||
case "cos": return Math.cos((Math.PI * n) / 180);
|
case "cos": return Math.cos(n * Math.PI / 180);
|
||||||
case "tan": return Math.tan((Math.PI * n) / 180);
|
case "tan": return Math.tan(n * Math.PI / 180);
|
||||||
case "asin": return (Math.asin(n) * 180) / Math.PI;
|
case "asin": return Math.asin(n) * 180 / Math.PI;
|
||||||
case "acos": return (Math.acos(n) * 180) / Math.PI;
|
case "acos": return Math.acos(n) * 180 / Math.PI;
|
||||||
case "atan": return (Math.atan(n) * 180) / Math.PI;
|
case "atan": return Math.atan(n) * 180 / Math.PI;
|
||||||
case "ln": return Math.log(n);
|
case "ln": return Math.log(n);
|
||||||
case "log": return Math.log(n) / Math.LN10;
|
case "log": return Math.log(n) / Math.LN10;
|
||||||
case "e ^": return Math.exp(n);
|
case "e ^": return Math.exp(n);
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var SensingPrims = function() {}
|
var SensingPrims = function() {};
|
||||||
|
|
||||||
SensingPrims.prototype.addPrimsTo = function(primTable) {
|
SensingPrims.prototype.addPrimsTo = function(primTable) {
|
||||||
primTable['touching:'] = this.primTouching;
|
primTable['touching:'] = this.primTouching;
|
||||||
|
@ -30,9 +30,9 @@ SensingPrims.prototype.addPrimsTo = function(primTable) {
|
||||||
|
|
||||||
primTable['getAttribute:of:'] = this.primGetAttribute;
|
primTable['getAttribute:of:'] = this.primGetAttribute;
|
||||||
|
|
||||||
primTable['timeAndDate'] = this.primTimeDate;
|
primTable['timeAndDate'] = function(b){ return runtime.getTimeString(interp.arg(b, 0)); };
|
||||||
primTable['timestamp'] = this.primTimestamp;
|
primTable['timestamp'] = this.primTimestamp;
|
||||||
}
|
};
|
||||||
|
|
||||||
SensingPrims.prototype.primTouching = function(b) {
|
SensingPrims.prototype.primTouching = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
|
@ -51,7 +51,7 @@ SensingPrims.prototype.primTouching = function(b) {
|
||||||
if (s2 == null || !s2.visible) return false;
|
if (s2 == null || !s2.visible) return false;
|
||||||
|
|
||||||
return spriteHitTest(s, s2);
|
return spriteHitTest(s, s2);
|
||||||
}
|
};
|
||||||
|
|
||||||
SensingPrims.prototype.primTouchingColor = function(b) {
|
SensingPrims.prototype.primTouchingColor = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
|
@ -60,7 +60,7 @@ SensingPrims.prototype.primTouchingColor = function(b) {
|
||||||
var color = interp.arg(b, 0);
|
var color = interp.arg(b, 0);
|
||||||
|
|
||||||
return stageColorHitTest(s, color);
|
return stageColorHitTest(s, color);
|
||||||
}
|
};
|
||||||
|
|
||||||
SensingPrims.prototype.primColorTouchingColor = function(b) {
|
SensingPrims.prototype.primColorTouchingColor = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
|
@ -70,7 +70,7 @@ SensingPrims.prototype.primColorTouchingColor = function(b) {
|
||||||
var stageColor = interp.arg(b, 1);
|
var stageColor = interp.arg(b, 1);
|
||||||
|
|
||||||
return stageColorByColorHitTest(s, myColor, stageColor);
|
return stageColorByColorHitTest(s, myColor, stageColor);
|
||||||
}
|
};
|
||||||
|
|
||||||
var spriteHitTest = function(a, b) {
|
var spriteHitTest = function(a, b) {
|
||||||
var hitCanvas = document.createElement('canvas');
|
var hitCanvas = document.createElement('canvas');
|
||||||
|
@ -91,7 +91,7 @@ var spriteHitTest = function(a, b) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
var stageColorHitTest = function(target, color) {
|
var stageColorHitTest = function(target, color) {
|
||||||
var r, g, b;
|
var r, g, b;
|
||||||
|
@ -123,18 +123,18 @@ var stageColorHitTest = function(target, color) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
var stageColorByColorHitTest = function(target, myColor, otherColor) {
|
var stageColorByColorHitTest = function(target, myColor, otherColor) {
|
||||||
var threshold_acceptable = function(a, b, c, x, y, z) {
|
var threshold_acceptable = function(a, b, c, x, y, z) {
|
||||||
diff_a = Math.abs(a-x);
|
var diff_a = Math.abs(a-x);
|
||||||
diff_b = Math.abs(b-y);
|
var diff_b = Math.abs(b-y);
|
||||||
diff_c = Math.abs(c-z);
|
var diff_c = Math.abs(c-z);
|
||||||
if (diff_a + diff_b + diff_c < 100) {
|
if (diff_a + diff_b + diff_c < 100) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
var targetCanvas = document.createElement('canvas');
|
var targetCanvas = document.createElement('canvas');
|
||||||
targetCanvas.width = 480;
|
targetCanvas.width = 480;
|
||||||
targetCanvas.height = 360;
|
targetCanvas.height = 360;
|
||||||
|
@ -157,22 +157,22 @@ var stageColorByColorHitTest = function(target, myColor, otherColor) {
|
||||||
var hitCanvas = document.createElement('canvas');
|
var hitCanvas = document.createElement('canvas');
|
||||||
hitCanvas.width = 480;
|
hitCanvas.width = 480;
|
||||||
hitCanvas.height = 360;
|
hitCanvas.height = 360;
|
||||||
hitCtx = hitCanvas.getContext('2d');
|
var hitCtx = hitCanvas.getContext('2d');
|
||||||
$.each(runtime.sprites, function(i, sprite) {
|
$.each(runtime.sprites, function(i, sprite) {
|
||||||
if (sprite != target)
|
if (sprite != target) {
|
||||||
sprite.stamp(hitCtx, 100);
|
sprite.stamp(hitCtx, 100);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var hitData = hitCtx.getImageData(0, 0, hitCanvas.width, hitCanvas.height).data;
|
var hitData = hitCtx.getImageData(0, 0, hitCanvas.width, hitCanvas.height).data;
|
||||||
var pxCount = targetData.length;
|
var pxCount = targetData.length;
|
||||||
for (var i = 0; i < pxCount; i += 4) {
|
for (var i = 0; i < pxCount; i += 4) {
|
||||||
if (threshold_acceptable(targetData[i], targetData[i+1], targetData[i+2], mr, mg, mb)
|
if (threshold_acceptable(targetData[i], targetData[i+1], targetData[i+2], mr, mg, mb) && threshold_acceptable(hitData[i], hitData[i+1], hitData[i+2], or, og, ob)) {
|
||||||
&& threshold_acceptable(hitData[i], hitData[i+1], hitData[i+2], or, og, ob)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
SensingPrims.prototype.primKeyPressed = function(b) {
|
SensingPrims.prototype.primKeyPressed = function(b) {
|
||||||
var key = interp.arg(b, 0);
|
var key = interp.arg(b, 0);
|
||||||
|
@ -184,7 +184,7 @@ SensingPrims.prototype.primKeyPressed = function(b) {
|
||||||
if (key == "down arrow") ch = 40;
|
if (key == "down arrow") ch = 40;
|
||||||
if (key == "space") ch = 32;
|
if (key == "space") ch = 32;
|
||||||
return (typeof(runtime.keysDown[ch]) != 'undefined');
|
return (typeof(runtime.keysDown[ch]) != 'undefined');
|
||||||
}
|
};
|
||||||
|
|
||||||
SensingPrims.prototype.primDistanceTo = function(b) {
|
SensingPrims.prototype.primDistanceTo = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
|
@ -193,7 +193,7 @@ SensingPrims.prototype.primDistanceTo = function(b) {
|
||||||
var dx = p.x - s.scratchX;
|
var dx = p.x - s.scratchX;
|
||||||
var dy = p.y - s.scratchY;
|
var dy = p.y - s.scratchY;
|
||||||
return Math.sqrt((dx * dx) + (dy * dy));
|
return Math.sqrt((dx * dx) + (dy * dy));
|
||||||
}
|
};
|
||||||
|
|
||||||
SensingPrims.prototype.primGetAttribute = function(b) {
|
SensingPrims.prototype.primGetAttribute = function(b) {
|
||||||
var attr = interp.arg(b, 0);
|
var attr = interp.arg(b, 0);
|
||||||
|
@ -207,7 +207,7 @@ SensingPrims.prototype.primGetAttribute = function(b) {
|
||||||
if (attr == 'size') return targetSprite.getSize();
|
if (attr == 'size') return targetSprite.getSize();
|
||||||
if (attr == 'volume') return targetSprite.volume;
|
if (attr == 'volume') return targetSprite.volume;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
};
|
||||||
|
|
||||||
SensingPrims.prototype.primTimeDate = function(b) {
|
SensingPrims.prototype.primTimeDate = function(b) {
|
||||||
var dt = interp.arg(b, 0);
|
var dt = interp.arg(b, 0);
|
||||||
|
@ -220,13 +220,16 @@ SensingPrims.prototype.primTimeDate = function(b) {
|
||||||
if (dt == 'minute') return now.getMinutes();
|
if (dt == 'minute') return now.getMinutes();
|
||||||
if (dt == 'second') return now.getSeconds();
|
if (dt == 'second') return now.getSeconds();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
};
|
||||||
|
|
||||||
SensingPrims.prototype.primTimestamp = function(b) {
|
SensingPrims.prototype.primTimestamp = function(b) {
|
||||||
var now = new Date(), epoch = new Date(2000,0,1), dst = now.getTimezoneOffset() - epoch.getTimezoneOffset(), msSince = now.getTime() - epoch.getTime();
|
var now = new Date();
|
||||||
|
var epoch = new Date(2000, 0, 1);
|
||||||
|
var dst = now.getTimezoneOffset() - epoch.getTimezoneOffset();
|
||||||
|
var msSince = now.getTime() - epoch.getTime();
|
||||||
msSince += (now.getTimezoneOffset() - dst) * 60000;
|
msSince += (now.getTimezoneOffset() - dst) * 60000;
|
||||||
return msSince / 86400000;
|
return msSince / 86400000;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
SensingPrims.prototype.mouseOrSpritePosition = function(arg) {
|
SensingPrims.prototype.mouseOrSpritePosition = function(arg) {
|
||||||
|
@ -239,4 +242,4 @@ SensingPrims.prototype.mouseOrSpritePosition = function(arg) {
|
||||||
return new Point(s.scratchX, s.scratchY);
|
return new Point(s.scratchX, s.scratchY);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
};
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var SoundPrims = function() {}
|
var SoundPrims = function() {};
|
||||||
|
|
||||||
SoundPrims.prototype.addPrimsTo = function(primTable) {
|
SoundPrims.prototype.addPrimsTo = function(primTable) {
|
||||||
primTable['playSound:'] = this.primPlaySound;
|
primTable['playSound:'] = this.primPlaySound;
|
||||||
|
@ -34,7 +34,7 @@ SoundPrims.prototype.addPrimsTo = function(primTable) {
|
||||||
primTable['changeTempoBy:'] = function(b) { runtime.stage.data.tempoBPM = runtime.stage.data.tempoBPM + interp.arg(b, 0); };
|
primTable['changeTempoBy:'] = function(b) { runtime.stage.data.tempoBPM = runtime.stage.data.tempoBPM + interp.arg(b, 0); };
|
||||||
primTable['setTempoTo:'] = function(b) { runtime.stage.data.tempoBPM = interp.arg(b, 0); };
|
primTable['setTempoTo:'] = function(b) { runtime.stage.data.tempoBPM = interp.arg(b, 0); };
|
||||||
primTable['tempo'] = function(b) { return runtime.stage.data.tempoBPM; };
|
primTable['tempo'] = function(b) { return runtime.stage.data.tempoBPM; };
|
||||||
}
|
};
|
||||||
|
|
||||||
var playSound = function(snd) {
|
var playSound = function(snd) {
|
||||||
if (snd.source) {
|
if (snd.source) {
|
||||||
|
@ -64,7 +64,7 @@ var playSound = function(snd) {
|
||||||
runtime.audioPlaying.push(snd);
|
runtime.audioPlaying.push(snd);
|
||||||
snd.source.noteOn(0);
|
snd.source.noteOn(0);
|
||||||
return snd.source;
|
return snd.source;
|
||||||
}
|
};
|
||||||
|
|
||||||
var playDrum = function(drum, secs, client) {
|
var playDrum = function(drum, secs, client) {
|
||||||
var player = SoundBank.getDrumPlayer(drum, secs);
|
var player = SoundBank.getDrumPlayer(drum, secs);
|
||||||
|
@ -83,7 +83,7 @@ var playDrum = function(drum, secs, client) {
|
||||||
}
|
}
|
||||||
window.setTimeout(source.finished, secs * 1000);
|
window.setTimeout(source.finished, secs * 1000);
|
||||||
return player;
|
return player;
|
||||||
}
|
};
|
||||||
|
|
||||||
var playNote = function(instrument, midiKey, secs, client) {
|
var playNote = function(instrument, midiKey, secs, client) {
|
||||||
var player = SoundBank.getNotePlayer(instrument, midiKey);
|
var player = SoundBank.getNotePlayer(instrument, midiKey);
|
||||||
|
@ -101,7 +101,7 @@ var playNote = function(instrument, midiKey, secs, client) {
|
||||||
}
|
}
|
||||||
window.setTimeout(source.finished, secs * 1000);
|
window.setTimeout(source.finished, secs * 1000);
|
||||||
return player;
|
return player;
|
||||||
}
|
};
|
||||||
|
|
||||||
var stopAllSounds = function() {
|
var stopAllSounds = function() {
|
||||||
var oldPlaying = runtime.audioPlaying;
|
var oldPlaying = runtime.audioPlaying;
|
||||||
|
@ -121,14 +121,14 @@ var stopAllSounds = function() {
|
||||||
oldPlaying[s].finished();
|
oldPlaying[s].finished();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
SoundPrims.prototype.primPlaySound = function(b) {
|
SoundPrims.prototype.primPlaySound = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s == null) return;
|
if (s == null) return;
|
||||||
var snd = s.soundNamed(interp.arg(b, 0));
|
var snd = s.soundNamed(interp.arg(b, 0));
|
||||||
if (snd != null) playSound(snd);
|
if (snd != null) playSound(snd);
|
||||||
}
|
};
|
||||||
|
|
||||||
SoundPrims.prototype.primPlaySoundUntilDone = function(b) {
|
SoundPrims.prototype.primPlaySoundUntilDone = function(b) {
|
||||||
var activeThread = interp.activeThread;
|
var activeThread = interp.activeThread;
|
||||||
|
@ -145,11 +145,11 @@ SoundPrims.prototype.primPlaySoundUntilDone = function(b) {
|
||||||
} else {
|
} else {
|
||||||
interp.yield = true;
|
interp.yield = true;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
var beatsToSeconds = function(beats) {
|
var beatsToSeconds = function(beats) {
|
||||||
return (beats * 60) / runtime.stage.data.tempoBPM;
|
return beats * 60 / runtime.stage.data.tempoBPM;
|
||||||
}
|
};
|
||||||
|
|
||||||
SoundPrims.prototype.primPlayNote = function(b) {
|
SoundPrims.prototype.primPlayNote = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
|
@ -162,7 +162,7 @@ SoundPrims.prototype.primPlayNote = function(b) {
|
||||||
} else {
|
} else {
|
||||||
interp.checkTimer();
|
interp.checkTimer();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
SoundPrims.prototype.primPlayDrum = function(b) {
|
SoundPrims.prototype.primPlayDrum = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
|
@ -175,7 +175,7 @@ SoundPrims.prototype.primPlayDrum = function(b) {
|
||||||
} else {
|
} else {
|
||||||
interp.checkTimer();
|
interp.checkTimer();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
SoundPrims.prototype.primPlayRest = function(b) {
|
SoundPrims.prototype.primPlayRest = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
|
@ -186,28 +186,28 @@ SoundPrims.prototype.primPlayRest = function(b) {
|
||||||
} else {
|
} else {
|
||||||
interp.checkTimer();
|
interp.checkTimer();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
SoundPrims.prototype.primSetInstrument = function(b) {
|
SoundPrims.prototype.primSetInstrument = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) s.instrument = interp.arg(b, 0);
|
if (s != null) s.instrument = interp.arg(b, 0);
|
||||||
}
|
};
|
||||||
|
|
||||||
SoundPrims.prototype.primStopAllSounds = function(b) {
|
SoundPrims.prototype.primStopAllSounds = function(b) {
|
||||||
stopAllSounds();
|
stopAllSounds();
|
||||||
}
|
};
|
||||||
|
|
||||||
SoundPrims.prototype.primChangeVolume = function(b) {
|
SoundPrims.prototype.primChangeVolume = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) s.volume += interp.arg(b, 0);
|
if (s != null) s.volume += interp.arg(b, 0);
|
||||||
}
|
};
|
||||||
|
|
||||||
SoundPrims.prototype.primSetVolume = function(b) {
|
SoundPrims.prototype.primSetVolume = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s != null) s.volume = interp.arg(b, 0);
|
if (s != null) s.volume = interp.arg(b, 0);
|
||||||
}
|
};
|
||||||
|
|
||||||
SoundPrims.prototype.primVolume = function(b) {
|
SoundPrims.prototype.primVolume = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
return (s != null) ? s.volume : 0;
|
return s != null ? s.volume : 0;
|
||||||
}
|
};
|
||||||
|
|
|
@ -34,7 +34,7 @@ VarListPrims.prototype.addPrimsTo = function(primTable) {
|
||||||
primTable['lineCountOfList:'] = this.primListLength;
|
primTable['lineCountOfList:'] = this.primListLength;
|
||||||
primTable['getLine:ofList:'] = this.primListGetLine;
|
primTable['getLine:ofList:'] = this.primListGetLine;
|
||||||
primTable['list:contains:'] = this.primListContains;
|
primTable['list:contains:'] = this.primListContains;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Variable primitive implementations
|
// Variable primitive implementations
|
||||||
|
|
||||||
|
@ -42,21 +42,23 @@ VarListPrims.prototype.primReadVar = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s == null) return;
|
if (s == null) return;
|
||||||
var targetVar = interp.arg(b, 0);
|
var targetVar = interp.arg(b, 0);
|
||||||
if (targetVar in s.variables)
|
if (targetVar in s.variables) {
|
||||||
return s.variables[targetVar];
|
return s.variables[targetVar];
|
||||||
else if (targetVar in runtime.stage.variables)
|
} else if (targetVar in runtime.stage.variables) {
|
||||||
return runtime.stage.variables[targetVar];
|
return runtime.stage.variables[targetVar];
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
VarListPrims.prototype.primSetVar = function(b) {
|
VarListPrims.prototype.primSetVar = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
if (s == null) return;
|
if (s == null) return;
|
||||||
var targetVar = interp.arg(b, 0);
|
var targetVar = interp.arg(b, 0);
|
||||||
if (targetVar in s.variables)
|
if (targetVar in s.variables) {
|
||||||
s.variables[targetVar] = interp.arg(b, 1);
|
s.variables[targetVar] = interp.arg(b, 1);
|
||||||
else if (targetVar in runtime.stage.variables)
|
} else if (targetVar in runtime.stage.variables) {
|
||||||
runtime.stage.variables[targetVar] = interp.arg(b, 1);
|
runtime.stage.variables[targetVar] = interp.arg(b, 1);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
VarListPrims.prototype.primChangeVar = function(b) {
|
VarListPrims.prototype.primChangeVar = function(b) {
|
||||||
var s = interp.targetSprite();
|
var s = interp.targetSprite();
|
||||||
|
@ -69,7 +71,7 @@ VarListPrims.prototype.primChangeVar = function(b) {
|
||||||
runtime.stage.variables[targetVar] = parseFloat(runtime.stage.variables[targetVar]);
|
runtime.stage.variables[targetVar] = parseFloat(runtime.stage.variables[targetVar]);
|
||||||
runtime.stage.variables[targetVar] += interp.arg(b, 1);
|
runtime.stage.variables[targetVar] += interp.arg(b, 1);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
VarListPrims.prototype.primHideVar = function(b) {
|
VarListPrims.prototype.primHideVar = function(b) {
|
||||||
var targetVar = interp.arg(b, 0);
|
var targetVar = interp.arg(b, 0);
|
||||||
|
@ -79,7 +81,7 @@ VarListPrims.prototype.primHideVar = function(b) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
VarListPrims.prototype.primShowVar = function(b) {
|
VarListPrims.prototype.primShowVar = function(b) {
|
||||||
var targetVar = interp.arg(b, 0);
|
var targetVar = interp.arg(b, 0);
|
||||||
|
@ -89,7 +91,7 @@ VarListPrims.prototype.primShowVar = function(b) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// List primitive implementations
|
// List primitive implementations
|
||||||
|
|
||||||
|
@ -102,20 +104,20 @@ var findList = function(targetSprite, listName) {
|
||||||
return runtime.stage.lists[listName].contents;
|
return runtime.stage.lists[listName].contents;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
};
|
||||||
|
|
||||||
VarListPrims.prototype.primReadList = function(b) {
|
VarListPrims.prototype.primReadList = function(b) {
|
||||||
var list = findList(interp.targetSprite(), interp.arg(b, 0));
|
var list = findList(interp.targetSprite(), interp.arg(b, 0));
|
||||||
if (list) {
|
if (list) {
|
||||||
var allOne = list.map(function(val){return val.length}).reduce(function(old,val){return old+val},0)===list.length;
|
var allOne = list.map(function(val) { return val.length; }).reduce(function(old,val) { return old + val; }, 0) === list.length;
|
||||||
return list.join(allOne?'':' ');
|
return list.join(allOne ? '' : ' ');
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
VarListPrims.prototype.primListAppend = function(b) {
|
VarListPrims.prototype.primListAppend = function(b) {
|
||||||
var list = findList(interp.targetSprite(), interp.arg(b, 1));
|
var list = findList(interp.targetSprite(), interp.arg(b, 1));
|
||||||
if (list) list.push(interp.arg(b, 0));
|
if (list) list.push(interp.arg(b, 0));
|
||||||
}
|
};
|
||||||
|
|
||||||
VarListPrims.prototype.primListDeleteLine = function(b) {
|
VarListPrims.prototype.primListDeleteLine = function(b) {
|
||||||
var list = findList(interp.targetSprite(), interp.arg(b, 1));
|
var list = findList(interp.targetSprite(), interp.arg(b, 1));
|
||||||
|
@ -124,7 +126,7 @@ VarListPrims.prototype.primListDeleteLine = function(b) {
|
||||||
if (line == 'all' || list.length == 0) list.length = 0;
|
if (line == 'all' || list.length == 0) list.length = 0;
|
||||||
else if (line == 'last') list.splice(list.length - 1, 1);
|
else if (line == 'last') list.splice(list.length - 1, 1);
|
||||||
else if (parseInt(line) - 1 in list) list.splice(parseInt(line) - 1, 1);
|
else if (parseInt(line) - 1 in list) list.splice(parseInt(line) - 1, 1);
|
||||||
}
|
};
|
||||||
|
|
||||||
VarListPrims.prototype.primListInsertAt = function(b) {
|
VarListPrims.prototype.primListInsertAt = function(b) {
|
||||||
var list = findList(interp.targetSprite(), interp.arg(b, 2));
|
var list = findList(interp.targetSprite(), interp.arg(b, 2));
|
||||||
|
@ -138,7 +140,7 @@ VarListPrims.prototype.primListInsertAt = function(b) {
|
||||||
if (position > list.length) return;
|
if (position > list.length) return;
|
||||||
|
|
||||||
list.splice(position, 0, newItem);
|
list.splice(position, 0, newItem);
|
||||||
}
|
};
|
||||||
|
|
||||||
VarListPrims.prototype.primListSetLine = function(b) {
|
VarListPrims.prototype.primListSetLine = function(b) {
|
||||||
var list = findList(interp.targetSprite(), interp.arg(b, 1));
|
var list = findList(interp.targetSprite(), interp.arg(b, 1));
|
||||||
|
@ -149,16 +151,17 @@ VarListPrims.prototype.primListSetLine = function(b) {
|
||||||
if (position == 'last') position = list.length - 1;
|
if (position == 'last') position = list.length - 1;
|
||||||
else if (position == 'random') position = Math.floor(Math.random() * list.length);
|
else if (position == 'random') position = Math.floor(Math.random() * list.length);
|
||||||
else position = parseInt(position) - 1;
|
else position = parseInt(position) - 1;
|
||||||
|
|
||||||
if (position > list.length - 1) return;
|
if (position > list.length - 1) return;
|
||||||
|
|
||||||
list[position] = newItem;
|
list[position] = newItem;
|
||||||
}
|
};
|
||||||
|
|
||||||
VarListPrims.prototype.primListLength = function(b) {
|
VarListPrims.prototype.primListLength = function(b) {
|
||||||
var list = findList(interp.targetSprite(), interp.arg(b, 0));
|
var list = findList(interp.targetSprite(), interp.arg(b, 0));
|
||||||
if (!list) return 0;
|
if (!list) return 0;
|
||||||
return list.length;
|
return list.length;
|
||||||
}
|
};
|
||||||
|
|
||||||
VarListPrims.prototype.primListGetLine = function(b) {
|
VarListPrims.prototype.primListGetLine = function(b) {
|
||||||
var list = findList(interp.targetSprite(), interp.arg(b, 1));
|
var list = findList(interp.targetSprite(), interp.arg(b, 1));
|
||||||
|
@ -169,7 +172,7 @@ VarListPrims.prototype.primListGetLine = function(b) {
|
||||||
else if (line == 'last') line = list.length;
|
else if (line == 'last') line = list.length;
|
||||||
else if (list.length < line) return 0;
|
else if (list.length < line) return 0;
|
||||||
return list[line - 1];
|
return list[line - 1];
|
||||||
}
|
};
|
||||||
|
|
||||||
VarListPrims.prototype.primListContains = function(b) {
|
VarListPrims.prototype.primListContains = function(b) {
|
||||||
var list = findList(interp.targetSprite(), interp.arg(b, 0));
|
var list = findList(interp.targetSprite(), interp.arg(b, 0));
|
||||||
|
@ -177,4 +180,4 @@ VarListPrims.prototype.primListContains = function(b) {
|
||||||
var searchItem = interp.arg(b, 1);
|
var searchItem = interp.arg(b, 1);
|
||||||
if (parseFloat(searchItem) == searchItem) searchItem = parseFloat(searchItem);
|
if (parseFloat(searchItem) == searchItem) searchItem = parseFloat(searchItem);
|
||||||
return $.inArray(searchItem, list) > -1;
|
return $.inArray(searchItem, list) > -1;
|
||||||
}
|
};
|
||||||
|
|
|
@ -65,11 +65,11 @@ var NotePlayer = function(wavFileData, originalPitch, loopStart, loopEnd, env) {
|
||||||
if (env) {
|
if (env) {
|
||||||
this.attackEnd = env[0] * 44.100;
|
this.attackEnd = env[0] * 44.100;
|
||||||
if (this.attackEnd > 0) this.attackRate = Math.pow(33000, 1 / this.attackEnd);
|
if (this.attackEnd > 0) this.attackRate = Math.pow(33000, 1 / this.attackEnd);
|
||||||
this.holdEnd = this.attackEnd + (env[1] * 44.100);
|
this.holdEnd = this.attackEnd + env[1] * 44.100;
|
||||||
var decayCount = env[2] * 44100;
|
var decayCount = env[2] * 44100;
|
||||||
this.decayRate = (decayCount == 0) ? 1 : Math.pow(33000, -1 / decayCount);
|
this.decayRate = decayCount == 0 ? 1 : Math.pow(33000, -1 / decayCount);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
NotePlayer.prototype = Object.create(SoundDecoder.prototype);
|
NotePlayer.prototype = Object.create(SoundDecoder.prototype);
|
||||||
NotePlayer.prototype.constructor = NotePlayer;
|
NotePlayer.prototype.constructor = NotePlayer;
|
||||||
|
@ -79,14 +79,14 @@ NotePlayer.prototype.setNoteAndDuration = function(midiKey, secs) {
|
||||||
var pitch = 440 * Math.pow(2, (midiKey - 69) / 12); // midi key 69 is A (440 Hz)
|
var pitch = 440 * Math.pow(2, (midiKey - 69) / 12); // midi key 69 is A (440 Hz)
|
||||||
this.stepSize = pitch / (2 * this.originalPitch); // adjust for original sampling rate of 22050
|
this.stepSize = pitch / (2 * this.originalPitch); // adjust for original sampling rate of 22050
|
||||||
this.setDuration(secs);
|
this.setDuration(secs);
|
||||||
}
|
};
|
||||||
|
|
||||||
NotePlayer.prototype.setDuration = function(secs) {
|
NotePlayer.prototype.setDuration = function(secs) {
|
||||||
this.samplesSinceStart = 0;
|
this.samplesSinceStart = 0;
|
||||||
this.samplesRemaining = 44100 * secs;
|
this.samplesRemaining = 44100 * secs;
|
||||||
if (!this.isLooped) this.samplesRemaining = Math.min(this.samplesRemaining, this.endOffset / this.stepSize);
|
if (!this.isLooped) this.samplesRemaining = Math.min(this.samplesRemaining, this.endOffset / this.stepSize);
|
||||||
this.envelopeValue = (this.attackEnd > 0) ? 1 / 33000 : 1;
|
this.envelopeValue = this.attackEnd > 0 ? 1 / 33000 : 1;
|
||||||
}
|
};
|
||||||
|
|
||||||
NotePlayer.prototype.interpolatedSample = function() {
|
NotePlayer.prototype.interpolatedSample = function() {
|
||||||
if (this.samplesRemaining-- <= 0) { this.noteFinished(); return 0; }
|
if (this.samplesRemaining-- <= 0) { this.noteFinished(); return 0; }
|
||||||
|
@ -99,11 +99,11 @@ NotePlayer.prototype.interpolatedSample = function() {
|
||||||
var frac = this.index - i;
|
var frac = this.index - i;
|
||||||
var curr = this.rawSample(i);
|
var curr = this.rawSample(i);
|
||||||
var next = this.rawSample(i + 1);
|
var next = this.rawSample(i + 1);
|
||||||
var sample = (curr + (frac * (next - curr))) / 100000; // xxx 32000; attenuate...
|
var sample = (curr + frac * (next - curr)) / 100000; // xxx 32000; attenuate...
|
||||||
if (this.samplesRemaining < 1000) sample *= (this.samplesRemaining / 1000.0); // relaase phease
|
if (this.samplesRemaining < 1000) sample *= (this.samplesRemaining / 1000.0); // relaase phease
|
||||||
this.updateEnvelope();
|
this.updateEnvelope();
|
||||||
return this.envelopeValue * sample;
|
return this.envelopeValue * sample;
|
||||||
}
|
};
|
||||||
|
|
||||||
NotePlayer.prototype.rawSample = function(sampleIndex) {
|
NotePlayer.prototype.rawSample = function(sampleIndex) {
|
||||||
if (sampleIndex >= this.endOffset) {
|
if (sampleIndex >= this.endOffset) {
|
||||||
|
@ -112,8 +112,8 @@ NotePlayer.prototype.rawSample = function(sampleIndex) {
|
||||||
}
|
}
|
||||||
var byteIndex = 2 * sampleIndex;
|
var byteIndex = 2 * sampleIndex;
|
||||||
var result = (this.soundData[byteIndex + 1] << 8) + this.soundData[byteIndex];
|
var result = (this.soundData[byteIndex + 1] << 8) + this.soundData[byteIndex];
|
||||||
return (result <= 32767) ? result : result - 65536;
|
return result <= 32767 ? result : result - 65536;
|
||||||
}
|
};
|
||||||
|
|
||||||
NotePlayer.prototype.updateEnvelope = function() {
|
NotePlayer.prototype.updateEnvelope = function() {
|
||||||
// Compute envelopeValue for the current sample.
|
// Compute envelopeValue for the current sample.
|
||||||
|
@ -125,4 +125,4 @@ NotePlayer.prototype.updateEnvelope = function() {
|
||||||
} else if (this.samplesSinceStart > this.holdEnd) {
|
} else if (this.samplesSinceStart > this.holdEnd) {
|
||||||
if (this.decayRate < 1) this.envelopeValue *= this.decayRate;
|
if (this.decayRate < 1) this.envelopeValue *= this.decayRate;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
|
@ -178,24 +178,24 @@ SoundBank.getNotePlayer = function(instNum, midiKey) {
|
||||||
// Return a NotePlayer for the given Scratch 2.0 instrument number (1..21)
|
// Return a NotePlayer for the given Scratch 2.0 instrument number (1..21)
|
||||||
// and MIDI key (0..127). If the instrument is out of range, use 1.
|
// and MIDI key (0..127). If the instrument is out of range, use 1.
|
||||||
var r = SoundBank.getNoteRecord(instNum - 1, midiKey);
|
var r = SoundBank.getNoteRecord(instNum - 1, midiKey);
|
||||||
var env = (r.length > 5) ? r[5] : null;
|
var env = r.length > 5 ? r[5] : null;
|
||||||
return new NotePlayer(Instr.samples[r[1]], SoundBank.pitchForKey(r[2]), r[3], r[4], env);
|
return new NotePlayer(Instr.samples[r[1]], SoundBank.pitchForKey(r[2]), r[3], r[4], env);
|
||||||
}
|
};
|
||||||
|
|
||||||
SoundBank.getNoteRecord = function(instNum, midiKey) {
|
SoundBank.getNoteRecord = function(instNum, midiKey) {
|
||||||
// Get a note record for the given instrument number.
|
// Get a note record for the given instrument number.
|
||||||
if ((instNum < 0) || (instNum >= SoundBank.instruments.length)) instNum = 0;
|
if (instNum < 0 || instNum >= SoundBank.instruments.length) instNum = 0;
|
||||||
var keyRanges = SoundBank.instruments[instNum];
|
var keyRanges = SoundBank.instruments[instNum];
|
||||||
for (var r = 0; r < keyRanges.length; r++) {
|
for (var r = 0; r < keyRanges.length; r++) {
|
||||||
var topOfKeyRange = keyRanges[r][0];
|
var topOfKeyRange = keyRanges[r][0];
|
||||||
if (midiKey <= topOfKeyRange) return keyRanges[r];
|
if (midiKey <= topOfKeyRange) return keyRanges[r];
|
||||||
}
|
}
|
||||||
return keyRanges[keyRanges.length - 1]; // return the note record for the top key range.
|
return keyRanges[keyRanges.length - 1]; // return the note record for the top key range.
|
||||||
}
|
};
|
||||||
|
|
||||||
SoundBank.pitchForKey = function(midiKey) {
|
SoundBank.pitchForKey = function(midiKey) {
|
||||||
return 440 * Math.pow(2, (midiKey - 69) / 12); // midi key 69 is A=440 Hz
|
return 440 * Math.pow(2, (midiKey - 69) / 12); // midi key 69 is A=440 Hz
|
||||||
}
|
};
|
||||||
|
|
||||||
SoundBank.getDrumPlayer = function(drumNum, secs) {
|
SoundBank.getDrumPlayer = function(drumNum, secs) {
|
||||||
// Return a NotePlayer for the given drum number.
|
// Return a NotePlayer for the given drum number.
|
||||||
|
@ -210,6 +210,4 @@ SoundBank.getDrumPlayer = function(drumNum, secs) {
|
||||||
var player = new NotePlayer(Instr.samples[entry[0]], SoundBank.pitchForKey(60), loopStart, loopEnd, env);
|
var player = new NotePlayer(Instr.samples[entry[0]], SoundBank.pitchForKey(60), loopStart, loopEnd, env);
|
||||||
player.setNoteAndDuration(60 + entry[1], 0);
|
player.setNoteAndDuration(60 + entry[1], 0);
|
||||||
return player;
|
return player;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -61,12 +61,12 @@ var SoundDecoder = function(wavFileData) {
|
||||||
if (info.bitsPerSample == 16) this.getSample = this.getSample16Uncompressed;
|
if (info.bitsPerSample == 16) this.getSample = this.getSample16Uncompressed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
SoundDecoder.prototype.noteFinished = function() {
|
SoundDecoder.prototype.noteFinished = function() {
|
||||||
// Called by subclasses to force ending condition to be true in writeSampleData()
|
// Called by subclasses to force ending condition to be true in writeSampleData()
|
||||||
this.bytePosition = this.endOffset;
|
this.bytePosition = this.endOffset;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Used for Notes and Drums - Web Audio API ScriptProcessorNodes use this
|
// Used for Notes and Drums - Web Audio API ScriptProcessorNodes use this
|
||||||
// as a callback function to fill the buffers with sample data.
|
// as a callback function to fill the buffers with sample data.
|
||||||
|
@ -78,7 +78,7 @@ SoundDecoder.prototype.writeSampleData = function(evt) {
|
||||||
var n = this.interpolatedSample();
|
var n = this.interpolatedSample();
|
||||||
output[i] = n;
|
output[i] = n;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// For pre-caching the samples of WAV sounds
|
// For pre-caching the samples of WAV sounds
|
||||||
// Return a full list of samples generated by the decoder.
|
// Return a full list of samples generated by the decoder.
|
||||||
|
@ -90,7 +90,7 @@ SoundDecoder.prototype.getAllSamples = function() {
|
||||||
smp = this.interpolatedSample();
|
smp = this.interpolatedSample();
|
||||||
}
|
}
|
||||||
return samples;
|
return samples;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Provide the next sample for the buffer
|
// Provide the next sample for the buffer
|
||||||
SoundDecoder.prototype.interpolatedSample = function() {
|
SoundDecoder.prototype.interpolatedSample = function() {
|
||||||
|
@ -101,11 +101,9 @@ SoundDecoder.prototype.interpolatedSample = function() {
|
||||||
this.fraction -= 1.0;
|
this.fraction -= 1.0;
|
||||||
}
|
}
|
||||||
if (this.nextSample == null) { return null; }
|
if (this.nextSample == null) { return null; }
|
||||||
var out = (this.fraction == 0) ?
|
var out = this.fraction == 0 ? this.thisSample : this.thisSample + this.fraction * (this.nextSample - this.thisSample);
|
||||||
this.thisSample :
|
return out / 32768.0;
|
||||||
this.thisSample + (this.fraction * (this.nextSample - this.thisSample));
|
};
|
||||||
return (out) / 32768.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 16-bit samples, big-endian
|
// 16-bit samples, big-endian
|
||||||
SoundDecoder.prototype.getSample16Uncompressed = function() {
|
SoundDecoder.prototype.getSample16Uncompressed = function() {
|
||||||
|
@ -119,13 +117,13 @@ SoundDecoder.prototype.getSample16Uncompressed = function() {
|
||||||
result = null;
|
result = null;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
};
|
||||||
|
|
||||||
// 8-bit samples, uncompressed
|
// 8-bit samples, uncompressed
|
||||||
SoundDecoder.prototype.getSample8Uncompressed = function() {
|
SoundDecoder.prototype.getSample8Uncompressed = function() {
|
||||||
if (this.bytePosition >= this.info.sampleDataSize) return null;
|
if (this.bytePosition >= this.info.sampleDataSize) return null;
|
||||||
return (this.soundData[this.bytePosition++] - 128) << 8;
|
return (this.soundData[this.bytePosition++] - 128) << 8;
|
||||||
}
|
};
|
||||||
|
|
||||||
/*SoundDecoder.prototype.updateVolume = function() {
|
/*SoundDecoder.prototype.updateVolume = function() {
|
||||||
if (this.client == null) {
|
if (this.client == null) {
|
||||||
|
@ -154,8 +152,8 @@ SoundDecoder.prototype.getSampleADPCM = function() {
|
||||||
// Note: Handles only one channel, 4-bits/sample.
|
// Note: Handles only one channel, 4-bits/sample.
|
||||||
var step = 0, code = 0, delta = 0;
|
var step = 0, code = 0, delta = 0;
|
||||||
|
|
||||||
if (((this.bytePosition % this.adpcmBlockSize) == 0) && (this.lastByte < 0)) { // read block header
|
if (this.bytePosition % this.adpcmBlockSize == 0 && this.lastByte < 0) { // read block header
|
||||||
if (this.bytePosition > (this.info.sampleDataSize - 4)) return null;
|
if (this.bytePosition > this.info.sampleDataSize - 4) return null;
|
||||||
this.sample = (this.soundData[this.bytePosition + 1] << 8) + this.soundData[this.bytePosition];
|
this.sample = (this.soundData[this.bytePosition + 1] << 8) + this.soundData[this.bytePosition];
|
||||||
if (this.sample > 32767) this.sample -= 65536;
|
if (this.sample > 32767) this.sample -= 65536;
|
||||||
this.index = this.soundData[this.bytePosition + 2];
|
this.index = this.soundData[this.bytePosition + 2];
|
||||||
|
@ -184,7 +182,7 @@ SoundDecoder.prototype.getSampleADPCM = function() {
|
||||||
if (this.index > 88) this.index = 88;
|
if (this.index > 88) this.index = 88;
|
||||||
if (this.index < 0) this.index = 0;
|
if (this.index < 0) this.index = 0;
|
||||||
// compute and output sample
|
// compute and output sample
|
||||||
this.sample += ((code & 8) ? -delta : delta);
|
this.sample += code & 8 ? -delta : delta;
|
||||||
if (this.sample > 32767) this.sample = 32767;
|
if (this.sample > 32767) this.sample = 32767;
|
||||||
if (this.sample < -32768) this.sample = -32768;
|
if (this.sample < -32768) this.sample = -32768;
|
||||||
return this.sample;
|
return this.sample;
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
var WAVFile = function() {};
|
var WAVFile = function() {};
|
||||||
|
|
||||||
|
|
||||||
WAVFile.decode = function(waveData) {
|
WAVFile.decode = function(waveData) {
|
||||||
// Decode the given WAV file data and return an Object with the format and sample data.
|
// Decode the given WAV file data and return an Object with the format and sample data.
|
||||||
var result = {};
|
var result = {};
|
||||||
|
@ -75,8 +74,7 @@ WAVFile.decode = function(waveData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
WAVFile.extractChunk = function(desiredType, data) {
|
WAVFile.extractChunk = function(desiredType, data) {
|
||||||
// Return the contents of the first chunk of the given type or an empty OffsetBuffer if it is not found.
|
// Return the contents of the first chunk of the given type or an empty OffsetBuffer if it is not found.
|
||||||
|
@ -93,8 +91,7 @@ WAVFile.extractChunk = function(desiredType, data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new OffsetBuffer(new ArrayBuffer());
|
return new OffsetBuffer(new ArrayBuffer());
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
WAVFile.dataChunkStartAndSize = function(data) {
|
WAVFile.dataChunkStartAndSize = function(data) {
|
||||||
// Return an array with the starting offset and size of the first chunk of the given type.
|
// Return an array with the starting offset and size of the first chunk of the given type.
|
||||||
|
@ -110,4 +107,4 @@ WAVFile.dataChunkStartAndSize = function(data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [0, 0]; // chunk not found; bad wave file
|
return [0, 0]; // chunk not found; bad wave file
|
||||||
}
|
};
|
||||||
|
|
|
@ -29,8 +29,8 @@ Color.fromHSV = function(h, s, v) {
|
||||||
var i = Math.floor(h / 60);
|
var i = Math.floor(h / 60);
|
||||||
var f = (h / 60) - i;
|
var f = (h / 60) - i;
|
||||||
var p = v * (1 - s);
|
var p = v * (1 - s);
|
||||||
var q = v * (1 - (s * f));
|
var q = v * (1 - s * f);
|
||||||
var t = v * (1 - (s * (1 - f)));
|
var t = v * (1 - s * (1 - f));
|
||||||
if (i == 0) { r = v; g = t; b = p; }
|
if (i == 0) { r = v; g = t; b = p; }
|
||||||
else if (i == 1) { r = q; g = v; b = p; }
|
else if (i == 1) { r = q; g = v; b = p; }
|
||||||
else if (i == 2) { r = p; g = v; b = t; }
|
else if (i == 2) { r = p; g = v; b = t; }
|
||||||
|
@ -41,7 +41,7 @@ Color.fromHSV = function(h, s, v) {
|
||||||
g = Math.floor(g * 255);
|
g = Math.floor(g * 255);
|
||||||
b = Math.floor(b * 255);
|
b = Math.floor(b * 255);
|
||||||
return (r << 16) | (g << 8) | b;
|
return (r << 16) | (g << 8) | b;
|
||||||
}
|
};
|
||||||
|
|
||||||
Color.rgb2hsv = function(rgb) {
|
Color.rgb2hsv = function(rgb) {
|
||||||
var h, s, v, x, f, i;
|
var h, s, v, x, f, i;
|
||||||
|
@ -51,18 +51,18 @@ Color.rgb2hsv = function(rgb) {
|
||||||
x = Math.min(Math.min(r, g), b);
|
x = Math.min(Math.min(r, g), b);
|
||||||
v = Math.max(Math.max(r, g), b);
|
v = Math.max(Math.max(r, g), b);
|
||||||
if (x == v) return [0, 0, v]; // gray; hue arbitrarily reported as zero
|
if (x == v) return [0, 0, v]; // gray; hue arbitrarily reported as zero
|
||||||
f = (r == x) ? g - b : ((g == x) ? b - r : r - g);
|
f = r == x ? g - b : g == x ? b - r : r - g;
|
||||||
i = (r == x) ? 3 : ((g == x) ? 5 : 1);
|
i = r == x ? 3 : g == x ? 5 : 1;
|
||||||
h = ((i - (f / (v - x))) * 60) % 360;
|
h = ((i - f / (v - x)) * 60) % 360;
|
||||||
s = (v - x) / v;
|
s = (v - x) / v;
|
||||||
return [h, s, v];
|
return [h, s, v];
|
||||||
}
|
};
|
||||||
|
|
||||||
Color.scaleBrightness = function(rgb, scale) {
|
Color.scaleBrightness = function(rgb, scale) {
|
||||||
var hsv = Color.rgb2hsv(rgb);
|
var hsv = Color.rgb2hsv(rgb);
|
||||||
scale = Math.max(0, Math.min(scale, 1));
|
scale = Math.max(0, Math.min(scale, 1));
|
||||||
return Color.fromHSV(hsv[0], hsv[1], scale * hsv[2]);
|
return Color.fromHSV(hsv[0], hsv[1], scale * hsv[2]);
|
||||||
}
|
};
|
||||||
|
|
||||||
Color.mixRGB = function(rgb1, rgb2, fraction) {
|
Color.mixRGB = function(rgb1, rgb2, fraction) {
|
||||||
// Mix rgb1 with rgb2. 0 gives all rgb1, 1 gives rbg2, .5 mixes them 50/50.
|
// Mix rgb1 with rgb2. 0 gives all rgb1, 1 gives rbg2, .5 mixes them 50/50.
|
||||||
|
@ -78,7 +78,7 @@ Color.mixRGB = function(rgb1, rgb2, fraction) {
|
||||||
var g = ((fraction * g2) + ((1.0 - fraction) * g1)) & 255;
|
var g = ((fraction * g2) + ((1.0 - fraction) * g1)) & 255;
|
||||||
var b = ((fraction * b2) + ((1.0 - fraction) * b1)) & 255;
|
var b = ((fraction * b2) + ((1.0 - fraction) * b1)) & 255;
|
||||||
return (r << 16) | (g << 8) | b;
|
return (r << 16) | (g << 8) | b;
|
||||||
}
|
};
|
||||||
|
|
||||||
Color.random = function() {
|
Color.random = function() {
|
||||||
// return a random color
|
// return a random color
|
||||||
|
@ -86,4 +86,4 @@ Color.random = function() {
|
||||||
var s = 0.7 + (0.3 * Math.random());
|
var s = 0.7 + (0.3 * Math.random());
|
||||||
var v = 0.6 + (0.4 * Math.random());
|
var v = 0.6 + (0.4 * Math.random());
|
||||||
return Color.fromHSV(h, s, v);
|
return Color.fromHSV(h, s, v);
|
||||||
}
|
};
|
||||||
|
|
|
@ -19,63 +19,63 @@
|
||||||
var OffsetBuffer = function(data) {
|
var OffsetBuffer = function(data) {
|
||||||
this.offset = 0;
|
this.offset = 0;
|
||||||
this.ab = data;
|
this.ab = data;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Read various datatypes from the ArrayBuffer, seeking the offset.
|
// Read various datatypes from the ArrayBuffer, seeking the offset.
|
||||||
OffsetBuffer.prototype.readString = function(length) {
|
OffsetBuffer.prototype.readString = function(length) {
|
||||||
var str = this.ab2str(this.ab.slice(this.offset, this.offset + length));
|
var str = this.ab2str(this.ab.slice(this.offset, this.offset + length));
|
||||||
this.offset += length;
|
this.offset += length;
|
||||||
return str;
|
return str;
|
||||||
}
|
};
|
||||||
|
|
||||||
OffsetBuffer.prototype.readInt = function() {
|
OffsetBuffer.prototype.readInt = function() {
|
||||||
var num = this.ab2int(this.ab.slice(this.offset, this.offset + 4));
|
var num = this.ab2int(this.ab.slice(this.offset, this.offset + 4));
|
||||||
this.offset += 4;
|
this.offset += 4;
|
||||||
return num;
|
return num;
|
||||||
}
|
};
|
||||||
|
|
||||||
OffsetBuffer.prototype.readUint = function() {
|
OffsetBuffer.prototype.readUint = function() {
|
||||||
var num = this.ab2uint(this.ab.slice(this.offset, this.offset + 4));
|
var num = this.ab2uint(this.ab.slice(this.offset, this.offset + 4));
|
||||||
this.offset += 4;
|
this.offset += 4;
|
||||||
return num;
|
return num;
|
||||||
}
|
};
|
||||||
|
|
||||||
OffsetBuffer.prototype.readShort = function() {
|
OffsetBuffer.prototype.readShort = function() {
|
||||||
var num = this.ab2short(this.ab.slice(this.offset, this.offset + 2));
|
var num = this.ab2short(this.ab.slice(this.offset, this.offset + 2));
|
||||||
this.offset += 2;
|
this.offset += 2;
|
||||||
return num;
|
return num;
|
||||||
}
|
};
|
||||||
|
|
||||||
OffsetBuffer.prototype.readBytes = function(length) {
|
OffsetBuffer.prototype.readBytes = function(length) {
|
||||||
var bytes = this.ab.slice(this.offset, this.offset + length);
|
var bytes = this.ab.slice(this.offset, this.offset + length);
|
||||||
this.offset += length;
|
this.offset += length;
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Length of the internal buffer
|
// Length of the internal buffer
|
||||||
OffsetBuffer.prototype.getLength = function() {
|
OffsetBuffer.prototype.getLength = function() {
|
||||||
return this.ab.byteLength;
|
return this.ab.byteLength;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Number of bytes remaining from the current offset
|
// Number of bytes remaining from the current offset
|
||||||
OffsetBuffer.prototype.bytesAvailable = function() {
|
OffsetBuffer.prototype.bytesAvailable = function() {
|
||||||
return (this.getLength() - this.offset);
|
return this.getLength() - this.offset;
|
||||||
}
|
};
|
||||||
|
|
||||||
// ArrayBuffer -> JS type conversion methods
|
// ArrayBuffer -> JS type conversion methods
|
||||||
OffsetBuffer.prototype.ab2str = function(buf) {
|
OffsetBuffer.prototype.ab2str = function(buf) {
|
||||||
return String.fromCharCode.apply(null, new Uint8Array(buf));
|
return String.fromCharCode.apply(null, new Uint8Array(buf));
|
||||||
}
|
};
|
||||||
|
|
||||||
// These create Javascript Numbers
|
// These create Javascript Numbers
|
||||||
OffsetBuffer.prototype.ab2int = function(buf) {
|
OffsetBuffer.prototype.ab2int = function(buf) {
|
||||||
return new Int32Array(buf)[0];
|
return new Int32Array(buf)[0];
|
||||||
}
|
};
|
||||||
|
|
||||||
OffsetBuffer.prototype.ab2uint = function(buf) {
|
OffsetBuffer.prototype.ab2uint = function(buf) {
|
||||||
return new Uint32Array(buf)[0];
|
return new Uint32Array(buf)[0];
|
||||||
}
|
};
|
||||||
|
|
||||||
OffsetBuffer.prototype.ab2short = function(buf) {
|
OffsetBuffer.prototype.ab2short = function(buf) {
|
||||||
return new Int16Array(buf)[0];
|
return new Int16Array(buf)[0];
|
||||||
}
|
};
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
var Point = function(x, y) {
|
var Point = function(x, y) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
};
|
||||||
|
|
||||||
var Rectangle = function(x, y, width, height) {
|
var Rectangle = function(x, y, width, height) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
|
@ -27,10 +27,8 @@ var Rectangle = function(x, y, width, height) {
|
||||||
this.right = x + width;
|
this.right = x + width;
|
||||||
this.top = y;
|
this.top = y;
|
||||||
this.bottom = y + height;
|
this.bottom = y + height;
|
||||||
}
|
};
|
||||||
|
|
||||||
Rectangle.prototype.intersects = function(other) {
|
Rectangle.prototype.intersects = function(other) {
|
||||||
return !(this.left > other.right ||
|
return !(this.left > other.right || this.right < other.left || this.top > other.bottom || this.bottom < other.top);
|
||||||
this.right < other.left ||
|
};
|
||||||
this.top > other.bottom ||
|
|
||||||
this.bottom < other.top);
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,40 +21,40 @@ var Timer = function() {
|
||||||
var trials = [];
|
var trials = [];
|
||||||
var last_trial = 0;
|
var last_trial = 0;
|
||||||
var start_time = 0;
|
var start_time = 0;
|
||||||
}
|
};
|
||||||
|
|
||||||
Timer.prototype.time = function() {
|
Timer.prototype.time = function() {
|
||||||
return (new Date()).getTime();
|
return Date.now();
|
||||||
}
|
};
|
||||||
|
|
||||||
Timer.prototype.start = function() {
|
Timer.prototype.start = function() {
|
||||||
start_time = this.time();
|
start_time = this.time();
|
||||||
}
|
};
|
||||||
|
|
||||||
Timer.prototype.stop = function() {
|
Timer.prototype.stop = function() {
|
||||||
end = this.time();
|
end = this.time();
|
||||||
last_trial = end - start_time;
|
last_trial = end - start_time;
|
||||||
trials.push(last_trial);
|
trials.push(last_trial);
|
||||||
}
|
};
|
||||||
|
|
||||||
Timer.prototype.count = function() {
|
Timer.prototype.count = function() {
|
||||||
return trials.length;
|
return trials.length;
|
||||||
}
|
};
|
||||||
|
|
||||||
Timer.prototype.average = function() {
|
Timer.prototype.average = function() {
|
||||||
sum = 0;
|
sum = 0;
|
||||||
for(i = 0; i < this.count(); i++) {
|
for (i = 0; i < this.count(); i++) {
|
||||||
sum += trials[i];
|
sum += trials[i];
|
||||||
}
|
}
|
||||||
return sum / this.count();
|
return sum / this.count();
|
||||||
}
|
};
|
||||||
|
|
||||||
Timer.prototype.print = function(element) {
|
Timer.prototype.print = function(element) {
|
||||||
text = "Trial: " + last_trial + "ms" +
|
text = "Trial: " + last_trial + "ms" +
|
||||||
"<br />\nTrials: " + this.count() + ", Avg: " + this.average() + "ms";
|
"<br />\nTrials: " + this.count() + ", Avg: " + this.average() + "ms";
|
||||||
if(element) {
|
if (element) {
|
||||||
$(element).html(text);
|
$(element).html(text);
|
||||||
} else {
|
} else {
|
||||||
console.log(text);
|
console.log(text);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
Reference in a new issue