For context, I am working on a game using Phaser framework. However, this question is generally geared at Javascript.
I have defined the following class in my main.js file via a function constructor:
function AchievementsMenu() {
this.lastY = 43 * c.length
}
However, when making a prototype AchievementsMenu.prototype = Object.create( Phaser.Group.prototype ); I get the error: 'Uncaught ReferenceError: AchievementsMenu is not defined'.
I understand that I have simply created a function class defining the object without actually making an instance of it. I shouldn't need to, though, to create a prototype method, right?
Any help would be greatly appreciated!
Edit:
import 'pixi'
import 'p2'
import Phaser from 'phaser'
import * as AM from './managers/AchievementManager.js'
import * as HG from './managers/hgManager.js'
import * as DM from './managers/dataManager.js'
//Configs for initializing Phaser framework
var cfg = {
width: 1334,
height: 750,
renderer: Phaser.WEBGL,
parent: "gameDiv",
enableDebug: !1,
transparent: !1,
antialias: !1
},
game = new Phaser.Game(cfg);
game.achievementManager = new AM.AchievementManager( game );
game.hgManager = new HG.HGManager();
game.dataManager = new DM.DataManager( game );
//A decent chunk of the class
function AchievementsMenu() {
Phaser.Group.call(this, game);
var a = game.add.image(0, 0, "MainUI", "Achievements/Achievements_TextBG_Disabled.png");
a.anchor.setTo(.5),
a.scale.setTo(200),
a.alpha = .4,
a.tint = 0,
a.inputEnabled = !0,
a.events.onInputUp.add(this.onPressBG, this),
this.add(a);
var b = game.add.image(0, 0, "MainUI", "Achievements/Achievements_BG.png");
b.inputEnabled = !0,
b.events.onInputDown.add(this.onStartDrag, this),
b.events.onInputUp.add(this.onEndDrag, this),
this.add(b),
this.add(this.game.add.bitmapText(15, 2, "Omnes", "Achievements", 28)),
this.scrollableContent = game.add.group(),
this.add(this.scrollableContent);
for (var c = this.game.constants.achievements, d = this.game.playerData.achievements, e = 0; e < c.length; e++) {
var f = 80 * e + 35;
if (d.indexOf(e) == -1){
this.game.add.image(10, f, "MainUI", "Achievements/Achievements_TextBG_Disabled.png", this.scrollableContent),
this.game.add.image(15, f + 4, "MainUI", "Achievements/Achievements_Icon_Locked.png", this.scrollableContent);
}
else {
this.game.add.image(10, f, "MainUI", "Achievements/Achievements_TextBG_Enabled.png", this.scrollableContent),
this.game.add.image(15, f + 4, "MainUI", "Achievements/Achievements_Icon_0" + e + ".png", this.scrollableContent);
var g = this.game.add.bitmapText(450, f + 25, "Omnes", "Completed", 20, this.scrollableContent);
g.tint = 7454787
}
this.game.add.bitmapText(75, f + 10, "Omnes", c[e].name, 25, this.scrollableContent),
this.game.add.bitmapText(75, f + 35, "Omnes", c[e].description, 20, this.scrollableContent)
}
this.lastY = 43 * c.length;
}
AchievementsMenu.prototype = Object.create( Phaser.Group.prototype );
AchievementsMenu.prototype.onPressBG = function() {
this.visible = !1
};
Related
I would like to be able to overlay a html iframe on top of an augmented reality marker, however I cannot get the CSS3DRenderer to show the same result as the WebGLRenderer and I'm not sure where I'm going wrong.
The WebGL renders perfectly, with the mesh following the marker and it's all magic, the CSS3DRenderer however centers the iframe in the middle of the video, inversed and unscaled, and it rotates in the opposite direction.
Thanks to three.js and artoolkit, here is some test code using video input and both renderers.
new Promise(function(resolve,reject) {
var source = document.createElement('video');
source.autoplay = true;
source.playsinline = true;
source.controls = false;
source.loop = true;
source.onplay = function(event) {
resolve(source);
}
source.src = 'data/output_4.ogg';
document.body.appendChild(source);
}).then(function(source) {
var scene = new THREE.Scene();
var camera = new THREE.Camera();
camera.matrixAutoUpdate = false;
scene.add(camera);
var material = new THREE.MeshNormalMaterial({
transparent : true,
opacity : 0.5,
side : THREE.DoubleSide
});
var geometry = new THREE.PlaneGeometry(1,1);
var mesh = new THREE.Mesh(geometry,material);
// mesh.matrixAutoUpdate = false;
scene.add(mesh);
var renderer = new THREE.WebGLRenderer({
antialias : true,
alpha : true
});
renderer.setSize(source.videoWidth,source.videoHeight);
renderer.setClearColor(new THREE.Color('lightgrey'),0);
document.body.appendChild(renderer.domElement);
/*\
cssRenderer
\*/
var cssRenderer = new THREE.CSS3DRenderer();
cssRenderer.setSize(source.videoWidth,source.videoHeight);
var cssScene = new THREE.Scene();
var iframe = document.createElement("iframe");
iframe.src = "/data/index.html";
iframe.style.background = "rgb(0,0,0)";
var iframe3D = new THREE.CSS3DObject(iframe);
// iframe3D.matrixAutoUpdate = false;
cssScene.add(iframe3D);
document.body.appendChild(cssRenderer.domElement);
/*\
arController
\*/
var cameraParameters = new ARCameraParam();
var arController = null;
cameraParameters.onload = function() {
arController = new ARController(source.videoWidth,source.videoHeight,cameraParameters);
arController.addEventListener("getMarker",function(event) {
var modelViewMatrix = new THREE.Matrix4().fromArray(event.data.matrix);
camera.matrix.getInverse(modelViewMatrix);
// mesh.matrix.copy(modelViewMatrix);
// iframe3D.matrix.copy(modelViewMatrix);
});
var cameraViewMatrix = new THREE.Matrix4().fromArray(arController.getCameraMatrix());
camera.projectionMatrix.copy(cameraViewMatrix);
}
cameraParameters.load("data/camera_para.dat");
/*\
animate
\*/
requestAnimationFrame(function animate() {
requestAnimationFrame(animate);
if (!arController) {
return;
}
arController.process(source);
renderer.render(scene,camera);
cssRenderer.render(cssScene,camera);
});
});
I had hoped that rotating the camera instead of the object would provide a solution, alas. It's as if I was missing out some matrix transformation that needs to be applied.
Perhaps there was something with the fov parameters of the camera, or maybe the transform matrix was getting overwritten, but anyway I couldn't locate the problem. So here's an alternative that doesn't use CSS3DRenderer, or THREE.js.
Essentially we can use the coordinates from the marker data itself to create a projection matrix. Many, many thanks to this post which provided most of the code I needed.
function adjugate(m) { // Compute the adjugate of m
return [
m[4]*m[8]-m[7]*m[5],m[7]*m[2]-m[1]*m[8],m[1]*m[5]-m[4]*m[2],
m[6]*m[5]-m[3]*m[8],m[0]*m[8]-m[6]*m[2],m[3]*m[2]-m[0]*m[5],
m[3]*m[7]-m[6]*m[4],m[6]*m[1]-m[0]*m[7],m[0]*m[4]-m[3]*m[1]
];
}
function multiply(a,b) { // multiply two matrices
a = [
a[0],a[3],a[6],
a[1],a[4],a[7],
a[2],a[5],a[8]
];
b = [
b[0],b[3],b[6],
b[1],b[4],b[7],
b[2],b[5],b[8]
];
var m = Array(9);
for (var i = 0; i != 3; ++i) {
for (var j = 0; j != 3; ++j) {
var mij = 0;
for (var k = 0; k != 3; ++k) {
mij += a[3*i + k]*b[3*k + j];
}
m[3*i + j] = mij;
}
}
return [
m[0],m[3],m[6],
m[1],m[4],m[7],
m[2],m[5],m[8]
];
}
function apply(m,v) { // multiply matrix and vector
return [
m[0]*v[0] + m[3]*v[1] + m[6]*v[2],
m[1]*v[0] + m[4]*v[1] + m[7]*v[2],
m[2]*v[0] + m[5]*v[1] + m[8]*v[2]
];
}
//
var iframe = document.createElement("iframe");
iframe.src = "data/index.html";
iframe.style.position = "absolute";
iframe.style.left = "0";
iframe.style.top = "0";
iframe.style.transformOrigin = "0 0";
document.querySelector("main").appendChild(iframe);
var s = [
0,0,1,
iframe.offsetWidth,0,1,
0,iframe.offsetHeight,1
];
var v = apply(adjugate(s),[iframe.offsetWidth,iframe.offsetHeight,1]);
s = multiply(s,[
v[0], 0, 0,
0, v[1], 0,
0, 0, v[2]
]);
arController.addEventListener("getMarker",function(event) {
if (event.data.marker.id === marker) {
var d = [
event.data.marker.vertex[(4 - event.data.marker.dir) % 4][0],event.data.marker.vertex[(4 - event.data.marker.dir) % 4][1],1,
event.data.marker.vertex[(5 - event.data.marker.dir) % 4][0],event.data.marker.vertex[(5 - event.data.marker.dir) % 4][1],1,
event.data.marker.vertex[(7 - event.data.marker.dir) % 4][0],event.data.marker.vertex[(7 - event.data.marker.dir) % 4][1],1
];
var v = apply(adjugate(d),[event.data.marker.vertex[(6 - event.data.marker.dir) % 4][0],event.data.marker.vertex[(6 - event.data.marker.dir) % 4][1],1]);
d = multiply(d,[
v[0],0,0,
0,v[1],0,
0,0,v[2]
]);
var t = multiply(d,adjugate(s));
for (i = 0; i < 9; ++i) {
t[i] = t[i] / t[8];
t[i] = Math.abs(t[i]) < Number.EPSILON ? 0 : t[i];
}
t = [
t[0],t[1],0,t[2],
t[3],t[4],0,t[5],
0,0,1,0,
t[6],t[7],0,t[8]
];
iframe.style.transform = "matrix3d(" + t.join(", ") + ")";
} else {
// mesh.visible = false;
}
});
Might be an answer 4 years overdue, but it might be useful for somebody.
I've created an alternative solution.
You can check it here: https://github.com/jonathanneels/QrA
In essence;
QrA uses tilt-js to simulate 3D-effects (parallax) and AR.js a-box as the startobject.
The iframe gets pushed by the tilt.js functions and the AR cube's .position, .scale and .rotation is used as reference.
Enjoy!
Everything is working, except in the update function, when I put back the var player, it doesn't recognize it:
"Uncaught ReferenceError: player is not defined"
(I'm also not sure for the animation) (Mario is the player, it's a mario level)
Here is my code:
var SandBox = {
preload:function(){
//this.game
console.log("preload Sand Box");
this.game.load.image('platform', 'assets/platform.png');
this.game.load.spritesheet('mario', 'assets/mario.png', 32, 32 , 12);
this.game.load.image('coinbox', 'assets/coinbox.png');
},
create:function(){
console.log("create Sand Box");
var imageHeight = this.game.cache.getImage("platform").height;
this.game.physics.startSystem(Phaser.Physics.ARCADE);
var worldHeight = this.game.world.height;
var ground = this.game.add.sprite(0, worldHeight - imageHeight, 'platform');
var platform = this.game.add.sprite(250, 285, 'platform');
var platform = this.game.add.sprite(-250, 145, 'platform');
var platform = this.game.add.sprite(280, 285, 'coinbox');
var player = this.game.add.sprite(32, 100, 'mario');
this.game.physics.enable(ground);
this.game.physics.enable(platform);
this.game.physics.arcade.enable(player);
player.frame = 5;
ground.body.immovable = true;
platform.body.immovable = true;
player.body.bounce.y = 0.2;
player.body.gravity.y = 300;
player.body.collideWorldBounds = true;
player.animations.add('left', [0, 1, 2, 3], 10, true);
player.animations.add('right', [5, 6, 7, 8], 10, true);
},
update:function(){
console.log("update Sand Box");
this.game.physics.arcade.enable(player);
var hitPlatform = this.game.physics.arcade.collide(player, ground); // << THESE FUNCTIONS
}
}
The scope of variable player in thr snippet is local to the function it is in. One can move the declaration (with var) for player outside of the sandbox object:
var player;
var sandbox = {
create: function() {
//... skipping lines ...
player = this.game.add.sprite(32, 100, 'mario');
},
Update: function() {
//use player here
var hitPlatform = this.game.physics.arcade.collide(player, ground); // << THESE FUNCTIONS
}
};
Or make it part of the object:
var sandbox = {
create: function() {
//... skipping lines ...
this.player = this.game.add.sprite(32, 100, 'mario');
},
Update: function() {
//... skipping lines ...
//use this.player here
var hitPlatform = this.game.physics.arcade.collide(this.player, ground);
}
};
I've been through all the javascript, modernizr, and all the other files I can think of that might be controlling the speed of the main slider at the top of this webpage. The div is as follows:
<div class="image-block" id="AfWBAclyVl">
<img data-bottom-top="top: 0%;" data-top-bottom="top: -40%;" data-anchor-target="#AfWBAclyVl" data-src="images/slider/animation_1.jpg" />
<img data-bottom-top="top: 0%;" data-top-bottom="top: -40%;" data-anchor-target="#AfWBAclyVl" data-src="images/slider/animation_2.jpg" />
</div>
But the only javascript I can find that seems to affect slider speed is:
$.fn.owlCarousel.options = { slideSpeed : 200,};
And I can tell its not the control I'm looking for.
the website is http://sabiopleasanton.com - any thoughts at all are more than appreciated.
You're having trouble finding it because of how the code was obfuscated and minified. It's not being controlled via CSS. It's done in the core.min.js file.
Specifically this block:
var m = 15e3,
n = 4e3,
o = !0;
a(".image-block").each(function() {
function b() {
var b = d[e],
g = b.attr("data-src");
a.imgpreload(g, {
all: function() {
b.attr("src", g), Modernizr.csstransitions ? (a("img", c).removeClass("active"), b.addClass("active")) : (a("img", c).velocity({
opacity: 0
}, {
ease: i,
duration: n
}), b.velocity({
opacity: [1, 0]
}, {
ease: i,
duration: n
})), o = !1
}
}), e++, e >= f && (e = 0)
}
var c = this,
d = new Array;
a("img", this).each(function() {
d.push(a(this))
});
var e = 0,
f = d.length;
setInterval(b, m), b()
});
Here you have a variable in scientific notation var m = 15e3 which is referenced in the setInterval, alter that and you should be able to change it.
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 7 years ago.
Enchant.js is not familiarly used, but since it using same OOP style like prototype.js i think i've got a chance to ask it here.
this is my main.js:
var DIR_LEFT = 0;
var DIR_RIGHT = 1;
var DIR_UP = 2;
var DIR_DOWN = 3;
enchant();
window.onload = function () {
game = new Core(320, 320);
game.preload(
'res/map0.png',
'res/chara0.png'
);
game.fps = 30;
game.onload = function() {
var sceneGame = new SceneGame();
game.pushScene(sceneGame);
}
game.start();
//main gameplay scene
var SceneGame = Class.create(Scene, {
initialize: function() {
Scene.apply(this);
var stage, map, player, label;
stage = new Group();
map = tileMap(game.assets['res/map0.png']);
player = new Player();
label = new Label("hi!");
player.addEventListener(Event.ENTER_FRAME, this.update);
this.player = player;
this.map = map;
stage.addChild(map);
stage.addChild(player);
this.Elx = 1;
this.label = label;
this.addChild(stage);
this.addChild(label);
var pad = new Pad();
pad.y = 220;
this.addChild(pad);
},
update: function() {
this.Elx = 2;
console.log("Elx :" + this.Elx );
console.log(this.player.x);
}
});
var Player = Class.create(Sprite, {
initialize: function() {
Sprite.apply(this, [32, 32]);
this.image = game.assets['res/chara0.png'];
this.x = 2 * 16;
this.y = 16;
this.dir = DIR_DOWN;
this.anim = [
9, 10, 11, 10,
18, 19, 20, 19,
27, 28, 29, 28,
0, 1, 2, 1];
// Frame setting
if (!game.input.up && !game.input.down && !game.input.right && !game.input.left) {
this.age = 1;
this.frame = this.anim[this.dir * 4 + (this.age % 4)];
}
},
update: function (evt) {
}
});
}
initialize is the Enchant.js object constructor method,
the code above successfully returning the stage group child ( map and player) images on screen, but when i want to use on update SceneGame's method,
the console returned 2 for the this.Elx
but returning undefined error for this.player.x .
Why this is happening ?
any help are appreciated . thank you
thank you guys for your answer, so basically is my fault for lack of understanding about the Grouping method. So in the line i declared :
map = tileMap(game.assets['res/map0.png']);
this.map = map;
player = new Player();
this.player = player;
stage = new Group();
stage.addChild(player);
stage.addChild(map);
map.addChild(stage);
and in the update i tried to call console.log(this.player)
of course it wont work because the player inserted in scene as a child. I tried to change above line to :
map = tileMap(game.assets['res/map0.png']);
player = new Player();
stage = new Group();
stage.addChild(player);
this.player = stage.childNodes[0];
stage.addChild(map);
this.map = stage.childNodes[1];
map.addChild(stage);
above code succesfully return any property of this.player.
So this is solved . thank you :)
I am looking for a way to fill an Image with an image pattern in a FabricJs canvas, since there is not a built-in image filter to do this. Although my code is still in an early version, basically it should work(unfortunately it doesn't);
All the eavy work is done by applyTo method, where I load an image, then fill an hidden canvas with a pattern. I noticed that there is a function (source) which fall in an infinite recursion:
var pattern = new fabric.Pattern({
source: function () {
fhc.setDimensions({
width: smile.getWidth() + 5,
height: smile.getHeight() + 5,
});
return fhc.getElement();
},
repeat: 'repeat'
});
I have prepared a demo on JSFiddle
Could anyone help me to understand how to solve this issue?
(function (global) {
'use strict';
var fabric = global.fabric || (global.fabric = {}),
extend = fabric.util.object.extend;
fabric.Image.filters.ImagePatternEffect = fabric.util.createClass(fabric.Image.filters.BaseFilter, {
type: 'ImagePatternEffect',
initialize: function (options) {
options = options || {};
this.img = options.img;
},
applyTo: function (canvasEl) {
var w = canvasEl.width;
var h = canvasEl.height;
var hc = document.createElement('canvas');
fabric.Image.fromURL('http://i.imgur.com/0Ks0mlY.png', function (smile) {
debugger;
hc.setAttribute('width', w);
hc.setAttribute('height', h);
var fhc = new fabric.StaticCanvas(hc);
fhc.add(smile);
var pattern = new fabric.Pattern({
source: function () {
fhc.setDimensions({
width: smile.getWidth() + 5,
height: smile.getHeight() + 5,
});
return fhc.getElement();
},
repeat: 'repeat'
});
var rect = new fabric.Rect({
fill: pattern,
width: w,
height: h
});
fhc.add(rect);
fhc.renderAll();
var ifhcContext = fhc.getContext('2d');
var fhcImageData = ifhcContext.getImageData(0, 0, fhc.width, fhc.height);
var fhcData = fhcImageData.data;
var context = canvasEl.getContext('2d'),
imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
data = imageData.data;
for (var i = 0, n = data.length; i < n; i += 4) {
data[i] += fhcData[i];
data[i + 1] += fhcData[i + 1];
data[i + 2] += fhcData[i + 2];
}
context.putImageData(imageData, 0, 0);
});
},
toObject: function () {
return extend(this.callSuper('toObject'), {
});
}
});
fabric.Image.filters.ImagePatternEffect.fromObject = function (object) {
return new fabric.Image.filters.ImagePatternEffect(object);
};
})(typeof exports !== 'undefined' ? exports : this);
var canvas = new fabric.Canvas('c');
fabric.Image.fromURL('http://i.imgur.com/qaQ8jir.png', function (img) {
var orImg = img;
img.filters.push(new fabric.Image.filters.ImagePatternEffect({
img: orImg,
}));
img.applyFilters(canvas.renderAll.bind(canvas));
canvas.add(img.set({
width: 300,
height: 300,
}));
}, {
crossOrigin: ''
});
i also use pattern image on my web application , in order to add it on objects, and it works.
All you need is this function function loadPattern(url, seatObj) where i pass the object which i want to add the pattern each time and the image(pattern) link.
here is the snippet :
function loadPattern(url, seatObj) {
//i use the loadImage function to load the image and pass it to the fabric.Pattern constructor
fabric.util.loadImage(url, function (img) {
//i change the fill property of the object to the
//image that i want to load on it as a pattern
seatObj.fill = new fabric.Pattern({
source: img,
repeat: 'no-repeat'
});
//refresh canvas and watch your image pattern on the object
canvas.renderAll();
});
}
hope this helps,
good luck