9

我是 HTML5/Canvas/Game 编程的新手,但在阅读了几本书后一直在修改它。我认为我对事情的发展有相当好的了解。这个问题提出了几个较小的问题,但总的来说基本上是一个“结构方法”的问题。我不期待冗长的回应,但希望这里和那里的小指针:) 这是一个非滚动的链接,目前相当无聊的超级马里奥世界。

超级马里奥世界测试

注意:控件是左/右和空格键跳跃。这只是我现在正在学习的 Firefox 的设置。


我在这一点上做错了吗?

目前我只关注马里奥如何跑和跳,并认为我已经把它搞定了。硬币盒没有任何作用,背景只是为了外观而加载的图像。这是我的方法,如果有什么完全错误的,请告诉我:

  • 允许马里奥通过 2 Y 速度(重力和跳跃变量)进行跳跃
  • 允许马里奥以 1 速度运行(左或右“摩擦”+ 加速度)
  • 根据 keypress/keydown 使用和定位精灵
  • 我不确定这是否正确,但我正在使用构造函数来构建一个对象,然后在主动画循环中我调用该对象的原型函数来更新所有变量并重绘对象。
  • 我每帧都清理整个画布
  • 我是否应该将其拆分为不仅仅是一个绘图函数,比如 Mario.move()?
  • 我设置了一个 GroundLevel 和一个 JumpLevel 变量来创建 2 个游戏平面。JumpLevel 设置为允许控制马里奥在飞行中可以跳多高。这两个地方可以让地面像一座小山一样上升 - 保持重力超过马里奥的跳跃力的点与地面的距离相同。
  • 为清楚起见,所有内容都被分成不同的 JS 文件,但显然会合并。

向前进:

现在我已经完成了马里奥如何移动的设置(我认为我可能会做一些其他的小事情,比如蘑菇向上/向下和射击火球)。我想我可以弄清楚,但是在可视化以下内容以及 HTML5/Canvas 如何轻松处理这一点时,我真的迷失了:

  • 滚动背景(我尝试设置地面瓷砖并使用屏幕环绕,但这似乎会导致很多不均匀的问题,因为我正在向相反方向移动瓷砖。不幸的是,由于我试图考虑加速,这扔掉计数并在地面上造成间隙。我放弃了这个想法。画布下方带有大背景图像的 DIV 会是最好的解决方案吗?

  • 敌人:我会以同样的方式创建敌人并在每一帧中对每个敌人运行一个循环来检测碰撞吗?

  • 背景框:我试图让马里奥站在背景中的框上,但不确定如何处理。我目前为马里奥设置了边界以留在画布上,我是否继续扩展这些条件以根据框设置不同的边界?我可以看到在屏幕上显示几个框并以这种方式进行操作会有点疯狂,尤其是如果我要对敌人进行相同的命中测试?我知道我在这里遗漏了一些东西......

  • 水平运动:这有点相关。当按下 Right 键时,基本上关卡中的所有内容都需要向左移动。我是否需要在每个动画帧中追踪所有可能触及马里奥的物体的所有位置(让他站立的盒子和让他碰撞的敌人)?这似乎会变得效率低下?

谢谢大家!我会用结果/解决方案来更新这个:)

4

1 回答 1

7

哇,好吧。我真的很喜欢你的问题,因为你显然已经对此做了很多思考,但部分原因是它非常广泛和对话。你最好找个论坛问这个问题。

...话虽如此,我将回答我有资格回答的少数几个点,没有特别的顺序。:)

  • 水平移动:这是一种奇怪(阅读:低效)的方式。我不会根据屏幕上的位置进行任何计算:为关卡中的所有内容跟踪一组规范的、与相机无关的坐标,并更新视觉效果以匹配。这将阻止您遇到奇怪的琐碎问题,其中帧速率会影响您可以通过和不能通过的东西,或者导致速度较慢的计算机让马里奥有时会穿过敌人而不会受到损坏。以这种方式跟踪位置将顺便解决您的许多其他问题。

  • 您绝对应该将其拆分为多个功能。将移动代码和渲染代码放在同一个地方会让你感到厌烦,特别是通过与你的更新/刷新率进行恶意交互。这基本上意味着每次玩家进行棘手的跳跃时,游戏都会进行比平时更多的更新,这将使动画/命中检测/等变得更不可能均匀。

  • 敌人:我建议将其与其他所有内容一起使用。对所有东西进行一次命中检测传递,如果你击中某物,请检查它是什么。您可以尝试通过仅针对自身 100 像素内的对象检查任何给定实体来优化这一点,但如果您这样做,您将需要为每个敌人运行单独的碰撞检测事件。让敌人互相夹击在计算上会更便宜。

编辑:我想澄清我关于“水平运动”的第一点。本质上,您不想做的是每次相机移动屏幕上的每个实体,或者将所有实体位置存储为与相机位置的偏移量(在这种情况下,您仍然必须有效地移动所有内容,每次相机移动。)

您理想的方法是使用从关卡的绝对左上角偏移的 X/Y 坐标存储您的敌人、方块、地形位置(在开始时)。为了渲染帧,您基本上会这样做: (伪代码,因为我们在谈论一种假设的级别格式!)

function GetVisible(x,width,level_entities_array) {
  for (i = 0; i < count(level_array); i++){
    if (level_entities_array[i][x] > x && level_entities_array[i][x] < x+width) {
      visible_elements[] = level_entities_array[i][x];
    }
  }
return visible_elements;
}

繁荣,你已经拥有了应该在窗户内的一切。现在你从实体的位置和 ZAP 中减去相机的x偏移量x,你就得到了它在画布上的位置。摆成一个团队,因为事情变得真实了。

你会注意到我没有在 Y 轴上进行剔除。这可以通过外推来纠正,我猜你可以处理,因为你已经做到了这一点。如果您想进行任何马里奥风格的垂直探索,这将是必要的。

是的,我知道我的伪代码看起来像 C# 和 JavaScript 的邪恶之子。对不起,这就是我在晚上 11:30 滚动的方式。;)

于 2012-08-21T03:21:08.167 回答