Formatting and indentation fixes

This commit is contained in:
Nathan Dinsmore 2013-11-01 22:44:51 -04:00
parent 73fdd4b7eb
commit 1a72b01b31
22 changed files with 690 additions and 691 deletions

View file

@ -4,112 +4,113 @@ header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Scratch HTML5 vs. Flash</title> <title>Scratch HTML5 vs. Flash</title>
<meta charset="utf-8"> <meta charset="utf-8">
<style type="text/css"> <style type="text/css">
body { body {
background: #222; background: #222;
color: #fff; color: #fff;
margin: 0; margin: 0;
} }
</style> </style>
<link href="player.css" type="text/css" rel="stylesheet" /> <link href="player.css" type="text/css" rel="stylesheet" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script> <script src="//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
<script src="js/util/Timer.js"></script> <script src="js/util/Timer.js"></script>
<script src="js/util/OffsetBuffer.js"></script> <script src="js/util/OffsetBuffer.js"></script>
<script src="js/util/Color.js"></script> <script src="js/util/Color.js"></script>
<script src="js/util/Rectangle.js"></script> <script src="js/util/Rectangle.js"></script>
<script src="js/Sprite.js"></script> <script src="js/Sprite.js"></script>
<script src="js/Reporter.js"></script> <script src="js/Reporter.js"></script>
<script src="js/Stage.js"></script> <script src="js/Stage.js"></script>
<script src="js/sound/WAVFile.js"></script> <script src="js/sound/WAVFile.js"></script>
<script src="js/sound/SoundDecoder.js"></script> <script src="js/sound/SoundDecoder.js"></script>
<script src="js/sound/SoundBank.js"></script> <script src="js/sound/SoundBank.js"></script>
<script src="js/sound/NotePlayer.js"></script> <script src="js/sound/NotePlayer.js"></script>
<script src="soundbank/Instr.js"></script> <script src="soundbank/Instr.js"></script>
<script src="js/IO.js"></script> <script src="js/IO.js"></script>
<script src="js/primitives/VarListPrims.js"></script> <script src="js/primitives/VarListPrims.js"></script>
<script src="js/primitives/MotionAndPenPrims.js"></script> <script src="js/primitives/MotionAndPenPrims.js"></script>
<script src="js/primitives/LooksPrims.js"></script> <script src="js/primitives/LooksPrims.js"></script>
<script src="js/primitives/SensingPrims.js"></script> <script src="js/primitives/SensingPrims.js"></script>
<script src="js/primitives/SoundPrims.js"></script> <script src="js/primitives/SoundPrims.js"></script>
<script src="js/primitives/Primitives.js"></script> <script src="js/primitives/Primitives.js"></script>
<script src="js/Interpreter.js"></script> <script src="js/Interpreter.js"></script>
<script src="js/Runtime.js"></script> <script src="js/Runtime.js"></script>
<script src="js/Scratch.js"></script> <script src="js/Scratch.js"></script>
<script type="text/javascript"> <script type="text/javascript">
if (window.location.hash) { if (window.location.hash) {
var project_id = parseInt(window.location.hash.substr(1)); var project_id = parseInt(window.location.hash.substr(1));
} else { } else {
var project_id = 10000160; // Default project for display var project_id = 10000160; // Default project for display
} }
</script> </script>
<script> <script>
$(function() { $(function() {
// The flashvars tell flash about the project data (and autostart=true) // The flashvars tell flash about the project data (and autostart=true)
var flashvars = { var flashvars = {
server: encodeURIComponent('scratch.mit.edu'), server: encodeURIComponent('scratch.mit.edu'),
project_id: project_id project_id: project_id
}; };
// 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";
var swf_url = "http://jiggler.media.mit.edu/shanemc/scratchr2/static/Scratch.swf"; var swf_url = "http://jiggler.media.mit.edu/shanemc/scratchr2/static/Scratch.swf";
swfobject.embedSWF(swf_url, "flashScratch", "480", "400", "10.2.0", swfobject.embedSWF(swf_url, "flashScratch", "480", "400", "10.2.0",
"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() {
flashPlayer.ASstartRunning();
});
// Stop button behavior
$('#trigger_stop').click(function() {
flashPlayer.ASstopRunning();
});
}); });
</script>
$('#trigger_green_flag, #greenSlide').click(function() { </head>
flashPlayer.ASstartRunning(); <body>
}); <div style="display: inline-block;">
<div id="up">&nbsp;</div>
// Stop button behavior <div id="left">&nbsp;</div>
$('#trigger_stop').click(function() { <div id="overContainer">
flashPlayer.ASstopRunning(); <div id="greenSlide"><div id="greenSlideFg"><img src="img/greenflag.png"></div></div>
}); <div id="container"></div>
}); </div>
</script> <div id="right">&nbsp;</div>
</head> <div id="down">&nbsp;</div>
<body>
<div style="display: inline-block;">
<div id="up">&nbsp;</div>
<div id="left">&nbsp;</div>
<div id="overContainer">
<div id="greenSlide"><div id="greenSlideFg"><img src="img/greenflag.png"></div></div>
<div id="container"></div>
</div> </div>
<div id="right">&nbsp;</div> <div style="display: inline-block;">
<div id="down">&nbsp;</div> <div id="flashScratch" style="text-align:center;visibility:hidden;">
</div> <p style="color:#aaa;font-size:22px;margin-top:14px;line-height:28px;">Oh Noes! Scratch project cannot display.<br/>Flash player is disabled, missing, or less than version 10.2.</p>
<div style="display: inline-block;"> <a href="http://www.adobe.com/go/getflashplayer">
<div id="flashScratch" style="text-align:center;visibility:hidden;"> <img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" target="_blank" />
<p style="color:#aaa;font-size:22px;margin-top:14px;line-height:28px;">Oh Noes! Scratch project cannot display.<br/>Flash player is disabled, missing, or less than version 10.2.</p> </a>
<a href="http://www.adobe.com/go/getflashplayer"> </div>
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" target="_blank" />
</a>
</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>
<button id="trigger_stop">Stop</button> <button id="trigger_stop">Stop</button>
<input type="text" name="project_id" id="project_id" /><button id='go_project'>Go!</button> <input type="text" name="project_id" id="project_id" /><button id='go_project'>Go!</button>
</body> </body>
</html> </html>

View file

@ -27,26 +27,24 @@ var IO = function() {
// In production, simply use the local path (no proxy) // In production, simply use the local path (no proxy)
// since we won't be hampered by the same-origin policy. // since we won't be hampered by the same-origin policy.
this.base = 'proxy.php?resource=internalapi/'; this.base = 'proxy.php?resource=internalapi/';
this.project_base = this.base + 'project/'; this.project_base = this.base + 'project/';
this.project_suffix = '/get/'; this.project_suffix = '/get/';
this.asset_base = this.base + 'asset/'; this.asset_base = this.base + 'asset/';
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,22 +79,22 @@ 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
runtime.stage = new Stage(this.data); runtime.stage = new Stage(this.data);
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 // Create the sprites
$.each(this.data.children, function(index, obj) { $.each(this.data.children, function(index, obj) {
var newSprite; var newSprite;
if(!obj.cmd) { if (!obj.cmd) {
newSprite = new Sprite(obj); newSprite = new Sprite(obj);
} else { } else {
newSprite = new Reporter(obj); newSprite = new Reporter(obj);
@ -107,8 +105,8 @@ IO.prototype.makeObjects = function() {
if (!obj.cmd) if (!obj.cmd)
newSprite.loadSounds(); newSprite.loadSounds();
}); });
} };
IO.prototype.loadThreads = function() { IO.prototype.loadThreads = function() {
var target = runtime.stage; var target = runtime.stage;
var scripts = target.data.scripts; var scripts = target.data.scripts;
@ -123,9 +121,9 @@ IO.prototype.loadThreads = function() {
$.each(target.data.scripts, function(j, s) { $.each(target.data.scripts, function(j, s) {
target.stacks.push(interp.makeBlockList(s[2])); target.stacks.push(interp.makeBlockList(s[2]));
}); });
} }
}); });
} };
// Returns the number sprite we are rendering // Returns the number sprite we are rendering
// used for initial layering assignment // used for initial layering assignment
@ -133,4 +131,4 @@ IO.prototype.getCount = function() {
var rv = this.spriteLayerCount; var rv = this.spriteLayerCount;
this.spriteLayerCount++; this.spriteLayerCount++;
return rv; return rv;
} };

View file

@ -22,7 +22,7 @@
var Block = function(opAndArgs, optionalSubstack) { var Block = function(opAndArgs, optionalSubstack) {
this.op = opAndArgs[0]; this.op = opAndArgs[0];
this.primFcn = interp.lookupPrim(this.op); this.primFcn = interp.lookupPrim(this.op);
this.args = opAndArgs.slice(1); // arguments can be either or constants (numbers, boolean strings, etc.) or expressions (Blocks) this.args = opAndArgs.slice(1); // arguments can be either or constants (numbers, boolean strings, etc.) or expressions (Blocks)
this.isLoop = false; // set to true for loop blocks the first time they run this.isLoop = false; // set to true for loop blocks the first time they run
this.substack = optionalSubstack; this.substack = optionalSubstack;
@ -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,10 +54,10 @@ 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) {
// Convert the arguments of the given block into blocks or substacks if necessary. // Convert the arguments of the given block into blocks or substacks if necessary.
// A block argument can be a constant (numbers, boolean strings, etc.), an expression (Blocks), or a substack (an array of blocks). // A block argument can be a constant (numbers, boolean strings, etc.), an expression (Blocks), or a substack (an array of blocks).
var newArgs = []; var newArgs = [];
@ -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() {
@ -115,17 +115,17 @@ Interpreter.prototype.stepThreads = function() {
if (this.threads[a].nextBlock != null) { if (this.threads[a].nextBlock != null) {
newThreads.push(this.threads[a]); newThreads.push(this.threads[a]);
} }
} }
this.threads = newThreads; this.threads = newThreads;
if (this.threads.length == 0) return; if (this.threads.length == 0) return;
} }
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;
@ -141,7 +141,7 @@ Interpreter.prototype.stepActiveThread = function() {
b = this.activeThread.nextBlock; // refresh local variable b in case primitive did some control flow b = this.activeThread.nextBlock; // refresh local variable b in case primitive did some control flow
while (b == null) { while (b == null) {
// end of a substack; pop the owning control flow block from stack // end of a substack; pop the owning control flow block from stack
// Note: This is a loop to handle nested control flow blocks. // Note: This is a loop to handle nested control flow blocks.
b = this.activeThread.stack.pop(); b = this.activeThread.stack.pop();
if ((b == null) || (b.isLoop)) { if ((b == null) || (b.isLoop)) {
this.activeThread.nextBlock = b; this.activeThread.nextBlock = b;
@ -149,8 +149,8 @@ Interpreter.prototype.stepActiveThread = function() {
} }
} }
} }
} };
Interpreter.prototype.toggleThread = function(b, targetObj) { Interpreter.prototype.toggleThread = function(b, targetObj) {
var newThreads = [], wasRunning = false; var newThreads = [], wasRunning = false;
for (var i = 0; i < this.threads.length; i++) { for (var i = 0; i < this.threads.length; i++) {
@ -161,16 +161,16 @@ 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
var newThread = new Thread(b, targetObj); var newThread = new Thread(b, targetObj);
@ -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,27 +247,27 @@ 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) {
b.tmp = Math.max(interp.arg(b, 0), 0); // Initialize repeat count on this block b.tmp = Math.max(interp.arg(b, 0), 0); // Initialize repeat count on this block
@ -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]);
} }
@ -303,14 +303,14 @@ Interpreter.prototype.broadcast = function(b, waitFlag) {
if (interp.isRunning(interp.activeThread.tmpObj[pair][0])) { if (interp.isRunning(interp.activeThread.tmpObj[pair][0])) {
done = false; done = false;
} }
} }
if (done) { if (done) {
interp.activeThread.tmpObj = null; interp.activeThread.tmpObj = null;
interp.activeThread.firstTime = true; interp.activeThread.firstTime = true;
} 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;
} }
} };

View file

@ -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) {
@ -47,7 +47,7 @@ Reporter.prototype.attach = function(scene) {
// Temporarily, set the value to sliderMin until an update // Temporarily, set the value to sliderMin until an update
this.slider = $('<input type="range" min="' + this.sliderMin + this.slider = $('<input type="range" min="' + this.sliderMin +
'" max="' + this.sliderMax + '" step="1" value="' + '" max="' + this.sliderMax + '" step="1" value="' +
this.sliderMin + '" data-target="' + this.target + this.sliderMin + '" data-target="' + this.target +
'" data-var="' + this.param + '">'); '" data-var="' + this.param + '">');
this.slider.change(this.changeSlider); this.slider.change(this.changeSlider);
this.el.append('<br>'); this.el.append('<br>');
@ -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,17 +104,18 @@ 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;
} };

View file

@ -35,8 +35,8 @@ 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() {
this.scene = $('#container'); this.scene = $('#container');
@ -44,8 +44,8 @@ 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
// and animate methods. // and animate methods.
@ -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,8 +98,8 @@ 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.
Runtime.prototype.allStacksDo = function(f) { Runtime.prototype.allStacksDo = function(f) {
@ -106,25 +107,25 @@ 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);
}); });
} }
} }
$.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() {
function startIfGreenFlag(stack, target) { function startIfGreenFlag(stack, target) {
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;
if (('A'.charCodeAt(0) <= ch) && (ch <= 'Z'.charCodeAt(0)) || if (('A'.charCodeAt(0) <= ch) && (ch <= 'Z'.charCodeAt(0)) ||
@ -140,43 +141,43 @@ 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) {
if (n == 'Stage') return this.stage; if (n == 'Stage') return this.stage;
var selected_sprite = null; var selected_sprite = null;
$.each(this.sprites, function(index, s) { $.each(this.sprites, function(index, s) {
if (s.objName == n) { if (s.objName == n) {
selected_sprite = s; selected_sprite = s;
return false; return false;
} }
}); });
return selected_sprite; return selected_sprite;
} };
Runtime.prototype.getTimeString = function(which) { Runtime.prototype.getTimeString = function(which) {
// Return local time properties. // Return local time properties.
@ -191,9 +192,8 @@ Runtime.prototype.getTimeString = function(which) {
case 'day of week': return now.getDay() + 1; // 1-7, where 1 is Sunday case 'day of week': return now.getDay() + 1; // 1-7, where 1 is Sunday
} }
return ''; // shouldn't happen 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) {
var sprites = this.sprites; var sprites = this.sprites;
@ -205,18 +205,18 @@ Runtime.prototype.reassignZ = function(target, move) {
sprites.splice(index, 1); sprites.splice(index, 1);
} }
}); });
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 {
// No change is required // No change is required
this.sprites.splice(oldIndex, 0, target); this.sprites.splice(oldIndex, 0, target);
} }
// Renumber the z-indices // Renumber the z-indices
var newZ = 1; var newZ = 1;
$.each(this.sprites, function(index, sprite) { $.each(this.sprites, function(index, sprite) {
@ -224,4 +224,4 @@ Runtime.prototype.reassignZ = function(target, move) {
sprite.updateLayer(); sprite.updateLayer();
newZ++; newZ++;
}); });
} };

View file

@ -23,58 +23,58 @@
'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();
$(window).keydown(function(e) { $(window).keydown(function(e) {
runtime.keysDown[e.which] = true; runtime.keysDown[e.which] = true;
runtime.startKeyHats(e.which); runtime.startKeyHats(e.which);
}); });
$(window).keyup(function(e) { $(window).keyup(function(e) {
delete runtime.keysDown[e.which]; delete runtime.keysDown[e.which];
}); });
// Update the project ID field // Update the project ID field
$('#project_id').val(project_id); $('#project_id').val(project_id);
// Go project button behavior // Go project button behavior
$('#go_project').click(function() { $('#go_project').click(function() {
window.location = "#" + parseInt($('#project_id').val()); window.location = "#" + parseInt($('#project_id').val());
window.location.reload(true); window.location.reload(true);
}); });
// Green flag behavior // Green flag behavior
$('#trigger_green_flag, #greenSlide').click(function() { $('#trigger_green_flag, #greenSlide').click(function() {
$('#greenSlide').css('display', 'none'); $('#greenSlide').css('display', 'none');
runtime.greenFlag() runtime.greenFlag()
}); });
// Stop button behavior // Stop button behavior
$('#trigger_stop').click(function() { $('#trigger_stop').click(function() {
runtime.stopAll(); runtime.stopAll();
}); });
// Canvas container mouse events // Canvas container mouse events
$('#container').mousedown(function(e) { $('#container').mousedown(function(e) {
runtime.mouseDown = true; runtime.mouseDown = true;
//e.preventDefault(); //e.preventDefault();
}); });
$('#container').mouseup(function(e) { $('#container').mouseup(function(e) {
runtime.mouseDown = false; runtime.mouseDown = false;
//e.preventDefault(); //e.preventDefault();
}); });
$('#container').mousemove(function(e) { $('#container').mousemove(function(e) {
var absX = e.pageX - this.offsetLeft; var absX = e.pageX - this.offsetLeft;
var absY = e.pageY - this.offsetTop; var absY = e.pageY - this.offsetTop;
runtime.mousePos = [absX-240, -absY+180]; runtime.mousePos = [absX-240, -absY+180];
}); });
// Touch events - EXPERIMENTAL // Touch events - EXPERIMENTAL
$(window).bind('touchstart', function(e) { $(window).bind('touchstart', function(e) {
// On iOS, we need to activate the Web Audio API // On iOS, we need to activate the Web Audio API
// with an empty sound play on the first touch event. // with an empty sound play on the first touch event.
if (!iosAudioActive) { if (!iosAudioActive) {
@ -85,8 +85,8 @@ $(function () {
isource.noteOn(0); isource.noteOn(0);
iosAudioActive = true; iosAudioActive = true;
} }
}); });
$('#container').bind('touchstart', function(e) { $('#container').bind('touchstart', function(e) {
runtime.mouseDown = true; runtime.mouseDown = true;
}); });
@ -94,14 +94,14 @@ $(function () {
$('#container').bind('touchend', function(e) { $('#container').bind('touchend', function(e) {
runtime.mouseDown = true; runtime.mouseDown = true;
}); });
$('#container').bind('touchmove', function(e) { $('#container').bind('touchmove', function(e) {
var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
var absX = touch.pageX - this.offsetLeft; var absX = touch.pageX - this.offsetLeft;
var absY = touch.pageY - this.offsetTop; var absY = touch.pageY - this.offsetTop;
runtime.mousePos = [absX-240, -absY+180]; runtime.mousePos = [absX-240, -absY+180];
}); });
// Border touch events - EXPERIMENTAL // Border touch events - EXPERIMENTAL
$('#left').bind('touchstart touchmove', function(e) { runtime.keysDown[37] = true; runtime.startKeyHats(37); }); $('#left').bind('touchstart touchmove', function(e) { runtime.keysDown[37] = true; runtime.startKeyHats(37); });
$('#left').bind('touchend', function(e) { delete runtime.keysDown[37]; }); $('#left').bind('touchend', function(e) { delete runtime.keysDown[37]; });
@ -111,11 +111,11 @@ $(function () {
$('#right').bind('touchend', function(e) { delete runtime.keysDown[39]; }); $('#right').bind('touchend', function(e) { delete runtime.keysDown[39]; });
$('#down').bind('touchstart touchmove', function(e) { runtime.keysDown[40] = true; runtime.startKeyHats(40); }); $('#down').bind('touchstart touchmove', function(e) { runtime.keysDown[40] = true; runtime.startKeyHats(40); });
$('#down').bind('touchend', function(e) { delete runtime.keysDown[40]; }); $('#down').bind('touchend', function(e) { delete runtime.keysDown[40]; });
// Load the interpreter and primitives // Load the interpreter and primitives
interp = new Interpreter(); interp = new Interpreter();
interp.initPrims(); interp.initPrims();
// Load the requested project and go! // Load the requested project and go!
io = new IO(); io = new IO();
io.loadProject(project_id); io.loadProject(project_id);

View file

@ -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,8 +94,8 @@ 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) {
// Create textures and materials for each of the costumes. // Create textures and materials for each of the costumes.
@ -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(); })
@ -137,24 +137,23 @@ Sprite.prototype.attach = function(scene) {
this.talkBubbleStyler = $('<div class="bubble-say"></div>'); this.talkBubbleStyler = $('<div class="bubble-say"></div>');
this.talkBubble.append(this.talkBubbleBox); this.talkBubble.append(this.talkBubbleBox);
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) {
if (costume < 0) { if (costume < 0) {
@ -167,34 +166,34 @@ 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!!
var boxOffset = $('#container').offset(); var boxOffset = $('#container').offset();
@ -238,34 +237,35 @@ 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];
var resolution = this.costumes[this.currentCostumeIndex].bitmapResolution || 1; var resolution = this.costumes[this.currentCostumeIndex].bitmapResolution || 1;
var drawWidth = texture.width * this.scale / resolution; var drawWidth = texture.width * this.scale / resolution;
var drawHeight = texture.height * this.scale / resolution; var drawHeight = texture.height * this.scale / resolution;
var rotationCenterX = this.costumes[this.currentCostumeIndex].rotationCenterX; var rotationCenterX = this.costumes[this.currentCostumeIndex].rotationCenterX;
var rotationCenterY = this.costumes[this.currentCostumeIndex].rotationCenterY; var rotationCenterY = this.costumes[this.currentCostumeIndex].rotationCenterY;
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;
@ -275,26 +275,26 @@ Sprite.prototype.updateTransform = function() {
// sign to the X scale. // sign to the X scale.
} }
$(this.mesh).css('transform', $(this.mesh).css('transform',
'translatex(' + drawX + 'px) \ 'translatex(' + drawX + 'px) \
translatey(' + drawY + 'px) \ translatey(' + drawY + 'px) \
rotate(' + this.rotation + 'deg) \ rotate(' + this.rotation + 'deg) \
scaleX(' + scaleXprepend + (this.scale / resolution) + ') scaleY(' + (this.scale / resolution) + ')'); scaleX(' + scaleXprepend + (this.scale / resolution) + ') scaleY(' + (this.scale / resolution) + ')');
$(this.mesh).css('-moz-transform', $(this.mesh).css('-moz-transform',
'translatex(' + drawX + 'px) \ 'translatex(' + drawX + 'px) \
translatey(' + drawY + 'px) \ translatey(' + drawY + 'px) \
rotate(' + this.rotation + 'deg) \ rotate(' + this.rotation + 'deg) \
scaleX(' + scaleXprepend + this.scale + ') scaleY(' + this.scale / resolution + ')'); scaleX(' + scaleXprepend + this.scale + ') scaleY(' + this.scale / resolution + ')');
$(this.mesh).css('-webkit-transform', $(this.mesh).css('-webkit-transform',
'translatex(' + drawX + 'px) \ 'translatex(' + drawX + 'px) \
translatey(' + drawY + 'px) \ translatey(' + drawY + 'px) \
rotate(' + this.rotation + 'deg) \ rotate(' + this.rotation + 'deg) \
scaleX(' + scaleXprepend + (this.scale / resolution) + ') scaleY(' + (this.scale / resolution) + ')'); scaleX(' + scaleXprepend + (this.scale / resolution) + ') scaleY(' + (this.scale / resolution) + ')');
$(this.mesh).css('-webkit-transform-origin', rotationCenterX + 'px ' + rotationCenterY + 'px'); $(this.mesh).css('-webkit-transform-origin', rotationCenterX + 'px ' + rotationCenterY + 'px');
$(this.mesh).css('-moz-transform-origin', rotationCenterX + 'px ' + rotationCenterY + 'px'); $(this.mesh).css('-moz-transform-origin', rotationCenterX + 'px ' + rotationCenterY + 'px');
$(this.mesh).css('-ms-transform-origin', rotationCenterX + 'px ' + rotationCenterY + 'px'); $(this.mesh).css('-ms-transform-origin', rotationCenterX + 'px ' + rotationCenterY + 'px');
$(this.mesh).css('-o-transform-origin', rotationCenterX + 'px ' + rotationCenterY + 'px'); $(this.mesh).css('-o-transform-origin', rotationCenterX + 'px ' + rotationCenterY + 'px');
$(this.mesh).css('transform-origin', rotationCenterX + 'px ' + rotationCenterY + 'px'); $(this.mesh).css('transform-origin', rotationCenterX + 'px ' + rotationCenterY + 'px');
// Don't forget to update the talk bubble. // Don't forget to update the talk bubble.
@ -303,9 +303,9 @@ Sprite.prototype.updateTransform = function() {
this.talkBubble.css('left', xy[0] + 'px'); this.talkBubble.css('left', xy[0] + 'px');
this.talkBubble.css('top', xy[1] + 'px'); this.talkBubble.css('top', xy[1] + 'px');
} }
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') {
if (this.visible) this.talkBubbleStyler.addClass('bubble-think');
}
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,23 +371,23 @@ 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() {
var x = this.scratchX + 240; var x = this.scratchX + 240;
@ -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,35 +410,38 @@ 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) {
var hsv = Color.rgb2hsv(c); var hsv = Color.rgb2hsv(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;
var drawHeight = this.textures[this.currentCostumeIndex].height * this.scale; var drawHeight = this.textures[this.currentCostumeIndex].height * 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;
} };

View file

@ -35,31 +35,28 @@ 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;
this.lineCache.lineCap = 'round'; this.lineCache.lineCap = 'round';
@ -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();
} };

View file

@ -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;
@ -42,28 +42,28 @@ LooksPrims.prototype.addPrimsTo = function(primTable) {
primTable["changeGraphicEffect:by:"] = this.primChangeEffect; primTable["changeGraphicEffect:by:"] = this.primChangeEffect;
primTable["setGraphicEffect:to:"] = this.primSetEffect; primTable["setGraphicEffect:to:"] = this.primSetEffect;
primTable["filterReset"] = this.primClearEffects; primTable["filterReset"] = this.primClearEffects;
primTable["say:"] = function(b) { showBubble(b, 'say'); }; primTable["say:"] = function(b) { showBubble(b, 'say'); };
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();
if (s == null) return; if (s == null) return;
@ -88,8 +88,8 @@ 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;
var arg = interp.arg(b, 0); var arg = interp.arg(b, 0);
@ -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.primSetEffect = function(b) {} LooksPrims.prototype.primChangeEffect = function(b) {};
LooksPrims.prototype.primClearEffects = function(b) {} LooksPrims.prototype.primSetEffect = 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();
} }
} };

View file

@ -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;
@ -26,19 +26,19 @@ MotionAndPenPrims.prototype.addPrimsTo = function(primTable) {
primTable["gotoX:y:"] = this.primGoTo; primTable["gotoX:y:"] = this.primGoTo;
primTable["gotoSpriteOrMouse:"] = this.primGoToSpriteOrMouse; primTable["gotoSpriteOrMouse:"] = this.primGoToSpriteOrMouse;
primTable["glideSecs:toX:y:elapsed:from:"] = this.primGlide; primTable["glideSecs:toX:y:elapsed:from:"] = this.primGlide;
primTable["changeXposBy:"] = this.primChangeX; primTable["changeXposBy:"] = this.primChangeX;
primTable["xpos:"] = this.primSetX; primTable["xpos:"] = this.primSetX;
primTable["changeYposBy:"] = this.primChangeY; primTable["changeYposBy:"] = this.primChangeY;
primTable["ypos:"] = this.primSetY; primTable["ypos:"] = this.primSetY;
primTable["bounceOffEdge"] = this.primBounceOffEdge; primTable["bounceOffEdge"] = this.primBounceOffEdge;
primTable["setRotationStyle"] = this.primSetRotationStyle; primTable["setRotationStyle"] = this.primSetRotationStyle;
primTable["xpos"] = this.primXPosition; primTable["xpos"] = this.primXPosition;
primTable["ypos"] = this.primYPosition; primTable["ypos"] = this.primYPosition;
primTable["heading"] = this.primDirection; primTable["heading"] = this.primDirection;
primTable["clearPenTrails"] = this.primClear; primTable["clearPenTrails"] = this.primClear;
primTable["putPenDown"] = this.primPenDown; primTable["putPenDown"] = this.primPenDown;
primTable["putPenUp"] = this.primPenUp; primTable["putPenUp"] = this.primPenUp;
@ -49,63 +49,62 @@ MotionAndPenPrims.prototype.addPrimsTo = function(primTable) {
primTable["changePenShadeBy:"] = this.primChangePenShade; primTable["changePenShadeBy:"] = this.primChangePenShade;
primTable["penSize:"] = this.primSetPenSize; primTable["penSize:"] = this.primSetPenSize;
primTable["changePenSizeBy:"] = this.primChangePenSize; primTable["changePenSizeBy:"] = this.primChangePenSize;
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,44 +118,43 @@ 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
moveSpriteTo(s, state[4], state[5]); moveSpriteTo(s, state[4], state[5]);
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));
} }
} };

View file

@ -26,57 +26,57 @@ 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);
new LooksPrims().addPrimsTo(primTable); new LooksPrims().addPrimsTo(primTable);
new SensingPrims().addPrimsTo(primTable); new SensingPrims().addPrimsTo(primTable);
new SoundPrims().addPrimsTo(primTable); new SoundPrims().addPrimsTo(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);
} }
Primitives.prototype.primModulo = function(b) { Primitives.prototype.primModulo = function(b) {
var modulus = interp.arg(b, 1); var modulus = interp.arg(b, 1);
var n = interp.arg(b, 0) % modulus; var n = interp.arg(b, 0) % modulus;
@ -90,14 +90,14 @@ 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);
case "10 ^": return Math.exp(n * Math.LN10); case "10 ^": return Math.exp(n * Math.LN10);
} }

View file

@ -15,13 +15,13 @@
'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;
primTable['touchingColor:'] = this.primTouchingColor; primTable['touchingColor:'] = this.primTouchingColor;
primTable['color:sees:'] = this.primColorTouchingColor; primTable['color:sees:'] = this.primColorTouchingColor;
primTable['keyPressed:'] = this.primKeyPressed; primTable['keyPressed:'] = this.primKeyPressed;
primTable['mousePressed'] = function(b) { return runtime.mouseDown; }; primTable['mousePressed'] = function(b) { return runtime.mouseDown; };
primTable['mouseX'] = function(b) { return runtime.mousePos[0]; }; primTable['mouseX'] = function(b) { return runtime.mousePos[0]; };
@ -32,27 +32,27 @@ SensingPrims.prototype.addPrimsTo = function(primTable) {
primTable['timeAndDate'] = function(b){ return runtime.getTimeString(interp.arg(b, 0)); }; 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();
if (s == null || !s.visible) return false; if (s == null || !s.visible) return false;
var arg = interp.arg(b, 0); var arg = interp.arg(b, 0);
if (arg == '_edge_') { if (arg == '_edge_') {
return false; // TODO return false; // TODO
} }
if (arg == '_mouse_') { if (arg == '_mouse_') {
return false; // TODO return false; // TODO
} }
var s2 = runtime.spriteNamed(arg); var s2 = runtime.spriteNamed(arg);
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();
if (s == null || !s.visible) return false; if (s == null || !s.visible) return false;
@ -60,8 +60,8 @@ 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();
if (s == null || !s.visible) return false; if (s == null || !s.visible) return false;
@ -70,8 +70,8 @@ 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');
hitCanvas.width = 480; hitCanvas.width = 480;
@ -91,8 +91,8 @@ 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;
r = (color >> 16); r = (color >> 16);
@ -123,8 +123,8 @@ 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) {
var diff_a = Math.abs(a-x); var diff_a = Math.abs(a-x);
@ -134,7 +134,7 @@ var stageColorByColorHitTest = function(target, myColor, otherColor) {
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;
@ -159,21 +159,21 @@ var stageColorByColorHitTest = function(target, myColor, otherColor) {
hitCanvas.height = 360; hitCanvas.height = 360;
var 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);
var ch = key.charCodeAt(0); var ch = key.charCodeAt(0);
@ -184,8 +184,8 @@ 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();
var p = mouseOrSpritePosition(interp.arg(b, 0)); var p = mouseOrSpritePosition(interp.arg(b, 0));
@ -193,8 +193,8 @@ 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);
var targetSprite = runtime.spriteNamed(interp.arg(b, 1)); var targetSprite = runtime.spriteNamed(interp.arg(b, 1));
@ -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();
msSince += (now.getTimezoneOffset() - dst) * 60000; var epoch = new Date(2000, 0, 1);
return msSince / 86400000; var dst = now.getTimezoneOffset() - epoch.getTimezoneOffset();
} var msSince = now.getTime() - epoch.getTime();
msSince += (now.getTimezoneOffset() - dst) * 60000;
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;
} };

View file

@ -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) {
@ -42,11 +42,11 @@ var playSound = function(snd) {
snd.source.noteOff(0); snd.source.noteOff(0);
snd.source = null; snd.source = null;
} }
snd.source = runtime.audioContext.createBufferSource(); snd.source = runtime.audioContext.createBufferSource();
snd.source.buffer = snd.buffer; snd.source.buffer = snd.buffer;
snd.source.connect(runtime.audioGain); snd.source.connect(runtime.audioGain);
// Track the sound's completion state // Track the sound's completion state
snd.source.done = false; snd.source.done = false;
snd.source.finished = function() { snd.source.finished = function() {
@ -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);
@ -81,9 +81,9 @@ var playDrum = function(drum, secs, client) {
runtime.notesPlaying.splice(i, 1); runtime.notesPlaying.splice(i, 1);
} }
} }
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);
@ -99,9 +99,9 @@ var playNote = function(instrument, midiKey, secs, client) {
runtime.notesPlaying.splice(i, 1); runtime.notesPlaying.splice(i, 1);
} }
} }
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;
} };

View file

@ -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,11 +91,11 @@ VarListPrims.prototype.primShowVar = function(b) {
return; return;
} }
} }
} };
// List primitive implementations // List primitive implementations
// Take a list name and target sprite and return the JS list itself // Take a list name and target sprite and return the JS list itself
var findList = function(targetSprite, listName) { var findList = function(targetSprite, listName) {
if (targetSprite == null) targetSprite = runtime.stage; if (targetSprite == null) targetSprite = runtime.stage;
if (listName in targetSprite.lists) { if (listName in targetSprite.lists) {
@ -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,41 +126,42 @@ 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));
if (!list) return; if (!list) return;
var newItem = interp.arg(b, 0); var newItem = interp.arg(b, 0);
var position = interp.arg(b, 1); var position = interp.arg(b, 1);
if (position == 'last') position = list.length; if (position == 'last') position = list.length;
else if (position == 'random') position = Math.round(Math.random() * list.length); else if (position == 'random') position = Math.round(Math.random() * list.length);
else position = parseInt(position) - 1; else position = parseInt(position) - 1;
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));
if (!list) return; if (!list) return;
var newItem = interp.arg(b, 2); var newItem = interp.arg(b, 2);
var position = interp.arg(b, 0); var position = interp.arg(b, 0);
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;
} };

View file

@ -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;
} }
} };

View file

@ -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;
} };

View file

@ -22,7 +22,7 @@
var SoundDecoder = function(wavFileData) { var SoundDecoder = function(wavFileData) {
this.scratchSound = null; this.scratchSound = null;
this.soundData = null; this.soundData = null;
this.startOffset = 0; this.startOffset = 0;
this.endOffset = 0; this.endOffset = 0;
@ -37,10 +37,10 @@ var SoundDecoder = function(wavFileData) {
this.thisSample = 0; this.thisSample = 0;
// decoder state // decoder state
this.sample = 0; this.sample = 0;
this.index = 0; this.index = 0;
this.lastByte = -1; // -1 indicates that there is no saved lastByte this.lastByte = -1; // -1 indicates that there is no saved lastByte
this.nextSample = 0; this.nextSample = 0;
this.info = null; this.info = null;
@ -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) {
@ -149,13 +147,13 @@ SoundDecoder.stepTable = [
12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
]; ];
SoundDecoder.prototype.getSampleADPCM = function() { SoundDecoder.prototype.getSampleADPCM = function() {
// Decompress sample data using the IMA ADPCM algorithm. // Decompress sample data using the IMA ADPCM algorithm.
// 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;

View file

@ -19,11 +19,10 @@
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 = {};
var data = new OffsetBuffer(waveData); var data = new OffsetBuffer(waveData);
// read WAVE File Header // read WAVE File Header
@ -31,11 +30,11 @@ WAVFile.decode = function(waveData) {
var totalSize = data.readInt(); var totalSize = data.readInt();
if (data.getLength() != (totalSize + 8)) console.log("WAVFile: bad RIFF size; ignoring"); if (data.getLength() != (totalSize + 8)) console.log("WAVFile: bad RIFF size; ignoring");
if (data.readString(4) != 'WAVE') { console.log("WAVFile: not a WAVE file"); return; } if (data.readString(4) != 'WAVE') { console.log("WAVFile: not a WAVE file"); return; }
// read format chunk // read format chunk
var formatChunk = WAVFile.extractChunk('fmt ', data); var formatChunk = WAVFile.extractChunk('fmt ', data);
if (formatChunk.getLength() < 16) { console.log("WAVFile: format chunk is too small"); return; } if (formatChunk.getLength() < 16) { console.log("WAVFile: format chunk is too small"); return; }
var encoding = formatChunk.readShort(); var encoding = formatChunk.readShort();
result.encoding = encoding; result.encoding = encoding;
result.channels = formatChunk.readShort(); result.channels = formatChunk.readShort();
@ -48,7 +47,7 @@ WAVFile.decode = function(waveData) {
var sampleDataStartAndSize = WAVFile.dataChunkStartAndSize(data); var sampleDataStartAndSize = WAVFile.dataChunkStartAndSize(data);
result.sampleDataStart = sampleDataStartAndSize[0]; result.sampleDataStart = sampleDataStartAndSize[0];
result.sampleDataSize = sampleDataStartAndSize[1]; result.sampleDataSize = sampleDataStartAndSize[1];
// handle various encodings // handle various encodings
if (encoding == 1) { if (encoding == 1) {
if (!((result.bitsPerSample == 8) || (result.bitsPerSample == 16))) { if (!((result.bitsPerSample == 8) || (result.bitsPerSample == 16))) {
@ -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
} };

View file

@ -20,70 +20,70 @@
Color = function() {}; Color = function() {};
Color.fromHSV = function(h, s, v) { Color.fromHSV = function(h, s, v) {
var r, g, b; var r, g, b;
h = h % 360; h = h % 360;
if (h < 0) h += 360; if (h < 0) h += 360;
s = Math.max(0, Math.min(s, 1)); s = Math.max(0, Math.min(s, 1));
v = Math.max(0, Math.min(v, 1)); v = Math.max(0, Math.min(v, 1));
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; }
else if (i == 3) { r = p; g = q; b = v; } else if (i == 3) { r = p; g = q; b = v; }
else if (i == 4) { r = t; g = p; b = v; } else if (i == 4) { r = t; g = p; b = v; }
else if (i == 5) { r = v; g = p; b = q; } else if (i == 5) { r = v; g = p; b = q; }
r = Math.floor(r * 255); r = Math.floor(r * 255);
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;
var r = ((rgb >> 16) & 255) / 255; var r = ((rgb >> 16) & 255) / 255;
var g = ((rgb >> 8) & 255) / 255; var g = ((rgb >> 8) & 255) / 255;
var b = (rgb & 255) / 255; var b = (rgb & 255) / 255;
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.
if (fraction <= 0) return rgb1; if (fraction <= 0) return rgb1;
if (fraction >= 1) return rgb2; if (fraction >= 1) return rgb2;
var r1 = (rgb1 >> 16) & 255; var r1 = (rgb1 >> 16) & 255;
var g1 = (rgb1 >> 8) & 255; var g1 = (rgb1 >> 8) & 255;
var b1 = rgb1 & 255 var b1 = rgb1 & 255
var r2 = (rgb2 >> 16) & 255; var r2 = (rgb2 >> 16) & 255;
var g2 = (rgb2 >> 8) & 255; var g2 = (rgb2 >> 8) & 255;
var b2 = rgb2 & 255 var b2 = rgb2 & 255
var r = ((fraction * r2) + ((1.0 - fraction) * r1)) & 255; var r = ((fraction * r2) + ((1.0 - fraction) * r1)) & 255;
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
var h = 360 * Math.random(); var h = 360 * Math.random();
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);
} };

View file

@ -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];
} };

View file

@ -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);
}

View file

@ -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);
} }
} };