Me and my team are developing a HTML5 Game with the framework Phaser.io.
Now we encountered a problem, since we pushed the speed of our bullets to a faster one.
this.game.physics.arcade.collide(this.objects.cups, this.obstacleLayer, this.destroy, null, this);
This is the function call, that our bullets (named cups) should collide with the obstacleLayer (where the walls are placed on).
You can run our actual version with the problem here.
You can walk around with WASD and shoot with a mouseclick.
The problem is, that the bullets collide with the walls just sometimes and sometimes they do not. We tried to figure out in which special situation they collide or not, but we were not enable to locate the actual problem.
To fire our bullets we use
this.game.physics.arcade.moveToPointer(cup, 4000);
4000 is the speed. The problem occurs with higher speed, e.g. with a speed of 100 it will work. But we need minimum 2000 as the speed of our bullets.
Hope you can help us,
thank you in advance
Here is the source code of the phaser.io core timer https://github.com/photonstorm/phaser/blob/v2.4.4/src/time/Time.js
As Vladimirs stated in the comments you have to increase the calculated fps-rate (not the displayed) or decrease msMax value
Related
I'm trying to build an HTML5 Game with Canvas 2D (Only for Computer as device). But there's a Problem, I have thousands of moving images and with around 4000+ Images (Enemys) I dont get more then 10 FPS. With Java2D it's working fine, now I'm trying to import the Game to HTML5. Did anyone have some tips to realize this in HTML5? Some Code optimization? For any help I would be very grateful.
http://jsfiddle.net/LtlFdl/tzd8z/
ctx.clearRect(0, 0, 320, 320); // <- Maybe just Clear the Enemy Square Position?
btw.: on the Fiddle is just ONE playerfield, at the end there 4 playerfields (rotated 90, 180 and 270 degress), a background image, towers and a lot of effects. So I have to multiple everything with 4.
First...Ditto the good thoughts that #enhzflep has already mentioned in his comment.
I would add that setting the fillStyle is a somewhat expensive operation so setting the fillStyle with each of 4000 Enemy draws becomes very expensive. I suggest that you just display the textual & health info once per second rather than with each Update_Map1.
On my modestly fast development desktop I can do 4000 X drawImage(img,0,0) at a rate of 45 times per second. This leads me to believe the transformations (translate,rotate) are slowing you down. Perhaps create 4 versions of your enemy image--facing up,down,left & right. Then entirely replace the transforms by drawing the appropriately facing image.
I see you're using delete Enemys_P1[i]. It's more resource effective to "recycle" exiting enemies. You can do this by marking an Enemy as "inactive" and not processing that enemy. When you need a new enemy you can change an inactive enemy to "active" and set its properties to the "new" enemy values.
Good luck with your project!
I'm trying to make a little platform game with pure HTML5 and JavaScript. No frameworks.
So in order to make my character jump on top of enemies and floors/walls etc., it needs some proper collision detection algorithms.
Since I'm not usually into doing this. I really have no clue on how to approach the problem.
Should I do a re-check in every frame (it runs in 30 FPS) for all obstacles in the Canvas and see if it collides with my player, or is there a better and faster way to do so?
I even thought of making dynamic maps. So the width, height, x- and y coordinates of the obstacle are stored in an object. Would that make it faster to check if it's colliding with the player?
1. Should I re-check in every frame (it runs on 30 FPS)?
Who says it runs in 30 FPS? I found no such thing in the HTML5 specification. Closest you'll get to have anything to say about the framerate at all is to programmatically call setInterval or the newish, more preferred, requestAnimationFrame function.
However, back to the story. You should always look for collisions as much as you can. Usually, writing games on other platforms where one have a greater ability to measure CPU load, this could be one of those things you might find favorable to scale back some if the CPU has a hard time to follow suit. In JavaScript though, you're out of luck trying to implement advanced solutions like this one.
I don't think there's a shortcut here. The computer has no way of knowing what collided, how, when- and where, if you don't make that computation yourself. And yes, this is usually, if not at all times even, done just before each new frame is painted.
2. A dynamic map?
If by "map" you mean an array-like object or multidimensional array that maps coordinates to objects, then the short answer has to be no. But please do have an array of all objects on the scene. The width, height and coordinates of the object should be stored in variables in the object. Leaking these things would quickly become a burden; rendering the code complex and introduce bugs (please see separation of concerns and cohesion).
Do note that I just said "array of all objects on the scene" =) There is a subtle but most important point in this quote:
Whenever you walk through objects to determine their position and whether they have collided with someone or not. Also have a look at your viewport boundaries and determine whether the object are still "on the scene" or not. For instance, if you have a space craft simulator of some kind and a star just passed the player's viewport from one side to the other and then of the screen, and there is no way for the star to return and become visible again, then there is no reason for the star to be left behind in the system any more. He should be deleted and removed. He should definitely not be stored in an array and become part of a future collision detection with the player's avatar! Such things could dramatically slow down your game.
Bonus: Collision quick tips
Divide the screen into parts. There is no reason for you to look for a collision between two objects if one of them are on left side of the screen, and the other one is on the right side. You could split up the screen into more logical units than just left and right too.
Always strive to have a cheap computation made first. We kind of already did that in the last tip. But even if you now know that two objects just might be in collision with each other, draw two logical squares around your objects. For instance, say you have two 2D airplanes, then there is no reason for you to first look if some part of their wings collide. Draw a square around each airplane, effectively capturing their largest width and their largest height. If these two squares do not overlap, then just like in the last tip, you know they cannot be in collision with each other. But, if your first-phase cheap computation hinted that they might be in collision, pass those two airplanes to another more expensive computation to really look into the matter a bit more.
I am still working on something i wanted to make lots of divs and make them act on physics. I will share somethings that weren't obvious to me at first.
Detect collisions in data first. I was reading the x and y of boxes on screen then checking against other divs. After a week it occurred to me how stupid this was. I mean first i would assign a new value to div, then read it from div. Accessing divs is expensive. Think dom as a rendering stage.
Use webworkers if possible easy.
Use canvas if possible.
And if possible make elements carry a list of elements they should be checked against for collision.(this would be helpful in only certain cases).
I learned that interactive collisions are way more expensive. Because you have to check for changes in environment while in normal interaction you simulate what is going to happen in future, and therefore your animation would be more fluid and more cpu available.
i made something very very early stage just for fun: http://www.lastnoob.com/
How to create good timer for HTML5 Canvas games?
I am using RequestAnimationFrame( http://paulirish.com/2011/requestanimationframe-for-smart-animating/ )
But object's move too fast.
Something like my code is:
http://pastebin.com/bSHCTMmq
But if I press UP_ARROW player don't move one pixel, but move 5, 8, or 10 or more or less pixels. How to do if I press UP_ARROW player move 1 pixel?
Thanks for help.
The problem is that your approach of incrementing a value on each interval produces inconsistent results. Sounds like in your case RequestAnimationFrame is triggering too fast, but in other cases -- like on a slow CPU -- they would trigger slower, giving different results.
So, game animations need to be based on "absolute" time. Ie, you need to "remember" when the UP_ARROW was pressed, and where the player was at that point. Then, when you call update() determine how much time elapsed, and based on that, and the desired speed (in, say, pixels per second), move the player to the appropriate position. It makes your code more complicated, but unfortunately that's how it has to be done.
This issue is discussed a lot online. Here's one random article I found (based on Flash, but it doesn't matter):
http://www.flashgamesclassroom.com/classroom/actionscript/frame-based-vs-time-based-animation/
You can google "time based game animation" to research more.
Morning,
Over the past few months I have been tinkering with the HTML5 Canvas API and have had quite a lot of fun doing so.
I've gradually created a number of small games purely for teaching myself the do's and don'ts of game development. I am at a point where I am able to carry out basic collision detection, i.e. collisions between circles and platforms (fairly simple for most out there but it felt like quite an achievement when you first get it working, and even better when you understand what is actually going on). I know pixel collision detection is not for every game purely because in many scenarios you can achieve good enough results using the methods discussed above and this method is obviously quite expensive on resources.
But I just had a brainwave (It is more than likely somebody else has thought of this and I am way down the field but I've googled it and found nothing)....so here goes....
Would it possible to use/harness the "globalCompositeOperation" feature of canvas. My initial thoughts were to set its method to "xor" and then check the all pixels on the canvas for transparency, if a pixel is found there must be a collision. Right? Obviously at this point you need to work out which objects the pixel in question is occupied by and how to react but you would have to do this for other other techniques.
Saying that is the canvas already doing this collision detection behind the scenes in order to work out when shapes are overlapping? Would it be possible to extend upon this?
Any ideas?
Gary
The canvas doesn't do this automatically (probably b/c it is still in its infancy). easeljs takes this approach for mouse enter/leave events, and it is extremely inefficient. I am using an algorithmic approach to determining bounds. I then use that to see if the mouse is inside or outside of the shape. In theory, to implement hit detection this way, all you have to do is take all the points of both shapes, and see if they are ever in the other shape. If you want to see some of my code, just let me know
However, I will say that, although your way is very inefficient, it is globally applicable to any shape.
I made a demo on codepen which does the collision detection using an off screen canvas with globalCompositeOperation set to xor as you mentioned. The code is short and simple, and should have OK performance with smallish "collision canvases".
http://codepen.io/sakri/pen/nIiBq
if you are using a Xor mode fullscreen ,the second step is to getImageData of the screen, which is a high cost step, and next step is to find out which objects were involved in the collision.
No need to benchmark : it will be too slow.
I'd suggest rather you use the 'classical' bounding box test, then a test on the inner BBOxes of objects, and only after you'd go for pixels, locally.
By inner bounding box, i mean a rectangle for which you're sure to be completely inside your object, the reddish part in this example :
So use this mixed strategy :
- do a test on the bounding boxes of your objects.
- if there's a collision in between 2 BBoxes, perform an inner bounding box test : we are sure there's a collision if the sprite's inner bboxes overlaps.
- then you keep the pixel-perfect test only for the really problematic cases, and you need only to draw both sprites on a temporary canvas that has the size of the bigger sprite. You'll be able to perform a much much faster getImageData. At this step, you know which objects are involved in the collision.
Notice that you can draw the sprites with a scale, on a smaller canvas, to get faster getImageData at the cost of a lower resolution.
Be sure to disable smoothing, and i think that already a 8X8 canvas should be enough (it depends on average sprite speed in fact. If your sprites are slow, increase the resolution).
That way the data is 8 X 8 X 4 = 256 bytes big and you can keep a good frame-rate.
Rq also that, when deciding how you compute the inner BBox, you can allow a given number of empty pixels to get into that inner BBox, trading accuracy for speed.
Right now I've got two game loops in a game I'm making. A draw loop that loops through an array of objects on screen and a logic loop that does game logic. I have the logic loop running about 10 more frames than the draw loop. I have this set up like this because doing game logic may take longer and I don't want it to interfere with the draw loop.
I have the logic loop set up like this:
vs.logicloop = function(){
vs.Gameloop();
//do the updating of object scripts
if(vs.windowActive){
var l = vs.scenegraph.length;
var i = 0;
while(i < l){
vs.scenegraph[i].logicScript();
i++;
}
}
//restart loop
setTimeout(vs.logicloop, 1000/(vs.fps+10));
};
and the draw loop like this:
vs.drawloop = function(){
//clear the screen
vsd.clr();
//goes through everything in the scene
//graph and draws it and runs each object's
//personal draw code
if(vs.windowActive){
var l = vs.scenegraph.length;
var i = 0;
while(i < l){
vs.ctx.save();
vs.scenegraph[i].update();
vs.scenegraph[i].draw();
vs.scenegraph[i].drawScript();
vs.ctx.restore();
i++;
}
}
//restart loop
setTimeout(vs.drawloop, 1000/vs.fps);
};
I'm using setTimeout because I heard that setInterval will cause loops to overlap if one isn't finished yet. Are there any optimizations I can do to really get some speed? Especially optimizing the game loops.
I've heard of some javascript engines getting thousands of objects on screen at once. I can't imagine how they do that, at most mine can get up to 100 objects on screen on a very old computer and about 700 on a reasonably stocked computer. And that's without a lot of game code running in the background and before I've worked out how to do pixel perfect collision detection and physics.
My process is to draw a background color fillRect over the canvas every draw loop, then looping through all the objects and drawing their draw code. Also it doesn't try to draw objects out of view.
This is my first paying job, and I really want to impress. Plus I can keep ownership of the engine once I'm done with the game.
Thanks A Lot
if you use floating values for sprite coordinates, try converting them to integers. that will cost you losing subpixel rendering but you will gain a lot of speed.
don't use images with odd widths. always use widths as powers of 2.
this one is hard to implement in some cases but if your game is suitable, don't clear screen and redraw everything each frame. instead, draw changed parts.
if you have to clear the canvas, don't draw a blank rectangle. try setting the canvas width/height again with the same size. that should reset the pixels faster than rectangle drawing.
rest of the methods i can suggest are not HTML5 canvas dependent but general subjects like using bit shiftings, inverse loops, and operator instead of modulo when possible, precalculations etc.
Oh geez, I could probably write you a full sonnet here if you posted all your code. Here's a quick rundown:
Read Emir's answer. All of those are good except the last one which is very dependent on the situation. Setting canvas.width = canvas.width to clear the canvas can be faster on some browsers but it also clobbers all canvas state (ie the last set fill and font) which can slow things down because setting those properties is actually painfully slow.
Read my articles on Canvas performance: http://simonsarris.com/blog/tag/performance
I have a lot of other tips saved up in a private document that I'm writing a small ebook out of. If you want early access to it I can probably allow that.
Pick up High performance JavaScript by Zakas and read it.
Don't use save() and restore() like you are in the quoted code unless you must. They are just slowing things down.
For the timer see http://paulirish.com/2011/requestanimationframe-for-smart-animating/
Multiple canvases for foreground-background-middleground can definitely help. Caching things on in-memory canvases can definitely help. It all depends on what you're drawing.
A lot of performance problems are due to death by a thousand tiny cuts. For instance:
vs.scenegraph[i].update();
vs.scenegraph[i].draw();
vs.scenegraph[i].drawScript();
To
var scene = vs.scenegraph[i];
scene.update();
scene.draw();
scene.drawScript();
Will help a minute amount. How many opportunities for minute-amount stuff you have I don't know - we'd need to see a lot more code.
I heard that setInterval will cause loops to overlap if one isn't finished yet.
This is false, JavaScript is single threaded. This means that if your first interval is still running when it hits the next step, the next step will be delayed until the first step has finished computing. This also means that you can't rely on setInterval to be accurate if you start doing a lot of computations.
I'd echo much of all has been said by other people. Integer values, use request animation frame, etc. If drawing text be careful how often you set fonts. Also you might find using an object pool can help if you are creating lots of temporary objects per frame.
As a general read on game loops I'd recommend this: http://www.koonsolo.com/news/dewitters-gameloop/