Cache SpriteSheets in EaselJS - javascript

How can I cache SpriteSheets in EaselJS? I have a Sprite object and when I use user.hero.cache(0, 0, 30, 40); it stops playing animation (probably because I'm just caching the current frame, not the entire SpriteSheet image). So how can I cache it?
Here's my relevant EaselJS code:
data = {
images: ["Graphics/hero.png"],
frames: {
width: 30,
height: 40
},
animations: {
stand: 0,
run: [1, 2, "runLoop", 0.15],
runLoop: [3, 7, true, 0.15],
jump: [8, 10, "happy", 0.5],
happy: 11,
fall: 12,
stopFalling: [13, 14, "stand", 0.2],
almostFalling: [16, 19, true, 0.1]
}
};
user.hero.spriteSheet = new createjs.SpriteSheet(data);
user.hero = new createjs.Sprite(user.hero.spriteSheet, "stand");
user.hero.name = "hero";
user.hero.x = user.hero.safeX = 40 * 3;
user.hero.y = user.hero.safeY = 0;
user.hero.offset = 4;
user.hero.regX = user.hero.offset + 2;
user.hero.regY = user.hero.offset;
user.hero.width = 30 - (user.hero.offset * 2) - 10;
user.hero.height = 40 - (user.hero.offset * 2);
user.hero.xvel = user.hero.yvel = 0;
user.hero.cache(0, 0, 30, 40); // <--- This is the problem.
movableObjContainer.addChild(user.hero);
movableObj.push(user.hero);
Without cache:
With cache:
I've tried caching the data.image or user.hero.spriteSheet too, without success.
Is there any way to cache the SpriteSheet without compromising its animations?

When you cache the sprite, you are saving off how it looks at that instant.
Can you explain why you want to cache it? The only reason I can think of to cache it would be to apply filters. Each time you cache it, the contents are drawn to an off-screen canvas, which is then drawn in place of it. This makes a lot of sense if you have complex content, like a container or graphics, which do not change, but with the spritesheet, it means you are creating a new bitmap to draw a bitmap. The spritesheet itself is a great way to be filesize, network, and GPU-optimzed, so re-caching it is basically negating all those benefits.
If you want to cache anyways, you will need to re-cache it, or call updateCache() every time it changes. Here is an example using the ticker.
createjs.Ticker.on("tick", function() {
user.hero.updateCache();
// or
user.hero.cache(0,0,30,40)
}, this);
Here is a quick demo I did a while back using a few approaches for filters. It provides an example of constant re-caching, as well as an example where the entire spritesheet is cached to apply the filter once, and then that cached version is used for the sprite.
http://jsfiddle.net/lannymcnie/NRH5X/

Related

Tilemap collides with player and moves as one solid object (Phaser 3)

I have a tilemap that I'm generating from an array, (I can't use tiled, the game will be procedurally generated) that I need to collide with the player, but instead of the player colliding with the wall layer, when the player goes outside of the camera bounds and the tilemap and comes back in, they push the tilemap off the screen. My tilemap code is here, simplified. I'm guessing I need to be able to add blank tiles, but I'm not sure how.
var room = [
[1, 2, 2, 3],
[4, 0, 0, 8],
[4, 0, 0, 8],
[5, 6, 6, 7],];
this.map = this.make.tilemap({ data: room, tileWidth: 64, tileHeight: 64 });
var tiles = this.map.addTilesetImage("wall");
var layer = this.map.createLayer('wallLayer', tiles, 0, 0)
layer.setCollisionBetween(1, 8, true, true, layer)
this.physics.add.existing(layer)
this.physics.add.collider(layer, this.player)
Any help would be great, thanks!
The problem is, that you are adding the layer to the physics world with the line of code
this.physics.add.existing(layer);
in the file camp.js line 126
This is not needed! Since the two lines of code,
layer.setCollisionBetween(1, 16, true, false, layer); //(line 125)
this.physics.add.collider(layer, this.player); //(line 127)
in the file camp.js
set the collisions up between player and layer. No other action is needed to achieve collisions.

Drawing Lines on a Canvas from a For-Loop in Typescript doesnt render

I was making a graphing utility for fun, and then it turned into a real project...
I was trying to achieve a very simple graph... a line graph.
However, using a for-loop inside of my typescript project yields no results.
Look in the source code below, you can see I have console logs where I need to confirm an action is occuring. All of them run fine and in the perfect order in my typescript project.
Since SO doesnt support typescript, heres a codepen with the full source and typescript compiler: https://codepen.io/SkylerSpark/pen/zYvpWNZ
Snippet causing me the issues:
g.px & g.py are my coordinates. They are grabbed from this array (its an example array of pizza sales):
const pizzas = {
x: [0, 5, 10, 15, 20, 25, 30, 35, 40],
y: [0, 1, 2, 3, 4],
px: [0, 5.2, 7, 20.9, 34.3, 39.5],
py: [0, 1.1, 1.3, 2.7, 3.5, 3.9]
};
// Draw Numbers
if (g.px.length == g.py.length) {
console.log("confirm");
for (var i = 1; i < g.px.length + 1; i++) {
if (i == 1) {
console.log("start");
ctx.beginPath();
ctx.moveTo(g.px[i], g.py[i]);
} else if (i < g.px.length) {
console.log("continue");
ctx.lineTo(g.px[i], g.py[i]);
} else {
console.log("draw");
ctx.stroke();
}
console.log(i);
}
}
Now see the picture below, its running fine:
The problem is that your y-values need to be negative. In situations like these it's often useful to just draw any line instead of immediately using loops. I found this out by adding the following code
ctx.beginPath();
ctx.moveTo(-40, -40);
ctx.lineTo(40, -40);
ctx.lineTo(40, 40);
ctx.lineTo(-40, 40);
ctx.stroke();
just before you start drawing the line, which actually shows some results. If I change g.py[i] to -g.py[i] everywhere, then a small line is added to the bottom left of the graph. Hope this helps!

Surrounding 3d sound effects using howler.js or another library?

I'm working on a project and I need to add 3d sounds effects, like the sound is continually moving around the listener effects. Is it possible to achieve that with howlerjs i see that with howler i'm able to play a sound from specific coordinates/orientation but how to achieve surrounding/ambisonics sounds ?
Or another library in JavaScript to achieve that?
Thanks for your help.
Half a year late, but yeah that's entirely possible in howler.js, haven't used it myself but judging from the docs you can just update the position. there's some more libraries that do it that I've found, check here how 3dage does exactly what you want:
https://codepen.io/naugtur/pen/QgmvOB?editors=1010
var world = IIIdage.World({
tickInterval: 200
})
var annoyingFly = IIIdage.Thing({
is: ['fly'],
sounds: {
'buzzing constantly': {
sound: 'buzz',
times: Infinity
}
},
reacts: [
{
// to: world.random.veryOften(),
to: world.time.once(),
with: 'buzzing constantly'
}
]
})
// scene should create and expose a default world or accept one
var scene = IIIdage.Scene({
title: 'Annoying fly',
library: {
sounds: {
'buzz': {
src: ['https://webaudiogaming.github.io/3dage/fly.mp3']
}
}
},
world: world,
things: [ // scene iterates all things and spawns them into the world. same can be done manually later on.
annoyingFly({
pos: [-1, -15, 0],
dir: [1, 0, 0],
v: 1
})
]
}).load().run()
setTimeout(function () {
scene.dev.trace(IIIdage.dev.preview.dom())
}, 500)
setInterval(function rotateVector() {
var angleRad = 0.15
var d=scene.things[0].attributes.dir
var x=d[0], y=d[1]
var cosAngle = Math.cos(angleRad), sinAngle = Math.sin(angleRad)
scene.things[0].attributes.dir = [x * cosAngle - y * sinAngle, y * cosAngle + x * sinAngle, 0]
}, 500)
window.scene = scene
There's still some others that do similar stuff:
https://www.npmjs.com/package/songbird-audio
https://www.npmjs.com/package/ambisonics
Hope this pushes you in the right direction if you still want help with it.

Updating candlestick data point using restyle in Plotly.js

I am using a WebSocket connection to update a candlestick chart with live data.
Creating the initial candlestick chart is relatively easy:
var candleDiv = document.getElementById('candle-chart');
var data = {
x: x, //Each of these is a single dimension array of the same length
open: open,
close: close,
high: high,
low: low,
type: 'candlestick',
};
var layout = {
datarevision: candleCount,
dragmode: 'zoom',
showlegend: false,
xaxis: {
type: 'date',
range: [x[x.length - 26], x[x.length - 1]], //Only show the last 25 entries so it's not zoomed out too far.
rangeslider: {
visible: false
},
yaxis: {
autorange: true,
}
}
}
data.xaxis = 'x';
data.yaxis = 'y';
data = [data];
Plotly.plot(candleDiv, data, layout);
However, the documentation for the restyle method doesn't talk much to the update of data. More about how the data is displayed. After much tinkering, I found a reasonable workaround of updating the data variable directly:
candleDiv.data[0].open[candleDiv.data[0].open.length - 1] = updatedOpenValue;
candleDiv.data[0].close[candleDiv.data[0].close.length - 1] = updatedCloseValue;
candleDiv.data[0].high[candleDiv.data[0].high.length - 1] = updatedHighValue;
candleDiv.data[0].low[candleDiv.data[0].low.length - 1] = updatedLowValue;
Plotly.restyle(candleDiv, 'data[0]', candleDiv.data[0], [0]);
This works, except that it appears to draw the new candle on the old candle. This becomes particularly distracting when the stick changes from a green (increasing) stick to a red (decreasing) stick.
Is there a correct syntax to achieve what I am attempting to do such that I don't get display issues?
I checked out this link from this post but I couldn't get the method used to work in the context of a candlestick chart.
You may want to look at the Plotly.react method instead of Plotly.restyle: https://plot.ly/javascript/plotlyjs-function-reference/#plotlyreact

Setting size: Modifier vs Surface

What is the difference between setting size on a modifier vs setting the size on the surface itself?
It is my understanding that an individual surface is laid out based on the composition of modifiers it has been added to. Do the (state)modifiers only relate to position and not size?
Why doesn't the following code restrict the size of the surface to 50x50 instead of rendering the 100x100 square? (When is it appropriate to set the size on a Modifier?)
var stateModifier = new StateModifier({
size: [50, 50],
transform: Transform.translate(50, 100, 0)
});
var surface = new Surface({
size: [100, 100],
properties: {
backgroundColor: '#FA5C4F'
}
});
mainContext.add(stateModifier).add(surface);
Thanks,
JD
http://famo.us/university/lessons/#/famous-101/positioning/2
Simply put, the surface gets an attitude when you set a size and it will tell a modifier to kiss its ass. The only way to make a surface respect a modifier is by setting the size to [undefined, undefined] (or just undefined), as it will then use the modifier's size.
Essentially, the engine gets the size the modifier provides and sets it as the current size for following components to be rendered with. However, your surface defines a new size, and thus the engine is going to use that size, but only for that surface.
TLDR: to restrict, don't give the surface a size
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var StateModifier = require('famous/modifiers/StateModifier');
var mainContext = Engine.createContext();
var stateModifier = new StateModifier({
size: [100, 100],
transform: Transform.translate(150, 100, 0)
});
var surface = new Surface({
properties: {
backgroundColor: '#FA5C4F'
}
});
mainContext.add(stateModifier).add(surface);
This would output the exact same in this case, but if you give the modifier any more children, they will also be affected by the size.

Categories