custom point to point path with bezier curve animation - javascript

I wanna create a moving car object that animates from point-A to point-B, point-B to point-C, and point-C to point-D. I'm using the "jQuery.Path.js" with bezier curve function but it only has 2 points to setup (start & end). How can I add 2 more points in between?? please help!
here's the original js page: JQUERY PATH BEZIER CURVE GENERATOR
<script type="text/javascript" src="js/jquery.path.js"></script>
<script type="text/javascript">
function animate(){
var path = {
start: {
x: 1200,
y: 445,
},
second: {
x: 890,
y: 520,
},
third: {
x: 650,
y: 600,
angle: 20,
length: 0.2
},
end: {
x: -100,
y: 470,
}
};
$('.car').animate(
{
path : new $.path.bezier(path)
},
20000,
animate
);
}
animate();
</script>

Related

Phaser groups moving each child independantly

so i have a phaser group
this.cows = this.physics.add.group({
key: "cow",
repeat: 2,
setXY: { x: 160, y: 1500, stepX: 32 },
});
this.cows.children.iterate(function (child) {
child.setSize(20, 10, true);
child.setBounceY(Phaser.Math.FloatBetween(0.2, 0.4));
});
I plan to update the movement of every child in the update function, so how would i make sure every child has a different amount of movement in a different direction?
Depending on your use case you could simply use, a property destination which the child wants to reach, and when it is reached, just set a new destination.
Here a short demo showcaing this:
(it uses Vector's, not everybody likes/understtands them, but they are concise)
document.body.style = 'margin:0;';
var config = {
type: Phaser.AUTO,
width: 536,
height: 183,
physics: {
default: 'arcade',
arcade: {
debug: true
}
},
scene: {
create,
update
},
banner: false
};
function create () {
this.add.text(10,10, 'Random Movment')
.setOrigin(0)
.setStyle({fontStyle: 'bold', fontFamily: 'Arial'});
let graphics = this.make.graphics();
graphics.fillStyle(0xffffff);
graphics.fillRect(0, 0, 10, 10);
graphics.generateTexture('cow', 10, 10);
this.cows = this.physics.add.group({
key: "cow",
repeat: 2,
setXY: { x: 50, y: 50, stepX: 32 },
});
this.cows.children.iterate(function (child) {
child.setSize(10, 10, true);
child.setBounceY(Phaser.Math.FloatBetween(0.2, 0.4));
child.speed = Phaser.Math.Between(30, 50);
child.destination = { x: child.x , y: child.y};
});
}
function update(){
this.cows.children.iterate(function (child) {
if(Phaser.Math.Distance.BetweenPoints(child.body.position, child.destination) <= 20){
//new destination
child.destination = { x:Phaser.Math.Between(50, 200), y:Phaser.Math.Between(50, 150)};
// Setup velocity
let vector = new Phaser.Math.Vector2(child.destination);
vector.subtract(child.body.position)
.setLength(child.speed);
child.setVelocity(vector.x, vector.y);
}
});
}
new Phaser.Game(config);
<script src="//cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>

Timed particle emitters in Phaser 3

I'm adding a blood effect for when enemies are hit in my game and I want to be able to specify how long the particle emitter will emit particles for, but the lifespan property when creating a particle emitter is the lifespan of the particles, not the emitter. Is there something like this, or another way? I could set it to off after a minute but I'm not sure how a ton of inactive particle emitters would affect performance.
this.add.particles({
//particle stuff
emitterLifespan: 1000
})
Any suggestions? Thanks!
tldr; ("easy" solution simply use setTimeout(() => emiter.stop(), 1000) , to stop the emitter. In the demo below, it is the last/yellow emitter)
I don't know of any such property, and is also not mentioned in the documentation (or the unofficial more hands on documentation)
I had the same problem, since the particles work abit odd, I think.
It seems you must balance the properies carefully. For the basic scenario, (seen below), the following properties could cause a problem:
lifespan lifespan of emitted particles
maxParticles hard limit of particles
frequency milliseconds for emit cycle
I noticed if the particles "die" before it reaches maxParticles, the emitter won't "stop".
You could configer the properties, so that the emitter stop when it reaches the max ( the red particles in the example), or you could use the setTimeout function to stop it, after some time(like the yellow particles). Green and blue just show how different values won't stop the emitter. (due to the random part, and depending on the performance of the browser/pc, this might run forever or stop. On my CellPhone the blue emitter stops, but the green ones don't. And on my PC green and blue run for "ever")
document.body.style = 'margin:0;';
var config = {
type: Phaser.AUTO,
width: 536,
height: 183,
physics: {
default: 'arcade',
arcade: {
gravity:{ y: 100 },
debug: true
}
},
scene: {
create
},
banner: false
};
function create () {
this.add.text(10,10, 'Click to Create Blood').setOrigin(0);
let g = this.make.graphics({add:false});
g.fillStyle(0xffffff)
g.fillCircle(4,4,4);
g.generateTexture('blood', 8, 8)
let particles = this.add.particles('blood');
this.input.on('pointerdown', p => {
particles.createEmitter({
tint: 0xff0000,
alpha: { start: 1, end: 0 },
scale: { start: 0.5, end: 1.5 },
speed: {random: [20, 100] },
accelerationY: {random: [-100, 200] },
rotate: { min: -180, max: 180 },
lifespan: { min: 300, max: 800 },
frequency: 20,
maxParticles: 10,
x: p.x,
y: p.y
});
particles.createEmitter({
alpha: { start: 1, end: 0 },
tint: 0x00ff00,
scale: { start: 0.5, end: 1.5 },
speed: {random: [20, 100] },
accelerationY: {random: [-100, 200] },
rotate: { min: -180, max: 180 },
lifespan: { min: 300, max: 800 },
frequency: 120,
maxParticles: 10,
x: p.x + 100,
y: p.y
});
particles.createEmitter({
alpha: { start: 1, end: 0 },
tint: 0x0000ff,
scale: { start: 0.5, end: 1.5 },
speed: {random: [20, 100] },
accelerationY: {random: [-100, 200] },
rotate: { min: -180, max: 180 },
lifespan: { min: 200, max: 300 },
frequency: 10,
maxParticles: 20,
x: p.x + 200,
y: p.y
});
let emitter = particles.createEmitter({
alpha: { start: 1, end: 0 },
tint: 0xffff00,
scale: { start: 0.5, end: 1.5 },
speed: {random: [20, 100] },
accelerationY: {random: [-100, 200] },
rotate: { min: -180, max: 180 },
lifespan: { min: 200, max: 300 },
frequency: 10,
maxParticles: 20,
x: p.x + 300,
y: p.y
});
// Stop after 1000 ms
setTimeout(()=> emitter.stop(), 1000);
});
}
new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
btw.: you could also use the explode function if all particles should be emitted at once, checkout this official example, and here the link to the documenation.

Bug report: Wrong position of the UIElement / ChartMarkerXY when first rendering a chart with animation disabled

I've tried to place an UIElement / ChartMarkerXY on a chart where the animations are disabled.
Unfortunately, the UIElement / ChartMarkerXY was not in the right position on the first render.
However, when we do an another render (eg: when you put the mouse on the chart for show the AutoCursor), it has been moved to the right position.
I noticed that when the animations are enabled, the first frame of the animation put the UIElement / ChartMarkerXY at the same position.
Currently, I have a workaround for prevent this: chart.engine.renderFrame(0,0)
Demonstration of the bug
You can find in the snippet an example that reproduce the bug:
const {
AxisPosition,
AxisTickStrategies,
emptyLine,
lightningChart,
Point,
UIElementBuilders,
emptyFill
} = lcjs;
const dataSeries = [
{ x: -5, y: 0 },
{ x: 2, y: -5 },
{ x: 5, y: 6 },
{ x: 8, y: 12 },
{ x: 12, y: -12 }
];
const chart = lightningChart().ChartXY({
container: 'chart',
});
chart.setAnimationsEnabled(false);
chart.addLineSeries().add(dataSeries);
chart.addUIElement(UIElementBuilders.TextBox, {
x: chart.getDefaultAxisX(),
y: chart.getDefaultAxisY()
})
.setText('My Text')
.setPosition({ x: 0, y: 0 });
.lcCanvas {
width: 500px;
height: 300px;
}
<script src="https://unpkg.com/#arction/lcjs#3.1.0/dist/lcjs.iife.js"></script>
<h2>Example of the bug</h2>
<div id="chart" class="lcCanvas"></div>
Bug reports should be sent to support#lightningchart.com instead of posting here.
-- Snekw
Bug report sent.
Currently, the workaround I found is chart.engine.renderFrame(0,0).
This will force the re-render of the chart, and put the marker at the right position.
Here, a snippet of how implement the workaround.
const {
AxisPosition,
AxisTickStrategies,
emptyLine,
lightningChart,
Point,
UIElementBuilders,
emptyFill
} = lcjs;
const dataSeries = [
{ x: -5, y: 0 },
{ x: 2, y: -5 },
{ x: 5, y: 6 },
{ x: 8, y: 12 },
{ x: 12, y: -12 }
];
const chart = lightningChart().ChartXY({
container: 'chart',
});
chart.setAnimationsEnabled(false);
chart.addLineSeries().add(dataSeries);
chart.addUIElement(UIElementBuilders.TextBox, {
x: chart.getDefaultAxisX(),
y: chart.getDefaultAxisY()
})
.setText('My Text')
.setPosition({ x: 0, y: 0 });
chart.engine.renderFrame(0, 0); // Workaround: Add this for force the re-render
.lcCanvas {
width: 500px;
height: 300px;
}
<script src="https://unpkg.com/#arction/lcjs#3.1.0/dist/lcjs.iife.js"></script>
<h2>Workaround</h2>
<div id="chart" class="lcCanvas"></div>

How should I place an object using Matter.Object.create in matter.js?

I'm using matter.js and I have vertex data for objects with absolute positions (from SVG files). When I try to place them on the map, they all end up positioned around 0, 0. This is easily observable with this code snippet:
<body>
<script src="matter-0.8.0.js"></script>
<script>
var engine = Matter.Engine.create(document.body);
var object = Matter.Body.create(
{
vertices: [ { x: 300, y: 300 }, { x: 200, y: 300 }, { x: 350, y: 200 } ],
isStatic: true
});
Matter.World.add(engine.world, [object]);
Matter.Engine.run(engine);
</script>
</body>
Or just look at this jsfiddle: https://jsfiddle.net/vr213z4u/
How is this positioning supposed to work? Do I need to normalize the absolute position data into relative positions and use the position attribute of the options sent to Matter.Object.create? I tried that, but all objects got a little displaced, probably due to my lack of understanding.
Update/clarification:
My goal is that the vertices of the created object end up on exactly on the coordinates they have in the source data.
At body creation the vertices are re-orientated about their center of mass and then translated to the given body.position. As you've not passed a position vector here this just defaults to (0, 0).
Try something like this:
var body = Matter.Body.create({
position: { x: 500, y: 500 },
vertices: [{ x: 300, y: 300 }, { x: 200, y: 300 }, { x: 350, y: 200 }],
isStatic: true
});
If you want the position to be absolute:
var vertices = [{ x: 300, y: 300 }, { x: 200, y: 300 }, { x: 350, y: 200 }];
var body = Matter.Body.create({
position: Matter.Vertices.centre(vertices),
vertices: vertices,
isStatic: true
});

prevent looping in kineticjs sprite animation

I'm developing a board game with kineticjs, where a pice is animated simultaneously in 2 ways:
1 - animate with a tween the x and y coordinates, from place a to b. i do this without a problem, getting input from user.
2 - in a sprite, we should see the piece being lift up (frames 0 > 4), and staying up during the previous animation, and in the end of it, it animates from 4 to 8, and goes back goes to the initial idle state
So far I have this:
var animations = {
idle: [{x: 0, y: 0, width: 100, height: 100}],
up: [{x: 0, y: 0, width: 100, height: 100},
{x: 100, y: 0, width: 100, height: 100},
{x: 200, y: 0, width: 100, height: 100},
{x: 300, y: 0, width: 100, height: 100}],
down: [{x: 400, y: 0, width: 100, height: 100},
{x: 500, y: 0, width: 100, height: 100},
{x: 600, y: 0, width: 100, height: 100},
{x: 700, y: 0, width: 100, height: 100}]
};
/* coordinates_js is an array of the possible x and y coordinates for the player. like this, the player is created in the first coordinate, the starting point
*/
var player = new Kinetic.Sprite({
x: coordinates_js[0].x,
y: coordinates_js[0].y,
image: imageObj,
animation: 'idle',
animations: animations,
frameRate: 7,
index: 0,
scale: 0.4,
id: "player"
});
imageObj.onload = function() {
var targetx = null;
var targety = null;
var targetIndex = null;
var playerIndex = 0;
document.getElementById('enviar').addEventListener('click', function() {
targetIndex = document.getElementById("targetIndex").value;
var destino = coordinates_js[targetIndex];
var tween = new Kinetic.Tween({
node: player,
x: destino.x,
y: destino.y,
rotation: 0,
duration: 5
}).play();
console.log("x: " + destino.x + "y: " + destino.y)
playerIndex = targetIndex;
tween.play();
player.setAnimation("up");
player.afterFrame(3, function(){
console.log("idle")
player.setAnimation("idle");
})
}, false);
playLayer.add(player);
stage.add(playLayer);
player.start();
}
the proble here is that the sprite animation plays from 1 to 4 and goes to idle; i neet it to stay up until the end of the tween. i could have:
player.setAnimation("up");
player.afterFrame(3, function(){
console.log("idle")
player.setAnimation("idle");
})
this lifts up the piece, but wont let it drop. So, how can i do like in flash gotoAndPlay("up") to start, and in the end of the tween gotoAndStop("idle").
many thanks to you all
Have you seen the onFinish event for tweens?
http://www.html5canvastutorials.com/kineticjs/html5-canvas-transition-callback-with-kineticjs/
You could do something like this:
var tween = new Kinetic.Tween({
node: player,
x: destino.x,
y: destino.y,
rotation: 0,
duration: 5,
onFinish: function() {
player.setAnimation("idle"); //When tween finishes, go back to "idle" animation
}
}).play(); //Play the Tween
player.setAnimation("up"); //Start the "up" animation for the sprite

Categories