轻轻松松学习JavaScript

JavaScript 的历史虽短,但却发展迅速。最初NetScape开发了LiveScript语言,使得它的Navigator和Web 服务器产品有了基本的脚本编写功能。当 Navigator 2.0中加入了Java小程序后,NetScape才把LiveScript变成了JavaScript,至此JavaScript诞生。

本文将以一个有趣的小程序为开端,介绍JavaScript的基本语法与功能。此趣味程序为小球碰撞仿真程序,它可仿真弹性碰撞和动能有损的不完全恢复碰撞。你若想了解此例程中的球间碰撞处理程序,需熟悉矢量的坐标旋转和一些基本的物理学知识。如果你对此一窍不通,也没什么关系,因为对于小球之间的碰撞程序仅为几个函数,你只管调用就是了,这并不影响我们对JavaScript 的学习。之所以要写这样一个带点旁门左道的趣味例程,只是希望你对JavaScript多增加一分兴趣。

废话就不多说,现在开始吧。

第一步:材料的准备

制作两张小球图片,红球 、蓝球 各一张。图片格式为 GIF。你可先用3D软件制作出立体球图片,然后再将其转为GIF格式,这样程序动画会显得更加逼真。需注意的是图片背景一定要透明,不然就会让人看出破绽。最后还需一张背景图,图片格式同上。

第二步:编写主页骨架

1. 在NetObject ScriptBuilder 中用New 命令生成一个HTML文件的骨架。顺便在新生成的HTML文件中,将TITLE标志之间的文字改为"小球碰撞仿真演示程序"。

2. 加入背景图案和小球图片资源。  
将BODY标志改为,此语句中的background 属性指定window.gif 为背景图案。

为加载小球图片资源,在标志与间添加以下两句

这两句HTML脚本的含义完全相同,标志IMG用于加入图片资源,其中SRC属性指明加入的图片文件名。ID属性指出图片的对象名称,这是个重要属性,因为以后在JavaScript 编程中要使用它。如第一句中,指明BallBlue为图片资源的对象名称(你可以把它想象成变量名)。STYLE属性指明图片在浏览器中的风格,其中"position" 开关设为"absolute",这样图片在窗口中的定位就可使用绝对坐标模式,而非文本行模式。

HTML 部分的编写到此完成。接下来该用JavaScript 让图片动起来了。

第三步:编写JavaScript 程序

1.仿真程序使用窗口对象的SetTimeout()方法循环调用Move_Step()函数,达到移动图片的目的,而Move_Step()根据速度矢量来计算移动一步的长度和方向。碰撞处理分为两部分,第一是球对墙壁的碰撞处理,其处理函数为Ball_Crash_Wall(),第二是球体之间的碰撞处理,其处理函数为Ball_Crash_Ball()。还需设置一些碰撞标志变量,记录当前碰撞状态,以避免仿真误差带来的错误,也许现在你还不明白为什么误差会导致错误,不要紧,后面会慢慢告诉你。

2.图片对象使用属性 style.pixelLeft、style.pixelTop 指定图片在窗口上的位  
置,这两个属性是图片运动的关键。不过在计算图片移动位置时并不用它,而是用数组变量BallCoord 记录图片当前坐标位置,因为属性 style.pixelLeft、style.pixelTop 是整型变量,而在计算碰撞中有小数生成,这样如果直接用 style.pixelLeft、style.pixelTop 记录位置,除了有误差,最重要的是在窗口边缘发生某些类型的球间碰撞时,会产生小球被撞出屏幕的错误。而数组变量可为浮点型,用于存放小数,从而避免了错误的发生。

(一)变量定义与程序的初始化

JavaScript 语句可放在HTML文件的主体(BODY区)中或文件头(HEAD区)中,区别是HEAD 区一般摆放预制好的函数和全局变量,以供BODY区的语句调用,而BODY区一般放入程序初始语句。JavsScript 的变量定义比较自由,但仍需满足先定义后使用的基本规则。

1.在HEAD区中定义全局变量:  
Window_Top = 22 //窗口顶端位置。  
Window_Left = 22 //窗口左端位置。  
Window_Bottom = 294 //窗口底端位置。  
Window_Right = 590 //窗口右端位置。  
Setp_Proportion = 3.00 //速度放大比率。

BallCoord = new Array(new Array(2),new Array(2)) //定义一个二维数组,用于记录两球的当前坐标。

BallDiametre = new Array(66,92) //定义一维数组,存放两球的直径,其值分别为66和92。

BallMoveVector = new Array(new Array(2,1),new Array(1,-2))//定义一个二维数组,用于记录两球的速度向量,第二维分别存放X与Y轴的速度。

CrashingWall = new Array(new Array(false,false,false,false),new Array(false,false,false,false))//数组 CrashingWall 用于避免墙壁碰撞的二次计算,值为 true ,表明当前处于碰撞状态。初值为 false。

2.在BODY区中完成程序的初始工作。其内容如下:

这里你已经看见了一个JavaScript 程序的框架。标志SCRIPT 告诉浏览器,下面的内容为脚本程序,用LANGUAGE="JavaScript" 指明程序语言为JavaScript。不管是在BODY区,还是HEAD区中,任何JavaScript程序必须放在 标志之间。程序中用 new Array() 定义了一个数组Balls,以便以后存放图片对象。接下来的语句Balls[0] = BallBlue 将图片对象BallBlue 赋给Balls[0],如果你细心,你会发现BallBlue正是加载图片资源语句中指定的对象名。语句Balls[0].style.pixelTop = BallCoord[0][0] = 100,同时将值100赋给数组变量BallCoord[0][0]和图片对象的style.pixelTop属性。从而坐标数组变量BallCoord[0][0]得到了初值并且指定了球1的初始顶端位置。其余语句的含义雷同。最后一句调用函数Move_Step()将小球移动一步。

(二) 单步移动函数Move_Step()讲解

在HTML文件的HEAD区中编写Move_Step() 函数其内容如下:  
function Move_Step() {  
Ball_Crash_Ball() //调用球间碰状处理函数

Balls_Crash_Wall(0) //调用蓝球碰墙处理函数  
Balls_Crash_Wall(1) //调用红球碰墙处理函数

//计算移动步长  
BallCoord[0][0] += BallMoveVector[0][0] * Setp_Proportion  
BallCoord[0][1] += BallMoveVector[0][1] * Setp_Proportion  
BallCoord[1][0] += BallMoveVector[1][0] * Setp_Proportion  
BallCoord[1][1] += BallMoveVector[1][1] * Setp_Proportion  
//移动一步  
Balls[0].style.pixelTop = BallCoord[0][0]  
Balls[0].style.pixelLeft = BallCoord[0][1]  
Balls[1].style.pixelTop = BallCoord[1][0]  
Balls[1].style.pixelLeft = BallCoord[1][1]  
window.setTimeout("Move_Step()",100) //100毫秒后再次调用Move_Step()函数  
}  
该函数的大部分含义,你可看其中的注释,这里只对几点加以说明。

1在语句BallCoord[0][0] += BallMoveVector[0][0] * Setp_Proportion中, BallMoveVector数组存放着速度向量。Setp_Proportion 变量存放步长放大比率,BallMoveVector[0][0] 乘以Setp_Proportion 得到移动一步的长度。最后该语句加上BallCoord[0][0]原值后再赋给BallCoord[0][0]本身,得到移动位置。

2.语句window.setTimeout("Move_Step()",100) 表示100毫秒后再次调用Move_Step()函数。现在有了setTimeout()方法,程序就不断的循环起来了。

Ball_Crash_Ball()是小球之间的碰撞处理函数, 你只管调用就是了,如果你不使用它,程序一样能运行,只是少了处理球间碰撞的功能。(在Ball_Crash_Ball()函数中调用了函数CrashEnd_Speed() 与atan360(x,y),以及使用了全局变量CrashingBalls,因而要正确使用它,必须将以上所说的函数与变量都拷入你的程序中)

(三) 在HEAD区中编写墙壁碰撞处理函数Balls_Crash_Wall()

一个简化的函数如下:

function Balls_Crash_Wall(i) {

if( BallCoord[i][0] <= Window_Top)  
BallMoveVector[i][0] = - BallMoveVector[i][0]

if ( BallCoord[i][1] <= Window_Left)  
BallMoveVector[i][1] = - BallMoveVector[i][1]

if ( BallCoord[i][0] + BallDiametre[i] >= Window_Bottom)  
BallMoveVector[i][0] = - BallMoveVector[i][0]

if ( BallCoord[i][1] + BallDiametre[i] >= Window_Right)  
BallMoveVector[i][1] = - BallMoveVector[i][1]

}

函数首先判断是否球已经碰到了墙壁,如是就将相应方向上的速度方向反向,而大小不变。但这个函数有可能发生错误(错误发生的原因有些复杂,这里只梢作提示。由于小球移动的步长往往大于1个点,而仿真又是离散进行的,从而在有些情况下会发生错误)。需用数组变量CrashingWall 来标识碰撞状态,使得小球与墙壁处于碰撞状态时不能再发生第二次小球与墙壁的碰撞,相应的语句也要更改,如第一句改为

if( BallCoord[i][0] <= Window_Top)  
{ if (!CrashingWall[i][0]) { BallMoveVector[i][0] = - BallMoveVector[i][0] }  
CrashingWall[i][0] = true  
} else CrashingWall[i][0] = false

语句中CrahingWall数组的类型为逻辑型,记录球与墙壁是否正在发生碰撞。当为碰撞状态时,就不必再将球的运动方向反向。

到此程序的编写基本完成,其它详细内容见光盘的原程序及说明。现在在NetObject ScriptBuilder 中选择菜单Preview 项,运行程序。

附注:  
1. 运行本例程需先安装IE4.0以上浏览器 或Netscape Navigator 4.0以上浏览器

2. 球间碰撞处理提示:当两球发生碰撞时,计算两球圆心连线与X轴的夹角。在依据此夹角对坐标进行旋转。将原速度矢量映射到旋转后的坐标中。从而将球间的任意碰撞转变为正对心碰撞。用冲量定理可推出碰后的速度计算公式。然后再将坐标旋转成原始坐标。可得碰撞后的速度矢量。看了上面的文字是不是有些烦人,其实并非如此,程序中只用了11行语句就完成了全部计算。

(0)

相关推荐

  • 学习JavaScript的最佳方法分享

    学习新的东西是件可怕的事.对我来说,掌握一项新技能最大的问题是,我不知道自己懂什么.鉴于此,定个计划,学习你感兴趣的东西应该会有用.这篇文章的主旨就是:你为学习JavaScript 制定的蓝图.路线.行动计划!你不必担心找不到最好的资源,先整理些不好的资源,再确定下一步该学什么.遵循它,一步一步来. 任务0:了解什么是JavaScript 在你真正开始学习JavaScript 之前,花一分钟了解一下什么是JavaScript,它有哪些功能. JavaScript不是jQuery.Flash或Ja

  • 实例学习Javascript之构建方法、属性

    function crea(){ var obj = new CTagPages("maintag"); obj.add(new CTag("files","文件","content1"));//创建一个文档中不存在的内容页 obj.add(new CTag("edits","编辑","content2")); obj.add(new CTag("windo

  • 写给想学习Javascript的朋友一点学习经验小结

    当然只是个人的经验,有什么不对的也请高手见谅和指正. 关于到培训学校学习的忠告:别说现在没有这样的学校,就是有专门的学校也不要去,因为不会有好的老师的.不要浪费你自己(很可能是你父母)的钱和时间.趁早死了这个念头. 关于培训学校的这个我想我要比一般的朋友更有发言权,因为我本人干英语培训将近2年,我很清楚培训市场的情况,你很难碰到一个好的老师.英语可能还好些,毕竟英语说得好的老师还比较多,长期跟老外泡在一起,确实对口语能力的提高很显著,但是代价是很昂贵的.而你现在要学的是Javascript,呵呵

  • 向大师们学习Javascript(视频与PPT)

    Douglas Crockford:Douglas Crockford是JavaScript开发社区最知名的权威,是JSON.JSLint.JSMin和ADSafe之父,是<JavaScript:The Good Parts>(英文版.中文版)的作者.JavaScript的发明人Brendan Eich说他是"Yoda of lambda programming and JavaScript(lambda编程和JavaScript的精神领袖)".他同时也服务于ECMA的Ja

  • 学习javascript,实现插入排序实现代码

    插入排序 插入排序是这样实现的: 首先新建一个空列表,用于保存已排序的有序数列(我们称之为"有序列表"). 从原数列中取出一个数,将其插入"有序列表"中,使其仍旧保持有序状态. 重复2号步骤,直至原数列为空. 插入排序的平均时间复杂度为平方级的,效率不高,但是容易实现.它借助了"逐步扩大成果"的思想,使有序列表的长度逐渐增加,直至其长度等于原列表的长度. (引自百度百科) javascript代码 复制代码 代码如下: <script ty

  • 从面试题学习Javascript 面向对象(创建对象)

    题目: 复制代码 代码如下: try{ var me = Man({ fullname: "小红" }); var she = new Man({ fullname: "小红" }); console.group(); console.info("我的名字是:" + me.attr("fullname") + "\n我的性别是:" + me.attr("gender")); consol

  • 如何学习Javascript入门指导

    谈不上经验,都是一些教训. 这个时候有人要说,"靠,你丫半桶水,凭啥教我们".您先别急着骂,先听我说. 你叫一个大学生去教小学数学,不见得比一个初中生教得好.因为大学生早已经过了那个阶段,都忘记自己怎么走过来的了.而对于初中生,刚好走过那个阶段,对自己怎么走过来的还记忆犹新,或者还有一些自己的总结.比如,很多高手觉得那本犀牛书入门很好,他们觉得太简单了,但以我的经验来看,它不是入门的最好选择. 先说说学js的条件 论条件,咱是文科生,大学专业工商管理,和计算机毛关系都没:有人说英语,读

  • 菜鸟学习JavaScript小实验之函数引用

    复制代码 代码如下: function tt() { alert(11); } var b = tt; var b1 = tt(); //执行tt()函数功能 对于函数的引用,可直接将函数名"tt"赋给变量,但不可以是函数名+括号的形式"tt()",因为第二种是直接执行该函数. 调用函数的时候,用变量名+括号的形式,如:b(). 复制代码 代码如下: function tt() { alert(11); } var b = tt; alert(b); functio

  • 轻轻松松学习JavaScript

    JavaScript 的历史虽短,但却发展迅速.最初NetScape开发了LiveScript语言,使得它的Navigator和Web 服务器产品有了基本的脚本编写功能.当 Navigator 2.0中加入了Java小程序后,NetScape才把LiveScript变成了JavaScript,至此JavaScript诞生. 本文将以一个有趣的小程序为开端,介绍JavaScript的基本语法与功能.此趣味程序为小球碰撞仿真程序,它可仿真弹性碰撞和动能有损的不完全恢复碰撞.你若想了解此例程中的球间碰

  • 学习JavaScript设计模式之中介者模式

    一.定义 面向对象设计鼓励将行为分布到各个对象中,把对象划分成更小的粒度,有助于增强对象的可复用性.但由于这些细粒度对象之间的联系激增,又可能反过来降低它们的可复用性. 中介者模式的作用就是解除对象与对象之间的紧耦合关系. 二.示例:购买商品 假设我们正在开发一个购买手机的页面,购买流程中,可以选择手机颜色以及输入购买数量,同时页面中可以对应展示输入内容.还有一个按钮动态显示下一步操作(该颜色库存量充足,显示下一步:否则显示库存不足). <div> <span>请选择颜色</

  • 学习JavaScript设计模式之观察者模式

    一.定义 观察者模式(发布-订阅模式):其定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. 在JavaScript中,一般使用事件模型来替代传统的观察者模式. 好处: (1)可广泛应用于异步编程中,是一种替代传递回调函数的方案. (2)可取代对象之间硬编码的通知机制,一个对象不用再显示地调用另外一个对象的某个接口.两对象轻松解耦. 二.DOM事件–观察者模式典例 需要监控用户点击document.body的动作,但是我们没有办法预知用户将在什么时间点击

  • 学习JavaScript设计模式之享元模式

    一.定义 享元(flyweight)模式是一种用于性能优化的模式,核心是运用共享技术来有效支持大量细刻度的对象. 在JavaScript中,浏览器特别是移动端的浏览器分配的内存并不算多,如何节省内存就成了一个非常有意义的事情. 享元模式是一种用时间换空间的优化模式 内衣工厂有100种男士内衣.100中女士内衣,要求给每种内衣拍照.如果不使用享元模式则需要200个塑料模特:使用享元模式,只需要男女各1个模特. 二.什么场景下使用享元模式? (1)程序中使用大量的相似对象,造成很大的内存开销 (2)

  • 每个程序员都需要学习 JavaScript 的7个理由小结

    最近在和招聘经理交流现在找一个好的程序员有多难的时候,我渐渐意识到了现在编程语言越来越倾重于JavaScript.Web开发人员尤其如此.所以,如果你是一个程序员,那么你应该去学习JavaScript. 需求 我之所以这样说的主要原因是,随着JavaScript的日渐成熟,以及Node.js方案变得越来越可行,我们对JavaScript程序员的需求正在持续增长. JavaScript在需求比例上已经超过了C#,仅屈居于Java之下.如果你看看GitHub上可行的项目,你会发现JavaScript

  • 学习JavaScript设计模式之装饰者模式

    有时我们不希望某个类天生就非常庞大,一次性包含许多职责.那么我们就可以使用装饰着模式. 装饰着模式可以动态地给某个对象添加一些额外的职责,从而不影响这个类中派生的其他对象. 装饰着模式将一个对象嵌入另一个对象之中,实际上相当于这个对象被另一个对象包装起来,形成一条包装链. 一.不改动原函数的情况下,给该函数添加些额外的功能 1. 保存原引用 window.onload = function() { console.log(1); }; var _onload = window.onload ||

  • 学习JavaScript设计模式之代理模式

    明星都有经纪人作为代理.如果请明星办一场商演,只能联系其经纪人,经纪人会把商演的细节和报酬谈好,再把合同交给明星签. 一.定义 代理模式:为一个对象提供一个代用品或占位符,以便控制对它的访问. 代理分为:保护代理和虚拟代理 保护代理:用于控制不同权限的对象对目标对象的访问,在JavaScript中很难判断谁访问了某个对象,所以保护代理很难实现. 二.图片预加载(最常见的虚拟代理应用场景) 图片预加载是一种常用技术,如果直接给某个img标签节点设置src属性,由于图片过大或者网络不佳,图片的位置往

随机推荐