I need help form this bit of code, been stuck for hours, cant seems to figure out. Any help will be much appreciated.
I have multiple sections that has pixi.js app. Initiated the functions as below.
var pixiFunctions = [
function(type) {
var pixi, sectionContainer, stage, texture, sprite, bars;
sectionContainer = $('section[data-media="established"]');
var established = {
init: function() {
pixi = new PIXI.Application({
width: getViewport().width,
height: getViewport().height,
transparent: true,
resolution: window.devicePixelRatio || 1,
antialias: true
});
sectionContainer.append(pixi.view);
stage = new PIXI.Container();
texture = new PIXI.Texture.from(loadedMedia[1].src);
texture.baseTexture.resource.autoplay = false;
texture.baseTexture.resource.source.loop = 'loop';
sprite = new PIXI.Sprite(texture);
texture.baseTexture.on('loaded', function() {
sprite.height = pixi.renderer.screen.height;
sprite.width = pixi.renderer.screen.width;
pixi.stage.addChild(sprite);
established.start();
});
},
start: function() {
pixi.render(stage);
requestAnimationFrame(established.start);
},
animateIn: function() {
console.log('animateIN');
**console.log(pixi)**
sectionContainer.addClass('active');
},
animateOut: function() {
console.log('animateOut');
sectionContainer.removeClass('active');
}
}
if (type === 'animateIn') established.animateIn();
if (type === 'animateOut') established.animateOut();
if (type === 'init') established.init();
}
]
I have a sets of functions like this for each ,
On DOM load, I am calling these functions in this manner,
for (var i = 0; i < pixiFunctions.length; i++) {
pixiFunctions[i]('init');
}
And here comes the issue, when I am scrolling, I have set up functions to fire up in this manner;
pixiFunctions[currentPosition]('animateIn');
[currentPosition] - refers to the count that increment as you scroll so that I can animate in sections.
Issue is whenever i call this function with a , the console logs as PIXI undefined. I have no clue how to sort it out. I needed this because I need to get a hold of pixi in order to animate the mask.
** pixiFunctionscurrentPosition;**
Thank you all.
Related
I am sorry if the answer here is obvious, I am mostly a c/c++ guy and javascript is relatively new to me.
I am using THREE, bundling with browserify. In one module, I am creating an array of mesh objects that I need to access in a nested function using forEach(...), but I keep getting an error, that the corresponding object is not defined. I am suspecting that the problem is related to me actually defining the array in a separate callback function that is defined in parallel with the nested function using the forEach(). I have been trying to "declare" the variable globally, before I assign it to the array in the callback function, but that doesn't work. In c++ I would define an uninstantiated object globally (or in a class header) and then instantiate it in some function later, while accessing it in yet another function after that. Below is the relevant code and the variable that keeps coming back undefined is called "mesh". Note that I am not even sure why setPallete(...) and update(...) are implemented as nested function (a strange concept to me)? In another incarnation of this code, I implement them as "standalone" (e.g. not nested) functions and things are working, but in that code I am not using browserify to bundle, because I have just one, monolythic script. So maybe this has soemthing to do with that.
Thank you for your help.
let mesh; //try global definition -- no dice
module.exports = function (app) {
const totalMeshes = 40;
const subdivisions = 300;
const numSides = 8;
const openEnded = false;
const geometry = createGeometry(numSides, subdivisions, openEnded);
const container = new THREE.Object3D();
const lines = newArray(totalMeshes);
ShaderLoader("scripts/Grp3D/lib/shaders/tube.vert", "scripts/Grp3D/lib/shaders/tube.frag", function (vertex, fragment) {
const baseMaterial = new THREE.RawShaderMaterial({
vertexShader: vertex,
fragmentShader: fragment,
side: THREE.FrontSide,
extensions: {
deriviatives: true
},
defines: {
lengthSegments: subdivisions.toFixed(1),
ROBUST: false,
ROBUST_NORMALS: false,
FLAT_SHADED: true
},
uniforms: {
thickness: { type: 'f', value: 1 },
time: { type: 'f', value: 0 },
color: { type: 'c', value: new THREE.Color('#303030') },
animateRadius: { type: 'f', value: 0 },
animateStrength: { type: 'f', value: 0 },
index: { type: 'f', value: 0 },
totalMeshes: { type: 'f', value: totalMeshes },
radialSegments: { type: 'f', value: numSides }
}
});
lines.map((_, i) => {
const t = totalMeshes <= 1 ? 0 : i / (totalMeshes - 1);
const material = baseMaterial.clone();
material.uniforms = THREE.UniformsUtils.clone(material.uniforms);
material.uniforms.index.value = t;
material.uniforms.thickness.value = randomFloat(0.005, 0.0075);
mesh = new THREE.Mesh(geometry, material);
mesh.frustumCulled = false; // to avoid ThreeJS errors
return mesh;
});
lines.forEach(tmesh => container.add(tmesh));
});
return {
object3d: container,
update,
setPalette
};
// animate in a new color palette
function setPalette (palette) {
tweenr.cancel();
lines.forEach((mesh, i) => {
const uniforms = mesh.material.uniforms;
uniforms.color.value.set(palette);
const delay = i * 0.004;
uniforms.animateRadius.value = 0;
uniforms.animateStrength.value = 1;
tweenr.to(uniforms.animateRadius, { value: 1, duration: 0.5, delay, ease: 'epxoOut' });
tweenr.to(uniforms.animateStrength, { value: 0, duration: 1, delay, ease: 'expoInOut' });
});
}
function update (dt) {
dt = dt / 1000;
lines.forEach(mesh => { //undefined when the code runs
mesh.material.uniforms.time.value += dt;
});
}
};
Few problems here:
wrong const lines = newArray(totalMeshes);
correct const lines= []; //In Js its not necessary to have a predefined length.
You need to put data in above lines array as well.
I hope I get this right. You probably mean the container variable etc., right?
The problem I see is that you are adding a anonymous callback function to ShaderLoader which takes two parameters. This function is called within ShaderLoader somewhere. Within the scope of ShaderLoader your variable container etc. is not available anymore.
You are using const here, which is block scoped. I found an article which explains it in a very good way.
I'm creating a game with the Phaser engine, and I'm currently using the application 'Tiled' to create a my own tilemap.
The actual problem seems to be with having multiple layers when creating this tilemap. I have 6 different layers:
"Background"
"WallBlocks"
"Grass"
"SpikeAnimation"
"DiamondAnimation"
"SlimeAnimation"
Here is my Game.js file
SleepSim.Game = function (game) {
this.map;
this.Background;
this.WallBlocks;
this.Grass;
this.SpikeAnimation;
this.DiamondAnimation;
this.SlimeAnimation;
}
SleepSim.Game.prototype = {
create: function () {
this.world.setBounds(0,0,5000,1000);
this.map = this.add.tilemap('gameWorld');
this.map.addTilesetImage('gameworld', 'tiles');
this.Background = this.map.createLayer('Background');
this.Background.resizeWorld();
this.WallBlocks = this.map.createLayer('WallBlocks');
this.Grass = this.map.createLayer('Grass');
this.SpikeAnimation = this.map.createLayer('SpikeAnimation');
this.DiamondAnimation = this.map.createLayer('DiamondAnimation');
this.SlimeAnimation = this.map.createLayer('SlimeAnimation');
},
update: function() {
if(this.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
this.camera.y += 10;
}
else if (this.input.keyboard.isDown(Phaser.Keyboard.UP)){
this.camera.y -= 10;
}
if (this.input.keyboard.isDown(Phaser.Keyboard.LEFT)){
this.camera.x -= 10;
}
else if (this.input.keyboard.isDown(Phaser.Keyboard.RIGHT)){
this.camera.x += 10;
}
}
}
I have the camera set this way at the moment to just fly through the map to make sure things can load.
Apologies if the formatting to this question is abit off, it's my first time posting! Any help would be super super appreciated.
I ran into a similar problem. You only need to create a variable for the first layer, the rest should not be variables.
this.map = this.add.tilemap('gameWorld');
this.map.addTilesetImage('gameworld', 'tiles');
this.Background = this.map.createLayer('Background');
this.Background.resizeWorld();
this.map.createLayer('WallBlocks');
this.map.createLayer('Grass');
this.map.createLayer('SpikeAnimation');
this.map.createLayer('DiamondAnimation');
this.map.createLayer('SlimeAnimation');
So I have a website that does a few things in webgl w/ three.js, and I noticed that loadTexture is going away soon, and that I should probably switch to using textureloaders. Basically, i'd like to preload all my textures before any code executes at the start of my code. I was thinking about doing something like below, which will allow me to load any number of images, and assign them to a texture object that can be called when needed.
var loadedtex = {}
var to_load = ['images/a.png','images/b.png','images/c.png']
var texture_loader = new THREE.TextureLoader();
for(var i=0;i<to_load.length;i++){
texture_loader.load(to_load[i],function(tex){
loadedtex[to_load[i]] = tex
})
}
I'm probably missing something obvious, but I can't quite get it to work correctly. When I use the code above, loadedtex will fill up loadedtex['images/c.png'] every time, instead of properly looping and remember which "i" value it should be using.
Proper result should be something like:
loadedtex['images/a.png'] = Three.Texture{}...
loadedtex['images/b.png'] = Three.Texture{}...
loadedtex['images/c.png'] = Three.Texture{}...
but what i really get is:
loadedtex['images/c.png'] = Three.Texture{}
I know its because the "i" variable will always be max value by the time anything loads, but i'm not sure how to accomplish what i want.
Thanks.
---edit---
This is what I ended up with. Seems to work well. Thanks for the advice.
var loadedtex = {}
var textureloaded = 0
var to_load = ['images/a.png','images/b.png','images/c.png']
var texture_loader = new THREE.TextureLoader();
load_textures = function(){
if (textureloaded == to_load.length){return}
var texture = to_load[textureloaded]
texture_loader.load(texture,function(tex){
loadedtex[texture] = tex
textureloaded += 1
load_textures()
})
}
load_textures()
If you're using ES6:
let assets = [
{ name:'img1', url:'img/img1.png' },
{ name:'img2', url:'img/img2.png' },
{ name:'img3', url:'img/img3.png' },
];
this.textures = {};
for ( let img of assets ) {
this.loader.load(img.url, ( texture ) => {
this.textures[img.name] = texture;
assets.splice( assets.indexOf(img), 1);
if ( !assets.length ) {
this.init()
}
console.log('[TextureLoader] Loaded %o', img.name);
});
}
Try to make a closure function for it like,
for(var i=0;i<to_load.length;i++){
(function(tl){
texture_loader.load(tl,function(tex){
loadedtex[tl] = tex
})
})(to_load[i]);
}
I'm trying to scroll a greensock tween in pixi. I'm getting errors trying to hook the code that gets the mouse/arrow input (trackpad.value) with my tween.
Here's my working greensock test tween, to make sure I have greensock working in pixi: (have to tween the position element in pixi):
var t1 = new TimelineMax({onUpdate:animate, onUpdateScope:stage});
t1.to(bg.position, 3, {y:100});
Here's my code where I'm trying to hook trackpad.value into the greensock code (I'm getting the following error: Uncaught TypeError: bg.position is not a function):
trackpad = new Trackpad(document);
var t1 = new TimelineMax({paused:true, onUpdate:animate, onUpdateScope:stage});
t1.progress(bg.position( Math.abs( trackpad.value ) / 3240));
I then tried the following - it didn't work (but I didn't get an error):
var moveIt = trackpad.value / 3240;
t1.progress(bg.position, moveIt, {});
Here's the code where the trackpad value is defined:
/*
* param: the html element that will be scrolled
*/
Trackpad = function(target)
{
this.target = target;
this.value = 0;
this.easingValue = 00;
this.dragOffset = 0;
this.dragging;
this.speed= 0;
this.prevPosition = 0;
$(this.target).mousedown($.proxy(this.onMouseDown, this));
this.target.onmousewheel = $.proxy(this.onMouseWheel, this);
// not forgetting touchs!
this.target.ontouchstart = $.proxy(this.onTouchStart, this);
// stop dragging!
$(document).keydown( $.proxy(this.onArrow, this))//function(e){
//this.target.ondragstart = function(){return false;}
}
// set constructor
Trackpad.constructor = Trackpad;
// create the functions
Trackpad.prototype.unlock = function()
{
this.locked = false;
this.speed = 0;
this.easingValue = this.value;
}
Trackpad.prototype.lock = function()
{
this.locked = true;
}
Trackpad.prototype.update = function()
{
if(this.easingValue > 0)this.easingValue = 0;
if(this.easingValue < -10700)this.easingValue = -10700;
this.value = this.easingValue;
if(this.dragging)
{
var newSpeed = this.easingValue - this.prevPosition;
newSpeed *= 0.7;
this.speed += (newSpeed - this.speed) *0.5;//+= (newSpeed - this.speed) * 0.5;
this.prevPosition = this.easingValue;
}
else
{
this.speed *= 0.9;
this.easingValue += this.speed;
if(Math.abs(this.speed) < 1)this.speed = 0;
}
}
Trackpad.prototype.onArrow = function(event)
{
if (event.keyCode == 38) {
// UP
this.speed = 4;
return false;
}
else if (event.keyCode == 40) {
// UP
this.speed -= 4
return false;
}
}
Trackpad.prototype.onMouseWheel = function(event)
{
event.preventDefault();
this.speed = event.wheelDelta * 0.1;
}
Trackpad.prototype.startDrag = function(newPosition)
{
if(this.locked)return;
this.dragging = true;
this.dragOffset = newPosition - this.value;
}
Trackpad.prototype.endDrag = function(newPosition)
{
if(this.locked)return;
this.dragging = false;
}
Trackpad.prototype.updateDrag = function(newPosition)
{
if(this.locked)return;
this.easingValue = (newPosition - this.dragOffset);
}
/*
* MOUSE
*/
Trackpad.prototype.onMouseDown = function(event)
{
if(event)event.preventDefault();
event.returnValue = false;
$(document).mousemove($.proxy(this.onMouseMove, this));
$(document).mouseup($.proxy(this.onMouseUp, this));
this.startDrag(event.pageY);
}
Trackpad.prototype.onMouseMove = function(event)
{
if(event)event.preventDefault();
this.updateDrag(event.pageY);
}
Trackpad.prototype.onMouseUp = function(event)
{
//$(this.target).mousemove(null);
$(document).unbind('mousemove');
$(document).unbind('mouseup');
//this.target.onmousemove = null;
this.endDrag();// = false;
}
/*
* TOUCH!
*/
Trackpad.prototype.onTouchStart = function(event)
{
//event.preventDefault();
this.target.ontouchmove = $.proxy(this.onTouchMove, this);
this.target.ontouchend = $.proxy(this.onTouchEnd, this);
this.startDrag(event.touches[0].clientY);
}
Trackpad.prototype.onTouchMove = function(event)
{
event.preventDefault();
this.updateDrag(event.touches[0].clientY);
}
Trackpad.prototype.onTouchEnd = function(event)
{
this.target.ontouchmove = null;
this.target.ontouchend = null;
this.endDrag();
}
** edit
tl = new TimelineLite( { paused: true } );
// respond to scroll event - in this case using jquery
$(window).scroll();
//apply whatever math makes the most sense to progress the timeline progress from 0 to 1 within those parameters. Something like,
$(window).scroll( function() {
var st = $(this).scrollTop();
if ( st < someArbitraryValue ) { // someArbitraryValue, where to start
// Here, "someOtherArbitaryValue" would be the
// "height" of the scroll to react to
tl.progress( Math.abs( st ) / someOtherArbitaryValue );
}
});
Is this the kind of effect you were after?
JavaScript:
window.requestAnimFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(callback){window.setTimeout(callback,1000/60);};})(); //http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
var stageWidth=$(window).innerWidth();
var stageHeight=$(window).innerHeight();
var renderer=PIXI.autoDetectRenderer(stageWidth,stageHeight);
var bg,cat,moon,blue,trackpad,texture1,texture2,texture3;
document.body.appendChild(renderer.view);
texture1=PIXI.Texture.fromImage('https://dl.dropboxusercontent.com/u/45891870/Experiments/StackOverflow/1.5/cat.jpg');
texture2=PIXI.Texture.fromImage('https://dl.dropboxusercontent.com/u/45891870/Experiments/StackOverflow/1.5/moon.jpg');
texture3=PIXI.Texture.fromImage('https://dl.dropboxusercontent.com/u/45891870/Experiments/StackOverflow/1.5/blue.jpg');
bg=new PIXI.Container();
cat=new PIXI.Sprite(texture1);
moon=new PIXI.Sprite(texture2);
blue=new PIXI.Sprite(texture3);
cat.anchor.x=cat.anchor.y=moon.anchor.x=moon.anchor.y=blue.anchor.x=blue.anchor.y=0;
cat.position.x=cat.position.y=moon.position.x=blue.position.x=bg.position.x=bg.position.y=0;
cat.width=moon.width=blue.width=stageWidth;
moon.position.y=1080;
blue.position.y=2160;
bg.addChild(cat);
bg.addChild(blue);
bg.addChild(moon);
bg.vy=bg.vx=0;//what are those?
trackpad=new Trackpad(document);
requestAnimFrame(animate);
function animate(){
requestAnimFrame(animate);
bg.position.y=trackpad.value;
trackpad.update();
renderer.render(bg);
}
Let me know if this is exactly the thing you were looking for & I'll then break it down for you in terms of what has changed in comparison to your code.
Notes:
First & foremost, I have used the latest version (v3.0.6) of Pixi.JS in my example above. This v3 update brought a few major changes. Couple of them prominent to your problem are:
No need for Stage object anymore for rendering purposes. Any Container type object can be used directly to be rendered on canvas.
Shortening of the name DisplayObjectContainer to simply Container. This is probably the reason why you are getting the error when trying to implement my code in your environment that you mentioned in comments because I presume you are using one of the old verions.
Read all about this update here, here & here.
I always prefer to use the latest & greatest of GSAP (v1.17.0). Even the dot releases of this framework brings major updates which is why I like to keep it up to date. Read an important note on this update here. Having said that, the current implementation doesn't really use TweenMax at all.
TweenMax bundles EasePack, CSSPlugin & a few other things. No need to load them in separately. Update your HTML accordingly. Use this handy GSAP CheatSheet by Peter Tichy to get such information and more about this tool.
Changes in Trackpad.js:
Inside the update method, there was a maximum scroll limit defined the page can scroll up to. That value previously was -10700. I changed it to -2160. You may want to set it to -3240 I think, based on what I have been able to understand so far as to what you are trying to achieve.
Formatting changes.
Changes in main.js (whatever name you gave to your main script file):
Added a requestAnimationFrame polyfill thanks to Paul Irish.
Removed the var stage= new PIXI.Stage(0xff00ff); line. Read #1 above for details.
Renamed DisplayObjectContainer to Container which was assigned to bg. Read #1 above for details.
Added bg.position.y=trackpad.value; in the animate loop. You were missing this. You will need to use trackpad.value in order to position your bg.
Added trackpad.update(); in the same animate loop. This is the big one and IMHO, this is the one you were failing to understand the purpose of. In summary, Trackpad.js needs to update its value on a timely basis & the only loop you have got running is the animate loop thanks to requestAnimFrame. Hence, the update(); method is called.
Rendering bg instead of stage. Read #1 above for details.
Formatting changes.
Let me know if anything is unclear.
T
I thought of editing the old answer but decided against it because I think it answers your original question.
Take a look at this Codepen demo for a new approach to the same problem. I am really hoping to listen to community on the approach I have taken here in terms of listening to events and using them to adjust a GSAP timeline.
There are 4 JS files used in my example: app.js, constants.js, timeline.js & listeners.js. Links to which can be found in the settings gear icon of the JavaScript editor of the demo. All of these files are heavily annotated with links to solutions I found over the internet to specific problems.
Among these files, code of app.js is as follows:
JavaScript:
function Application(){}
Application.prototype.init=function(){
this.constants=Constants.getInstance();
this.BASE_URL=this.constants.BASE_URL;
this.IMAGE_JS_URL=this.constants.IMAGE_JS_URL;
this.IMAGE_PIXI_URL=this.constants.IMAGE_PIXI_URL;
this.IMAGE_GSAP_URL=this.constants.IMAGE_GSAP_URL;
this.createPolyfillForBind();
this.setupRenderer();
this.loadImages();
};
Application.prototype.setupRenderer=function(){
this.stageWidth=window.innerWidth;
this.stageHeight=window.innerHeight;
//this.renderer=PIXI.autoDetectRenderer(this.stageWidth,this.stageHeight);
this.renderer=new PIXI.CanvasRenderer(this.stageWidth,this.stageHeight);
document.body.appendChild(this.renderer.view);
};
Application.prototype.loadImages=function(){
var self=this;
this.loader=new PIXI.loaders.Loader(this.BASE_URL,1,{crossOrigin:''}); // PIXI Loader class [http://pixijs.github.io/docs/PIXI.loaders.Loader.html]
this.loader.add(this.IMAGE_JS_URL); // Loader extends ResourceLoader [http://adireddy.github.io/docs/haxe-pixi/v3/types/pixi/plugins/resourceloader/ResourceLoader.html]
this.loader.add(this.IMAGE_PIXI_URL);
this.loader.add(this.IMAGE_GSAP_URL);
//this.loader.once('complete',function(){self.onImagesLoaded.apply(self);}); // Vanilla JS alternative to jQuery's proxy() method [http://stackoverflow.com/a/4986536]
this.loader.once('complete',this.onImagesLoaded.bind(this)); // bind() polyfill [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Polyfill]
this.loader.load();
};
Application.prototype.onImagesLoaded=function(){
this.setupSprites();
this.initTimeline();
this.initListeners();
this.startTicker();
};
Application.prototype.setupSprites=function(){
this.containerBg=new PIXI.Container();
this.spriteJS=new PIXI.Sprite(PIXI.utils.TextureCache[this.BASE_URL+this.IMAGE_JS_URL]); // TextureCache in action [http://www.html5gamedevs.com/topic/7674-load-textures-synchronously/?p=45836]
this.spritePIXI=new PIXI.Sprite(PIXI.utils.TextureCache[this.BASE_URL+this.IMAGE_PIXI_URL]); // PIXI.TextureCache became PIXI.utils.TextureCache in v3 [http://www.html5gamedevs.com/topic/14144-v3-utilstexturecache-utils-is-not-defined/?p=80524]
this.spriteGSAP=new PIXI.Sprite(PIXI.utils.TextureCache[this.BASE_URL+this.IMAGE_GSAP_URL]);
this.containerBg.addChild(this.spriteJS);
this.containerBg.addChild(this.spritePIXI);
this.containerBg.addChild(this.spriteGSAP);
this.spriteJS.anchor.x=this.spriteJS.anchor.y=this.spritePIXI.anchor.x=this.spritePIXI.anchor.y=this.spriteGSAP.anchor.x=this.spriteGSAP.anchor.y=0;
this.spriteJS.position.x=this.spriteJS.position.y=this.spritePIXI.position.x=this.spriteGSAP.position.x=this.containerBg.position.x=this.containerBg.position.y=0;
this.scaleImage(this.spriteJS);
this.scaleImage(this.spritePIXI);
this.scaleImage(this.spriteGSAP);
this.spritePIXI.alpha=this.spriteGSAP.alpha=0;
this.spriteJS.position.y=this.constants.GUTTER;
this.spritePIXI.position.y=this.spriteJS.height*2+this.constants.GUTTER;
this.spriteGSAP.position.y=this.spriteJS.height+this.spritePIXI.height*2+this.constants.GUTTER;
};
Application.prototype.scaleImage=function(sprite){
//var scale=Math.min(this.stageWidth/sprite.width,this.stageHeight/sprite.height); // resize with aspect ratio [http://community.createjs.com/discussions/createjs/547-resizing-canvas-and-its-content-proportionally-cross-platform#comment_27266530] and [https://opensourcehacker.com/2011/12/01/calculate-aspect-ratio-conserving-resize-for-images-in-javascript/]
var scale=this.stageWidth/sprite.width;
sprite.scale.x=sprite.scale.y=scale;
};
Application.prototype.initTimeline=function(){
this.timeline=new Timeline();
this.timeline.init(this.containerBg,this.spriteJS,this.spritePIXI,this.spriteGSAP,this.stageWidth,this.stageHeight);
};
Application.prototype.initListeners=function(){
var self=this;
//this.listeners=new Listeners();
//this.constants.setListenersObject(this.listeners);
//this.listeners.init();
this.listeners=Listeners.getInstance();
this.listeners.addListeners();
document.addEventListener(this.constants.SCROLLED,this.onScroll.bind(this),false);
document.addEventListener(this.constants.STARTED_DRAG,this.onStartDrag.bind(this),false);
document.addEventListener(this.constants.DRAGGED,this.onDrag.bind(this),false);
document.addEventListener(this.constants.END_DRAG,this.onEndDrag.bind(this),false);
};
Application.prototype.onScroll=function(e){ this.timeline.onScroll(e); };
Application.prototype.onStartDrag=function(e){ this.timeline.onStartDrag(e); };
Application.prototype.onDrag=function(e){ this.timeline.onDrag(e); };
Application.prototype.onEndDrag=function(e){ this.timeline.onEndDrag(e); };
Application.prototype.startTicker=function(){
var self=this;
//TweenLite.ticker.addEventListener('tick',function(){self.render.apply(self);},false); // Vanilla JS alternative to jQuery's proxy() method [http://stackoverflow.com/a/4986536]
TweenLite.ticker.addEventListener('tick',this.render.bind(this),false);
};
Application.prototype.render=function(){this.renderer.render(this.containerBg);};
Application.prototype.createPolyfillForBind=function(){ // [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Polyfill]
if(!Function.prototype.bind){
Function.prototype.bind=function(oThis){
if(typeof this!=='function'){
// closest thing possible to the ECMAScript 5
// internal IsCallable function
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var aArgs=Array.prototype.slice.call(arguments,1),
fToBind=this,
fNOP=function(){},
fBound=function(){
return fToBind.apply(this instanceof fNOP
?this
:oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype=this.prototype;
fBound.prototype=new fNOP();
return fBound;
};
}
};
//
var app=new Application();
app.init();
P.S. I have also heavily experimented with design patterns in this same example, mainly Prototype and Singleton patterns. I am also looking forward to comments on them as well from the community.
T
I have been playing a bit with gskinner.com's EaselJS library (http://easeljs.com/, http://easeljs.com/examples/game/game.html), which makes dealing with HTML5's canvas a lot easier.
So I'm trying to remake something like Space Invaders in the canvas. So far it's not much, just the payer moving left to right. See the progress here: http://jansensan.net/experiments/easeljs-space-invader/
For the invaders, I needed an animation, so I followed a tutorial on how to do so: http://www.youtube.com/watch?v=HaJ615V6qLk
Now that is all good and dandy, however I follow gskinner.com's way of creating "classes": http://easeljs.com/examples/game/Ship.js I'm not certain if I can call that a class, but it is used as such.
So below is the class that I wrote for the Invader, however it seems like the BitmapSequence does not seem to be added to EaselJS's stage. Anyone can guide me through this? Thanks!
// REFERENCES
/*
http://easeljs.com/examples/game/Ship.js
*/
// CLASS
(function(window)
{
function Invader()
{
this.initialize();
}
var p = Invader.prototype = new Container();
// CONSTANTS
// VARS
p.image;
p.bitmapSequence;
// CONSTRUCTOR
p.Container_initialize = p.initialize; //unique to avoid overiding base class
p.initialize = function()
{
this.Container_initialize();
this.image = new Image();
this.image.onload = p.imageLoadHandler;
this.image.onerror = p.imageErrorHandler;
this.image.src = "assets/images/invader-spritesheet.png";
}
p.imageLoadHandler = function()
{
var frameData = {
anim:[0, 1, "anim"]
}
var spriteSheet = new SpriteSheet(p.image, 22, 16, frameData);
p.bitmapSequence = new BitmapSequence(spriteSheet);
p.bitmapSequence.regX = p.bitmapSequence.spriteSheet.frameWidth * 0.5;
p.bitmapSequence.regY = p.bitmapSequence.spriteSheet.frameHeight * 0.5;
p.bitmapSequence.gotoAndStop("anim");
p.addChild(p.bitmapSequence);
}
p.imageErrorHandler = function()
{
console.log("Error: the url assets/images/invader-spritesheet.png could not be loaded.");
}
window.Invader = Invader;
}(window));
Does you p.image/this.Container_initalize actually exist at that point? As you switch between using this. and p. between your init and other functions, while they might seem to be the same practice has often taught me its not the case. Try changing your init function to this:
p.initialize = function()
{
p.Container_initialize();
p.image = new Image();
p.image.onload = p.imageLoadHandler;
p.image.onerror = p.imageErrorHandler;
p.image.src = "assets/images/invader-spritesheet.png";
}