Can a easeljs hitarea be set using image data? - javascript

I'd like to be able to set set the hit area of my Display objects using image data instead of a Shape object. However setting the hitarea property of my objects doesn't seem to be working. Here's an example of what I'm attempting.
Say we have this sprite sheet for a button:
example of sprite sheet button with 3 frames. frame 3 is a hitmask
(Sorry my rep. isn't high enough to just post the image)
I have a function to get my hitmask frame and make it into a bitmap this isn't working.
/* Not the exact code, syntax may be a bit off */
var myButton = new createjs.Container() // assume this is an object with mouse events
var myExtractedFrame = ExtractFrame(myButton._sprite, 2) // a createjs Bitmap of frame the hitmask frame
myButton.hitArea = myExtractedFrame // will this work??

Yes, this should work. The hitArea property supports the use of any display object.
Without seeing more code, it's difficult to guess what you're doing wrong, so here is an example of it working correctly with Sprite instances (which is likely a more efficient approach than extracting frames into Bitmap instances): http://jsfiddle.net/6L5esy6v/

Related

How would I go about making a variable that allows me to toggle an object's visibility in Javascript

I am using the p5.js library to create Tetris. When someone gets a line clear (that is, a full line has been filled with Tetris blocks) then the tiles that made that line fill up should be removed/turned off.
What would be the best way to do this? For all visibility aspects of a tile, I use a show() function that draws a rectangle to show the tile. Should I add a variable to the object and check if that is true because executing the show function? Or is there a built-in method or function that makes removing an object easy? I can't seem to find anything like this online
It is hard to answer if we do not know how your tiles are represented in your program.
The method I recommend is to remove the tile from it's container structure altogether.
For example, if the state of your game is stored in a matrix, simply empty the cells that constitute a line. This way, your show() function should not be called at all.
Removing the tile from the container will work, but if its difficult then there is another way.
Have a variable to track whether the tile is being used and have its default be true e.g this.inPlay = true
Only update and show a tile if its inplay is true:
if (tile.inPlay == true) {
tile.update()
tile.show()
}
'''
If you want to remove it, just set its inplay to false
PS. a great tutorial for p5.js is on youtube (made by the coding train)
PPS. just search 'coding train p5.js tutorial' on youtube

Turn canvas objects into createjs elements

Apologies if this has been answered before, I think I maybe searching for the wrong keywords.
I have an element rendered on the canvas from another library.
Every time stage.update() gets called all my createJS elements get rendered on top.
The element however needs to sit between different createjs objects.
So either I need to find a way to turn this element into a createJs DisplayElement to put it in the correct index position.
Or I need to update just a Container and not the whole stage.
Can someone point me into the right direction?
Thanks
The best approach for this is to render your non-EaselJS content onto another Canvas, and then use it as the source for a Bitmap.
// Non-EaselJS content (whatever you can imagine!)
var canvas1 = document.getElementById("non-easel-canvas");
var context = canvas1.getContext("2d");
context.doStuffWithCanvasAPIs();
// EaselJS content (red background, blue circle)
var stage = new createjs.Stage("easel-canvas");
var bottom = new createjs.Shape();
bottom.graphics.beginFill("red").drawRect(0,0,800,600);
var top = new createjs.Shape();
top.graphics.beginFill("blue").drawCircle(0,0,25);
top.x = top.y = 100;
// Non-easel content added to Easel
var bmp = new createjs.Bitmap(canvas1);
stage.addChild(bottom, bmp, top);
stage.update();
Hope that makes sense. You can also the reverse, and draw the EaselJS content into a non-EaselJS stage using drawImage, and passing the EaselJS canvas as the source. This is how you can mix EaselJS content into things like three.js.
Note that you can also draw any EaselJS content directly without a stage. Each display object (including Container) has a draw() method, which you can call, which draws the object into a supplied context.
http://www.createjs.com/docs/easeljs/classes/DisplayObject.html#method_draw
Cheers,
You have two options here:
Do not use the other library at all, but EaselJS only.
...or...
Use multiple canvases.
Since you need to stack this graphics object in between two easeljs objects, you would need three canvases to accomplish what you're trying to do, and two easeljs stages. Still, this is a hacky workaround for a weird problem.

cesium - moving billboards

I am testing Cesiumjs to see if it can reflect a near-real-time expreience - for example: position of airplanes.
For that, I need to draw billboards and make them move - which I know is possible with cesium, just not sure how.
The code looks like this:
var billboards = scene.primitives.add(new Cesium.BillboardCollection());
var billboard = {
image : '/path/to/logo.png',
position : Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883)
};
billboards.add(billboard);
My question is how do I change the position of the billboard. I couldn't find ant documentation that would explain.
I thought doing:
billboard.position = ... //new position
but how will cesium know that I've changed the position attribute unless it somehow turns that reference into a observable object.
So how do I update the location?
Thanks.
Cesium does indeed listen for changes to billboard.position
(source code here), so it is correct behavior for apps to simply write a new position.
Note that you must write the whole position at once, meaning you may not write to billboard.position.x. Instead, keep a "scratch" Cartesian3 around (don't create a new one every animation frame at 60fps), write to the x,y,z properties of your scratch variable, and then assign your scratch variable to billboard.position. You can see in the source that the assigned value will be cloned into another pre-existing Cartesian3, so you may immediately reuse the scratch variable.
Here's an example:
// Just once at app startup. Don't call "new" at 60fps.
var scratchCartesian3 = new Cesium.Cartesian3();
var ellipsoid = viewer.scene.mapProjection.ellipsoid;
function onTick() {
// This is safe to call at 60fps.
billboard.position = Cesium.Cartesian3.fromDegrees(
lon, lat, alt, ellipsoid, scratchCartesian3);
}
Also note that your question and the above answer are focused on the "Graphics Primitive" layer of the Cesium API. Cesium has one higher layer, called the "Entity" API, that you can use if you want Cesium to handle the concept of user-selectable objects with pop-up descriptions etc. Here's a Sandcastle demo showing how to add a billboard as a property of an entity, instead of as a primitive. This allows you to add other properties to the same entity, for example a name, description, label, 3D model, etc, and have them all be controlled from the same position property, and have Cesium take care of popup descriptions. The position property is more complex for entities than for primitives, for example it can be constant or sampled. This allows entities to change position over time when the timeline is shown.

Javascript/Canvas - Create new images from preexisting ones?

I'm wondering if there's a way to take existing images and "stack" them to create a single asset in Javascript.
http://imgur.com/a/ajkBh
The above image album shows what I'd like to do.
Basically, for the game I'm making, I want to procedurally generate enemy NPC's and the like, drawing from a pool of different body parts. Each potential body part would have stats and a spritesheet attached to it, so when the character is randomly generated, I want to stack all of the necessary images together into a single asset that I can then use.
Is there any way to do this?
Canvas is a very basic drawing API with the ability to draw a few basic shapes, strokes and fills. Other than filling with the background color, and/or clearing the whole canvas, there's no way to animate scenes with "sprites" or any complete objects sitting on top of each other, using only the basic canvas API. Copying images in is possible, but then you need to clear them every single frame and replace them, which is a lot of code overhead, if you want them to animate.
You should look into http://createjs.com or a similar "screen graph" type framework, something that sits on top of the canvas and lets you easily load up sprite sheets and move them around. It does the drawing, clearing, rotation, animation etc. of the canvas for you (basically making it a bit like Flash).
In terms of purely stacking or drawing on the canvas, yes you can grab an image and copy it directly onto the canvas using the context2d.drawImage method, but this is probably not going to achieve the effect you want by itself.
You can build up your animation out of existing parts, if think the main issue is organizing the base artworks and having the drawing done to fit one with another.
Let's say :
You want an idle (line 1), walk (line 2), run (line 3)
on each line you have a constant number of frames, say 5.
Say also that your parts are : legs, body, arms, head.
Then you have to build the image by yourself, by stacking those images :
function buildAnimation(legs, body, arms, head) {
var resImg = document.createElement('canvas');
resImg.width = legs.width; resImg.height = legs.height;
var resCtx = resImg.getContext('2d');
resCtx.drawImage(legs,0,0);
resCtx.drawImage(body,0,0);
resCtx.drawImage(arms,0,0);
resCtx.drawImage(head,0,0);
return resImg;
}
then you can feed your game framework with this image, that will be used for an
animation.
The drawback of this method is that you have to draw all animations of all parts
at the same places each time.
Issues :
1) for the head for instance, you might not want to animate it.
2) you might want different height for different characters.
3) it's a lot of work !!
So you might decide of conventions to know where the parts should be drawn, and have
less part to prepare in an image, but a more complex way to build them.
Short example : the file name of the image parts ends with their height, so you can retrieve them
easily. (bodyMonster48.png, bodyHead12.png, ...)
Writing everything would be too much work here, but just a short example :
say we have animWidth, animHeight the size of each anim, and five frames in each
of the 3 anims. Now we just have one head that we want to copy everywhere :
function buildAnimation(animWidth, animHeight, legs, body, arms, head) {
var resImg = document.createElement('canvas');
resImg.width = legs.width; resImg.height = legs.height;
var resCtx = resImg.getContext('2d');
resCtx.drawImage(legs,0,0);
resCtx.drawImage(body,0,0);
resCtx.drawImage(arms,0,0);
// copy the head in all frames of all anims
for (var animLine=0; animLine<3; animLine++) { // iterate in idle, walk, run
for (var animFrame= 0; animFrame<5; animFrame++) { // iterate in images of the animation
resCtx.drawImage(head, animFrame*animWidth, animLine*animHeight);
}
}
return resImg;
}
To be able to build any combination with variable height, you'll
have to carefully parametrize everything, use file naming and positioning conventions,
and you'll surely need a whole helper class not to get lost in all combinations.

GLGE API setRot/setRotX doesn't work

I'm trying to make a little scene for viewing 3D models.
I modified the GLGE Collada example to add a .dae model from code.
http://goleztrol.nl/SO/GLGE/01/
What I've got
So far it works. The camera is rotated using an animation.
Using the buttons 'Add' and 'Remove' the model is added and removed from the scene, using the following code (Don't mind 'duck'. It was a duck in the original example.)
var duck = null;
function addDuck()
{
if (duck) return;
duck = new GLGE.Collada();
doc.getElement("mainscene").addCollada(duck);
duck.setId("duck");
duck.setDocument("amyrose.dae");
duck.setLocY(-15);
duck.setRotX(1);
duck.setScale(2);
}
function removeDuck()
{
if (!duck) return;
doc.getElement("mainscene").removeChild(duck);
duck = null;
}
Problem
Now the model is lying down, while it should stand up. The various methods of the element seem to work. The location is set, and the scale is set, but the call to setRotX seems to be ignored. I tried various others methods from the api, but setRotY, setRot, setQuatX and setDRotX all seem to fail. I don't get any errors (well not about this method). I tried values of 1.57 (which should be about 90 degrees), but other values as well, ranging from 1 to 180.
I can't find out what I'm doing wrong. Of course I could rotate the model itself in Blender, but I'd like to do it using the GLGE API.
Update
When I load the demo-model, seymourplane_triangulate.dae, the rotation works. Apparently my model differs in that it cannot be rotated. I just don't understand why. I figured it may be because the model is built of various separate meshes, but I don't understand why scaling and moving does work.
Does anyone know what's wrong with this model, and what I could do to fix it (maybe using Blender)?
Setting an initial rotation in the XML file that contains the scene does work. Setting rotation on another element (like the whole scene) works as well.
You need to rotate it after it has been loaded.
You can do this in the callback to setDocument
duck.setDocument("amyrose.dae", null, function() {
duck.setLocY(-15);
duck.setScale(2);
duck.setRotX(0);
duck.setRotY(0);
duck.setRotZ(3);
});

Categories