轻轻松松学习JavaScript


Posted in Javascript onFebruary 25, 2007

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行语句就完成了全部计算。

Javascript 相关文章推荐
YUI 读码日记之 YAHOO.util.Dom - Part.1
Mar 22 Javascript
js直接编辑当前cookie的脚本
Sep 14 Javascript
JavaScript使用concat连接数组的方法
Apr 06 Javascript
AngularJS 工作原理详解
Aug 18 Javascript
基于JS实现二维码图片固定在右下角某处并跟随滚动条滚动
Feb 08 Javascript
Ajax实现不刷新取最新商品
Mar 01 Javascript
vue动态组件实现选项卡切换效果
Mar 08 Javascript
laydate 显示结束时间不小于开始时间的实例
Aug 11 Javascript
使用vue实现grid-layout功能实例代码
Jan 05 Javascript
vue elementui el-form rules动态验证的实例代码详解
May 23 Javascript
搭建一个Koa后端项目脚手架的方法步骤
May 30 Javascript
ElementUI Tag组件实现多标签生成的方法示例
Jul 08 Javascript
用javascript编写的第一人称射击游戏
Feb 25 #Javascript
极酷的javascirpt,让你随意编辑任何网页
Feb 25 #Javascript
你真的了解JavaScript吗?
Feb 24 #Javascript
SUN的《AJAX与J2EE》全文译了
Feb 23 #Javascript
js玩一玩WSH吧
Feb 23 #Javascript
用Javascript做flash做的事..才完成的一个类.Auntion Action var 0.1
Feb 23 #Javascript
javascript知识点收藏
Feb 22 #Javascript
You might like
打造计数器DIY三步曲(上)
2006/10/09 PHP
解析PHP汉字转换拼音的类
2013/06/18 PHP
PHP中加速、缓存扩展的区别和作用详解(eAccelerator、memcached、xcache、APC )
2016/07/09 PHP
laravel实现批量更新多条记录的方法示例
2017/10/22 PHP
Laravel如何使用Redis共享Session
2018/02/23 PHP
php命名空间设计思想、用法与缺点分析
2019/07/17 PHP
深入学习微信网址链接解封的防封原理visit_type
2019/08/15 PHP
同一个表单 根据要求递交到不同页面的实现方法小结
2009/08/05 Javascript
Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结
2013/11/14 Javascript
js控制input输入字符解析
2013/12/27 Javascript
JQuery删除DOM节点的方法
2015/06/11 Javascript
jQuery基础知识点总结(必看)
2016/05/31 Javascript
bootstrap使用validate实现简单校验功能
2016/12/02 Javascript
ng2学习笔记之bootstrap中的component使用教程
2017/03/09 Javascript
详解Angular Forms中自定义ngModel绑定值的方式
2018/12/10 Javascript
[44:04]OG vs Mineski 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
Python3爬虫教程之利用Python实现发送天气预报邮件
2018/12/16 Python
Python-Seaborn热图绘制的实现方法
2019/07/15 Python
Python udp网络程序实现发送、接收数据功能示例
2019/12/09 Python
TensorFlow——Checkpoint为模型添加检查点的实例
2020/01/21 Python
利用django model save方法对未更改的字段依然进行了保存
2020/03/28 Python
Theory美国官网:后现代都市风时装品牌
2018/05/09 全球购物
玛蒂尔达简服装:Matilda Jane Clothing
2019/02/13 全球购物
如何用PHP实现邮件发送
2012/12/26 面试题
小学生检讨书大全
2014/02/06 职场文书
总经理岗位职责描述
2014/02/08 职场文书
大学生学年自我鉴定
2014/02/10 职场文书
户外拓展活动方案
2014/02/11 职场文书
大学生职业生涯规划书汇总
2014/03/20 职场文书
田径运动会开幕式及主持词
2014/03/28 职场文书
协议书样本
2014/04/23 职场文书
住房租房协议书
2014/08/20 职场文书
立志成才演讲稿
2014/09/04 职场文书
社区宣传标语口号
2015/12/26 职场文书
Vue.js 带下拉选项的输入框(Textbox with Dropdown)组件
2021/04/17 Vue.js
Python-OpenCV教程之图像的位运算详解
2021/06/21 Python