Skip to content

Commit

Permalink
Monster update.
Browse files Browse the repository at this point in the history
Interleave pond-basic and pond-advanced to form pond-tutor.
Create open-ended pond-duck with either JS or Blocks.
Update to latest Blockly core.
Replace readonly iframes with inline workspaces.
  • Loading branch information
NeilFraser committed Feb 24, 2016
1 parent 1d3aa46 commit 7d214a7
Show file tree
Hide file tree
Showing 118 changed files with 2,620 additions and 2,279 deletions.
23 changes: 12 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
# Definitions
##############################

USER_APPS = {index,puzzle,maze,bird,turtle,movie,pond/docs,pond/basic,pond/advanced}
ALL_JSON = {./,index,puzzle,maze,bird,turtle,movie,pond/docs,pond,pond/basic,pond/advanced}
ALL_TEMPLATES = appengine/template.soy,appengine/index/template.soy,appengine/puzzle/template.soy,appengine/maze/template.soy,appengine/bird/template.soy,appengine/turtle/template.soy,appengine/movie/template.soy,appengine/pond/docs/template.soy,appengine/pond/template.soy,appengine/pond/basic/template.soy,appengine/pond/advanced/template.soy
USER_APPS = {index,puzzle,maze,bird,turtle,movie,pond/docs,pond/tutor,pond/duck}
ALL_JSON = {./,index,puzzle,maze,bird,turtle,movie,pond/docs,pond,pond/tutor,pond/duck}
ALL_TEMPLATES = appengine/template.soy,appengine/index/template.soy,appengine/puzzle/template.soy,appengine/maze/template.soy,appengine/bird/template.soy,appengine/turtle/template.soy,appengine/movie/template.soy,appengine/pond/docs/template.soy,appengine/pond/template.soy,appengine/pond/tutor/template.soy,appengine/pond/duck/template.soy

JS_READ_ONLY = appengine/js-read-only
SOY_COMPILER = java -jar closure-templates-read-only/build/SoyToJsSrcCompiler.jar --shouldProvideRequireSoyNamespaces
SOY_COMPILER = java -jar closure-templates-read-only/build/SoyToJsSrcCompiler.jar --shouldProvideRequireSoyNamespaces --isUsingIjData
SOY_EXTRACTOR = java -jar closure-templates-read-only/build/SoyMsgExtractor.jar

BLOCKY_DIR = $(PWD)
Expand Down Expand Up @@ -44,23 +44,24 @@ movie-en: common-en
python build-app.py movie en

pond-docs-en:
mkdir -p appengine/pond/generated/en/
$(SOY_COMPILER) --outputPathFormat appengine/pond/docs/generated/en/soy.js --srcs appengine/pond/docs/template.soy
python build-app.py pond/docs en

pond-basic-en: pond-common-en
$(SOY_COMPILER) --outputPathFormat appengine/pond/basic/generated/en/soy.js --srcs appengine/pond/basic/template.soy
python build-app.py pond/basic en
pond-tutor-en: pond-common-en
$(SOY_COMPILER) --outputPathFormat appengine/pond/tutor/generated/en/soy.js --srcs appengine/pond/tutor/template.soy
python build-app.py pond/tutor en

pond-advanced-en: pond-common-en
$(SOY_COMPILER) --outputPathFormat appengine/pond/advanced/generated/en/soy.js --srcs appengine/pond/advanced/template.soy
python build-app.py pond/advanced en
pond-duck-en: pond-common-en
$(SOY_COMPILER) --outputPathFormat appengine/pond/duck/generated/en/soy.js --srcs appengine/pond/duck/template.soy
python build-app.py pond/duck en

pond-common-en: common-en
$(SOY_COMPILER) --outputPathFormat appengine/pond/generated/en/soy.js --srcs appengine/pond/template.soy
common-en:
$(SOY_COMPILER) --outputPathFormat appengine/generated/en/soy.js --srcs appengine/template.soy

en: index-en puzzle-en maze-en bird-en turtle-en movie-en pond-docs-en pond-basic-en pond-advanced-en
en: index-en puzzle-en maze-en bird-en turtle-en movie-en pond-docs-en pond-tutor-en pond-duck-en

languages:
$(SOY_EXTRACTOR) --outputFile extracted_msgs.xlf --srcs $(ALL_TEMPLATES)
Expand Down
12 changes: 6 additions & 6 deletions appengine/about.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,21 +72,21 @@ <h1><a id="back" href="/">Blockly Games</a> : About</h1>

<tr>
<td>
<img src="index/pond-basic.png" height=100 width=100>
<img src="index/pond-tutor.png" height=100 width=100>
</td>
<td>
<p>Pond is an open-ended contest to program the smartest duck. The blocks now
contain real JavaScript code written on them.</p>
<p>Pond Tutor introduces text-based programming. Levels switch back and forth
between blocks and actual JavaScript in a text editor.</p>
</td>
</tr>

<tr>
<td>
<img src="index/pond-advanced.png" height=100 width=100>
<img src="index/pond-duck.png" height=100 width=100>
</td>
<td>
<p>Pond JS switches from blocks to conventional text-based programming. The
ducks are faster and more skilled.</p>
<p>Pond is an open-ended contest to program the smartest duck.
Use either blocks or JavaScript.</p>
</td>
</tr>
</table>
Expand Down
15 changes: 8 additions & 7 deletions appengine/app.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
application: blockly-games
version: 2
version: 1
runtime: python27
api_version: 1
threadsafe: no
Expand Down Expand Up @@ -89,13 +89,13 @@ handlers:
secure: always

# Pond apps.
- url: /pond-basic
static_files: pond-basic.html
upload: pond-basic\.html
- url: /pond-tutor
static_files: pond-tutor.html
upload: pond-tutor\.html
secure: always
- url: /pond-advanced
static_files: pond-advanced.html
upload: pond-advanced\.html
- url: /pond-duck
static_files: pond-duck.html
upload: pond-duck\.html
secure: always
- url: /pond/
static_dir: pond
Expand Down Expand Up @@ -150,6 +150,7 @@ skip_files:
# Custom skip patterns.
- ^\w+/sources/.*$
- ^js-read-only/blockly/generators/dart.*$
- ^js-read-only/blockly/generators/php.*$
- ^js-read-only/blockly/generators/python.*$
- ^js-read-only/third_party_goog/.*$
- ^js-read-only/ace/snippets/.*$
Expand Down
69 changes: 42 additions & 27 deletions appengine/bird/js/bird.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ goog.require('BlocklyInterface');
goog.require('goog.math');
goog.require('goog.math.Coordinate');
goog.require('goog.math.Line');
goog.require('goog.style');


BlocklyGames.NAME = 'bird';
Expand Down Expand Up @@ -335,14 +336,16 @@ Bird.init = function() {
onresize();

var toolbox = document.getElementById('toolbox');
Blockly.inject(document.getElementById('blockly'),
BlocklyGames.workspace = Blockly.inject('blockly',
{'media': 'media/',
'rtl': rtl,
'toolbox': toolbox,
'trashcan': true});
Blockly.loadAudio_(['bird/quack.ogg', 'bird/quack.mp3'], 'quack');
Blockly.loadAudio_(['bird/whack.mp3', 'bird/whack.ogg'], 'whack');
Blockly.loadAudio_(['bird/worm.mp3', 'bird/worm.ogg'], 'worm');
BlocklyGames.workspace.loadAudio_(['bird/quack.ogg', 'bird/quack.mp3'],
'quack');
BlocklyGames.workspace.loadAudio_(['bird/whack.mp3', 'bird/whack.ogg'],
'whack');
BlocklyGames.workspace.loadAudio_(['bird/worm.mp3', 'bird/worm.ogg'], 'worm');
// Not really needed, there are no user-defined functions or variables.
Blockly.JavaScript.addReservedWords('noWorm,heading,getX,getY');

Expand Down Expand Up @@ -375,7 +378,7 @@ Bird.init = function() {
// Open interactive help. But wait 5 seconds for the
// user to think a bit before they are told what to do.
setTimeout(function() {
Blockly.addChangeListener(function() {Bird.levelHelp()});
BlocklyGames.workspace.addChangeListener(function() {Bird.levelHelp()});
Bird.levelHelp();
}, 5000);
if (BlocklyGames.LEVEL > 8) {
Expand All @@ -390,6 +393,12 @@ Bird.init = function() {

window.addEventListener('load', Bird.init);

/**
* PID of task to poll the mutator's state in level 5.
* @private
*/
Bird.mutatorHelpPid_ = 0;

/**
* When the workspace changes, update the help as needed.
*/
Expand All @@ -403,18 +412,20 @@ Bird.levelHelp = function() {
// The user has already won. They are just playing around.
return;
}
var rtl = BlocklyGames.isRtl();
var userBlocks = Blockly.Xml.domToText(
Blockly.Xml.workspaceToDom(Blockly.mainWorkspace));
var toolbar = Blockly.mainWorkspace.flyout_.workspace_.getTopBlocks(true);
Blockly.Xml.workspaceToDom(BlocklyGames.workspace));
var toolbar = BlocklyGames.workspace.flyout_.workspace_.getTopBlocks(true);
var content = document.getElementById('dialogHelp');
var origin = null;
var style = null;
if (BlocklyGames.LEVEL == 1) {
if (userBlocks.indexOf('>90<') != -1 ||
userBlocks.indexOf('bird_heading') == -1) {
if ((userBlocks.indexOf('>90<') != -1 ||
userBlocks.indexOf('bird_heading') == -1) &&
!Blockly.WidgetDiv.isVisible()) {
style = {'width': '370px', 'top': '140px'};
style[Blockly.RTL ? 'right' : 'left'] = '215px';
var blocks = Blockly.mainWorkspace.getTopBlocks(true);
style[rtl ? 'right' : 'left'] = '215px';
var blocks = BlocklyGames.workspace.getTopBlocks(true);
if (blocks.length) {
origin = blocks[0].getSvgRoot();
} else {
Expand All @@ -424,53 +435,57 @@ Bird.levelHelp = function() {
} else if (BlocklyGames.LEVEL == 2) {
if (userBlocks.indexOf('bird_noWorm') == -1) {
style = {'width': '350px', 'top': '170px'};
style[Blockly.RTL ? 'right' : 'left'] = '180px';
style[rtl ? 'right' : 'left'] = '180px';
origin = toolbar[1].getSvgRoot();
}
} else if (BlocklyGames.LEVEL == 4) {
if (userBlocks.indexOf('bird_compare') == -1) {
style = {'width': '350px', 'top': '230px'};
style[Blockly.RTL ? 'right' : 'left'] = '180px';
style[rtl ? 'right' : 'left'] = '180px';
origin = toolbar[2].getSvgRoot();
}
} else if (BlocklyGames.LEVEL == 5) {
if (!Bird.mutatorHelpPid_) {
// Keep polling the mutator's state.
Bird.mutatorHelpPid_ = setInterval(Bird.levelHelp, 100);
}
if (userBlocks.indexOf('mutation else') == -1) {
var blocks = Blockly.mainWorkspace.getTopBlocks(false);
var blocks = BlocklyGames.workspace.getTopBlocks(false);
for (var i = 0, block; block = blocks[i]; i++) {
if (block.type == 'controls_if') {
break;
}
}
if (!block.mutator.isVisible()) {
var xy = Blockly.getAbsoluteXY_(block.getSvgRoot());
var xy = goog.style.getPageOffset(block.getSvgRoot());
style = {'width': '340px', 'top': (xy.y + 100) + 'px'};
style.left = (xy.x - (Blockly.RTL ? 350 : 0)) + 'px';
style.left = (xy.x - (rtl ? 350 : 0)) + 'px';
origin = block.getSvgRoot();
} else {
var content = document.getElementById('dialogMutatorHelp');
content = document.getElementById('dialogMutatorHelp');
origin = block.mutator.workspace_.flyout_.buttons_[1];
var xy = Blockly.getAbsoluteXY_(origin);
var xy = goog.style.getPageOffset(origin);
style = {'width': '340px', 'top': (xy.y + 60) + 'px'};
style.left = (xy.x - (Blockly.RTL ? 310 : 0)) + 'px';
style.left = (xy.x - (rtl ? 310 : 0)) + 'px';
}
}
} else if (BlocklyGames.LEVEL == 6) {
if (userBlocks.indexOf('mutation') == -1) {
var blocks = Blockly.mainWorkspace.getTopBlocks(false);
var blocks = BlocklyGames.workspace.getTopBlocks(false);
for (var i = 0, block; block = blocks[i]; i++) {
if (block.type == 'controls_if') {
break;
}
}
var xy = Blockly.getAbsoluteXY_(block.getSvgRoot());
var xy = goog.style.getPageOffset(block.getSvgRoot());
style = {'width': '350px', 'top': (xy.y + 220) + 'px'};
style.left = (xy.x - (Blockly.RTL ? 350 : 0)) + 'px';
style.left = (xy.x - (rtl ? 350 : 0)) + 'px';
origin = block.getSvgRoot();
}
} else if (BlocklyGames.LEVEL == 8) {
if (userBlocks.indexOf('bird_and') == -1) {
style = {'width': '350px', 'top': '360px'};
style[Blockly.RTL ? 'right' : 'left'] = '450px';
style[rtl ? 'right' : 'left'] = '450px';
origin = toolbar[4].getSvgRoot();
}
}
Expand Down Expand Up @@ -535,7 +550,7 @@ Bird.runButtonClick = function(e) {
}
runButton.style.display = 'none';
resetButton.style.display = 'inline';
Blockly.mainWorkspace.traceOn(true);
BlocklyGames.workspace.traceOn(true);
Bird.reset(false);
Bird.execute();
};
Expand All @@ -552,7 +567,7 @@ Bird.resetButtonClick = function(e) {
var runButton = document.getElementById('runButton');
runButton.style.display = 'inline';
document.getElementById('resetButton').style.display = 'none';
Blockly.mainWorkspace.traceOn(false);
BlocklyGames.workspace.traceOn(false);
Bird.reset(false);
};

Expand Down Expand Up @@ -608,7 +623,7 @@ Bird.execute = function() {
}

Bird.log = [];
var code = Blockly.JavaScript.workspaceToCode();
var code = Blockly.JavaScript.workspaceToCode(BlocklyGames.workspace);
var start = code.indexOf('if (');
var end = code.indexOf('}\n');
if (start != -1 && end != -1) {
Expand Down Expand Up @@ -690,7 +705,7 @@ Bird.animate = function() {
BlocklyInterface.saveToLocalStorage();
BlocklyDialogs.congratulations();
} else if (action[0] == 'play') {
Blockly.playAudio(action[1], 0.5);
BlocklyGames.workspace.playAudio(action[1], 0.5);
}

Bird.pidList.push(setTimeout(Bird.animate, Bird.stepSpeed * 5));
Expand Down
2 changes: 1 addition & 1 deletion appengine/bird/js/blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ Blockly.Blocks['bird_compare'] = {
*/
init: function() {
this.setHelpUrl(Blockly.Msg.LOGIC_COMPARE_HELPURL);
if (Blockly.RTL) {
if (BlocklyGames.isRtl()) {
var OPERATORS = [['>', 'LT'], ['<', 'GT']];
} else {
var OPERATORS = [['<', 'LT'], ['>', 'GT']];
Expand Down
3 changes: 3 additions & 0 deletions appengine/common/common.css
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,6 @@ button:hover:not(:disabled) {
#dialog button {
min-width: 4em;
}
.readonly .blocklyMainBackground {
stroke: none;
}
42 changes: 0 additions & 42 deletions appengine/common/readonly-boot.js

This file was deleted.

6 changes: 3 additions & 3 deletions appengine/common/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,17 +138,17 @@ BlocklyStorage.handleRequest_ = function() {
* @private
*/
BlocklyStorage.monitorChanges_ = function() {
var startXmlDom = Blockly.Xml.workspaceToDom(Blockly.getMainWorkspace());
var startXmlDom = Blockly.Xml.workspaceToDom(BlocklyGames.workspace);
var startXmlText = Blockly.Xml.domToText(startXmlDom);
function change() {
var xmlDom = Blockly.Xml.workspaceToDom(Blockly.getMainWorkspace());
var xmlDom = Blockly.Xml.workspaceToDom(BlocklyGames.workspace);
var xmlText = Blockly.Xml.domToText(xmlDom);
if (startXmlText != xmlText) {
window.location.hash = '';
Blockly.removeChangeListener(bindData);
}
}
var bindData = Blockly.addChangeListener(change);
var bindData = BlocklyGames.workspace.addChangeListener(change);
};

/**
Expand Down
2 changes: 1 addition & 1 deletion appengine/index/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ goog.require('BlocklyGames');
* Array of application names.
*/
Index.APPS = ['puzzle', 'maze', 'bird', 'turtle', 'movie',
'pond-basic', 'pond-advanced'];
'pond-tutor', 'pond-duck'];

/**
* Initialize Blockly and the maze. Called on page load.
Expand Down
File renamed without changes
File renamed without changes
Loading

0 comments on commit 7d214a7

Please sign in to comment.