Merge remote-tracking branch 'LLK/develop' into develop

This commit is contained in:
Eric Rosenbaum 2016-10-11 13:47:24 -04:00
parent ed9623ef4b
commit 0024b209bd
11 changed files with 303 additions and 3 deletions

15
.github/ISSUE_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,15 @@
### Expected behavior
_Please describe what should happen_
### Actual behavior
_Describe what actually happens_
### Steps to reproduce
_Explain what someone needs to do in order to see what's described in *Actual behavior* above_
### Operating system and browser
_e.g. Mac OS 10.11.6 Safari 10.0_

7
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,7 @@
### Proposed changes
_Describe what this Pull Request does_
### Reason for changes
_Explain why these changes should be made. Please include an issue # if applicable._

25
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,25 @@
## Contributing
The development of scratch-vm is an ongoing process,
and we love to have people in the Scratch and open source communities help us along the way.
If you're interested in contributing, please take a look at the
[issues](https://github.com/LLK/scratch-vm/issues) on this repository.
Two great ways of helping are by identifying bugs and documenting them as issues,
or fixing issues and creating pull requests. When submitting pull requests please be patient
-- it can take a while to find time to review them.
The organization and class structures can't be radically changed without significant coordination
and collaboration from the Scratch Team, so these types of changes should be avoided.
It's been said that the Scratch Team spends about one hour of design discussion for every pixel in Scratch,
but some think that estimate is a little low. While we welcome suggestions for new features in our
[suggestions forum](https://scratch.mit.edu/discuss/1/) (especially ones that come with mockups), we are unlikely to accept PRs with
new features that haven't been thought through and discussed as a group. Why? Because we have a strong belief
in the value of keeping things simple for new users. To learn more about our design philosophy,
see [the Scratch Developers page](https://scratch.mit.edu/developers), or
[this paper](http://web.media.mit.edu/~mres/papers/Scratch-CACM-final.pdf).
Beyond this repo, there are also some other resources that you might want to take a look at:
* [Community Guidelines](https://github.com/LLK/scratch-www/wiki/Community-Guidelines) (we find it important to maintain a constructive and welcoming community, just like on Scratch)
* [Open Source forum](https://scratch.mit.edu/discuss/49/) on Scratch
* [Suggestions forum](https://scratch.mit.edu/discuss/1/) on Scratch
* [Bugs & Glitches forum](https://scratch.mit.edu/discuss/3/) on Scratch

View file

@ -2,6 +2,7 @@
#### Scratch VM is a library for representing, running, and maintaining the state of computer programs written using [Scratch Blocks](https://github.com/LLK/scratch-blocks).
[![Build Status](https://travis-ci.org/LLK/scratch-vm.svg?branch=develop)](https://travis-ci.org/LLK/scratch-vm)
[![Coverage Status](https://coveralls.io/repos/github/LLK/scratch-vm/badge.svg?branch=develop)](https://coveralls.io/github/LLK/scratch-vm?branch=develop)
[![Dependency Status](https://david-dm.org/LLK/scratch-vm.svg)](https://david-dm.org/LLK/scratch-vm)
[![devDependency Status](https://david-dm.org/LLK/scratch-vm/dev-status.svg)](https://david-dm.org/LLK/scratch-vm#info=devDependencies)

Binary file not shown.

Before

(image error) Size: 1.3 KiB

After

(image error) Size: 3.5 KiB

Before After
Before After

View file

@ -13,6 +13,7 @@ h2 {
right: 0;
top: 0;
bottom: 0;
font-family: "Helvetica Neue", Helvetica, sans-serif;
}
#vm-devtools {
color: rgb(217,217,217);

View file

@ -18,9 +18,11 @@ Scratch3MotionBlocks.prototype.getPrimitives = function() {
return {
'motion_movesteps': this.moveSteps,
'motion_gotoxy': this.goToXY,
'motion_goto': this.goTo,
'motion_turnright': this.turnRight,
'motion_turnleft': this.turnLeft,
'motion_pointindirection': this.pointInDirection,
'motion_pointtowards': this.pointTowards,
'motion_glidesecstoxy': this.glide,
'motion_setrotationstyle': this.setRotationStyle,
'motion_changexby': this.changeX,
@ -47,6 +49,26 @@ Scratch3MotionBlocks.prototype.goToXY = function (args, util) {
util.target.setXY(x, y);
};
Scratch3MotionBlocks.prototype.goTo = function (args, util) {
var targetX = 0;
var targetY = 0;
if (args.TO === '_mouse_') {
targetX = util.ioQuery('mouse', 'getX');
targetY = util.ioQuery('mouse', 'getY');
} else if (args.TO === '_random_') {
var stageWidth = this.runtime.constructor.STAGE_WIDTH;
var stageHeight = this.runtime.constructor.STAGE_HEIGHT;
targetX = Math.round(stageWidth * (Math.random() - 0.5));
targetY = Math.round(stageHeight * (Math.random() - 0.5));
} else {
var goToTarget = this.runtime.getSpriteTargetByName(args.TO);
if (!goToTarget) return;
targetX = goToTarget.x;
targetY = goToTarget.y;
}
util.target.setXY(targetX, targetY);
};
Scratch3MotionBlocks.prototype.turnRight = function (args, util) {
var degrees = Cast.toNumber(args.DEGREES);
util.target.setDirection(util.target.direction + degrees);
@ -62,6 +84,25 @@ Scratch3MotionBlocks.prototype.pointInDirection = function (args, util) {
util.target.setDirection(direction);
};
Scratch3MotionBlocks.prototype.pointTowards = function (args, util) {
var targetX = 0;
var targetY = 0;
if (args.TOWARDS === '_mouse_') {
targetX = util.ioQuery('mouse', 'getX');
targetY = util.ioQuery('mouse', 'getY');
} else {
var pointTarget = this.runtime.getSpriteTargetByName(args.TOWARDS);
if (!pointTarget) return;
targetX = pointTarget.x;
targetY = pointTarget.y;
}
var dx = targetX - util.target.x;
var dy = targetY - util.target.y;
var direction = 90 - MathUtil.radToDeg(Math.atan2(dy, dx));
util.target.setDirection(direction);
};
Scratch3MotionBlocks.prototype.glide = function (args, util) {
if (!util.stackFrame.timer) {
// First time: save data for future use.

View file

@ -16,6 +16,7 @@ Scratch3SensingBlocks.prototype.getPrimitives = function() {
return {
'sensing_touchingcolor': this.touchingColor,
'sensing_coloristouchingcolor': this.colorTouchingColor,
'sensing_distanceto': this.distanceTo,
'sensing_timer': this.getTimer,
'sensing_resettimer': this.resetTimer,
'sensing_mousex': this.getMouseX,
@ -37,6 +38,28 @@ Scratch3SensingBlocks.prototype.colorTouchingColor = function (args, util) {
return util.target.colorIsTouchingColor(targetColor, maskColor);
};
Scratch3SensingBlocks.prototype.distanceTo = function (args, util) {
if (util.target.isStage) return 10000;
var targetX = 0;
var targetY = 0;
if (args.DISTANCETOMENU === '_mouse_') {
targetX = util.ioQuery('mouse', 'getX');
targetY = util.ioQuery('mouse', 'getY');
} else {
var distTarget = this.runtime.getSpriteTargetByName(
args.DISTANCETOMENU
);
if (!distTarget) return 10000;
targetX = distTarget.x;
targetY = distTarget.y;
}
var dx = util.target.x - targetX;
var dy = util.target.y - targetY;
return Math.sqrt((dx * dx) + (dy * dy));
};
Scratch3SensingBlocks.prototype.getTimer = function (args, util) {
return util.ioQuery('clock', 'projectTimer');
};

View file

@ -70,6 +70,18 @@ function Runtime () {
this._cloneCounter = 0;
}
/**
* Width of the stage, in pixels.
* @const {number}
*/
Runtime.STAGE_WIDTH = 480;
/**
* Height of the stage, in pixels.
* @const {number}
*/
Runtime.STAGE_HEIGHT = 360;
/**
* Event name for glowing a script.
* @const {string}

View file

@ -137,9 +137,9 @@ VirtualMachine.prototype.createEmptyProject = function () {
stage.costumes.push({
skin: '/assets/stage.png',
name: 'backdrop1',
bitmapResolution: 1,
rotationCenterX: 240,
rotationCenterY: 180
bitmapResolution: 2,
rotationCenterX: 480,
rotationCenterY: 360
});
var target2 = stage.createClone();
this.runtime.targets.push(target2);

View file

@ -0,0 +1,175 @@
var test = require('tap').test;
var Operators = require('../../src/blocks/scratch3_operators');
var blocks = new Operators(null);
test('getPrimitives', function (t) {
t.type(blocks.getPrimitives(), 'object');
t.end();
});
test('add', function (t) {
t.strictEqual(blocks.add({NUM1:'1', NUM2:'1'}), 2);
t.strictEqual(blocks.add({NUM1:'foo', NUM2:'bar'}), 0);
t.end();
});
test('subtract', function (t) {
t.strictEqual(blocks.subtract({NUM1:'1', NUM2:'1'}), 0);
t.strictEqual(blocks.subtract({NUM1:'foo', NUM2:'bar'}), 0);
t.end();
});
test('multiply', function (t) {
t.strictEqual(blocks.multiply({NUM1:'2', NUM2:'2'}), 4);
t.strictEqual(blocks.multiply({NUM1:'foo', NUM2:'bar'}), 0);
t.end();
});
test('divide', function (t) {
t.strictEqual(blocks.divide({NUM1:'2', NUM2:'2'}), 1);
t.strictEqual(blocks.divide({NUM1:'1', NUM2:'0'}), Infinity); // @todo
t.ok(isNaN(blocks.divide({NUM1:'foo', NUM2:'bar'}))); // @todo
t.end();
});
test('lt', function (t) {
t.strictEqual(blocks.lt({OPERAND1:'1', OPERAND2:'2'}), true);
t.strictEqual(blocks.lt({OPERAND1:'2', OPERAND2:'1'}), false);
t.strictEqual(blocks.lt({OPERAND1:'1', OPERAND2:'1'}), false);
t.end();
});
test('equals', function (t) {
t.strictEqual(blocks.equals({OPERAND1:'1', OPERAND2:'2'}), false);
t.strictEqual(blocks.equals({OPERAND1:'2', OPERAND2:'1'}), false);
t.strictEqual(blocks.equals({OPERAND1:'1', OPERAND2:'1'}), true);
t.end();
});
test('gt', function (t) {
t.strictEqual(blocks.gt({OPERAND1:'1', OPERAND2:'2'}), false);
t.strictEqual(blocks.gt({OPERAND1:'2', OPERAND2:'1'}), true);
t.strictEqual(blocks.gt({OPERAND1:'1', OPERAND2:'1'}), false);
t.end();
});
test('and', function (t) {
t.strictEqual(blocks.and({OPERAND1:true, OPERAND2:true}), true);
t.strictEqual(blocks.and({OPERAND1:true, OPERAND2:false}), false);
t.strictEqual(blocks.and({OPERAND1:false, OPERAND2:false}), false);
t.end();
});
test('or', function (t) {
t.strictEqual(blocks.or({OPERAND1:true, OPERAND2:true}), true);
t.strictEqual(blocks.or({OPERAND1:true, OPERAND2:false}), true);
t.strictEqual(blocks.or({OPERAND1:false, OPERAND2:false}), false);
t.end();
});
test('not', function (t) {
t.strictEqual(blocks.not({OPERAND:true}), false);
t.strictEqual(blocks.not({OPERAND:false}), true);
t.end();
});
test('random', function (t) {
var min = 0;
var max = 100;
var result = blocks.random({FROM:min, TO:max});
t.ok(result >= min);
t.ok(result <= max);
t.end();
});
test('random - equal', function (t) {
var min = 1;
var max = 1;
t.strictEqual(blocks.random({FROM:min, TO:max}), min);
t.end();
});
test('random - decimal', function (t) {
var min = 0.1;
var max = 10;
var result = blocks.random({FROM:min, TO:max});
t.ok(result >= min);
t.ok(result <= max);
t.end();
});
test('random - int', function (t) {
var min = 0;
var max = 10;
var result = blocks.random({FROM:min, TO:max});
t.ok(result >= min);
t.ok(result <= max);
t.end();
});
test('random - reverse', function (t) {
var min = 0;
var max = 10;
var result = blocks.random({FROM:max, TO:min});
t.ok(result >= min);
t.ok(result <= max);
t.end();
});
test('join', function (t) {
t.strictEqual(blocks.join({STRING1:'foo', STRING2:'bar'}), 'foobar');
t.strictEqual(blocks.join({STRING1:'1', STRING2:'2'}), '12');
t.end();
});
test('letterOf', function (t) {
t.strictEqual(blocks.letterOf({STRING:'foo', LETTER:0}), '');
t.strictEqual(blocks.letterOf({STRING:'foo', LETTER:1}), 'f');
t.strictEqual(blocks.letterOf({STRING:'foo', LETTER:2}), 'o');
t.strictEqual(blocks.letterOf({STRING:'foo', LETTER:3}), 'o');
t.strictEqual(blocks.letterOf({STRING:'foo', LETTER:4}), '');
t.strictEqual(blocks.letterOf({STRING:'foo', LETTER:'bar'}), '');
t.end();
});
test('length', function (t) {
t.strictEqual(blocks.length({STRING:''}), 0);
t.strictEqual(blocks.length({STRING:'foo'}), 3);
t.strictEqual(blocks.length({STRING:'1'}), 1);
t.strictEqual(blocks.length({STRING:'100'}), 3);
t.end();
});
test('mod', function (t) {
t.strictEqual(blocks.mod({NUM1:1, NUM2:1}), 0);
t.strictEqual(blocks.mod({NUM1:3, NUM2:6}), 3);
t.strictEqual(blocks.mod({NUM1:-3, NUM2:6}), 3);
t.end();
});
test('round', function (t) {
t.strictEqual(blocks.round({NUM:1}), 1);
t.strictEqual(blocks.round({NUM:1.1}), 1);
t.strictEqual(blocks.round({NUM:1.5}), 2);
t.end();
});
test('mathop', function (t) {
t.strictEqual(blocks.mathop({OPERATOR:'abs', NUM:-1}), 1);
t.strictEqual(blocks.mathop({OPERATOR:'floor', NUM:1.5}), 1);
t.strictEqual(blocks.mathop({OPERATOR:'ceiling', NUM:0.1}), 1);
t.strictEqual(blocks.mathop({OPERATOR:'sqrt', NUM:1}), 1);
t.strictEqual(blocks.mathop({OPERATOR:'sin', NUM:1}), 0.01745240643728351);
t.strictEqual(blocks.mathop({OPERATOR:'cos', NUM:1}), 0.9998476951563913);
t.strictEqual(blocks.mathop({OPERATOR:'tan', NUM:1}), 0.017455064928217585);
t.strictEqual(blocks.mathop({OPERATOR:'asin', NUM:1}), 90);
t.strictEqual(blocks.mathop({OPERATOR:'acos', NUM:1}), 0);
t.strictEqual(blocks.mathop({OPERATOR:'atan', NUM:1}), 45);
t.strictEqual(blocks.mathop({OPERATOR:'ln', NUM:1}), 0);
t.strictEqual(blocks.mathop({OPERATOR:'log', NUM:1}), 0);
t.strictEqual(blocks.mathop({OPERATOR:'e ^', NUM:1}), 2.718281828459045);
t.strictEqual(blocks.mathop({OPERATOR:'10 ^', NUM:1}), 10);
t.strictEqual(blocks.mathop({OPERATOR:'undefined', NUM:1}), 0);
t.end();
});