I would like to use TypeScript with ImpactJs

Topics: General
Dec 3, 2012 at 1:36 PM

 

1 ) The problem is that ImpactJs uses a customized version of John Resig inheritance. 

I have no idea how i could derive my own typescript classes from ImpactJs core classes.

2) other point would be the module management from Impact...but that is acceptable in that form.

The problem is that i cannot define a typescript module inside a function...

 

Has anyone had similar problems with other javascript frameworks? 

Any advice?

 

Thank you.

Dec 3, 2012 at 1:46 PM

That would be a right ball-ache to try and get impact working with TS.

Quite frankly you'd be much better off just re-writing the impact functions in native TS yourself. It's not like there are that many of them, it wouldn't take too long.

Dec 3, 2012 at 1:52 PM
Edited Dec 3, 2012 at 1:57 PM

I would have to merge future updates of the framework into my Typescript code...

Anyway, it's an option to rewrite it all...
I felt it were simpler to create a declaration file for it. Translating it into TypeScript may bring hard to spot scope bugs...


Dec 3, 2012 at 1:58 PM

You'd have to do that anyway really as there's no "fits in neatly" solution.

Besides the more you start hacking around with impact the sooner you'll realise there isn't all that much in there anyway. What is in there is great and works well, don't get me wrong, but it wouldn't be a massive task to port over at all - just check if you're allowed to re: license.

Dec 3, 2012 at 2:04 PM
You seem to have tried impactjs for yourself.
Am i asking too much to recommend me a better game framework :) even commercial...
I've chosen ImpactJs because there is a tool that would translate the games for iOS (painless they say :) )




On Mon, Dec 3, 2012 at 3:58 PM, photonstorm <notifications@codeplex.com> wrote:

From: photonstorm

You'd have to do that anyway really as there's no "fits in neatly" solution.

Besides the more you start hacking around with impact the sooner you'll realise there isn't all that much in there anyway. What is in there is great and works well, don't get me wrong, but it wouldn't be a massive task to port over at all - just check if you're allowed to re: license.

Read the full discussion online.

To add a post to this discussion, reply to this email (typescript@discussions.codeplex.com)

To start a new discussion for this project, email typescript@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe on CodePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at CodePlex.com


Dec 4, 2012 at 2:10 PM
Edited Dec 4, 2012 at 2:12 PM

I haven't ever used ImpactJS but I did just watch the tutorial video and agree that using TypeScript classes to inherit from Impact classes would be difficult at best. What you could do, however, is use interfaces to model the framework and use their style of class definitions versus TypeScripts.  Classes in TypeScript are completely optional and modeling the classes used in ImpactJS is fairly straight forward with a caveat or two.

Below is an example I created in the playground. I defined a minimal set of ImpactJS.d.ts definitions (just enough to implement an example entity), then implemented the example entity from their docs, and finally added an example of creating this entity.  All of this is inline with the ImpactJS docs and should work fine:

// Minimal ImpactJS.d.ts
interface IG_XY {
	x?: number;
	y?: number;
}

interface IG_Entity_Static {
	extend(members:IG_Entity): IG_Entity_Class;
	COLLIDES: {
		NEVER: number;
		LITE: number;
		PASSIVE: number;
		ACTIVE: number;		
		FIXED: number;
	};
	TYPE: {
		NONE: number;
		A: number;
		B: number;
		BOTH: number;
	};
}

interface IG_Entity {
	init(x: number, y: number, settings: any): void;
	parent?(...args:any[]): any;
	
	addAnim?(name: string, frameTime: number, sequence: number[], stop?:bool): void;
	animSheet?: IG_AnimationSheet;
	anims?: any;
	checkAgainst?: number;
	collides?: number;
	currentAnim?: any;
	health?: number;
	size?: IG_XY;
	type?: number;
	update?(): void;
	vel?: IG_XY;
}

interface IG_Entity_Class extends IG_Entity {
	new(x: number, y: number, settings: any): IG_Entity;
}

interface IG_AnimationSheet {
	new (file: string, x: number, y: number): IG_AnimationSheet;
}

interface IG {
	Entity: IG_Entity_Static;
	AnimationSheet: IG_AnimationSheet;
	input: {
		pressed(action: string): bool;
	};
}
declare var ig: IG;

// Define a new entity
var EntityPlayer = ig.Entity.extend({

    // Set some of the properties
    collides: ig.Entity.COLLIDES.ACTIVE,
    type: ig.Entity.TYPE.A,
    checkAgainst: ig.Entity.TYPE.B,

    size: {x: 16, y: 16},
    health: 50,
    
    // Load an animation sheet
    animSheet: new ig.AnimationSheet( 'media/player.png', 16, 16 ),
    
    init: function( x, y, settings ) {
		var _this = <IG_Entity>this;

        // Add animations for the animation sheet
        _this.addAnim( 'idle', 0.1, [0,1,2] );
        _this.addAnim( 'jump', 0.1, [3,4,5] );
        
        // Call the parent constructor
        _this.parent( x, y, settings );
    },
    
    update: function() {
		var _this = <IG_Entity>this;

        // This method is called for every frame on each entity.
        // React to input, or compute the entity's AI here.
        
        if( ig.input.pressed('jump') ) {
            _this.vel.y = -100;
            _this.currentAnim = _this.anims.jump.rewind();
        }
        
        // Call the parent update() method to move the entity
        // according to its physics
        _this.parent(); 
    }
});

// Create instance of entity
var player = new EntityPlayer(0, 0, {});

If you plunk that into the playground you'll see that you get pretty rich intelisense throughout the sample.  The biggest deviation I had to make from the entity example in the docs is I needed to cast "this" to a new strongly typed "_this" variable in each of the implemented methods.  That's because TypeScript thinks the 'this' pointer is an <any> so you don't get any intelisense without a cast (which I think is actually a bug.)

The two other places where intelisense breaks down is; 1) with the _this.parent() method as this is a magic method added to the 'this' pointer of each invocation by the framework, and 2) with the _this.anims property which is a dynamic map of Animation objects.  You can in fact model that through an interface definition like "anims?: { [x:string]: IG_Animation; }" which says anims is a map of IG_Animation objects but then you would need to access this map using "_this.currentAnim = _this.anims['jump'].rewind();" which isn't horrible.

Hope that helps...

-steve    

Dec 4, 2012 at 2:21 PM
Edited Dec 4, 2012 at 2:30 PM

Thank you very much steve, eventually i thought creating something similar too.

I will continue using your suggestion.
Just i wouldn't use _this for fear of clashing with typescript own generated _this...

Dec 4, 2012 at 2:40 PM

Sure... You're probably not going to want to do anything that would cause TypeScript to generate an _this (like a lambda or something) as you would lose intelisense in doing so.  But you could easily use something else like _self or _entity if you'd like. 

Dec 10, 2012 at 10:02 AM
Edited Dec 10, 2012 at 10:12 AM

to ickman.

Thank you again for your example. It got me started on the right track, and showed me some features i did not know about typescript:

 

a) I can define a "new" constructor method on interfaces

  interface IG_Entity_Static{  new(x,y,settings) : IG_Entity }

b) the "new" call on interface is not allowed, but one can define a property with interface type, and call new on the property:

  new ig.Entity() where ig  has Entity : IG_Entity_Static

This is very cool.

 

I have a big problem with the ImpactJs' own module pattern implementation.

ig.module('moduleName').references(...).defines( function(){ code });

TypeScript does not allow defining modules inside functions, and typescript module code actually executes a call, which implies that all dependent modules must already be initialized.

I modified the typescript compiler to generate this plumbing code, that is wrap the module javascript in an ig.module call, and i am now testing if the source maps are correct. My changes are as following:

If there is a variable named ImpactJs defined inside the module, it must be initialized with an anonymous object like:

var impactJs = { moduleName: 'xxx', references : ['r1','r2'] };

I evaluate the initialization and wrap the moduleDeclaration at emit time with the correct ig.module calls.

I don't know if there is an alternative other that not using typescript modules at all...