Hello im trying to find a way to get the snap property of draggable for Greensock to work without throwprops or livesnap. I would like when you let go of the '.face' for it to snap to the closest spot. It works with livesnap but I don't want to have the jagged dragging of it.
Here is what i'm working with at the moment:
var droppables = $('.face');
var choice = $('.choice');
var gridWidth = 192;
var gridHeight = 256;
var overlapThreshold = '50%';
function onDrop(dragged, dropped) {
TweenMax.fromTo(dropped, 0.2, {opacity:1}, {opacity:0.5, repeat:1, yoyo:true});
}
Draggable.create(droppables, {
type:'x,y',
bounds:$('.content'),
liveSnap:true,
snap: {
x: function(endValue) {
return Math.round(endValue / gridWidth) * gridWidth;
},
y: function(endValue) {
return Math.round(endValue / gridHeight) * gridHeight;
}
},
onDrag: function(e) {
var i = droppables.length;
while (--i > -1) {
if (this.hitTest(choice[i], overlapThreshold)) {
$(droppables[i]).addClass('highlight');
} else {
$(droppables[i]).removeClass('highlight');
}
}
},
onDragEnd:function(e) {
var i = droppables.length;
while (--i > -1) {
if (this.hitTest(choice[i], overlapThreshold)) {
onDrop(this.target, choice[i]);
}
}
Any help would be great.
What you can do is change your conditional logic in the onDragEnd callback and remove everything related to the snap event.
Draggable.create(droppables, {
type:'x,y',
bounds:$('.content'),
onDrag: function(e) {
var i = droppables.length;
for(var j = 0; j < i; j++) {
if (this.hitTest(choice[j], overlapThreshold)) {
$(droppables[j]).addClass('highlight');
} else {
$(droppables[j]).removeClass('highlight');
}
}
},
onDragEnd:function(e) {
var i = droppables.length,
snappedEl = false,
originalOffset = $(this.target).offset();
for(var j = 0; j < i; j++) {
if (this.hitTest(choice[i], overlapThreshold)) {
var targetOffset = $(choice[j]).offset();
onDrop(this.target, choice[i]);
snappedEl = true;
$(this.target).addClass("snapped");
TweenLite.to(this.target, 0.1,{
x:targetOffset.left-originalOffset.left,
y:targetOffset.top-originalOffset.top
});
}
}
if(!snappedEl) {
TweenLite.to(this.target, 0.2, {x:0, y:0});
}
}
}
});
I set up a live sample here:
http://codepen.io/rhernando/pen/e2502a90f4ed69fef0e1e7b8d9c17aae
Also for this type of questions is far better for users to go straight to the GreenSock forums, you'll get a faster and official answer. Not that there's something wrong with coming here for answers, but the GreenSock forums are dedicated to GSAP and you'll get official support from the moderating team that includes the creator of the engine.
Cheers!!
Related
I would like to make the annotations move by a certain step and not stop in between two columns in axis.
For example, the x axis is [0, 10, 20, 30]. When dragging the annotation, I want its point to change directly from {x: 10, y: 10000} to {x: 20, y: 10000} without going to x: 15. i.e. make the annotation a bit sticky to the column and not sitting between columns.
I also need to get the current annotation point so I can update some other element.
I tried the solution from stackoverflow but it doesn't work.
Here is my current code. CodePen
enter code here
Edit 1:
Thanks to the solution from #ppotaczek, the annotation can move by steps now. Here is the updated code JSFiddle. What needs to be refined is when dragging the annotation too fast, it cannot keep up with the mouse. Is it because of the performance of Highcharts.redraw() method and how can we solve this?
Another unsolved question is -> how to get the current point of the annotation? It seems the annotation object doesn't provide any value about that. All I can think of is keep a record of the initial point, then everytime the annotation is moved by a step, update the record. Is there a better way?
//this code can deal with vertical and horizontal annotations now.
Highcharts.Annotation.prototype.onDrag = function(e) {
if (
this.chart.isInsidePlot(
e.chartX - this.chart.plotLeft,
e.chartY - this.chart.plotTop
)
) {
var translation = this.mouseMoveToTranslation(e),
xAxis = this.chart.xAxis[0],
yAxis = this.chart.yAxis[0],
xStep = 1,
yStep = 1000,
pxStep = xAxis.toPixels(xStep) - xAxis.toPixels(0),
pyStep = yAxis.toPixels(yStep) - yAxis.toPixels(0);
if (!Highcharts.defined(this.potentialTranslation)) { //not defined
this.potentialTranslation = 0;
}
if (this.options.draggable === 'x') {
this.potentialTranslation += translation.x;
translation.y = 0;
if (Math.abs(this.potentialTranslation) >= Math.abs(pxStep)) {
translation.x = (this.potentialTranslation > 0) ? pxStep : -pxStep;
this.potentialTranslation = 0;
//this.potentialTranslation = undefined;
if (this.points.length) {
this.translate(translation.x, translation.y);
} else {
this.shapes.forEach(function(shape) {
shape.translate(translation.x, translation.y);
});
this.labels.forEach(function(label) {
label.translate(translation.x, translation.y);
});
}
}
}
if (this.options.draggable === 'y') {
this.potentialTranslation += translation.y;
translation.x = 0;
if (Math.abs(this.potentialTranslation) >= Math.abs(pyStep)) {
translation.y = (this.potentialTranslation > 0) ? -pyStep : pyStep;
this.potentialTranslation = 0;
if (this.points.length) {
this.translate(translation.x, translation.y);
} else {
this.shapes.forEach(function(shape) {
shape.translate(translation.x, translation.y);
});
this.labels.forEach(function(label) {
label.translate(translation.x, translation.y);
});
}
}
}
this.redraw(false);
}
}
Edit 2:
Thanks to #ppotaczek again! The "mouse moving too fast" issue is solved now. I apply his updates and also my idea of how to get the annotation value into JSFiddle.
You can overwrite Highcharts.Annotation.prototype.onDrag method:
(function(H) {
H.Annotation.prototype.onDrag = function(e) {
if (
this.chart.isInsidePlot(
e.chartX - this.chart.plotLeft,
e.chartY - this.chart.plotTop
)
) {
var translation = this.mouseMoveToTranslation(e),
xAxis = this.chart.xAxis[0],
step = 0.5,
pxStep = xAxis.toPixels(step) - xAxis.toPixels(0);
if (!H.defined(this.potentialTranslation)) {
this.potentialTranslation = 0;
}
this.potentialTranslation += translation.x;
if (Math.abs(this.potentialTranslation) >= pxStep) {
translation.y = 0;
translation.x = (this.potentialTranslation > 0) ? pxStep : -pxStep;
this.potentialTranslation = 0;
if (this.points.length) {
this.translate(translation.x, translation.y);
} else {
this.shapes.forEach(function(shape) {
shape.translate(translation.x, translation.y);
});
this.labels.forEach(function(label) {
label.translate(translation.x, translation.y);
});
}
}
this.redraw(false);
}
}
}(Highcharts));
Live demo: http://jsfiddle.net/BlackLabel/vmon2chx/
Docs: https://www.highcharts.com/docs/extending-highcharts
I'm trying to create a fire effect for a game in Matter.js, and I need to blur a circle to make it look more realistic. However, I need to make it so it only blurs the fire, not the whole canvas. How can I do this?
This is the code I have so far:
function setOnFire(object) {
var fireX = object.position.x;
var fireY = object.position.y;
var fire = Bodies.circle(fireX, fireY, vw*1, {
isStatic: true,
render: {
fillStyle: "rgba(255,130,0,1)"
}
});
World.add(world, fire);
}
This is not exactly what I had in mind, but it is as close as you can get.
Start by going to matter.js and go to this section:
for (k = body.parts.length > 1 ? 1 : 0; k < body.parts.length; k++) {
part = body.parts[k];
if (!part.render.visible)
continue;
Add this code after the continue;:
if (body.bloom) {
c.shadowColor = body.render.fillStyle;
c.shadowOffsetX = 0;
c.shadowOffsetY = 0;
c.shadowBlur = body.bloom;
}
Then, go to the very end of the loop and add this:
if (body.bloom) {
c.shadowColor = "transparent";
c.shadowOffsetX = 0;
c.shadowOffsetY = 0;
c.shadowBlur = 0;
}
Then, just add the bloom while making your body. For instance:
let fireParticle = Bodies.circle(0, 0, {
bloom: 25
});
I'm quite new to javaScript and programing in general and i'm trying to make a one vs one 2D tank game using Phaser API.
I have been stuck for the past two days trying to figure out how to kill a single bullet that hits the other tank. I did manage to get it to work using the arcade physics and by using the Phaser example tank game. But i can't seem to convert my knowlegde so far and apply it to the P2 physics which i am currently using and would like to stick to.
This is the tank constructor which i use to create two tanks, each tank holds its individual bulletGroup named bullets, at the far bottom i have a function called shoot which reset a bullet and make it fly towards the target (this particular function is mostly taken from the phaser tank example)
var tank = function(playerIndex, startX, startY, facing, keyLeft, keyRight, keyUp, keyDown, keyTLeft, keyTRight, keyShoot) {
this.playerIndex = playerIndex.toString();;
this.tankBody;
this.tankTurret;
this.facing = facing;
this.bullets;
this.fireRate = 200;
this.nextFire = 0;
this.health = 100;
this.isAlive = true;
this.bodyTurnSpeed = 2;
this.turretTurnSpeed = 2;
this.currentSpeed = 0;
this.maxSpeed = 50;
this.keyLeft = keyLeft;
this.keyRight = keyRight;
this.keyUp = keyUp;
this.keyDown = keyDown;
this.keyTLeft = keyTLeft;
this.keyTRight = keyTRight;
this.keyShoot = keyShoot;
this.create = function() {
if (this.playerIndex === "1") {
this.tankBody = game.add.sprite(startX, startY, "body_player_one");
this.tankTurret = game.add.sprite(startX, startY, "turret_player_one");
} else if (this.playerIndex === "2") {
this.tankBody = game.add.sprite(startX, startY, "body_player_two");
this.tankTurret = game.add.sprite(startX, startY, "turret_player_two");
}
this.tankBody.anchor.setTo(0.5, 0.5);
this.tankTurret.anchor.setTo(0.5, 0.5);
game.physics.p2.enable([this.tankBody]);
this.tankBody.body.immovable = false;
this.tankBody.body.collideWorldBounds = true;
this.tankBody.body.debug = false;
this.tankBody.body.fixedRotation = true;
this.tankBody.body.mass = 50;
// this.tankBody.body.kinematic = true;
this.bullets = game.add.group();
this.bullets.enableBody = true;
this.bullets.physicsBodyType = Phaser.Physics.P2JS;
this.bullets.createMultiple(100, 'bullet', 0, false);
this.bullets.setAll('anchor.x', 0.5);
this.bullets.setAll('anchor.y', 0.5);
this.bullets.setAll('outOfBoundsKill', true);
this.bullets.setAll('checkWorldBounds', true);
switch (this.facing) {
case "left":
this.tankBody.rotation = this.tankBody.body.rotation = Phaser.Math.degToRad(-90);
this.tankTurret.rotation = Phaser.Math.degToRad(-90);
break;
case "right":
this.tankBody.rotation = this.tankBody.body.rotation = Phaser.Math.degToRad(90);
this.tankTurret.rotation = Phaser.Math.degToRad(90);
break;
case "up":
this.tankBody.rotation = this.tankBody.body.rotation = Phaser.Math.degToRad(0);
this.tankTurret.rotation = Phaser.Math.degToRad(0);
break;
case "down":
this.tankBody.rotation = this.tankBody.body.rotation = Phaser.Math.degToRad(180);
this.tankTurret.rotation = Phaser.Math.degToRad(180);
break;
}
}
this.update = function() {
if (this.isAlive) {
if (game.input.keyboard.isDown(this.keyLeft)) {
this.tankBody.rotation = this.tankBody.body.rotation -= Phaser.Math.degToRad(this.bodyTurnSpeed);
}
if (game.input.keyboard.isDown(this.keyRight)) {
this.tankBody.rotation = this.tankBody.body.rotation += Phaser.Math.degToRad(this.bodyTurnSpeed);;
}
if (game.input.keyboard.isDown(this.keyUp)) {
this.tankBody.body.moveForward(50);
} else if (game.input.keyboard.isDown(this.keyDown)) {
this.tankBody.body.moveBackward(50);
} else this.tankBody.body.setZeroVelocity();
if (game.input.keyboard.isDown(this.keyTLeft)) {
this.tankTurret.rotation -= Phaser.Math.degToRad(this.turretTurnSpeed);
} else if (game.input.keyboard.isDown(this.keyTRight)) {
this.tankTurret.rotation += Phaser.Math.degToRad(this.turretTurnSpeed);
}
if (game.input.keyboard.isDown(this.keyShoot)) {
this.shoot();
}
this.tankTurret.x = this.tankBody.x;
this.tankTurret.y = this.tankBody.y;
} else {
this.tankTurret.kill();
this.tankBody.kill();
}
}
this.shoot = function() {
if (game.time.now > this.nextFire && this.bullets.countDead() > 0) {
this.nextFire = game.time.now + this.fireRate;
var bullet = this.bullets.getFirstExists(false);
bullet.reset(this.tankTurret.x + this.tankTurret.width / 2 * Math.cos(this.tankTurret.rotation - Phaser.Math.degToRad(90)),
this.tankTurret.y + this.tankTurret.width / 2 * Math.sin(this.tankTurret.rotation - Phaser.Math.degToRad(90)));
bullet.body.rotation = this.tankTurret.rotation;
bullet.body.mass = 100;
bullet.body.moveForward(500);
}
}
}
This is where i assign collisionGroups and make them collide with eachother,
everything here is working as intended but the bullets do not dissapear
function create() {
game.add.sprite(0, 0, "background_one");
game.physics.startSystem(Phaser.Physics.P2JS);
game.physics.p2.setImpactEvents(true);
//creating the collisiongroups
var bulletsCollisionGroup = game.physics.p2.createCollisionGroup();
var playerOneCollisionGroup = game.physics.p2.createCollisionGroup();
var playerTwoCollisionGroup = game.physics.p2.createCollisionGroup();
var wallCollisionGroup = game.physics.p2.createCollisionGroup();
//sets the objects to collide with gamestage borders (prevent objects from moving out of bounds)
game.physics.p2.updateBoundsCollisionGroup();
//creating players, each player holds its own bulletgroup
player_one.create();
player_two.create();
//creates the tiles (mouseclick to place)
createTiles();
//sets sprites to different collisiongroups
player_one.tankBody.body.setCollisionGroup(playerOneCollisionGroup);
for (var i = 0; i < player_one.bullets.children.length; i++) //player_one bullets
{
player_one.bullets.children[i].body.setCollisionGroup(bulletsCollisionGroup);
}
player_two.tankBody.body.setCollisionGroup(playerTwoCollisionGroup);
for (var i = 0; i < player_two.bullets.children.length; i++) //player_two bullets
{
player_two.bullets.children[i].body.setCollisionGroup(bulletsCollisionGroup);
}
for (var i = 0; i < tiles.children.length; i++) //tiles
{
tiles.children[i].body.setCollisionGroup(wallCollisionGroup);
}
//makes the collisiongroups collide with eachother
player_one.tankBody.body.collides([playerTwoCollisionGroup, wallCollisionGroup, bulletsCollisionGroup]);
player_two.tankBody.body.collides([playerOneCollisionGroup, wallCollisionGroup, bulletsCollisionGroup]);
for (var i = 0; i < tiles.children.length; i++) //tiles with everything
{
tiles.children[i].body.collides([playerOneCollisionGroup, playerTwoCollisionGroup, bulletsCollisionGroup]);
}
for (var i = 0; i < player_one.bullets.children.length; i++) //player_one bullets with everything
{
player_one.bullets.children[i].body.collides([wallCollisionGroup]);
player_one.bullets.children[i].body.collides(playerTwoCollisionGroup, function() {
bulletHitPlayer(player_two)
}, this);
}
for (var i = 0; i < player_two.bullets.children.length; i++) //player_two bullets with everything
{
player_two.bullets.children[i].body.collides([wallCollisionGroup]);
player_two.bullets.children[i].body.collides(playerOneCollisionGroup, function() {
bulletHitPlayer(player_one)
}, this);
}
}
this is the function i tried to use for callback on collision with a tank, it seems to work in arcade physics with overlap
function bulletHitPlayerOne(tank, bullet) {
bullet.kill()
tank.health -= 20;
if (player.health <= 0) {
tank.isAlive = false;
}
}
and this is how i tried to implement the function above to my collisionHandler
for (var i = 0; i < player_two.bullets.children.length; i++) {
player_two.bullets.children[i].body.collides(playerOneCollisionGroup, bulletHitPlayerOne, this);
}
Now, I've tried a various of different ways to solve this problem but im completely stuck, I'm begining to think that i can't kill a sprite in a group with the P2 physics enabled (but then again why wouldn't it work?)
I did seacrh and tried to read as much documentations as possible but with this particular problem i seem to be alone :)
Thank you for your time!
/Martin
Something like this should work.
Game.prototype = {
create: function(){
//...
var bulletsCollisionGroup = game.physics.p2.createCollisionGroup();
var playerOneCollisionGroup = game.physics.p2.createCollisionGroup();
//....
this.bullets = game.add.group();
this.bullets.enableBody = true;
this.bullets.physicsBodyType = Phaser.Physics.P2JS;
this.bullets.createMultiple(100, 'bullet', 0, false);
this.bullets.setAll('anchor.x', 0.5);
this.bullets.setAll('anchor.y', 0.5);
this.bullets.setAll('outOfBoundsKill', true);
this.bullets.setAll('checkWorldBounds', true);
this.bullets.forEach(function(bullet){
bullet.body.setCollisionGroup(bulletsCollisionGroup);
bullet.body.collides(playerOneCollisionGroup);
});
player.body.setCollisionGroup(playerOneCollisionGroup);
player.body.collides(bulletsCollisionGroup, this.hit, this);
},
/...
hit: function(player,bullet){
bullet.parent.sprite.kill();
}
}
Bear in mind that player will collide with the bullet and it will change velocity, acceleration and other properties before the bullet is killed. You may want to use onBeginContact or maybe BroadphaseCallback
Total noob here, i'm assuming there's a way to write this faster/smaller. Any advice?
Sorry if its not really reduced down & out of the framework i'm using, but here's a live example if that helps.
Live Example: http://linkthegeek.com/public/code/bookmarker/index.html
(only works in webkit, & I've only tested in chrome)
BannerOne = 1;
BannerTwo = 2;
BannerThree = 3;
BannerFour = 4;
BannerFive = 5;
PSD['bannerdrop-'+ BannerOne].y= -200;
PSD['bannerdrop-'+ BannerTwo].y= -200;
PSD['bannerdrop-'+ BannerThree].y= -200;
PSD['bannerdrop-'+ BannerFour].y= -200;
PSD['bannerdrop-'+ BannerFive].y= -200;
PSD['bannerbtn-'+ BannerOne].on("click", function(){Bookmark(BannerOne) });
PSD['bannerdrop-'+ BannerOne].on("click", function(){Bookmark(BannerOne) });
PSD['bannerbtn-'+ BannerTwo].on("click", function(){Bookmark(BannerTwo) });
PSD['bannerdrop-'+ BannerTwo].on("click", function(){Bookmark(BannerTwo) });
PSD['bannerbtn-'+ BannerThree].on("click", function(){Bookmark(BannerThree) });
PSD['bannerdrop-'+ BannerThree].on("click", function(){Bookmark(BannerThree) });
PSD['bannerbtn-'+ BannerFour].on("click", function(){Bookmark(BannerFour) });
PSD['bannerdrop-'+ BannerFour].on("click", function(){Bookmark(BannerFour) });
PSD['bannerbtn-'+ BannerFive].on("click", function(){Bookmark(BannerFive) });
PSD['bannerdrop-'+ BannerFive].on("click", function(){Bookmark(BannerFive) });
function Bookmark (viewnum) {
item = PSD['item-'+ viewnum ]
bannerbtn = PSD['bannerbtn-'+ viewnum ]
bannerdrop = PSD['bannerdrop-'+ viewnum ]
var down;
var away;
var small;
if (bannerbtn.opacity == 1) {
away = 0;
small = .03;
down = -13;
};
if (bannerbtn.opacity == 0) {
away = 1;
small = 1;
down = -200;
};
//animations
bannerdrop.animate({
properties:{y:down},
curve:"spring(100,15,200)"
});
bannerbtn.animate({
properties:{opacity:away, scale:small},
curve:"linear",
time:100
});
};
Don't quite understand your application here, but here's something that might set you in the right direction.
This is definitely not functional as I don't have a lot of the background information and have made assumptions:
var BannerCount = 5;
var PSD = [];
for (i = 0; i < count; i++) {
PSD[i] = {};
PSD[i].btn = document.getElementById('bannerbtn-' + i);
PSD[i].btn.on("click", function (eevent) {
Bookmark(eevent.srcElement);
});
PSD[i].y = -200;
PSD[i].on("click", function (eevent) {
Bookmark(eevent.srcElement);
});
PSD[i].drop = document.getElementById('bannerdrop-' + i).addEventListener("click",
function (eevent) {
Bookmark(eevent.srcElement);
});
}
function Bookmark(itemPSD) {
var down;
var away;
var small;
if (itemPSD.btn.style.opacity == 1) {
away = 0;
small = 0.03;
down = -13;
} else if (itemPSD.btn.style.opacity === 0) {
away = 1;
small = 1;
down = -200;
}
//animations
itemPSD.drop.animate({
properties: {
y: down
},
curve: "spring(100,15,200)"
});
itemPSD.btn.animate({
properties: {
opacity: away,
scale: small
},
curve: "linear",
time: 100
});
}
We may be need an object bannerdrop will save any attribute you have. So what we do is declare array of this object like:
function bannerdrop(y){
this.y = y;
this.on('click', function(){bookmark(this);});
}
function bookmark(obj){
var down;
var away;
var small;
//animations
obj.animate({
properties:{y:down},
curve:"spring(100,15,200)"
});
}
var bannerArray = new Array(new bannerdrop(-200), new bannerdrop(-200), new bannerdrop(-200));
I need to adjust the script from http://javascript.about.com/library/blcvert.htm to change direction of scrolling to DOWN.
Could anybody help?
Of course, it would be also helpful if anybody knows/have some other script which produces the same effect.
Thanx
P.S. the script (in readable format is):
var imgAry1 = ['img1.png','img2.png'];
function startCloud() {
new mq('clouds', imgAry1, 380);
mqRotate(mqr);
}
$(document).ready(function() {
startCloud();
});
var mqr = [];
function mq(id, ary, heit) {
this.mqo=document.getElementById(id);
var wid = this.mqo.style.width;
this.mqo.onmouseout=function() { mqRotate(mqr); };
this.mqo.onmouseover=function() { clearTimeout(mqr[0].TO); };
this.mqo.ary=[];
var maxw = ary.length;
for (var i=0;i<maxw;i++) {
this.mqo.ary[i]=document.createElement('img');
this.mqo.ary[i].src=ary[i];
this.mqo.ary[i].style.position = 'absolute';
this.mqo.ary[i].style.top = (heit*i)+'px';
this.mqo.ary[i].style.height = heit+'px';
this.mqo.ary[i].style.width = wid;
this.mqo.appendChild(this.mqo.ary[i]);
}
mqr.push(this.mqo);
}
function mqRotate(mqr) {
if (!mqr) return;
for (var j=mqr.length - 1; j > -1; j--) {
maxa = mqr[j].ary.length;
for (var i=0;i<maxa;i++) {
var x = mqr[j].ary[i].style;
x.top=(parseInt(x.top,10)-1)+'px';
}
var y = mqr[j].ary[0].style;
if (parseInt(y.top,10)+parseInt(y.height,10)<0) {
var z = mqr[j].ary.shift();
z.style.top = (parseInt(z.style.top) + parseInt(z.style.height)*maxa) + 'px';
mqr[j].ary.push(z);
}
}
mqr[0].TO=setTimeout('mqRotate(mqr)',10);
}
On this line:
x.top=(parseInt(x.top,10)-1)+'px';
it says that you take x.top in pixels, parse out the number, subtract one and add the 'px' again. The element's position from top is decreased by 1 each time, so it goes up. All you need to do for it to go down is to add the one.
x.top=(parseInt(x.top,10)+1)+'px';
I also tested this hypothesis on the page you linked :)