最近在做什么?很多兄弟可能想知道,放着Ideas和Ominds不做,blog也不更新,该有很多人在骂了吧。呵呵,其实,我也很迷茫很纠结,是啊,ideas到底该做成什么样?ominds又该如何,半个月以来一直没有停止过思考,完全没有任何想法,总觉的自己已经没有思想了,快死了吗?
还是做了个简单的东西,首先是我的个人简历(点击查看) 这个就不做过多介绍了,毕竟没有什么技术可言,只不过是一时兴起,也可到github上下载哦。。。
好了言归证转,想做点小游戏玩玩(当然不会说是因为缺钱啊),cocos2d-html5,为什么选中这个,其实,我也不知到,可能是最近在学前端吧,不过,想做的是cocosd-android,毕竟在地铁上是件无聊的事情。。。。。
再说这个连锁反应小游戏,不得不吐嘈一下cocos官网,你妹啊,给个入门教程都是过时的,还在那挂着。。。。这个小游戏是国外的一个教程,自己加了点东西,想要把它加工一下,还没有完成,你们懂的,对游戏,我是在是没什么经验,也不怎么玩。。。。。
那么。。。
一、环境搭建
- 开始吧,到官方下载cocos2d-html5包,我下的是v2.2.2,解压,如果你用的是eclipse,那么新建web项目,将cocos2d、extensions、external、lib、template、tools目录直接拷贝到webroot下,如果是nodejs开发(如果不知道如何使用nodejs点击),请将以上目录拷贝到public下。(开始我用的是eclipse+tomcat,不过发现js修改后,总是很不容易加载进去,这让我很伤心,后来又用nodejs+sublime(当然你也可以继续用eclips)
- 我们假设你已经搭建好了一个nodejs的项目,并且已经把cocos2d相关文件放在了public目录下(其实你用eclipse+tomcat,建立web project也是可以的,但是我不知道怎么部署到heroku上,有会的同学在下面留话),修改view/index.ejs文件,全部替换为:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MyTest</title>
</head>
<body style="padding:0; margin: 0 auto; background: #fff;">
<div style="text-align: center; font-size: 0;margin-top:30px;">
<canvas id="gameCanvas" width="600" height="600">
Your browser does not support the canvas tag
</canvas>
</div>
</body>
</html>
<script src="/app/cocos2d.js"></script>
var MW = MW || {};
(function () {
var d = document;
var c = {
COCOS2D_DEBUG:2, //0 to turn debug off, 1 for basic debug, and 2 for full debug
box2d:false,
chipmunk: false,
showFPS:false,
frameRate:60,
tag:'gameCanvas', //the dom element to run cocos2d on
engineDir:'cocos2d/',
appFiles:['app/Resource.js','app/GameConfig.js','app/MenuLayer.js','app/CircleChain.js',
'app/AboutLayer.js','app/GameOver.js'
]
};
window.addEventListener('DOMContentLoaded', function () {
//first load engine file if specified
var s = d.createElement('script');
s.src = 'cocos2d/jsloader.js';
d.body.appendChild(s);
document.ccConfig = c;
s.id = 'cocos2d-html5';
});
})();
看一下代码,其中第一行先不说,tag:'gameCanvas' 这句跟我们的html的div标签id一致,engineDir:'cocos2d/'这句表示我们使用的是cocos2d引擎,appFiles里面加载的是各个文件,等会一一说明。
在public(确实是public目录)目录下新建main.js,内容:
var cocos2dApp = cc.Application.extend({
config:document.ccConfig,
ctor:function (scene) {
this._super();
this.startScene = scene;
cc.COCOS2D_DEBUG = this.config['COCOS2D_DEBUG'];
cc.setup(this.config['tag']);
cc.AppController.shareAppController().didFinishLaunchingWithOptions();
},
applicationDidFinishLaunching:function () {
if(cc.RenderDoesnotSupport()){
//show Information to user
alert("Browser doesn't support Canvas or WebGL");
return false;
}
// initialize director
var director = cc.Director.getInstance();
cc.EGLView.getInstance().setDesignResolutionSize(480,800,cc.RESOLUTION_POLICY.SHOW_ALL);
cc.EGLView.getInstance().resizeWithBrowserSize(true);
director.setDisplayStats(this.config['showFPS']);
// set FPS. the default value is 1.0/60 if you don't call this
director.setAnimationInterval(1.0 / this.config['frameRate']);
cc.LoaderScene.preload(g_mainmenu, function(){
director.replaceScene(new this.startScene());
}, this);
return true;
}
});
var myApp = new cocos2dApp(SysMenu.scene);
里面的一些参数可以看看api(又不得不吐嘈一下这api,你妹,这是api吗?)
好,在app下,新建Resource.js,内容如下:
var res = {
effect2_mp3 : 'audio/effect2.mp3',
effect2_ogg : 'audio/effect2.ogg',
background_mp3 : 'audio/background.mp3',
background_ogg : 'audio/background.ogg',
greenbullet_png : 'res/greenbullet.png',
greencircle_png : 'res/greencircle.png',
redbullet_png : 'res/redbullet.png',
redcircle_png : 'res/redcircle.png',
gameOver_png : 'res/gameOver.png',
menu_png : 'res/menu.png',
bg3_jpg:'res/bg3.jpg',
bg4_jpg:'res/bg4.jpg',
logo_png:'res/logo.png',
logo1_png:'res/logo_1.png',
logo2_png:'res/logo_2.png',
menuTitle_png:'res/menuTitle.png'
};
var g_mainmenu = [
{src:res.effect2_mp3},
{src:res.effect2_ogg},
{src:res.background_mp3},
{src:res.background_ogg},
{src:res.menu_png},
{src:res.bg4_jpg},
{src:res.logo_png},
{src:res.logo1_png},
{src:res.logo2_png},
{src:res.greencircle_png},
{src:res.menuTitle_png}
];
var g_maingame = [
//image
{src:res.greenbullet_png},
{src:res.greencircle_png},
{src:res.redbullet_png},
{src:res.redcircle_png},
{src:res.gameOver_png}
];
这个文件主要是加载资源的,什么你已经知道了啊?????在public下,建立两个文件夹audio放置音频资源,res放置图片资源,由于blog,本教程的资源请到 git下载
ok,在app下新建MenuLayer.js,内容:
cc.dumpConfig();
var SysMenu = cc.Layer.extend({
init:function () {
var bRet = false;
if (this._super()) {
//var layer = cc.LayerColor.create(new cc.Color4B(0, 0, 0, 255), 600, 600);
//background
/*var sp = cc.Sprite.create(res.bg3_jpg);
sp.setAnchorPoint(0,0);
this.addChild(sp, 0, 1);*/
var circleSpeed = 2;
winSize = cc.Director.getInstance().getWinSize();
var newGameNormal = cc.Sprite.create(res.menu_png, cc.rect(0, 0, 126, 33));
var newGameSelected = cc.Sprite.create(res.menu_png, cc.rect(0, 33, 126, 33));
var newGameDisabled = cc.Sprite.create(res.menu_png, cc.rect(0, 33 * 2, 126, 33));
var gameSettingsNormal = cc.Sprite.create(res.menu_png, cc.rect(126, 0, 126, 33));
var gameSettingsSelected = cc.Sprite.create(res.menu_png, cc.rect(126, 33, 126, 33));
var gameSettingsDisabled = cc.Sprite.create(res.menu_png, cc.rect(126, 33 * 2, 126, 33));
var aboutNormal = cc.Sprite.create(res.menu_png, cc.rect(252, 0, 126, 33));
var aboutSelected = cc.Sprite.create(res.menu_png, cc.rect(252, 33, 126, 33));
var aboutDisabled = cc.Sprite.create(res.menu_png, cc.rect(252, 33 * 2, 126, 33));
var newGame = cc.MenuItemSprite.create(newGameNormal, newGameSelected, newGameDisabled, function () {
this.onButtonEffect();
this.onNewGame();
}.bind(this));
var gameSettings = cc.MenuItemSprite.create(gameSettingsNormal, gameSettingsSelected, gameSettingsDisabled, this.onSettings, this);
var about = cc.MenuItemSprite.create(aboutNormal, aboutSelected, aboutDisabled, this.onAbout, this);
//menu
var menu = cc.Menu.create(newGame, gameSettings, about);
menu.alignItemsVerticallyWithPadding(10);
this.addChild(menu, 1, 2);
menu.setPosition(winSize.width / 2, winSize.height / 2 - 80);
//logo
var logo = cc.Sprite.create(res.logo2_png);
logo.setAnchorPoint(0, 0);
logo.setPosition(winSize.width /2 - 160 ,winSize.height / 2 + 10);
this.addChild(logo, 10, 1);
this.schedule(this.update, 0.1);
for(i=0;i<5;i++){
var greenCircle = cc.Sprite.create(res.greencircle_png);
var randomDir = Math.random()*2*Math.PI;
greenCircle.xSpeed=circleSpeed*Math.cos(randomDir);
greenCircle.ySpeed=circleSpeed*Math.sin(randomDir);
this.addChild(greenCircle);
greenCircle.setPosition(new cc.Point(Math.random()*winSize.width,Math.random()*winSize.height));
greenCircle.schedule(function(){
this.setPosition(new cc.Point(this.getPosition().x+this.xSpeed,this.getPosition().y+this.ySpeed));
if(this.getPosition().x>winSize.width){
this.setPosition(new cc.Point(this.getPosition().x-winSize.width,this.getPosition().y));
}
if(this.getPosition().x<0){
this.setPosition(new cc.Point(this.getPosition().x+winSize.width,this.getPosition().y));
}
if(this.getPosition().y>winSize.height){
this.setPosition(new cc.Point(this.getPosition().x ,this.getPosition().y-winSize.height));
}
if(this.getPosition().y<0){
this.setPosition(new cc.Point(this.getPosition().x ,this.getPosition().y+winSize.height));
}
})
}
if (MW.SOUND) {
cc.AudioEngine.getInstance().setMusicVolume(0.7);
cc.AudioEngine.getInstance().playMusic(res.background_mp3, true);
}
bRet = true;
}
return bRet;
},
onNewGame:function (pSender) {
//load resourcess
cc.LoaderScene.preload(g_maingame, function () {
var scene = cc.Scene.create();
scene.addChild(CircleChainGame.create());
//scene.addChild(GameControlMenu.create());
cc.Director.getInstance().replaceScene(cc.TransitionFade.create(1.2, scene));
}, this);
},
onSettings:function (pSender) {
this.onButtonEffect();
var scene = cc.Scene.create();
scene.addChild(SettingsLayer.create());
cc.Director.getInstance().replaceScene(cc.TransitionFade.create(1.2, scene));
},
onAbout:function (pSender) {
this.onButtonEffect();
var scene = cc.Scene.create();
scene.addChild(AboutLayer.create());
cc.Director.getInstance().replaceScene(cc.TransitionFade.create(1.2, scene));
},
/* update:function () {
if (this._ship.getPosition().y > 480) {
var pos = cc.p(Math.random() * winSize.width, 10);
this._ship.setPosition( pos );
this._ship.runAction( cc.MoveBy.create(
parseInt(5 * Math.random(), 10),
cc.p(Math.random() * winSize.width, pos.y + 480)));
}
},*/
onButtonEffect:function(){
if (MW.SOUND) {
var s = cc.AudioEngine.getInstance().playEffect(res.effect2_mp3);
}
}
});
SysMenu.create = function () {
var sg = new SysMenu();
if (sg && sg.init()) {
return sg;
}
return null;
};
SysMenu.scene = function () {
var scene = cc.Scene.create();
var layer = SysMenu.create();
console.log(layer);
scene.addChild(layer);
return scene;
};
这里面的代码是我模仿官方的demo,唉,不说了,都是泪。。。。
新建GameConfig.js,内容:
//game state
MW.GAME_STATE = {
HOME:0,
PLAY:1,
OVER:2
};
//keys
MW.KEYS = [];
//level
MW.LEVEL = {
STAGE1:1,
STAGE2:2,
STAGE3:3
};
//life
MW.LIFE = 4;
//score
MW.SCORE = 0;
//sound
MW.SOUND = true;
//enemy move type
MW.ENEMY_MOVE_TYPE = {
ATTACK:0,
VERTICAL:1,
HORIZONTAL:2,
OVERLAP:3
};
//delta x
MW.DELTA_X = -100;
//offset x
MW.OFFSET_X = -24;
//rot
MW.ROT = -5.625;
//bullet type
MW.BULLET_TYPE = {
PLAYER:1,
ENEMY:2
};
//weapon type
MW.WEAPON_TYPE = {
ONE:1
};
//unit tag
MW.UNIT_TAG = {
ENMEY_BULLET:900,
PLAYER_BULLET:901,
ENEMY:1000,
PLAYER:1000
};
//attack mode
MW.ENEMY_ATTACK_MODE = {
NORMAL:1,
TSUIHIKIDAN:2
};
//life up sorce
MW.LIFEUP_SORCE = [50000, 100000, 150000, 200000, 250000, 300000];
//container
MW.CONTAINER = {
ENEMIES:[],
ENEMY_BULLETS:[],
PLAYER_BULLETS:[],
EXPLOSIONS:[],
SPARKS:[],
HITS:[],
BACKSKYS:[],
BACKTILEMAPS:[]
};
//bullet speed
MW.BULLET_SPEED = {
ENEMY:-200,
SHIP:900
};
// the counter of active enemies
MW.ACTIVE_ENEMIES = 0;
MW.DEFAULT_CIRCLE = 20;
也是直接从demo中copy的,我去了。。。。
新建CircleChain.js,内容:
var redCircle;
var gameLayer;
var bulletSpeed=5;
var greenCircleArray=new Array();
var size ;
var cnt = 0;
var CircleChainGame = cc.Layer.extend({
init:function(){
cnt = 0;
MW.SCORE = 0;
var ret = false;
this._super();
// set mouse click event on;
this.setMouseEnabled(true);
// the default ball's speed;
var circleSpeed = 2;
MW.SCORE = 0;
cnt = 0;
size= cc.Director.getInstance().getWinSize();
gameLayer = cc.LayerColor.create(new cc.Color4B(0, 0, 0, 255), size.width, size.height);
greenCircleArray = new Array();
// give 10 ball's when begin;
for(i=0;i<MW.DEFAULT_CIRCLE;i++){
var greenCircle = cc.Sprite.create("res/greencircle.png");
greenCircleArray.push(greenCircle);
var randomDir = Math.random()*2*Math.PI;
greenCircle.xSpeed=circleSpeed*Math.cos(randomDir);
greenCircle.ySpeed=circleSpeed*Math.sin(randomDir);
gameLayer.addChild(greenCircle);
greenCircle.setPosition(new cc.Point(Math.random()*size.width,Math.random()*size.height));
greenCircle.schedule(function(){
this.setPosition(new cc.Point(this.getPosition().x+this.xSpeed,this.getPosition().y+this.ySpeed));
if(this.getPosition().x>size.width){
this.setPosition(new cc.Point(this.getPosition().x-size.width,this.getPosition().y));
}
if(this.getPosition().x<0){
this.setPosition(new cc.Point(this.getPosition().x+size.width,this.getPosition().y));
}
if(this.getPosition().y>size.height){
this.setPosition(new cc.Point(this.getPosition().x ,this.getPosition().y-size.height));
}
if(this.getPosition().y<0){
this.setPosition(new cc.Point(this.getPosition().x ,this.getPosition().y+size.height));
}
})
}
console.log("Total:"+greenCircleArray.length);
redCircle=cc.Sprite.create("res/redcircle.png");
gameLayer.addChild(redCircle);
this.addChild(gameLayer);
/*var itemStartGame = cc.MenuItemImage.create(
"res/btnStartGameNor.png",
"res/btnStartGameDown.png",
this.menuCallBack,
this
);
itemStartGame.setPosition(size.width/2, 160);
var menu = cc.Menu.create(itemStartGame);
menu.setPosition(0,0);
this.addChild(menu);*/
ret = true;
return true;
},
onMouseDown:function (event) {
cnt++;
/*if(cnt>2||greenCircleArray.length==0){
this.setMouseEnabled(false);
MW.SCORE = 20 -greenCircleArray.length;
this.runAction(cc.Sequence.create(
cc.DelayTime.create(0.2),
cc.CallFunc.create(this.onGameOver, this)));
console.log(cnt);
console.log(greenCircleArray.length);
}*/
if(cnt>3||greenCircleArray.length==0){
this.setMouseEnabled(false);
MW.SCORE = MW.DEFAULT_CIRCLE - greenCircleArray.length;
this.runAction(cc.Sequence.create(
cc.DelayTime.create(0.2),
cc.CallFunc.create(this.onGameOver, this)));
return;
}
var location = event.getLocation();
gameLayer.removeChild(this.redCircle);
for(i=0;i<4;i++){
var redBullet = cc.Sprite.create("res/redbullet.png");
redBullet.xSpeed=bulletSpeed*Math.cos(i*Math.PI/2);
redBullet.ySpeed=bulletSpeed*Math.sin(i*Math.PI/2);
gameLayer.addChild(redBullet);
redBullet.setPosition(location);
redBullet.schedule(function(){
/*this.setPosition(new cc.Point(this.getPosition().x+this.xSpeed,this.getPosition().y+this.ySpeed));
if(this.getPosition().x>500 || this.getPosition().y>500 || this.getPosition().x<0 || this.getPosition().y<0){
gameLayer.removeChild(this);
}*/
handleBullet(this);
})
}
},
onMouseMoved:function(event){
var location = event.getLocation();
redCircle.setPosition(location);
},
menuCallBack:function(sender){
},
onGameOver:function () {
var scene = cc.Scene.create();
scene.addChild(GameOver.create());
cc.Director.getInstance().replaceScene(cc.TransitionFade.create(1.2, scene));
}
});
function handleBullet(bullet){
bullet.setPosition(new cc.Point(bullet.getPosition().x+bullet.xSpeed,bullet.getPosition().y+bullet.ySpeed));
if(bullet.getPosition().x>size.width || bullet.getPosition().y>size.height || bullet.getPosition().x<0 || bullet.getPosition().y<0){
gameLayer.removeChild(bullet);
}
for(i=greenCircleArray.length-1;i>=0;i--){
var distX=bullet.getPosition().x-greenCircleArray[i].getPosition().x;
var distY=bullet.getPosition().y-greenCircleArray[i].getPosition().y;
if(distX*distX+distY*distY<144){
gameLayer.removeChild(bullet);
for(j=0;j<4;j++){
var greenBullet = cc.Sprite.create("res/greenbullet.png");
greenBullet.xSpeed=bulletSpeed*Math.cos(j*Math.PI/2);
greenBullet.ySpeed=bulletSpeed*Math.sin(j*Math.PI/2);
gameLayer.addChild(greenBullet);
greenBullet.setPosition(new cc.Point(greenCircleArray[i].getPosition().x,greenCircleArray[i].getPosition().y));
greenBullet.schedule(function(){
handleBullet(this);
})
}
gameLayer.removeChild(greenCircleArray[i]);
greenCircleArray.splice(i,1);
console.log(i+"ii");
console.log(cnt);
console.log(greenCircleArray.length);
if(cnt>2||greenCircleArray.length==0){
return ;
}
}
}
};
/*var circleChainScene = cc.Scene.extend({
onEnter:function(){
this._super();
var layer = new circleChainGame();
layer.init();
this.addChild(layer);
}
});*/
CircleChainGame.create = function () {
var sg = new CircleChainGame();
if (sg && sg.init()) {
return sg;
}
return null;
};
CircleChainGame.scene = function () {
var scene = cc.Scene.create();
var layer = CircleChainGame.create();
scene.addChild(layer);
return scene;
};
恩,这个是我们主要的程序,简单的逻辑。。。。
新建AboutLayer.js,内容:
var AboutLayer = cc.Layer.extend({
init:function () {
var bRet = false;
if (this._super()) {
/*var sp = cc.Sprite.create(res.loading_png);
sp.setAnchorPoint(0,0);
this.addChild(sp, 0, 1);*/
var cacheImage = cc.TextureCache.getInstance().addImage(res.menuTitle_png);
var title = cc.Sprite.createWithTexture(cacheImage, cc.rect(0, 36, 100, 34));
title.setPosition( winSize.width / 2, winSize.height - 160 );
this.addChild(title);
// There is a bug in LabelTTF native. Apparently it fails with some unicode chars.
var about = cc.LabelTTF.create("Circle chain game create by jov.\n QQ:247911950 \n Email:jov123@163.com \n Git:", "Arial", 16, cc.size(winSize.width * 0.85, 320), cc.TEXT_ALIGNMENT_CENTER );
about.setPosition(winSize.width / 2, winSize.height/2 -20 );
about.setAnchorPoint(0.5, 0.5 );
this.addChild(about);
var label = cc.LabelTTF.create("Go back", "Arial", 18);
var back = cc.MenuItemLabel.create(label, this.onBackCallback);
var menu = cc.Menu.create(back);
menu.setPosition( winSize.width / 2, winSize.height/2 -100);
this.addChild(menu);
bRet = true;
}
return bRet;
},
onBackCallback:function (pSender) {
var scene = cc.Scene.create();
scene.addChild(SysMenu.create());
cc.Director.getInstance().replaceScene(cc.TransitionFade.create(1.2, scene));
}
});
AboutLayer.create = function () {
var sg = new AboutLayer();
if (sg && sg.init()) {
return sg;
}
return null;
};
新建GameOver.js,内容:
var GameOver = cc.Layer.extend({
//_ship:null,
_lbScore:0,
init:function () {
var bRet = false;
if (this._super()) {
//var sp = cc.Sprite.create(res.loading_png);
//sp.setAnchorPoint(0,0);
//this.addChild(sp, 0, 1);
var logo = cc.Sprite.create(res.gameOver_png);
logo.setAnchorPoint(0,0);
logo.setPosition(winSize.width / 2 -160,winSize.height/2);
this.addChild(logo,10,1);
var playAgainNormal = cc.Sprite.create(res.menu_png, cc.rect(378, 0, 126, 33));
var playAgainSelected = cc.Sprite.create(res.menu_png, cc.rect(378, 33, 126, 33));
var playAgainDisabled = cc.Sprite.create(res.menu_png, cc.rect(378, 33 * 2, 126, 33));
//var cocos2dhtml5 = cc.Sprite.create(res.cocos2d_html5_png);
//cocos2dhtml5.setPosition(160,150);
//this.addChild(cocos2dhtml5,10);
//var flare = cc.Sprite.create(res.flare_jpg);
//this.addChild(flare);
//flare.setVisible(false);
var playAgain = cc.MenuItemSprite.create(playAgainNormal, playAgainSelected, playAgainDisabled, function(){
this.onPlayAgain();
}.bind(this) );
var menu = cc.Menu.create(playAgain);
this.addChild(menu, 1, 2);
menu.setPosition(winSize.width / 2, winSize.height/2-100);
var str = "Your Score:"+MW.SCORE;
if(MW.SCORE>=15&&MW.SCORE<=17){
str +="\n\nGood!";
}else if(MW.SCORE>=18&&MW.SCORE<=19){
str +="\n\nGreat!"
}else if(MW.SCORE==20){
str +="\n\nExcellent!";
}else{
str += "\n\n干八爹!"
}
var lbScore = cc.LabelTTF.create(str,"Arial Bold",16);
lbScore.setPosition(winSize.width / 2,winSize.height/2-40);
lbScore.setColor(cc.c3b(250,250,250));
this.addChild(lbScore,10);
/* var b1 = cc.LabelTTF.create("Download Cocos2d-html5","Arial",14);
var b2 = cc.LabelTTF.create("Download This Sample","Arial",14);
var menu1 = cc.MenuItemLabel.create(b1,function(){
window.location.href = "http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Cocos2d-html5";
});
var menu2 = cc.MenuItemLabel.create(b2,function(){
window.location.href = "https://github.com/ShengxiangChen/MoonWarriors";
});
var cocos2dMenu = cc.Menu.create(menu1,menu2);
cocos2dMenu.alignItemsVerticallyWithPadding(10);
cocos2dMenu.setPosition(160,80);
this.addChild(cocos2dMenu);*/
if(MW.SOUND){
cc.AudioEngine.getInstance().playMusic(res.background_mp3);
}
bRet = true;
}
return bRet;
},
onPlayAgain:function (pSender) {
var scene = cc.Scene.create();
scene.addChild(CircleChainGame.create());
//scene.addChild(GameControlMenu.create());
cc.Director.getInstance().replaceScene(cc.TransitionFade.create(1.2,scene));
}
});
GameOver.create = function () {
var sg = new GameOver();
if (sg && sg.init()) {
return sg;
}
return null;
};
GameOver.scene = function () {
var scene = cc.Scene.create();
var layer = GameOver.create();
scene.addChild(layer);
return scene;
};
恩,ok了,启动server,看看效果:
不管如何跑起来就行,恩,ok了,别忘了上传到heroku哦,好东西大家分享嘛,后面打算加一些关卡。。。
本示例演示地址:http://ogames.herokuapp.com/ 由于加载的东西比较多,可能有点慢,一定要等啊。。。。
github下载地址:https://github.com/joveth/games
QQ交流群:158325682