专业编程基础技术教程

网站首页 > 基础教程 正文

Blockly Game之迷宫(迷宫游戏:解谜攻略)

ccvgpt 2024-08-01 11:32:52 基础教程 28 ℃

游戏介绍

迷宫游戏总共有10个关卡,随着关卡等级的提高,积木会变多,难度也有相应的增加。游戏目的:了解方向积木、循环积木、以及判断积木的使用;游戏等级:1-10级;运行程序:单机可以执行积木脚本,积木脚本将控制企鹅运动,直到脚本执行完成或找到地图图标标志;方向积木:向左转、向右转;循环积木:重复执行直到,for或while循环;判断积木:如果前方可以通行,if or ifelse;

分析实现

积木定义

旋转方向积木

Blockly Game之迷宫(迷宫游戏:解谜攻略)

Blockly.Blocks['maze_turn'] = {
  init: function() {
  //控制积木左转、右转
    var DIRECTIONS =
        [[BlocklyGames.getMsg('Maze_turnLeft'), 'turnLeft'],
         [BlocklyGames.getMsg('Maze_turnRight'), 'turnRight']];
    // Append arrows to direction messages.
    DIRECTIONS[0][0] += Maze.Blocks.LEFT_TURN;
    DIRECTIONS[1][0] += Maze.Blocks.RIGHT_TURN;
    this.setColour(Maze.Blocks.MOVEMENT_HUE);
     //添加元素下拉列表
    this.appendDummyInput()
        .appendField(new Blockly.FieldDropdown(DIRECTIONS), 'DIR');
    this.setPreviousStatement(true);
    this.setNextStatement(true);
    this.setTooltip(BlocklyGames.getMsg('Maze_turnTooltip'));
  }
};

Blockly.JavaScript['maze_turn'] = function(block) {
  // 获得下拉列表值
  var dir = block.getFieldValue('DIR');
  return dir + '(\'block_id_' + block.id + '\');\n';
};

循环积木

Blockly.Blocks['maze_forever'] = {
  init: function() {
    this.setColour(Maze.Blocks.LOOPS_HUE);
    //添加图标
    this.appendDummyInput()
        .appendField(BlocklyGames.getMsg('Maze_repeatUntil'))
        .appendField(new Blockly.FieldImage(Maze.SKIN.marker, 12, 16));
        //添加执行语句
    this.appendStatementInput('DO')
        .appendField(BlocklyGames.getMsg('Maze_doCode'));
    this.setPreviousStatement(true);
this.setTooltip(BlocklyGames.getMsg('Maze_whileTooltip'));
  }
};

Blockly.JavaScript['maze_forever'] = function(block) {
  // Generate JavaScript for repeat loop.
  var branch = Blockly.JavaScript.statementToCode(block, 'DO');
  if (Blockly.JavaScript.INFINITE_LOOP_TRAP) {
    branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,
        '\'block_id_' + block.id + '\'') + branch;
  }
  //循环执行branch直到碰到地图图标
  return 'while (notDone()) {\n' + branch + '}\n';
};

判断积木

Blockly.Blocks['maze_if'] = {
 //判断积木是否可以前进、左转、右转
  init: function() {
    var DIRECTIONS =
        [[BlocklyGames.getMsg('Maze_pathAhead'), 'isPathForward'],
         [BlocklyGames.getMsg('Maze_pathLeft'), 'isPathLeft'],
         [BlocklyGames.getMsg('Maze_pathRight'), 'isPathRight']];
    // Append arrows to direction messages.
    DIRECTIONS[1][0] += Maze.Blocks.LEFT_TURN;
    DIRECTIONS[2][0] += Maze.Blocks.RIGHT_TURN;
    this.setColour(Maze.Blocks.LOGIC_HUE);
    //添加元素下拉列表
    this.appendDummyInput()
        .appendField(new Blockly.FieldDropdown(DIRECTIONS), 'DIR');
        //判断执行代码
    this.appendStatementInput('DO')
        .appendField(BlocklyGames.getMsg('Maze_doCode'));
    this.setTooltip(BlocklyGames.getMsg('Maze_ifTooltip'));
    this.setPreviousStatement(true);
    this.setNextStatement(true);
  }
};

Blockly.JavaScript['maze_if'] = function(block) {
  // 获取下拉列表if中的条件代码
  var argument = block.getFieldValue('DIR') +
      '(\'block_id_' + block.id + '\')';
  var branch = Blockly.JavaScript.statementToCode(block, 'DO');
  var code = 'if (' + argument + ') {\n' + branch + '}\n';
  return code;
};

迷宫生成

企鹅迷宫对象:Maze.map,随着等级的变化map中的路线图也会变化地图图标位置:Maze.finish[y, x],用于判断企鹅是否到达finsih点企鹅当前位置:[pegmanY, pegmanX]企鹅方向:NORTH: 0:[pegmanY-1, pegmanX],EAST: 1:[pegmanY, pegmanX+1],SOUTH: 2:[pegmanY+1, pegmanX],WEST: 3:[pegmanY-1, pegmanX+1]

  // 添加地图图标
  var finishMarker = Blockly.utils.dom.createSvgElement('image', {
      'id': 'finish',
      'height': 34,
      'width': 20
    }, svg);
  finishMarker.setAttributeNS(Blockly.utils.dom.XLINK_NS, 'xlink:href',
      Maze.SKIN.marker);
// 添加企鹅图标
  var pegmanIcon = Blockly.utils.dom.createSvgElement('image', {
      'id': 'pegman',
      'height': Maze.PEGMAN_HEIGHT,
      'width': Maze.PEGMAN_WIDTH * 21, // 49 * 21 = 1029
      'clip-path': 'url(#pegmanClipPath)'
    }, svg);
  pegmanIcon.setAttributeNS(Blockly.utils.dom.XLINK_NS, 'xlink:href',
      Maze.SKIN.sprite);

积木执行

企鹅移动企鹅移动对象为[command, id],comand为东南西北四个方向,id为积木的id。

Maze.move = function(direction, id) {
//判断企鹅某个方向是否可以移动
  if (!Maze.isPath(direction, null)) {
    Maze.log.push(['fail_' + (direction ? 'backward' : 'forward'), id]);
    throw false;
  }
  var effectiveDirection = Maze.pegmanD + direction;
  var command;
  //构造企鹅移动方向对象
  switch (Maze.constrainDirection4(effectiveDirection)) {
    case Maze.DirectionType.NORTH:
      Maze.pegmanY--;
      command = 'north';
      break;
    case Maze.DirectionType.EAST:
      Maze.pegmanX++;
      command = 'east';
      break;
    case Maze.DirectionType.SOUTH:
      Maze.pegmanY++;
      command = 'south';
      break;
    case Maze.DirectionType.WEST:
      Maze.pegmanX--;
      command = 'west';
      break;
  }
  Maze.log.push([command, id]);
};

企鹅转动方向

Maze.turn = function(direction, id) {
  if (direction) {
    // Right turn (clockwise).
    Maze.pegmanD++;
    Maze.log.push(['right', id]);
  } else {
    // Left turn (counterclockwise).
    Maze.pegmanD--;
    Maze.log.push(['left', id]);
  }
  Maze.pegmanD = Maze.constrainDirection4(Maze.pegmanD);
};

企鹅某个方向是否可移动

Maze.isPath = function(direction, id) {
  var effectiveDirection = Maze.pegmanD + direction;
  var square;
  var command;
  switch (Maze.constrainDirection4(effectiveDirection)) {
    case Maze.DirectionType.NORTH:
      square = Maze.map[Maze.pegmanY - 1] &&
          Maze.map[Maze.pegmanY - 1][Maze.pegmanX];
      command = 'look_north';
      break;
    case Maze.DirectionType.EAST:
      square = Maze.map[Maze.pegmanY][Maze.pegmanX + 1];
      command = 'look_east';
      break;
    case Maze.DirectionType.SOUTH:
      square = Maze.map[Maze.pegmanY + 1] &&
          Maze.map[Maze.pegmanY + 1][Maze.pegmanX];
      command = 'look_south';
      break;
    case Maze.DirectionType.WEST:
      square = Maze.map[Maze.pegmanY][Maze.pegmanX - 1];
      command = 'look_west';
      break;
  }
  if (id) {
    Maze.log.push([command, id]);
  }
  return square !== Maze.SquareType.WALL && square !== undefined;
};

脚本执行回调

Maze.initInterpreter = function(interpreter, scope) {
  var wrapper;
  moveForward = function(id) {
    Maze.move(0, id);//前进
  };
  moveBackward = function(id) {
    Maze.move(2, id);//后退
  };
  turnLeft = function(id) {
    Maze.turn(0, id);//左转
  };
  turnRight = function(id) {
    Maze.turn(1, id);//右转
  };
  isPathForward = function(id) {
    return Maze.isPath(0, id);//是否可前进
  };
  isPathRight = function(id) {
    return Maze.isPath(1, id);
  };
  isPathBackward = function(id) {
    return Maze.isPath(2, id);
  };
  isPathLeft = function(id) {
    return Maze.isPath(3, id);
  };
  notDone = function() {//游戏是否结束
    return Maze.notDone();
  };
};

其他

迷宫游戏某个等级,脚本区只能使用固定数量的积木,此函数提示脚本区剩余积木数量。

Maze.updateCapacity = function() {
  var cap = BlocklyInterface.workspace.remainingCapacity();
  var p = document.getElementById('capacity');
  if (cap == Infinity) {
    p.style.display = 'none';
  } else {
    p.style.display = 'inline';
    p.innerHTML = '';
    cap = Number(cap);
    var capSpan = document.createElement('span');
    capSpan.className = 'capacityNumber';
    capSpan.appendChild(document.createTextNode(cap));
    if (cap == 0) {
      var msg = BlocklyGames.getMsg('Maze_capacity0');
    } else if (cap == 1) {
      var msg = BlocklyGames.getMsg('Maze_capacity1');
    } else {
      var msg = BlocklyGames.getMsg('Maze_capacity2');
    }
    var parts = msg.split(/%\d/);
    for (var i = 0; i < parts.length; i++) {
      p.appendChild(document.createTextNode(parts[i]));
      if (i != parts.length - 1) {
        p.appendChild(capSpan.cloneNode(true));
      }
    }
  }
};

Tags:

最近发表
标签列表