当前位置: 首页 > news >正文

2017-12-05 JavaScript实现ZLOGO子集: 前进+转向

在前文中文编程语言之Z语言初尝试: ZLOGO 4与相关讨论后, 萌生了用JavaScript编写类似语言以便在线编程的想法. 于是使用 @TKT2016 (知乎账号)的ZLOGO语法设计, 在编程语言试验之Antlr4+JavaScript实现"圈4"基础上, 通过p5js的绘图功能, 实现了基本的两个ZLOGO功能. 如图(动态效果看起来更爽一点, 当然要耐心等它画完, 请自行尝试):
2017_12_05_star

源码库: program-in-chinese/quan3, 导出代码到本地后, 在浏览器中打开"圈3.html"即可在本地实践编程.

在线演示: 地址.

由于还不支持循环, 实现这个五角星的代码很重影:

开始
  前进200
  左转144度
  前进200
  左转144度
  前进200
  左转144度
  前进200
  左转144度
  前进200
结束

下面是编程语言试验之Antlr4+JavaScript实现"圈4"之后添加的主要部分:
语法文件(圈3.g4):

声明 : 前进 | 转向;

前进 : '前进' T数 ;

转向 :  T转向 '转' T数 '度' ;

T转向 : '左' | '右' ;

主要修改在"定制监听器.js":

命名还比较粗糙, 一些用语最好更加一致(比如"长度","距离","前进量"虽在不同上下文, 实际指的是一个东西), 需要改进. 当然算法肯定也可以改进, 暂时是实现功能优先.

var 常量_指令名_前进 = "前进";
var 常量_指令名_转向 = "转向";

var 序号 = 0;

var 画布尺寸 = {x: 1000, y: 800};
var 原点 = {x: 画布尺寸.x/2, y: 画布尺寸.y/2};
var 前进角度 = 90; // 默认向上, 对应弧度: 90 * Math.PI / 180
// 指令格式: 名称 (转向, 前进, 笔色等等); 参数 (转向角度--右为负,左为正; 前进长度-像素数等等);
var 指令序列 = [];

定制监听器.prototype.enter程序 = function(ctx) {
  重置状态();
  // 只需调用一次
  // https://p5js.org/reference/#/p5/setup
  构图 = function() {
    新画布(画布尺寸.x, 画布尺寸.y);
  }
};

function 重置状态() {
  序号 = 0;
  原点 = {x: 画布尺寸.x/2, y: 画布尺寸.y/2};
  前进角度 = 90;
  指令序列 = [];
}

// 根据指令序列, 生成路径分段描述(段起止点坐标, 颜色等等)
// 如: 前进50, 左转90度, 前进50 应返回(假设起点为{x: 200, y: 200}):
// {起点: {x: 200, y: 200}, 终点: {x: 200, y: 150}, 长度: 50},
// {起点: {x: 200, y: 150}, 终点: {x: 150, y: 150}, 长度: 50}
function 生成路径表(指令序列) {
  // 段: {起点: {x, y}, 终点: {x, y}, 长度, 颜色}
  var 路径表 = [];
  var 起点 = 原点;
  for(var i = 0; i < 指令序列.length; i++ ){
    var 指令 = 指令序列[i];
    var 指令名 = 指令.名称;
    var 段 = {起点: 起点};
    if (指令名 === 常量_指令名_前进) {
      var 距离 = 指令.参数;
      var x增量 = Math.cos(前进角度 * Math.PI / 180);
      var y增量 = Math.sin(前进角度 * Math.PI / 180);
      段.终点 = {x: 起点.x + x增量 * 距离, y: 起点.y - y增量 * 距离};
      段.长度 = 距离;
      路径表.push(段);

      起点 = 段.终点;
    } else if (指令名 === 常量_指令名_转向) {
      前进角度 += 指令.参数;
    }
  }
  return 路径表;
}

定制监听器.prototype.exit程序 = function(ctx) {
  var 路径表 = 生成路径表(指令序列);
  绘制 = function() {
    var 当前序号 = 序号;
    background(255, 255, 255);

    for (var i = 0; i < 路径表.length; i++ ) {
      var 段 = 路径表[i];
      var 起点 = 段.起点;
      var 终点 = 段.终点;
      var 距离 = 段.长度;
      if (当前序号 < 距离) {
        line(起点.x, 起点.y, 起点.x + (终点.x - 起点.x) * 当前序号 / 距离, 起点.y + (终点.y - 起点.y) * 当前序号 / 距离);
        break;
      } else {
        line(起点.x, 起点.y, 终点.x, 终点.y);
        当前序号 = 当前序号 - 段.长度;
      }
    }
    
    序号 ++;
  }
};

定制监听器.prototype.exit前进 = function(上下文) {
  var 前进量 = 上下文.getChild(1).getText()
  指令序列.push({名称: 常量_指令名_前进, 参数: parseInt(前进量)});
};

定制监听器.prototype.exit转向 = function(上下文) {
  var 方向 = 上下文.getChild(0).getText();
  var 角度 = parseInt(上下文.getChild(2).getText());

  角度 = 角度 * (方向 === "左" ? 1 : -1);
  指令序列.push({名称: 常量_指令名_转向, 参数: 角度});
};

相关文章:

  • 阿里云性能测试 PTS 上手体验
  • FastDfs 分布式文件系统 安装与配置 (实测成功)
  • 读JVM(深入理解Java虚拟机)笔记(一)
  • Vue之坑
  • flask 第七章 简陋版智能玩具 +MongoDB初识和基本操作
  • 4-1 requests库的安装
  • 学起来:Flutter将支持桌面应用开发
  • 基于binlog方式搭建MySQL主从
  • C# 虹软SDK视频人脸识别和注册
  • redis-主从复制
  • 再见 异步回调, 再见 Async Await, 10 万 个 协程 的 时代 来 了
  • 007《loom》 Chrome翻录网页视频神器
  • 03python面向对象编程1
  • 前端知识杂锦(二)
  • 大传媒时代报业如何驾驭新媒体
  • python3.6+scrapy+mysql 爬虫实战
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • [译]如何构建服务器端web组件,为何要构建?
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • 【Amaple教程】5. 插件
  • JS字符串转数字方法总结
  • mysql 数据库四种事务隔离级别
  • SpiderData 2019年2月16日 DApp数据排行榜
  • spring cloud gateway 源码解析(4)跨域问题处理
  • 从tcpdump抓包看TCP/IP协议
  • 浮现式设计
  • 基于MaxCompute打造轻盈的人人车移动端数据平台
  • 前嗅ForeSpider采集配置界面介绍
  • 设计模式走一遍---观察者模式
  • 云大使推广中的常见热门问题
  • 【云吞铺子】性能抖动剖析(二)
  • 7行Python代码的人脸识别
  • 阿里云移动端播放器高级功能介绍
  • 交换综合实验一
  • 数据库巡检项
  • 选择阿里云数据库HBase版十大理由
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • # Swust 12th acm 邀请赛# [ E ] 01 String [题解]
  • #### go map 底层结构 ####
  • #每日一题合集#牛客JZ23-JZ33
  • (2)MFC+openGL单文档框架glFrame
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (八)c52学习之旅-中断实验
  • (四)【Jmeter】 JMeter的界面布局与组件概述
  • (四)库存超卖案例实战——优化redis分布式锁
  • (算法二)滑动窗口
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (一)UDP基本编程步骤
  • (一)WLAN定义和基本架构转
  • (一)硬件制作--从零开始自制linux掌上电脑(F1C200S) <嵌入式项目>
  • (转)Scala的“=”符号简介