构造HTML5画布/ JS游戏 [英] Structuring an HTML5 Canvas/JS Game

查看:127
本文介绍了构造HTML5画布/ JS游戏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚接触HTML5 / Canvas /游戏编程,但是在阅读了几本书之后,一直在修复它。我想我有一个很好的想法如何工作。这个问题问几个较小的问题,但一般来说基本上是一个结构方法问题。我不期望冗长的响应,但希望在这里和那里的小指针:)这里是一个非滚动,并且目前相当无聊的超级马里奥世界的链接。



超级马里奥世界测试



注意:控件是左/右和空格键跳转。






我做错了在这一点?



目前,我只关注如何马里奥运行和跳跃,并认为我已经把它下来相当不错。硬币盒不做任何事情,背景只是一个图像加载的外观。




  • 允许马里奥在2个Y速度重力和跳跃变量)

  • 允许Mario通过1个速度(左或右摩擦+加速度)运行

  • 使用Sprite根据keypress / keydown定位

  • 我不确定这是否正确,但我使用构造函数来构建一个对象,然后在主动画循环中我调用

  • 我要清除整个画布每个框架

  • 我应该

  • 我设置了一个GroundLevel和一个JumpLevel变量来创建2个游戏平面。 JumpLevel设置为允许控制马里奥可以飞得多高。这两个地方将允许地面像山一样上升 - 保持重力推翻马里奥在距离地面相同距离处的跳跃力。

  • 为了清楚起见,一切都是分开的





  • 前进:



    现在我已经完成了马里奥的移动(我认为还有一些其他的小事情,我可能会喜欢蘑菇上/下和射击火球)。我想我可以想出来,但是当我们想象以下的HTML5 / Canvas如何处理这个问题时,我真的很失望:




    • 滚动背景(我试过设置地面砖和使用屏幕环绕,但是这似乎导致了很多不平衡的问题,因为我在相反的方向移动瓷砖。不幸的是,

    • $ b $

      :我想让马里奥站在背景的盒子上,但我不确定如何处理这个。我目前有边界设置马里奥留在画布上,我继续扩展这些条件,以设置不同的边界在箱子上?我可以看到,在屏幕上有几个盒子,这样做会得到一种疯狂,特别是如果我对敌人做同样的命中测试?我知道我在这里缺少一些东西....


    • 水平运动:这有点相关。当按下Right键时,基本上该级别中的所有内容都需要向左移动。我需要在每个动画帧期间跟踪所有可能触及马里奥的所有位置(盒子让他站起来和敌人碰撞)吗?这似乎会得到一种低效率?




    感谢所有!我会保持更新结果/解决方案:)

    解决方案

    哇,好吧。我真的很喜欢你的问题,因为你明显做了很多思考,但部分因为它是非常宽泛和对话。你最好找一个论坛来提出这个问题。



    ...说的话,我会回答我有资格的几个点,没有特定的顺序。 :)




    • 关卡移动:这是一个奇怪的(读:低效)方式。我不会根据屏幕上的位置做任何计算:跟踪一个规范,相机无关的坐标集的一切在你的级别,并更新视觉匹配。这将阻止你进入怪异的问题,其中帧速率影响你可以和不能走过,或导致较慢的计算机让马里奥跑过敌人,有时没有被损坏。


    • 您应该绝对将这个功能分成多个功能。在同一个地方有移动代码和渲染代码会危害你,特别是通过恶意与你的更新/刷新率进行交互。这实际上意味着,每当玩家做一个棘手的跳跃,游戏会做出比平时更多的更新,这将使动画/点击检测等更不可能是偶然的。


    • 敌人:我建议和其他东西一起滚动。做一个命中检测通过对一切,如果你打某事检查看看是什么。你可以尝试通过只检查任何给定的实体对象在自己的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;
    }

    Boom,你有一切应该在窗口内。现在你从实体的 x 位置和ZAP中减去相机的 x 偏移,你的位置在画布上。



    你会注意到,我不打算在Y轴上剔除。这可以通过外推法纠正,我猜你可以处理,因为你已经做得很远。如果你想做任何马里奥风格的垂直探索,这将是必要的。



    是的,我知道我的伪代码看起来像C#和JavaScript的unholy lovechild。对不起,这就是我如何在晚上11:30滚。 ;)


    I'm new to HTML5/Canvas/Game programming, but have been tinkering around with it after reading a couple of books. I THINK I have a fairly good idea of how things work out. This question asks several smaller questions, but in general is basically a "structural approach" question. I'm not expecting verbose responses, but hopefully small pointers here and there :) Here is a link to a non-scrolling, and currently rather boring Super Mario World.

    Super Mario World Test

    NOTE: Controls are Left/Right and Spacebar to jump. This is only setup for Firefox right now as I'm just learning.


    Did I Do Something Wrong at This Point?

    Currently I've just focused on how Mario runs and jumps, and think that I've gotten it down fairly okay. The coin box doesn't do anything and the background is just an image loaded in for looks. Here's my approach, please let me know if there is anything entirely wrong with this:

    • Allows Mario to jump by enacting on 2 Y velocities (Gravity and Jump variables)
    • Allows Mario to run by enacting on 1 velocity (Left or Right "Friction" + Acceleration)
    • Sprites are used and positioned according to keypress/keydown
    • I'm not sure if this is right, but I'm using a constructor function to build an object, then inside the main animation loop I'm calling the prototype.draw function for that object to update all variables and redraw the object.
    • I'm clearing the entire canvas each Frame
    • Should I be splitting this into more than just a draw function, like Mario.move()?
    • I've setup a GroundLevel and a JumpLevel variable to create 2 planes of gameplay. The JumpLevel is setup to allow for controlling how high Mario can jump on the fly. The 2 places would allow for the ground to rise like a hill - keeping the point at which Gravity overrules Mario's jumping force at the same distance from the ground.
    • For clarity sake, everything is separated into different JS files, but would obviously consolidate.

    Moving Forward:

    Now that I've finished setting up how Mario moves around (I think there are a couple other minor things I might do like mushroom up/down and shooting fireballs). I think I can figure that out, but I'm really lost when it comes to visualizing the following and how HTML5/Canvas can handle this easily:

    • Scrolling background (I've tried setting up Ground Tiles and using Screen Wrapping, but that seems to cause a lot of uneven issues since I was moving the tiles in the opposite direction. Unfortunately, since I'm trying to account for acceleration, this threw off the count and was causing gaps in the ground. I ditched this idea. Would a DIV beneath the canvas with a large background image be the best solution?

    • Enemies: Would I create enemies the same way and run a loop for collision detection on every enemy during each frame?

    • Background Boxes: I'm trying to allow Mario to stand on the boxes in the background, but am unsure how to approach this. I currently have boundaries setup for Mario to stay on the canvas, do I continue to expand these conditions to setup different boundaries based on the boxes? I can see that having several boxes on the screen and doing it this way would get kind of crazy, especially if I would be doing the same hit testing for enemies? I know I'm missing something here....

    • Level Movement: This is somewhat related. When the Right key is pressed, basically everything in the level needs to move to the left. Would I need to track out all positions of everything that could touch Mario (boxes for him to stand on and enemies for him to collide with) during every animation frame? This seems like it would get kind of inefficient?

    Thanks to all! I'll keep this updated with results/solutions :)

    解决方案

    Wow, okay. I really like your question because you've obviously done a lot of thinking on this, but partially because of that it's incredibly broad and conversational. You'd do better to find a forum to ask this question.

    ...That being said, I'm gonna answer the handful of points I'm qualified to, in no particular order. :)

    • Level Movement: That's a weird (read: inefficient) way to do it. I wouldn't do any calculations based on onscreen positions: track a canonical, camera-agnostic set of coordinates for everything in your level and update the visuals to match. This will stop you from running into weird niggling problems where framerate impacts what you can and can't walk through, or causing slower computers to let Mario run through enemies without being damaged sometimes. Tracking positions this way will incidentally fix a lot of your other problems.

    • You should absolutely be splitting this into multiple functions. Having movement code and rendering code in the same place is going to screw you, particularly by interacting malignantly with your update/refresh rate. It's going to essentially mean that every time the player does a tricky jump the game does more updates than usual which will make animation/hit detection/etc much less likely to be even.

    • Enemies: I'd suggest rolling this in with everything else. Do one hit-detection pass against everything, and if you hit something check to see what it was. You could try to optimize this by only checking any given entity against objects within 100 pixels of itself, but if you do it this way you'll need to run separate collision detection events for every enemy. Letting the enemies clip through each other would be computationally cheaper.

    Edit: I'd like to clarify about my first point on 'level movement.' Essentially, what you don't want to do is move every entity onscreen every time the camera does, or to store all entity locations as offsets from the camera location (in which case you're still effectively having to move everything, every time the camera moves.)

    Your ideal approach is to store your enemy, block, terrain locations with X/Y coordinates that are offset from the absolute top-left of the level (at the very beginning.) In order to render a frame, you'd do essentially this: (pseudocode because we're talking about a hypothetical level format!)

    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;
    }
    

    Boom, you've got everything that should be inside the window. Now you subtract the camera's x offset from the entity's x location and ZAP, you've got its position on the canvas. Pose as a team, 'cause things just got real.

    You'll note that I'm not bothering to cull on the Y axis. This can be rectified by extrapolation, which I'm guessing you can handle because you've made it this far. This will be necessary if you want to do any Mario-style vertical exploration.

    Yes, I know my pseudocode looks like C# and JavaScript's unholy lovechild. I'm sorry, that's just how I roll at 11:30 at night. ;)

    这篇关于构造HTML5画布/ JS游戏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆