How to do a Tween in CraftyJS? - javascript

Alright, I'm at my wits end and I can't get CraftyJS to do a tween.
So what I wanna do is, everytime a Mushroom gets hit, I want to check if that mushroom has the component "Answer". If it exists, I will do nothing. Otherwise, I wanna display a big red box that fades away.
Crafty.c("Mushroom", {
init: function() {
this.addComponent("collision");
this.collision();
this.onhit("bullet",function(e) {
this.destroy();
e[0].obj.destroy();
if(!this.has("Answer")) {
Crafty.e("2D, Tween, color, canvas")
.attr({alpha: 1.0, x: 170, y: 100, w:300, h:100})
.color("red")
.bind("enterframe", function() { //How do i actually get the box to fade?
this.tween({alpha: 0.5, x: 170, y: 100}, 30);
});
}
});
}

You are binding the tween code execution to the EnterFrame event, which will cause the tween to start with each frame. Instead, you want to simply call the tween function on the entity you created, like so
Crafty.e("2D, Tween, color, canvas")
.attr({alpha: 1.0, x: 170, y: 100, w:300, h:100})
.color("red")
.tween({alpha: 0.5, x: 170, y: 100}, 600);
And the tween function will manage its own EnterFrame over the next 600 ms (30 frames), after which it will fire the TweenEnd event.
(In old versions of Crafty, you specified the duration in frames instead of ms.)

This is more like a meta answer :-)
First, i would encourage you to upgrade to the latest version as it has a lot of bugfixes. Some of the changes you will have to do to get your code to run under the new release is to change all components and events to Pascal casing. That is enterframe => EnterFrame, canvas => Canvas etc.
Second, i think you should bring these questions to the Crafty forum to get the right audience. The only way i discovered this question was through a google alert.
The best way to get help is to create a jsfiddle from this template http://jsfiddle.net/mCdUX/62/ with a small running example demonstrating the part that you can not get to work.
Oh, and welcome to the Crafty community :-)

Related

How to work with multiple hitbox areas in crafty.js?

I am trying to create multiple hitbox areas in my game, but I can't find any documentation or examples of how to work with them.
The scenario is, my "Hero" have 2 hitbox, one on his feet and another on his body. If he hits an enemy with the foot hitbox, the enemy dies. If he hits the enemy with his body, his health have to be decreased.
How can I identify which hitbox create the collision event?
The answer to this question is similar to one recently answered on Crafty's forum.
You can attach invisible entities to a parent entity, which will move alongside the parent entity and simultaneously serve as hitboxes for your parent entity. In response to detecting collisions on these child entities, you can inform the parent entity about those collisions. There may be other ways to achieve the same thing.
Following is a small example that showcases the principle.
Use WASD to move, observe the color change depending on which body part touches the brown enemy.
Note that it doesn't resolve the case when both body parts are colliding with the enemy. Triggering events on the parent entity was reduced to directly modifying the parent entity for simplicity. onHit has its limitations and is used here for simplicity.
Crafty.init();
var hero = Crafty
.e("2D, DOM, Color, hero, Fourway")
.attr({x: 0, y: 0, w: 64, h: 128})
.color('gray')
.fourway();
var body = Crafty
.e("2D, Collision, WiredHitBox, body")
.attr({x: 0, y: 0, w: 64, h: 96})
.onHit('enemy', function() {
this._parent.color('red');
}, function() {
this._parent.color('gray');
});
var feet = Crafty
.e("2D, Collision, WiredHitBox, feet")
.attr({x:0, y: 96, w: 64, h: 32})
.onHit('enemy', function() {
this._parent.color('green');
}, function() {
this._parent.color('gray');
});
hero.attach(body);
hero.attach(feet);
Crafty.e("2D, DOM, Color, enemy")
.attr({x: 150, y: 96, w: 32, h: 32})
.color('brown');
<script src="https://github.com/craftyjs/Crafty/releases/download/0.7.1/crafty-min.js"></script>

Bitmap rotation in circular path CreateJS Tweenjs

I'm trying to rotate a bird in circular path but the problem is the to method doesn't give much control to do the exact thing, I 'm trying to move the bird head up or down with the rotation.
Here is my fiddle
http://jsfiddle.net/HF765/142/
var tween = createjs.Tween.get(shape, {loop: true})
.to({x: 100 , y: 100, rotation: 0}, 0)
.to({x: 200 , y: 200, rotation: 90}, 2000)
.to({x: 100 , y: 300, rotation: 180}, 2000)
.to({x: 0 , y: 200, rotation: 270}, 2000)
.to({x: 100 , y: 100, rotation: 360}, 2000)
I want to rotate it in a circle, any help will be greatly appreciated.
Thanks
The rotation seems to be working correctly in your example, but you are tweening the bird around a diamond shape (with straight paths), so it looks weird.
One easy way to get the effect you're looking for is to offset the bird's center point using regX and regY, and then rotate it. If you imagine the bird was cut out of a piece of paper, this is like attaching a stick pointing down from the center of it and rotating it using the stick. See an example here:
http://jsfiddle.net/HF765/143/
Another option is to look at the MotionGuidePlugin for TweenJS. It's more complicated to work with, but offers a lot of control, including the ability to have the target rotate along the path.
http://www.createjs.com/Docs/TweenJS/classes/MotionGuidePlugin.html

Best method for drawing a moving line JavaScript

I wish to have a line going across my canvas element in a similar fashion to the one I have managed to produce below after I had read up a little about the tween function:
http://jsfiddle.net/MjLdT/17/
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var line = new Kinetic.Line({
x: 100,
y: 100,
points: [0, 0, 0, 0],
stroke: '#000000'
});
layer.add(line);
stage.add(layer);
var tween = new Kinetic.Tween({
node: line,
duration: 3,
x: 800,
y: 100,
points: [-700, 0, 800, 0]
});
setTimeout(function () {
tween.play();
}, 2000);
Eventually I wish to have users be able to manipulate the line by clicking the left mouse button and the line goes up and to the right diagonally, right clicking and the line goes down diagonally (horizontal speed towards the right of the screen remains the same). Letting go of the mouse button will result in it returning to it's normal horizontal motion at whatever 'height' it is on the screen at that time.
This is one of my first attempts at using JavaScript and was wondering if the method I have chosen is appropriate for what I wish to achieve.
Also, any tips on how to get started on the mouse effects would be much appreciated.
The method is appropriate and it works, you should look into Kinetic.Animation which may give you slightly cleaner code. With an animation you can put more logic into the code that is being re-run. I believe tweens may be limited for what you are trying to do, it is possible but Animations are probably what you are looking for if you are aiming for a good design.
I would read through this documentation.
http://kineticjs.com/docs/Kinetic.Animation.html

KineticJS calling moveToTop() automatically after clicking over shape

I am with a little problem here but I don't know if it is a bug or a new feature since in the KineticJS change logs there is the following change:
"drag and drop operations now automatically dynamically create a temporary top layer, and place nodes there for groups and shapes to greatly improve drag and drop performance..."
I was used to use the version 4.0.0 in my test projects and I must use explicity moveToTop() when I want to move some shape to the top (I think that this is the correct way). Now (version 4.3.2) if I just click over some pic, it is automatically moved to the top against my wish. This temporary layer should be something internal, nothing visual. So is this really a bug or there is someway to turn this thing off.
Even the labs changed I think, before I think that the objects keeps the space order if you don't call the moveUp, moveToTop, etc, functions. For example in the following link there are no moveToTop() function calls, even this way if you click on the shapes, they are moved to the top.
http://www.html5canvastutorials.com/kineticjs/html5-canvas-move-shape-to-another-container-with-kineticjs/
Thanks for the attention
While I dont think you can completely disable the layer, you can turn off moving the shapes into it. Say you have some shape like:
var shape1 = new Kinetic.Rect({
x: 100,
y: 100,
width: 100,
height: 100,
fill: 'blue',
draggable: true
});
you need to add one parameter to this to disable moving your shape to the temporary layer on drag: 'dragOnTop' which needs to be false, so make your shapes something like:
var shape1 = new Kinetic.Rect({
x: 100,
y: 100,
width: 100,
height: 100,
fill: 'blue',
draggable: true,
dragOnTop: false //<-- add this line so that this shape doesn't use the drag layer.
});

How can I use scrollbars to pan around a virtual canvas?

I want to create a jQuery plugin that implements a virtual HTML5 Canvas, i.e. a canvas that is physically no larger (or not much larger) that its appearance on the page. But the contents of what is intended to be shown on the canvas may be many times larger that the canvas and will be dynamically redrawn on depending on scrollbars.
You would think that this is very common functionality, but so far i have not been able to find examples either with jQuery plugins or otherwise. This is very similar to what e.g. SlickGrid does for a Div, except this is with a Canvas. I can think of two solutions:
Use a jQuery UI Slider to implement a scrollbar as a completely separate element and use its event to control the Canvas redrawing.
Do whatever it is SlickGrid does for the Div. It appears to make a Div that is slightly larger than what is being displayed and the hook up to scroll events to dynamically add/remove element to/from the Div. But I can't see how it modifies the scrollbar to make it appear as if there is much more in the Div that what is currently being displayed.
What would you recommend? Sample code would be greatly appreciated.
I dug into the SlickGrid code and used method 2) (sort of) - it was something like this I had in mind:
/*
jensk#migselv.com
Simple virtual CANVAS controlled by a native scrollbar made with two DIVs
Uses jCanvas by Caleb Evans (http://calebevans.me/projects/jcanvas/index.php)
Thanks to Michael Leibman of SlickGrid fame for ideas.
Still need to clean it up (get rid of hardcoded values) and make it a nice, configurable
jQuery component.
Currently also redraws the entire canvas on each scroll event. Could be optimized to
do real browser scrolling and only redrawing the needed parts.
Another gotcha is that since it is the zero width DIVs that causes the scroll events,
mouse wheel, trackpad, touchscreen etc. scrolling over the Canvas will not work - only
the scrollbar is active. To solve this, one could make the Canvas larger inside a
smaller DIV too, catch scroll events from it and perform redrawing and setting the DIV's
scrollTop accordingly.
*/
var h = 10000; // virtual canvas height
var vp = 400; // viewport height
var viewport, fakescrolldiv, canvas;
function onScroll() {
var scrollTop = viewport.scrollTop();
console.log("onScroll scrollTop=" + scrollTop);
$("canvas").clearCanvas();
// Red box top
$("canvas").drawRect({
fillStyle: "#F00",
x: 150,
y: 20 - scrollTop,
width: 100,
height: 100,
fromCenter: false
});
// Green box middle
$("canvas").drawRect({
fillStyle: "#0F0",
x: 150,
y: 140 - scrollTop,
width: 100,
height: 100,
fromCenter: false
});
// Blue box bottom
$("canvas").drawRect({
fillStyle: "#00F",
x: 150,
y: 260 - scrollTop,
width: 100,
height: 100,
fromCenter: false
});
var i = 0;
for (i = 0; i <= 396; i++) {
$("canvas").drawLine({
strokeStyle: "#000",
strokeWidth: 1,
x1: 0,
y1: i,
x2: (scrollTop + i) % 50,
y2: i
});
if ((scrollTop + i) % 50 === 0) {
$("canvas").drawText({
fillStyle: "#729fcf",
text: (scrollTop + i).toString(),
align: "left",
baseline: "top",
font: "normal 12pt Verdana",
x: 60,
y: i
});
}
}
}
$(function() {
viewport = $("#viewport");
fakescrolldiv = $("#fakescrolldiv");
canvas = $("#gfx");
viewport.css("height", vp);
fakescrolldiv.css("height", h);
viewport.scroll(onScroll);
viewport.trigger("scroll");
});
Live demo
Any suggestions for improvements or simplifications are greatly appreciated.
From my personal experience your option (1) is an attractive choice, but there might be some interesting points in making it into a useable jQuery plugin.
I've been working on a financial data visualisation system that explicitly uses HTML5 Canvas for graph and chart drawing. We have different virtual 'scenes' or 'slides' in the canvas which 'slide in' and 'slide out' in the canvas, much like the same way you'd navigate in a big virtual canvas. All the event handling buttons are exclusively drawn on the canvas which dictate which screen we'd be showing, but we have a one/two normal HTML forms that take user inputs and brings those 'slides'. We use jQuery to handle events from these text boxes, but the jQuery codes are deeply nested inside the other Canvas drawing codes, (unlike an externalised call, which would be an idea candidate for making a plugin).
Sliding or updating the canvas is another thing. This is because not only it depends on the jQuery event that triggers the update but it also depends on the Canvas Framework (plain code or KineticJS, EaselJS, jCotton etc) that is responsible for the update. If you use a framework, you'll need to interface with the framework as well.
For simplicity let's assume that there is a callback function that you can call for that Canvas framework with parameters like movement offset (x, y), and the framework will add/remove this offset to the x and y positions of all the objects drawn in the canvas, most Canvas drawing frameworks also have a render() function that it calls periodically so that next time it draws the scene the results will automatically show (in your case, scrolling through the virtual canvas).
So it basically comes down to not only writing it as a jQuery plugin but also a binding it to a particular Canvas Framework e.g. KineticJS or others.
If you use basic Canvas functions instead of using any of those Frameworks, then it's another story, you can write your own render and update functions for the canvas, but in that case it'll be restricting the potential user to adhere the limitations of your drawing functions, unless you expose an API to extend them; but then again, that means you are writing your own Canvas framework :)
I'm not sure if I understood your problem correctly, in that case you can safely ignore my advice :), but If I'm right, my opinion would be: making a plugin like this would require also binding to a Canvas framework to make it really useable.
Hope it helps.

Categories

Resources