How do I add a rectangle to the zoomed canvas area? - javascript

I'm using Fabric JS. Every time I press the Add Door button it creates on the upper left. I gave the values ​​in the rectangle (left: 40, top: 40,).
However, when I press the button while I am on the area I zoomed, I want it to add it to the area I zoomed. I looked at a few examples but could not find what I wanted. How can I do that?
Video
var canvas = new fabric.Canvas('c');
canvas.setBackgroundImage('https://i.hizliresim.com/0pIPiv.jpg', canvas.renderAll.bind(canvas));
var uniqids = 0;
$("#door").on("click", function(e) {
rect = new fabric.Rect({
id:uniqid,
left: 40,
top: 40,
width: 35,
height: 50,
fill: 'blue',
stroke: 'blue',
strokeWidth: 5,
strokeUniform: false,
hasControls : true,
});
var uniqid = uniqids.toString();
var text = new fabric.Text(uniqid, {
fontSize: 30,
originX: 'center',
originY: 'right'
});
var group = new fabric.Group([ rect, text ], {
left: 0,
top: 100,
});
canvas.add(group);
uniqids++;
canvas.on('selection:cleared', c => {
console.log("empty");
});
canvas.selection = false;
});
//*****************************
// canvas.on('mouse:wheel', function(opt) {
// var delta = opt.e.deltaY;
// var zoom = canvas.getZoom();
// zoom *= 0.999 ** delta;
// if (zoom > 20) zoom = 20;
// if (zoom < 0.01) zoom = 0.01;
// canvas.setZoom(zoom);
// opt.e.preventDefault();
// opt.e.stopPropagation();
// })
$('#getid').click(function() {
var activeObject = canvas.getActiveObjects();
alert(canvas.getActiveObject().id);
});
//***************************************
$("#save").on("click", function(e) {
$(".save").html(canvas.toSVG());
});
$('#delete').click(function() {
var activeObject = canvas.getActiveObjects();
canvas.discardActiveObject();
canvas.remove(...activeObject);
});
$("#btnResetZoom").on("click", function(e) {
canvas.setViewportTransform([1,0,0,1,0,0]);
});
canvas.on('mouse:wheel', function(opt) {
var delta = opt.e.deltaY;
var zoom = canvas.getZoom();
zoom *= 0.999 ** delta;
if (zoom > 20) zoom = 20;
if (zoom < 1) zoom = 1;
canvas.zoomToPoint({x: opt.e.offsetX, y: opt.e.offsetY}, zoom);
opt.e.preventDefault();
opt.e.stopPropagation();
});
var shiftKeyDown = true;
var mouseDownPoint = null;
canvas.on('mouse:move', function(options) {
if (shiftKeyDown && mouseDownPoint) {
var pointer = canvas.getPointer(options.e, true);
var mouseMovePoint = new fabric.Point(pointer.x, pointer.y);
canvas.relativePan(mouseMovePoint.subtract(mouseDownPoint));
mouseDownPoint = mouseMovePoint;
keepPositionInBounds(canvas);
}
});
var Direction = {
LEFT: 0,
UP: 1,
RIGHT: 2,
DOWN: 3
};
var zoomLevel = 0;
var zoomLevelMin = 0;
var zoomLevelMax = 3;
var shiftKeyDown = false;
var mouseDownPoint = null;
canvas.on('mouse:down', function(options) {
var pointer = canvas.getPointer(options.e, true);
mouseDownPoint = new fabric.Point(pointer.x, pointer.y);
});
canvas.on('mouse:up', function(options) {
mouseDownPoint = null;
});
canvas.on('mouse:move', function(options) {
if (shiftKeyDown && mouseDownPoint) {
var pointer = canvas.getPointer(options.e, true);
var mouseMovePoint = new fabric.Point(pointer.x, pointer.y);
canvas.relativePan(mouseMovePoint.subtract(mouseDownPoint));
mouseDownPoint = mouseMovePoint;
keepPositionInBounds(canvas);
}
});
fabric.util.addListener(document.body, 'keydown', function(options) {
if (options.repeat) {
return;
}
var key = options.which || options.keyCode; // key detection
if (key == 16) { // handle Shift key
canvas.defaultCursor = 'move';
canvas.selection = false;
shiftKeyDown = true;
} else if (key === 37) { // handle Left key
move(Direction.LEFT);
} else if (key === 38) { // handle Up key
move(Direction.UP);
} else if (key === 39) { // handle Right key
move(Direction.RIGHT);
} else if (key === 40) { // handle Down key
move(Direction.DOWN);
}
});
fabric.util.addListener(document.body, 'keyup', function(options) {
var key = options.which || options.keyCode; // key detection
if (key == 16) { // handle Shift key
canvas.defaultCursor = 'default';
canvas.selection = true;
shiftKeyDown = false;
}
});
// jQuery('.canvas-container').on('mousewheel', function(options) {
// var delta = options.originalEvent.wheelDelta;
// if (delta != 0) {
// var pointer = canvas.getPointer(options.e, true);
// var point = new fabric.Point(pointer.x, pointer.y);
// if (delta > 0) {
// zoomIn(point);
// } else if (delta < 0) {
// zoomOut(point);
// }
// }
// });
function move(direction) {
switch (direction) {
case Direction.LEFT:
canvas.relativePan(new fabric.Point(-10 * canvas.getZoom(), 0));
break;
case Direction.UP:
canvas.relativePan(new fabric.Point(0, -10 * canvas.getZoom()));
break;
case Direction.RIGHT:
canvas.relativePan(new fabric.Point(10 * canvas.getZoom(), 0));
break;
case Direction.DOWN:
canvas.relativePan(new fabric.Point(0, 10 * canvas.getZoom()));
break;
}
keepPositionInBounds(canvas);
}
// function zoomIn(point) {
// if (zoomLevel < zoomLevelMax) {
// zoomLevel++;
// canvas.zoomToPoint(point, Math.pow(2, zoomLevel));
// keepPositionInBounds(canvas);
// }
// }
// function zoomOut(point) {
// console.log(zoomLevel, zoomLevelMin);
// if (zoomLevel > zoomLevelMin) {
// zoomLevel--;
// canvas.zoomToPoint(point, Math.pow(2, zoomLevel));
// keepPositionInBounds(canvas);
// }
// }
function keepPositionInBounds() {
var zoom = canvas.getZoom();
var xMin = (2 - zoom) * canvas.getWidth() / 2;
var xMax = zoom * canvas.getWidth() / 2;
var yMin = (2 - zoom) * canvas.getHeight() / 2;
var yMax = zoom * canvas.getHeight() / 2;
var point = new fabric.Point(canvas.getWidth() / 2, canvas.getHeight() / 2);
var center = fabric.util.transformPoint(point, canvas.viewportTransform);
var clampedCenterX = clamp(center.x, xMin, xMax);
var clampedCenterY = clamp(center.y, yMin, yMax);
var diffX = clampedCenterX - center.x;
var diffY = clampedCenterY - center.y;
if (diffX != 0 || diffY != 0) {
canvas.relativePan(new fabric.Point(diffX, diffY));
}
}
function clamp(value, min, max) {
return Math.max(min, Math.min(value, max));
}
#c {
background-color: grey;
margin-top: 10px;
}
button {
padding: 10px 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.1.0/fabric.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<button id="door">Door</button>
<button id="delete">Delete Door</button>
<button id="save">Save</button>
<button id="getid">GET ID</button>
<button id="btnResetZoom">Reset Zoom</button>
<canvas id="c" width="800" height="800"></canvas>
<br>
<p class="save">
</p>

I think you should use the transformPoint method to translate position
$("#door").on("click", function (e) {
const points = {};
const iVpt = fabric.util.invertTransform(canvas.viewportTransform);
points.tl = fabric.util.transformPoint({x: 40, y: 40}, iVpt);
rect = new fabric.Rect({
id: uniqid,
left: points.tl.x,
top: points.tl.y,
width: 35,
height: 50,
fill: "blue",
stroke: "blue",
strokeWidth: 5,
strokeUniform: false,
hasControls: true,
});

Related

phaser 3 Trying to make bullet travel towards a location

i am trying to make my bullet travel towards the cursor location. I have tried lots of things and I just can't get it to work. I have the player arm set up to always move to the player shoulder level. The player's arm and the gun has the same rotation value. The rotation value is calculated using Phaser.Math.Angle.BetweenPoints(playerArm, player1Aim);. I found a couple examples but i couldn't get them to work. Please teach me how to use it. I am a newbie. Please help. Here is my code:
var config = {
type: Phaser.AUTO,
width: 512,
height: 512,
physics: {
default: 'arcade',
arcade: {
gravity: {
y: 1500
},
debug: false
}
},
scene: {
preload: preload,
create: create,
update: update
}
// plugins: {
// global: [{
// key: 'PhaserPauseRenderPlugin',
// plugin: PhaserPauseRenderPlugin,
// mapping: 'render'
// }]
// }
};
// class SceneMain extends Phaser.Scene {
// constructor() {
// super('SceneMain');
// }
// preload() {}
// create() {
// //make 3 bars
// let healthBar = this.makeBar(140, 100, 0x2ecc71);
// this.setValue(healthBar, 100);
// // let powerBar = this.makeBar(140, 200, 0xe74c3c);
// // this.setValue(powerBar, 50);
// // let magicBar = this.makeBar(140, 300, 0x2980b9);
// // this.setValue(magicBar, 33);
// }
// makeBar(x, y, color) {
// //draw the bar
// let bar = this.add.graphics();
// //color the bar
// bar.fillStyle(color, 1);
// //fill the bar with a rectangle
// bar.fillRect(0, 0, 200, 50);
// //position the bar
// bar.x = x;
// bar.y = y;
// //return the bar
// return bar;
// }
// setValue(bar, percentage) {
// //scale the bar
// bar.scaleX = percentage / 100;
// }
// update() {}
// }
var player;
var platforms;
var cursors;
var gameOver = false;
var score = 0;
var time;
var waves;
var enemies;
var enemy;
var health;
var hacking = false;
var timer;
var enemyCount = 0;
var startGame = false;
var timeSpeed = 1;
var keys;
var damageStrike = 0;
var toMouse = 0;
var toPlayer = 0;
var bullets;
var ship;
var speed;
var stats;
var cursors;
var lastFired = 0;
var fire = false;
var pointerDown = false;
// var healthBar = new SceneMain();
// spaceBar input
// var spaceBar = Phaser.Input.Keyboard.KeyCodes.SPACE;
var game = new Phaser.Game(config);
function preload() {
//this.load.image('platform', 'images/platform.png');
// this.load.image('background', 'images/background.png');z
this.load.image('background', 'images/background.png');
this.load.image('platform', 'images/platform.png');
this.load.image('longPlatform', 'images/platform long.png');
this.load.image('itembg', 'images/item bg.png');
this.load.image('playerArm', 'images/player arm.png');
this.load.image('enemyArm', 'images/enemy arm.png');
this.load.image('playerGun', 'images/player gun.png');
this.load.image('enemyGun', 'images/enemy gun.png');
this.load.image('medkit', 'images/medkit.png');
this.load.image('aim', 'images/aim.png');
this.load.image('bullet', 'images/laser.png');
this.load.spritesheet('player', 'images/player idle-1.png', {
frameWidth: 49,
frameHeight: 128
});
this.load.spritesheet('enemy', 'images/enemy.png', {
frameWidth: 49,
frameHeight: 128
});
}
function create() {
// var Bullet = new Phaser.Class({
// Extends: Phaser.GameObjects.Image,
// initialize:
// // Bullet Constructor
// function Bullet(scene) {
// Phaser.GameObjects.Image.call(this, scene, 0, 0, 'bullet');
// this.speed = 1;
// this.born = 0;
// this.direction = 0;
// this.xSpeed = 0;
// this.ySpeed = 0;
// this.setSize(12, 12, true);
// },
// // Fires a bullet from the player to the reticle
// fire: function(player, target) {
// this.setPosition(player.x, player.y); // Initial position
// this.direction = Math.atan((target.x - this.x) / (target.y - this.y));
// // Calculate X and y velocity of bullet to moves it from shooter to target
// if (target.y >= this.y) {
// this.xSpeed = this.speed * Math.sin(this.direction);
// this.ySpeed = this.speed * Math.cos(this.direction);
// } else {
// this.xSpeed = -this.speed * Math.sin(this.direction);
// this.ySpeed = -this.speed * Math.cos(this.direction);
// }
// this.rotation = player.rotation; // angle bullet with shooters rotation
// this.born = 0; // Time since new bullet spawned
// },
// // Updates the position of the bullet each cycle
// update: function(time, delta) {
// this.x += this.xSpeed * delta;
// this.y += this.ySpeed * delta;
// this.born += delta;
// if (this.born > 500) {
// this.setActive(false);
// this.setVisible(false);
// }
// }
// });
// playerBullets = this.physics.add.group({
// classType: Bullet,
// runChildUpdate: true
// });
speed = Phaser.Math.GetSpeed(300, 1);
// healthBar.makeBar(32, 32, 0xffffff);
// console.log(timer);
// add background
// this.add.image(256, 256, 'background');
background = this.add.image(256, 256, 'background');
background.alpha = 0.8;
itemBg = this.add.image(256, 520, 'itembg')
platforms = this.physics.add.staticGroup();
// Here we create the ground.
platforms.create(256, 450, 'longPlatform').refreshBody();;
// platforms.create(256, 450, 'platform');
platforms.create(50, 175, 'platform');
platforms.create(460, 175, 'platform');
platforms.create(50, 350, 'platform');
platforms.create(460, 350, 'platform');
platforms.create(265, 250, 'platform');
player = this.physics.add.sprite(256, 10, 'player');
player.setScale(0.5);
player.setBounce(0.1);
player.setCollideWorldBounds(true);
playerArm = this.add.image(256, 256, 'playerArm');
playerArm.setScale(0.5);
playerArm.angle = 0;
playerGun = this.add.image(256, 256, 'playerGun');
playerGun.setScale(0.5);
playerGun.angle = 0;
enemyArm = this.add.image(256, 256, 'enemyArm');
enemyArm.setScale(0.5);
enemyArm.angle = 0;
enemyGun = this.add.image(256, 256, 'enemyGun');
enemyGun.setScale(0.5);
enemyGun.angle = 0;
player1Aim = this.add.image(256, 256, 'aim');
player1Aim.setScale(2);
player1Aim.angle = 0;
bullet = this.add.image(256, 10, 'bullet');
bullet.setScale(0.25);
bullet.angle = 0;
var playerX = player.x;
var playerY = player.y;
enemies = this.physics.add.group();
medkits = this.physics.add.group();
spawn = (x, enemyName) => {
enemyPlayer = this.physics.add.sprite(x, 20, enemyName);
// enemyPlayer = this.physics.add.sprite.destroy(true);
console.log(enemyPlayer);
enemyPlayer.setScale(0.5);
enemyPlayer.setBounce(0.1);
enemyPlayer.setCollideWorldBounds(true);
enemyPlayer.allowGravity = true;
return enemyPlayer;
}
spawnMedkit = (x, enemyName) => {
enemyPlayer = this.physics.add.sprite(x, 20, enemyName);
// enemyPlayer = this.physics.add.sprite.destroy(true);
console.log(enemyPlayer);
enemyPlayer.setScale(1);
enemyPlayer.setBounce(0.1);
enemyPlayer.setCollideWorldBounds(true);
enemyPlayer.allowGravity = true;
return enemyPlayer;
}
enemy = spawn(450, 'enemy');
medkit = spawnMedkit(100, 'medkit');
enemyCount += 1;
console.log(enemyCount);
// enemy = enemies.create(450, 20, 'enemy')
// // enemies.create(250, 20, 'enemy')
// enemy.setScale(0.5)
// enemy.setBounce(0.1);
// enemy.setCollideWorldBounds(true);
// enemy.allowGravity = true;
cursors = this.input.keyboard.createCursorKeys();
this.physics.add.collider(player, platforms);
this.physics.add.collider(enemy, platforms);
this.physics.add.collider(medkit, platforms);
// this.physics.add.collider(bombs, platforms);
health = 100;
waves = 0;
// timer = this.time.create(false);
// The score
scoreText = this.add.text(16, 16, 'score: 0', {
fontSize: '25px',
fill: '#00FFFF'
});
// FPS
fps = this.add.text(16, 50, game.loop.actualFps, {
fontSize: '15px',
fill: '#00FFFF'
});
timeScale = this.add.text(16, 70, this.physics.world.timeScale, {
fontSize: '15px',
fill: '#00FFFF'
});
gunRotation = this.add.text(16, 100, 'gun rotation: 0', {
fontSize: '15px',
fill: '#00FFFF'
});
// gameStatus = this.add.text(16, 60, 'Game Status: Alive', {
// fontSize: '25px',
// fill: '#00FFFF'
// });
// hp = this.add.text(16, 100, 'Health: ' + health, {
// fontSize: '25px',
// fill: '#00FFFF'
// });
// add collisions
this.physics.add.collider(player, enemy, damage, null, this);
this.physics.add.collider(player, medkit, healByMedkit, null, this);
// this.physics.add.collider(laser, enemy, hit, null, this);
keys = this.input.keyboard.addKeys('W,A,S,D,F,J,K,L,SPACE');
var r1 = this.add.rectangle(playerX, playerY - 15, 200, 69, 10, 0x6666ff);
this.input.on('pointermove', function(pointer) {
toMouse = Phaser.Math.Angle.BetweenPoints(playerArm, player1Aim);
});
this.input.on('pointerdown', function(pointer) {
// shoot the bullet towards the cursor (player1Aim)
});
startGame = true;
}
function update(time, delta) {
var playerX = player.x;
var playerY = player.y;
var enemyX = enemy.x;
var enemyY = enemy.y;
var playerArmX = playerArm.x;
var playerArmY = playerArm.y;
var playerArmRotation = playerArm.angle;
var mouseX = game.input.mousePointer.x;
var mouseY = game.input.mousePointer.y;
// var theta =
// console.log(playerArmRotation);
// position the arm to the shoulder level of the player
playerArm.x = playerX;
playerArm.y = playerY - 5;
playerGun.x = playerX;
playerGun.y = playerY - 3;
enemyArm.x = enemyX;
enemyArm.y = enemyY - 5;
enemyGun.x = enemyX;
enemyGun.y = enemyY - 5;
player1Aim.x = mouseX;
player1Aim.y = mouseY;
toPlayer = Phaser.Math.Angle.BetweenPoints(enemy, player);
playerArm.rotation = Phaser.Math.Angle.BetweenPoints(playerArm, player1Aim);
playerGun.rotation = Phaser.Math.Angle.BetweenPoints(playerArm, player1Aim);
enemyArm.rotation = toPlayer;
enemyGun.rotation = toPlayer;
// rotate gun for player
if (playerGun.angle >= 90 || playerGun.angle <= -90) {
playerGun.flipY = true;
// console.log('flipped')
} else {
playerGun.flipY = false;
}
// rotate gun for player
if (enemyGun.angle >= 90 || enemyGun.angle <= -90) {
enemyGun.flipY = true;
// console.log('flipped')
} else {
enemyGun.flipY = false;
}
// this.input.on('pointerdown', function(pointer) {
// if (pointerDown == false) {
// pointerDown = true;
// fire();
// console.log('FIRE');
// } else {
// pointerDown = false;
// }
// });
// this.input.on('pointerdown', function(pointer, time, lastFired) {
// if (player.active === false)
// return;
// // Get bullet from bullets group
// var bullet = playerBullets.get().setActive(true).setVisible(true);
// if (bullet) {
// bullet.fire(playerGun, player1Aim);
// // this.physics.add.collider(enemy, bullet, enemyHitCallback);
// }
// }, this);
// this.input.on('pointerdown', function(pointer) {
// if (time > lastFired) {
// var bullet = bullets.get();
// console.log('test2');
// if (bullet) {
// // bullet.rotation = playerGun.rotation;
// bullet.fire(playerGun.x, playerGun.y);
// lastFired = time + 50;
// }
// }
// });
if (startGame == true) {
if (keys.J.isDown) {
this.physics.world.timeScale = 1.75;
// console.log(this.physics.world.timeScale);
// timeSpeed = 0.5;
// console.log(timeSpeed);
} else
if (keys.K.isDown) {
this.physics.world.timeScale = 0.75;
// timeSpeed = 1;
}
if (keys.L.isDown) {
}
if (gameOver) {
return;
gameStatus.setText('Game Status: Dead')
}
if (cursors.left.isDown || keys.A.isDown) {
player.setVelocityX(-160 * timeSpeed);
} else if (cursors.right.isDown || keys.D.isDown) {
player.setVelocityX(160 * timeSpeed);
} else {
player.setVelocityX(0 * timeSpeed);
}
if (cursors.up.isDown && player.body.touching.down) {
player.setVelocityY(-650 * timeSpeed);
}
if (keys.W.isDown && player.body.touching.down) {
player.setVelocityY(-650 * timeSpeed);
}
if (keys.SPACE.isDown && player.body.touching.down) {
player.setVelocityY(-650 * timeSpeed);
}
if (waves == 0) {
waves += 1;
console.log(waves)
}
fps.setText('fps: ' + game.loop.actualFps);
scoreText.setText('Score: ' + score);
timeScale.setText('timeScale: ' + this.physics.world.timeScale);
gunRotation.setText('gun rotation: ' + playerGun.angle);
}
}
function damage(player, enemy) {
enemy.disableBody(true, true);
// enemy.body.enable = false;
// enemy.body.gameObject.active = false;
enemyCount -= 1;
console.log(enemyCount);
health -= 10;
score -= 10;
damageStrike += 1;
if (enemyCount === 0) {
var randomX = Phaser.Math.FloatBetween(0, 500);
enemy.enableBody(true, randomX, 15, true, true);
enemyCount += 1;
console.log(enemyCount);
}
if (damageStrike === 3 && medkits.countActive(false) == 0) {
var randomX = Phaser.Math.FloatBetween(0, 500);
medkit.enableBody(true, randomX, 15, true, true);
damageStrike = 0;
}
console.log('Health: ' + health);
if (health <= 0) {
gameOver = true;
}
}
function hit(laser, enemy) {
score += 10;
enemy.disableBody(true, true);
}
function healByMedkit(player, medkit) {
score += 5;
health += 15;
console.log(health);
medkit.disableBody(true, true);
}
Well if you want to rotate a gameObjects and shoot something in a specific angle, in Phaser you should have to keep somethings in mind:
Origin of the gameObject (since the rotation occurs around this point)
The direction / angle offset of the gameObject you want to rotate
Apart from that, everything is more or less straightforward, calculate the vector for "shooting" a bullet and set the velocity of that bullet.
Here a short demo:
In this Demo, the both main factors are shown, origin and "angle-offset".
(It should cover the basic from your code)
document.body.style = 'margin:0;';
var config = {
type: Phaser.AUTO,
width: 536,
height: 183,
physics: {
default: 'arcade',
arcade: {
gravity:{ y: 50 },
}
},
scene: {
create,
update
},
banner: false
};
function create () {
this.add.text(10, 10, 'Click to shoot bullets')
.setOrigin(0);
// head
this.add.circle ( 42, 60, 8, 0xffffff)
.setOrigin(0);
// body
let player = this.add.rectangle( 40, 80, 20, 50, 0xffffff)
.setOrigin(0);
// sholder
this.add.circle ( 50, 90, 5, 0xff0000)
.setOrigin(0.5);
// arm
let playerArm = this.add.rectangle( 50, 90, 10, 30, 0xff0000)
// Point #1: the Point of rotation is more or less the shoulder
.setOrigin(.5, 0)
.setDepth(10);
// create bullet Group
this.bullets = this.add.group();
this.input.on('pointermove', pointer => {
let rotation = Phaser.Math.Angle.BetweenPoints(playerArm, pointer);
// Point #2: Angle-Offset since the 0 Degrees is on the right,
// and the arm is pointing down I need to subtract 90° 0 PI/2
playerArm.rotation = rotation - Math.PI / 2;
});
this.input.on('pointerdown', pointer => {
let speed = 300;
// create bullet
let bullet = this.add.circle( playerArm.x, playerArm.y, 4, 0xffff00)
.setDepth(9);
this.physics.add.existing(bullet);
// get Vector where to shoot bullet
let vector = new Phaser.Math.Vector2( pointer.x - playerArm.x, pointer.y - playerArm.y );
// set Speed of bullet
vector.setLength(speed);
// DEMO: to shoot in a straightline, just comment the following line in
// bullet.body.setAllowGravity(false);
// DEMO: QuickFix to destroy the bullet after 1 Second automatically
// setTimeout( () => bullet.destroy(), 1000);
// add bullet to group
this.bullets.add(bullet);
bullet.body.setVelocity(vector.x, vector.y);
});
}
function update(){
this.bullets.getChildren().forEach(bullet => {
if(bullet.x > config.width){
bullet.destroy();
}
})
}
new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
If you want the bullet to fly without gravity / in a straight line, just add this line bullet.body.setAllowGravity(false); after the creation of the bullet, to turn off the physics effect for the bullet.

Draw moving line in phaser 3

I want to draw line, where it's first pair of coordinates situated in the center of drew circle and it's second pair will be unsettled until I direct it to the cirlce with the same color, which have first one. Do you have any ideas?
My code:
let config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#f0ebeb',
physics: {
default: 'arcade',
arcade: {
gravity: { y: 300 },
debug: false
}
},
scene: {
preload: preload,
create: create,
update: update
},
scale: {
autoCenter: Phaser.Scale.CENTER_BOTH
}
};
let game = new Phaser.Game(config);
let items = [];
let dots = new Map([
[1, '#4293f5'],
[2, '#42f554'],
[3, '#f5e942'],
[4, '#f55a42'],
[5, '#f542c8'],
])
function preload() {
}
function create() {
let x = 100;
let y = 0;
for (i = 0; i < 36; i++) {
if (i % 6 === 0) {
y += 85;
x = 100;
}
this.add.circle(x, y, 35, parseInt(dots.get(getRandomInt(5)).replace(/^#/, ''), 16));
x += 125;
}
}
function update() { }
function getRandomInt(max) {
return Math.floor(Math.random() * max) + 1;
}
What I am trying to do: https://play.google.com/store/apps/details?id=com.nerdyoctopus.gamedots
A quick possible solution could be to use the pointer Events (pointerdown, pointermove and pointerup) of the scene. Here is a demo code, with the basic functionality
let config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 400,
height: 200,
scene: { create }
};
let game = new Phaser.Game(config);
let isDragging = false;
let lineStartPosition = {x:0 , y:0};
let line;
function create ()
{
let cicles = []
for(let rowIdx = 0; rowIdx < 4; rowIdx++ ){
for(let colIdx = 0; colIdx < 2; colIdx++ ){
let circle = this.add.circle(50 + 100 * rowIdx, 50 + 100 * colIdx, 25, 0x6666ff).setOrigin(.5);
circle.setInteractive();
cicles.push(circle);
}
}
line = this.add.line(0,0, 0,0, 100, 100, 0xffffff).setOrigin(0);
line.setLineWidth(5);
line.visible = false;
// adding the events to the scene
this.input.on('pointerdown', dragStart);
this.input.on('pointerup', dragEnd);
this.input.on('pointermove', drag);
}
function dragStart(pointer, gameObjects){
if(gameObjects.length == 0)
return
lineStartPosition.x = gameObjects[0].x;
lineStartPosition.y = gameObjects[0].y;
isDragging = true;
line.x = gameObjects[0].x;
line.y = gameObjects[0].y;
line.setTo(0, 0, 0, 0);
line.visible = true;
}
function drag(pointer, gameObject){
if(isDragging == true){
line.setTo(0, 0, pointer.x - lineStartPosition.x, pointer.y - lineStartPosition.y);
}
}
function dragEnd(pointer, gameObject){
isDragging = false;
}
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>

Drawing repeating image behind Divs

var sketcher = null;
var brush = null;
function Sketcher(canvasID, brushImage) {
this.renderFunction = (brushImage == null || brushImage == undefined) ? this.updateCanvasByLine : this.updateCanvasByBrush;
this.brush = brushImage;
this.touchSupported = Modernizr.touch;
this.canvasID = canvasID;
this.canvas = $("#" + canvasID);
this.context = this.canvas.get(0).getContext("2d");
this.context.strokeStyle = "#000000";
this.context.lineWidth = 3;
this.lastMousePoint = {
x: 0,
y: 0
};
if (this.touchSupported) {
this.mouseDownEvent = "touchstart";
this.mouseMoveEvent = "touchmove";
this.mouseUpEvent = "touchend";
} else {
this.mouseDownEvent = "mousedown";
this.mouseMoveEvent = "mousemove";
this.mouseUpEvent = "mouseup";
}
this.canvas.bind(this.mouseMoveEvent, this.onCanvasMouseMove());
}
Sketcher.prototype.onCanvasMouseMove = function() {
var self = this;
return function(event) {
self.mouseMoveHandler = self.onCanvasMouseMove()
self.mouseUpHandler = self.onCanvasMouseUp()
$(document).bind(self.mouseMoveEvent, self.mouseMoveHandler);
$(document).bind(self.mouseUpEvent, self.mouseUpHandler);
self.updateMousePosition(event);
self.renderFunction(event);
}
}
Sketcher.prototype.onCanvasMouseMove = function() {
var self = this;
return function(event) {
self.renderFunction(event);
event.preventDefault();
return false;
}
}
Sketcher.prototype.onCanvasMouseUp = function(event) {
var self = this;
return function(event) {
$(document).unbind(self.mouseMoveEvent, self.mouseMoveHandler);
$(document).unbind(self.mouseUpEvent, self.mouseUpHandler);
self.mouseMoveHandler = null;
self.mouseUpHandler = null;
}
}
Sketcher.prototype.updateMousePosition = function(event) {
var target;
if (this.touchSupported) {
target = event.originalEvent.touches[0]
} else {
target = event;
}
var offset = this.canvas.offset();
this.lastMousePoint.x = target.pageX - offset.left;
this.lastMousePoint.y = target.pageY - offset.top;
}
Sketcher.prototype.updateCanvasByLine = function(event) {
this.context.beginPath();
this.context.moveTo(this.lastMousePoint.x, this.lastMousePoint.y);
this.updateMousePosition(event);
this.context.lineTo(this.lastMousePoint.x, this.lastMousePoint.y);
this.context.stroke();
}
Sketcher.prototype.updateCanvasByBrush = function(event) {
var halfBrushW = this.brush.width / 2;
var halfBrushH = this.brush.height / 2;
var start = {
x: this.lastMousePoint.x,
y: this.lastMousePoint.y
};
this.updateMousePosition(event);
var end = {
x: this.lastMousePoint.x,
y: this.lastMousePoint.y
};
var distance = parseInt(Trig.distanceBetween2Points(start, end));
var angle = Trig.angleBetween2Points(start, end);
var x, y;
for (var z = 0;
(z <= distance || z == 0); z++) {
x = start.x + (Math.sin(angle) * z) - halfBrushW;
y = start.y + (Math.cos(angle) * z) - halfBrushH;
//console.log( x, y, angle, z );
this.context.drawImage(this.brush, x, y);
}
}
Sketcher.prototype.toString = function() {
var dataString = this.canvas.get(0).toDataURL("image/png");
var index = dataString.indexOf(",") + 1;
dataString = dataString.substring(index);
return dataString;
}
Sketcher.prototype.toDataURL = function() {
var dataString = this.canvas.get(0).toDataURL("image/png");
return dataString;
}
var Trig = {
distanceBetween2Points: function ( point1, point2 ) {
var dx = point2.x - point1.x;
var dy = point2.y - point1.y;
return Math.sqrt( Math.pow( dx, 2 ) + Math.pow( dy, 2 ) );
},
angleBetween2Points: function ( point1, point2 ) {
var dx = point2.x - point1.x;
var dy = point2.y - point1.y;
return Math.atan2( dx, dy );
}
}
var canvas = document.getElementById("sketch");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
brush = new Image();
brush.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/e/eb/Ash_Tree_-_geograph.org.uk_-_590710.jpg/440px-Ash_Tree_-_geograph.org.uk_-_590710.jpg";
brush.onload = function() {
sketcher = new Sketcher("sketch", brush);
};
body {
margin: 0;
padding: 0;
}
* {
box-sizing: border-box;
}
.sketch-container {
position: relative;
position: absolute;
height: 100vh;
width: 100%;
}
#sketch {
background: none yellow;
position: absolute;
height: 100vh;
width: 100%;
}
.button-container {
position: absolute;
left: 10px;
top: 10px;
opacity: .5;
background: none blue;
font-size: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
<div class="sketch-container">
<canvas id="sketch"></canvas>
<button type="button" class="button-container">Can you draw below me?</button>
</div>
I am drawing an image using this javascript code:
var sketcher = null;
var brush = null;
function Sketcher(canvasID, brushImage) {
this.renderFunction = (brushImage == null || brushImage == undefined) ? this.updateCanvasByLine : this.updateCanvasByBrush;
this.brush = brushImage;
this.touchSupported = Modernizr.touch;
this.canvasID = canvasID;
this.canvas = $("#" + canvasID);
this.context = this.canvas.get(0).getContext("2d");
this.context.strokeStyle = "#000000";
this.context.lineWidth = 3;
this.lastMousePoint = {
x: 0,
y: 0
};
if (this.touchSupported) {
this.mouseDownEvent = "touchstart";
this.mouseMoveEvent = "touchmove";
this.mouseUpEvent = "touchend";
} else {
this.mouseDownEvent = "mousedown";
this.mouseMoveEvent = "mousemove";
this.mouseUpEvent = "mouseup";
}
this.canvas.bind(this.mouseMoveEvent, this.onCanvasMouseMove());
}
Sketcher.prototype.onCanvasMouseMove = function() {
var self = this;
return function(event) {
self.mouseMoveHandler = self.onCanvasMouseMove()
self.mouseUpHandler = self.onCanvasMouseUp()
$(document).bind(self.mouseMoveEvent, self.mouseMoveHandler);
$(document).bind(self.mouseUpEvent, self.mouseUpHandler);
self.updateMousePosition(event);
self.renderFunction(event);
}
}
Sketcher.prototype.onCanvasMouseMove = function() {
var self = this;
return function(event) {
self.renderFunction(event);
event.preventDefault();
return false;
}
}
Sketcher.prototype.onCanvasMouseUp = function(event) {
var self = this;
return function(event) {
$(document).unbind(self.mouseMoveEvent, self.mouseMoveHandler);
$(document).unbind(self.mouseUpEvent, self.mouseUpHandler);
self.mouseMoveHandler = null;
self.mouseUpHandler = null;
}
}
Sketcher.prototype.updateMousePosition = function(event) {
var target;
if (this.touchSupported) {
target = event.originalEvent.touches[0]
} else {
target = event;
}
var offset = this.canvas.offset();
this.lastMousePoint.x = target.pageX - offset.left;
this.lastMousePoint.y = target.pageY - offset.top;
}
Sketcher.prototype.updateCanvasByLine = function(event) {
this.context.beginPath();
this.context.moveTo(this.lastMousePoint.x, this.lastMousePoint.y);
this.updateMousePosition(event);
this.context.lineTo(this.lastMousePoint.x, this.lastMousePoint.y);
this.context.stroke();
}
Sketcher.prototype.updateCanvasByBrush = function(event) {
var halfBrushW = this.brush.width / 2;
var halfBrushH = this.brush.height / 2;
var start = {
x: this.lastMousePoint.x,
y: this.lastMousePoint.y
};
this.updateMousePosition(event);
var end = {
x: this.lastMousePoint.x,
y: this.lastMousePoint.y
};
var distance = parseInt(Trig.distanceBetween2Points(start, end));
var angle = Trig.angleBetween2Points(start, end);
var x, y;
for (var z = 0;
(z <= distance || z == 0); z++) {
x = start.x + (Math.sin(angle) * z) - halfBrushW;
y = start.y + (Math.cos(angle) * z) - halfBrushH;
//console.log( x, y, angle, z );
this.context.drawImage(this.brush, x, y);
}
}
Sketcher.prototype.toString = function() {
var dataString = this.canvas.get(0).toDataURL("image/png");
var index = dataString.indexOf(",") + 1;
dataString = dataString.substring(index);
return dataString;
}
Sketcher.prototype.toDataURL = function() {
var dataString = this.canvas.get(0).toDataURL("image/png");
return dataString;
}
var Trig = {
distanceBetween2Points: function ( point1, point2 ) {
var dx = point2.x - point1.x;
var dy = point2.y - point1.y;
return Math.sqrt( Math.pow( dx, 2 ) + Math.pow( dy, 2 ) );
},
angleBetween2Points: function ( point1, point2 ) {
var dx = point2.x - point1.x;
var dy = point2.y - point1.y;
return Math.atan2( dx, dy );
}
}
var canvas = document.getElementById("sketch");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
brush = new Image();
brush.src = "https://upload.wikimedia.org/wikipedia/commons/thumb/e/eb/Ash_Tree_-_geograph.org.uk_-_590710.jpg/440px-Ash_Tree_-_geograph.org.uk_-_590710.jpg";
brush.onload = function() {
sketcher = new Sketcher("sketch", brush);
};
It works well and draws an image exactly as I would like. However, I have divs on top with text for which I have onclick functions on.
Picture of how the image is being drawn
The problem is the image is not being drawn underneath the divs because the canvas is under them. I understand I may need to add a listener to the window and draw according to that, but I have tried and tried and do not understand where something like that goes/what needs to be replaced.
Something that I've tried is to get rid of pointer events, which of course works to maintain the continuity of the image being dragged, but prevents me from clicking on the button.
Thanks

Trying to remove quadtree from javascript game

I got an agar.io clone from online and I am trying to remove the Quadtree in the corner (acts as a map) completely! I try to delete everything associating with the quadtree but i end up with a gray screen. Could someone please remove the map from the top right corner for me or tell me which lines to remove?
Here is my HTML:
<div id="viewport">
<canvas id="canvas1"></canvas>
<canvas id="canvas2"></canvas>
<canvas id="canvas3" width="250px" height="250px"></canvas>
</div>
Here is my javascript:
var MouseHandler = (function() {
var x = 0;
var y = 0;
var mouseIn = false;
var init = function(eventSrc) {
eventSrc.addEventListener('mousemove', onMouseMove);
eventSrc.addEventListener('mouseout', onMouseOut);
eventSrc.addEventListener('mouseover', onMouseOver);
};
var onMouseOut = function() {
mouseIn = false;
};
var onMouseOver = function() {
mouseIn = true;
};
var onMouseMove = function(e) {
x = e.clientX;
y = e.clientY;
};
var getPos = function() {
return {
x: x,
y: y
};
};
var isMouseIn = function() {
return mouseIn;
};
return {
init: init,
getPos: getPos,
isMouseIn: isMouseIn
};
}());
Quadtree.MAX_OBJECTS = 5;
Quadtree.MAX_LEVEL = 5;
function Quadtree(lvl, bnds) {
var level = lvl;
var bounds = bnds;
var objects = [];
var nodes = [];
var xMiddle = bounds.x + (bounds.width / 2);
var yMiddle = bounds.y + (bounds.height / 2);
var clear = function() {
objects = [];
nodes = [];
};
var split = function() {
nodes[0] = new Quadtree(level+1, {x: xMiddle, y: bounds.y , width: bounds.width/2, height: bounds.height/2});
nodes[1] = new Quadtree(level+1, {x: bounds.x, y: bounds.y, width: bounds.width/2, height: bounds.height/2});
nodes[2] = new Quadtree(level+1, {x: bounds.x, y: yMiddle, width: bounds.width/2, height: bounds.height/2});
nodes[3] = new Quadtree(level+1, {x: xMiddle, y: yMiddle, width: bounds.width/2, height: bounds.height/2});
};
var getIndex = function(rec) {
var top = (rec.y > bounds.y && (rec.y+rec.height) < yMiddle);
var bottom = (rec.y > yMiddle && (rec.y+rec.height) < (bounds.y+bounds.height));
if(rec.x > bounds.x && (rec.x+rec.width) < xMiddle) {
if(top) {
return 1;
} else if(bottom) {//LEFT
return 2;
}
} else if(rec.x > xMiddle && (rec.x+rec.width) < (bounds.x+bounds.width)) {
if(top) {
return 0;
} else if(bottom) {//RIGHT
return 3;
}
}
return -1;
};
var insert = function(ent) {
var rec = ent.getBounds();
var index = getIndex(rec);
var len = 0;
var i = 0;
if(nodes[0] && index !== -1) {
nodes[index].insert(ent);
return;
}
objects.push(ent);
if(objects.length > Quadtree.MAX_OBJECTS && level < Quadtree.MAX_LEVEL) {
if(!nodes[0]) {
split();
}
len = objects.length;
while(i < objects.length) {
index = getIndex(objects[i].getBounds());
if(index !== -1) {
nodes[index].insert(objects[i]);
objects.splice(i, 1);
} else {
i += 1;
}
}
}
};
var retrieve = function (list, ent) {
var rec1 = bounds;
var rec2 = ent.getBounds();
if(rec2.x < (rec1.x+rec1.width) && (rec2.x+rec2.width) > rec1.x &&
rec2.y < (rec1.y+rec1.height) && (rec2.y+rec2.height) > rec1.y) {
for(var o in objects) {
if(objects[o] !== ent) {
list.push(objects[o]);
}
}
if(nodes.length) {
nodes[0].retrieve(list, ent);
nodes[1].retrieve(list, ent);
nodes[2].retrieve(list, ent);
nodes[3].retrieve(list, ent);
}
}
return list;
};
var drawTree = function(ctx) {
draw(ctx);
if(nodes[0]) {
nodes[0].drawTree(ctx);
nodes[1].drawTree(ctx);
nodes[2].drawTree(ctx);
nodes[3].drawTree(ctx);
}
};
var draw = function(ctx) {
var entAttr = null
ctx.strokeStyle = 'black';
ctx.lineWidth = 1;
ctx.strokeRect(bounds.x/20, bounds.y/20, bounds.width/20, bounds.height/20);
ctx.fillStyle = 'gray';
for(o in objects) {
entAttr = objects[o].getAttr();
ctx.fillRect(entAttr.x/20, entAttr.y/20, 3, 3);
}
};
var toString = function() {
return '('+bounds.x+','+bounds.y+')'+'['+bounds.width+','+bounds.height+']';
};
return {
clear: clear,
insert: insert,
retrieve: retrieve,
drawTree: drawTree,
toString: toString,
};
}
function Circle(attr) {
attr = attr || {};
var x = attr.x || 0;
var y = attr.y || 0;
var mass = attr.mass || 500;
var color = attr.color || 'white';
var borderColor = attr.borderColor || 'black';
var velX = attr.velX || 0;
var velY = attr.velY || 0;
var droplet = attr.droplet || false;
var maxVel = 80 * (80 / Math.sqrt(mass));
var radius = Math.sqrt( mass / Math.PI ); //1 unit of area === 1 uni of mass
var getAttr = function() {
return {
x: x,
y: y,
mass: mass,
radius: radius,
color: color,
velX: velX,
velY: velY,
maxVel: maxVel
};
};
var setAttr = function(attr) {
x = (attr.x !== undefined)? attr.x: x;
y = (attr.y !== undefined)? attr.y: y;
mass = (attr.mass !== undefined)? attr.mass: mass;
color = (attr.color !== undefined)? attr.color: color;
velX = (attr.velX !== undefined)? attr.velX: velX;
velY = (attr.velY !== undefined)? attr.velY: velY;
};
var incMass = function(dMass) {
mass += dMass;
maxVel = 100 * (100 / Math.sqrt(mass));
radius = Math.sqrt( mass / Math.PI );
};
var intersects = function(ent2) {
var ent2Attr = ent2.getAttr();
var dX = Math.abs(ent2Attr.x - x);
var dY = Math.abs(ent2Attr.y - y);
var totalRadius = ent2Attr.radius + radius;
return (dX < totalRadius && dY < totalRadius);
};
var draw = function(ctx, cam) {
var camSize = cam.getSize();
var rPos = cam.getRelPos(getAttr());
//if outside Cam view
if((rPos.x + radius) < 0 || (rPos.y + radius) < 0 || (rPos.x - radius) > camSize.width || (rPos.y - radius) > camSize.height) {
return;
}
ctx.fillStyle = color;
ctx.strokeStyle = borderColor;
ctx.lineWidth = 5;
ctx.beginPath();
ctx.arc(rPos.x, rPos.y, radius, 0, 2 * Math.PI, false);
ctx.fill();
ctx.stroke();
};
var update = !droplet && function(dTime) {
x += velX * dTime;
y += velY * dTime;
};
var getBounds = function() {
return {
x: x-radius,
y: y-radius,
width: radius*2,
height: radius*2,
};
};
return {
getBounds: getBounds,
getAttr: getAttr,
setAttr: setAttr,
incMass: incMass,
intersects: intersects,
draw: draw,
update: update
};
}
var gameManager = (function() {
var canvasGrid = null;
var canvasEnt = null;
var canvasQuadtree = null;
var ctxGrid = null;
var ctxEnt = null;
var ctxQuadTree = null;
var dTime = 1 / 60;
var player = null;
var entityBag = [];
var qTree = null;
var drwQuad = 0;
var addEntity = function(ent) {
entityBag.push(ent);
};
var removeEntity = function(ent) {
var len = entityBag.length;
var i = 0;
for(i=0; i<len; i+=1) {
if(ent === entityBag[i]) {
entityBag.splice(i, 1);
return;
}
}
};
var init = function(cvsGridId, cvsEntId, cvsQuadtree) {
canvasGrid = document.getElementById(cvsGridId);
canvasEnt = document.getElementById(cvsEntId);
canvasQuadtree = document.getElementById(cvsQuadtree);
ctxGrid = canvasGrid.getContext('2d');
ctxEnt = canvasEnt.getContext('2d');
ctxQuadtree = canvasQuadtree.getContext('2d');
fitToContainer(canvasGrid);
fitToContainer(canvasEnt);
ctxGrid.fillStyle = '#F0FBFF';
ctxGrid.strokeStyle = '#BFBFBF';
ctxGrid.lineWidth = 1;
MouseHandler.init(document);
qTree = new Quadtree(0, {x:0, y:0, width:5000, height:5000});
player = new Circle({
x: 50,
y: 50,
color: 'red',
mass: 1000,
velX: 500,
velY:500
});
Camera.init(ctxEnt, player);
addEntity(player);
gameloop();
};
var handleInput = function() {
if(MouseHandler.isMouseIn() === false) {
player.setAttr({ velX: 0, velY: 0 });
return;
}
var pAttr = player.getAttr();
var rPlyrPos = Camera.getRelPos(player.getAttr());
var mPos = MouseHandler.getPos();
var dX = mPos.x - rPlyrPos.x;
var dY = mPos.y - rPlyrPos.y;
var vLength = Math.sqrt( (dX*dX) + (dY*dY) );
var normX = dX / vLength;
var normY = dY / vLength;
var newVelX = normX * (pAttr.maxVel * vLength / 50);
var newVelY = normY * (pAttr.maxVel * vLength / 50);
player.setAttr({
velX: newVelX,
velY: newVelY
});
};
var drawGrid = function() {
var camPos = Camera.getPos();
var camSize = Camera.getSize();
var start = Math.floor(camPos.x / 40);
var relX = Camera.getRelPos({x: (start*40), y: 0}).x;
var numLines = camSize.width / 40;
var i = 0;
ctxGrid.fillRect(0, 0, canvasGrid.width, canvasGrid.height);
for(i=0; i<numLines; i+=1) {
ctxGrid.beginPath();
ctxGrid.moveTo(relX + (40 * i), 0);
ctxGrid.lineTo(relX + (40 * i), camSize.height);
ctxGrid.stroke();
}
start = Math.floor(camPos.y / 40);
var relY = Camera.getRelPos({x: 0, y: (start * 40)}).y;
numLines = camSize.height / 40;
for(i=0; i<numLines; i+=1) {
ctxGrid.beginPath();
ctxGrid.moveTo(0, relY + (40 * i));
ctxGrid.lineTo(camSize.width, relY + (40 * i));
ctxGrid.stroke();
}
};
var handleCollisions = function() {
var possibleColl = [];
var collisions = [];
var coll = null;
var ent = null;
var plyMass = player.getAttr().mass
var entMass = 0;
qTree.clear();
for(ent in entityBag) {
qTree.insert(entityBag[ent]);
}
possibleColl = qTree.retrieve([], player);
while(ent = possibleColl.pop()) {
if(player.intersects(ent)) {
entMass = ent.getAttr().mass;
if(plyMass > (1.5 * entMass)) {
removeEntity(ent);
player.incMass(entMass);
}
}
var entAttr = ent.getAttr();
ctxQuadtree.fillStyle = 'red';
ctxQuadtree.fillRect(entAttr.x/20, entAttr.y/20, 3, 3);
}
};
var fitToContainer = function(canvas) {
canvas.style.width='100%';
canvas.style.height='100%';
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
};
var gameloop = function() {
var len = entityBag.length;
var i = 0;
var ent = null;
handleInput();
Camera.update();
drawGrid();
if(drwQuad === 5) {
ctxQuadtree.fillStyle = 'white';
ctxQuadtree.fillRect(0, 0, 250, 250);
qTree.drawTree(ctxQuadtree);
drwQuad = 0;
}
drwQuad += 1;
ctxEnt.clearRect(0, 0, canvasEnt.width, canvasEnt.height)
for(i=0; i<len; i+=1) {
ent = entityBag[i];
if(ent.update) {
ent.update(dTime);
}
if(ent.draw) {
ent.draw(ctxEnt, Camera);
}
}
handleCollisions();
setTimeout(gameloop, dTime * 1000);
};
return {
init: init,
addEntity: addEntity,
removeEntity: removeEntity
};
}());
var Camera = (function() {
var x = 0;
var y = 0;
var width = 0;
var height = 0;
var ctx = null;
var player = null;
var init = function(_ctx, plyr) {
ctx = _ctx;
player = plyr;
width = ctx.canvas.width;
height = ctx.canvas.height;
};
var update = function() {
width = ctx.canvas.width;
height = ctx.canvas.height;
var plyrAttr = player.getAttr();
x = (plyrAttr.x - width / 2);
y = (plyrAttr.y - height / 2);
};
var getRelPos = function(entAttr) {
var relX = entAttr.x - x;
var relY = entAttr.y - y;
return {
x: relX,
y: relY
};
};
var getPos = function() {
return {
x: x,
y: y
};
};
var getSize = function() {
return {
width: width,
height: height
};
};
return {
init: init,
update: update,
getRelPos: getRelPos,
getPos: getPos,
getSize: getSize
};
}());
var i = 0;
var space = 70;
for(i=0; i<400; i+=1) {
gameManager.addEntity(new Circle({
x: 100 + Math.random() * 4850,//(i%20) * space,
y: 100 + Math.random() * 4850,//Math.floor(i/20)*space,
color: ['red', 'blue', 'green', 'yellow', 'purple', 'brown', 'violet'][Math.floor(Math.random()*7)],
droplet: true
}));
}
gameManager.init('canvas1', 'canvas2', 'canvas3');
And last but not least, my css:
html, body {
background: gray;
width: 100%;
height: 100%;
margin: 0px;
}
#viewport {
position: relative;
width: 100%;
height: 100%;
}
#viewport canvas {
position: absolute;
}
canvas {
background-color: transparent;
}

Famous Engine Bruteforce collisions

I have a famous engine setup and working with physics / drag etc.
But it appears there are other physics options, BruteForce, SweepAndPrune etc.
I suspect these may be what i need to improve the collision detection between the elements.
I've tried to add the BruteForce collision detection like so:
this.collision = new collision([rightWall, leftWall, topWall, bottomWall]);
But I get an error about an incorrect constraint.
this.simulation.addConstraint(this.collision);
Does anyone have experience with solving this issue?
You can see a demo here:
var famous = famous;
var FamousEngine = famous.core.FamousEngine;
var Camera = famous.components.Camera;
var DOMElement = famous.domRenderables.DOMElement;
var Gravity3D = famous.physics.Gravity3D;
var MountPoint = famous.components.MountPoint;
var PhysicsEngine = famous.physics.PhysicsEngine;
var Position = famous.components.Position;
var Size = famous.components.Size;
var Wall = famous.physics.Wall;
var Sphere = famous.physics.Sphere;
var Vec3 = famous.math.Vec3;
var math = famous.math;
var physics = famous.physics;
var collision = famous.physics.Collision;
var gestures = famous.components.GestureHandler;
var Spring = famous.physics.Spring;
console.log(famous)
var anchor = new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0);
//Create Walls
var rightWall = new Wall({
direction: Wall.LEFT
}).setPosition(window.innerWidth - 20, 0, 0);
var leftWall = new Wall({
direction: Wall.RIGHT
}).setPosition(window.innerWidth + 20, 0, 0);
var topWall = new Wall({
direction: Wall.DOWN
}).setPosition(0, 20, 0);
var bottomWall = new Wall({
direction: Wall.UP
}).setPosition(0, window.innerHeight - 20, 0);
var centerPoint;
function Demo() {
this.scene = FamousEngine.createScene('body');
this.collision = new collision([rightWall, leftWall, topWall, bottomWall]);
console.log(this.collision)
this.simulation = new PhysicsEngine();
this.simulation.setOrigin(0.5, 0.5);
this.simulation.addConstraint(this.collision);
this.items = [];
this.walls = [];
//Create Items
for (var i = 0; i < 10; i++) {
var node = this.scene.addChild();
node.setMountPoint(0.5, 0.5);
var size = new Size(node).setMode(1, 1);
var position = new Position(node);
if (i === 0) {
createLogo.call(this, node, size, position);
}
if (i !== 0 && i !== 9) {
node.id = i;
createSatellites.call(this, node, size, position);
}
if (i === 9) {
node.id = i;
createAlternateShape.call(this, node, size, position);
}
}
//Create Walls
var node = this.scene.addChild();
createWalls(node);
var once = true;
Demo.prototype.onUpdate = function(time) {
this.simulation.update(time);
this.collision.resolve(time, 360)
//Postition walls
var wallPosition = topWall.getPosition();
node.setPosition(wallPosition.x, wallPosition.y);
//Position elements
if (this.items.length > 0) {
for (var i = 0; i < this.items.length; i++) {
if (once) {
console.log(this.items[i][1]._node.moving)
once = false;
}
if (this.items[i][1]._node.moving) {
console.log('moving!')
} else {
var itemPosition = this.simulation.getTransform(this.items[i][0]).position;
this.items[i][1].set(itemPosition[0], itemPosition[1], 0);
}
}
}
FamousEngine.requestUpdateOnNextTick(this);
};
FamousEngine.requestUpdateOnNextTick(this);
}
function createWalls(wallNode) {
wallNode.setSizeMode('absolute', 'absolute', 'absolute').setAbsoluteSize(window.innerWidth, 10, 0);
var wallDOMElement = new DOMElement(wallNode, {
tagName: 'div'
}).setProperty('background-color', 'lightblue');
}
function createLogo(node, size, position) {
node.moving = false;
size.setAbsolute(100, 100);
var mp = new MountPoint(node).set(0.5, 0.5);
var el = new DOMElement(node, {
tagName: 'img',
attributes: {
src: 'http://www.denisboudreau.org/presentations/2014/CSUN/Browser%20Zoom%20and%20Low%20Vision/Comps/ToM_EnsoCircle.png'
}
});
centerPoint = new Sphere({
radius: 50,
mass: 10000,
restrictions: ['xy'],
position: new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0)
});
var spring = new Spring(null, centerPoint, {
stiffness: 95,
period: 0.6,
dampingRatio: 1.0,
anchor: new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0)
});
centerPoint.setVelocity(0, 0, 0);
this.simulation.add(centerPoint, spring);
this.items.push([centerPoint, position]);
this.collision.addTarget(centerPoint);
}
function createAlternateShape(node, size, position) {
node.moving = false;
size.setAbsolute(100, 100);
var el = new DOMElement(node, {
properties: {
'background-color': 'red',
}
});
var box = new physics.Box({
size: [100, 100, 100],
mass: 10,
position: new Vec3(100, 100, 0)
});
// Attach the box to the anchor with a `Spring` force
var spring = new Spring(null, box, {
stiffness: 95,
period: 0.6,
dampingRatio: 1.0,
anchor: new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0)
});
box.setVelocity(0.5, 0.5, 0);
this.simulation.add(box, spring);
this.items.push([box, position]);
this.collision.addTarget(box);
}
function createSatellites(node, size, position, i) {
node.moving = false;
var rand = Math.round(Math.random() * 100 + 30);
size.setAbsolute(rand, rand);
var radius = 100;
var x = Math.floor(Math.random() * radius * 2) - radius;
var y = (Math.round(Math.random()) * 2 - 1) * Math.sqrt(radius * radius - x * x);
var color = 'rgb(' + Math.abs(x) + ',' + Math.abs(Math.round(y)) + ',' + (255 - node.id) + ')';
var el = new DOMElement(node, {
properties: {
'background-color': color,
'border-radius': '50%'
}
});
var satellite = new Sphere({
radius: rand / 2,
mass: 10,
position: new Vec3(x + window.innerWidth / 2, y + window.innerHeight / 2, 0)
});
// Attach the box to the anchor with a `Spring` force
var spring = new Spring(null, satellite, {
stiffness: 95,
period: 0.6,
dampingRatio: 1.0,
anchor: anchor
});
//console.log(color);
// satellite.setVelocity(-y / Math.PI, -x / Math.PI / 2, y / 2);
satellite.setVelocity(0.5, 0.5, 0);
// this.gravity.addTarget(satellite);
this.simulation.add(satellite, spring);
this.items.push([satellite, position]);
this.collision.addTarget(satellite);
//Drag
var nodeGesture = new gestures(node);
nodeGesture.on('drag', function(e, p) {
if (e.status == "move") {
node.moving = true;
}
var currentPos = node.getPosition()
var newPosX = currentPos[0] + e.centerDelta.x
var newPosY = currentPos[1] + e.centerDelta.y
satellite.setPosition(newPosX, newPosY)
node.setPosition(newPosX, newPosY)
if (e.status == "end") {
node.moving = false;
}
});
//event
node.addUIEvent('click');
// node.addComponent({
// onReceive:function(event, payload){
// if(event==='click'){
// // el.setContent('I\'ve been clicked')
//
// }
// }
// })
}
setTimeout(function() {
// Boilerplate
FamousEngine.init();
}, 500);
// App Code
var demo = new Demo();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Famous :: Seed Project</title>
<link rel="icon" href="favicon.ico?v=1" type="image/x-icon">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
}
body {
position: absolute;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-font-smoothing: antialiased;
-webkit-tap-highlight-color: transparent;
-webkit-perspective: 0;
perspective: none;
overflow: hidden;
}
</style>
</head>
<body>
<script src="http://code.famo.us/famous/0.6.2/famous.min.js"></script>
</body>
</html>
This is the solution using BruteForceAABB.
var famous = famous;
var FamousEngine = famous.core.FamousEngine;
var Camera = famous.components.Camera;
var DOMElement = famous.domRenderables.DOMElement;
var Gravity3D = famous.physics.Gravity3D;
var MountPoint = famous.components.MountPoint;
var PhysicsEngine = famous.physics.PhysicsEngine;
var Position = famous.components.Position;
var Size = famous.components.Size;
var Wall = famous.physics.Wall;
var Sphere = famous.physics.Sphere;
var Vec3 = famous.math.Vec3;
var math = famous.math;
var physics = famous.physics;
var collision = famous.physics.Collision;
var gestures = famous.components.GestureHandler;
var Spring = famous.physics.Spring;
console.log(famous)
var anchor = new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0);
//Create Walls
var rightWall = new Wall({
direction: Wall.LEFT
}).setPosition(window.innerWidth - 20, 0, 0);
var leftWall = new Wall({
direction: Wall.RIGHT
}).setPosition(window.innerWidth + 20, 0, 0);
var topWall = new Wall({
direction: Wall.DOWN
}).setPosition(0, 20, 0);
var bottomWall = new Wall({
direction: Wall.UP
}).setPosition(0, window.innerHeight - 20, 0);
var centerPoint;
function Demo() {
this.scene = FamousEngine.createScene('body');
// this.collision = new collision.({broadphase: 'BruteForce'});
var broadPhase = new physics.Collision.BruteForceAABB([rightWall, leftWall, topWall, bottomWall]);
this.collision = new collision([topWall], {
'broadPhase': broadPhase
});
this.simulation = new PhysicsEngine();
this.simulation.setOrigin(0.5, 0.5);
this.simulation.addConstraint(this.collision);
this.items = [];
this.walls = [];
//Create Items
for (var i = 0; i < 10; i++) {
var node = this.scene.addChild();
node.setMountPoint(0.5, 0.5);
var size = new Size(node).setMode(1, 1);
var position = new Position(node);
if (i === 0) {
createLogo.call(this, node, size, position);
}
if (i !== 0 && i !== 9) {
node.id = i;
createSatellites.call(this, node, size, position);
}
if (i === 9) {
node.id = i;
createAlternateShape.call(this, node, size, position);
}
}
//Create Walls
var node = this.scene.addChild();
createWalls(node);
var once = true;
Demo.prototype.onUpdate = function(time) {
this.simulation.update(time);
// this.collision.resolve(time, 360)
//Postition walls
var wallPosition = topWall.getPosition();
node.setPosition(wallPosition.x, wallPosition.y);
//Position elements
if (this.items.length > 0) {
for (var i = 0; i < this.items.length; i++) {
if (once) {
console.log(this.items[i][1]._node.moving)
once = false;
}
if (this.items[i][1]._node.moving) {
console.log('moving!')
} else {
var itemPosition = this.simulation.getTransform(this.items[i][0]).position;
this.items[i][1].set(itemPosition[0], itemPosition[1], 0);
}
}
}
FamousEngine.requestUpdateOnNextTick(this);
};
FamousEngine.requestUpdateOnNextTick(this);
}
function createWalls(wallNode) {
wallNode.setSizeMode('absolute', 'absolute', 'absolute').setAbsoluteSize(window.innerWidth, 10, 0);
var wallDOMElement = new DOMElement(wallNode, {
tagName: 'div'
}).setProperty('background-color', 'lightblue');
}
function createLogo(node, size, position) {
node.moving = false;
size.setAbsolute(100, 100);
var mp = new MountPoint(node).set(0.5, 0.5);
var el = new DOMElement(node, {
tagName: 'img',
attributes: {
src: './images/famous_logo.png'
}
});
centerPoint = new Sphere({
radius: 50,
mass: 100000,
restrictions: ['xy'],
position: new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0)
});
var spring = new Spring(null, centerPoint, {
stiffness: 95,
period: 0.6,
dampingRatio: 1.0,
anchor: new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0)
});
centerPoint.setVelocity(0, 0, 0);
this.simulation.add(centerPoint, spring);
this.items.push([centerPoint, position]);
this.collision.addTarget(centerPoint);
}
function createAlternateShape(node, size, position) {
node.moving = false;
size.setAbsolute(100, 100);
var el = new DOMElement(node, {
properties: {
'background-color': 'red',
}
});
var box = new physics.Box({
size: [101, 101, 101],
mass: 100,
position: new Vec3(100, 100, 0)
});
// Attach the box to the anchor with a `Spring` force
var spring = new Spring(null, box, {
period: 1.5,
dampingRatio: 0.8,
anchor: new Vec3(window.innerWidth / 2, window.innerHeight / 2, 0)
});
box.setVelocity(0.1, 0.1, 0);
this.simulation.add(box, spring);
this.items.push([box, position]);
this.collision.addTarget(box);
}
function createSatellites(node, size, position, i) {
node.moving = false;
var rand = Math.round(Math.random() * 100 + 30);
size.setAbsolute(rand, rand);
var radius = rand;
var x = Math.floor(Math.random() * radius * 2) - radius;
var y = (Math.round(Math.random()) * 2 - 1) * Math.sqrt(radius * radius - x * x);
var color = 'rgb(' + Math.abs(x) + ',' + Math.abs(Math.round(y)) + ',' + (255 - node.id) + ')';
var el = new DOMElement(node, {
properties: {
'background-color': color,
'border-radius': '50%'
}
});
var satellite = new Sphere({
radius: rand / 2,
mass: 100,
position: new Vec3(x + window.innerWidth / 2, y + window.innerHeight / 2, 0)
});
// Attach the box to the anchor with a `Spring` force
var spring = new Spring(null, satellite, {
// stiffness: 10,
period: 1.5,
dampingRatio: 0.8,
anchor: anchor
});
//console.log(color);
// satellite.setVelocity(-y / Math.PI, -x / Math.PI / 2, y / 2);
satellite.setVelocity(0.1, 0.1, 0);
// this.gravity.add(satellite);
this.simulation.add(satellite, spring);
this.items.push([satellite, position]);
this.collision.addTarget(satellite);
//Drag
var nodeGesture = new gestures(node);
nodeGesture.on('drag', function(e, p) {
if (e.status == "move") {
node.moving = true;
}
var currentPos = node.getPosition()
var newPosX = currentPos[0] + e.centerDelta.x
var newPosY = currentPos[1] + e.centerDelta.y
satellite.setPosition(newPosX, newPosY)
node.setPosition(newPosX, newPosY)
if (e.status == "end") {
node.moving = false;
}
});
//event
node.addUIEvent('click');
// node.addComponent({
// onReceive:function(event, payload){
// if(event==='click'){
// // el.setContent('I\'ve been clicked')
//
// }
// }
// })
}
setTimeout(function() {
// Boilerplate
FamousEngine.init();
}, 500);
// App Code
var demo = new Demo();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Famous :: Seed Project</title>
<link rel="icon" href="favicon.ico?v=1" type="image/x-icon">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
}
body {
position: absolute;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-font-smoothing: antialiased;
-webkit-tap-highlight-color: transparent;
-webkit-perspective: 0;
perspective: none;
overflow: hidden;
}
</style>
</head>
<body>
<script src="http://code.famo.us/famous/0.6.2/famous.min.js"></script>
</body>
</html>

Categories