本文介绍一个基于HTA(HTML Application)和VML(Vector Markup Language)编写的经典打砖块游戏——HTAnoid。该游戏由Jean-Luc Antoine于2002年开发,无需任何外部图片即可实现图形界面,完全通过VML绘制砖块、挡板、球体等元素。对于想了解HTA应用开发、VML矢量图形以及VBScript事件驱动编程的开发者,这是一个完整可运行的参考案例。
- <html xmlns:v="urn:schemas-microsoft-com:vml" XMLNS:t="urn:schemas-microsoft-com:time">
- <head>
- <HTA:APPLICATION APPLICATIONNAME="HTAnoid" BORDER="thick" BORDERSTYLE="raised" CAPTION="yes" CONTEXTMENU="yes" ID="oHTA" alert(oHTA.applicationName); INNERBORDER="yes" MAXIMIZEBUTTON="yes" MINIMIZEBUTTON="yes" NAVIGABLE="no" SCROLL="no" SCROLLFLAT="no" SELECTION="yes" SHOWINTASKBAR="yes" SINGLEINSTANCE="no" SYSMENU="yes" VERSION="0.5" WINDOWSTATE="normal">
复制代码
一、HTA声明与窗口配置
上面的HTA声明设置了应用名称为"HTAnoid",边框风格为raised,显示标题栏,禁用导航和滚动,窗口不可调整大小。注意代码中有一段冗余的alert,原意是演示访问applicationName属性,实际运行时可以忽略或删除。窗口初始状态为normal,后续通过VBScript的Init过程重新定位和调整大小:窗口移动到屏幕中央(screen.Width/2-200,0),尺寸设为400×484像素。
二、样式与VML初始化
在<style>中定义了VML的行为(behavior:url(#default#VML)),同时设置body背景色为深蓝(#003159),表格和单元格边框为0像素闪避风格。VML元素(如<v:rect>、<v:oval>、<v:group>、<v:roundrect>)用于绘制游戏界面:
- 顶部渐变背景条
- 左右两侧装饰栏(使用虚线描边和渐变填充)
- 球体(id="balle",椭圆形,位置绝对定位)
- 挡板(id="Raquette",group中包含圆角矩形和渐变矩形)
三、游戏逻辑与VBScript实现
游戏核心代码位于VBScript中,定义常量、全局变量并实现子过程。
1. 常量与变量
- C_ScreenW = 400(屏幕宽度)
- C_NbX = 12,C_NbY = 10(砖块横向12列,纵向10行,但当前关卡仅生成6行)
- Terrain(10,12) 二维数组存储砖块剩余击打次数,初始为0
- RaqX, RaqW, BalleX, BalleY 表示挡板左坐标、宽度、球体坐标
- DirBX, DirBY 球移动方向和速度
- BordDroit = 368(屏幕宽减32,右侧边界)
2. Init过程(页面加载时触发)
- 移动窗口并调整大小
- 计算挡板实际宽度(RaqW = 挡板style.width值转换为像素,约48px,因为30pc=30*1.6=48,但原文使用Replace("pc","")再乘1.6,实际得到48)
- 绘制三条生命指示(使用VML group + roundrect + rect,红色外框、蓝色渐变填充)
- 调用DrawLevel(1)生成第一关砖块
- 设置Playing = False,然后通过setTimeout启动每10ms一次的Gere循环
3. DrawLevel(n)子过程
- 重置Terrain数组
- 根据关卡(目前只有case 1)生成6行砖块:使用insertAdjacentHTML在前面插入TABLE元素,每个砖块绝对定位,top从102开始,每行递增14px,left从16开始每列27px,宽度25px高度10px,颜色依次为silver(银)、red(红)、yellow(黄)、blue(蓝)、magenta(品红)、lightgreen(浅绿)
- 设置初始球坐标BalleY=400,随机方向DirBX(1~3),DirBY(-4~-1,向上)
4. Document_onMouseMove事件
- 鼠标移动时更新挡板位置:RaqX = 鼠标clientX - 挡板一半宽度
- 左边界limit为16,右边界limit为BordDroit - RaqW
- 更新Raquette.style.Left
- 如果Playing=False,球跟随挡板中心(BalleX = RaqX + RaqW/2)
5. Document_onKeyPress事件
- 按P键弹出"pause"提示(暂停功能未完全实现,仅示例)
6. Document_onClick事件
- 点击页面开始游戏:设置Playing = True
7. Gere子过程(游戏主循环)
- 每10ms调用一次,如果Playing=True,则:
- 根据DirBX, DirBY计算球的新位置
- 边界碰撞检测:左右边界(16和BordDroit-10)弹回;上下边界(50和400)弹回
- 更新球的位置(Balle.style.Left和Top)
- 如果Playing=False,则在标题栏显示当前时间(作为简单的屏幕刷新标志)
四、运行与扩展建议
将上述完整代码保存为.hta文件(如htanoid.hta),在Windows系统下双击即可运行(需IE6以上支持,Windows 10/11需启用IE兼容模式或使用旧版Edge的IE模式)。当前版本仅包含一关,球碰到底部时游戏并未结束(未实现生命减少与游戏结束逻辑),挡板与球的碰撞检测也未实现(球只会上下左右反弹,不会因挡板改变方向)。原作者鼓励开发者继续完善:
- 添加球与砖块的碰撞检测,当球碰到砖块时消除该砖块并更新分数
- 实现生命系统:球落到底部时减少一条生命,生命归零则游戏结束
- 增加关卡切换和多级砖块
- 完善暂停功能
- 优化图形:当前使用VML,在后续系统中可改用Canvas或SVG
五、技术影响与分析
HTA是微软在Windows中推出的桌面应用技术,允许用HTML+脚本创建具有系统权限的应用程序。本例展示了HTA与VML结合实现无外部资源二维游戏的能力。虽然HTA已逐渐被UWP和现代Web技术取代,但对于学习早期浏览器编程技巧、理解VML矢量绘制,以及研究如何利用DHTML构建互动应用仍有参考价值。VML的gradient和stroke等特性在当时提供了丰富的视觉效果,而insertAdjacentHTML方法动态创建元素也是一种高效方式。
注意:在现代浏览器中直接运行此代码可能无法显示VML图形,建议在IE兼容模式下测试。若需跨平台,可考虑将逻辑迁移至HTML5 Canvas或WebGL。
完整代码可参考原文链接或从本文代码片段组合得到。开发者可以基于此模板快速搭建自己的HTA小游戏。 |