Google's Blockly Games 是一个基于Blockly library的系列具有教育意义的游戏,包含了8个小游戏,分别是拼图、迷宫、贪吃鸟、画图、电影、音乐、射击指南、自由射击。此系列游戏,目的是加深对Blockly library的理解以及应用,我会简单分析游戏是如何玩的,然后再向大家介绍源码的实现方式。
游戏界面导航 -c
BlocklyGames对象
BlocklyGames是某个游戏的全局对象,主要功能是控制程序语言以及等级。
BlocklyGames.LEVEL 游戏等级
BlocklyGames.LANG 游戏语言
初始化函数:初始化游戏语言和游戏等级
加载浏览器缓存:游戏会进行自动保存,保存到浏览器缓存中,进入游戏时会首先读缓存,然后再执行指定等级。
BlocklyGames.loadFromLocalStorage = function(name, level) {
var xml;
try {
xml = window.localStorage[name + level];
} catch (e) {
// Firefox sometimes throws a SecurityError when accessing localStorage.
// Restarting Firefox fixes this, so it looks like a bug.
}
return xml;
};
国际化语言
BlocklyGames.getMsgOrNull = function(key) {
var element = document.getElementById(key);
if (element) {
var text = element.textContent;
text = text.replace(/\\n/g, '\n');
return text;
} else {
return null;
}
};
BlocklyInterface
工作空间
BlocklyInterface.workspace = null;
文本编辑器(可供修改xml)
BlocklyInterface.editor = null;
积木编辑器是否禁用
BlocklyInterface.blocksDisabled = false;
从浏览器缓存中获取到的xml代码,根据游戏等级转换成积木脚本;
BlocklyInterface.loadBlocks = function(defaultXml, inherit)
设置或获取文本xml和js脚本
BlocklyInterface.setCode = function(code)
BlocklyInterface.getCode = function()
获取JS代码
BlocklyInterface.getJsCode = function()
创建工作空间
BlocklyInterface.injectBlockly = function(options)
BlocklyInterface.injectBlockly = function(options) {
var toolbox = document.getElementById('toolbox');
if (toolbox) {
options['toolbox'] = toolbox;
}
options['media'] = 'third-party/blockly/media/';
options['oneBasedIndex'] = false;
BlocklyInterface.workspace = Blockly.inject('blockly', options);
BlocklyInterface.workspace.addChangeListener(BlocklyInterface.codeChanged);
};
保存浏览器缓存
BlocklyInterface.saveToLocalStorage = function()
BlocklyInterface.saveToSessionStorage = function()
执行代码,积木高亮显示
BlocklyInterface.highlight = function(id, opt_state)
代码执行器和代码美化器
BlocklyInterface.importInterpreter = function()
BlocklyInterface.importPrettify = function()
特殊积木定义
Blockly Game将很多积木重写了,但是总体来说没有太多变化。对for循环,标准积木中没有,下面进行说明。
Blockly.Blocks['controls_for'].init = function() {
//通常%1 %3 %5是一个变量
this.jsonInit({
"message0": "for (var %1 = %2; %3 < %4; %5 += 1) { %6 %7 }",
"args0": [
{
"type": "field_variable",
"name": "VAR",
"variable": null
},
{
"type": "input_value",
"name": "FROM",
"check": "Number",
"align": "RIGHT"
},
{
"type": "field_label",
"name": "VAR1",
"text": '?'
},
{
"type": "input_value",
"name": "TO",
"check": "Number",
"align": "RIGHT"
},
{
"type": "field_label",
"name": "VAR2",
"text": "?"
},
{
"type": "input_dummy"
},
{
"type": "input_statement",
"name": "DO"
}
],
"inputsInline": true,
"previousStatement": null,
"nextStatement": null,
"colour": Blockly.Msg['LOOPS_HUE'],
"helpUrl": Blockly.Msg['CONTROLS_FOR_HELPURL']
});
var thisBlock = this;
this.setTooltip(function() {
return Blockly.Msg['CONTROLS_FOR_TOOLTIP'].replace('%1',
thisBlock.getFieldValue('VAR'));
});
};
//积木变化时,设置%1 %2 %3设置为%1的值
Blockly.Blocks['controls_for'].onchange = function(e) {
var varName = this.getField('VAR').getText();
this.setFieldValue(varName, 'VAR1');
this.setFieldValue(varName, 'VAR2');
};
//controls_for生成js代码,首先获得变量名,然后获得 FROM TO DO相应代码,最后将代码组合为for循环代码
Blockly.JavaScript['controls_for'] = function(block) {
var variable = Blockly.JavaScript.variableDB_.getName(
block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
var from = Blockly.JavaScript.valueToCode(block, 'FROM',
Blockly.JavaScript.ORDER_ASSIGNMENT) || '0';
var to = Blockly.JavaScript.valueToCode(block, 'TO',
Blockly.JavaScript.ORDER_ASSIGNMENT) || '0';
var branch = Blockly.JavaScript.statementToCode(block, 'DO');
branch = Blockly.JavaScript.addLoopTrap(branch, block.id);
var code = 'for (var ' + variable + ' = ' + from + '; ' +
variable + ' < ' + to + '; ' +
variable + ' += 1) {\n' +
branch + '}\n';
return code;
};
网友评论