Impact

This forum is read only and just serves as an archive. If you have any questions, please post them on github.com/phoboslab/impact

1 decade ago by quidmonkey

Okay, this is a bit of a doozy. My thanks ahead of time for looking into this.

I'm trying to extend the Font class to pop-up various notifications to the player, which will then fade after a few seconds. Here's what I got so far:

ig.module(
	'impact.chain-notification'
)
.requires(
	'impact.font'
)
.defines(function(){

ChainNotification = ig.Font.extend({

	font: null,
	text: '',
	pos: { x: null, y: null },
	_kill: null,
	vel: { x: 0, y: -10 },
        
	lifetime: 5,
	fadetime: 1,
        
        init: function( text, x, y ) {
            
		this.font = new ig.Font( 'media/04b03.font.png' );
		this.text = text;
		this._kill = false;
                
		this.pos.x = x;
		this.pos.y = y;
		
		this.idleTimer = new ig.Timer();
	},
	
	
	update: function() {
		
		//if greater than lifetime, kill note
		if( this.idleTimer.delta() > this.lifetime ) {
			this._kill = true;
			return;
		}
                
		//slowly dissipate
		this.currentAnim.alpha = this.idleTimer.delta().map(
			this.lifetime - this.fadetime, this.lifetime, 1, 0 );
		
		//update position
		this.pos.x += this.vel.x;
		this.pos.y += this.vel.y;
		
	},
	
	draw: function() {
		this.font.draw( this.text, this.pos.x, this.pos.y, ig.Font.ALIGN.LEFT );
	}
    
});

});

The chain-notification.js file is placed in the /game/impact/ directory. I want to be able to instantiate these notifications whenever I want, so I've modded my main.js accordingly:

ig.module( 
	'game.main' 
)
.requires(
	'impact.game',
	'impact.font',
	//other stuff
)
.defines(function(){

MyGame = ig.Game.extend({
	
	notes: [],	//my notifications array

	//code

	update: function() {
		// Update all entities and backgroundMaps
		this.parent();
		
		if( this.notes.length ) {
			for( i = this.notes.length; i--; i ) {
				this.notes[i].update();
				
				//if note is dead, erase it
				if( this.notes[i]._kill ) {
					this.notes.splice(i, 1);
				}
			}
		}
	},

	draw: function() {
		//other code
		//draw notes
		if( this.notes.length ){
			for(var note in this.notes) {
				this.notes[note].draw();
			}
		}
		
	}

};

ig.main( '#canvas', MyGame, 60, 528, 576, 1 );

//create note
ig.main.spawnNote = function( text, x, y) {
	var note = new ChainNotification( text, x, y );
	MyGame.notes.push( note );
};

});

When I try to call ig.main.spawnNote() from any Entity class, I get this:
Uncaught TypeError: Object [object Object] has no method 'spawnNote'
Any ideas on what's broken?

1 decade ago by paularmstrong

either move spawnNote into the main declaration of MyGame

MyGame = ig.Game.extend({

    notes: [],

    // all the other stuff

    spawnNote: function (text, x, y) {
        // snip
    }
});

or it should be

ig.main.prototype.spawnNote = function (text, x, y) { //...

1 decade ago by quidmonkey

Thx. If I do those, how do I reference spawnNote then? ig.game.spawnNote()?

1 decade ago by paularmstrong

Yep!

[edit]
Forgot to mention, MyGame.notes.push(note); should be this.notes.push(note);

1 decade ago by quidmonkey

Cool. So I did your first suggestion, and it works! But now I'm getting this:
Uncaught ReferenceError: ChainNotification is not defined
EDIT:

Be aware I placed my chain-notification.js in the game/impact/ directory - is that right?

1 decade ago by quidmonkey

Thx to the IRC I got this figured out!

For posterity, we made the following changes:

1) main.js requires impact.chain-notification.js

2) Change main.js draw():

draw: function() {
        //other code
        //draw notes
        if( this.notes.length ){
            for(var i = 0; i < this.notes.length; i++) {
                this.notes[i].draw();
            }
        }
        
    }

3) Give chain-notification.js its on .alpha property and change draw():

draw: function() {
		
		//set system alpha for fade effect
		if( this.alpha != 1) {
			ig.system.context.globalAlpha = this.alpha;
		}
		
		this.font.draw( this.text, this.pos.x, this.pos.y, ig.Font.ALIGN.LEFT );
		
		//reset system alpha so fade effect doesn't get applied
		//to other objects being drawn
		if( this.alpha != 1) {
			ig.system.context.globalAlpha = 1;
		}
		
	}

1 decade ago by dominic

You called your module impact.chain-notification, so it should be in a lib/impact/chain-notification.js file. The module name directly corresponds to the directory and file name.

You have to require the chain-notification module in the module in which you want to use it. Since you're using it in your lib/game/main.js, require it there:
ig.module( 
    'game.main' 
)
.requires(
    'impact.game',
    'impact.font',
    'impact.chain-notification', // <- add this
    //other stuff
)
.defines(function(){
…

That said, it has been common practice to let the lib/impact/ directory completely untouched, to allow easier updating to new versions. To honor that, you can put your chain-notification in lib/game/chain-notification.js, call the module game.chain-notification and require it as game.chain-notification as well.

1 decade ago by quidmonkey

So I decided to try and extend this into a proper plugin to share with the community:

ig.module(
	'plugins.notification'
)
.requires(
	'impact.font'
)
.defines(function(){

Notification = ig.Font.extend({
        
	font: null,			//font
	text: '',			//string to draw
	pos: { x: null, y: null },	//position
	_kill: null,			//state
	vel: { x: 0, y: -1 },		//velocity - set to 0 if font doesn't move
	alpha: 1,			//alpha, 0 = translucent, 1 = opaque
        
	lifetime: 1.2,			//how long notification should last
	fadetime: .4,			//how long until note fades
        
        init: function( font, text, x, y ) {
            
                this.font = new ig.Font( font );
		this.text = text;
                this._kill = false;
                
		this.pos.x = x;
		this.pos.y = y;
		
		this.idleTimer = new ig.Timer();
	},
	
	
	update: function() {
		
		//if greater than lifetime, kill note
		if( this.idleTimer.delta() > this.lifetime ) {
			this._kill = true;
			return;
		}
			
		//update position
		this.pos.x += this.vel.x;
		this.pos.y += this.vel.y;
                
		//do fade - slowly dissipate
		this.alpha = this.idleTimer.delta().map(
			this.lifetime - this.fadetime, this.lifetime, 1, 0 );
		
	},
	
	draw: function() {
		
		//set system alpha for fade effect
		if( this.alpha != 1) {
			ig.system.context.globalAlpha = this.alpha;
		}
		
		//draw font
		this.font.draw( this.text, this.pos.x, this.pos.y, ig.Font.ALIGN.LEFT );
		
		//reset system alpha so fade effect doesn't get applied
		//to other objects being drawn
		if( this.alpha != 1) {
			ig.system.context.globalAlpha = 1;
		}
		
	}
    
});

NotificationManager = Notification.extend({
        
	notes: [],
	
	init: function() {},
	
	draw: function() {
		
		for(var i = 0; i < this.notes.length; i++) {
			this.notes[i].draw();
		}
		
	},
	
	spawnNote: function( font, text, x, y) {
		
		var note = new Notification( font, text, x, y );
		this.notes.push( note );
		
	},
	
	update: function() {
		
		//update each note
		for( i = this.notes.length ; i--; i ) {
			this.notes[i].update();
			
			//if note is dead, erase it
			if( this.notes[i]._kill ) {
				this.notes.splice(i, 1);
			}
		}
	}
    
});

});

I create an instance in ig.main (MyGame) called chainNotes. I then create Notifications via ig.game.chainNotes.spawnNote(). Here's where I'm running into an issue: it'll run fine the first note I spawn; but once I create a second one, I get this error:
Uncaught TypeError: Object [object Object] has no method 'update'
At first I thought it was the splice(), but if I comment that out, the same issue persists.

1 decade ago by MikeL

@quidmonkey. Great idea! Thanks for doing that. I've been wanting to use something along the lines of what you've done. I've taken the liberty of making several changes to get it working. Hope you don't mind. Here is the code:

ig.module(
    'plugins.notification-manager'
)
.requires(
    'impact.impact'
)
.defines(function(){

ig.NotificationManager = ig.Class.extend({
        
    notes: [],
    
    init: function() { },
    
    draw: function() {
        
        for(var i = 0; i < this.notes.length; i++) {
            this.notes[i].draw();
        }
        
    },
    
    spawnNote: function( font, text, x, y, settings) {
        
        var note = new Notification( font, text, x, y, settings );
        this.notes.push( note );
        
    },
    
    update: function() {
        
        //update each note
        for( i = this.notes.length ; i--; i ) {
            this.notes[i].update();
            
            //if note is dead, erase it
            if( this.notes[i]._kill ) {
                this.notes.splice(i, 1);
            }
        }
    }
    
});

Notification = ig.Class.extend({
        
    font: null,            //font
    text: '',            //string to draw
    pos: { x: null, y: null },    //position
    _kill: null,            //state
    vel: { x: 0, y: -75 },        //velocity - set to 0 if font doesn't move
    alpha: 1,            //alpha, 0 = translucent, 1 = opaque
        
    lifetime: 1.2,            //how long notification should last
    fadetime: 0.4,            //how long until note fades
        
    init: function( font, text, x, y, settings ) {
        this.font =  font;
        this.text = text;
        this._kill = false;
                
        this.pos.x = x;
        this.pos.y = y;

        ig.merge( this, settings );
        
        this.idleTimer = new ig.Timer();
    },
    
    
    update: function() {
        
        //if greater than lifetime, kill note
        if( this.idleTimer.delta() > this.lifetime ) {
            this._kill = true;
            return;
        }
            
        //update position
        this.pos.x += (this.vel.x * ig.system.tick);
        this.pos.y += (this.vel.y * ig.system.tick);
                
        //do fade - slowly dissipate
        this.alpha = this.idleTimer.delta().map(
            this.lifetime - this.fadetime, this.lifetime, 1, 0 );
        
    },
    
    draw: function() {
        
        //set system alpha for fade effect
        if( this.alpha != 1) {
            ig.system.context.globalAlpha = this.alpha;
        }
        
        //draw font
        this.font.draw( this.text, this.pos.x, this.pos.y, ig.Font.ALIGN.LEFT );
        
        //reset system alpha so fade effect doesn't get applied
        //to other objects being drawn
        if( this.alpha != 1) {
            ig.system.context.globalAlpha = 1;
        }
        
    }
    
});

});

Relevant changes:
1. Changed the plugin name to 'notification-manager' as this best expresses what you are doing. Be sure to change the filename in your plugins directory.
2. NotificationManager is now a generic impact class.
3. Notification is now a generic impact class.
4. When spawning, an existing font is used so there is no need to recreate the font.
5. You can change the settings for Notification when spawning. I've got an example below.
6. Changed the velocity to take into account ig.system.tick so that the velocity will work in a way similar to impact entities.

To intitialize notification manager in main.js:
    this.chainNotes = new ig.NotificationManager();

To spawn (here you can see applying a change in settings if desired):
          this.chainNotes.spawnNote(this.fontLarge, "tester " , x, y, {lifetime: 3, vel: {x: 0, y: 0} });

Note, I already created a font in main.js called fontLarge, so no need to recreate it.
Then in the main.js update and draw functions, I call this.chainNotes update and draw functions respectively.

Hopefully this works for you too. Let me know if you have other questions.

1 decade ago by quidmonkey

Thx! That's perfect.

1 decade ago by stahlmanDesign

Can you guys post a working example of this so we can see what it does?

1 decade ago by quidmonkey

Here's an example: Let's say you're making an RPG and you want to display the damage done to an enemy whenever a player hits the enemy, ethen have the damage done fade away in a second or two. You could easily do this by spawning a new Notification, and setting the lifetime = 1 or 2 (for one or two seconds).

1 decade ago by Hareesun

I think stahlman meant a working demo, as in a very basic interactive demo. :P

1 decade ago by stahlmanDesign

If I have time I'll try to get it working to see if it suits my needs.

In my game I want characters to have thought balloons appear when touched, containing icons of game items they desire, or messages. The icons could use the same code as the messages, but instead of letters, I would use a custom "font" that is made up of my game items.
Page 1 of 1
« first « previous next › last »