Structuring an HTML5 Canvas/JS Game - javascript

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. ;)

Related

How to check if a video is stabilized or not?

I was wondering how to detect camera motion in a youtube video.
I want to read in an youtube link process the video and tell the user if it was filmed using a tripod or if it was super shakey.
Do anyone know where I would even start? It might not even be possible?
Just spitballing here, but I'd start by capturing frames that are close together at various points throughout the video.
You would take the frames from each section and compare them to each other for variations in composition, dunno how to best go about that.. I'd probably start with like colour detection in various spots? anyway, start building a "difference score"
once you've gone through the frames for each section you sampled, you'll have a "difference score" and you can then start trying to figure out what the cut off point is for detecting a shakey video.
you probably couldn't do this anywhere close to realtime, so be prepared to have a bit of a wait period while the video processes.
Take some images each seconds (avoid to take it at a fixed frequency, because if the film has a move frequency, ie: if we are on a boat and we film during high waves)
After you can convert it to black and white (not gray levels) and compare it. Using the position of the minor color. (But it ain't gonna work fine)
Usually we use, edge detection : http://fr.mathworks.com/discovery/edge-detection.html and compare some of it. To see what is the scene and work together and waht is not. You must find "interest points" an calculate the vector between two frames. Some of this vector will move together. It's an object. Now you have to find which object if the scene.

HTML Canvas Tracing

I'm trying to build something in HTML5/Canvas to allow tracing over an image and alert if deviating from a predefined path.
I've figured out how to load an external image into the canvas, and allow mousedown/mousemovement events over it to draw over the image, but what I'm having trouble getting my head around is comparing the two.
Images are all simple black on white outlines, so from what I can tell a getPixel style event can tell if there is black underneath where has been drawn upon or underneath where the mouse is on.
I could do it with just the mouse position, but that would require defining the paths of every image outline (and there are a fair number, hence ideally wanting to do it by analyzing the underlying image)..
I've been told that its possible with Flash, but would like to avoid that if possible so that compatability with non-flash platforms (namely the ipad) can be maintained as they are the primary target for the page to run.
Any insight or assistance would be appreciated!
I think you already touched upon the most straight-forward approach to solving this.
Given a black and white image on a canvas, you can attach a mousemove event handler to the element to track where the cursor is. If the user is holding left-mouse down, you want to determine whether or not they are currently tracing the pre-defined path. To make things less annoying for the user, I would approach this part of the problem by sampling a small window of pixels. Something around 9x9 pixels would probably be a good size. Note that you want your window size to be odd in both dimensions so that you have a symmetric sampling in both directions.
Using the location of the cursor, call getImageData() on the canvas. Your function call would look something like this: getImageData(center_x - Math.floor(window_size / 2), center_y - Math.floor(window_size / 2), window_size, window_size) so that you get a sample window of pixels with the center right over the cursor. From there, you could do a simple check to see if any non-white pixels are within the window, or you could be more strict and require a certain number of non-white pixels to declare the user on the path.
The key to making this work well, I think, is making sure the user doesn't receive negative feedback when they deviate the tiniest bit from the path (unless that's what you want). At that point you run the risk of making the user annoyed and frustrated.
Ultimately it comes down to one of two approaches. Either you load the actual vector path for the application to compare the user's cursor to (ie. do point-in-path checks), or you sample pixel data from the image. If you don't require the perfect accuracy of point-in-path checking, I think pixel sampling should work fine.
Edit: I just re-read your question and realized that, based on your reference to getPixel(), you might be using WebGL for this. The approach for WebGL would be the same, except you would of course be using different functions. I don't think you need to require WebGL, however, as a 2D context should give you enough flexibility (unless the app is more involved than it seems).

slider that also magnifies around cursor

It can be difficult to use (webpage) sliders that cover a large range with fine granularity. On the one hand, it is easy to move across the range. On the other hand, it is difficult to locate the exact point one wants, assuming a fine enough granularity.
I was thinking that a magnify effect around the cursor could solve this problem (assuming the problem really exists).
I looked for existing solutions or ideas via google, but couldn't find anything.
Any suggestions here?
I doubt if this is what you're looking for, but... within Mac OSX, holding down the control key and moving the scroll wheel will zoom in and out.
I'm having trouble thinking of a scenario where having so much data that scrolling of this nature would be a problem you'd want to have. In almost all scenarios it makes more sense to chunk up the data or reduce it down in some other way.
About the only thing that makes sense is the seek-bar/scrubber on a video player. If your player is 400px wide with a 360px wide scrubber, but the video is an hour long, the best granularity you'll get is 10 seconds-per-step (with the step-size being 1 pixel).
If that isn't enough granularity, then it's possible you'll need to augment your scrubber with another UI convention - which could be a magnifier - but it could also be other things. Like a "jump to point" text field that would allow to user to entire a time and seek to that exact position.
It sounds like you're going for something (visually) like the OS X dock. This is called a fish-eye effect. There's a jQuery plugin for a fish eye menu which you may be able adapt and merge with a slider to give you the functionality that you're looking for.

Create fireflies in Javascript?

I want to create some randomly flying objects in a Unity 3D game. You can imagine them like fireflies. Now there're some tasks to do with them, include:
They usually fly randomly (of course).
They can fly away or fly back in some conditions.
I have to write some Javascript to do these things, but I don't know how to do. Can you help me? Thank you very much!
EDIT: I think I'll need these functions:
function Fly()
{
//control the gameObject to fly randomly
}
function FlyAway()
{
}
function FlyBack()
{
}
I would suggest that you look at the canvas tag, but then it will not work on IE as I don't know if 3D effects will work on excanvas well.
This gives you a drawable surface to do your graphics.
You will probably need to write your own primitive functions for the graphics, but it is very doable.
EDIT: You will need to use object oriented javascript for each of your fireflies, which will help you to move each of them each frame.
If you show your attempt at drawing graphics you can get more help.
As much as I hate condoning the use of Flash, this really sounds like a Flash job.
However, if you insist on using JavaScript, I'd thumb through some Chrome Experiments for 3D examples (w/canvas): http://www.chromeexperiments.com/
I've done an abstraction library that may help here:
DP_PanelManager
The library makes moving objects pretty simple - at the bottom of the page there's an example called "Useless Animation" - it's basically a checkerboard where each square randomly moves, changes size and changes opacity.
Something like that with fewer panels and a little math to do smoother travel (something like this should be easy enough to modify) should get you close.
The component also has simplified functions for collision detection and distance between panels (with bearing - the function will tell you how far apart two panels are AND in which direction they lay).
Hopes this gives you a headstart.
My approach would be
randomly create a x/y equation (may be from a given set, if you don't know how to 100% randomize this).
Decide, randomly if you go by the x or by the y.
decide the number of steps you take on the axis you chose in step 2.
move your element according to the x/y you get from the equation in step 1.
When you finished to move all the steps (number of steps is given in step 3), go back to step 1. In a loop.

Drawing Application Zoom Concept

I'm building an application on top of canvas, it consists of a simple DOM that gets redrawn on every mouse move (yes, it is necessary), for performance issues not every part part gets redrawn only what is needed.
The app is working well but I'd like to add the zoom feature, the way I see it, it can be done in three different ways:
1 - Every DOM element gets recalculated (position and size) every time a user zooms in or out - it might have issues with precision and its not a very good abstraction
2 - The canvas has a resolution property (i.e. when the user zooms out resolution might change from 1 to .75) - there will be a need to make the calculations on every redraw
3 - Use the built in translate() and scale() methods - possibly the most elegant and fastest solution, however it is not intuitive at all, it might be difficult to understand how it is being done latter on by me or someone else (these methods work on the full canvas, first you would translate and scale on the canvas and afterwards everything you draw gets 'magicly' translated and scaled)
Which one is best or are there other possibilities I'm not thinking of?
I would use the builtin translate()/scale() methods. If you're worried about the performance and quality of any of these methods, you should try to do it in a way that you can swap it out for another of the options to compare, if the results end up giving you any concern.

Categories

Resources