I am developing a HTML5 game. The server-side code (node.js, socket.io) is mostly done and I am moving on to polishing the client-side code.
I have been directly drawing tiles/grid on the canvas and moving the player's sprite using context and clearRect etc. I am thinking of drawing simple animations and effects over the tile-map/grid such as:
Rain, with flashes of lightning, and thunder audio clip.
Animating some of the tiles. E.g. grass tile has grass blowing in the wind by cycling through frames (like an animated gif).
Pop up text boxes that are close-able with mouse clicks or keyboard button press.
I have checked out this long list of JavaScript engines and tried out CraftyJS and MelonJS but most of these are made for platform or arcade style games, and many of them are not ready for production or are poorly maintained.
Is there a simple, lightweight, production-quality HTML5 canvas engine that can accomplish what I want?
Take a look at CreateJS; it's a great engine for what you're looking for.
EaseJS can be used for the Canvas element
SoundJS for the audio clip which you want played
It's well maintained, but an 1.0 version hasn't been released (yet).
Is it just animated sprites you want to achieve? You can do this easy without the use of a game engine. As for dialog boxes - you could just use dom elements over the canvas.
Here is a sprite class I wrote in javascript - maybe it's of some help :)
var FrtlsSprite = Class.extend({
init: function(bitmap, offsetX, offsetY, frameWidth, frameHeight, frameCount, loop){
this.dtotal=0;
this.framerate=0.007;
this.loop = loop;
this.isPlaying=false;
this.bitmap = new Image();
this.bitmap.src = bitmap;
this.frames= new Array();
this.currentFrame=0;
this.endFrame=0;
for(var i=0;i<frameCount;i++){
this.frames.push(new FrtlsFrame(offsetX+i*frameWidth, offsetY+0, frameWidth, frameHeight));
}
},
update: function(dt){
if(this.isPlaying){
this.dtotal += dt //we add the time passed since the last update, probably a very small number like 0.01
if (this.dtotal >= this.framerate){
this.dtotal -= this.framerate;
this.currentFrame++;
if(this.currentFrame==this.endFrame){
if(this.loop == false){
this.stop();
}
else{
this.currentFrame=0;
}
}
}
}
},
draw: function(){
fruitless.ctx.drawImage(this.bitmap,
this.frames[this.currentFrame].pos.x,
this.frames[this.currentFrame].pos.y,
this.frames[this.currentFrame].dimensions.x,
this.frames[this.currentFrame].dimensions.y,
0,
0,
this.frames[this.currentFrame].dimensions.x*fruitless.worldScale,
this.frames[this.currentFrame].dimensions.y*fruitless.worldScale);
},
play:function(frame){
this.currentFrame=(frame==undefined)?0:frame;
this.endFrame = this.frames.length-1
this.isPlaying=true;
},
playTo:function(frame, endFrame){
this.currentFrame=frame;
this.endFrame = endFrame;
this.isPlaying=true;
},
stop:function(frame){
this.currentFrame=(frame==undefined)?this.currentFrame:frame;
this.isPlaying=false;
}
});
cgSceneGraph will do the job for you.
Look at the examples web page, there are some examples with animated Sprite. It's a native component of the framework and is really easy to use with several featres like multi animation inside the same instance of the animated sprite, use of spritesheet, ...
Related
I am trying to verify that this happens no matter what, and there's no way to bypass it. It seems pretty silly to me that createjs uses this architecture. But I noticed that creating a stage from an existing canvas element removes all shapes, writings, etc from the canvas? Code is below:
html:
<canvas id="canvas" width="800" height="400"></canvas>
js:
var canv = document.getElementById("canvas");
var stage = new createjs.Stage(canv);
var ctx = canv.getContext('2d');
ctx.beginPath();
ctx.arc(50,50,10,0,2*Math.PI);
ctx.stroke();
createjs.Ticker.addEventListener("tick", tick);//circle created is overwritten here!!!?! Why createjs!?
//stage.update();
createjs.MotionGuidePlugin.install();
var shape1 = new createjs.Shape();
shape1.graphics.f("#000000").dc(0,0,10);
var path1 = new createjs.Shape();
path1.graphics.beginStroke("#ff0000").mt(0,0).qt(50,100,100,0);
stage.addChild(path1, shape1);
createjs.Tween.get(shape1).to({guide:{ path:[0,0, 50,100, 100,0] }},2000, createjs.Ease.cubicInOut);
function tick(event) {
stage.update();
}
Is this something that cannot be bypassed? It seems silly to me that createjs wouldn't just actually use the existing element unerased. If not, what is the point in passing in an element in the first place, why doesn't it just create a canvas element, and give you the ID? Anyways, if this is how it's going to be, unfortunately, I am going to have to go somewhere else. Sad, because createjs seemed pretty useful.
CreateJS uses a retained graphics mode, that is, it stores the state and redraws it each time. This is because the canvas is basically a big Bitmap with drawing commands – clearing the stage is the only way to remove the previous state.
But good news! There are lots of ways to get around these limitations if you want to blend CreateJS content with other content, or even make additive drawing effects.
The first is easy, which is setting autoClear. This will prevent the clear, and just draw the new contents over the old one.
stage.autoClear = false;
The second is a bit tougher, but great for instances where you want to mix CreateJS content with other libraries or effects. You can basically use the other canvas as the source to a Bitmap you include in CreateJS:
// Create a child for CreateJS referencing the other canvas
var bmp = new createjs.Bitmap(otherCanvas);
// Add it at the bottom (or top or wherever) in your new CreateJS canvas
stage.addChildAt(bmp, 0);
This is a great approach because it lets you put your content wherever you want, edit it separately, etc.
If you have a different case this doesn't cover, let me know and I can try to make a recommendation!
Cheers.
Long time lurker but never made an account. Just wanted to preface that I'm by no means a dev and just tinkering and experimenting for fun, so I apologise in advance if I seem really dumb.
I'm working on a dynamic overlay for Twitch streaming and was previously using AS3 but I've switched over to HTML5 now. I'm trying to load an image onto the canvas (which will eventually be a profile picture fetched using Twitch API... but one step at a time). I'm using Adobe Animate and I have the following so far applied in Actions on the first frame of the layer:
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d');
show_image();
function show_image() {
source_image = new Image();
source_image.src = 'https://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png';
source_image.onload = function () {
context.drawImage(source_image, 100, 100);
}
}
When I hit Ctrl+Enter and see it in Chrome, the image appears for the first frame then disappears. I'm not sure how I'm supposed to get it to stay indefinitely. I need to be able to animate it later, and it'll change depending on the latest follow/donation/sub, etc.
I tried extending the frame itself in the timeline, however, this just changed long how it took to loop and didn't make the image itself stay longer. I'm probably missing something really simple!
Any help would be appreciated. Thanks!
Your code is okay if your approach is using a canvas with HTML and JS, without any libraries involved. However, this is not the case, as you are using Animate, and the way to draw graphics with it is different than using default canvas methods like drawImage().
Animate includes the CreateJS suite, which includes the EaselJS library ,and this allows you to use another tools to draw to your canvas. Two or them are the Stage object, the visual container of your animate project, and the Bitmap object, who represents an image, canvas or video. For effects of this question, only both objects are required.
Note that the code below is only for the first frame:
/* It is not necessary to declare the canvas or stage element,
as both are already declared. At this point the stage is ready to be drawn */
show_image();
function show_image() {
var source_image = new Image();
source_image.src = 'https://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png';
source_image.onload = function(event) {
/* A new Bitmap object is created using your image element */
var bmp = new createjs.Bitmap(event.currentTarget);
/* The Bitmap is added to the stage */
stage.addChild(bmp);
}
}
I've been stuck on this for about a week now and can't figure out why the shape instance inside my container is getting blurred when it is animated at 60 fps. My container holds one shape instance. The shape instance is associated with one graphics instance. There seems to be a white blur that trails the direction of the animation. Is there a way to stop this blurring or is it a limitation of tweenJS? Here's the jsFiddle.
http://jsfiddle.net/1chh2de6/
Here are some additional details, I am working on a billiards game which involves a lot of moving circles. I've created a class for each pool ball, which will hold more shape instances in the future. However, at 60 fps the shape instances are blurred during animations. Here's the 'poolBall' class.
function poolBall(number, posX, posY) {
this.number = number;
this.shapesArray = [];
this.shapesArray.push(new createjs.Shape());
this.containerInstance = new createjs.Container();
this.containerInstance.addChild(this.shapesArray[0]);
this.containerInstance.x = posX;
this.containerInstance.y = posY;
this.drawGraphic = function(){
this.shapesArray[0].graphics.beginFill('white')
.setStrokeStyle(1)
.beginStroke("#000000")
.drawCircle(14, 14, 14)
.endFill()
.endStroke();
};
};
This is just a symptom of how the canvas displays the contents as they change, and not related to EaselJS or TweenJS. Here is a fiddle using raw canvas APIs.
http://jsfiddle.net/lannymcnie/97vLu9q9/1/
Circle Code
context.beginPath();
context.arc(0,0,20,0,2* Math.PI,false);
context.fillStyle = "white";
context.fill();
context.lineWidth = 1;
context.strokeStyle = "black";
context.stroke();
Note that I used RequestAnimationFrame to update the stage. I tested RAF with EaselJS as well, with no change in how it animated.
Unless I'm missing something here, this is just persistence of vision, which is just how normal human vision works, especially with high contrast graphics on computer screens.
Try going outside on a dark night and waving a bright light back and forth, you will similarly see a subtle "trail" behind it.
An even better way to prove this, is to capture a screen shot while the animation is happening. Looking at the static frame, you will see that it does not have the blur.
I am having trouble finding a good method to limit my mouse to be only able to click on a pre existing line in canvas (stroke width of 3)
What I need to know
how to limit mouse so can only click on pre- existing line, add a dot on click
line is drawn with this function
function createLine(startX:Float, startY:Float, endX:Float, endY:Float)
{
surface.beginPath();
surface.moveTo(startX, startY);
surface.lineTo(endX, endY);
surface.closePath();
surface.strokeStyle = '#ffffff';
surface.lineWidth = 2;
surface.stroke();
}
I am working in haxe, but solution in JS is fine
Thanks in advance.
The only way is for you to keep track of what you have drawn and do the collision/mouse over detection on your own.
If you need your canvas to be highly interactive, you should probably be looking at SVG. http://raphaeljs.com/ is a great library for drawing which will use canvas or SVG, whichever is available.
I am trying to build a roulette wheel in javascript.
I found this example: http://www.switchonthecode.com/tutorials/creating-a-roulette-wheel-using-html5-canvas but I find the look & feel not very terrible.
Since my roulette will have a limited number of option, I was thinking of using an image and then place text above with the proper angle. When spinning the wheel, I would just make the image and the text turn.
Is it a good approach? Are there some better approaches?
You can also do that with css3 rotation but it will work only on newer browsers
You can do even better. Make hole roulette wheel in SVG, it support animation and it can be programmed in javascript
Well I think the best approach in terms of creating something quickly and easily is to use an existing Javascript library for creating spinning prize/winning wheels.
I am the creator of a Javascript library called Winwheel.js which is specifically for this purpose. See http://www.dougtesting.net
One great feature about my Winwheel.js is that you can mix a graphically rich image for the face of the wheel with code-drawn text for the segment labels, so if you want the wheel to look really nice but have the flexibility of configurable text, you can.
Here is an example of the code needed to do this using Winwheel.js...
var myWheel = new Winwheel({
'drawMode' : 'image',
'drawText' : true, // Set this to true for text to be rendered on image.
'numSegments' : 4,
'textOrientation' : 'curved', // Set text properties.
'textAlignment' : 'outer',
'textMargin' : 5,
'textFontFamily' : 'courier',
'segments' : // Set segment text
[
{'text' : 'Television'},
{'text' : 'Mobile Phone'},
{'text' : 'Old Radio'},
{'text' : 'Computer'}
]
});
var wheelImg = new Image();
wheelImg.onload = function()
{
myWheel.wheelImage = wheelImg;
myWheel.draw();
}
wheelImg.src = "wheel_image.png";
There is a full set of tutorials on my site explaining how to use Winwheel.js, but the particular one about Image wheels can be found here http://dougtesting.net/winwheel/docs/tut9_creating_with_an_image
Thanks,
DouG
jQuery is not necessary. The example was done using the HTML5 Canvas element, which is probably the only (clean) way you could do it without Flash or Silverlight. You can customize the colors using the first array in the code, or any other nuance of it with a little tinkering.
You could use an SVG (Scalable vector graphics format) image and rotate it.
I wrote http://roulette.dabase.com/ as an exercise which works on mobile browsers I've tried.
I actually implemented a similar mini-game on my site not too long ago. No canvas, no SVG, no jQuery.
I used a simple image for the board (more specifically as a background-image), then placed a <div> on it to be the ball.
<div id="board"><div></div></div>
CSS:
#board {
width:256px;
height:256px;
background-image:url('gameboard.png');
position:relative;
transform-origin:50% 50%;
}
#board>div {
position:absolute;
margin-left:-7px;
margin-top:-7px;
border:7px outset #ccc;
width:1px; height:1px;
left:248px;
top:128px;
}
Then this JavaScript is used to position the ball when spinning:
function placeBall(angle) {
var board = document.getElementById("board"), ball = board.children[0];
ball.style.left = (128+Math.cos(angle)*120)+"px";
ball.style.top = (128-Math.sin(angle)*120)+"px";
board.style.transform = "rotate(-"+angle+"rad)";
}
This will result in the ball spinning around the wheel in older browsers. In newer browsers, the ball will stay in place (but the border shading will spin) while the entire board rotates. You can of course use a combination of the two if you do something different on the transformation (for example, "rotate(-"+(angle/2)+"rad)")