Related
I look at stackoverflow other people similar problems a they have very similar solution but all examples are done in three.js (Not in my case).
Jump is relative good working at the moment, i powered gravity (double it).
Stairs also works fine even without jumping it is ok for me.
I put one big cube to make blocking volume but i dont now how to make player to simple stops because i use WASD for body set position. My player in big cube just have big jump , i wanna prevent WASD body set position in moment of first touch.
Some solutions [not yet tested]:
1] To make movement only with force [not set position] => [possible not nature movements]
2] Make collide detection then prevent set position => [possible angle problems]
3] Some other solution....
All related code is visible in example.
Matrix-engine example for FPS:
import App from '../program/manifest';
import * as CANNON from 'cannon';
import {ENUMERATORS, ORBIT_FROM_ARRAY, OSCILLATOR, randomFloatFromTo} from '../lib/utility';
export var runThis = (world) => {
// Camera
canvas.style.cursor = 'none';
App.camera.FirstPersonController = true;
matrixEngine.Events.camera.fly = false;
App.camera.speedAmp = 0.01;
matrixEngine.Events.camera.yPos = 2;
// Audio effects
App.sounds.createAudio('shoot', 'res/music/single-gunshot.mp3', 5);
// Prevent right click context menu
window.addEventListener("contextmenu", (e) => {
e.preventDefault();
});
// Override mouse up
App.events.CALCULATE_TOUCH_UP_OR_MOUSE_UP = () => {
App.scene.FPSTarget.glBlend.blendParamSrc = matrixEngine.utility.ENUMERATORS.glBlend.param[4];
App.scene.FPSTarget.glBlend.blendParamDest = matrixEngine.utility.ENUMERATORS.glBlend.param[4];
App.scene.FPSTarget.geometry.setScale(0.1);
App.scene.xrayTarget.visible = false;
};
// Override right mouse down
matrixEngine.Events.SYS.MOUSE.ON_RIGHT_BTN_PRESSED = (e) => {
App.scene.FPSTarget.geometry.setScale(0.6);
App.scene.FPSTarget.glBlend.blendParamSrc = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
App.scene.FPSTarget.glBlend.blendParamDest = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
App.scene.xrayTarget.visible = true;
};
// Override mouse down
App.events.CALCULATE_TOUCH_DOWN_OR_MOUSE_DOWN = (ev, mouse) => {
// `checkingProcedure` gets secound optimal argument
// for custom ray origin target.
if(mouse.BUTTON_PRESSED == 'RIGHT') {
// Zoom
} else {
// This call represent `SHOOT` Action.
// And it is center of screen
matrixEngine.raycaster.checkingProcedure(ev, {
clientX: ev.target.width / 2,
clientY: ev.target.height / 2
});
App.sounds.play('shoot');
}
};
window.addEventListener('ray.hit.event', (ev) => {
console.log("You shoot the object! Nice!", ev);
// Physics force apply also change ambienty light.
if(ev.detail.hitObject.physics.enabled == true) {
// Shoot the object - apply force
ev.detail.hitObject.physics.currentBody.force.set(0, 0, 1000);
// Apply random diff color
if(ev.detail.hitObject.LightsData) ev.detail.hitObject.LightsData.ambientLight.set(
randomFloatFromTo(0, 2), randomFloatFromTo(0, 2), randomFloatFromTo(0, 2));
}
});
// Load obj seq animation
const createObjSequence = (objName) => {
function onLoadObj(meshes) {
for(let key in meshes) {
matrixEngine.objLoader.initMeshBuffers(world.GL.gl, meshes[key]);
}
var textuteImageSamplers2 = {
source: [
"res/bvh-skeletal-base/swat-guy/textures/Ch15_1001_Diffuse.png" // ,
// "res/bvh-skeletal-base/swat-guy/textures/Ch15_1001_Diffuse.png"
],
mix_operation: "multiply", // ENUM : multiply , divide
};
var animArg = {
id: objName,
meshList: meshes,
currentAni: 0,
animations: {
active: 'walk',
walk: {
from: 0,
to: 20,
speed: 3
}
}
};
world.Add("obj", 1, objName, textuteImageSamplers2, meshes[objName], animArg);
// Fix object orientation - this can be fixed also in blender.
matrixEngine.Events.camera.yaw = 0;
// Add collision cube to the local player.
world.Add("cube", 0.5, "playerCollisonBox");
var collisionBox = new CANNON.Body({
mass: 500,
linearDamping: 0.001,
position: new CANNON.Vec3(0, 0, 0),
shape: new CANNON.Box(new CANNON.Vec3(3, 3, 3))// new CANNON.Sphere(2)
});
physics.world.addBody(collisionBox);
App.scene.playerCollisonBox.physics.currentBody = collisionBox;
App.scene.playerCollisonBox.physics.enabled = true;
App.scene.playerCollisonBox.physics.currentBody.fixedRotation = true;
App.scene.playerCollisonBox.geometry.setScale(0.02);
App.scene.playerCollisonBox.glBlend.blendEnabled = true;
App.scene.playerCollisonBox.glBlend.blendParamSrc = ENUMERATORS.glBlend.param[5];
App.scene.playerCollisonBox.glBlend.blendParamDest = ENUMERATORS.glBlend.param[6];
// test
addEventListener('hit.keyDown', (e) => {
// console.log('Bring to the top level', e.detail.keyCode);
// dont mess in events
if(e.detail.keyCode == 32) {
setTimeout(() => {
App.scene.playerCollisonBox.physics.currentBody.force.set(0, 0, 111)
}, 250)
} else if(e.detail.keyCode == 87) {
// Good place for blocking volume
// App.scene.playerCollisonBox.physics.currentBody.force.set(0,10,0)
setTimeout(() => {
// App.scene.playerCollisonBox.physics.currentBody.force.set(0,100,0)
}, 100);
}
});
var playerUpdater = {
UPDATE: () => {
App.scene[objName].rotation.rotateY(
matrixEngine.Events.camera.yaw + 180)
var detPitch;
var limit = 2;
if(matrixEngine.Events.camera.pitch < limit &&
matrixEngine.Events.camera.pitch > -limit) {
detPitch = matrixEngine.Events.camera.pitch * 2;
} else if(matrixEngine.Events.camera.pitch > limit) {
detPitch = limit * 2;
} else if(matrixEngine.Events.camera.pitch < -(limit + 2)) {
detPitch = -(limit + 2) * 2;
}
if(matrixEngine.Events.camera.virtualJumpActive == true) {
// invert logic
// Scene object set
App.scene[objName].rotation.rotateX(-detPitch);
var detPitchPos = matrixEngine.Events.camera.pitch;
if(detPitchPos > 4) detPitchPos = 4;
App.scene.playerCollisonBox.physics.currentBody.mass = 10;
App.scene.playerCollisonBox.physics.currentBody.force.set(0, 0, 700);
App.scene[objName].position.setPosition(
App.scene.playerCollisonBox.physics.currentBody.position.x,
App.scene.playerCollisonBox.physics.currentBody.position.z,
App.scene.playerCollisonBox.physics.currentBody.position.y
)
// Cannonjs object set / Switched Z - Y
matrixEngine.Events.camera.xPos = App.scene.playerCollisonBox.physics.currentBody.position.x;
matrixEngine.Events.camera.zPos = App.scene.playerCollisonBox.physics.currentBody.position.y;
matrixEngine.Events.camera.yPos = App.scene.playerCollisonBox.physics.currentBody.position.z;
App.scene.playerCollisonBox.
physics.currentBody.angularVelocity.set(0, 0, 0);
setTimeout(() => {
matrixEngine.Events.camera.virtualJumpActive = false;
App.scene.playerCollisonBox.physics.currentBody.mass = 550;
}, 1350);
} else {
// Make more stable situation
App.scene.playerCollisonBox.physics.currentBody.mass = 500;
App.scene.playerCollisonBox.physics.currentBody.quaternion.setFromEuler(0,0,0)
// Tamo tu iznad duge nebo zri...
// Cannonjs object set
// Switched Z - Y
matrixEngine.Events.camera.yPos = App.scene.playerCollisonBox.physics.currentBody.position.z;
// Scene object set
App.scene[objName].rotation.rotateX(-detPitch);
var detPitchPos = matrixEngine.Events.camera.pitch;
if(detPitchPos > 4) detPitchPos = 4;
App.scene[objName].position.setPosition(
matrixEngine.Events.camera.xPos,
matrixEngine.Events.camera.yPos, // - 0.3 + detPitchPos / 50,
// App.scene.playerCollisonBox.physics.currentBody.position.y,
matrixEngine.Events.camera.zPos,
)
// Cannonjs object set
// Switched Z - Y
App.scene.playerCollisonBox.
physics.currentBody.position.set(
matrixEngine.Events.camera.xPos,
matrixEngine.Events.camera.zPos,
matrixEngine.Events.camera.yPos)
// App.scene.playerCollisonBox.physics.currentBody.position.y)
}
}
};
App.updateBeforeDraw.push(playerUpdater);
// Player Energy status
App.scene.player.energy = {};
for(let key in App.scene.player.meshList) {
App.scene.player.meshList[key].setScale(1.85);
}
// Target scene object
var texTarget = {
source: [
"res/bvh-skeletal-base/swat-guy/target.png",
"res/bvh-skeletal-base/swat-guy/target.png"
],
mix_operation: "multiply",
};
world.Add("squareTex", 0.25, 'FPSTarget', texTarget);
App.scene.FPSTarget.position.setPosition(0, 0, -4);
App.scene.FPSTarget.glBlend.blendEnabled = true;
App.scene.FPSTarget.glBlend.blendParamSrc = matrixEngine.utility.ENUMERATORS.glBlend.param[4];
App.scene.FPSTarget.glBlend.blendParamDest = matrixEngine.utility.ENUMERATORS.glBlend.param[4];
App.scene.FPSTarget.isHUD = true;
App.scene.FPSTarget.geometry.setScale(0.1);
// Energy active bar
// Custom generic textures. Micro Drawing.
// Example for arg shema square for now only.
var options = {
squareShema: [8, 8],
pixels: new Uint8Array(8 * 8 * 4)
};
// options.pixels.fill(0);
App.scene.player.energy.value = 8;
App.scene.player.updateEnergy = function(v) {
this.energy.value = v;
var t = App.scene.energyBar.preparePixelsTex(App.scene.energyBar.specialValue);
App.scene.energyBar.textures.pop()
App.scene.energyBar.textures.push(App.scene.energyBar.createPixelsTex(t));
};
function preparePixelsTex(options) {
var I = 0, R = 0, G = 0, B = 0, localCounter = 0;
for(var funny = 0;funny < 8 * 8 * 4;funny += 4) {
if(localCounter > 7) {
localCounter = 0;
}
if(localCounter < App.scene.player.energy.value) {
I = 128;
if(App.scene.player.energy.value < 3) {
R = 255;
G = 0;
B = 0;
I = 0;
} else if(App.scene.player.energy.value > 2 && App.scene.player.energy.value < 5) {
R = 255;
G = 255;
B = 0;
} else {
R = 0;
G = 255;
B = 0;
}
} else {
I = 0;
R = 0;
G = 0;
B = 0;
}
options.pixels[funny] = R;
options.pixels[funny + 1] = G;
options.pixels[funny + 2] = B;
options.pixels[funny + 3] = 0;
localCounter++;
}
return options;
}
var tex2 = {
source: [
"res/images/hud/energy-bar.png",
"res/images/hud/energy-bar.png"
],
mix_operation: "multiply",
};
world.Add("squareTex", 1, 'energyBar', tex2);
App.scene.energyBar.glBlend.blendEnabled = true;
App.scene.energyBar.glBlend.blendParamSrc = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
App.scene.energyBar.glBlend.blendParamDest = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
App.scene.energyBar.isHUD = true;
// App.scene.energy.visible = false;
App.scene.energyBar.position.setPosition(0, 1.1, -3);
App.scene.energyBar.geometry.setScaleByX(1)
App.scene.energyBar.geometry.setScaleByY(0.05)
App.scene.energyBar.preparePixelsTex = preparePixelsTex;
options = preparePixelsTex(options);
// App.scene.energyBar.textures[0] = App.scene.energyBar.createPixelsTex(options);
App.scene.energyBar.textures.push(App.scene.energyBar.createPixelsTex(options));
App.scene.energyBar.specialValue = options;
}
matrixEngine.objLoader.downloadMeshes(
matrixEngine.objLoader.makeObjSeqArg(
{
id: objName,
// path: "res/bvh-skeletal-base/swat-guy/anims/swat-multi",
path: "res/bvh-skeletal-base/swat-guy/FPShooter-hands/FPShooter-hands",
from: 1,
to: 20
}),
onLoadObj
);
};
let promiseAllGenerated = [];
const objGenerator = (n) => {
for(var j = 0;j < n;j++) {
promiseAllGenerated.push(new Promise((resolve) => {
setTimeout(() => {
world.Add("cubeLightTex", 1, "CUBE" + j, tex);
var b2 = new CANNON.Body({
mass: 1,
linearDamping: 0.01,
position: new CANNON.Vec3(1, -14.5, 15),
shape: new CANNON.Box(new CANNON.Vec3(1, 1, 1))
});
physics.world.addBody(b2);
App.scene['CUBE' + j].physics.currentBody = b2;
App.scene['CUBE' + j].physics.enabled = true;
resolve();
}, 1000 * j);
}));
}
}
// objGenerator(15);
createObjSequence('player');
Promise.all(promiseAllGenerated).then((what) => {
console.info(`Runtime wait for some generetion of scene objects,
then swap scene array index for target ->
must be manual setup for now!`, what);
// swap(5, 19, matrixEngine.matrixWorld.world.contentList);
});
// Add ground for physics bodies.
var tex = {
source: ["res/images/complex_texture_1/diffuse.png"],
mix_operation: "multiply",
};
// Load Physics world.
// let gravityVector = [0, 0, -9.82];
let gravityVector = [0, 0, -29.82];
let physics = world.loadPhysics(gravityVector);
// Add ground
var groundBody = new CANNON.Body({
mass: 0, // mass == 0 makes the body static
position: new CANNON.Vec3(0, -15, -2)
});
var groundShape = new CANNON.Plane();
groundBody.addShape(groundShape);
physics.world.addBody(groundBody);
// Matrix engine visual
world.Add("squareTex", 1, "FLOOR_STATIC", tex);
App.scene.FLOOR_STATIC.geometry.setScaleByX(20);
App.scene.FLOOR_STATIC.geometry.setScaleByY(20);
App.scene.FLOOR_STATIC.position.SetY(-2);
App.scene.FLOOR_STATIC.position.SetZ(-15);
App.scene.FLOOR_STATIC.rotation.rotx = 90;
// Target x-ray
// See through the objects.
// In webGL context it is object how was drawn before others.
var texTarget = {
source: [
"res/bvh-skeletal-base/swat-guy/target-night.png"
],
mix_operation: "multiply",
};
world.Add("squareTex", 0.18, 'xrayTarget', texTarget);
App.scene.xrayTarget.glBlend.blendEnabled = true;
App.scene.xrayTarget.glBlend.blendParamSrc = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
App.scene.xrayTarget.glBlend.blendParamDest = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
App.scene.xrayTarget.isHUD = true;
App.scene.xrayTarget.visible = false;
App.scene.xrayTarget.position.setPosition(-0.3, 0.27, -4);
// Energy
var tex1 = {
source: [
"res/images/hud/energy.png"
],
mix_operation: "multiply",
};
world.Add("squareTex", 0.5, 'energy', tex1);
App.scene.energy.glBlend.blendEnabled = true;
App.scene.energy.glBlend.blendParamSrc = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
App.scene.energy.glBlend.blendParamDest = matrixEngine.utility.ENUMERATORS.glBlend.param[5];
App.scene.energy.isHUD = true;
// App.scene.energy.visible = false;
App.scene.energy.position.setPosition(-1, 1.15, -3);
App.scene.energy.geometry.setScaleByX(0.35)
App.scene.energy.geometry.setScaleByY(0.1)
// good for fix rotation in future
world.Add("cubeLightTex", 1, "FLOOR2", tex);
var b2 = new CANNON.Body({
mass: 0,
linearDamping: 0.01,
position: new CANNON.Vec3(1, -14.5, -1),
shape: new CANNON.Box(new CANNON.Vec3(3, 1, 1))
});
physics.world.addBody(b2);
App.scene['FLOOR2'].position.setPosition(1, -1, -14.5)
App.scene['FLOOR2'].geometry.setScaleByX(3);
App.scene['FLOOR2'].physics.currentBody = b2;
App.scene['FLOOR2'].physics.enabled = true;
world.Add("cubeLightTex", 2, "FLOOR3", tex);
var b3 = new CANNON.Body({
mass: 0,
linearDamping: 0.01,
position: new CANNON.Vec3(0, -19, 0),
shape: new CANNON.Box(new CANNON.Vec3(3, 3, 3))
});
physics.world.addBody(b3);
App.scene['FLOOR3'].position.setPosition(0, 0, -19)
// App.scene['FLOOR3'].geometry.setScaleByX(3);
App.scene['FLOOR3'].physics.currentBody = b3;
App.scene['FLOOR3'].physics.enabled = true;
world.Add("cubeLightTex", 5, "WALL_BLOCK", tex);
var b5 = new CANNON.Body({
mass: 0,
linearDamping: 0.01,
position: new CANNON.Vec3(10, -19, 0),
shape: new CANNON.Box(new CANNON.Vec3(5, 5, 5))
});
physics.world.addBody(b5);
App.scene['WALL_BLOCK'].position.setPosition(10, 0, -19)
// App.scene['WALL_BLOCK'].geometry.setScaleByX(3);
App.scene['WALL_BLOCK'].physics.currentBody = b5;
App.scene['WALL_BLOCK'].physics.enabled = true;
};
Any suggestion ?
Following the phaser documentation, the scene restart is not working.
What I'm doing is the following, there are three scenes (start, play and end.). When it gets to the end, when clicking on the screen it gives this.scene.start('play'). I tried several ways, researched a lot and tried several things but the ones that worked in my case, the game for some events and some settings are not reset.
For example, in this game you will create enemies and some packs. When it is restarted or started again, these builds are no longer executed.
Start
import Phaser from "phaser";
class Start extends Phaser.Scene{
constructor ()
{
super({ key: 'start', active: true });
}
init(){
console.log("- ./node_modules/babel-loader/lib??ref--2-0!./node_modules/vue-loader/lib??vue-loader-options!./pages/game/index.vue?vue&type=script&lang=js&")
console.log("initiated 0418971")
console.log("Unexpected console statement no-console")
console.log("bundle 'client' has 1 warnings")
console.log("Caching create all")
this.cameras.main.setBackgroundColor("#24252A");
}
preload(){
}
create() {
this.helloWorld = this.add.text(
this.cameras.main.centerX,
this.cameras.main.centerY,
"Clique para jogar",
{ font: "40px Arial", fill: "#ffffff" }
);
this.helloWorld.setOrigin(0.5);
this.input.on('pointerup', function (pointer) {
this.scene.start('play');
}, this);
}
update() {
}
}
export default Start;
Play
import Phaser from "phaser";
// import Pack from '~/assets/game/Components/Pack.js'
class Play extends Phaser.Scene {
constructor() {
super({
key: 'play',
active: false
});
}
index = 0;
packs = Phaser.GameObjects.Group;
enemys = Phaser.GameObjects.Group;
spriteLife = [];
config = {
speed: 0,
speedVelocity: 0.3,
maxSpeed: 15,
pack: {
created: 0,
limitcreate: 1,
value: 4.5,
},
enemy: {
speed: 5,
created: 0,
limitcreate: 1,
x: 0,
},
engine: {
temperature: 0,
}
};
init() {
}
preload() {
// Images
this.load.image('grama', require('~/assets/game/assets/grama.jpg'));
this.load.image('road', require('~/assets/game/assets/road-2.png'))
this.load.image('pack', require('~/assets/game/assets/pack.png'));
this.load.image('life', require('~/assets/game/assets/life.png'));
// Sprite sheet
this.load.spritesheet('player', require('~/assets/game/assets/car-sprite.png'), {
frameWidth: 404,
frameHeight: 1009
})
}
createGram() {
let a = 0;
let b = 0;
const totalA = 8;
const totalB = 4;
for (a = 0; a <= totalA; a++) {
for (b = 0; b <= totalB; b++) {
const grama = this.add.sprite(0, 0, 'grama').setScale(0.2);
grama.setPosition(grama.displayWidth * b, grama.displayHeight * a);
}
}
}
createScore() {
this.score = 0;
this.scoreText = this.add.text(15, 45,
`SCORE: 0`, {
font: "20px Arial",
fill: "#ffffff"
}
);
}
createLife() {
this.numberLifes = 3;
this.add.text(15, 15,
`LIFE:`, {
font: "20px Arial",
fill: "#ffffff"
}
);
for (let i = 0; i < this.numberLifes; i++) {
this.spriteLife.push(this.add.image(80 + 30 * i, 25, 'life').setScale(0.09))
}
}
createPlayer() {
this.player = this.physics.add.sprite(0, 0, 'player');
this.player.setOrigin(0.5)
this.player.setScale(0.2);
this.player.setPosition(this.cameras.main.centerX, this.cameras.main.displayHeight - 120);
this.player.setCollideWorldBounds(true);
}
createPack() {
if(this.config.pack.created < this.config.pack.limitcreate){
this.packs.create(Phaser.Math.Between(60, 330), 0, 'pack').setScale(.15).setOrigin(.5);
this.config.pack.created += 1;
}
}
createEnemy() {
if(this.config.enemy.created < this.config.enemy.limitcreate){
this.enemy = this.enemys.create(Phaser.Math.Between(70, 320), -200, 'player').setScale(.2).setOrigin(.5);
this.enemy.anims.play('default', true);
this.config.enemy.created += 1;
this.config.enemy.x = this.enemys.children.entries[0].x;
}
}
createEngineTemperatureBar() {
this.engineTemperatureBar = this.add.graphics();
this.engineTemperatureBar.fillStyle(0xffffff, 1);
this.engineTemperatureBar.fillRect(0, 0, 130, 30);
// Position
this.engineTemperatureBar.x = 350;
this.engineTemperatureBar.y = 830;
this.engineTemperatureBar.angle = -90;
this.engineTemperatureBar.scaleX = 0;
}
myAnims() {
this.anims.create({
key: 'left',
frames: this.anims.generateFrameNumbers('player', {
start: 4,
end: 4
}),
frameRate: 3,
repeat: 0
})
this.anims.create({
key: 'right',
frames: this.anims.generateFrameNumbers('player', {
start: 0,
end: 1
}),
frameRate: 3,
repeat: 0
})
this.anims.create({
key: 'default',
frames: [{
key: 'player',
frame: 2
}],
frameRate: 20
});
}
addPhysics(){
// Add
this.packs = this.physics.add.group();
this.enemys = this.physics.add.group();
// Collider
this.physics.add.collider(this.player, this.packs, this.collectPack, null, this);
this.physics.add.collider(this.player, this.enemys, this.collideEnemy, null, this, this.enemys);
}
create() {
// Camera
this.cameras.main.setBackgroundColor("#24252A");
// Gram
this.createGram();
// Roads
this.roads = this.add.tileSprite((this.game.canvas.clientWidth / 2), 0, 500, 1210, 'road').setOrigin(0.5, 0).setScale(0.7);
// Functions
this.createScore();
this.createLife();
this.createPlayer();
this.myAnims();
this.addPhysics();
this.createEngineTemperatureBar();
// Body
this.packs.enableBody = true;
this.enemys.enableBody = true;
// Cursors
this.cursors = this.input.keyboard.createCursorKeys();
}
update(time) {
this.roads.tilePositionY -= this.config.speed;
this.movePlayerManager();
this.createPack();
this.createEnemy();
this.movePacks();
this.moveEnemy()
this.updateEngineTemperatureBar()
}
movePlayerManager() {
// Left
if (this.cursors.left.isDown) {
this.player.x -= 5;
this.player.anims.play('left', false);
}
// Right
else if (this.cursors.right.isDown) {
this.player.x += 5;
this.player.anims.play('right', false);
}
else {
this.player.anims.play('default', true);
}
// Up
if (this.cursors.up.isDown) {
// Increase speed
if (this.config.speed <= this.config.maxSpeed){
this.config.speed += this.config.speedVelocity;
}
}
if (this.cursors.up.isUp) {
if (this.config.speed > 0){
this.config.speed -= 0.5;
}
else
this.config.speed = 0
}
}
movePacks() {
this.packs.children.each((e) => {
e.y += this.config.speed;
if(e.y > this.game.config.height){
e.destroy();
this.config.pack.created -= 1;
}
})
}
moveEnemy() {
this.enemys.children.each((e) => {
if(this.cursors.up.isDown){
if(this.config.speed < this.config.maxSpeed-1){
e.y -= this.config.maxSpeed;
return
};
e.y += this.config.enemy.speed;
// Move left or right
if(this.config.enemy.x < 150 && e.x < 290){
e.x += 1;
this.enemy.anims.play('right', true);
}
else if(e.x > 90){
e.x -= 1;
this.enemy.anims.play('left', true);
}else{
this.enemy.anims.play('default', true);
}
}else{
if(e.y < -1000) return;
e.y -= this.config.maxSpeed;
}
if(e.y - 200 > this.game.config.height){
e.destroy();
this.config.enemy.created -= 1;
}
})
}
updateEngineTemperatureBar(){
if(this.cursors.up.isDown && this.config.engine.temperature <= 100){
this.config.engine.temperature += 0.1;
}
else if(this.cursors.up.isUp && this.config.engine.temperature < 100){
this.config.engine.temperature += 0.2;
}else{
this.scene.start('end', { motiveText: "O motor do seu carro explodiu." });
}
// change the size of the bar
this.engineTemperatureBar.scaleX = this.config.engine.temperature/100;
}
updateLifes(){
if(this.numberLifes <= 1){
this.scene.start('end', { motiveText: "Suas vidas acabaram." });
}else{
this.spriteLife[this.numberLifes-1].destroy();
this.numberLifes = this.numberLifes -1;
}
}
collectPack(player, pack){
// Destroy pack
pack.disableBody(true, true);
pack.destroy();
// Config
this.config.pack.created -= 1;
// Score
this.score++;
this.scoreText.setText("SCORE: " + this.score);
// Engien temperature bar
if(this.config.engine.temperature > 1)
this.config.engine.temperature -= this.config.pack.value;
}
collideEnemy(player, enemy){
// Life
this.updateLifes();
// Destroy
enemy.destroy();
// Config
this.config.speed = 1;
this.config.enemy.created -= 1;
}
}
export default Play;
End
import Phaser from "phaser";
class End extends Phaser.Scene{
constructor ()
{
super({ key: 'end', active: false });
}
init(data){
this.motiveText = data.motiveText;
}
preload(){
}
create() {
this.helloWorld = this.add.text(
this.cameras.main.centerX,
this.cameras.main.centerY,
"Perdeu!",
{ font: "40px Arial", fill: "#ffffff" }
);
this.helloWorld.setOrigin(0.5);
this.helloWorld = this.add.text(
this.cameras.main.centerX,
this.cameras.main.centerY + 40,
this.motiveText,
{ font: "20px Arial", fill: "#ffffff" }
);
this.helloWorld.setOrigin(0.5);
this.helloWorld = this.add.text(
this.cameras.main.centerX,
this.cameras.main.centerY + 70,
"Clique para jogar novamente.",
{ font: "20px Arial", fill: "#ffffff" }
);
this.helloWorld.setOrigin(0.5);
this.input.on('pointerup', function (pointer) {
this.scene.start("start");
}, this);
}
update() {
}
}
export default End;
Again, the problem is that he doesn't completely rest. Even using the 'restart' methods, destroying the events and restarting them.
The issue is, that your are setting properties on the Scenes classes, like the property config on the Play class. Since these properties are not set in the create or the init function, they will never be reset, on start/
restart.
When the Scenes are restarted, scenes are not recreated, so properties are not reset and the constructor is also not called.
If you need to define / set properties on the Scenes, the best solution would be to always (re)set them in the init or create function, since these functions are called on start or restart.
I would recomend, simply moving the properties from the Play class into the init method like this:
class Play extends Phaser.Scene {
...
init() {
this.index = 0;
this.packs = Phaser.GameObjects.Group;
this.enemys = Phaser.GameObjects.Group;
this.spriteLife = [];
this.config = {
speed: 0,
speedVelocity: 0.3,
maxSpeed: 15,
pack: {
...
},
enemy: {
...
},
engine: {
temperature: 0,
}
};
}
...
}
I’m trying to set up the Conway's Game of Life using Phaser.
My question is this: how can I make a Rectangular of the Phaser.geom class contain a click event?
Class Dots:
import 'phaser';
const COLOUR_ALIVE = 0xffffff;
const COLOUR_DEAD = 0x00000;
export class Dots extends Phaser.Geom.Rectangle {
public alive: number;
public fillColor: number;
public id: string;
constructor(scene, x, y, width, height, alive, id?) {
super(x, y, width, height);
this.alive = alive;
if(this.alive == 1){
this.fillColor = COLOUR_ALIVE;
} else {
this.fillColor = COLOUR_DEAD;
}
this.id = id;
console.log(id);
}
public isAlive():boolean{
return (this.alive == 1);
}
public returnAliveValue():number{
return this.alive;
}
public getFillColor(): number{
return this.fillColor;
}
public dead(){
this.alive = 0;
this.fillColor = COLOUR_DEAD;
}
public setAlive(){
this.alive = 1;
this.fillColor = COLOUR_ALIVE;
}
public click(pointer, gameobject){
console.log(pointer, gameobject);
}
}
Class Game:
import 'phaser';
import {Dots} from './classes/Dots'
const square_size = 10;
const pixel_height = 600;
const pixel_width = 800;
const DOTS = 100;
export default class Demo extends Phaser.Scene
{
private alives: Dots[] = [];
private graphics:Phaser.GameObjects.Graphics = null;
public timeElapsed: number;
public maxTime: number;
public cont = 0;
constructor ()
{
super('demo');
this.timeElapsed = 0;
this.maxTime = 1;
}
preload ()
{
}
draw () {
this.graphics = this.add.graphics();
//Afegim les fitxes vives
let pointer = this.input.activePointer;
this.alives.forEach((rectangle:Dots) => {
this.graphics.fillStyle(rectangle.getFillColor(), 1);
this.graphics.fillRectShape(rectangle);
this.graphics.setInteractive({
hitArea: new Phaser.Geom.Rectangle(0, 22, 27, 29),
hitAreaCallback: Phaser.Geom.Rectangle.Contains,
useHandCursor: true
}, (evt, geom) => {
if(pointer.isDown){
console.log(evt, geom);
}
});
});
}
destroy(obj:Phaser.GameObjects.Graphics) {
obj.destroy();
}
intersects(object1:Dots, object2:Dots){
let x = object1.x;
let y = object1.y;
let intersects = false;
if(object2.x == x - square_size && y == object2.y){
//Bloque izquierda
intersects = true;
} else if( object2.x == x + square_size && y == object2.y){
//Bloque derecha
intersects = true;
}
if(object2.y == y - square_size && x == object2.x){
//Bloque superior
intersects = true;
} else if(object2.y == y + square_size && x == object2.x){
//Bloque inferior
intersects = true;
}
if(object2.x == x - square_size && object2.y == y - square_size){
// Bloque izquierda superior
intersects = true;
} else if (object2.x == x - square_size && object2.y == y + square_size){
// Bloque izquierda inferior
intersects = true;
}
if(object2.x == x + square_size && object2.y == y - square_size){
// Bloque derecha superior
intersects = true;
} else if (object2.x == x + square_size && object2.y == y + square_size){
// Bloque derecha inferior
intersects = true;
}
return intersects;
}
searchArrIntersect(){
this.alives.forEach((x) => {
if(x.alive == 1){
let intersections = 0;
this.alives.forEach((y) => {
if(x != y){
let intersects = this.intersects(x, y);
if(intersects){
intersections ++;
}
}
});
if(intersections == 2 || intersections == 3){
x.isAlive();
}
if(intersections >= 3){
x.dead();
}
} else{
//fichas muertas
let intersections = 0;
this.alives.forEach((y) => {
if(x != y){
let intersects = this.intersects(x, y);
if(intersects){
intersections ++;
}
}
});
if(intersections == 3){
x.isAlive();
}
}
});
}
castObjectIntersects(object_search:Dots):Dots{
let dot_intersect = null;
this.alives.forEach((x, index) => {
if(x.x == object_search.x && x.y == object_search.y){
dot_intersect = x;
}
});
return dot_intersect;
}
create ()
{
let positions = [
//cross
// {x: pixel_width/2 - square_size, y: pixel_height/2, alive:1, id:'left'},
// {x: pixel_width/2 + square_size, y: pixel_height/2, alive:1, id:'right'},
// {x: pixel_width/2, y: pixel_height/2, alive:1, id:'center'},
// {x: pixel_width/2, y: pixel_height/2 - square_size, alive:1, id:'up'},
// {x: pixel_width/2, y: pixel_height/2 + square_size, alive:1, id:'down'},
// //borders
// //left
// {x: pixel_width/2 - square_size, y: pixel_height/2 - square_size, alive: 1, id:'left_up'},
// {x: pixel_width/2 - square_size, y: pixel_height/2 + square_size, alive: 1, id:'left_down'},
// //right
// {x: pixel_width/2 + square_size, y: pixel_height/2 - square_size, alive:0, id:'right_up'},
// {x: pixel_width/2 + square_size, y: pixel_height/2 + square_size, alive:0, id:'right_down'},
];
for(let i = 0; i < pixel_width; i+=10){
for(let j = 0; j < pixel_height; j+=10){
positions.push({x: i, y: j, alive:0, id:`${i}-${j}`});
}
}
positions.forEach((obj) => {
this.alives.push(new Dots(this, obj.x, obj.y, square_size, square_size, obj.alive, obj.id));
});
for(let i = 0; i <= DOTS; i++){
let random_length = Math.floor(Math.random() * (this.alives.length - 1 + 1) + 1);
let dot = this.alives[random_length];
dot.setAlive();
}
this.draw();
}
update(time: number, delta: number): void {
let deltaInSecond = delta/1000; // convert it to second
this.timeElapsed = this.timeElapsed + deltaInSecond;
if(this.timeElapsed >= this.maxTime) // if the time elapsed already more than 1 second
{
this.searchArrIntersect();
this.destroy(this.graphics);
this.draw();
// this.maxTime = 1200;
this.timeElapsed = 0;
}
}
}
const config = {
type: Phaser.AUTO,
backgroundColor: '#000000',
width: pixel_width,
height: pixel_height,
render: {
pixelArt: true
},
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH
},
scene: Demo
};
const game = new Phaser.Game(config);
You are setting interactive on the graphics serveral time, it the forEach-loop. I think this can be done only once, so you are overriding it, but I'm no expert.
I would set the interactivity once, for the whole region:
this.graphics.setInteractive({ useHandCursor: true,
hitArea: new Phaser.Geom.Rectangle(0, 0, pixel_width, pixel_height),
hitAreaCallback: Phaser.Geom.Rectangle.Contains,
})
And than in the "click event" select the Rectangle/Dot
this.graphics.on( 'pointerdown', function(){
// ...
});
To get the Rectangle/Dot clicked, there are many ways, here is one:
this.graphics.on( 'pointerdown', function(pointer){
let selected = this.alives.find( point => Phaser.Geom.Rectangle.Contains( new
Phaser.Geom.Rectangle(point.x, point.y, point.width, point.height), pointer.worldX, pointer.worldY
));
console.log('pointerover', pointer, selected);
}, this);
btw.:
I would add the graphics once in the create method:
create () {
// ...
this.graphics = this.add.graphics();
this.graphics.setInteractive({
// ...
});
this.graphics.on('pointerdown', () => {
// ...
});
this.draw();
}
and in the draw method just clear the graphics-object.
draw () {
this.graphics.clear();
// ...
}
I'm integrating FabricJS into my angular application. I've managed to get the canvas down and automatically adding a figure into the canvas.
My goals are to make the figure 8inches by 8inches and to add a grid that has dynamic grid height and width (lets say 1/16th inch x 1/16inch).
Here are my problems:
1. When adding the figure, I cannot set the figure height and width in inches. I can only use a number. How can I use a different unit for this? I used cssOnly: true for the canvas but I cant seem to figure it out for the figure.
addFigure(figure) {
let add: any;
switch (figure) {
case 'rectangle':
add = new fabric.Rect({
width: 500, height: 500, left: 150, top: 10, angle: 0, opacity: .3,
fill: '#3f51b5'
});
break;
case 'square':
add = new fabric.Rect({
width: 200, height: 200, left: 0, top: 0, angle: 0, opacity: .15,
fill: '#4caf50'
});
break;
case 'triangle':
add = new fabric.Triangle({
width: 100, height: 100, left: 10, top: 10, fill: '#2196f3'
});
break;
case 'circle':
add = new fabric.Circle({
radius: 50, left: 10, top: 10, fill: '#ff5722'
});
break;
}
this.extend(add, this.randomId());
console.log(add);
this.canvas.add(add);
// this.selectItemAfterAdded(add);
}
The figure height displays 200 but it appears incorrect. Here is an example of the above figure as a square. Notice the 200 width is correct but the height does not seem right seeing as the canvas is 6inches by 6inches. The height extends pass the bottom of the canvas.
Notice the grid above. Im having the same problem. Here is my code for grid which I pulled from Adding grid over Fabric.js canvas . The problem I'm having is I have no idea how to make this grid evenly 1/16th inch 1/16th inch given this is an 8in by 8in canvas.
onst gridGroup = new fabric.Group([], {left: 0, top: 0});
const gridSize = 16;
const gridWidth = 400;
const gridHeight = 400;
const lineOption = {stroke: 'rgba(0,0,0,.4)', strokeWidth: 1, selectable: false, strokeDashArray: [3, 3]};
for (let i = Math.ceil(gridWidth / gridSize); i--;) {
this.canvas.add( new fabric.Line([gridSize * i, 0, gridSize * i, gridHeight], lineOption) );
}
for (let i = Math.ceil(gridHeight / gridSize); i--;) {
this.canvas.add( new fabric.Line([0, gridSize * i, gridWidth, gridSize * i], lineOption) );
}
this.canvas.add(gridGroup);
Here is the entire component for review. Is there something I'm doing wrong in the setup?
// private canvas: any;
uploading = false;
uploaded = false;
pdfUrl = '';
canvas: any;
props: any = {
canvasFill: '#ffffff',
canvasImage: '',
id: null,
opacity: null,
fill: null,
fontSize: null,
lineHeight: null,
charSpacing: null,
fontWeight: null,
fontStyle: null,
textAlign: null,
fontFamily: null,
TextDecoration: ''
};
textString: string;
url = '';
size: any = {
width: '6in',
height: '6in'
};
json: any;
globalEditor = false;
textEditor = false;
imageEditor = false;
figureEditor = false;
selected: any;
constructor(
private router: Router,
private userService: UserService,
private fileService: FileService
) { }
ngOnInit() {
this.getActive();
// this.activateCanvas();
//setup front side canvas
this.canvas = new fabric.Canvas('canvas', {
hoverCursor: 'pointer',
selection: true,
selectionBorderColor: 'blue'
});
this.canvas.on({
'object:moving': (e) => { },
'object:modified': (e) => { },
'object:selected': (e) => {
const selectedObject = e.target;
this.selected = selectedObject
selectedObject.hasRotatingPoint = true;
selectedObject.transparentCorners = false;
// selectedObject.cornerColor = 'rgba(255, 87, 34, 0.7)';
this.resetPanels();
if (selectedObject.type !== 'group' && selectedObject) {
this.getId();
this.getOpacity();
switch (selectedObject.type) {
case 'rect':
case 'circle':
case 'triangle':
this.figureEditor = true;
this.getFill();
break;
case 'i-text':
this.textEditor = true;
this.getLineHeight();
this.getCharSpacing();
this.getBold();
this.getFontStyle();
this.getFill();
this.getTextDecoration();
this.getTextAlign();
this.getFontFamily();
break;
case 'image':
break;
}
}
},
'selection:cleared': (e) => {
this.selected = null;
this.resetPanels();
}
});
this.canvas.setWidth(this.size.width, {cssOnly: true});
this.canvas.setHeight(this.size.height, {cssOnly: true});
this.addFigure('square');
const gridGroup = new fabric.Group([], {left: 0, top: 0});
const gridSize = 16;
const gridWidth = 400;
const gridHeight = 400;
const lineOption = {stroke: 'rgba(0,0,0,.4)', strokeWidth: 1, selectable: false, strokeDashArray: [3, 3]};
for (let i = Math.ceil(gridWidth / gridSize); i--;) {
this.canvas.add( new fabric.Line([gridSize * i, 0, gridSize * i, gridHeight], lineOption) );
}
for (let i = Math.ceil(gridHeight / gridSize); i--;) {
this.canvas.add( new fabric.Line([0, gridSize * i, gridWidth, gridSize * i], lineOption) );
}
this.canvas.add(gridGroup);
// for ( let x = 1; x < ( this.canvas.width / gridsize); x++) {
// this.canvas.add(new fabric.Line([cellWidth * x, 0, cellWidth * x, 800],
// { stroke: '#000000', strokeWidth: 1, selectable: false}));
// this.canvas.add(new fabric.Line([0, cellWidth * x, 800, cellWidth * x],
// { stroke: '#000000', strokeWidth: 1, selectable: false}));
// }
// get references to the html canvas element & its context
// this.canvas.on('mouse:down', (e) => {
// let canvasElement: any = document.getElementById('canvas');
// console.log(canvasElement)
// });
}
/*------------------------Block elements------------------------*/
//Block "Size"
changeSize(event: any) {
this.canvas.setWidth(this.size.width);
this.canvas.setHeight(this.size.height);
}
//Block "Add text"
addText() {
let textString = this.textString;
let text = new fabric.IText(textString, {
left: 10,
top: 10,
fontFamily: 'helvetica',
angle: 0,
fill: '#000000',
scaleX: 0.5,
scaleY: 0.5,
fontWeight: '',
hasRotatingPoint: true
});
this.extend(text, this.randomId());
this.canvas.add(text);
this.selectItemAfterAdded(text);
this.textString = '';
}
//Block "Add images"
getImgPolaroid(event: any) {
let el = event.target;
fabric.Image.fromURL(el.src, (image) => {
image.set({
left: 10,
top: 10,
angle: 0,
padding: 10,
cornersize: 10,
hasRotatingPoint: true,
peloas: 12
});
// image.setWidth(150);
// image.setHeight(150);
this.extend(image, this.randomId());
this.canvas.add(image);
this.selectItemAfterAdded(image);
});
}
//Block "Upload Image"
addImageOnCanvas(url) {
if (url) {
fabric.Image.fromURL(url, (image) => {
image.set({
left: 10,
top: 10,
angle: 0,
// scaleX: 200,
// scaleY: 200,
padding: 10,
cornersize: 10,
hasRotatingPoint: true
});
image.scale(0.2);
// image.setWidth(200);
// image.height = 200;
// image.width = 200;
this.extend(image, this.randomId());
this.canvas.add(image);
this.selectItemAfterAdded(image);
});
}
}
readUrl(event) {
if (event.target.files && event.target.files[0]) {
const reader = new FileReader();
reader.onload = (e) => {
this.url = e.target['result'];
};
reader.readAsDataURL(event.target.files[0]);
}
}
removeWhite(url) {
this.url = '';
}
//Block "Add figure"
addFigure(figure) {
let add: any;
switch (figure) {
case 'rectangle':
add = new fabric.Rect({
width: 500, height: 500, left: 150, top: 10, angle: 0, opacity: .3,
fill: '#3f51b5'
});
break;
case 'square':
add = new fabric.Rect({
width: 200, height: 200, left: 0, top: 0, angle: 0, opacity: .4,
fill: '#4caf50'
});
break;
case 'triangle':
add = new fabric.Triangle({
width: 100, height: 100, left: 10, top: 10, fill: '#2196f3'
});
break;
case 'circle':
add = new fabric.Circle({
radius: 50, left: 10, top: 10, fill: '#ff5722'
});
break;
}
this.extend(add, this.randomId());
console.log(add);
this.canvas.add(add);
// this.selectItemAfterAdded(add);
}
/*Canvas*/
cleanSelect() {
this.canvas.discardActiveObject();
}
selectItemAfterAdded(obj) {
this.canvas.discardActiveObject();
this.canvas.setActiveObject(obj);
}
setCanvasFill() {
if (!this.props.canvasImage) {
this.canvas.backgroundColor = this.props.canvasFill;
this.canvas.renderAll();
}
}
extend(obj, id) {
obj.toObject = (function (toObject) {
return function () {
return fabric.util.object.extend(toObject.call(this), {
id: id
});
};
})(obj.toObject);
}
setCanvasImage() {
let self = this;
if (this.props.canvasImage) {
this.canvas.setBackgroundColor({ source: this.props.canvasImage, repeat: 'repeat' }, function () {
// self.props.canvasFill = '';
self.canvas.renderAll();
});
}
}
randomId() {
return Math.floor(Math.random() * 999999) + 1;
}
/*------------------------Global actions for element------------------------*/
getActiveStyle(styleName, object) {
object = object || this.canvas.getActiveObject();
if (!object) {return '';}
return (object.getSelectionStyles && object.isEditing)
? (object.getSelectionStyles()[styleName] || '')
: (object[styleName] || '');
}
setActiveStyle(styleName, value, object) {
object = object || this.canvas.getActiveObject();
if (!object) {return '';}
if (object.setSelectionStyles && object.isEditing) {
let style = {};
style[styleName] = value;
object.setSelectionStyles(style);
object.setCoords();
} else {
object.set(styleName, value);
}
object.setCoords();
this.canvas.renderAll();
}
getActiveProp(name) {
let object = this.canvas.getActiveObject();
if (!object) {return '';}
return object[name] || '';
}
setActiveProp(name, value) {
const object = this.canvas.getActiveObject();
if (!object) {return ''};
object.set(name, value).setCoords();
this.canvas.renderAll();
}
clone() {
const activeObject = this.canvas.getActiveObject(),
activeGroup = this.canvas.getActiveGroup();
if (activeObject) {
let clone;
switch (activeObject.type) {
case 'rect':
clone = new fabric.Rect(activeObject.toObject());
break;
case 'circle':
clone = new fabric.Circle(activeObject.toObject());
break;
case 'triangle':
clone = new fabric.Triangle(activeObject.toObject());
break;
case 'i-text':
clone = new fabric.IText('', activeObject.toObject());
break;
case 'image':
clone = fabric.util.object.clone(activeObject);
break;
}
if (clone) {
clone.set({ left: 10, top: 10 });
this.canvas.add(clone);
this.selectItemAfterAdded(clone);
}
}
}
getId() {
this.props.id = this.canvas.getActiveObject().toObject().id;
}
setId() {
const val = this.props.id;
const complete = this.canvas.getActiveObject().toObject();
console.log(complete);
this.canvas.getActiveObject().toObject = () => {
complete.id = val;
return complete;
};
}
getOpacity() {
this.props.opacity = this.getActiveStyle('opacity', null) * 100;
}
setOpacity() {
this.setActiveStyle('opacity', +this.props.opacity / 100, null);
}
getFill() {
this.props.fill = this.getActiveStyle('fill', null);
}
setFill() {
this.setActiveStyle('fill', this.props.fill, null);
}
getLineHeight() {
this.props.lineHeight = this.getActiveStyle('lineHeight', null);
}
setLineHeight() {
this.setActiveStyle('lineHeight', parseFloat(this.props.lineHeight), null);
}
getCharSpacing() {
this.props.charSpacing = this.getActiveStyle('charSpacing', null);
}
setCharSpacing() {
this.setActiveStyle('charSpacing', this.props.charSpacing, null);
}
getFontSize() {
this.props.fontSize = this.getActiveStyle('fontSize', null);
}
setFontSize() {
this.setActiveStyle('fontSize', +this.props.fontSize, null);
}
getBold() {
this.props.fontWeight = this.getActiveStyle('fontWeight', null);
}
setBold() {
this.props.fontWeight = !this.props.fontWeight;
this.setActiveStyle('fontWeight', this.props.fontWeight ? 'bold' : '', null);
}
getFontStyle() {
this.props.fontStyle = this.getActiveStyle('fontStyle', null);
}
setFontStyle() {
this.props.fontStyle = !this.props.fontStyle;
this.setActiveStyle('fontStyle', this.props.fontStyle ? 'italic' : '', null);
}
getTextDecoration() {
this.props.TextDecoration = this.getActiveStyle('textDecoration', null);
}
setTextDecoration(value) {
let iclass = this.props.TextDecoration;
if (iclass.includes(value)) {
iclass = iclass.replace(RegExp(value, 'g'), '');
} else {
iclass += ` ${value}`
}
this.props.TextDecoration = iclass;
this.setActiveStyle('textDecoration', this.props.TextDecoration, null);
}
hasTextDecoration(value) {
return this.props.TextDecoration.includes(value);
}
getTextAlign() {
this.props.textAlign = this.getActiveProp('textAlign');
}
setTextAlign(value) {
this.props.textAlign = value;
this.setActiveProp('textAlign', this.props.textAlign);
}
getFontFamily() {
this.props.fontFamily = this.getActiveProp('fontFamily');
}
setFontFamily() {
this.setActiveProp('fontFamily', this.props.fontFamily);
}
/*System*/
removeSelected() {
let activeObject = this.canvas.getActiveObject(),
activeGroup = this.canvas.getActiveGroup();
if (activeObject) {
this.canvas.remove(activeObject);
// this.textString = '';
} else if (activeGroup) {
let objectsInGroup = activeGroup.getObjects();
this.canvas.discardActiveGroup();
let self = this;
objectsInGroup.forEach(function (object) {
self.canvas.remove(object);
});
}
}
bringToFront() {
let activeObject = this.canvas.getActiveObject(),
activeGroup = this.canvas.getActiveGroup();
if (activeObject) {
activeObject.bringToFront();
// activeObject.opacity = 1;
}
else if (activeGroup) {
let objectsInGroup = activeGroup.getObjects();
this.canvas.discardActiveGroup();
objectsInGroup.forEach((object) => {
object.bringToFront();
});
}
}
sendToBack() {
const activeObject = this.canvas.getActiveObject(),
activeGroup = this.canvas.getActiveGroup();
if (activeObject) {
activeObject.sendToBack();
// activeObject.opacity = 1;
} else if (activeGroup) {
const objectsInGroup = activeGroup.getObjects();
this.canvas.discardActiveGroup();
objectsInGroup.forEach((object) => {
object.sendToBack();
});
}
}
confirmClear() {
if (confirm('Are you sure?')) {
this.canvas.clear();
}
}
rasterize() {
if (!fabric.Canvas.supports('toDataURL')) {
alert('This browser doesn\'t provide means to serialize canvas to an image');
} else {
console.log(this.canvas.toDataURL('png'))
//window.open(this.canvas.toDataURL('png'));
let image = new Image();
image.src = this.canvas.toDataURL('png')
let w = window.open('');
w.document.write(image.outerHTML);
}
}
rasterizeSVG() {
console.log(this.canvas.toSVG())
// window.open(
// 'data:image/svg+xml;utf8,' +
// encodeURIComponent(this.canvas.toSVG()));
// console.log(this.canvas.toSVG())
// let image = new Image();
// image.src = this.canvas.toSVG()
const w = window.open('');
w.document.write(this.canvas.toSVG());
}
saveCanvasToJSON() {
const json = JSON.stringify(this.canvas);
localStorage.setItem('Kanvas', json);
console.log('json');
console.log(json);
}
loadCanvasFromJSON() {
const CANVAS = localStorage.getItem('Kanvas');
console.log('CANVAS');
console.log(CANVAS);
// and load everything from the same json
this.canvas.loadFromJSON(CANVAS, () => {
console.log('CANVAS untar');
console.log(CANVAS);
// making sure to render canvas at the end
this.canvas.renderAll();
// and checking if object's "name" is preserved
console.log('this.canvas.item(0).name');
console.log(this.canvas);
});
}
rasterizeJSON() {
this.json = JSON.stringify(this.canvas, null, 2);
}
resetPanels() {
this.textEditor = false;
this.imageEditor = false;
this.figureEditor = false;
}
In summary, I'm looking to use a 1/16th inch x 1/16th inch (possibly dynamic) grid on an 8inch by 8inch canvas and add a figure that is also an even square inside this canvas.
For anyone having this same problem. It seems that the cssOnly boolean param option Im passing is not a solution for actually scaling the canvas to inches.
Here's how I resolved.
1) I now have an input that allows the user to manually enter in their PPI given the information on this url - http://dpi.lv/
2) I save that PPI
3) I created a method calcPixels(inches: number) which uses pixels = inches * ppi to calculate the number of pixels needed
4) I use that method across the application for all widths, heights, grid lines and etc.
This gives me a to scale 7in by 7inch grid line. Its a little less automated but if you save the PPI, the user only has to enter it once!
New result
I am working on a tool to perform sequence of animations by updating an object array. This array would have all the parameters to customize animation as per varied requirements. This tool is being developed with JavaScript and makes use of createJS library and TweenJS to animate objects. Objects are created dynamically and positioned, then the tween is applied. Tween doesn't seem to work in my code.
I have the whole code below
var AnimationFlow = (function () {
'use strict';
var AnimationFlow = function (canvasID) {
this.canvas = document.getElementById(canvasID);
this.stage = new createjs.Stage(this.canvas);
this.timeline = new createjs.Timeline();
this.tween = [];
this.preload;
this.animData;
this.manifest = [];
this.animObject = [];
this.stageObject = [];
this.loadProgressLabel;
this.loadingBarContainer;
this.loadingBar;
};
AnimationFlow.prototype.setData = function (data) {
this.animData = data;
this.manifest = [];
this.renderProgressBar();
for (var i = 0; i < this.animData.length; i++) {
this.manifest.push({'src': this.animData[i].targeturl, 'id': this.animData[i].targetID});
}
};
AnimationFlow.prototype.init = function () {
createjs.Ticker.addEventListener("tick", this.tick.bind(this));
createjs.Ticker.setFPS(30);
createjs.Ticker.useRAF = true;
this.preload = new createjs.LoadQueue(false);
this.preload.addEventListener("complete", this.handleComplete.bind(this));
this.preload.addEventListener("progress", this.handleProgress.bind(this));
this.preload.loadManifest(this.manifest);
this.stage.update();
};
AnimationFlow.prototype.handleProgress = function () {
this.loadingBar.scaleX = this.preload.progress * this.loadingBarWidth;
this.progresPrecentage = Math.round(this.preload.progress * 100);
this.loadProgressLabel.text = this.progresPrecentage + "% Loaded";
this.stage.update();
};
AnimationFlow.prototype.handleComplete = function () {
//Load images logic to be added
for (var i = 0; i < this.manifest.length; i++) {
this.animObject.push(this.preload.getResult(this.manifest[i].id));
}
this.loadProgressLabel.text = "Loading complete click to start";
this.stage.update();
this.canvas.addEventListener("click", this.handleClick.bind(this));
};
AnimationFlow.prototype.handleClick = function () {
this.start();
this.stage.removeChild(this.loadProgressLabel, this.loadingBarContainer);
this.canvas.removeEventListener("click", this.handleClick);
};
AnimationFlow.prototype.start = function () {
for (var i = 0; i < this.animObject.length; i++) {
this.obj = new createjs.Bitmap(this.animObject[i]);
this.obj.x = this.animData[i].initialXPos;
this.obj.y = this.animData[i].initialYPos;
this.obj.visible = this.animData[i].initialVisibility;
this.stage.addChild(this.obj);
this.stageObject.push(this.obj);
if(this.animData[i].isAnimatable){
var c = createjs.Tween.get(this.obj);
c.to({x:this.animData[i].params.xpos}, this.animData[i].duration);
c.call(this.tweenComplete);
this.timeline.addTween(c);
}
}
this.stage.update();
};
AnimationFlow.prototype.tick = function () {
console.log("heart beat on....");
this.stage.update();
};
AnimationFlow.prototype.tweenComplete = function () {
console.log("tweenComplete.......");
};
AnimationFlow.prototype.renderProgressBar = function () {
this.loadProgressLabel = new createjs.Text("", "18px Verdana", "black");
this.loadProgressLabel.lineWidth = 200;
this.loadProgressLabel.textAlign = "center";
this.loadProgressLabel.x = this.canvas.width / 2;
this.loadProgressLabel.y = 50;
this.stage.addChild(this.loadProgressLabel);
this.loadingBarContainer = new createjs.Container();
this.loadingBarHeight = 20;
this.loadingBarWidth = 300;
this.LoadingBarColor = createjs.Graphics.getRGB(0, 0, 0);
this.loadingBar = new createjs.Shape();
this.loadingBar.graphics.beginFill(this.LoadingBarColor).drawRect(0, 0, 1, this.loadingBarHeight).endFill();
this.frame = new createjs.Shape();
this.padding = 3;
this.frame.graphics.setStrokeStyle(1).beginStroke(this.LoadingBarColor).drawRect(-this.padding / 2, -this.padding / 2, this.loadingBarWidth + this.padding, this.loadingBarHeight + this.padding);
this.loadingBarContainer.addChild(this.loadingBar, this.frame);
this.loadingBarContainer.x = Math.round(this.canvas.width / 2 - this.loadingBarWidth / 2);
this.loadingBarContainer.y = 100;
this.stage.addChild(this.loadingBarContainer);
};
return AnimationFlow;
})();
var data = [{targetID: 'background', targeturl: 'assets/images/heliGame/sky.png',isAnimatable:true, duration: 2000, params: {xpos: '600'}, isVisibleAfterAnimation: true, isVisibleAtStartAnimation: true, initialVisibility: true, initialXPos: '0', initialYPos: '0'},
{targetID: 'mousePointer', targeturl: 'assets/images/heliGame/helicopter.png',isAnimatable:true, duration: 1000, params: {xpos: '500'}, isVisibleAfterAnimation: false, isVisibleAtStartAnimation: true, initialVisibility: true, initialXPos: '0', initialYPos: '0'}];
var buttons = ["playPauseBtn", "startFirstBtn", "reverseBtn"];
var animTool = new AnimationFlow('testCanvas');
animTool.setData(data);
animTool.init();
I have the code in JSFiddle
https://jsfiddle.net/jamesshaji/t4pxzsoo/
There were a couple of issues. Firstly, you need to define all of your positions as integers and not as strings (ie: take the quotes off of your position data in your data object). Secondly, you need to call: this.timeline.gotoAndPlay(0); to start the timeline execution. Otherwise the animations won't play. Here is a fixed version:
var AnimationFlow = (function() {
'use strict';
var AnimationFlow = function(canvasID) {
this.canvas = document.getElementById(canvasID);
this.stage = new createjs.Stage(this.canvas);
this.timeline = new createjs.Timeline();
this.tween = [];
this.preload;
this.animData;
this.manifest = [];
this.animObject = [];
this.stageObject = [];
this.loadProgressLabel;
this.loadingBarContainer;
this.loadingBar;
};
AnimationFlow.prototype.setData = function(data) {
this.animData = data;
this.manifest = [];
this.renderProgressBar();
for (var i = 0; i < this.animData.length; i++) {
this.manifest.push({
'src': this.animData[i].targeturl,
'id': this.animData[i].targetID
});
}
};
AnimationFlow.prototype.init = function() {
createjs.Ticker.addEventListener("tick", this.tick.bind(this));
createjs.Ticker.setFPS(30);
createjs.Ticker.useRAF = true;
this.preload = new createjs.LoadQueue(false);
this.preload.addEventListener("complete", this.handleComplete.bind(this));
this.preload.addEventListener("progress", this.handleProgress.bind(this));
this.preload.loadManifest(this.manifest);
this.stage.update();
};
AnimationFlow.prototype.handleProgress = function() {
this.loadingBar.scaleX = this.preload.progress * this.loadingBarWidth;
this.progresPrecentage = Math.round(this.preload.progress * 100);
this.loadProgressLabel.text = this.progresPrecentage + "% Loaded";
this.stage.update();
};
AnimationFlow.prototype.handleComplete = function() {
//Load images logic to be added
for (var i = 0; i < this.manifest.length; i++) {
this.animObject.push(this.preload.getResult(this.manifest[i].id));
}
this.loadProgressLabel.text = "Loading complete click to start";
this.stage.update();
this.canvas.addEventListener("click", this.handleClick.bind(this));
};
AnimationFlow.prototype.handleClick = function() {
this.start();
this.stage.removeChild(this.loadProgressLabel, this.loadingBarContainer);
this.canvas.removeEventListener("click", this.handleClick);
};
AnimationFlow.prototype.start = function() {
for (var i = 0; i < this.animObject.length; i++) {
this.obj = new createjs.Bitmap(this.animObject[i]);
this.obj.x = this.animData[i].initialXPos;
this.obj.y = this.animData[i].initialYPos;
this.obj.visible = this.animData[i].initialVisibility;
this.stage.addChild(this.obj);
this.stageObject.push(this.obj);
if (this.animData[i].isAnimatable) {
console.log("animatable:" + this.animData[i].params.xpos + " " + this.animData[i].duration);
var c = createjs.Tween.get(this.obj);
c.to({
x: this.animData[i].params.xpos
}, this.animData[i].duration);
c.call(this.tweenComplete);
this.timeline.addTween(c);
}
}
this.timeline.gotoAndPlay(0);
this.stage.update();
};
AnimationFlow.prototype.tick = function() {
this.stage.update();
};
AnimationFlow.prototype.tweenComplete = function() {
console.log("tweenComplete.......");
};
AnimationFlow.prototype.renderProgressBar = function() {
this.loadProgressLabel = new createjs.Text("", "18px Verdana", "black");
this.loadProgressLabel.lineWidth = 200;
this.loadProgressLabel.textAlign = "center";
this.loadProgressLabel.x = this.canvas.width / 2;
this.loadProgressLabel.y = 50;
this.stage.addChild(this.loadProgressLabel);
this.loadingBarContainer = new createjs.Container();
this.loadingBarHeight = 20;
this.loadingBarWidth = 300;
this.LoadingBarColor = createjs.Graphics.getRGB(0, 0, 0);
this.loadingBar = new createjs.Shape();
this.loadingBar.graphics.beginFill(this.LoadingBarColor).drawRect(0, 0, 1, this.loadingBarHeight).endFill();
this.frame = new createjs.Shape();
this.padding = 3;
this.frame.graphics.setStrokeStyle(1).beginStroke(this.LoadingBarColor).drawRect(-this.padding / 2, -this.padding / 2, this.loadingBarWidth + this.padding, this.loadingBarHeight + this.padding);
this.loadingBarContainer.addChild(this.loadingBar, this.frame);
this.loadingBarContainer.x = Math.round(this.canvas.width / 2 - this.loadingBarWidth / 2);
this.loadingBarContainer.y = 100;
this.stage.addChild(this.loadingBarContainer);
};
return AnimationFlow;
})();
var data = [{
targetID: 'background',
targeturl: 'https://s13.postimg.org/tyj4iop93/Sky_Pic.jpg',
isAnimatable: true,
duration: 2000,
params: {
xpos: -100
},
isVisibleAfterAnimation: true,
isVisibleAtStartAnimation: true,
initialVisibility: true,
initialXPos: 0,
initialYPos: 0
}, {
targetID: 'mousePointer',
targeturl: 'http://jamesshaji.com/angular/assets/images/heliGame/helicopter.png',
isAnimatable: true,
duration: 2000,
params: {
xpos: 100
},
isVisibleAfterAnimation: false,
isVisibleAtStartAnimation: true,
initialVisibility: true,
initialXPos: 450,
initialYPos: 50
}];
var buttons = ["playPauseBtn", "startFirstBtn", "reverseBtn"];
var animTool = new AnimationFlow('testCanvas');
animTool.setData(data);
animTool.init();
<script src="https://code.createjs.com/createjs-2015.11.26.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tweenjs/0.6.2/tweenjs.min.js"></script>
<div>Animation</div>
<canvas height="500" width="500" id="testCanvas">
</canvas>