65.9K
CodeProject 正在变化。 阅读更多。
Home

DeeHTML - 一个基于 Web 的平台游戏

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.80/5 (83投票s)

2006 年 8 月 30 日

5分钟阅读

viewsIcon

147586

downloadIcon

1906

一个仅使用 DHTML 的平台游戏

Sample Image - deehtml.gif

引言

作为一个教育性的练习,我创建了一个平台游戏。这是一个初学者式的马里奥式平台游戏,仅使用 JavaScript、CSS 和 HTML。它可以在 Internet Explorer 5+ 和 Firefox 上运行。游戏的主角是我们的英雄 Dee,他必须跳到敌人的头上并收集柠檬。收集 100 个柠檬可获得一条额外生命。一路上,他会遇到炮弹、移动的平台、水以及一只会把蛋丢到他头上的飞鸟。很逼真吧?这是我第一次尝试编写平台游戏。我当时正在使用 JavaScript 来移动屏幕上的表格,这时我想到了捕获用户键盘输入并允许他们使用 JavaScript 控制 HTML 表格的可能性。

开发

这个想法逐渐发展成让一个小图像响应键盘箭头键移动。然后我在屏幕上放置了一个 HTML 表格。每次键盘输入后,我都会检查图像是否在表格的边界框内,即它是否在 left & righttop & bottom 坐标之间。如果是,我就会停止移动,从而制造出碰撞的假象。我绘制了更多表格并将它们放置在屏幕上。然后,我给英雄图像添加了一些 expando 属性。这允许我添加官方 <IMG> 标签中没有的内容,但它对我的游戏很有用。例如,我的游戏英雄标签具有

<IMG SRC='hero.gif' id=hero width=10 height=10 ohdestspeed=3 
    destx=100 desty=999>

现在看 ohdestspeed,它是 <IMG> 标签的一个 expando 属性,允许我设置和改变玩家的速度。destx 是当你按下右箭头时玩家的目的地。使用 JavaScript,我将 destx 属性设置为玩家当前的 posLeft 加上 ohdestspeed(3 像素)。在 JavaScript 中

Onkeydown="if(event.keyCode==39){
    document.getElementById('hero').style.posLeft+= document.getElementById(
    'hero').ohdestspeed;}"

对于左箭头,我减去玩家的 posLeft 等。对于跳跃,我将 desty 设置为玩家的 posTop 并减去 60。这意味着他将开始向上移动 60 像素。当他到达那里时,我添加了代码让他落下。这会将 desty 属性设置为屏幕底部(screen.clientHeight)。当我后来添加水时,为了让玩家变慢,我只需将 ohdestspeed 改为 1。所以,他每次移动不再是 3 像素,而是只移动 1 像素。

万物皆需移植

让游戏在 Firefox 中运行需要一些更改,因为自定义的 expando 标签属性工作方式不同。取而代之的是,我将每个对象的自定义属性放在 title 标签中的一个逗号分隔列表中。这会在运行时读入一个数组,并且与之前一样工作。以前,我使用 document.all 来解析元素。然而,对于跨浏览器方法,我现在遍历 document.body.childNodes 集合,它在两个浏览器中都能很好地运行。IE 中的元素定位允许我使用 element.style.pixelLeft(和 pixelTop)并返回一个整数,快速方便。但在 Firefox 中,我必须使用 element.style.left(和 .top),它返回一个像“144 px”这样的字符串。可惜,我必须使用 parseInt() 函数,这使得数值处理慢了很多。

让它飞驰

对于移动对象,我使用 JavaScript 的 setTimeout 定时器创建了一个函数,该函数大约每毫秒运行一次。基本上,这个名为 u1() 的函数移动敌人,检查它们的 destxdesty 并设置它们的 posLeftposRight 属性。在此函数中,玩家的位置会与表格(敌人和墙壁都是表格)的坐标进行比较。因为 setInterval 每毫秒更新一次,所以它会产生真实的运动错觉。显示会在脚本完成前等待更新,这就是为什么 u1() 函数调用之间有一个间隔(setInterval)。在此间隔期间,显示引擎会更新屏幕,然后我们继续。根据 MSDN 的说法,“这些计时器不能保证精确到毫秒的精确计时。” 这对于精确的更新和动画来说不是好兆头,但在我老旧的 500 MHz 测试机上效果还不错。

最终,它变得更加复杂。随着关卡的增大,我添加了滚动功能,它会检查玩家的 posLeft 是否靠近屏幕中间,并使用 JavaScript 的 document.body.scrollLeft(Firefox 中是 scrollTo)属性滚动屏幕。我在游戏框架中隐藏了滚动条,所以只有游戏可以滚动。移动平台会在玩家站上去时滚动玩家,水会改变玩家的速度。游戏中的炮弹很简单:炮弹只是会造成伤害的移动平台!对于场景,我添加了云朵和地上的叶子,它们与玩家没有互动。

内部工作原理

文件 main.htm 包含生命计数器、时间和柠檬计数器。它在一个 IFRAME 中包含游戏屏幕。它还包含 2 个隐藏的 IFRAME。一个包含更新游戏 IFRAME 的游戏引擎,另一个包含关卡 HTML 代码。关卡只加载一次到这个隐藏的 IFRAME 中,然后每次英雄死亡时,我都会将关卡重新传输到主屏幕。当关卡加载时,它的 onLoad 事件会告诉顶部分数框架(main.htm)将文件 opiframe1.htm 加载到另一个 IFRAME 中。这会开始游戏更新。游戏的内部逻辑在 opiframe1.htm 中,你需要在这里打开脚本调试器!

所以,我最终得到了一个迷你平台游戏,里面有我自己业余制作的用 Paint! 绘制的图形。试试完成它,然后创建你自己的关卡!

更新!

  • 2007 年 5 月 - (v1.41) 修复了关卡加载错误并调整了关卡 3

许可证

本文没有明确的许可证,但可能包含文章文本或下载文件本身的使用条款。如有疑问,请通过下方的讨论板联系作者。作者可能使用的许可证列表可以在 此处找到。

© . All rights reserved.