Warcraft2 by Feng.Chun | JavaScriptSource

Warcraft2 by Feng.Chun

Feng.Chun Apr 15, 2012

Abstract

A warcraft game demo was written with JSGF(JavaScript Game Framework).

Description

Study JSGF Courses from this website: http://jsdk2.sourceforge.net

Code Snippet

/**  * @project JSDK JavaScript Development Kit http://jsdk2.sourceforge.net  * @copyright Copyright(c) 2004-2012, Dragonfly.org. All rights reserved.  * @license LGPLv3  * @author fengchun  */ var L = js.Lang, 	D = js.Dom, 	$ = js.Dom.$, 	E = js.util.Event, 	MT = js.math.MathTool, 	G2D = js.math.Geom2D, 	F = js.phys.Formulas;	 L.namespace('js.game.demo.warcraft2');  var GAME = { 	MAP1:[ 		['320,672','320,672','128,704','320,672','128,704','128,704','128,704','320,672' 		 ,'128,704','128,704','128,704','128,704','320,672','128,704','128,704','128,704'] 		,['320,672','320,672','128,704','320,672','128,704','320,672','320,672','320,672' 		 ,'128,704','320,672','320,672','320,672','320,672','128,704','320,672','320,672'] 		,['320,672','320,672','128,704','320,672','128,704','128,704','128,704','320,672' 		 ,'128,704','320,672','128,704','128,704','320,672','128,704','128,704','128,704'] 		,['128,704','320,672','128,704','320,672','320,672','320,672','128,704','320,672' 		 ,'128,704','320,672','320,672','128,704','320,672','128,704','320,672','320,672'] 		,['320,672','128,704','320,672','320,672','128,704','128,704','128,704','320,672' 		 ,'128,704','128,704','128,704','128,704','320,672','128,704','320,672','320,672'] 		,['320,672','320,672','320,672','320,672','320,672','320,672','320,672','320,672' 		 ,'320,672','320,672','320,672','320,672','320,672','320,672','320,672','320,672'] 		,['320,672','320,672','320,672','320,672','320,672','320,672','320,672','320,672' 		 ,'320,672','320,672','320,672','320,672','320,672','320,672','320,672','320,672'] 		,['320,672','320,672','320,672','320,672','320,672','320,672','320,672','320,672' 		 ,'320,672','320,672','320,672','320,672','320,672','320,672','320,672','320,672'] 		,['32,576','32,576','32,576','0,544','320,672','320,672','320,672','96,704' 		  ,'320,672','320,672','320,672','320,672','320,672','320,672','320,672','320,672'] 		,['64,448','64,448','32,416','32,544','320,672','320,672','320,672','320,672' 		  ,'32,704','256,192','64,256','64,256','64,256','64,256','64,256','352,192'] 		,['416,384','416,384','320,384','96,544','320,672','320,672','320,672','320,672' 		  ,'320,672','0,256','384,192','384,192','384,192','384,192','384,192','128,224'] 		,['416,512','416,512','416,512','288,512','320,672','320,672','320,672','320,672' 		 ,'320,672','192,192','192,256','480,224','448,192','480,224','192,256','352,224'] 		,['320,672','320,672','320,672','288,544','32,576','32,576','0,544','320,672' 		  ,'320,672','320,672','320,672','320,672','320,672','320,672','320,672','320,672'] 		,['320,672','320,672','416,672','416,544','256,416','0,416','64,544','320,672' 		 ,'320,672','320,672','320,672','320,672','320,672','320,672','320,672','320,672'] 		,['320,672','320,672','320,672','416,544','416,416','96,416','32,544','320,672' 		 ,'320,672','320,672','320,672','320,672','320,672','320,672','320,672','320,672'] 		,['320,672','320,672','320,672','416,544','384,416','96,416','64,544','320,672' 		 ,'320,672','320,672','320,672','320,672','320,672','320,672','320,672','320,672']								 	] 	,UNPASS_TILES:[ 		'64,448','32,416','256,192','64,256','352,192' 		,'416,384','320,384','0,256','384,192','128,224' 		,'192,192','192,256','480,224','448,192','480,224','352,224' 		,'256,416','0,416','416,416','96,416','384,416' 	] }  js.game.demo.warcraft2.Warrior = function(config){ 	this.side = config['side']; 	this.hp = config['hp']; 	this.MAX_HP = config['MAX_HP']; 	this.controlable = config['controlable']||false; 	this.walkTo = null;	 	js.game.demo.warcraft2.Warrior.superclass.constructor.apply(this, arguments); 	 	this.setState(config['state']||'stand'); 	this.setAABB('space',{x:14,y:14,w:44,h:44}); 	this.setAABB('body',{x:27,y:27,w:18,h:18}); };  L.extend(js.game.demo.warcraft2.Warrior, js.game.Sprite, { 	setState: function(state){ 		this.state = state; 		this._setFrameKey(); 	}, 	autoZ: function(){ 		this._setFrameKey(); 		var line = [G2D.movePoint([0,0],MT.RADIAN_6,10),[0,0]]; 		d = G2D.getLDOfPointAndLine(this.getXY(), line); 		this.setZ(Math.floor(d/10)); 	}, 	startFighting: function(){ 		if(this.state=='walk') this.stopWalkTo(); 		this.setState('fight');		 	}, 	stopFighting: function(){ 		if(this.state=='walk') this.stopWalkTo(); 		this.setKillTarget(null); 		this.setState('stand'); 		this.hiddenHP(); 	}, 	setKillTarget: function(target){this._killTarget = target;}, 	getKillTarget: function(){return this._killTarget;}, 	autoKillTarget: function(){ 		if(!this._killTarget) return; 		if(this._killTarget.state=='die') { 			this.stopFighting(); 			return; 		} 		this.turn(MT.calcRadian(this._killTarget.getXY(),this.getXY())); 		if(this.collidesWithKiller()){ 			this.startFighting(); 		}else{ 			this.setWalkTo(this._killTarget.getXY()); 		} 	}, 	beHit: function(him, canvas){ 		if(!this.controlable) this.setKillTarget(him);//Computer's counterattack 		this.hp-= 5; 		if (this.hp <= 0) { 			this.state = 'die'; 			this.destory(canvas); 			him.stopFighting(); 		}else{ 			this.showHP(); 		} 	}, 	collidesWithKiller: function(){ 		var killTarget = this.getKillTarget(); 		if(!killTarget) return false; 		return this.getAABB('space').collidesWith(killTarget.getAABB('space')); 	},	 	init: function(game){ 		this.autoZ();		 		var canvas = game.getCanvas(); 		this.paint(canvas); 		 		if(this.controlable){ 			this._initSelect(canvas); 			game.onMouseLeftClick(this.getId(), 'down', function(e){ 				if(this.state!='die') game.selectPlayer(this);	 				E.stopEvent(e); 			}, this, true); 			game.onMouseRightClick(this.getId(), 'down', function(e){ 				this.unselect(); 			}, this, true); 		}else{ 			var me = this, players = null; 			D.setCursorStyle(this.getId(), game.getCursorStyle('attackable')); 			game.onMouseRightClick(this.getId(), 'down', function(e){ 				players = this.getPlayers(); 				players.forEach(function(player){ 					if(player.isSelected()) player.setKillTarget(me); 				});				 			}); 		} 		 		this._initHP(canvas); 		game.onMouseMove(this.getId(), 'enter', function(e){ 			this.showHP();	 		}, this, true); 		game.onMouseMove(this.getId(), 'leave', function(e){ 			this.hiddenHP();	 		}, this, true); 		 		this.subscribe('painting', function(){ 			this.updateHP(); 			this.updateSelect(); 		}) 		this.subscribe('moving', function(){ 			this.autoZ(); 		}) 		this.subscribe('moved', function(){			 			if(this.getAABB('body').avoidToTiles(game.getMapLayer(), GAME.UNPASS_TILES) ||  			   this.getAABB('space').limitIn(canvas.getBound())) { 				this.stopWalkTo();		 			}else if(this.collidesWithKiller()) { 				this.startFighting(); 			}else { 				var sprites = game.getSprites(); 				sprites.forEach(function(sp){ 					if(sp.getId()!=this.getId() && this.getAABB('body').avoidTo(sp.getAABB('body'))){ 						this.stopWalkTo(); 					} 				},this); 			}			 		}); 		this.subscribe('destoryed', function(){ 			if(this.controlable) game.playSound('dead'); 			game.rmWarrior(this); 			canvas.erase([this.getId()+'_hpc',this.getId()+'_hp',this.getId()+'_select']); 			var anim = new js.anim.Film({ 				canvas: canvas, src: this.getImageSrc(), interval:300 				, width: 72, height: 72, frameSeq: this.getFrameSeq('die'+Math.floor(this.getDir()/MT.RADIAN_2)) 			}); 			anim.setPosition([this.getX(),this.getY(),this.getZ()],this.getId()+'_die'); 			anim.subscribe('completed', function(){ 				canvas.erase(this.getId()+'_die'); 			});	 			anim.start(); 		}) 	}, 	_setFrameKey: function(){ 		var dir = this.getDir(), num = Math.floor(dir/MT.RADIAN_2);		 		this.setFrameSeqKey(this.state + num); 	}, 	_getSelectX: function(){return this.getX()+14;}, 	_getSelectY: function(){return this.getY()+10;},	 	_getHPY: function(){return this.getY()-5;},	 	_initHP: function(canvas){ 		var el1 = D.createEl('div', {id:this.getId()+'_hpc'}, { 			position:'absolute',border:'1px solid white',visible:false 			,x:this._getSelectX(),y:this._getHPY(),z:this.getZ()+1,width:40,height:5 		}), el2 = D.createEl('div', {id:this.getId()+'_hp'}, { 			backgroundColor:'green',width:40*this.hp/this.MAX_HP,height:5 		}) 		el1.appendChild(el2); 		canvas.appendElement(el1); 	}, 	showHP: function(){		 		D.updateEl(this.getId()+'_hpc', null, {visible:true, x:this._getSelectX(),y:this._getHPY(),z:this.getZ()+1}); 		D.updateEl(this.getId()+'_hp', null, {width:40*this.hp/this.MAX_HP}); 	}, 	updateHP: function(){		 		D.updateEl(this.getId()+'_hpc', null, {x:this._getSelectX(),y:this._getHPY(),z:this.getZ()+1}); 		D.updateEl(this.getId()+'_hp', null, {width:40*this.hp/this.MAX_HP}); 	}, 	hiddenHP: function(){ 		D.updateEl(this.getId()+'_hpc', null, {visible:false}); 	}, 	_initSelect: function(canvas){ 		var el = D.createEl('div', {id:this.getId()+'_select'}, { 			position:'absolute',border:'2px solid green',visible:false 			,x:this._getSelectX(),y:this._getSelectY(),z:this.getZ()-1,width:40,height:40 		}) 		canvas.appendElement(el); 	}, 	isSelected: function(){ 		if(!this.controlable) return false; 		return D.getStyle(this.getId()+'_select', 'visibility')=='visible'; 	}, 	select: function(){ 		if(this.controlable) D.updateEl(this.getId()+'_select', null, {visible:true,x:this._getSelectX(),y:this._getSelectY(),z:this.getZ()-1}); 	}, 	updateSelect: function(){ 		if(this.controlable) D.updateEl(this.getId()+'_select', null, {x:this._getSelectX(),y:this._getSelectY(),z:this.getZ()-1});	 	}, 	unselect: function(){ 		if(this.controlable) D.updateEl(this.getId()+'_select', null, {visible:false}); 	}, 	isReach: function(){ 		var rst = G2D.isPointOnSegment(this.walkTo['to'], [this.walkTo['from'], this.getXY()]); 		 		if(rst) this.stopWalkTo(); 		return rst; 	}, 	stopWalkTo: function(){ 		this.setState('stand'); 		this.walkTo = null; 	}, 	setWalkTo: function(to){		 		var bound = this.getBound(); 		this.setMovable(true); 		this.turn(MT.calcRadian(to, G2D.getRectCenter(bound))); 		this.setState('walk'); 		this.walkTo = {'from':this.getXY(),'to':[to[0]-0.5*bound.w,to[1]-0.5*bound.h]}; 	} });  js.game.demo.warcraft2.Game = function(config){ 	this._players = []; 	this._computers = []; 	js.game.demo.warcraft2.Game.superclass.constructor.apply(this, arguments); 	 	this._greenCross = new js.anim.Film({ 		canvas: this.getCanvas(), src: '../../images/warcraft2/green_cross.png', interval:100 		, width: 32, height: 32, frameSeq: [[0,96],[0,64],[0,32],[0,0]]}); 	this._redCross = new js.anim.Film({ 		canvas: this.getCanvas(), src: '../../images/warcraft2/red_cross.png', interval:100 		, width: 32, height: 32, frameSeq: [[0,96],[0,64],[0,32],[0,0]]}); 	this._map = new js.game.TiledLayer({x:0,y:0,z:0,src:'../../images/warcraft2/wasteland.png' 		,cell_size:[32,32]}); };  L.extend(js.game.demo.warcraft2.Game, js.game.Game, { 	_newWarrior: function(config){ 		var warrior = new js.game.demo.warcraft2.Warrior({ 			side:config['side'],hp:config['MAX_HP'],MAX_HP:config['MAX_HP'],controlable:config['controlable'] 		    ,imageSrc:'../../images/warcraft2/'+config['side']+'/'+config['name']+'.png' 		    ,x:config['x'],y:config['y'],dir:L.random(0, 2*Math.PI, true),width:72,height:72 		    ,frameSeqs:{ 		    	stand6:[[0,0]] 		        ,stand7:[[72,0]] 		        ,stand0:[[144,0]] 		        ,stand1:[[216,0]] 		        ,stand2:[[288,0]] 		        ,stand3:[[360,0]] 		        ,stand4:[[432,0]] 		        ,stand5:[[504,0]] 				 		    	,walk6:[[0,0],[0,72],[0,144],[0,216],[0,288]] 		        ,walk7:[[72,0],[72,72],[72,144],[72,216],[72,288]] 		        ,walk0:[[144,0],[144,72],[144,144],[144,216],[144,288]] 		        ,walk1:[[216,0],[216,72],[216,144],[216,216],[216,288]] 		        ,walk2:[[288,0],[288,72],[288,144],[288,216],[288,288]] 		        ,walk3:[[360,0],[360,72],[360,144],[360,216],[360,288]] 		        ,walk4:[[432,0],[432,72],[432,144],[432,216],[432,288]] 		        ,walk5:[[504,0],[504,72],[504,144],[504,216],[504,288]] 				 		        ,fight6:[[0,360],[0,432],[0,504],[0,576]] 		        ,fight7:[[72,360],[72,432],[72,504],[72,576]] 		        ,fight0:[[144,360],[144,432],[144,504],[144,576]] 	            ,fight1:[[216,360],[216,432],[216,504],[216,576]] 		        ,fight2:[[288,360],[288,432],[288,504],[288,576]] 				,fight3:[[360,360],[360,432],[360,504],[360,576]] 				,fight4:[[432,360],[432,432],[432,504],[432,576]] 				,fight5:[[504,360],[504,432],[504,504],[504,576]] 				 				,die6:[[0,648],[0,720],[0,792]] 				,die7:[[72,648],[72,720],[72,792]] 				,die0:[[144,648],[144,720],[144,792]] 				,die1:[[216,648],[216,720],[216,792]] 				,die2:[[288,648],[288,720],[288,792]] 				,die3:[[360,648],[360,720],[360,792]] 				,die4:[[432,648],[432,720],[432,792]] 				,die5:[[504,648],[504,720],[504,792]] 		    } 		}); 		 		warrior.init(this); 		var arr = config['controlable']?this._players:this._computers; 		arr.push(warrior); 	}, 	newPlayers: function(xys){ 		xys.forEach(function(xy){this._newWarrior({side:'orc',name:'axethrower',MAX_HP:500,x:xy[0],y:xy[1],controlable:true});},this);		 	}, 	newComputers: function(xys){ 		xys.forEach(function(xy){this._newWarrior({side:'human',name:'footman',MAX_HP:100,x:xy[0],y:xy[1],controlable:false});},this);		 	}, 	rmWarrior: function(warrior){ 		var arr = warrior.controlable?this._players:this._computers; 		arr.remove(warrior, function(a, b){return a.getId()==b.getId();}); 	}, 	getSprites: function(){return this._players.clone().concat(this._computers);}, 	getPlayers: function(id){return this._players;}, 	loadMap: function(d){ 		this._map.setData(d); 		this._map.paint(this.getCanvas());				 	}, 	getMapLayer: function(){return this._map;}, 	getCursorStyle: function(name){ 		switch (name) { 		case 'unmovable': 			return '../../images/warcraft2/orc/cursor2.cur';	 		case 'attackable': 			return '../../images/warcraft2/orc/cursor3.cur'; 		default: 			return '../../images/warcraft2/orc/cursor1.cur';			 		} 	}, 	init: function(){ 		var canvas = this.getCanvas(), me = this;		 		D.setCursorStyle(canvas.getConfig('id'), this.getCursorStyle('default')); 		this._map.subscribe('painted', function(eType, args){ 			var cell = args[0], value = args[1]; 			if(GAME.UNPASS_TILES.contains(value)) D.setCursorStyle(cell, me.getCursorStyle('unmovable')); 		}) 		this.loadMap(GAME.MAP1); 		 		this.onKeyHold({ctrl:true}); 		this.onMouseLeftClick(canvas.getConfig('id'), 'down', function(e){ 			this._players.forEach(function(player){ 				player.unselect(); 			}); 		});	 		this.onMouseRightClick(canvas.getConfig('id'), 'down', function(e){ 			if(this._players.length<=0) return; 			var canvasXY = canvas.getXY(), hasMoved = null 			, to = MT.translateCCS(E.getXY(e), [-1*canvasXY[0], -1*canvasXY[1]]);					 			 			this._players.forEach(function(player){ 				if(player.isSelected()){ 					player.setWalkTo(to); 					hasMoved = player; 				} 			}); 			if(hasMoved){ 				var noAnim = false; 				this._computers.forEach(function(sp){ 					if(G2D.isPointInRect(to, sp.getAABB('space').getBoundingBox())) noAnim = true; 				}); 				 				if(!noAnim) { 					hasMoved.setKillTarget(null);hasMoved.hiddenHP();this.playSound('move'); 					var cellValue = this._map.getCellByXY(to[0],to[1]) 					, anim = GAME.UNPASS_TILES.contains(cellValue)?this._redCross:this._greenCross; 					anim.setPosition([to[0]-16,to[1]-16,3],'move_cross');		 					anim.start();//play animation 				}									 			} 		});	 		this.subscribe('ended', function(){ 			this.getCanvas().clear();			 		}); 		 		//defined all sounds 		var SP = js.media.SoundPlayer; 		SP.on('ready',  			function(){ 				if(SP.isOK()){ 					SP.createSounds([ 		         		{id:'select1',url:'../../images/warcraft2/orc/1.mp3'}, 		         		{id:'select2',url:'../../images/warcraft2/orc/2.mp3'}, 		         		{id:'select3',url:'../../images/warcraft2/orc/3.mp3'}, 		         		{id:'select4',url:'../../images/warcraft2/orc/4.mp3'}, 		         		{id:'select5',url:'../../images/warcraft2/orc/5.mp3'}, 		         		{id:'select6',url:'../../images/warcraft2/orc/6.mp3'}, 		        		{id:'dead',url:'../../images/warcraft2/orc/dead.mp3'}, 		        		{id:'move',url:'../../images/warcraft2/orc/move.mp3'} 					]); 					this._soundOK = true; 				}			 			},null,this); 				 		this.newPlayers([[20,350],[20,400],[20,450]]); 		this.newComputers([[150,250],[150,300],[200,250],[200,300] 		,[300,400],[350,400],[400,400],[300,450],[350,450],[400,450] 		,[300,150],[350,150],[400,150],[300,200],[350,200],[400,200]]); 	}, 	selectPlayer: function(player){		 	    if(!this.isKeyHold(js.input.KEY.CONTROL)) { 			this._players.forEach(function(player){if(player.isSelected()) player.unselect();}); 		} 	    this.playSound('select'); 		player.select(); 	}, 	run: function(){ 		this.getSprites().forEach(function(warrior){ 			if(warrior.state=='walk'){ 				if(!warrior.isReach()) warrior.moveWith(2); 			}else if(warrior.state=='fight') warrior.getKillTarget().beHit(warrior, this.getCanvas()); 			 			if(!warrior.controlable) warrior.autoKillTarget(); 			 			warrior.nextFrame(); 			warrior.paint(this.getCanvas()); 		}, this) 	}, 	playSound: function(id){ 		if(!this._soundOK) return; 		js.media.SoundPlayer.play(id=='select'?(id+L.randomEnum([1,2,3,4,5,6])):id); 	} });  js.game.demo.warcraft2.GameApp = function(){ 	var game = null; 	return { 		main: function(btn){ 			if(game) return; 			var height = 512, y = D.getY(btn) - height;				 			game = new js.game.demo.warcraft2.Game({ 				id:'warcraft2',x:300,y:y,background:'black',width:512,height:height,fpsMax:12 			}); 			game.watchFPS(true);	 			 			js.lang.Loader.loadImage( 				[ 				 '../../images/warcraft2/green_cross.png', 				 '../../images/warcraft2/red_cross.png', 				 '../../images/warcraft2/orc/axethrower.png', 				 '../../images/warcraft2/human/footman.png', 				 '../../images/warcraft2/wasteland.png' 				 ], 				{fn: function(imgObj, len, index){if(index>=4) {game.init();game.start();}}}, 				{fn: function(){alert('Resource-loading failed.\nPress "F5" refresh this page.');}} 			); 		}, 		end: function(){ 			if(!game) return; 			game.end(); 		} 	} }();

Download

Download

Leave a Response

(4 comments)

download button does this error: The requested URL /content/one/FAILED was not found on this server.

pedro Jul 27, 2012

The download button is not working for me

everpwning May 15, 2012

i like it

tshewang dorji May 15, 2012

i like it

tshewang dorji May 15, 2012