Related
I'm using Matter.js for some graphics and want this rectangle
let title = Bodies.rectangle(w / 2.4, height / 1.8, 300, 100, {
isStatic: true,
})
to get isStatic: false and fall when it's hit by some circles that are raining down on it. I've done some extensive Googling, but haven't really found anything else but this:
Events.on(engine, 'collisionStart', function (event) {
event.pairs.forEach(function (obj) {
console.log(
'BodyA is static: ' + obj.bodyA.isStatic + '. BodyB is static: ' + obj.bodyB.isStatic
)
})
})
This gives me all the collisions happening, but I haven't figured out how to set isStatic: false when something hits. Appreciate your help!
You can call Matter.Body.setStatic(body, false) on the body in question to make it active.
Here's an example:
const engine = Matter.Engine.create();
const render = Matter.Render.create({
element: document.body,
engine,
options: {width: 400, height: 400, wireframes: false},
});
const fallingBody = Matter.Bodies.rectangle(
200, 0, 20, 20, {
frictionAir: 0.1,
density: 0.8,
render: {fillStyle: "red"},
},
);
const wall = Matter.Bodies.rectangle(
200, 150, 400, 20, {
frictionAir: 0.05,
isStatic: true,
render: {fillStyle: "green"}
},
);
Matter.Composite.add(engine.world, [fallingBody, wall]);
Matter.Events.on(engine, "collisionStart", event => {
if (
wall.isStatic &&
event.pairs.some(e => Object.values(e).includes(wall))
) {
Matter.Body.setStatic(wall, false);
}
});
Matter.Render.run(render);
Matter.Runner.run(Matter.Runner.create(), engine);
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>
I have particles that I emit when clicking and moving my mouse over a certain object. However I noticed that while the particles start out as little, they become more and more the more often I click and move my mouse,until the stream of particles is far too dense.
This only seems to happen when I click down multiple times (thus triggering the pointerdown event multiple times), not when I click once and keep moving.
How can I stop this?
function pet(start, scene, pointer = null)
{
if(start){
scene.input.on('pointermove', function(){
if (scene.input.activePointer.isDown && gameState.chara.getBounds().contains(scene.input.activePointer.x, scene.input.activePointer.y)){
gameState.sparkle.emitParticle(1,scene.input.activePointer.x, scene.input.activePointer.y); // !!!! Here is where I emit my particles
}
});
} else {
gameState.sparkle.stop(); // !!!! Here I stop my particles
}
}
const gameState = {
gameWidth: 800,
gameHeight: 800,
menu: {},
textStyle: {
fontFamily: "'Comic Sans MS'",
fill: "#fff",
align: "center",
boundsAlignH: "left",
boundsAlignV: "top"
},
};
function preload()
{
this.load.baseURL = 'assets/';
// Chara
this.load.atlas('chara', 'chara.png', 'chara.json');
// Particle
this.load.image('sparkle', 'sparkle.png'); // Here I load my particle image
}
function create()
{
// Scene
let scene = this;
// Chara
this.anims.create({
key: "wag",
frameRate: 12,
frames: this.anims.generateFrameNames("chara", {
prefix: 'idle_000',
start: 0,
end: 5}),
repeat: 0,
});
this.anims.create({
key: "happy",
frameRate: 12,
frames: this.anims.generateFrameNames("chara", {
prefix: 'happy_000',
start: 0,
end: 5}),
repeat: -1
});
gameState.chara = this.add.sprite(400, 400, "chara", "idle_0000");
gameState.chara.setInteractive({cursor: "pointer"});
// !!!! Here I set up my Particle Emitter !!!!
gameState.sparkle = this.add.particles('sparkle').createEmitter({
x: gameState.height/2,
y: gameState.width/2,
scale: { min: 0.1, max: 0.5 },
speed: { min: -100, max: 100 },
quantity: 0.1,
frequency: 1,
lifespan: 1000,
gravityY: 100,
on: false,
});
gameState.chara.on('pointerdown', function(){ pet(true, scene) });
gameState.chara.on('pointerout', function(){ pet(false, scene, 'default') });
gameState.chara.on('pointerup', function(){ pet(false, scene, 'pointer') });
}
function update()
{
}
// Configs
var config = {
backgroundColor: "0xf0f0f0",
scale: {
width: gameState.gameWidth,
height: gameState.gameHeight,
autoCenter: Phaser.Scale.CENTER_BOTH
},
scene: {
preload, create, update
}
};
var game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
The problem is, that you are adding a new scene.input.on('pointermove',...) event-handler in the pet function, on each click.
I would only change the code abit (look below), this should prevent generating too many particles and too many event-handlers (too many event-handlers could harm performance, so be careful, when adding them).
Here is how I would modify the Code:
(I stripped out and added some stuff to make the demo, easier to understand and shorter. And also that the snippet can be executed, without errors/warnings)
The main changes are marked and explained in the code, with comments
function pet(start, scene, pointer = null)
{
if(start){
// Update: remove Event listener add click state
gameState.mouseDown = true
} else {
// Update: add click state
gameState.mouseDown = false;
gameState.sparkle.stop();
}
}
const gameState = {
gameWidth: 400,
gameHeight: 200,
// Update: add click state
mouseDown: false
};
function create()
{
// Scene
let scene = this;
// Just could for Demo START
var graphics = this.add.graphics();
graphics.fillStyle(0xff0000);
graphics.fillRect(2,2,10,10);
graphics.generateTexture('particle', 20, 20);
graphics.clear();
graphics.fillStyle(0xffffff);
graphics.fillRect(0,0,40,40);
graphics.generateTexture('player', 40, 40);
graphics.destroy();
// Just Code for Demo END
gameState.chara = this.add.sprite(200, 100, "player");
gameState.chara.setInteractive({cursor: "pointer"});
gameState.sparkle = this.add.particles('particle').createEmitter({
scale: { min: 0.1, max: 0.5 },
speed: { min: -100, max: 100 },
quantity: 0.1,
frequency: 1,
lifespan: 1000,
gravityY: 100,
on: false,
});
gameState.chara.on('pointerdown', function(){ pet(true, scene) });
gameState.chara.on('pointerout', function(){ pet(false, scene, 'default') });
gameState.chara.on('pointerup', function(){ pet(false, scene, 'pointer') });
// Update: add new single Event Listener
gameState.chara.on('pointermove', function(pointer){
if(gameState.mouseDown){
gameState.sparkle.emitParticle(1,pointer.x, pointer.y);
}
});
}
// Configs
var config = {
width: gameState.gameWidth,
height: gameState.gameHeight,
scene: { create }
};
var game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
var config = {
type: Phaser.AUTO,
width: 1900,
height: 1000,
physics: {
default: 'arcade',
arcade: {
gravity: { y: 300 },
debug: false
}
},
scene: {
preload: preload,
create: create,
update: update
}
};
var main = document.getElementById("startBtn")
var gameOver
score = 0;
function start() {
game = new Phaser.Game(config);
main.innerHTML = ''
score = 0;
}
function preload() {
this.load.image('Background', 'assets/Background.jpg');
this.load.image('ground', 'assets/platform.png');
this.load.image('coin', 'assets/coin.png');
this.load.image('redCoin', 'assets/redCoin.png');
this.load.spritesheet('monkey',
'assets/monkey.png',
{ frameWidth: 600, frameHeight: 720 }
);
}
var platforms;
var score = 0;
var scoreText;
function create() {
this.add.image(500, 275, 'Background').setScale(3);
this.w = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W)
this.a = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A)
this.s = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S)
this.d = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D)
platforms = this.physics.add.staticGroup();
platforms.create(200, 650, 'ground').setScale(0.15).refreshBody();
platforms.create(600, 400, 'ground').setScale(0.15).refreshBody();
platforms.create(1600, 650, 'ground').setScale(0.15).refreshBody();
platforms.create(750, 100, 'ground').setScale(0.15).refreshBody();
platforms.create(850, 750, 'ground').setScale(0.15).refreshBody();
platforms.create(100, 950, 'ground').setScale(0.15).refreshBody();
platforms.create(400, 950, 'ground').setScale(0.15).refreshBody();
platforms.create(700, 950, 'ground').setScale(0.15).refreshBody();
platforms.create(1000, 950, 'ground').setScale(0.15).refreshBody();
platforms.create(1300, 950, 'ground').setScale(0.15).refreshBody();
platforms.create(1600, 950, 'ground').setScale(0.15).refreshBody();
platforms.create(1900, 950, 'ground').setScale(0.15).refreshBody();
platforms.create(1800, 800, 'ground').setScale(0.15).refreshBody();
platforms.create(250, 250, 'ground').setScale(0.15).refreshBody();
platforms.create(1000, 500, 'ground').setScale(0.15).refreshBody();
platforms.create(1150, 220, 'ground').setScale(0.15).refreshBody();
player = this.physics.add.sprite(100, 450, 'monkey').setScale(0.075);
this.physics.add.collider(player, platforms);
player.setBounce(0.2);
player.setCollideWorldBounds(true);
this.anims.create({
key: 'left',
frames: this.anims.generateFrameNumbers('monkey', { start: 0, end: 3 }),
frameRate: 10,
repeat: -1
});
this.anims.create({
key: 'turn',
frames: [{ key: 'monkey', frame: 4 }],
frameRate: 20
});
this.anims.create({
key: 'right',
frames: this.anims.generateFrameNumbers('monkey', { start: 5, end: 8 }),
frameRate: 10,
repeat: -1
});
coins = this.physics.add.group({
key: 'coin',
repeat: 10,
setXY: { x: 12, y: 0, stepX: 150 }
});
coins.children.iterate(function (child) {
child.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
child.setScale(0.05)
});
this.physics.add.collider(coins, platforms);
this.physics.add.overlap(player, coins, collectCoin, null, this);
redCoins = this.physics.add.group();
this.physics.add.collider(redCoins, platforms);
this.physics.add.collider(player, redCoins, hitredCoin, null, this);
scoreText = this.add.text(16, 16, 'score: 0', { fontSize: '64px', fill: 'rgb(85, 1, 1)' });
}
function update() {
cursors = this.input.keyboard.createCursorKeys();
if (cursors.left.isDown) {
player.setVelocityX(-160);
player.anims.play('left', true);
}
else if (cursors.right.isDown) {
player.setVelocityX(160);
player.anims.play('right', true);
}
else {
player.setVelocityX(0);
player.anims.play('turn');
}
if (cursors.up.isDown && player.body.touching.down) {
player.setVelocityY(-330);
}
}
function collectCoin(player, coin) {
coin.disableBody(true, true);
score += 1;
scoreText.setText('Score: ' + score);
if (coins.countActive(true) === 0) {
coins.children.iterate(function (child) {
child.enableBody(true, child.x, 0, true, true);
});
var x = (player.x < 400) ? Phaser.Math.Between(400, 800) : Phaser.Math.Between(0, 400);
var redCoin = redCoins.create(x, 16, 'redCoin').setScale(0.05);
redCoin.setBounce(1);
redCoin.setCollideWorldBounds(true);
redCoin.setVelocity(Phaser.Math.Between(-200, 200), 20);
}
}
function hitredCoin(player, redCoin) {
this.physics.pause();
player.setTint(0xff0000);
player.anims.play('turn');
gameOver = true;
window.setTimeout(restart, 3000);
}
function restart () {
this.scene.stop();
this.scene.start();
}
This code is my game and it doesn't work because you can not respawn when you die, the delay doesn't work. I would like help fixing the time delay at the end of the hitredcoinfunction that calls the restart function. Please help me with this problem
it may be because I am using a delay thing from javascript, if so please tell me how to swap it out for the phaser version
pls help me with this, I really need my game to work
The problem is that the this context is not set.
you can do this simply with the bind function. Here is the link to the documentation (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind)
Just change the line to this:
window.setTimeout(restart.bind(this), 3000);
the bind function, passes an object/context (in this case the phaser scene) to the function, so that it can be referred to as this.
If you want to use the phaser delayedCall function you have to replace the line with (link to the documentation https://photonstorm.github.io/phaser3-docs/Phaser.Time.Clock.html ):
this.time.delayedCall(3000, restart, null, this);
the first parameter is the time in ms: 3000
the second parameter is the function to call: restart
the third parameter are arguments, that should be passed to the passed function: null
the last parameter is the context, for the passed function: this (the current scene)
I'm using cropper, it's a jquery plugin I found at cropper web site.
I have an image size full hd 1920w on 1080h, and I need to give the user ability to crop in fixed box size 675*1080, my question is how do I set the options of this plugin ?
I've tried to do the follow with no success:
var c1 = $('.cropper-example-1 img').cropper({
//aspectRatio: 10 / 16,
strict: true,
background:false,
guides: false,
highlight: false,
dragCrop: false,
movable: false,
resizable: false,
mouseWheelZoom: false,
touchDragZomm:false,
built: function () {
//alert(1);
// $(this).cropper('setData', 0, 0, 675, 1080,90);
// $(this).cropper('setCropBoxData', 0, 0, 1920, 1080);
}
});
After soo many trials this worked for me... i needed to set the initial width and height to 240px by 607px and this is my code.
var cropper;
var imgx;
$(function(){
var imgx = $('#cpdiv').find('img');
cropper = new Cropper(imgx[0], {
//aspectRatio: 1/2,
autoCropArea: 0,
strict: false,
guides: false,
highlight: true,
dragCrop: false,
//cropBoxMovable: false,
cropBoxResizable: false,
data:{
width: 240,
height: 607,
},
crop(event) {
console.log(event.detail.width);
console.log(event.detail.height);
},
});
});
i tried using the setCropBoxData({}) function which didnt work.. but this approach worked for me.
Try like this add autoCropArea: 0.5, and changes the built method
var $image=$('.cropper-example-1 img');
$image.cropper({
//aspectRatio: 10 / 16,
strict: true,
background:false,
guides: false,
highlight: false,
dragCrop: false,
movable: false,
resizable: false,
mouseWheelZoom: false,
touchDragZomm:false,
autoCropArea: 0.5,
built: function () {
//alert(1);
// $(this).cropper('setData', 0, 0, 675, 1080,90);
// $(this).cropper('setCropBoxData', 0, 0, 1920, 1080);
$image.cropper('setCanvasData', 0, 0, 1920, 1080));
$image.cropper('setCropBoxData', 0, 0, 675, 1080);
}
});
built: function () {
//$image.cropper('setCropBoxData', 0, 0, 675, 1080);
$image.cropper("setCropBoxData", { width: 160, height: 80 });
or
$image.cropper("setCropBoxData", { left: 0, top: 0, width: 160, height: 80 });
}
If you want to make CropBox selection fit to Canvas use this
autoCropArea: 1,
To make CropBox selection has margin 50% from the Canvas
autoCropArea: 0.5,
try to limit its height and width on cropper.js.. not the best option but it fixed my problem. When user try to minimize the cropbox, it will stop at the set size creating a not so bad solution for now..:')
minCropBoxWidth: 350,
minCropBoxHeight: 350
Working code to set crop box. I am using jQuery Cropper v1.0.0
var $image = $(".image-crop > img");
var init_data = { x: parseFloat($("#event_crop_x").val()), y: parseFloat($("#event_crop_y").val()), width: parseFloat($("#event_crop_w").val()), height: parseFloat($("#event_crop_h").val()) };
$($image).cropper({
zoomable: false,
aspectRatio: 2 / 1,
preview: ".img-preview",
crop: function(event) {
$("#event_crop_x").val(event.detail.x);
$("#event_crop_y").val(event.detail.y);
$("#event_crop_w").val(event.detail.width);
$("#event_crop_h").val(event.detail.height);
},
data: init_data
});
I am trying to get fullduration my MP3 file but it returns me NaN,
Here is my code:
<script>
$f("player", "http://releases.flowplayer.org/swf/flowplayer-3.2.7.swf", {
clip: {
// our song
url: '1.mp3',
// when music starts grab song's metadata and display it using content plugin
onStart: function(){
var fullduration = parseInt(this.getClip().fullDuration, 10);
alert(fullduration);
var p = this, c = p.getClip(), d;
timer = setInterval(function(){
d = showtime(c.fullDuration);
$("a[href=" + c.url + "] > samp").html(showtime(p.getTime()) + "/" + d);
}, 1000);
}
},
plugins: {
// content plugin settings
content: {
url: 'flowplayer.content-3.2.0.swf',
backgroundColor: '#002200',
top: 25,
right: 25,
width: 160,
height: 60
},
// and a bit of controlbar skinning
controls: {
backgroundColor: '#002200',
height: 30,
fullscreen: false,
autoHide: false,
volume: false,
mute: true,
time: true,
stop: false,
play: false
}
}
});
</script>
I had a look at your code using flowplayer version 3.2.7 and 3.2.8. With version 3.2.7 I get the same error and with 3.2.8 I get the duration in seconds which is what is expected. So you'll need to upgrade and change the following from
http://releases.flowplayer.org/swf/flowplayer-3.2.7.swf
to
http://releases.flowplayer.org/swf/flowplayer-3.2.8.swf