init before WX13
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
node_modules
|
||||
trash
|
||||
.DS_Store
|
||||
*.sublime-*
|
||||
images
|
66
Button.js
Normal file
|
@ -0,0 +1,66 @@
|
|||
'use strict';
|
||||
|
||||
function Button (txt,onclick) {
|
||||
createjs.Container.prototype.initialize.call(this);
|
||||
|
||||
this.changed = true;
|
||||
|
||||
var paddingTop = 5;
|
||||
var paddingLeft = 8;
|
||||
|
||||
var fontSize = Button.HEIGHT;
|
||||
var font = fontSize + 'px "Segoe UI", Arial, "Microsoft Yahei", Simsun, sans-serif';
|
||||
|
||||
this.text = new createjs.Text(txt,font);
|
||||
this.text.textBaseline = "middle";
|
||||
|
||||
this.height = fontSize + paddingTop*2;
|
||||
this.width = this.text.getMeasuredWidth() + paddingLeft*2;
|
||||
|
||||
this.regX = this.width/2;
|
||||
this.regY = this.height/2;
|
||||
|
||||
this.text.x = paddingLeft;
|
||||
this.text.y = this.height/2;
|
||||
|
||||
this.background = new createjs.Shape();
|
||||
|
||||
this.toDefaultStyle();
|
||||
|
||||
this.addChild(this.background,this.text);
|
||||
|
||||
this.on('click',onclick);
|
||||
this.on('mouseover',this.toHoverStyle);
|
||||
this.on('mouseout',this.toDefaultStyle);
|
||||
}
|
||||
|
||||
Button.HEIGHT = 11;
|
||||
|
||||
Button.prototype = new createjs.Container();
|
||||
Button.prototype.constructor = Button;
|
||||
|
||||
Button.prototype.toDefaultStyle = function () {
|
||||
this.changed = true;
|
||||
this.text.color = '#444';
|
||||
this.background.graphics
|
||||
.clear()
|
||||
.beginStroke('#c0c0c0')
|
||||
.beginLinearGradientFill(['#ededed','#ededed','#dedede'],[0,0.38,1],0,0,0,this.height)
|
||||
.drawRoundRect(0,0,this.width,this.height,2);
|
||||
};
|
||||
|
||||
Button.prototype.toHoverStyle = function () {
|
||||
this.changed = true;
|
||||
this.text.color = '#000';
|
||||
this.background.graphics
|
||||
.clear()
|
||||
.beginStroke('#afafaf')
|
||||
.beginLinearGradientFill(['#f0f0f0','#f0f0f0','#e0e0e0'],[0,0.38,1],0,0,0,this.height)
|
||||
.drawRoundRect(0,0,this.width,this.height,2);
|
||||
};
|
||||
|
||||
Button.prototype.update = function () {
|
||||
var changed = this.changed;
|
||||
this.changed = false;
|
||||
return changed;
|
||||
};
|
50
ButtonList.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
'use strict';
|
||||
|
||||
function ButtonList () {
|
||||
createjs.Container.prototype.initialize.call(this);
|
||||
|
||||
this.changed = false;
|
||||
this.buttons = [];
|
||||
}
|
||||
|
||||
ButtonList.prototype = new createjs.Container();
|
||||
ButtonList.prototype.constructor = ButtonList;
|
||||
|
||||
ButtonList.prototype.addButton = function (btn) {
|
||||
this.changed = true;
|
||||
this.buttons.push(btn);
|
||||
this.addChild(btn);
|
||||
};
|
||||
|
||||
ButtonList.prototype.setButtonPositions = function () {
|
||||
var base = -this.buttons.length/2 + 0.5;
|
||||
this.buttons.forEach(function (btn,i) {
|
||||
btn.x = 0;
|
||||
btn.y = (base + i)*btn.height;
|
||||
});
|
||||
};
|
||||
|
||||
ButtonList.prototype.removeButton = function (btn) {
|
||||
removeFromArr(btn,this.buttons);
|
||||
if (this.removeChild(btn)) this.changed = true;
|
||||
};
|
||||
|
||||
ButtonList.prototype.removeAllButtons = function () {
|
||||
if (!this.buttons.length) return;
|
||||
this.changed = true;
|
||||
this.buttons.length = 0;
|
||||
this.removeAllChildren();
|
||||
};
|
||||
|
||||
ButtonList.prototype.update = function () {
|
||||
if (this.changed) {
|
||||
this.setButtonPositions();
|
||||
}
|
||||
|
||||
var changed = this.changed;
|
||||
this.buttons.forEach(function (btn) {
|
||||
if (btn.update()) changed = true;
|
||||
});
|
||||
this.changed = false;
|
||||
return changed;
|
||||
};
|
279
Card.js
Normal file
|
@ -0,0 +1,279 @@
|
|||
'use strict';
|
||||
|
||||
function Card (game,isWhiteBack) {
|
||||
createjs.Container.prototype.initialize.call(this);
|
||||
|
||||
// 基本属性
|
||||
this.game = game;
|
||||
this.isWhiteBack = isWhiteBack;
|
||||
this.width = Card.WIDTH;
|
||||
this.height = Card.HEIGHT;
|
||||
this.pid = 0;
|
||||
this.zone = null;
|
||||
this.zIndex = 0;
|
||||
this.changed = true;
|
||||
|
||||
// 渲染层
|
||||
// 因为EasleJS没有位置偏移(translate),
|
||||
// 所以增加渲染层来提供偏移. 即:
|
||||
// Card.x 指定卡片的水平位置, renderLayer.x 指定其水平偏移.
|
||||
// 所有显示对象都放到渲染层,这样,它们都会跟着偏移.
|
||||
this.renderLayer = new createjs.Container();
|
||||
this.addChild(this.renderLayer);
|
||||
|
||||
// 变形原点在中心.
|
||||
this.renderLayer.regX = this.width/2;
|
||||
this.renderLayer.regY = this.height/2;
|
||||
|
||||
// 位图层
|
||||
this.bitmap = new CardBitmap('',game.imageManager.noimage);
|
||||
this.renderLayer.addChild(this.bitmap);
|
||||
|
||||
// 状态层 (冻结,枪兵等状态)
|
||||
this.stateLayer = new createjs.Container();
|
||||
this.renderLayer.addChild(this.stateLayer);
|
||||
|
||||
// 效果层
|
||||
this.effectShape = new createjs.Shape();
|
||||
this.renderLayer.addChild(this.effectShape);
|
||||
|
||||
// 按钮层
|
||||
this.buttonLayer = new ButtonList();
|
||||
this.buttonLayer.x = this.width/2;
|
||||
this.buttonLayer.y = this.height/2
|
||||
this.renderLayer.addChild(this.buttonLayer);
|
||||
|
||||
// 样式
|
||||
this.style = new Style({
|
||||
x: 0,
|
||||
y: 0,
|
||||
zIndex: 0,
|
||||
top: false,
|
||||
covered: false,
|
||||
offX: 0, // 位置偏移
|
||||
offY: 0,
|
||||
rotation: 0,
|
||||
scaleX: -1, // 用于翻面,负数表示反面,正数表示正面
|
||||
shadowColor: "#f7ff00",
|
||||
shadowBlur: 0,
|
||||
flash: 0, // 用于闪烁: alpha = 1 - (flash % 1)
|
||||
// flash 从0渐变到n,则闪烁n次.
|
||||
shine: 0 // 用于闪耀,范围为0至1,
|
||||
// 表示闪耀动画进行的百分比.
|
||||
});
|
||||
this.style.checkSkip = function () {
|
||||
return this.game.skip;
|
||||
}.bind(this);
|
||||
|
||||
this.on('mouseover',this.handleMouseover);
|
||||
this.on('mouseout',this.handleMouseout);
|
||||
|
||||
this.game.addCard(this);
|
||||
}
|
||||
|
||||
Card.WIDTH = 63;
|
||||
Card.HEIGHT = 88;
|
||||
|
||||
Card.prototype = new createjs.Container();
|
||||
Card.prototype.constructor = Card;
|
||||
|
||||
Card.prototype.up = function () {
|
||||
var rotation = this.zone.opposite? 180 : 0;
|
||||
this.style.transit('rotation',rotation,0.2);
|
||||
};
|
||||
|
||||
Card.prototype.down = function () {
|
||||
var rotation = this.zone.opposite? 180 : 0;
|
||||
rotation += 90;
|
||||
this.style.transit('rotation',rotation,0.2);
|
||||
};
|
||||
|
||||
Card.prototype.faceup = function () {
|
||||
this.style.transit('scaleX',1,0.2);
|
||||
};
|
||||
|
||||
Card.prototype.facedown = function () {
|
||||
this.style.transit('scaleX',-1,0.2);
|
||||
};
|
||||
|
||||
Card.prototype.move = function (pid,zone,up,faceup,bottom) {
|
||||
this.pid = pid;
|
||||
this.floatdown();
|
||||
|
||||
if (this.zone) this.zone.removeCard(this);
|
||||
this.zone = zone;
|
||||
this.zone.addCard(this,bottom);
|
||||
|
||||
up? this.up() : this.down();
|
||||
faceup? this.faceup() : this.facedown();
|
||||
};
|
||||
|
||||
Card.prototype.moveTo = function (x,y,coveredMoving,coveredSettaled) {
|
||||
this.style.transit('x',x,0.2);
|
||||
this.style.transit('y',y,0.2);
|
||||
if (x !== this.x || y !== this.y) {
|
||||
this.style.set('top',true);
|
||||
this.style.transit('top',false,0.2);
|
||||
}
|
||||
this.style.set('covered',coveredMoving);
|
||||
this.style.transit('covered',coveredSettaled,0.2);
|
||||
};
|
||||
|
||||
Card.prototype.floatup = function () {
|
||||
this.style.set('top',true);
|
||||
// this.style.transit('offY',-10,0.1,Style.linear);
|
||||
};
|
||||
|
||||
Card.prototype.floatdown = function () {
|
||||
this.style.set('top',false);
|
||||
// this.style.transit('offY',0,0.1,Style.linear);
|
||||
};
|
||||
|
||||
Card.prototype.outlineOn = function () {
|
||||
this.style.transit('shadowBlur',5,0.2,Style.linear);
|
||||
};
|
||||
|
||||
Card.prototype.outlineOff = function () {
|
||||
this.style.transit('shadowBlur',0,0.2,Style.linear);
|
||||
};
|
||||
|
||||
Card.prototype.flash = function () {
|
||||
this.style.set('flash',0);
|
||||
this.style.transit('flash',3,0.3,Style.linear);
|
||||
};
|
||||
|
||||
Card.prototype.shine = function () {
|
||||
this.style.set('shine',0);
|
||||
this.style.transit('shine',1,0.3,Style.linear);
|
||||
};
|
||||
|
||||
Card.prototype.addStates = function (states) {
|
||||
this.changed = true;
|
||||
this.stateLayer.visible = true;
|
||||
states.forEach(function (state) {
|
||||
var stateImage = this.game.imageManager.getStateImage(state);
|
||||
var bitmap = new createjs.Bitmap(stateImage);
|
||||
this.stateLayer.addChild(bitmap);
|
||||
},this);
|
||||
};
|
||||
|
||||
Card.prototype.removeStates = function () {
|
||||
this.changed = true;
|
||||
this.stateLayer.visible = false;
|
||||
this.stateLayer.removeAllChildren();
|
||||
};
|
||||
|
||||
Card.prototype.addButton = function (txt,onclick) {
|
||||
// var useDialog = this.shouldUseDialog();
|
||||
|
||||
// if (useDialog) {
|
||||
// this.zone.addButton(txt,onclick.bind(this,this),this);
|
||||
// return;
|
||||
// }
|
||||
|
||||
var btn = new Button(txt,onclick.bind(this,this));
|
||||
this.buttonLayer.addButton(btn);
|
||||
// this.outlineOn();
|
||||
};
|
||||
|
||||
|
||||
// 在给卡片添加按钮时,有时候卡片被遮挡,
|
||||
// 须要用卡片选择框.
|
||||
// 问:具体什么情况下要用选择框呢?
|
||||
// 答:满足以下条件之一:
|
||||
// 1.卡片在TileZone(除了己方手牌),牌组,LRIG牌组,废弃区,LRIG废弃区;
|
||||
// 2.卡片在检查区,且检查区不止1张卡.
|
||||
// 3.卡片在SIGNI区或LRIG区,并且,不在最上面.
|
||||
Card.prototype.shouldUseDialog = function () {
|
||||
var zoneName = this.zone.name;
|
||||
if (this.zone.constructor === TileZone) {
|
||||
if (this.zone !== this.game.player.handZone) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (inArr(zoneName,['MainDeck','LrigDeck','TrashZone','LrigTrashZone'])) {
|
||||
return true;
|
||||
}
|
||||
if (zoneName === 'CheckZone') {
|
||||
if (this.zone.cards.length > 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (inArr(zoneName,['SigniZone','LrigZone'])) {
|
||||
if (this.zone.getCardIndex(this) !== 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Card.prototype.removeButtons = function () {
|
||||
this.buttonLayer.removeAllButtons();
|
||||
// this.outlineOff();
|
||||
};
|
||||
|
||||
Card.prototype.update = function () {
|
||||
var changed = this.style.isChanged() || this.changed;
|
||||
concat(this.buttonLayer,this.bitmap).forEach(function (obj) {
|
||||
if (obj.update()) changed = true;
|
||||
},this);
|
||||
if (!changed) return false;
|
||||
this.changed = false;
|
||||
// shortcuts
|
||||
var layer = this.renderLayer;
|
||||
var effectShape = this.effectShape;
|
||||
var bitmap = this.bitmap;
|
||||
// 计算样式
|
||||
var style = this.style.getComputedStyle();
|
||||
// 位置
|
||||
this.x = style.x;
|
||||
this.y = style.y;
|
||||
// 旋转
|
||||
this.rotation = style.rotation;
|
||||
this.buttonLayer.rotation = -style.rotation;
|
||||
// 闪烁 (flash)
|
||||
this.alpha = 1 - (style.flash % 1);
|
||||
// 偏移
|
||||
layer.x = style.offX;
|
||||
layer.y = style.offY;
|
||||
// 翻面
|
||||
var cardName = this.pid? Localize.cardName(CardInfo[this.pid]) : '???';
|
||||
if (style.scaleX > 0) {
|
||||
// 正面
|
||||
this.bitmap.setAltImage(cardName,this.game.imageManager.getImageByPid(this.pid));
|
||||
} else {
|
||||
// 背面
|
||||
this.bitmap.setAltImage(cardName,this.game.imageManager.getBackImage(this.isWhiteBack));
|
||||
}
|
||||
layer.scaleX = Math.abs(style.scaleX);
|
||||
// outline (其实是shadow)
|
||||
bitmap.shadow = new createjs.Shadow(style.shadowColor,0,0,style.shadowBlur);
|
||||
// 闪耀 (shine)
|
||||
// 闪耀就是在效果层上画一道移动的白光
|
||||
if (style.shine > 0) {
|
||||
var w = 40; // 白光的"宽度" (等于白光实际宽度除以根号2,因为白光是45度倾斜的)
|
||||
var x0 = style.shine*(this.width+w) - w;
|
||||
var y0 = style.shine*(this.height+w) - w;
|
||||
var x1 = x0 + w;
|
||||
var y1 = y0 + w;
|
||||
this.effectShape.graphics
|
||||
.clear()
|
||||
.beginLinearGradientFill(['rgba(255,255,255,0)','white','rgba(255,255,255,0)'],[0,0.5,1],x0,y0,x1,y1)
|
||||
.drawRect(0,0,this.width,this.height);
|
||||
}
|
||||
// zIndex
|
||||
this.zIndex = style.top? 512 : style.zIndex;
|
||||
this.visible = style.top || !style.covered;
|
||||
return true;
|
||||
};
|
||||
|
||||
Card.prototype.handleMouseover = function (event) {
|
||||
this.game.cardDetail.show(this.pid);
|
||||
if (this.zone.opposite || this.zone.name !== 'HandZone') return;
|
||||
this.floatup();
|
||||
};
|
||||
|
||||
Card.prototype.handleMouseout = function (event) {
|
||||
if (this.zone.opposite || this.zone.name !== 'HandZone') return;
|
||||
this.floatdown();
|
||||
};
|
58
CardBitmap.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
'use strict';
|
||||
|
||||
function CardBitmap (alt,img) {
|
||||
createjs.Container.prototype.initialize.call(this);
|
||||
|
||||
this.setAltImage(alt,img);
|
||||
this.setWidthHeight(Card.WIDTH,Card.HEIGHT);
|
||||
|
||||
this.complete = img.complete;
|
||||
|
||||
this.text = new createjs.Text(alt);
|
||||
this.bitmap = new createjs.Bitmap(img);
|
||||
this.addChild(this.text,this.bitmap);
|
||||
|
||||
this.changed = true;
|
||||
}
|
||||
|
||||
CardBitmap.prototype = new createjs.Container();
|
||||
CardBitmap.prototype.constructor = CardBitmap;
|
||||
|
||||
CardBitmap.prototype.setAltImage = function (alt,img) {
|
||||
if (alt !== this.alt || img !== this.img) {
|
||||
this.changed = true;
|
||||
this.alt = alt;
|
||||
this.img = img;
|
||||
}
|
||||
};
|
||||
|
||||
CardBitmap.prototype.setWidthHeight = function (width,height) {
|
||||
if (width !== this.width || height !== this.height) {
|
||||
this.changed = true;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
};
|
||||
|
||||
CardBitmap.prototype.update = function () {
|
||||
if (this.complete != this.img.complete) {
|
||||
this.changed = true;
|
||||
}
|
||||
|
||||
if (!this.changed) return false;
|
||||
|
||||
this.changed = false;
|
||||
this.complete = this.img.complete;
|
||||
this.text.text = this.alt;
|
||||
if (this.img.complete && this.img.naturalWidth !== 0) {
|
||||
this.bitmap.image = this.img;
|
||||
this.bitmap.scaleX = this.width / this.img.width;
|
||||
this.bitmap.scaleY = this.height / this.img.height;
|
||||
this.bitmap.visible = true;
|
||||
this.text.visible = false;
|
||||
} else {
|
||||
this.bitmap.visible = false;
|
||||
this.text.visible = true;
|
||||
}
|
||||
return true;
|
||||
};
|
95
CardButton.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
'use strict';
|
||||
|
||||
function CardButton (card,onclick) {
|
||||
createjs.Container.prototype.initialize.call(this);
|
||||
|
||||
this.changed = true;
|
||||
this.selected = false;
|
||||
this.disabled = false;
|
||||
this.hovered = false;
|
||||
this.order = 0;
|
||||
|
||||
var img = card.game.imageManager.getImageByCid(card.cid);
|
||||
this.bitmap = new CardBitmap(card.cid,img);
|
||||
this.width = Card.WIDTH*2;
|
||||
this.height = Card.HEIGHT*2;
|
||||
this.bitmap.setWidthHeight(this.width,this.height);
|
||||
this.addChild(this.bitmap);
|
||||
|
||||
this.maskLayer = new createjs.Shape();
|
||||
this.orderLayer = new createjs.Text();
|
||||
this.addChild(this.maskLayer,this.orderLayer);
|
||||
|
||||
this.orderLayer.font = "70px 'Segoe UI', Arial, 'Microsoft Yahei', Simsun, sans-serif'";
|
||||
this.orderLayer.textBaseline = "middle";
|
||||
this.orderLayer.textAlign = 'center';
|
||||
this.orderLayer.x = this.width/2;
|
||||
this.orderLayer.y = this.height/2;
|
||||
|
||||
this.on('click',onclick);
|
||||
this.on('mouseover',this.onmouseover);
|
||||
this.on('mouseout',this.onmouseout);
|
||||
}
|
||||
|
||||
CardButton.prototype = new createjs.Container();
|
||||
CardButton.prototype.constructor = CardButton;
|
||||
|
||||
CardButton.prototype.onmouseover = function (event) {
|
||||
if (this.hovered) return;
|
||||
this.hovered = true;
|
||||
this.changed = true;
|
||||
};
|
||||
|
||||
CardButton.prototype.onmouseout = function (event) {
|
||||
if (!this.hovered) return;
|
||||
this.hovered = false;
|
||||
this.changed = true;
|
||||
};
|
||||
|
||||
CardButton.prototype.setOrder = function (order) {
|
||||
if (this.order === order) return;
|
||||
this.order = order;
|
||||
this.changed = true;
|
||||
};
|
||||
|
||||
CardButton.prototype.disable = function () {
|
||||
if (this.disabled) return;
|
||||
this.disabled = true;
|
||||
this.changed = true;
|
||||
};
|
||||
|
||||
CardButton.prototype.enable = function () {
|
||||
if (!this.disabled) return;
|
||||
this.disabled = false;
|
||||
this.changed = true;
|
||||
};
|
||||
|
||||
CardButton.prototype.update = function () {
|
||||
if (this.bitmap.update()) this.changed = true;
|
||||
if (!this.changed) return false;
|
||||
this.changed = false;
|
||||
|
||||
this.maskLayer.graphics.clear();
|
||||
if (this.order) {
|
||||
this.orderLayer.visible = true;
|
||||
this.orderLayer.text = this.order;
|
||||
} else {
|
||||
this.orderLayer.visible = false;
|
||||
}
|
||||
if (this.selected) {
|
||||
this.maskLayer.graphics
|
||||
.beginFill('rgba(255,255,255,0.5)')
|
||||
.drawRect(0,0,this.width,this.height);
|
||||
} else if (this.disabled) {
|
||||
this.maskLayer.graphics
|
||||
.beginFill('rgba(0,0,0,0.5)')
|
||||
.drawRect(0,0,this.width,this.height);
|
||||
} else if (this.hovered) {
|
||||
this.maskLayer.graphics
|
||||
.beginFill('rgba(255,255,255,0.1)')
|
||||
.drawRect(0,0,this.width,this.height);
|
||||
} else {
|
||||
this.maskLayer.graphics.clear();
|
||||
}
|
||||
return true;
|
||||
};
|
256
CardDialog.js
Normal file
|
@ -0,0 +1,256 @@
|
|||
'use strict';
|
||||
|
||||
function CardDialog (game,id) {
|
||||
this.game = game;
|
||||
this.stage = new createjs.Stage(id+'Canvas');
|
||||
this.stage.enableMouseOver(10);
|
||||
|
||||
this.scrollDiv = document.getElementById(id+'ScrollDiv');
|
||||
this.windowDiv = document.getElementById(id+'WindowDiv');
|
||||
this.warpDiv = document.getElementById(id+'WarpDiv');
|
||||
this.titleDiv = document.getElementById(id+'TitleDiv');
|
||||
this.closeIcon = document.getElementById(id+'CloseIcon');
|
||||
this.okButton = document.getElementById(id+'OkButton');
|
||||
|
||||
this.cardButtons = [];
|
||||
|
||||
this.hidden = true;
|
||||
this.canClose = false;
|
||||
|
||||
this.warpDiv.style.visibility = 'hidden';
|
||||
|
||||
var dialog = this;
|
||||
}
|
||||
|
||||
CardDialog.prototype.showCards = function (title,cards,callback) {
|
||||
var dialog = this;
|
||||
cards.forEach(function (card) {
|
||||
var btn = new CardButton(card,function () {});
|
||||
dialog.cardButtons.push(btn);
|
||||
dialog.stage.addChild(btn);
|
||||
},this);
|
||||
|
||||
dialog.okButton.disabled = false;
|
||||
dialog.okButton.textContent = '确定';
|
||||
dialog.okButton.onclick = function (event) {
|
||||
dialog.close();
|
||||
callback();
|
||||
}
|
||||
dialog.okButton.hidden = false;
|
||||
dialog.canClose = false;
|
||||
dialog.pop(title);
|
||||
};
|
||||
|
||||
CardDialog.prototype.selectOne = function (title,cards,callback) {
|
||||
var dialog = this;
|
||||
cards.forEach(function (card) {
|
||||
var btn = new CardButton(card,function (event) {
|
||||
dialog.close();
|
||||
callback(card);
|
||||
});
|
||||
dialog.cardButtons.push(btn);
|
||||
dialog.stage.addChild(btn);
|
||||
},this);
|
||||
dialog.okButton.hidden = true;
|
||||
dialog.pop(title);
|
||||
};
|
||||
|
||||
CardDialog.prototype.selectSomeAdvanced = function (title,cards,careOrder,onSelectChange,callback) {
|
||||
var dialog = this;
|
||||
var selectedIndexes = [];
|
||||
cards.forEach(function (card,idx) {
|
||||
var btn = new CardButton(card,function (event) {
|
||||
if (!this.selected && this.disabled) return;
|
||||
this.changed = true;
|
||||
dialog.cardButtons.forEach(function (btn) {
|
||||
btn.enable();
|
||||
},this);
|
||||
if (this.selected) {
|
||||
this.selected = false;
|
||||
removeFromArr(idx,selectedIndexes);
|
||||
} else {
|
||||
this.selected = true;
|
||||
selectedIndexes.push(idx);
|
||||
}
|
||||
handleSelectChange();
|
||||
});
|
||||
dialog.cardButtons.push(btn);
|
||||
dialog.stage.addChild(btn);
|
||||
},this);
|
||||
handleSelectChange();
|
||||
this.okButton.textContent = '确定';
|
||||
this.okButton.hidden = false;
|
||||
dialog.pop(title);
|
||||
|
||||
function handleSelectChange () {
|
||||
var done = onSelectChange(selectedIndexes,disable);
|
||||
if (careOrder) {
|
||||
dialog.cardButtons.forEach(function (btn,idx) {
|
||||
var order = selectedIndexes.indexOf(idx) + 1;
|
||||
btn.setOrder(order);
|
||||
});
|
||||
}
|
||||
if (done) {
|
||||
dialog.okButton.disabled = false;
|
||||
dialog.okButton.onclick = function (event) {
|
||||
dialog.close();
|
||||
callback(selectedIndexes);
|
||||
};
|
||||
} else {
|
||||
dialog.okButton.disabled = true;
|
||||
dialog.okButton.onclick = null;
|
||||
}
|
||||
}
|
||||
function disable (idx) {
|
||||
dialog.cardButtons[idx].disable();
|
||||
}
|
||||
};
|
||||
|
||||
CardDialog.prototype.selectSome = function (title,cards,min,max,careOrder,callback) {
|
||||
this.selectSomeAdvanced(title,cards,careOrder,function (selectedIndexes,disable) {
|
||||
var len = selectedIndexes.length;
|
||||
if (len >= max) {
|
||||
cards.forEach(function (card,idx) {
|
||||
disable(idx);
|
||||
},this);
|
||||
return true;
|
||||
}
|
||||
return len >= min;
|
||||
},function (selectedIndexes) {
|
||||
callback(selectedIndexes.map(function (idx) {
|
||||
return cards[idx];
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
CardDialog.prototype.seekSome = function (title,cards,targets,min,max,callback) {
|
||||
this.selectSomeAdvanced(title,cards,false,function (selectedIndexes,disable) {
|
||||
// 先 disable 掉 targets 以外的卡.
|
||||
cards.forEach(function (card,idx) {
|
||||
if (!inArr(card,targets)) disable(idx);
|
||||
},this);
|
||||
|
||||
var len = selectedIndexes.length;
|
||||
if (len >= max) {
|
||||
cards.forEach(function (card,idx) {
|
||||
disable(idx);
|
||||
},this);
|
||||
return true;
|
||||
}
|
||||
return len >= min;
|
||||
},function (selectedIndexes) {
|
||||
callback(selectedIndexes.map(function (idx) {
|
||||
return cards[idx];
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
CardDialog.prototype.selectEner = function (title,cards,colors,cost,callback) {
|
||||
this.selectSomeAdvanced(title,cards,false,onSelectChange,function (selectedIndexes) {
|
||||
callback(selectedIndexes.map(function (idx) {
|
||||
return cards[idx];
|
||||
}));
|
||||
});
|
||||
|
||||
function onSelectChange (selectedIndexes,disable) {
|
||||
var need = {};
|
||||
var total = 0;
|
||||
['colorless','white','black','red','blue','green','multi'].forEach(function (color) {
|
||||
need[color] = cost[color] || 0;
|
||||
total += need[color];
|
||||
},this);
|
||||
|
||||
if (selectedIndexes.length >= total) {
|
||||
cards.forEach(function (card,idx) {
|
||||
disable(idx);
|
||||
},this);
|
||||
return true;
|
||||
}
|
||||
|
||||
selectedIndexes.forEach(function (idx) {
|
||||
var color = colors[idx];
|
||||
if (color === 'multi') return;
|
||||
if (need[color] > 0) {
|
||||
need[color] -= 1;
|
||||
} else {
|
||||
need.colorless -= 1;
|
||||
}
|
||||
},this);
|
||||
|
||||
if (need.colorless > 0) return false;
|
||||
|
||||
cards.forEach(function (card,idx) {
|
||||
var color = colors[idx];
|
||||
if (color === 'multi') return;
|
||||
if (!need[color]) disable(idx);
|
||||
},this);
|
||||
}
|
||||
};
|
||||
|
||||
CardDialog.prototype.draw = function () {
|
||||
var width = Card.WIDTH*2;
|
||||
var height = Card.HEIGHT*2;
|
||||
var space = 10;
|
||||
var len = this.cardButtons.length;
|
||||
var singleRow = len <= 3;
|
||||
var totalWidth = (width + 2*space) * 3;
|
||||
var totalHeight = (height + 2*space) * Math.ceil(this.cardButtons.length/3);
|
||||
this.cardButtons.forEach(function (btn,i) {
|
||||
var row = i%3; // 第row行 (下标从0开始);
|
||||
var col = Math.floor(i/3); // 第col列 (下标从0开始);
|
||||
if (singleRow) {
|
||||
btn.x = (totalWidth - len*(width+2*space)) / 2;
|
||||
} else {
|
||||
btn.x = 0;
|
||||
}
|
||||
btn.x += row*(width+2*space) + space;
|
||||
btn.y = col*(height+2*space) + space;
|
||||
},this);
|
||||
this.stage.canvas.width = totalWidth;
|
||||
this.stage.canvas.height = totalHeight;
|
||||
};
|
||||
|
||||
CardDialog.prototype.pop = function (title) {
|
||||
this.draw();
|
||||
this.titleDiv.textContent = title;
|
||||
if (this.canClose) {
|
||||
this.closeIcon.style.display = '';
|
||||
this.closeIcon.onclick = this.close.bind(this);
|
||||
} else {
|
||||
this.closeIcon.style.display = 'none';
|
||||
this.closeIcon.onclick = null;
|
||||
}
|
||||
this.hidden = false;
|
||||
|
||||
var warp = this.warpDiv;
|
||||
var win = this.windowDiv;
|
||||
var scroll = this.scrollDiv;
|
||||
warp.style.opacity = '0';
|
||||
warp.style.visibility = 'visible';
|
||||
// 消灭水平滚动条
|
||||
scroll.style.width = this.stage.canvas.width + scroll.offsetWidth - scroll.clientWidth + 'px';
|
||||
// 居中
|
||||
win.style.top = (this.game.stage.canvas.height - win.offsetHeight)/2 + 'px';
|
||||
win.style.left = (this.game.stage.canvas.width - win.offsetWidth)/2 + 'px';
|
||||
warp.style.opacity = '1';
|
||||
|
||||
this.update();
|
||||
};
|
||||
|
||||
CardDialog.prototype.close = function () {
|
||||
this.hidden = true;
|
||||
this.cardButtons.length = 0;
|
||||
this.stage.removeAllChildren();
|
||||
this.warpDiv.style.visibility = 'hidden';
|
||||
};
|
||||
|
||||
CardDialog.prototype.update = function () {
|
||||
if (this.hidden) return;
|
||||
var changed = false;
|
||||
this.stage.children.forEach(function (bitmap) {
|
||||
if (bitmap.update()) changed = true;
|
||||
},this);
|
||||
if (changed) {
|
||||
this.stage.update();
|
||||
}
|
||||
};
|
42
CardDialogLayer.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
'use strict';
|
||||
|
||||
function CardDialogLayer (game,stage) {
|
||||
this.game = game;
|
||||
this.stage = stage;
|
||||
|
||||
this.div = stage.canvas.parentElement;
|
||||
this.scrollDiv = this.div.parentElement;
|
||||
}
|
||||
|
||||
CardDialogLayer.prototype.show = function (cards,callbacks) {
|
||||
var width = Card.WIDTH*2;
|
||||
var height = Card.HEIGHT*2;
|
||||
var space = 10;
|
||||
var totalWidth = (width + 2*space) * 3;
|
||||
var totalHeight = (height + 2*space) * Math.ceil(this.cards.length/3);
|
||||
this.cards.forEach(function (card,i) {
|
||||
var img = this.game.getImageByCid(card.cid);
|
||||
var bitmap = new CardBitmap(card.cid,img);
|
||||
var row = i%3; // 第row行 (下标从0开始);
|
||||
var col = Math.floor(i/3); // 第col列 (下标从0开始);
|
||||
bitmap.x = row*(width+2*space) + space;
|
||||
bitmap.y = col*(height+2*space) + space;
|
||||
bitmap.setWidthHeight(width,height);
|
||||
bitmap.on('click',callbacks[i]);
|
||||
this.stage.addChild(bitmap);
|
||||
},this);
|
||||
this.stage.canvas.width = totalWidth;
|
||||
this.stage.canvas.height = totalHeight;
|
||||
this.stage.update();
|
||||
|
||||
var div = this.div;
|
||||
var scrollDiv = this.scrollDiv;
|
||||
div.style.opacity = '0';
|
||||
div.style.visibility = 'visible';
|
||||
// 消灭水平滚动条
|
||||
scrollDiv.style.width = totalWidth + scrollDiv.offsetWidth - scrollDiv.clientWidth + 'px';
|
||||
// 居中
|
||||
scrollDiv.style.top = (this.stage.canvas.height - scrollDiv.offsetHeight)/2 + 'px';
|
||||
scrollDiv.style.left = (this.stage.canvas.width - scrollDiv.offsetWidth)/2 + 'px';
|
||||
div.style.opacity = '1';
|
||||
};
|
115244
CardInfo.js
Normal file
19
CardInfo_ru.js
Normal file
10
Charging.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>WEBXOSS收费标准</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>放心,WEBXOSS将保持免费.</p>
|
||||
</body>
|
||||
</html>
|
67
ChatManager.js
Normal file
|
@ -0,0 +1,67 @@
|
|||
'use strict';
|
||||
|
||||
function ChatManager (socket) {
|
||||
this.socket = socket;
|
||||
this.dialogue = document.getElementById('chat-dialogue');
|
||||
this.input = document.getElementById('chat-input');
|
||||
|
||||
// socket.on('chat feedback',this.receiveFeedback.bind(this));
|
||||
// socket.on('chat',this.onChat.bind(this));
|
||||
this.input.onkeypress = function (event) {
|
||||
var keyCode = event.keyCode || event.which || event.charCode;
|
||||
if (keyCode !== 13) return;
|
||||
this.sendMsg(this.input.value);
|
||||
this.input.value = null;
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
// ChatManager.prototype.receiveFeedback = function (msg) {
|
||||
// var chatCount = sessionStorage.getItem('chat count') || 0;
|
||||
// chatCount++;
|
||||
// sessionStorage.setItem('chat count',chatCount);
|
||||
// this.addMsg(msg,'self');
|
||||
// };
|
||||
|
||||
// ChatManager.prototype.onChat = function (msgObj) {
|
||||
// this.addMsg(msg.nickname+':' + msg.msg,'opponent');
|
||||
// };
|
||||
|
||||
ChatManager.prototype.sendMsg = function (msg) {
|
||||
if (!msg) return;
|
||||
this.socket.emit('chat',msg);
|
||||
};
|
||||
|
||||
ChatManager.prototype.addSysMsg = function (msg) {
|
||||
var div = document.createElement('div');
|
||||
div.classList.add('sys');
|
||||
div.textContent = msg;
|
||||
this.dialogue.appendChild(div);
|
||||
this.dialogue.scrollTop = this.dialogue.scrollHeight;
|
||||
};
|
||||
|
||||
ChatManager.prototype.addMsg = function (name,content,isOpponent,isSpectator) {
|
||||
var div = document.createElement('div');
|
||||
if (isOpponent) div.classList.add('opponent');
|
||||
if (isSpectator) div.classList.add('spectator');
|
||||
|
||||
var spanName = document.createElement('span');
|
||||
spanName.classList.add('name');
|
||||
spanName.textContent = name;
|
||||
|
||||
var spanContent = document.createElement('span');
|
||||
spanContent.classList.add('content');
|
||||
spanContent.textContent = content;
|
||||
|
||||
div.appendChild(spanName);
|
||||
div.appendChild(spanContent);
|
||||
this.dialogue.appendChild(div);
|
||||
|
||||
if (this.dialogue.children.length > 64) {
|
||||
this.dialogue.removeChild(this.dialogue.firstChild);
|
||||
}
|
||||
this.dialogue.scrollTop = this.dialogue.scrollHeight;
|
||||
};
|
||||
|
||||
ChatManager.prototype.clear = function () {
|
||||
this.dialogue.innerHTML = '';
|
||||
};
|
3
DeckEditor.appcache
Normal file
|
@ -0,0 +1,3 @@
|
|||
CACHE MANIFEST
|
||||
|
||||
# 2015/04/06 23:59:53
|
1
DeckEditor/Deck.min.js
vendored
Normal file
8
DeckEditor/DeckEditor.appcache
Normal file
|
@ -0,0 +1,8 @@
|
|||
CACHE MANIFEST
|
||||
|
||||
CACHE:
|
||||
|
||||
NETWORK:
|
||||
*
|
||||
|
||||
# 2016/03/07 01:46:04
|
1
DeckEditor/DeckEditor.js
Normal file
583
DeckEditor/Rules.js
Normal file
|
@ -0,0 +1,583 @@
|
|||
'use strict';
|
||||
|
||||
function TextualRule (prop,map,exact) {
|
||||
this.prop = prop;
|
||||
this.map = map;
|
||||
this.exact = exact;
|
||||
}
|
||||
TextualRule.prototype.parse = function (words) {
|
||||
var keywords = [];
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
var word = words[i];
|
||||
var keyword = this.parseWord(word);
|
||||
if (!keyword) continue;
|
||||
keywords.push(keyword);
|
||||
words.splice(i,1);
|
||||
i--;
|
||||
}
|
||||
var prop = this.prop;
|
||||
var exact = this.exact;
|
||||
return function filter (info) {
|
||||
if (!keywords.length) return true;
|
||||
return keywords.some(function (keyword) {
|
||||
var value = info[prop].toLowerCase();
|
||||
if (exact) {
|
||||
return value === keyword;
|
||||
} else {
|
||||
return value.indexOf(keyword) !== -1;
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
TextualRule.prototype.parseWord = function (word) {
|
||||
for (var keyword in this.map) {
|
||||
var matchWords = this.map[keyword];
|
||||
if (matchWords.some(function (matchWord) {
|
||||
return word === Localize.traditionalize(matchWord);
|
||||
},this)) {
|
||||
return keyword;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 枚举型规则,包括:
|
||||
// ColorRule,TypeRule,RarityRule
|
||||
// 匹配例子:
|
||||
// "白 LRIG SR 红"
|
||||
// "白色 精灵 lr red"
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
var ColorRule = new TextualRule('color',{
|
||||
'colorless': ['colorless','无','无色','無','incolore'],
|
||||
'white': ['white','白','白色','白','белая','bianco'],
|
||||
'black': ['black','黑','黑色','黒','чёрная','nero'],
|
||||
'red': ['red','红','红色','赤','красная','rosso'],
|
||||
'blue': ['blue','蓝','蓝色','青','синяя','blu'],
|
||||
'green': ['green','绿','绿色','緑','зелёная','verde']
|
||||
},false);
|
||||
var TypeRule = new TextualRule('cardType',{
|
||||
'lrig': ['l','lrig','分身','ルリグ','идел'],
|
||||
'signi': ['s','signi','精灵','シグニ','запись'],
|
||||
'spell': ['spell','魔法','スペル','магия'],
|
||||
'arts': ['arts','必杀','技艺','アーツ','умение'],
|
||||
'resona': ['resona','共鸣','レゾナ','отголосок']
|
||||
},true);
|
||||
var RarityRule = new TextualRule('rarity',{
|
||||
'c': ['c'],
|
||||
'r': ['r'],
|
||||
'lc': ['lc'],
|
||||
'sr': ['sr'],
|
||||
'lr': ['lr'],
|
||||
'st': ['st'],
|
||||
'pr': ['pr'],
|
||||
'sp': ['sp']
|
||||
},true);
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 效果(能力)型规则:
|
||||
// SkillRule
|
||||
// 匹配例子:
|
||||
// "常","常时","常时效果","常时能力"
|
||||
// "※","爆发","爆发效果","迸发","迸发效果"
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
var SkillRule = {};
|
||||
SkillRule.parse = function (words) {
|
||||
var effectProps = [];
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
var word = words[i];
|
||||
var effectProp = this.parseWord(word);
|
||||
if (!effectProp) continue;
|
||||
effectProps.push(effectProp);
|
||||
words.splice(i,1);
|
||||
i--;
|
||||
}
|
||||
return function filter (info) {
|
||||
if (!effectProps.length) return true;
|
||||
info = CardInfo[info.cid];
|
||||
return effectProps.some(function (effectProp) {
|
||||
var effectTexts = info[effectProp];
|
||||
return effectTexts && effectTexts.length;
|
||||
});
|
||||
};
|
||||
};
|
||||
SkillRule.parseWord = TextualRule.prototype.parseWord;
|
||||
SkillRule.map = {
|
||||
'constEffectTexts': [
|
||||
'【常】','常','常时','常时效果','常時能力',
|
||||
'【常】','常','常時','常時效果','常時能力',
|
||||
'[constant]','const','constant',
|
||||
'[постоянно]','постоянно'
|
||||
],
|
||||
'startUpEffectTexts': [
|
||||
'【出】','出','出场','出场效果','出场能力',
|
||||
'【出】','出','出現','出現效果','出現能力',
|
||||
'[on-play]','[onplay]','on-play','onplay',
|
||||
'[при вводе]','при вводе'
|
||||
],
|
||||
'actionEffectTexts': [
|
||||
'【起】','起','起动','起动效果','起动能力',
|
||||
'【起】','起','起動','起動效果','起動能力',
|
||||
'[action]','action',
|
||||
'[действие]','действие'
|
||||
],
|
||||
'burstEffectTexts': [
|
||||
'【※】','※','爆发','迸发','爆发效果','迸发效果','生命爆发','生命迸发','生命爆发效果','生命迸发效果',
|
||||
'ライフバースト','バースト',
|
||||
'burst','lifeburst','lb',
|
||||
'вспышка','жизненная вспышка'
|
||||
]
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 无迸发规则:
|
||||
// NoBurstRule
|
||||
// 匹配例子:
|
||||
// "无爆发","noburst"
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
var NoBurstRule = {};
|
||||
NoBurstRule.parse = function (words) {
|
||||
var matched = false;
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
var word = words[i];
|
||||
if (!this.parseWord(word)) continue;
|
||||
matched = true;
|
||||
words.splice(i,1);
|
||||
i--;
|
||||
}
|
||||
return function filter (info) {
|
||||
if (!matched) return true;
|
||||
info = CardInfo[info.cid];
|
||||
return (info.cardType === 'SIGNI' || info.cardType === 'SPELL') &&
|
||||
(!info.burstEffectTexts || !info.burstEffectTexts.length);
|
||||
};
|
||||
};
|
||||
NoBurstRule.parseWord = TextualRule.prototype.parseWord;
|
||||
NoBurstRule.map = {
|
||||
'burstEffectTexts': [
|
||||
'无爆发','无迸发','无爆发效果','无迸发效果','无生命爆发','无生命迸发','无生命爆发效果','无生命迸发效果',
|
||||
'noburst',
|
||||
'ライフバースト-','バースト-',
|
||||
'迸发-','爆发-',
|
||||
'burst-','lifeburst-','lb-',
|
||||
'вспышка-','жизненная вспышка-'
|
||||
]
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CROSS规则:
|
||||
// CrossRule
|
||||
// 匹配例子:
|
||||
// "cross","交错","クロス"等
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
var CrossRule = {};
|
||||
CrossRule.parse = function (words) {
|
||||
var matched = false;
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
var word = words[i];
|
||||
if (!this.parseWord(word)) continue;
|
||||
matched = true;
|
||||
words.splice(i,1);
|
||||
i--;
|
||||
}
|
||||
return function filter (info) {
|
||||
if (!matched) return true;
|
||||
info = CardInfo[info.cid];
|
||||
return (info.cardType === 'SIGNI') &&
|
||||
(info.crossLeft || info.crossRight);
|
||||
};
|
||||
};
|
||||
CrossRule.parseWord = TextualRule.prototype.parseWord;
|
||||
CrossRule.map = {
|
||||
'cross': [
|
||||
'cross','交错','クロス',
|
||||
'[cross]','>cross<','【cross】','【交错】','【クロス】','[связь]'
|
||||
]
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 时点规则:
|
||||
// TimmingRule
|
||||
// 匹配例子:
|
||||
// "【主要阶段】","主要阶段"
|
||||
// "【魔法切入】","魔法切入"
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
var TimmingRule = {};
|
||||
TimmingRule.parse = function (words) {
|
||||
var timmings = [];
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
var word = words[i];
|
||||
var timming = this.parseWord(word);
|
||||
if (!timming) continue;
|
||||
timmings.push(timming);
|
||||
words.splice(i,1);
|
||||
i--;
|
||||
}
|
||||
return function filter (info) {
|
||||
if (!timmings.length) return true;
|
||||
return timmings.some(function (timming) {
|
||||
if (!info.timmings) return false;
|
||||
return inArr(timming,info.timmings);
|
||||
});
|
||||
};
|
||||
};
|
||||
TimmingRule.parseWord = TextualRule.prototype.parseWord;
|
||||
TimmingRule.map = {
|
||||
'mainPhase': [
|
||||
'主要阶段','【主要阶段】','主要',
|
||||
'メインフェイズ','【メインフェイズ】',
|
||||
'[mainphase]','mainphase','main',
|
||||
'[основнаяфаза]','основнаяфаза','основная'
|
||||
],
|
||||
'attackPhase': [
|
||||
'攻击阶段','【攻击阶段】','攻击',
|
||||
'アタックフェイズ','【アタックフェイズ】',
|
||||
'[attackphase]','attackphase','attack',
|
||||
'[фазаатаки]','фазаатаки','атака'
|
||||
],
|
||||
'spellCutIn': [
|
||||
'魔法切入','【魔法切入】','切入',
|
||||
'スペルカットイン','【スペルカットイン】',
|
||||
'[spellcut-in]','[cut-in]','[spellcutin]','[cutin]','spellcutin','cutin','cut',
|
||||
'[ответнамагию]','[ответ]','ответнамагию','ответ'
|
||||
]
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 限定规则:
|
||||
// LimitingRule
|
||||
// 匹配例子:
|
||||
// "小玉"
|
||||
// "小玉+"
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
var LimitingRule = {};
|
||||
LimitingRule.parse = function (words) {
|
||||
var matchedClasses = [];
|
||||
var flagNoLimiting = false;
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
var word = words[i];
|
||||
var classes = [
|
||||
'タマ','花代','ユヅキ','ピルルク','エルドラ','ミルルン','緑子',
|
||||
'アン','ウリス','イオナ','ウムル','リメンバ','タウィル','サシェ',
|
||||
'ミュウ','アイヤイ','アルフォウ','ハナレ'
|
||||
];
|
||||
for (var j = 0; j < classes.length; j++) {
|
||||
var cls = classes[j];
|
||||
var matched = false;
|
||||
var localizedClass = Localize('class',cls).toLowerCase();
|
||||
if (word === localizedClass) {
|
||||
matched = true;
|
||||
} else if (word === localizedClass+'+') {
|
||||
matched = true;
|
||||
flagNoLimiting = true;
|
||||
}
|
||||
if (matched) {
|
||||
matchedClasses.push(cls);
|
||||
words.splice(i,1);
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return function filter (info) {
|
||||
if (!matchedClasses.length) return true;
|
||||
if (info.cardType === 'LRIG') {
|
||||
return matchedClasses.some(function (cls) {
|
||||
if (!info.classes) return false;
|
||||
return inArr(cls,info.classes);
|
||||
},this);
|
||||
}
|
||||
if (!info.limiting) return flagNoLimiting;
|
||||
return inArr(info.limiting,matchedClasses);
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 类别规则:
|
||||
// ClassRule
|
||||
// 匹配例子:
|
||||
// "精武"
|
||||
// "武装"
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
var ClassRule = {};
|
||||
ClassRule.parse = function (words) {
|
||||
var matchedClasses = [];
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
var word = words[i];
|
||||
var classes = [
|
||||
'精像','天使','悪魔','美巧','精武','アーム','ウェポン','遊具',
|
||||
'毒牙','精羅','鉱石','宝石','植物','原子','宇宙','精械','電機',
|
||||
'古代兵器','迷宮','精生','水獣','空獣','地獣','龍獣','凶蟲','精元'
|
||||
];
|
||||
for (var j = 0; j < classes.length; j++) {
|
||||
var cls = classes[j];
|
||||
if (word === Localize('class',cls).toLowerCase().replace(' ','')) {
|
||||
matchedClasses.push(cls);
|
||||
words.splice(i,1);
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return function filter (info) {
|
||||
if (!matchedClasses.length) return true;
|
||||
return matchedClasses.some(function (cls) {
|
||||
if (!info.classes) return false;
|
||||
return inArr(cls,info.classes);
|
||||
},this);
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 数值型规则,包括:
|
||||
// PowerRule,LevelRule,LimitRule
|
||||
// 匹配格式:
|
||||
// 相等: "关键字:=数值"
|
||||
// 大于: "关键字:>=数值" 或 "关键字:数值+"
|
||||
// 小于: "关键字:<=数值" 或 "关键字:数值-"
|
||||
// 范围: "关键字:min~max" 或 "关键字:min-max"
|
||||
// (注: 上述的":"和"="可省略.)
|
||||
// 匹配例子(每行等价):
|
||||
// "力量>100","Power>100","Power:100+","Power100+"
|
||||
// "等级=4","level=4","level4","lv4","lv.4"
|
||||
// "界限>7 界限<9","limit7+ 界限9-","界限:7-9","界限7~9"
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
function NumericRule (prop,keywords) {
|
||||
this.prop = prop;
|
||||
this.keywords = keywords;
|
||||
}
|
||||
NumericRule.prototype.parseExpression = function (str) {
|
||||
var match;
|
||||
// 相等
|
||||
match = str.match(/^=*(\d+)$/);
|
||||
if (match) {
|
||||
var num = parseInt(match[1]);
|
||||
return [num,num];
|
||||
}
|
||||
// 大于
|
||||
match = str.match(/^>=*(\d+)\+?$/);
|
||||
if (!match) match = str.match(/^(\d+)\+$/);
|
||||
if (match) {
|
||||
var num = parseInt(match[1]);
|
||||
return [num,Infinity];
|
||||
}
|
||||
// 小于
|
||||
match = str.match(/^<=*(\d+)\-?$/);
|
||||
if (!match) match = str.match(/^(\d+)\-$/);
|
||||
if (match) {
|
||||
var num = parseInt(match[1]);
|
||||
return [-Infinity,num];
|
||||
}
|
||||
// 范围
|
||||
match = str.match(/^(\d+)[\-\~](\d+)$/);
|
||||
if (match) {
|
||||
var a = parseInt(match[1]);
|
||||
var b = parseInt(match[2]);
|
||||
return [a,b];
|
||||
}
|
||||
return null
|
||||
};
|
||||
NumericRule.prototype.parseWord = function (word) {
|
||||
for (var i = 0; i < this.keywords.length; i++) {
|
||||
var keyword = Localize.traditionalize(this.keywords[i]);
|
||||
if (word.indexOf(keyword) === 0) {
|
||||
word = word.slice(keyword.length).replace(/^:/,'');
|
||||
return this.parseExpression(word);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
NumericRule.prototype.parse = function (words) {
|
||||
var ranges = [];
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
var word = words[i];
|
||||
var range = this.parseWord(word);
|
||||
if (!range) continue;
|
||||
ranges.push(range);
|
||||
words.splice(i,1);
|
||||
i--;
|
||||
}
|
||||
var prop = this.prop;
|
||||
return function filter (info) {
|
||||
if (!ranges.length) return true;
|
||||
if ((info.cardType === 'SPELL') || (info.cardType === 'ARTS')) {
|
||||
return false;
|
||||
}
|
||||
return ranges.every(function (range) {
|
||||
var value = info[prop];
|
||||
var min = range[0];
|
||||
var max = range[1];
|
||||
return (value >= min) && (value <= max);
|
||||
});
|
||||
};
|
||||
};
|
||||
var PowerRule = new NumericRule('power',['力量','パワー','power','сила']);
|
||||
var LevelRule = new NumericRule('level',['等级','レベル','level','lv.','lv','уровень','livello']);
|
||||
var LimitRule = new NumericRule('limit',['界限','リミット','limite','limit','ограничение']);
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 数字规则: NumberRule.
|
||||
// 匹配说明:
|
||||
// 力量和等级的关键字可以省略,此时用NumberRule匹配.
|
||||
// 数字小于10,则匹配为等级,否则匹配为力量.
|
||||
// 匹配例子:
|
||||
// "1000+ 3-" // 等价于"power>1000 level<3"
|
||||
// ">3 2000~3000" // 等价于"level>3 power:2000~3000"
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
var NumberRule = new NumericRule('',['']);
|
||||
NumberRule.parse = function (words) {
|
||||
var ranges = [];
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
var word = words[i];
|
||||
var range = this.parseWord(word);
|
||||
if (!range) continue;
|
||||
ranges.push(range);
|
||||
words.splice(i,1);
|
||||
i--;
|
||||
}
|
||||
return function filter (info) {
|
||||
return ranges.every(function (range) {
|
||||
if ((info.cardType === 'SPELL') || (info.cardType === 'ARTS')) return false;
|
||||
function matchLevel (num) {
|
||||
return !isFinite(num) || (num < 10);
|
||||
}
|
||||
var value = range.every(matchLevel)? info.level : info.power;
|
||||
var min = range[0];
|
||||
var max = range[1];
|
||||
return (value >= min) && (value <= max);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 画师规则: IllustRule.
|
||||
// 匹配例子:
|
||||
// "画师:pop"
|
||||
// "Illust:藤真拓哉"
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
var IllustRule = {};
|
||||
IllustRule.parseWord = function (word) {
|
||||
var match = word.match(/illust:?(.+)/);
|
||||
if (!match) match = word.match(/画师:?(.+)/);
|
||||
if (!match) match = word.match(/畫師:?(.+)/);
|
||||
if (!match) return null;
|
||||
return match[1];
|
||||
}
|
||||
IllustRule.parse = function (words) {
|
||||
var illusts = [];
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
var word = words[i];
|
||||
var illust = this.parseWord(word);
|
||||
if (!illust) continue;
|
||||
illusts.push(illust);
|
||||
words.splice(i,1);
|
||||
i--;
|
||||
}
|
||||
return function filter (info) {
|
||||
if (!illusts.length) return true;
|
||||
return illusts.some(function (illust) {
|
||||
var cardIllust = info.illust.toLowerCase();
|
||||
return cardIllust.indexOf(illust) !== -1;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ID规则: WxidRule.
|
||||
// 匹配例子:
|
||||
// "WD01-001","wd01-001","wD01001" // 仅匹配"WD01-001"
|
||||
// "wx02-01","WX0201" // 匹配"WX02-010"至"WX02-019"
|
||||
// "wd03-","WD03" // 匹配"WD03"的所有卡
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
var WxidRule = {};
|
||||
WxidRule.parseWord = function (word) {
|
||||
var match = word.match(/^(wx\d{2}|wd\d{2}|pr|sp\d{2})-?(\d{0,3})$/);
|
||||
if (!match) return null;
|
||||
return match[1] + '-' + match[2];
|
||||
}
|
||||
WxidRule.parse = function (words) {
|
||||
var idLimits = [];
|
||||
for (var i = 0; i < words.length; i++) {
|
||||
var word = words[i];
|
||||
var limit = this.parseWord(word);
|
||||
if (!limit) continue;
|
||||
idLimits.push(limit);
|
||||
words.splice(i,1);
|
||||
i--;
|
||||
}
|
||||
return function filter (info) {
|
||||
if (!idLimits.length) return true;
|
||||
return idLimits.some(function (limit) {
|
||||
return info.wxid.toLowerCase().indexOf(limit) === 0;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 卡名规则: NameRule.
|
||||
// 匹配例子:
|
||||
// "喷流 知识" // 卡名同时包含"喷流"和"知识".
|
||||
// "喷流|知识" // 卡名包含"喷流"或"知识".
|
||||
// "喷流||知识" // 卡名包含"喷流"或"知识".
|
||||
// "喷流||的||知识" // 卡名包含"喷流"或"知识"或"的".
|
||||
//
|
||||
///////////////////////////////////////////////////////////////
|
||||
var NameRule = {};
|
||||
NameRule.dotRegex =
|
||||
/[\u00B7\u0387\u05BC\u2022\u2027\u2219\u22C5\u30FB\uFF0E\uFF65]/g;
|
||||
NameRule.fullWidth =
|
||||
'0123456789=@' +
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
|
||||
'abcdefghijklmnopqrstuvwxyz';
|
||||
NameRule.halfWidth =
|
||||
'0123456789=@' +
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
|
||||
'abcdefghijklmnopqrstuvwxyz';
|
||||
NameRule.normalizeString = function (str) {
|
||||
var chars = str.replace(this.dotRegex,'').split('');
|
||||
chars.forEach(function (char,idx) {
|
||||
var i = this.fullWidth.indexOf(char);
|
||||
chars[idx] = this.halfWidth[i] || char;
|
||||
},this);
|
||||
return chars.join('').toLowerCase();
|
||||
};
|
||||
NameRule.parse = function (words) {
|
||||
var wordSets = [];
|
||||
words.forEach(function (word) {
|
||||
wordSets.push(word.split(/\|+/));
|
||||
},this);
|
||||
words.length = 0;
|
||||
var that = this;
|
||||
return function filter (info) {
|
||||
return wordSets.every(function (wordSet) {
|
||||
if (!wordSet.length) return true;
|
||||
return wordSet.some(function (word) {
|
||||
var name = that.normalizeString(Localize.cardName(info));
|
||||
var w = that.normalizeString(word);
|
||||
return (name.indexOf(w) !== -1);
|
||||
},this);
|
||||
},this);
|
||||
};
|
||||
};
|
71
DeckEditor/SearchTips.html
Normal file
|
@ -0,0 +1,71 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Search Tips</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
<style>
|
||||
body,html {
|
||||
font-family: 'Microsoft YaHei','WenQuanYi Micro Hei',sans-serif;
|
||||
}
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0 0 0 1.5em;
|
||||
list-style-type: none;
|
||||
}
|
||||
#examples > li {
|
||||
margin: 0.5em 0;
|
||||
padding-left: 0.5em;
|
||||
border-left: #888 2px solid;
|
||||
}
|
||||
code {
|
||||
font-family: monospace;
|
||||
white-space: nowrap;
|
||||
padding: 0.2em 0.5em;
|
||||
background-color: #F0F0F0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<section>
|
||||
<p>在WEBXOSS中,您可以按卡牌的编号,名字,类型,颜色,等级等进行组合搜索.</p>
|
||||
<p>搜索示例:</p>
|
||||
<ul id="examples">
|
||||
<li>
|
||||
ID为WX01-001的卡: <code>WX01-001</code>
|
||||
</li>
|
||||
<li>
|
||||
预组包02: <code>WD02</code>
|
||||
</li>
|
||||
<li>
|
||||
白色或红色的精灵: <code>白 红 S</code>
|
||||
</li>
|
||||
<li>
|
||||
蓝色的0级pr分身: <code>蓝色 0 L pr</code>
|
||||
</li>
|
||||
<li>
|
||||
使用时点包括攻击阶段的必杀: <code>必杀 攻击阶段</code>
|
||||
</li>
|
||||
<li>
|
||||
力量3000以上,等级2的精灵: <code>3000+ 2</code>
|
||||
</li>
|
||||
<li>
|
||||
小玉限定的有爆发效果的卡: <code>小玉 爆发</code>
|
||||
</li>
|
||||
<li>
|
||||
小玉限定或无限定的,没有爆发效果的卡: <code>小玉+ 爆发-</code>
|
||||
</li>
|
||||
<li>
|
||||
类别为"地兽"的精灵: <code>地兽</code>
|
||||
</li>
|
||||
<li>
|
||||
有出场效果和常时效果的卡: <code>出 常</code>
|
||||
</li>
|
||||
<li>
|
||||
画师是POP的卡: <code>画师:POP</code>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
71
DeckEditor/SearchTips_en.html
Normal file
|
@ -0,0 +1,71 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Search Tips</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
<style>
|
||||
body,html {
|
||||
font-family: Arial,Helvetica,sans-serif;
|
||||
}
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0 0 0 1.5em;
|
||||
list-style-type: none;
|
||||
}
|
||||
#examples > li {
|
||||
margin: 0.5em 0;
|
||||
padding-left: 0.5em;
|
||||
border-left: #888 2px solid;
|
||||
}
|
||||
code {
|
||||
font-family: monospace;
|
||||
white-space: nowrap;
|
||||
padding: 0.2em 0.5em;
|
||||
background-color: #F0F0F0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<section>
|
||||
<p>In WEBXOSS, you can search card by its id, name, type, color, level, etc, combined.</p>
|
||||
<p>Examples:</p>
|
||||
<ul id="examples">
|
||||
<li>
|
||||
Card with ID WX01-001: <code>WX01-001</code>
|
||||
</li>
|
||||
<li>
|
||||
Pre-built deck 02: <code>WD02</code>
|
||||
</li>
|
||||
<li>
|
||||
White or red SIGNI: <code>white red S</code>
|
||||
</li>
|
||||
<li>
|
||||
Level 0, blue, PR LRIG: <code>blue 0 L pr</code>
|
||||
</li>
|
||||
<li>
|
||||
ARTS with use timing of attack phase: <code>ARTS AttackPhase</code>
|
||||
</li>
|
||||
<li>
|
||||
Level 2 SIGNI with power 3000 or above: <code>3000+ 2</code>
|
||||
</li>
|
||||
<li>
|
||||
Tama only with life burst: <code>tama burst</code>
|
||||
</li>
|
||||
<li>
|
||||
Tama only or unlimited, without life burst: <code>tama+ burst-</code>
|
||||
</li>
|
||||
<li>
|
||||
<Earth Beast> SIGNI: <code>EarthBeast</code>
|
||||
</li>
|
||||
<li>
|
||||
With [On-Play] and [Constant] abilities: <code>OnPlay Constant</code>
|
||||
</li>
|
||||
<li>
|
||||
Illust by POP: <code>Illust:POP</code>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
71
DeckEditor/SearchTips_it.html
Normal file
|
@ -0,0 +1,71 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Search Tips</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
<style>
|
||||
body,html {
|
||||
font-family: Arial,Helvetica,sans-serif;
|
||||
}
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0 0 0 1.5em;
|
||||
list-style-type: none;
|
||||
}
|
||||
#examples > li {
|
||||
margin: 0.5em 0;
|
||||
padding-left: 0.5em;
|
||||
border-left: #888 2px solid;
|
||||
}
|
||||
code {
|
||||
font-family: monospace;
|
||||
white-space: nowrap;
|
||||
padding: 0.2em 0.5em;
|
||||
background-color: #F0F0F0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<section>
|
||||
<p>In WEBXOSS, puoi ricercare le carte tramite il loro id, nome, tipo, colore, livello, etc, contemporaneamente.</p>
|
||||
<p>Esempi:</p>
|
||||
<ul id="examples">
|
||||
<li>
|
||||
Carte con id WX01-001: <code>WX01-001</code>
|
||||
</li>
|
||||
<li>
|
||||
Deck precostruiti 02: <code>WD02</code>
|
||||
</li>
|
||||
<li>
|
||||
SIGNI bianchi o rossi: <code>white red S</code>
|
||||
</li>
|
||||
<li>
|
||||
Livello 0, blue, PR LRIG: <code>blue 0 L pr</code>
|
||||
</li>
|
||||
<li>
|
||||
ARTS attivabili nell'attack phase: <code>ARTS AttackPhase</code>
|
||||
</li>
|
||||
<li>
|
||||
SIGNI livello 2 con potere 3000 o piu: <code>3000+ 2</code>
|
||||
</li>
|
||||
<li>
|
||||
Tama only con life burst: <code>tama burst</code>
|
||||
</li>
|
||||
<li>
|
||||
Tama only o senza restrizioni senza lifeburst: <code>tama+ burst-</code>
|
||||
</li>
|
||||
<li>
|
||||
<Earth Beast> SIGNI: <code>EarthBeast</code>
|
||||
</li>
|
||||
<li>
|
||||
Con abilita [On-Play] e [Constant]: <code>OnPlay Constant</code>
|
||||
</li>
|
||||
<li>
|
||||
Illustrate da POP: <code>Illust:POP</code>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
36
DeckEditor/Searcher.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
'use strict';
|
||||
function Searcher () {
|
||||
this.infos = [];
|
||||
for (var pid in CardInfo) {
|
||||
this.infos.push(CardInfo[pid]);
|
||||
}
|
||||
this.rules = [
|
||||
ColorRule,
|
||||
CrossRule,
|
||||
TypeRule,
|
||||
RarityRule,
|
||||
SkillRule,
|
||||
NoBurstRule,
|
||||
// LifeBurstRule,
|
||||
TimmingRule,
|
||||
LimitingRule,
|
||||
ClassRule,
|
||||
PowerRule,
|
||||
LevelRule,
|
||||
LimitRule,
|
||||
NumberRule,
|
||||
IllustRule,
|
||||
WxidRule,
|
||||
NameRule
|
||||
];
|
||||
}
|
||||
Searcher.prototype.search = function (str) {
|
||||
// if (!str) return [];
|
||||
var words = str.toLowerCase().split(/\s+/);
|
||||
var filters = this.rules.map(function (rule) {
|
||||
return rule.parse(words);
|
||||
},this);
|
||||
return filters.reduce(function (results,filter) {
|
||||
return results.filter(filter);
|
||||
},this.infos);
|
||||
};
|
234
DeckEditor/editor.css
Normal file
|
@ -0,0 +1,234 @@
|
|||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
/*font-family: 'Hiragino Sans GB','Microsoft YaHei','WenQuanYi Micro Hei',sans-serif;*/
|
||||
font-family: 'Microsoft YaHei','WenQuanYi Zen Hei',sans-serif;
|
||||
background-image: url('../background/bg.png');
|
||||
}
|
||||
body {
|
||||
margin: 5px 5px 0;
|
||||
padding: 0;
|
||||
width: 1100px;
|
||||
}
|
||||
table, th, td {
|
||||
border: 1px solid black;
|
||||
padding: 0;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0px;
|
||||
}
|
||||
ol,ul,li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
/*#Detail,#Deck,#Search {
|
||||
min-height: 720px;
|
||||
}*/
|
||||
|
||||
#div-search-results {
|
||||
max-height: 600px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#Detail {
|
||||
float: left;
|
||||
width: 260px;
|
||||
}
|
||||
|
||||
#detail-card-figure {
|
||||
height: 349px;
|
||||
}
|
||||
#detail-card-image {
|
||||
border-radius: 4%;
|
||||
}
|
||||
#detail-card-data {
|
||||
height: 340px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
position: relative;
|
||||
}
|
||||
#detail-card-wxid {
|
||||
font-size: small;
|
||||
}
|
||||
#detail-card-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
#detail-card-name > a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
#detail-card-name > a:active {
|
||||
color: red;
|
||||
}
|
||||
#detail-card-limiting {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0.5em;
|
||||
}
|
||||
#detail-table {
|
||||
width: 100%;
|
||||
white-space: pre-line;
|
||||
}
|
||||
#detail-table[lang="ru"] {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
#Deck {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 620px;
|
||||
}
|
||||
|
||||
#link-back-to-webxoss {
|
||||
position: absolute;
|
||||
right: 1em;
|
||||
top: 1em;
|
||||
color: blue;
|
||||
text-decoration: none;
|
||||
/* font-size: small; */
|
||||
}
|
||||
|
||||
#div-import-warp {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
#div-import-export {
|
||||
position: absolute;
|
||||
width: 500px;
|
||||
top: 10%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
padding: 1em 2em;
|
||||
background-color: white;
|
||||
box-shadow: 0px 0px 38px rgba(0,0,0,0.7);
|
||||
}
|
||||
#textarea-import-export {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 15em;
|
||||
box-sizing: border-box;
|
||||
resize: vertical;
|
||||
}
|
||||
#div-import-footer {
|
||||
text-align: center;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
#div-import-footer > button {
|
||||
margin-left: 0.5em;
|
||||
/* margin-right: 0.5em; */
|
||||
}
|
||||
|
||||
#select-decks,
|
||||
#input-new-deck-name {
|
||||
width: 10em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#main-deck-text-bar,
|
||||
#lrig-deck-text-bar {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
#main-deck-burst {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#main-deck-mayus-room {
|
||||
display: none;
|
||||
text-decoration: none;
|
||||
margin-left: 1em;
|
||||
}
|
||||
#main-deck-mayus-room.invalid {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#main-deck-title,
|
||||
#lrig-deck-title {
|
||||
color: green;
|
||||
transition: color 0.5s,background-color 0.5s;
|
||||
}
|
||||
|
||||
#main-deck-title.invalid,
|
||||
#lrig-deck-title.invalid,
|
||||
#main-deck-mayus-room.invalid {
|
||||
color: red;
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
#main-deck-title::before,
|
||||
#lrig-deck-title::before,
|
||||
#main-deck-mayus-room::before {
|
||||
content: '\2714';
|
||||
}
|
||||
|
||||
#main-deck-title.invalid::before,
|
||||
#lrig-deck-title.invalid::before,
|
||||
#main-deck-mayus-room.invalid::before {
|
||||
content: '\2718';
|
||||
}
|
||||
|
||||
#main-deck-zone img,
|
||||
#lrig-deck-zone img {
|
||||
position: absolute;
|
||||
width: 62px;
|
||||
height: 87px;
|
||||
transition: left 0.3s, top 0.3s;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#main-deck-zone {
|
||||
position: relative;
|
||||
width: 620px;
|
||||
height: 435px;
|
||||
}
|
||||
|
||||
#lrig-deck-zone {
|
||||
position: relative;
|
||||
width: 620px;
|
||||
height: 174px;
|
||||
}
|
||||
|
||||
#Search {
|
||||
float: left;
|
||||
width: 200px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#div-search-tips {
|
||||
text-align: right;
|
||||
}
|
||||
#link-search-tips {
|
||||
font-size: small;
|
||||
color: inherit;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#search-input {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#search-list li {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
#search-list img {
|
||||
width: 127px;
|
||||
height: 176px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#search-show-more {
|
||||
cursor: pointer;
|
||||
color: blue;
|
||||
}
|
523
DeckEditor/editor.js
Normal file
|
@ -0,0 +1,523 @@
|
|||
'use strict';
|
||||
// window.addEventListener('DOMContentLoaded',function () {
|
||||
|
||||
|
||||
var $ = document.getElementById.bind(document);
|
||||
function hide (el) {
|
||||
el.style.display = 'none';
|
||||
}
|
||||
function show (el) {
|
||||
el.style.display = '';
|
||||
}
|
||||
function disable (el) {
|
||||
el.disabled = true;
|
||||
}
|
||||
function enable (el) {
|
||||
el.disabled = false;
|
||||
}
|
||||
function newElement (tag) {
|
||||
var el = document.createElement(tag);
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
el.classList.add(arguments[i]);
|
||||
}
|
||||
return el;
|
||||
}
|
||||
function getImageUrlByPid (pid) {
|
||||
return imageManager.getUrlByPid(pid);
|
||||
}
|
||||
|
||||
|
||||
Localize.init();
|
||||
Localize.DOM('DeckEditor');
|
||||
window.searcher = new Searcher();
|
||||
window.imageManager = new ImageManager('../');
|
||||
window.detail = new CardDetail(imageManager);
|
||||
|
||||
// ====== 搜索开始 ======
|
||||
var results = [];
|
||||
var RESULTS_LENGTH = 20;
|
||||
var _shown = 0;
|
||||
$('search-input').onchange = search;
|
||||
$('search-input').onkeyup = search;
|
||||
function search () {
|
||||
var q = $('search-input').value;
|
||||
results = searcher.search(q);
|
||||
showResults();
|
||||
}
|
||||
function showResults () {
|
||||
_shown = 0;
|
||||
$('search-list').innerHTML = '';
|
||||
showMore();
|
||||
}
|
||||
$('search-show-more').onclick = showMore;
|
||||
function showMore () {
|
||||
for (var i = 0; i < RESULTS_LENGTH; i++) {
|
||||
var idx = _shown;
|
||||
if (idx >= results.length) break;
|
||||
var info = results[idx];
|
||||
var li = newElement('li');
|
||||
var img = new Image();
|
||||
img.src = getImageUrlByPid(info.pid);
|
||||
img.alt = Localize.cardName(info);
|
||||
img.title = Localize.cardName(info);
|
||||
img.onmousemove = showDetail.bind(null,info);
|
||||
img.onclick = addCardByInfo.bind(null,info,false);
|
||||
li.appendChild(img);
|
||||
$('search-list').appendChild(li);
|
||||
_shown++;
|
||||
}
|
||||
|
||||
if (_shown < results.length) {
|
||||
show($('search-show-more'));
|
||||
} else {
|
||||
hide($('search-show-more'));
|
||||
}
|
||||
}
|
||||
function showDetail (info) {
|
||||
detail.show(info.pid);
|
||||
}
|
||||
// ====== 搜索结束 ======
|
||||
|
||||
|
||||
|
||||
// ====== 组卡开始 ======
|
||||
var WIDTH = 62;
|
||||
var HEIGHT = 87;
|
||||
var mainData = {
|
||||
deck: 'main',
|
||||
limit: 50,
|
||||
deckObjs: [],
|
||||
zone: $('main-deck-zone')
|
||||
};
|
||||
var lrigData = {
|
||||
deck: 'lrig',
|
||||
limit: 20,
|
||||
deckObjs: [],
|
||||
zone: $('lrig-deck-zone')
|
||||
};
|
||||
var deckManager = new DeckManager();
|
||||
var deckNames = [];
|
||||
var deckName = '';
|
||||
var deckIndex = -1;
|
||||
var whiteHope = {
|
||||
mainDeck: [
|
||||
112,113,114,115,116,117,118,119,120,121,
|
||||
112,113,114,115,116,117,118,119,120,121,
|
||||
112,113,114,115,116,117,118,119,120,121,
|
||||
112,113,114,115,116,117,118,119,120,121
|
||||
],
|
||||
lrigDeck: [104,105,106,107,108,109,110,111]
|
||||
};
|
||||
updateDeckList();
|
||||
selectDeck(0);
|
||||
function updateDeckList () {
|
||||
$('select-decks').innerHTML = '';
|
||||
deckNames = deckManager.getDeckNames();
|
||||
if (!deckNames.length) {
|
||||
createDeck('WHITE_HOPE',whiteHope);
|
||||
return;
|
||||
}
|
||||
deckNames.forEach(function (name) {
|
||||
var eOption = newElement('option');
|
||||
eOption.textContent = name;
|
||||
$('select-decks').appendChild(eOption);
|
||||
},this);
|
||||
}
|
||||
function loadDeck (name) {
|
||||
var deck = deckManager.loadDeck(name);
|
||||
removeAllCards(mainData);
|
||||
deck.mainDeck.forEach(function (pid) {
|
||||
var info = CardInfo[pid];
|
||||
addCardByInfo(info,true);
|
||||
});
|
||||
removeAllCards(lrigData);
|
||||
deck.lrigDeck.forEach(function (pid) {
|
||||
var info = CardInfo[pid];
|
||||
addCardByInfo(info,true);
|
||||
});
|
||||
updateDeck(mainData);
|
||||
updateDeck(lrigData);
|
||||
}
|
||||
function saveDeck (name) {
|
||||
deckManager.saveDeck(name,getCurrentDeck());
|
||||
}
|
||||
var emptyDeck = {
|
||||
mainDeck: [],
|
||||
lrigDeck: []
|
||||
};
|
||||
$('button-new-deck').onclick = function (event) {
|
||||
if (!$('input-new-deck-name').value) {
|
||||
window.alert(Localize.editor('PLEASE_INPUT_A_DECK_NAME'));
|
||||
$('input-new-deck-name').focus();
|
||||
return;
|
||||
}
|
||||
createDeck($('input-new-deck-name').value,emptyDeck);
|
||||
$('input-new-deck-name').value = '';
|
||||
};
|
||||
$('button-copy-deck').onclick = function (event) {
|
||||
if (!$('input-new-deck-name').value) {
|
||||
window.alert(Localize.editor('PLEASE_INPUT_A_DECK_NAME'));
|
||||
$('input-new-deck-name').focus();
|
||||
return;
|
||||
}
|
||||
createDeck($('input-new-deck-name').value);
|
||||
$('input-new-deck-name').value = '';
|
||||
};
|
||||
function createDeck (name,deck) {
|
||||
if (!name) return false;
|
||||
var idx = deckNames.indexOf(name);
|
||||
if (idx >= 0) {
|
||||
selectDeck(idx);
|
||||
return;
|
||||
}
|
||||
deckManager.createDeck(name,deck || getCurrentDeck());
|
||||
updateDeckList();
|
||||
idx = deckNames.indexOf(name);
|
||||
selectDeck(idx);
|
||||
}
|
||||
$('button-delete-deck').onclick = function (event) {
|
||||
if (window.confirm(Localize.editor('CONFIRM_DELETE_DECK',deckName))) {
|
||||
deleteDeck(deckName);
|
||||
}
|
||||
};
|
||||
function deleteDeck (name) {
|
||||
var idx = deckIndex;
|
||||
deckManager.deleteDeck(name);
|
||||
updateDeckList();
|
||||
if (idx >= deckNames.length) {
|
||||
idx = deckNames.length-1;
|
||||
}
|
||||
selectDeck(idx);
|
||||
}
|
||||
$('select-decks').onchange = function (event) {
|
||||
selectDeck($('select-decks').selectedIndex);
|
||||
};
|
||||
$('button-rename').onclick = function (event) {
|
||||
var newName = window.prompt(Localize.editor('DECK_NAME'),deckName);
|
||||
if (!newName || newName === deckName) return;
|
||||
if (inArr(newName,deckNames)) {
|
||||
window.alert(Localize.editor('DECK_NAME_ALREADY_EXISTS',newName));
|
||||
return;
|
||||
}
|
||||
renameDeck(newName);
|
||||
}
|
||||
function renameDeck (newName) {
|
||||
var oldName = deckName;
|
||||
createDeck(newName);
|
||||
deleteDeck(oldName);
|
||||
}
|
||||
function selectDeck (idx) {
|
||||
deckIndex = idx;
|
||||
deckName = deckNames[idx];
|
||||
loadDeck(deckName);
|
||||
$('select-decks').selectedIndex = idx;
|
||||
}
|
||||
function getCurrentDeck () {
|
||||
var deck = {};
|
||||
deck.mainDeck = mainData.deckObjs.map(function (deckObj) {
|
||||
return deckObj.info.pid;
|
||||
});
|
||||
deck.lrigDeck = lrigData.deckObjs.map(function (deckObj) {
|
||||
return deckObj.info.pid;
|
||||
});
|
||||
return deck;
|
||||
}
|
||||
function dataToPids (data) {
|
||||
return data.deckObjs.map(function (obj) {
|
||||
return obj.info.pid;
|
||||
});
|
||||
}
|
||||
function addCardByInfo (info,dontUpdateOrSave) {
|
||||
var data;
|
||||
if (info.cardType==='LRIG' || info.cardType==='ARTS' || info.cardType==='RESONA') {
|
||||
data = lrigData;
|
||||
} else {
|
||||
data = mainData;
|
||||
}
|
||||
if (data.deckObjs.length >= data.limit) {
|
||||
return;
|
||||
}
|
||||
data.deckObjs.push({
|
||||
idx: data.deckObjs.length,
|
||||
info: info,
|
||||
img: null
|
||||
});
|
||||
if (!dontUpdateOrSave) {
|
||||
updateDeck(data);
|
||||
saveDeck(deckName);
|
||||
}
|
||||
}
|
||||
function removeCardByIndex (data,idx,dontUpdateOrSave) {
|
||||
data.zone.removeChild(data.deckObjs[idx].img);
|
||||
data.deckObjs.splice(idx,1);
|
||||
updateDeck(data);
|
||||
if (!dontUpdateOrSave) saveDeck(deckName);
|
||||
}
|
||||
function removeAllCards (data) {
|
||||
data.zone.innerHTML = '';
|
||||
data.deckObjs.length = 0;
|
||||
}
|
||||
function updateDeck (data) {
|
||||
defaultSort(data);
|
||||
var pids = dataToPids(data);
|
||||
var valid,elTitle;
|
||||
if (data.deck === 'main') {
|
||||
valid = deckManager.checkMainDeck(pids);
|
||||
elTitle = $('main-deck-title');
|
||||
$('main-deck-burst-count').textContent = deckManager.burstCount(pids);
|
||||
} else {
|
||||
valid = deckManager.checkLrigDeck(pids);
|
||||
elTitle = $('lrig-deck-title');
|
||||
}
|
||||
if (valid) {
|
||||
elTitle.classList.remove('invalid');
|
||||
} else {
|
||||
elTitle.classList.add('invalid');
|
||||
}
|
||||
elTitle = $('main-deck-mayus-room');
|
||||
valid = deckManager.checkMayusRoom(dataToPids(mainData).concat(dataToPids(lrigData)));
|
||||
if (valid) {
|
||||
elTitle.classList.remove('invalid');
|
||||
} else {
|
||||
elTitle.classList.add('invalid');
|
||||
}
|
||||
data.deckObjs.forEach(function (obj,idx) {
|
||||
var info = obj.info;
|
||||
var img = obj.img;
|
||||
if (!img) {
|
||||
img = new Image();
|
||||
img.src = getImageUrlByPid(info.pid);
|
||||
img.alt = Localize.cardName(info);
|
||||
img.onmousemove = showDetail.bind(null,info);
|
||||
|
||||
obj.img = img;
|
||||
|
||||
data.zone.appendChild(img);
|
||||
}
|
||||
img.onclick = removeCardByIndex.bind(null,data,idx,false);
|
||||
img.style.left = ((idx%10)*WIDTH) + 'px';
|
||||
img.style.top = (Math.floor(idx/10)*HEIGHT) + 'px';
|
||||
},this);
|
||||
}
|
||||
function defaultSort (data) {
|
||||
data.deckObjs.sort(function (aObj,bObj) {
|
||||
var a = aObj.info;
|
||||
var b = bObj.info;
|
||||
var aIdx = aObj.idx;
|
||||
var bIdx = bObj.idx;
|
||||
if (a.cardType === 'LRIG') {
|
||||
if (b.cardType !== 'LRIG') return -1;
|
||||
if (b.level !== a.level) {
|
||||
return a.level - b.level;
|
||||
}
|
||||
}
|
||||
if (a.cardType === 'ARTS') {
|
||||
if (b.cardType !== 'ARTS') return 1;
|
||||
}
|
||||
if (a.cardType === 'RESONA') {
|
||||
if (b.cardType === 'LRIG') return 1;
|
||||
if (b.cardType === 'ARTS') return -1;
|
||||
if (b.level !== a.level) {
|
||||
return a.level - b.level;
|
||||
}
|
||||
}
|
||||
if (a.cardType === 'SIGNI') {
|
||||
if (b.cardType !== 'SIGNI') return -1;
|
||||
if (a.level !== b.level) {
|
||||
return b.level - a.level;
|
||||
}
|
||||
if (a.power !== b.power) {
|
||||
return a.power - b.power;
|
||||
}
|
||||
}
|
||||
if (a.cardType === 'SPELL') {
|
||||
if (b.cardType !== 'SPELL') return 1;
|
||||
}
|
||||
if (a.cid !== b.cid) {
|
||||
return a.cid - b.cid
|
||||
}
|
||||
return aIdx - bIdx;
|
||||
});
|
||||
data.deckObjs.forEach(function (obj,idx) {
|
||||
obj.idx = idx;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ====== 导入导出开始 ======
|
||||
$('button-import-export').onclick = function (event) {
|
||||
show($('div-import-warp'));
|
||||
$('textarea-import-export').value = '';
|
||||
};
|
||||
$('button-import-export-cancel').onclick = function (event) {
|
||||
hideImpotExport();
|
||||
};
|
||||
function hideImpotExport () {
|
||||
hide($('div-import-warp'));
|
||||
}
|
||||
$('button-text').onclick = function (event) {
|
||||
var text = deckToText(getCurrentDeck());
|
||||
// var doc = window.open().document;
|
||||
// doc.title = deckName;
|
||||
// doc.body.innerText = text;
|
||||
$('textarea-import-export').value = text;
|
||||
$('textarea-import-export').select();
|
||||
}
|
||||
function deckToText (deck) {
|
||||
var text = '';
|
||||
var decks = [
|
||||
deck.lrigDeck,
|
||||
deck.mainDeck.filter(function (pid) {
|
||||
var info = CardInfo[pid];
|
||||
return !(info.burstEffectTexts && info.burstEffectTexts.length);
|
||||
}),
|
||||
deck.mainDeck.filter(function (pid) {
|
||||
var info = CardInfo[pid];
|
||||
return info.burstEffectTexts && info.burstEffectTexts.length;
|
||||
})
|
||||
];
|
||||
decks.forEach(function (deck,idx,arr) {
|
||||
var lastName = '';
|
||||
var count = 0;
|
||||
var decks = [];
|
||||
deck.forEach(function (pid,idx,arr) {
|
||||
var info = CardInfo[pid];
|
||||
var name = Localize.cardName(info);
|
||||
if ((name !== lastName) && (idx !== 0)) {
|
||||
text += count + ' ' + lastName + '\n';
|
||||
lastName = name;
|
||||
count = 1;
|
||||
} else {
|
||||
lastName = name;
|
||||
count++;
|
||||
}
|
||||
if (idx === arr.length-1) {
|
||||
text += count + ' ' + lastName + '\n';
|
||||
}
|
||||
},this);
|
||||
if (idx !== arr.length-1) {
|
||||
text += '——————————\n';
|
||||
}
|
||||
});
|
||||
return text;
|
||||
}
|
||||
$('button-export').onclick = function (event) {
|
||||
var filename = deckName + '.webxoss';
|
||||
var json = deckToJson(getCurrentDeck());
|
||||
download(filename,json);
|
||||
};
|
||||
$('button-export-code').onclick = function (event) {
|
||||
var json = deckToJson(getCurrentDeck());
|
||||
$('textarea-import-export').value = json;
|
||||
$('textarea-import-export').select();
|
||||
};
|
||||
var download = (function () {
|
||||
var a = newElement('a');
|
||||
a.target = '_blank';
|
||||
a.style.position = 'fixed';
|
||||
a.style.width = '0';
|
||||
a.style.height = '0';
|
||||
a.style.overflow = 'hidden';
|
||||
a.style.top = '0';
|
||||
a.style.left = '0';
|
||||
a.style.zIndex = '-1024';
|
||||
a.style.opacity = '0';
|
||||
document.body.appendChild(a);
|
||||
|
||||
return function download (name,text) {
|
||||
a.href = 'data:application/octet-stream,' + encodeURI(text);
|
||||
a.download = name;
|
||||
a.click();
|
||||
}
|
||||
})();
|
||||
function deckToJson (deck) {
|
||||
var fileObj = {
|
||||
format: 'WEBXOSS Deck',
|
||||
version: '1',
|
||||
content: deck
|
||||
};
|
||||
return JSON.stringify(fileObj);
|
||||
}
|
||||
$('input-file').onchange = function (event) {
|
||||
var file = $('input-file').files[0];
|
||||
$('input-file').value = null;
|
||||
if (!file) return;
|
||||
var name = file.name.replace(/\.webxoss$/,'');
|
||||
if (inArr(name,deckNames)) {
|
||||
window.alert(Localize.editor('DECK_NAME_ALREADY_EXISTS',name));
|
||||
return;
|
||||
}
|
||||
parseFile(file,function (deck) {
|
||||
$('input-file').value = null;
|
||||
if (!deck) {
|
||||
window.alert(Localize.editor('FAILED_TO_PARSE_FILE'));
|
||||
return;
|
||||
}
|
||||
createDeck(name,deck);
|
||||
hideImpotExport();
|
||||
});
|
||||
};
|
||||
$('button-import-code').onclick = function (event) {
|
||||
var json = $('textarea-import-export').value;
|
||||
var deck = parseCode(json);
|
||||
if (!deck) {
|
||||
window.alert(Localize.editor('FAILED_TO_PARSE_CODE'));
|
||||
} else {
|
||||
var name = window.prompt(Localize.editor('DECK_NAME'));
|
||||
if (!name) return;
|
||||
if (inArr(name,deckNames)) {
|
||||
window.alert(Localize.editor('DECK_NAME_ALREADY_EXISTS',name));
|
||||
return;
|
||||
}
|
||||
createDeck(name,deck);
|
||||
hideImpotExport();
|
||||
}
|
||||
};
|
||||
function parseFile (file,callback) {
|
||||
if (!FileReader || file.size > 1024) {
|
||||
callback(null);
|
||||
return;
|
||||
}
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (event) {
|
||||
callback(parseCode(reader.result));
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
function parseCode (json) {
|
||||
try {
|
||||
var obj = JSON.parse(json);
|
||||
var legal =
|
||||
(obj.format === 'WEBXOSS Deck') &&
|
||||
(+obj.version === 1) &&
|
||||
(obj.content.mainDeck.length <= 50) &&
|
||||
(obj.content.lrigDeck.length <= 20);
|
||||
if (legal) {
|
||||
return obj.content;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// ====== 导入导出结束 ======
|
||||
|
||||
$('link-back-to-webxoss').onclick = function (event) {
|
||||
if (window.opener && !window.opener.closed) {
|
||||
event.preventDefault();
|
||||
window.close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
search();
|
||||
|
||||
|
||||
|
||||
|
||||
// });
|
90
DeckEditor/index.html
Normal file
|
@ -0,0 +1,90 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- <html> -->
|
||||
<html manifest="../webxoss.appcache">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>DeckEditor</title>
|
||||
<script>
|
||||
global = window;
|
||||
</script>
|
||||
<script src="../CardInfo.js"></script>
|
||||
<script src="../CardInfo_ru.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="editor.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<section id="Detail">
|
||||
<div id="detail-card-figure">
|
||||
<img id="detail-card-image">
|
||||
</div>
|
||||
<div id="detail-card-data">
|
||||
<div id="detail-card-wxid"></div>
|
||||
<div id="detail-card-name"></div>
|
||||
<div id="detail-card-limiting"></div>
|
||||
<table id="detail-table">
|
||||
<tbody id="detail-table-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
<section id="Deck">
|
||||
<a id="link-back-to-webxoss" href="../">完成编辑</a>
|
||||
<div id="div-deck">
|
||||
<div>
|
||||
<span id="label-select-deck">选择牌组:</span><select id="select-decks"></select><button id="button-delete-deck">删除</button><button id="button-rename">重命名</button>
|
||||
</div>
|
||||
<div id="div-new-deck">
|
||||
<span id="label-new-deck">新建牌组:</span><input id="input-new-deck-name" type="text" placeholder="牌组名字"><button id="button-new-deck">新建</button><button id="button-copy-deck">复制</button><button id="button-import-export">导入/导出</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="main-deck-text-bar">
|
||||
<span id="main-deck-title">主卡组</span><a target="_blank" href="http://www.takaratomy.co.jp/products/wixoss/rule/rule_mayu_room.html" id="main-deck-mayus-room">茧的房间</a><span id="main-deck-burst"><span id="main-deck-burst-title">爆发:</span><span id="main-deck-burst-count"></span><span>/20</span></span>
|
||||
</div>
|
||||
<div id="main-deck-zone"></div>
|
||||
<div id="lrig-deck-text-bar">
|
||||
<span id="lrig-deck-title">LRIG卡组</span>
|
||||
</div>
|
||||
<div id="lrig-deck-zone"></div>
|
||||
<div id="div-import-warp" style="display: none;">
|
||||
<div id="div-import-export">
|
||||
<div>
|
||||
<span id="label-import-from-file">从文件导入:</span><input id="input-file" type="file">
|
||||
</div>
|
||||
<div>
|
||||
<span id="label-export-to-file">导出到文件:</span><button id="button-export">导出</button>
|
||||
</div>
|
||||
<div>
|
||||
<textarea id="textarea-import-export"></textarea>
|
||||
</div>
|
||||
<div id="div-import-footer">
|
||||
<button id="button-text">显示文本</button><button id="button-export-code">显示代码</button><button id="button-import-code">导入代码</button><button id="button-import-export-cancel">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="Search">
|
||||
<input id="search-input" placeholder="输入关键字以搜索" spellcheck="false" autocomplete="off" autocapitalize="none">
|
||||
<div id="div-search-tips">
|
||||
<a id="link-search-tips" href="./SearchTips.html" target="_blank">搜索技巧</a>
|
||||
</div>
|
||||
<div id="div-search-results">
|
||||
<ol id="search-list"></ol>
|
||||
<div id="search-show-more" style="display: none;">显示更多</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script src="../Localize.min.js"></script>
|
||||
<script src="../ImageAndDetail.min.js"></script>
|
||||
<script src="./Deck.min.js"></script>
|
||||
<script src="./DeckEditor.js"></script>
|
||||
|
||||
<!-- <script src="../lib/util.js"></script>
|
||||
<script src="../Localize.js"></script>
|
||||
<script src="../ImageFileCache.js"></script>
|
||||
<script src="../ImageManager.js"></script>
|
||||
<script src="../Detail.js"></script>
|
||||
<script src="../DeckManager.js"></script>
|
||||
<script src="./Rules.js"></script>
|
||||
<script src="./Searcher.js"></script>
|
||||
<script src="./editor.js"></script> -->
|
||||
</body>
|
||||
</html>
|
11
DeckEditor/tutorial.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Tutorial</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
207
DeckManager.js
Normal file
|
@ -0,0 +1,207 @@
|
|||
'use strict';
|
||||
|
||||
function DeckManager () {
|
||||
this.getDeckNames();
|
||||
}
|
||||
|
||||
DeckManager.prototype.getDeckNames = function () {
|
||||
var names = localStorage.getItem('deck_filenames');
|
||||
this._deckNames = names? JSON.parse(names) : [];
|
||||
return this._deckNames;
|
||||
};
|
||||
|
||||
DeckManager.prototype._updateDeckNames = function () {
|
||||
this._deckNames.sort();
|
||||
localStorage.setItem('deck_filenames',JSON.stringify(this._deckNames));
|
||||
};
|
||||
|
||||
DeckManager.prototype.createDeck = function (name,deck) {
|
||||
if (inArr(name,this._deckNames)) return false;
|
||||
this._deckNames.push(name);
|
||||
this._updateDeckNames();
|
||||
this.saveDeck(name,deck);
|
||||
return true;
|
||||
};
|
||||
|
||||
DeckManager.prototype.renameDeck = function (name,newName) {
|
||||
if (!inArr(name,this._deckNames)) return false;
|
||||
if (inArr(newName,this._deckNames)) return false;
|
||||
var deck = this.loadDeck(name);
|
||||
this.deleteDeck(name);
|
||||
this.createDeck(newName,deck);
|
||||
return true;
|
||||
};
|
||||
|
||||
DeckManager.prototype.deleteDeck = function (name) {
|
||||
if (!removeFromArr(name,this._deckNames)) return false;
|
||||
this._updateDeckNames();
|
||||
localStorage.removeItem('deck_file_'+name);
|
||||
return true;
|
||||
};
|
||||
|
||||
DeckManager.prototype.loadDeck = function (name) {
|
||||
var deck = localStorage.getItem('deck_file_'+name);
|
||||
if (!deck) return null;
|
||||
return JSON.parse(deck);
|
||||
};
|
||||
|
||||
DeckManager.prototype.saveDeck = function (name,deck) {
|
||||
if (!inArr(name,this._deckNames)) return false;
|
||||
localStorage.setItem('deck_file_'+name,JSON.stringify(deck));
|
||||
return true;
|
||||
};
|
||||
|
||||
DeckManager.prototype.checkMainDeck = function (pids) {
|
||||
if (!isArr(pids)) return false;
|
||||
if (pids.length !== 40) return false;
|
||||
var infos = [];
|
||||
for (var i = 0; i < pids.length; i++) {
|
||||
var info = CardInfo[pids[i]];
|
||||
if (!info) {
|
||||
debugger;
|
||||
return false
|
||||
};
|
||||
info = CardInfo[info.cid];
|
||||
if (!info) {
|
||||
debugger;
|
||||
return false
|
||||
};
|
||||
infos.push(info);
|
||||
}
|
||||
if (infos.some(function (info) {
|
||||
if (info.cardType === 'LRIG') return true;
|
||||
if (info.cardType === 'ARTS') return true;
|
||||
if (info.cardType === 'RESONA') return true;
|
||||
})) return false;
|
||||
if (this.burstCount(pids) !== 20) return false;
|
||||
if (!this.checkDuplicate(pids)) return false;
|
||||
return infos;
|
||||
};
|
||||
|
||||
DeckManager.prototype.checkLrigDeck = function (pids) {
|
||||
if (!isArr(pids)) return false;
|
||||
if (pids.length > 10) return false;
|
||||
var infos = [];
|
||||
for (var i = 0; i < pids.length; i++) {
|
||||
var info = CardInfo[pids[i]];
|
||||
if (!info) return false;
|
||||
info = CardInfo[info.cid];
|
||||
if (!info) return false;
|
||||
infos.push(info);
|
||||
}
|
||||
if (infos.some(function (info) {
|
||||
if (info.cardType === 'SIGNI') return true;
|
||||
if (info.cardType === 'SPELL') return true;
|
||||
})) return false;
|
||||
if (!infos.some(function (info) {
|
||||
return (info.cardType === 'LRIG') && (info.level === 0);
|
||||
})) return false;
|
||||
if (!this.checkDuplicate(pids)) return false;
|
||||
return infos;
|
||||
};
|
||||
|
||||
DeckManager.prototype.checkMayusRoom = function (pids) {
|
||||
var infos = [];
|
||||
for (var i = 0; i < pids.length; i++) {
|
||||
var info = CardInfo[pids[i]];
|
||||
if (!info) return false;
|
||||
info = CardInfo[info.cid];
|
||||
if (!info) return false;
|
||||
infos.push(info);
|
||||
}
|
||||
// 禁止 狐狸+修复 和 狐狸+Three out
|
||||
if (infos.some(function (info) {
|
||||
return info.cid === 33; // 狐狸
|
||||
}) && infos.some(function (info) {
|
||||
return (info.cid === 34) || (info.cid === 84); // 修复, three out
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
// 禁止 V・@・C+共鸣・进军 和 V・@・C+共鸣
|
||||
if (infos.some(function (info) {
|
||||
return info.cid === 1202; // V・@・C
|
||||
}) && infos.some(function (info) {
|
||||
return (info.cid === 884) || (info.cid === 1369); // 共鸣・进军, 共鸣
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
// 禁止 Lock+割裂 和 Lock+精挖
|
||||
if (infos.some(function (info) {
|
||||
return info.cid === 534; // Lock
|
||||
}) && infos.some(function (info) {
|
||||
return (info.cid === 408) || (info.cid === 570); // 割裂, 精挖
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
// 禁止 Ar+魔术手
|
||||
if (infos.some(function (info) {
|
||||
return info.cid === 814; // Ar
|
||||
}) && infos.some(function (info) {
|
||||
return (info.cid === 1090); // 魔术手
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
// 禁止 双麻油
|
||||
if (infos.some(function (info) {
|
||||
return info.cid === 649; // 創世の巫女 マユ
|
||||
}) && infos.some(function (info) {
|
||||
return (info.cid === 1562); // 真名の巫女 マユ
|
||||
})) {
|
||||
return false;
|
||||
}
|
||||
// 限制
|
||||
var limitMap = {
|
||||
37: 2, // <忘得ぬ幻想 ヴァルキリー>
|
||||
34: 2, // <修復>
|
||||
178: 2, // <先駆の大天使 アークゲイン>
|
||||
534: 1, // <ロック・ユー>
|
||||
689: 1, // <RAINY>
|
||||
474: 0, // <ノー・ゲイン>
|
||||
23: 0, // <大器晩成>
|
||||
};
|
||||
for (var i = 0; i < infos.length; i++) {
|
||||
var info = infos[i];
|
||||
var cid = info.cid;
|
||||
if (cid in limitMap) {
|
||||
limitMap[cid]--;
|
||||
if (limitMap[cid] < 0) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
DeckManager.prototype.checkDeck = function (deck,mayusRoom) {
|
||||
var valid = this.checkMainDeck(deck.mainDeck) &&
|
||||
this.checkLrigDeck(deck.lrigDeck);
|
||||
if (!valid) return false;
|
||||
if ((mayusRoom === false)) return true;
|
||||
return this.checkMayusRoom(deck.mainDeck.concat(deck.lrigDeck));
|
||||
};
|
||||
|
||||
DeckManager.prototype.burstCount = function (pids) {
|
||||
var count = 0;
|
||||
pids.forEach(function (pid) {
|
||||
var info = CardInfo[pid];
|
||||
info = CardInfo[info.cid];
|
||||
if (info.burstEffectTexts && info.burstEffectTexts.length) {
|
||||
count++;
|
||||
}
|
||||
});
|
||||
return count;
|
||||
};
|
||||
|
||||
DeckManager.prototype.checkDuplicate = function (pids) {
|
||||
var bucket = {};
|
||||
pids.forEach(function (pid) {
|
||||
var info = CardInfo[pid];
|
||||
if (info.cid in bucket) {
|
||||
bucket[info.cid]++;
|
||||
} else {
|
||||
bucket[info.cid] = 1;
|
||||
}
|
||||
});
|
||||
for (var cid in bucket) {
|
||||
if (bucket[cid] > 4) return false;
|
||||
}
|
||||
return true;
|
||||
};
|
151
Detail.js
Normal file
|
@ -0,0 +1,151 @@
|
|||
'use strict';
|
||||
|
||||
window.CardDetail = (function () {
|
||||
|
||||
function $ (id) {
|
||||
return document.getElementById(id);
|
||||
}
|
||||
function newElement (tag) {
|
||||
var el = document.createElement(tag);
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
el.classList.add(arguments[i]);
|
||||
}
|
||||
return el;
|
||||
}
|
||||
function KeyValue (prop,keyHidden) {
|
||||
this.prop = prop;
|
||||
this.keyHidden = keyHidden;
|
||||
this.value = '';
|
||||
|
||||
this.eKey = newElement('td','key',prop);
|
||||
this.eKey.textContent = Localize.propToKey(prop);
|
||||
|
||||
this.eValue = newElement('td','value',prop);
|
||||
}
|
||||
|
||||
|
||||
function CardDetail (imageManager) {
|
||||
this.imageManager = imageManager;
|
||||
|
||||
this.eDetail = $('detail');
|
||||
this.eImage = $('detail-card-image');
|
||||
this.eWxid = $('detail-card-wxid');
|
||||
this.eName = $('detail-card-name');
|
||||
this.eLimiting = $('detail-card-limiting');
|
||||
this.eTable = $('detail-table');
|
||||
this.eTableBody = $('detail-table-body');
|
||||
|
||||
this.kvCardType = new KeyValue('cardType');
|
||||
this.kvColor = new KeyValue('color');
|
||||
this.kvLevel = new KeyValue('level');
|
||||
this.kvClasses = new KeyValue('classes');
|
||||
this.kvLimit = new KeyValue('limit');
|
||||
this.kvPower = new KeyValue('power');
|
||||
this.kvLimting = new KeyValue('limting');
|
||||
this.kvGuard = new KeyValue('guard');
|
||||
this.kvCost = new KeyValue('cost');
|
||||
this.kvTimmings = new KeyValue('timmings');
|
||||
this.kvEffects = new KeyValue('effects',true);
|
||||
this.kvBurst = new KeyValue('burst',true);
|
||||
|
||||
this._pid = 0;
|
||||
}
|
||||
|
||||
CardDetail.prototype.show = function (pid) {
|
||||
if (!pid || this._pid === pid) return;
|
||||
this._pid = pid;
|
||||
this.eTable.setAttribute('lang',Localize.getLanguage());
|
||||
this.eTableBody.innerHTML = '';
|
||||
var info = CardInfo[pid];
|
||||
this.eWxid.textContent = info.wxid;
|
||||
this.eName.innerHTML = '';
|
||||
var link = newElement('a');
|
||||
link.target = '_blank';
|
||||
link.href = 'http://www.takaratomy.co.jp/products/wixoss/card/card_list.php?card=card_detail&card_no=' + info.wxid;
|
||||
link.textContent = Localize.cardName(info);
|
||||
this.eName.appendChild(link);
|
||||
this.eLimiting.textContent = Localize.limiting(info);
|
||||
this.eImage.src = this.imageManager.getUrlByPid(pid);
|
||||
this.kvColor.value = info.color.split('/').map(Localize.color).join('/');
|
||||
this.kvCardType.value = Localize.cardType(info);
|
||||
this.kvEffects.value = Localize.effectTexts(info);
|
||||
if (inArr(info.cardType,['LRIG','SIGNI','RESONA'])) {
|
||||
this.kvClasses.value = Localize.classes(info);
|
||||
this.kvLevel.value = info.level;
|
||||
}
|
||||
if (inArr(info.cardType,['LRIG','SPELL','ARTS'])) {
|
||||
this.kvCost.value = Localize.cost(info);
|
||||
}
|
||||
if (inArr(info.cardType,['SIGNI','SPELL'])) {
|
||||
this.kvBurst.value = Localize.burstEffectTexts(info);
|
||||
}
|
||||
if (info.cardType === 'LRIG') {
|
||||
if (info.limit >= 1024) {
|
||||
this.kvLimit.value = '∞';
|
||||
} else {
|
||||
this.kvLimit.value = info.limit;
|
||||
}
|
||||
this.addKeyValue(
|
||||
[this.kvCardType,this.kvColor],
|
||||
[this.kvLevel,this.kvClasses],
|
||||
[this.kvLimit,this.kvCost],
|
||||
[this.kvEffects]
|
||||
);
|
||||
} else if (info.cardType === 'SIGNI') {
|
||||
this.kvPower.value = info.power;
|
||||
this.kvGuard.value = Localize.guard(info);
|
||||
this.addKeyValue(
|
||||
[this.kvCardType,this.kvColor],
|
||||
[this.kvLevel,this.kvClasses],
|
||||
[this.kvPower,this.kvGuard],
|
||||
[this.kvEffects],
|
||||
[this.kvBurst]
|
||||
);
|
||||
} else if (info.cardType === 'RESONA') {
|
||||
this.kvPower.value = info.power;
|
||||
this.kvGuard.value = Localize.guard(info);
|
||||
this.addKeyValue(
|
||||
[this.kvCardType,this.kvColor],
|
||||
[this.kvLevel,this.kvClasses],
|
||||
[this.kvPower,this.kvGuard],
|
||||
[this.kvEffects]
|
||||
);
|
||||
} else if (info.cardType === 'SPELL') {
|
||||
this.addKeyValue(
|
||||
[this.kvCardType,this.kvColor],
|
||||
[this.kvCost],
|
||||
[this.kvEffects],
|
||||
[this.kvBurst]
|
||||
);
|
||||
} else if (info.cardType === 'ARTS') {
|
||||
this.kvTimmings.value = Localize.timmings(info);
|
||||
this.addKeyValue(
|
||||
[this.kvCardType,this.kvColor],
|
||||
[this.kvCost],
|
||||
[this.kvTimmings],
|
||||
[this.kvEffects]
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
CardDetail.prototype.addKeyValue = function () {
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
var rowArray = arguments[i];
|
||||
var eRow = newElement('tr');
|
||||
rowArray.forEach(function (kv) {
|
||||
kv.eValue.textContent = kv.value;
|
||||
kv.eValue.removeAttribute('colspan');
|
||||
if (!kv.keyHidden) eRow.appendChild(kv.eKey);
|
||||
eRow.appendChild(kv.eValue);
|
||||
},this);
|
||||
if (rowArray.length === 1) {
|
||||
var kv = rowArray[0];
|
||||
var colspan = kv.keyHidden? 4 : 3;
|
||||
kv.eValue.setAttribute('colspan',colspan);
|
||||
}
|
||||
this.eTableBody.appendChild(eRow);
|
||||
}
|
||||
};
|
||||
|
||||
return CardDetail;
|
||||
})();
|
453
Dialog.js
Normal file
|
@ -0,0 +1,453 @@
|
|||
'use strict';
|
||||
|
||||
function Dialog (game) {
|
||||
this.game = game;
|
||||
|
||||
this.searcher = new Searcher();
|
||||
|
||||
this.warpDiv = this.newElement('div');
|
||||
this.dialogDiv = this.newElement('div');
|
||||
this.titleDiv = this.newElement('div');
|
||||
this.closeIcon = this.newElement('div');
|
||||
this.bodyDiv = this.newElement('div');
|
||||
this.footerDiv = this.newElement('div');
|
||||
this.footSpan = this.newElement('span');
|
||||
this.okBtn = this.newElement('button');
|
||||
this.cancelBtn = this.newElement('button');
|
||||
|
||||
this.okBtn.textContent = Localize('common','OK');
|
||||
this.cancelBtn.textContent = Localize('common','CANCEL');
|
||||
this.closeIcon.onclick = this.close.bind(this);
|
||||
|
||||
this.warpDiv.classList.add('warp');
|
||||
this.dialogDiv.classList.add('dialog');
|
||||
this.titleDiv.classList.add('title');
|
||||
this.closeIcon.classList.add('closeIcon');
|
||||
this.bodyDiv.classList.add('body');
|
||||
this.footerDiv.classList.add('footer');
|
||||
this.okBtn.classList.add('okBtn');
|
||||
this.cancelBtn.classList.add('cancelBtn');
|
||||
|
||||
this.warpDiv.appendChild(this.dialogDiv);
|
||||
this.dialogDiv.appendChild(this.closeIcon);
|
||||
this.dialogDiv.appendChild(this.titleDiv);
|
||||
this.dialogDiv.appendChild(this.bodyDiv);
|
||||
this.dialogDiv.appendChild(this.footerDiv);
|
||||
this.footerDiv.appendChild(this.footSpan);
|
||||
this.footerDiv.appendChild(this.okBtn);
|
||||
this.footerDiv.appendChild(this.cancelBtn);
|
||||
|
||||
this.warpDiv.style.display = 'none';
|
||||
game.stage.canvas.parentElement.appendChild(this.warpDiv);
|
||||
}
|
||||
|
||||
Dialog.prototype.newElement = function (tag) {
|
||||
return document.createElement(tag);
|
||||
};
|
||||
|
||||
Dialog.prototype.newCardImg = function (pid) {
|
||||
var img = this.newElement('img');
|
||||
img.src = this.game.imageManager.getUrlByPid(pid);
|
||||
return img;
|
||||
};
|
||||
|
||||
Dialog.prototype.mouseover = function (el,pid) {
|
||||
el.onmouseover = this.game.cardDetail.show.bind(this.game.cardDetail,pid);
|
||||
};
|
||||
|
||||
Dialog.prototype.center = function (element) {
|
||||
var parent = element.parentElement;
|
||||
element.style.top = '0';
|
||||
element.style.left = '0';
|
||||
element.style.top = (parent.offsetHeight - element.offsetHeight)/2 + 'px';
|
||||
element.style.left = (parent.offsetWidth - element.offsetWidth)/2 + 'px';
|
||||
};
|
||||
|
||||
Dialog.prototype.pop = function (title,body,foot,canClose,callback,callbackCancel) {
|
||||
var dialog = this;
|
||||
// 构筑DOM
|
||||
this.titleDiv.textContent = title;
|
||||
this.footSpan.innerHTML = '';
|
||||
if (foot) this.footSpan.appendChild(foot);
|
||||
this.bodyDiv.innerHTML = '';
|
||||
this.bodyDiv.style.width = '';
|
||||
this.bodyDiv.appendChild(body);
|
||||
this.closeIcon.style.display = canClose? '' : 'none';
|
||||
if (!callback) {
|
||||
this.okBtn.onclick = null;
|
||||
this.footerDiv.style.display = 'none';
|
||||
} else {
|
||||
this.okBtn.onclick = function (event) {
|
||||
dialog.close();
|
||||
callback();
|
||||
};
|
||||
// this.okBtn.disabled = false;
|
||||
this.footerDiv.style.display = '';
|
||||
}
|
||||
if (!callbackCancel) {
|
||||
this.cancelBtn.onclick = null;
|
||||
this.cancelBtn.style.display = 'none';
|
||||
} else {
|
||||
this.cancelBtn.onclick = function (event) {
|
||||
dialog.close();
|
||||
callbackCancel();
|
||||
};
|
||||
// this.cancelBtn.disabled = false;
|
||||
this.cancelBtn.style.display = '';
|
||||
}
|
||||
// 渲染,但完全透明,用于计算元素尺寸和位置.
|
||||
this.warpDiv.style.opacity = '0';
|
||||
this.warpDiv.style.display = '';
|
||||
// 加上滚动条宽度
|
||||
// this.bodyDiv.style.width = 2*this.bodyDiv.offsetWidth - this.bodyDiv.clientWidth + 'px';
|
||||
// 居中
|
||||
this.center(this.dialogDiv);
|
||||
// 显示
|
||||
this.warpDiv.style.opacity = '1';
|
||||
};
|
||||
|
||||
Dialog.prototype.close = function () {
|
||||
this.okBtn.disabled = false;
|
||||
this.warpDiv.style.display = 'none';
|
||||
};
|
||||
|
||||
Dialog.prototype.showText = function (title,text,callback) {
|
||||
var body = document.createTextNode(text);
|
||||
this.pop(title,body,null,false,callback);
|
||||
};
|
||||
|
||||
Dialog.prototype.confirm = function (title,text,callback) {
|
||||
var body = document.createTextNode(text);
|
||||
this.pop(title,body,null,false,callback.bind(null,true),callback.bind(null,false));
|
||||
};
|
||||
|
||||
// 从多个文本选项选择一个.
|
||||
Dialog.prototype.selectText = function (title,options,canClose,callback) {
|
||||
var dialog = this;
|
||||
var body = this.newElement('div');
|
||||
options.forEach(function (option,idx) {
|
||||
var opt = this.newElement('div');
|
||||
opt.classList.add('option');
|
||||
opt.textContent = option;
|
||||
body.appendChild(opt);
|
||||
|
||||
opt.onclick = function (event) {
|
||||
dialog.close();
|
||||
callback(idx);
|
||||
}
|
||||
},this);
|
||||
this.pop(title,body,null,canClose,null);
|
||||
};
|
||||
|
||||
Dialog.prototype.selectNumber = function (title,min,max,defaultValue,canClose,callback) {
|
||||
var dialog = this;
|
||||
var body = this.newElement('div');
|
||||
var sel = this.newElement('select');
|
||||
for (var i = min; i <= max; i++) {
|
||||
var opt = this.newElement('option');
|
||||
opt.value = i;
|
||||
opt.textContent = i;
|
||||
sel.appendChild(opt);
|
||||
}
|
||||
sel.value = defaultValue;
|
||||
body.appendChild(sel);
|
||||
this.pop(title,body,null,canClose,function () {
|
||||
callback(sel.value);
|
||||
});
|
||||
};
|
||||
|
||||
Dialog.prototype.showCards = function (title,cards,callback) {
|
||||
var body = this.newElement('div');
|
||||
if (!cards.length) {
|
||||
body.textContent = Localize('common','NO_CARDS');
|
||||
} else {
|
||||
cards.forEach(function (card) {
|
||||
var crd = this.newElement('div');
|
||||
var img = this.newCardImg(card.pid);
|
||||
|
||||
crd.appendChild(img);
|
||||
crd.classList.add('card');
|
||||
this.mouseover(crd,card.pid);
|
||||
|
||||
body.appendChild(crd);
|
||||
},this);
|
||||
}
|
||||
this.pop(title,body,null,false,callback);
|
||||
};
|
||||
|
||||
Dialog.prototype.selectCardId = function (title,callback) {
|
||||
var dialog = this;
|
||||
var searcher = this.searcher;
|
||||
|
||||
var body = this.newElement('div');
|
||||
body.style.textAlign = 'center';
|
||||
|
||||
var searchBar = this.newElement('input');
|
||||
searchBar.setAttribute('placeholder','Search...');
|
||||
searchBar.type = 'text';
|
||||
searchBar.style.textAlign = 'center';
|
||||
searchBar.style.width = '90%';
|
||||
|
||||
var container = this.newElement('div');
|
||||
container.style.maxHeight = '450px';
|
||||
container.style['overflow-y'] = 'auto';
|
||||
container.style.textAlign = 'left';
|
||||
|
||||
var elShowMore = this.newElement('div');
|
||||
elShowMore.textContent = 'Show More...';
|
||||
elShowMore.style.color = 'blue';
|
||||
elShowMore.style.cursor = 'pointer';
|
||||
elShowMore.style.margin = '1em 0';
|
||||
|
||||
body.appendChild(searchBar);
|
||||
body.appendChild(container);
|
||||
body.appendChild(elShowMore);
|
||||
|
||||
var results = [];
|
||||
var RESULTS_LENGTH = 9;
|
||||
var _shown = 0;
|
||||
elShowMore.onclick = showMore;
|
||||
searchBar.onchange = searchBar.onkeyup = search;
|
||||
function search () {
|
||||
var q = searchBar.value;
|
||||
results = searcher.search(q);
|
||||
showResults();
|
||||
};
|
||||
search();
|
||||
function showResults () {
|
||||
_shown = 0;
|
||||
container.innerHTML = '';
|
||||
showMore();
|
||||
}
|
||||
function showMore () {
|
||||
for (var i = 0; i < RESULTS_LENGTH; i++) {
|
||||
var idx = _shown;
|
||||
if (idx >= results.length) break;
|
||||
var pid = results[idx].pid;
|
||||
|
||||
var opt = dialog.newElement('div');
|
||||
var img = dialog.newCardImg(pid);
|
||||
|
||||
opt.appendChild(img);
|
||||
opt.classList.add('card');
|
||||
dialog.mouseover(opt,pid);
|
||||
|
||||
opt.onclick = function (pid) {
|
||||
dialog.close();
|
||||
callback(pid);
|
||||
}.bind(null,pid);
|
||||
|
||||
container.appendChild(opt);
|
||||
_shown++;
|
||||
}
|
||||
|
||||
// if (_shown < results.length) {
|
||||
// show(elShowMore);
|
||||
// } else {
|
||||
// hide(elShowMore);
|
||||
// }
|
||||
}
|
||||
this.pop(title,body,null,false,null);
|
||||
|
||||
// 固定宽度
|
||||
body.style.minWidth = body.offsetWidth + 'px';
|
||||
searchBar.focus();
|
||||
};
|
||||
|
||||
// 选择一张.
|
||||
Dialog.prototype.selectCard = function (title,cards,canClose,callback) {
|
||||
var dialog = this;
|
||||
var body = this.newElement('div');
|
||||
cards.forEach(function (card,idx) {
|
||||
var opt = this.newElement('div');
|
||||
var img = this.newCardImg(card.pid);
|
||||
|
||||
opt.appendChild(img);
|
||||
opt.classList.add('card');
|
||||
this.mouseover(opt,card.pid);
|
||||
|
||||
opt.onclick = function (event) {
|
||||
dialog.close();
|
||||
callback(idx);
|
||||
}
|
||||
|
||||
body.appendChild(opt);
|
||||
},this);
|
||||
this.pop(title,body,null,canClose,null);
|
||||
};
|
||||
|
||||
Dialog.prototype.selectCardAdvanced = function (title,cards,texts,canClose,careOrder,onchanged,callback,callbackCancel) {
|
||||
if (!texts) texts = [];
|
||||
var dialog = this;
|
||||
var selectedIndexes = [];
|
||||
var datas = [];
|
||||
var body = this.newElement('div');
|
||||
cards.forEach(function (card,idx) {
|
||||
var opt = this.newElement('div');
|
||||
var img = this.newCardImg(card.pid);
|
||||
var txt = this.newElement('div');
|
||||
txt.textContent = texts[idx] || '';
|
||||
var msk = this.newElement('div');
|
||||
var num = this.newElement('div');
|
||||
|
||||
opt.appendChild(img);
|
||||
opt.appendChild(txt);
|
||||
opt.appendChild(msk);
|
||||
opt.appendChild(num);
|
||||
|
||||
opt.classList.add('card');
|
||||
txt.classList.add('txt');
|
||||
msk.classList.add('msk');
|
||||
num.classList.add('num');
|
||||
this.mouseover(opt,card.pid);
|
||||
|
||||
var data = {
|
||||
opt: opt,
|
||||
txt: txt,
|
||||
msk: msk,
|
||||
num: num,
|
||||
};
|
||||
datas[idx] = data;
|
||||
|
||||
opt.onclick = function (event) {
|
||||
if (!opt.classList.contains('selected') && opt.classList.contains('disabled')) return;
|
||||
if (opt.classList.contains('selected')) {
|
||||
removeFromArr(idx,selectedIndexes);
|
||||
} else {
|
||||
selectedIndexes.push(idx);
|
||||
}
|
||||
opt.classList.toggle('selected');
|
||||
handleSelectChanged();
|
||||
};
|
||||
|
||||
body.appendChild(opt);
|
||||
},this);
|
||||
|
||||
handleSelectChanged();
|
||||
dialog.pop(title,body,null,canClose,callback.bind(null,selectedIndexes),callbackCancel);
|
||||
datas.forEach(function (data) {
|
||||
this.center(data.txt);
|
||||
},this);
|
||||
|
||||
function handleSelectChanged () {
|
||||
datas.forEach(function (data,idx) {
|
||||
data.opt.classList.remove('disabled');
|
||||
},this);
|
||||
var ok = onchanged(selectedIndexes,disable);
|
||||
dialog.okBtn.disabled = !ok;
|
||||
if (careOrder) {
|
||||
datas.forEach(function (data,idx) {
|
||||
var order = selectedIndexes.indexOf(idx) + 1;
|
||||
data.num.textContent = order || '';
|
||||
dialog.center(data.num);
|
||||
},this);
|
||||
}
|
||||
}
|
||||
function disable (idx) {
|
||||
datas[idx].opt.classList.add('disabled');
|
||||
}
|
||||
};
|
||||
|
||||
// 选择若干张.
|
||||
Dialog.prototype.selectSomeCards = function (title,cards,arg,callback) {
|
||||
var min = arg.min || 0;
|
||||
// var max = arg.max || cards.length;
|
||||
var max = arg.max;
|
||||
if (!max) {
|
||||
max = arg.targets? arg.targets.length : cards.length;
|
||||
}
|
||||
var texts = arg.texts;
|
||||
var canClose = arg.canClose;
|
||||
var careOrder = arg.careOrder;
|
||||
var targets = arg.targets;
|
||||
var callbackCancel;
|
||||
if (min) {
|
||||
callbackCancel = null;
|
||||
} else {
|
||||
callbackCancel = callback.bind(null,[]);
|
||||
}
|
||||
this.selectCardAdvanced(title,cards,texts,canClose,careOrder,function (selectedIndexes,disable) {
|
||||
if (targets && targets.length) {
|
||||
cards.forEach(function (card,idx) {
|
||||
if (!inArr(card,targets)) disable(idx);
|
||||
},this);
|
||||
}
|
||||
|
||||
var len = selectedIndexes.length;
|
||||
if (len >= max) {
|
||||
cards.forEach(function (card,idx) {
|
||||
disable(idx);
|
||||
},this);
|
||||
return true;
|
||||
}
|
||||
return len && (len >= min);
|
||||
},function (selectedIndexes) {
|
||||
if (targets && targets.length && (targets.length !== cards.length)) {
|
||||
selectedIndexes = selectedIndexes.map(function (idx) {
|
||||
return targets.indexOf(cards[idx]);
|
||||
});
|
||||
}
|
||||
callback(selectedIndexes);
|
||||
},callbackCancel);
|
||||
};
|
||||
|
||||
Dialog.prototype.selectEner = function (title,cards,colors,cost,callback,onCancel) {
|
||||
this.selectCardAdvanced(title,cards,null,false,false,onSelectChange,callback,onCancel);
|
||||
|
||||
function onSelectChange (selectedIndexes,disable) {
|
||||
var need = {};
|
||||
var total = 0;
|
||||
['colorless','white','black','red','blue','green','multi'].forEach(function (color) {
|
||||
need[color] = cost[color] || 0;
|
||||
total += need[color];
|
||||
},this);
|
||||
|
||||
if (selectedIndexes.length >= total) {
|
||||
cards.forEach(function (card,idx) {
|
||||
disable(idx);
|
||||
},this);
|
||||
return true;
|
||||
}
|
||||
|
||||
var colorSets = [];
|
||||
selectedIndexes.forEach(function (idx) {
|
||||
var color = colors[idx];
|
||||
if (color === 'multi') return;
|
||||
if (isArr(color)) {
|
||||
// 多重颜色,延迟考虑
|
||||
colorSets.push(color);
|
||||
return
|
||||
}
|
||||
if (need[color] > 0) {
|
||||
need[color] -= 1;
|
||||
} else {
|
||||
need.colorless -= 1;
|
||||
}
|
||||
},this);
|
||||
// 多重颜色
|
||||
colorSets.forEach(function (colorSet) {
|
||||
for (var i = 0; i < colorSet.length; i++) {
|
||||
var color = colorSet[i];
|
||||
if (need[color] > 0) {
|
||||
need[color] -= 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
need.colorless -= 1;
|
||||
});
|
||||
|
||||
if (need.colorless > 0) return false;
|
||||
|
||||
cards.forEach(function (card,idx) {
|
||||
var color = colors[idx];
|
||||
if (color === 'multi') return;
|
||||
if (isArr(color)) {
|
||||
if (color.some(function (color) {
|
||||
return need[color] > 0;
|
||||
})) return;
|
||||
return disable(idx);
|
||||
}
|
||||
if (!need[color]) disable(idx);
|
||||
},this);
|
||||
}
|
||||
};
|
88
FakeSocket.js
Normal file
|
@ -0,0 +1,88 @@
|
|||
'use strict';
|
||||
|
||||
window.FakeSocket = (function () {
|
||||
|
||||
|
||||
var sockets = [];
|
||||
|
||||
window.addEventListener('message',function (event) {
|
||||
var win = event.source;
|
||||
var name = event.data.name;
|
||||
var data = event.data.data;
|
||||
if ((name !== 'tick') && (name !== 'tock')) console.log(JSON.stringify(event.data));
|
||||
for (var i = 0; i < sockets.length; i++) {
|
||||
var socket = sockets[i];
|
||||
if (socket._win === win) {
|
||||
socket._doEmit(name,data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function FakeSocket (win) {
|
||||
this._win = win;
|
||||
this._listeners = {};
|
||||
this.id = '<' + sockets.push(this) + '>';
|
||||
this.io = {
|
||||
reconnection: function () {},
|
||||
opts: {
|
||||
query: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FakeSocket.prototype.on = function (name,handler) {
|
||||
if (!this._listeners[name]) this._listeners[name] = [];
|
||||
this._listeners[name].push(handler);
|
||||
};
|
||||
|
||||
FakeSocket.prototype.emit = function (name,data) {
|
||||
this._win.postMessage({
|
||||
name: name,
|
||||
data: data
|
||||
},'*');
|
||||
};
|
||||
|
||||
FakeSocket.prototype._doEmit = function (name,data) {
|
||||
var listeners = this._listeners[name];
|
||||
if (listeners) {
|
||||
listeners.forEach(function (listener) {
|
||||
listener(data);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
FakeSocket.prototype.disconnect = function () {
|
||||
this.emit('disconnect');
|
||||
};
|
||||
|
||||
FakeSocket.prototype.removeAllListeners = function (name) {
|
||||
var listeners = this._listeners[name];
|
||||
if (listeners) {
|
||||
listeners.length = 0;
|
||||
}
|
||||
};
|
||||
|
||||
return FakeSocket;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
})();
|
643
Game.js
Normal file
|
@ -0,0 +1,643 @@
|
|||
'use strict';
|
||||
|
||||
function Game (io,audio,ongameover,spectating) {
|
||||
this.io = io;
|
||||
this.audio = audio;
|
||||
this.ongameover = ongameover;
|
||||
this.io.listener = function (data) {
|
||||
console.log(data);
|
||||
this.addMsgs(data);
|
||||
this.update();
|
||||
}.bind(this);
|
||||
|
||||
this.onidle = null;
|
||||
|
||||
// this._waiting = false;
|
||||
|
||||
// 老是清不干净,干脆粗暴地删掉元素.
|
||||
this.gameDiv = document.getElementById('GameDiv');
|
||||
this.canvasContainer = document.getElementById('BattleField');
|
||||
this.canvasContainer.innerHTML = '';
|
||||
this.canvas = document.createElement('canvas');
|
||||
this.canvas.width = 576;
|
||||
this.canvas.height = 734;
|
||||
this.canvasContainer.appendChild(this.canvas);
|
||||
this.stage = new createjs.Stage(this.canvas);
|
||||
this.stage.enableDOMEvents(true);
|
||||
this.stage.enableMouseOver(10);
|
||||
|
||||
this.dialog = new Dialog(this);
|
||||
this.selector = new Selector(this,spectating);
|
||||
|
||||
this.objList = [];
|
||||
|
||||
this.background = new GameBackground(this);
|
||||
this.stage.addChild(this.background);
|
||||
|
||||
this.cards = [];
|
||||
this.cardLayer = new createjs.Container();
|
||||
this.stage.addChild(this.cardLayer);
|
||||
|
||||
this.zones = [];
|
||||
this.zoneLayer = new createjs.Container();
|
||||
this.stage.addChild(this.zoneLayer);
|
||||
|
||||
this.msgQueue = [];
|
||||
this._packageCount = 0;
|
||||
// this._done = false;
|
||||
|
||||
this.imageManager = new ImageManager();
|
||||
this.cardDetail = new CardDetail(this.imageManager);
|
||||
|
||||
this.initZones();
|
||||
|
||||
this.skip = false; // 跳过动画
|
||||
}
|
||||
|
||||
// Game.prototype.destroy = function () {
|
||||
// this.gameDiv.classList.remove('colored');
|
||||
// ['white','black','red','blue','green'].forEach(function (color) {
|
||||
// this.gameDiv.classList.remove('self-'+color);
|
||||
// this.gameDiv.classList.remove('opponent-'+color);
|
||||
// },this);
|
||||
// this.stage.autoClear = true;
|
||||
// this.stage.removeAllChildren();
|
||||
// this.stage.update();
|
||||
// this.stage.enableDOMEvents(false);
|
||||
// this.stage.removeAllChildren();
|
||||
// this.stage.removeAllEventListeners();
|
||||
// };
|
||||
|
||||
// =========================
|
||||
// Game.prototype.initZones
|
||||
// 定义在ZonePosition.js
|
||||
// =========================
|
||||
|
||||
Game.prototype.setSid = function (obj,sid) {
|
||||
obj.sid = sid;
|
||||
this.objList[sid] = obj;
|
||||
};
|
||||
|
||||
Game.prototype.getObjBySid = function (sid) {
|
||||
return this.objList[sid];
|
||||
};
|
||||
|
||||
Game.prototype.addCard = function (card) {
|
||||
this.cards.push(card);
|
||||
this.cardLayer.addChild(card);
|
||||
};
|
||||
|
||||
Game.prototype.addZone = function (zone) {
|
||||
this.zones.push(zone);
|
||||
this.zoneLayer.addChild(zone);
|
||||
};
|
||||
|
||||
Game.prototype.handleInit = function (msg) {
|
||||
this.setSid(this.player,msg.player);
|
||||
this.setSid(this.opponent,msg.opponent);
|
||||
|
||||
function setZones (player,zones) {
|
||||
this.setSid(player.mainDeck,zones.mainDeck);
|
||||
this.setSid(player.lrigDeck,zones.lrigDeck);
|
||||
this.setSid(player.handZone,zones.handZone);
|
||||
this.setSid(player.lrigZone,zones.lrigZone);
|
||||
this.setSid(player.signiZones[0],zones.signiZones[0]);
|
||||
this.setSid(player.signiZones[1],zones.signiZones[1]);
|
||||
this.setSid(player.signiZones[2],zones.signiZones[2]);
|
||||
this.setSid(player.enerZone,zones.enerZone);
|
||||
this.setSid(player.checkZone,zones.checkZone);
|
||||
this.setSid(player.trashZone,zones.trashZone);
|
||||
this.setSid(player.lrigTrashZone,zones.lrigTrashZone);
|
||||
this.setSid(player.lifeClothZone,zones.lifeClothZone);
|
||||
this.setSid(player.excludedZone,zones.excludedZone);
|
||||
zones.mainDeckCards.forEach(function (sid) {
|
||||
var card = new Card(this,false);
|
||||
this.setSid(card,sid);
|
||||
card.move(0,player.mainDeck,true,false,false);
|
||||
},this);
|
||||
zones.lrigDeckCards.forEach(function (sid,i) {
|
||||
var card = new Card(this,true);
|
||||
this.setSid(card,sid);
|
||||
card.move(zones.lrigDeckCardIds[i],player.lrigDeck,true,false,false);
|
||||
},this);
|
||||
}
|
||||
|
||||
setZones.call(this,this.player,msg.playerZones);
|
||||
setZones.call(this,this.opponent,msg.opponentZones);
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handleSetColor = function (msg) {
|
||||
// this.gameDiv.classList.add('colored');
|
||||
document.body.setAttribute('self',msg.selfColor);
|
||||
document.body.setAttribute('opponent',msg.opponentColor);
|
||||
var zoneTextColorMap = {
|
||||
'white': 'black',
|
||||
'black': 'yellow',
|
||||
'red': 'white',
|
||||
'blue': 'yellow',
|
||||
'green': 'white'
|
||||
};
|
||||
this.zones.forEach(function (zone) {
|
||||
var color = zone.opposite? zoneTextColorMap[msg.opponentColor] : zoneTextColorMap[msg.selfColor];
|
||||
zone.setTextColor(color);
|
||||
},this);
|
||||
var audio = this.audio;
|
||||
audio.bgmFadeOut(function () {
|
||||
audio.playBgm(msg.selfColor);
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handlePackedMsgStart = function () {
|
||||
// this.audio.playBgm();
|
||||
this._packageCount++;
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handlePackedMsgEnd = function () {
|
||||
this._packageCount--;
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handleMoveCard = function (msg) {
|
||||
var card = this.getObjBySid(msg.card);
|
||||
var zone = this.getObjBySid(msg.zone);
|
||||
card.move(msg.pid,zone,msg.up,msg.faceup,msg.bottom);
|
||||
return false;
|
||||
};
|
||||
|
||||
Game.prototype.handleUpCard = function (msg) {
|
||||
var card = this.getObjBySid(msg.card);
|
||||
card.up();
|
||||
return false;
|
||||
};
|
||||
|
||||
Game.prototype.handleDownCard = function (msg) {
|
||||
var card = this.getObjBySid(msg.card);
|
||||
card.down();
|
||||
return false;
|
||||
};
|
||||
|
||||
Game.prototype.handleFaceupCard = function (msg) {
|
||||
var card = this.getObjBySid(msg.card);
|
||||
card.pid = msg.pid;
|
||||
card.faceup();
|
||||
return false;
|
||||
};
|
||||
|
||||
Game.prototype.handleFacedownCard = function (msg) {
|
||||
var card = this.getObjBySid(msg.card);
|
||||
card.facedown();
|
||||
return false;
|
||||
};
|
||||
|
||||
Game.prototype.handleShuffle = function (msg) {
|
||||
msg.cards.forEach(function (sid) {
|
||||
var card = this.getObjBySid(sid);
|
||||
card.pid = 0;
|
||||
},this);
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handleSelect = function (msg) {
|
||||
console.log(msg);
|
||||
if (this.skip) return true;
|
||||
this.selector.addMsg(msg);
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handlePayEner = function (msg) {
|
||||
console.log('handlePayEner',msg);
|
||||
|
||||
if (this.skip) return true;
|
||||
|
||||
var cards = msg.cards.map(function (sid) {
|
||||
return this.getObjBySid(sid);
|
||||
},this);
|
||||
|
||||
var game = this;
|
||||
var onCancel = null;
|
||||
if (msg.cancelable) {
|
||||
onCancel = function () {
|
||||
game.input('PAY_ENER',null);
|
||||
}
|
||||
}
|
||||
this.dialog.selectEner(Localize('buttonTitle','PAY_ENER'),cards,msg.colors,msg,function (selectedIndexes) {
|
||||
game.input('PAY_ENER',selectedIndexes);
|
||||
},onCancel);
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handleShowCards = function (msg) {
|
||||
if (this.skip) return true;
|
||||
var cards = msg.cards.map(function (sid,idx) {
|
||||
var card = this.getObjBySid(sid);
|
||||
card.pid = msg.pids[idx];
|
||||
return card;
|
||||
},this);
|
||||
var game = this;
|
||||
var label = msg.label || 'CONFIRM';
|
||||
this.dialog.showCards(Localize('buttonTitle',label),cards,function () {
|
||||
game.input('OK');
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handleShowCardsById = function (msg) {
|
||||
if (this.skip) return true;
|
||||
var cards = msg.ids.map(function (pid,idx) {
|
||||
return {pid: pid};
|
||||
},this);
|
||||
var game = this;
|
||||
var label = msg.label || 'CONFIRM';
|
||||
this.dialog.showCards(Localize('buttonTitle',label),cards,function () {
|
||||
game.input('OK');
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handleShowColors = function (msg) {
|
||||
if (this.skip) return true;
|
||||
var colors = msg.colors.map(function (color) {
|
||||
return Localize.color(color);
|
||||
});
|
||||
var game = this;
|
||||
this.dialog.showText(Localize('buttonTitle','COLOR'),colors.join(','),function () {
|
||||
game.input('OK');
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handleShowTypes = function (msg) {
|
||||
if (this.skip) return true;
|
||||
var types = msg.types.map(function (type) {
|
||||
return Localize('cardType',type);
|
||||
});
|
||||
var game = this;
|
||||
this.dialog.showText(Localize('prop','cardType'),types.join(','),function () {
|
||||
game.input('OK');
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handleShowEffects = function (msg) {
|
||||
if (this.skip) return true;
|
||||
var text = msg.effects.map(function (desc) {
|
||||
return Localize.desc(desc);
|
||||
}).join('\n');
|
||||
var game = this;
|
||||
this.dialog.showText(Localize('gameText','SHOW_EFFECTS_DIALOG_TITLE'),text,function () {
|
||||
game.input('OK');
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handleShowText = function (msg) {
|
||||
if (this.skip) return true;
|
||||
var text = '';
|
||||
if (msg.type === 'number') {
|
||||
text = msg.content;
|
||||
} else {
|
||||
debugger;
|
||||
}
|
||||
var game = this;
|
||||
this.dialog.showText(Localize.labelToDialogTitle(msg.title),text,function () {
|
||||
game.input('OK');
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handleInformCards = function (msg) {
|
||||
msg.cards.forEach(function (sid,idx) {
|
||||
var card = this.getObjBySid(sid);
|
||||
card.pid = msg.pids[idx];
|
||||
},this);
|
||||
return true;
|
||||
};
|
||||
|
||||
// Game.prototype.handlePower = function (msg) {
|
||||
// msg.cards.forEach(function (sid,idx) {
|
||||
// var card = this.getObjBySid(sid);
|
||||
// card.zone.power = msg.powers[idx];
|
||||
// },this);
|
||||
// return true;
|
||||
// };
|
||||
|
||||
Game.prototype.handleCardStates = function (msg) {
|
||||
var signiInfos = msg.signiInfos;
|
||||
var lrigInfos = msg.lrigInfos;
|
||||
var zoneInfos = msg.zoneInfos;
|
||||
signiInfos.forEach(function (signiInfo) {
|
||||
var card = this.getObjBySid(signiInfo.card);
|
||||
card.zone.power = signiInfo.power;
|
||||
card.removeStates();
|
||||
card.addStates(signiInfo.states);
|
||||
},this);
|
||||
lrigInfos.forEach(function (lrigInfo) {
|
||||
var card = this.getObjBySid(lrigInfo.card);
|
||||
card.removeStates();
|
||||
card.addStates(lrigInfo.states);
|
||||
},this);
|
||||
if (zoneInfos) { // 向前兼容
|
||||
zoneInfos.forEach(function (zoneInfo) {
|
||||
var zone = this.getObjBySid(zoneInfo.zone);
|
||||
zone.removeStates();
|
||||
zone.addStates(zoneInfo.states);
|
||||
},this);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handleActivate = function (msg) {
|
||||
var card = this.getObjBySid(msg.card);
|
||||
card.shine();
|
||||
return false;
|
||||
};
|
||||
|
||||
Game.prototype.handleCardSelected = function (msg) {
|
||||
var card = this.getObjBySid(msg.card);
|
||||
card.flash();
|
||||
return false;
|
||||
};
|
||||
|
||||
Game.prototype.handleSelectNumber = function (msg) {
|
||||
if (this.skip) return true;
|
||||
var label = msg.label;
|
||||
var min = msg.min;
|
||||
var max = msg.max;
|
||||
var defaultValue = msg.defaultValue || 0;
|
||||
var title = Localize.labelToDialogTitle(label);
|
||||
// var options = [];
|
||||
// var n = min;
|
||||
// while (n <= max) {
|
||||
// options.push(n++);
|
||||
// }
|
||||
// var game = this;
|
||||
// this.dialog.selectText(title,options,false,function (idx) {
|
||||
// game.input(label,min+idx);
|
||||
// });
|
||||
var game = this;
|
||||
this.dialog.selectNumber(title,min,max,defaultValue,false,function (num) {
|
||||
game.input(label,num);
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handleSelectText = function (msg) {
|
||||
if (this.skip) return true;
|
||||
var label = msg.label;
|
||||
var title = Localize.labelToDialogTitle(label);
|
||||
var type = msg.type || 'gameText';
|
||||
var options = msg.texts.map(function (text) {
|
||||
return Localize(type,text);
|
||||
},this);
|
||||
var game = this;
|
||||
this.dialog.selectText(title,options,false,function (idx) {
|
||||
game.input(label,idx);
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handleSelectCardId = function (msg) {
|
||||
if (this.skip) return true;
|
||||
try {
|
||||
var game = this;
|
||||
var label = msg.label;
|
||||
var title = Localize.labelToDialogTitle(label);
|
||||
this.dialog.selectCardId(title,function (pid) {
|
||||
game.input(label,pid);
|
||||
});
|
||||
} catch (e) {
|
||||
window.alert(e.name + e.message);
|
||||
}
|
||||
// console.log('game.input(' + label + ',pid)');
|
||||
// debugger;
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handleConfirm = function (msg) {
|
||||
if (this.skip) return true;
|
||||
var title = Localize.labelToDialogTitle('CONFIRM');
|
||||
var text = Localize('gameText',msg.text);
|
||||
var game = this;
|
||||
this.dialog.confirm(title,text,function (answer) {
|
||||
game.input('OK',answer);
|
||||
});
|
||||
return true;
|
||||
};
|
||||
|
||||
// Game.prototype.handleWaitForOpponent = function (msg) {
|
||||
// if (this._waiting) {
|
||||
// this.buttonZone.setText(Localize.waitingMsg());
|
||||
// } else {
|
||||
// this._waiting = true;
|
||||
// this.buttonZone.setText(Localize.waitingMsg(msg.operation));
|
||||
// }
|
||||
// this.background.setWaiting(true);
|
||||
// return true;
|
||||
// };
|
||||
|
||||
// Game.prototype.handleRockPaperScissors = function (msg) {
|
||||
// var title = Localize('ROCK_PAPER_SCISSORS');
|
||||
// var options = [
|
||||
// Localize('ROCK'),
|
||||
// Localize('PAPER'),
|
||||
// Localize('SCISSORS')
|
||||
// ];
|
||||
// var game = this;
|
||||
// this.dialog.selectText(title,options,false,function (idx) {
|
||||
// game.input('ROCK_PAPER_SCISSORS',idx);
|
||||
// });
|
||||
// return true;
|
||||
// };
|
||||
|
||||
Game.prototype.handleWin = function (msg) {
|
||||
this.win();
|
||||
};
|
||||
|
||||
Game.prototype.win = function (surrender) {
|
||||
// var gameCount = sessionStorage.getItem('game count') || 0;
|
||||
// gameCount++;
|
||||
// sessionStorage.setItem('game count',gameCount);
|
||||
// this.audio.playBgm();
|
||||
// this.dialog.showText('WIN',text,function () {
|
||||
// this.supportWebxoss(this.ongameover);
|
||||
// }.bind(this));
|
||||
this.ongameover(true,surrender,this.getMessagePacks());
|
||||
};
|
||||
|
||||
// Game.prototype.supportWebxoss = function (callback) {
|
||||
// if (this.shouldPopSupport()) {
|
||||
// var title = 'SUPPORT WEBXOSS';
|
||||
// var body = this.dialog.newElement('div');
|
||||
// var link = this.dialog.newElement('a');
|
||||
// link.target = '_blank';
|
||||
// link.style.color = 'red';
|
||||
// link.style.textDecoration = 'underline';
|
||||
// link.href = Localize('index','SUPPORT_URL');
|
||||
// link.textContent = 'help';
|
||||
// link.onclick = function () {
|
||||
// localStorage.setItem('support','webxoss~');
|
||||
// return true;
|
||||
// }
|
||||
// body.appendChild(document.createTextNode('WEBXOSS needs your '));
|
||||
// body.appendChild(link);
|
||||
// body.appendChild(document.createTextNode('!'));
|
||||
// body.style.color = 'green';
|
||||
// this.dialog.pop(title,body,false,callback);
|
||||
// } else {
|
||||
// callback();
|
||||
// }
|
||||
// };
|
||||
|
||||
// Game.prototype.shouldPopSupport = function () {
|
||||
// if (localStorage.getItem('support') === 'webxoss~') return false;
|
||||
// var gameCount = sessionStorage.getItem('game count') || 0;
|
||||
// if (gameCount >= 4) return true;
|
||||
// return false;
|
||||
// };
|
||||
|
||||
Game.prototype.handleLose = function (msg) {
|
||||
this.lose();
|
||||
};
|
||||
|
||||
Game.prototype.lose = function (surrender) {
|
||||
// var gameCount = sessionStorage.getItem('game count') || 0;
|
||||
// gameCount++;
|
||||
// sessionStorage.setItem('game count',gameCount);
|
||||
// this.audio.playBgm();
|
||||
// this.dialog.showText('LOSE',text,this.ongameover);
|
||||
this.ongameover(false,surrender,this.getMessagePacks());
|
||||
};
|
||||
|
||||
Game.prototype.getMessagePacks = function () {
|
||||
// var datas = this.io.getDatas();
|
||||
// return {
|
||||
// format: 'WEBXOSS Replay',
|
||||
// version: '1',
|
||||
// content: {
|
||||
// clietVersion: this.version,
|
||||
// messagePacks: this.io.getDatas();
|
||||
// }
|
||||
// };
|
||||
return this.io.getDatas();
|
||||
};
|
||||
|
||||
Game.prototype.handleMsg = function (msg) {
|
||||
if (!msg) return false;
|
||||
var handlerMap = {
|
||||
'INIT': this.handleInit,
|
||||
'SET_COLOR': this.handleSetColor,
|
||||
'PACKED_MSG_START': this.handlePackedMsgStart,
|
||||
'PACKED_MSG_END': this.handlePackedMsgEnd,
|
||||
'MOVE_CARD': this.handleMoveCard,
|
||||
'UP_CARD': this.handleUpCard,
|
||||
'DOWN_CARD': this.handleDownCard,
|
||||
'FACEUP_CARD': this.handleFaceupCard,
|
||||
'FACEDOWN_CARD': this.handleFacedownCard,
|
||||
'SHUFFLE': this.handleShuffle,
|
||||
'SELECT': this.handleSelect,
|
||||
'PAY_ENER': this.handlePayEner,
|
||||
'SHOW_CARDS': this.handleShowCards,
|
||||
'SHOW_CARDS_BY_ID': this.handleShowCardsById,
|
||||
'SHOW_COLORS': this.handleShowColors,
|
||||
'SHOW_TYPES': this.handleShowTypes,
|
||||
'SHOW_EFFECTS': this.handleShowEffects,
|
||||
'SHOW_TEXT': this.handleShowText,
|
||||
'INFORM_CARDS': this.handleInformCards,
|
||||
// 'POWER': this.handlePower,
|
||||
'CARD_STATES': this.handleCardStates,
|
||||
'ACTIVATE': this.handleActivate,
|
||||
'CARD_SELECTED': this.handleCardSelected,
|
||||
'SELECT_NUMBER': this.handleSelectNumber,
|
||||
'SELECT_TEXT': this.handleSelectText,
|
||||
'SELECT_CARD_ID': this.handleSelectCardId,
|
||||
'CONFIRM': this.handleConfirm,
|
||||
// 'ROCK_PAPER_SCISSORS': this.handleRockPaperScissors,
|
||||
// 'WAIT_FOR_OPPONENT': this.handleWaitForOpponent,
|
||||
'WIN': this.handleWin,
|
||||
'LOSE': this.handleLose
|
||||
};
|
||||
var handler = handlerMap[msg.type];
|
||||
if (handler) {
|
||||
return handler.call(this,msg.content) || this.skip;
|
||||
}
|
||||
console.warn(msg);
|
||||
window.alert('Unknown message type: "' + msg.type + '" .');
|
||||
return true;
|
||||
};
|
||||
|
||||
Game.prototype.handleMsgQueue = function () {
|
||||
if (!this.msgQueue.length) return;
|
||||
// this._waiting = false;
|
||||
this.buttonZone.setText('');
|
||||
this.background.setWaiting(false);
|
||||
|
||||
var done = true;
|
||||
var msg;
|
||||
while (msg = this.msgQueue.shift()) {
|
||||
if (!this.handleMsg(msg)) done = false;
|
||||
if (!done && !this._packageCount) break;
|
||||
}
|
||||
if (!this.msgQueue.length) {
|
||||
this.handleIdle();
|
||||
}
|
||||
};
|
||||
|
||||
Game.prototype.handleIdle = function () {
|
||||
this.selector.removeButtons();
|
||||
this.selector.showButtons();
|
||||
this.selector.autoPop();
|
||||
if (!this.selector.msgs.length) {
|
||||
this.buttonZone.setText(Localize.waitingMsg());
|
||||
this.background.setWaiting(true);
|
||||
}
|
||||
if (this.onidle) this.onidle();
|
||||
};
|
||||
|
||||
Game.prototype.addMsgs = function (msgs) {
|
||||
this.selector.clear();
|
||||
this.msgQueue = this.msgQueue.concat(msgs);
|
||||
if (!msgs.length) {
|
||||
this.handleIdle();
|
||||
}
|
||||
};
|
||||
|
||||
Game.prototype.input = function (label,data) {
|
||||
if (data === undefined) {
|
||||
data = [];
|
||||
}
|
||||
this.removeButtons();
|
||||
this.io.send({
|
||||
label: label,
|
||||
input: data
|
||||
});
|
||||
this.background.setWaiting(true);
|
||||
};
|
||||
|
||||
Game.prototype.removeButtons = function () {
|
||||
this.cards.forEach(function (card) {
|
||||
card.removeButtons();
|
||||
},this);
|
||||
this.zones.forEach(function (zone) {
|
||||
zone.removeButtons();
|
||||
},this);
|
||||
// this.dialog.close();
|
||||
};
|
||||
|
||||
Game.prototype.update = function () {
|
||||
var changed = false;
|
||||
concat(this.cards,this.zones,this.background).forEach(function (obj) {
|
||||
if (obj.update()) changed = true;
|
||||
},this);
|
||||
|
||||
if (changed) {
|
||||
this.cardLayer.sortChildren(function (a,b) {
|
||||
return a.zIndex - b.zIndex;
|
||||
});
|
||||
this.stage.update();
|
||||
} else {
|
||||
this.handleMsgQueue();
|
||||
}
|
||||
};
|
91
GameAudio.js
Normal file
|
@ -0,0 +1,91 @@
|
|||
'use strict';
|
||||
|
||||
function GameAudio () {
|
||||
this.bgm = document.getElementById('audio-bgm');
|
||||
this.soundEffect = document.getElementById('audio-sound-effect');
|
||||
this.bgmCheckBox = document.getElementById('checkbox-bgm');
|
||||
this.seCheckBox = document.getElementById('checkbox-sound-effect');
|
||||
this.bgmDisabled = false;
|
||||
this.seDisabled = false;
|
||||
this.lastPlay = '';
|
||||
this.map = {
|
||||
'white': 'WhiteAng',
|
||||
'black': 'DarkFßen',
|
||||
'red': 'reLEIdEN',
|
||||
'blue': 'Süblueß',
|
||||
'green': 'GreenWi',
|
||||
'NevWorry': 'NevWorry',
|
||||
'main': 'Love Your Enemies.W',
|
||||
'Battle': 'バトル!'
|
||||
}
|
||||
this.loadSettings();
|
||||
}
|
||||
|
||||
GameAudio.prototype.loadSettings = function () {
|
||||
if (localStorage.getItem('bgm') === 'disabled') {
|
||||
this.bgmDisabled = true;
|
||||
}
|
||||
if (localStorage.getItem('sound effect') === 'disabled') {
|
||||
this.seDisabled = true;
|
||||
}
|
||||
this.bgmCheckBox.checked = !this.bgmDisabled;
|
||||
this.seCheckBox.checked = !this.seDisabled;
|
||||
};
|
||||
|
||||
GameAudio.prototype.disableBgm = function (flag) {
|
||||
if (flag) {
|
||||
this.bgmDisabled = true;
|
||||
localStorage.setItem('bgm','disabled');
|
||||
this.bgm.pause();
|
||||
this.bgm.src = '';
|
||||
} else {
|
||||
this.bgmDisabled = false;
|
||||
localStorage.setItem('bgm','enabled');
|
||||
this.bgm.src = this.lastPlay;
|
||||
this.bgm.play();
|
||||
}
|
||||
};
|
||||
|
||||
GameAudio.prototype.disableSoundEffect = function (flag) {
|
||||
if (flag) {
|
||||
this.seDisabled = true;
|
||||
localStorage.setItem('sound effect','disabled');
|
||||
} else {
|
||||
this.bgmDisabled = false;
|
||||
localStorage.setItem('sound effect','enabled');
|
||||
}
|
||||
};
|
||||
|
||||
GameAudio.prototype.bgmFadeOut = function (callback) {
|
||||
var bgm = this.bgm;
|
||||
var timer = setInterval(function () {
|
||||
if (bgm.volume <= 0.2) {
|
||||
bgm.volume = 0;
|
||||
clearInterval(timer);
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
bgm.volume -= 0.2;
|
||||
},200);
|
||||
};
|
||||
|
||||
GameAudio.prototype.playBgm = function (code) {
|
||||
if (!code) {
|
||||
this.bgm.src = '';
|
||||
this.lastPlay = '';
|
||||
return;
|
||||
}
|
||||
var src = './background/' + this.map[code] + '.mp3';
|
||||
if (this.lastPlay === src) return;
|
||||
this.lastPlay = src;
|
||||
if (this.bgmDisabled) return;
|
||||
this.bgm.src = src;
|
||||
this.bgm.volume = 1;
|
||||
this.bgm.play();
|
||||
};
|
||||
|
||||
GameAudio.prototype.playSoundEffect = function (name) {
|
||||
if (this.seDisabled) return;
|
||||
this.soundEffect.src = './background/' + name + '.mp3';
|
||||
this.soundEffect.play();
|
||||
};
|
68
GameBackground.js
Normal file
|
@ -0,0 +1,68 @@
|
|||
'use strict';
|
||||
|
||||
function GameBackground (game) {
|
||||
createjs.Container.prototype.initialize.call(this);
|
||||
|
||||
this.game = game;
|
||||
this.width = game.stage.canvas.width;
|
||||
this.height = game.stage.canvas.height;
|
||||
|
||||
this.changed = true;
|
||||
|
||||
// this.imageWhite = this.newImage('./background/white.png');
|
||||
// this.imageBlack = this.newImage('./background/black.png');
|
||||
// this.imageGreen = this.newImage('./background/green.png');
|
||||
// this.imageBlue = this.newImage('./background/blue.png');
|
||||
// this.imageRed = this.newImage('./background/red.png');
|
||||
|
||||
// this.selfBackground = new createjs.Bitmap('');
|
||||
// this.opponentBackground = new createjs.Bitmap('');
|
||||
|
||||
// this.selfBackground.x = 0;
|
||||
// this.selfBackground.y = 367;
|
||||
// this.opponentBackground.regX = 576;
|
||||
// this.opponentBackground.regY = 368;
|
||||
// this.opponentBackground.rotation = 180;
|
||||
|
||||
this.mask = new createjs.Shape();
|
||||
// this.addChild(this.selfBackground,this.opponentBackground,this.mask);
|
||||
this.addChild(this.mask);
|
||||
}
|
||||
|
||||
GameBackground.prototype = new createjs.Container();
|
||||
GameBackground.prototype.constructor = GameBackground;
|
||||
|
||||
// GameBackground.prototype.newImage = function (src) {
|
||||
// var img = new Image();
|
||||
// img.src = src;
|
||||
// return img;
|
||||
// };
|
||||
// GameBackground.prototype.setColor = function (selfColor,opponentColor) {
|
||||
// var imageMap = {
|
||||
// 'white': this.imageWhite,
|
||||
// 'black': this.imageBlack,
|
||||
// 'green': this.imageGreen,
|
||||
// 'blue': this.imageBlue,
|
||||
// 'red': this.imageRed
|
||||
// }
|
||||
// this.selfBackground.image = imageMap[selfColor];
|
||||
// this.opponentBackground.image = imageMap[opponentColor];
|
||||
// this.changed = true;
|
||||
// };
|
||||
GameBackground.prototype.setWaiting = function (waiting) {
|
||||
if (waiting) {
|
||||
this.mask.graphics
|
||||
.clear()
|
||||
.beginFill('rgba(0,0,0,0.25)')
|
||||
.drawRect(0,0,this.width,this.height);
|
||||
} else {
|
||||
this.mask.graphics.clear();
|
||||
}
|
||||
this.changed = true;
|
||||
};
|
||||
|
||||
GameBackground.prototype.update = function () {
|
||||
var changed = this.changed;
|
||||
this.changed = false;
|
||||
return changed;
|
||||
};
|
78
IO.js
Normal file
|
@ -0,0 +1,78 @@
|
|||
'use strict';
|
||||
|
||||
/*
|
||||
服务器 -> 客户端:
|
||||
msg = {
|
||||
buffer: [{
|
||||
id: id,
|
||||
data: []
|
||||
}]
|
||||
}
|
||||
客户端 -> 服务器
|
||||
msg = {
|
||||
id: id,
|
||||
data: {
|
||||
label: label,
|
||||
input: []
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
function IO (socket) {
|
||||
this.socket = socket;
|
||||
this.listener = null;
|
||||
this.sendingMsg = null; // 上次发送的信息,用于重连时重新发送.
|
||||
this.datas = []; // 收到的数据.
|
||||
this.id = 0;
|
||||
|
||||
// For test
|
||||
this.inputBlocked = false;
|
||||
this.outputBlocked = false;
|
||||
|
||||
this.socket.removeAllListeners('gameMessage');
|
||||
this.socket.on('gameMessage',this.receiveGameMessage.bind(this));
|
||||
};
|
||||
|
||||
IO.prototype.receiveGameMessage = function (msg) {
|
||||
if (this.inputBlocked) return;
|
||||
msg.buffer.forEach(function (buf) {
|
||||
if (buf.id < this.datas.length) return;
|
||||
if (buf.id !== this.datas.length) {
|
||||
console.error('buf.id !== this.datas.length');
|
||||
return;
|
||||
}
|
||||
this.sendingMsg = null;
|
||||
this.datas.push(buf.data);
|
||||
if (this.listener) {
|
||||
this.listener(buf.data);
|
||||
}
|
||||
},this);
|
||||
};
|
||||
|
||||
IO.prototype.send = function (data) {
|
||||
this.id++;
|
||||
this.sendingMsg = {
|
||||
id: this.id,
|
||||
data: data
|
||||
};
|
||||
if (this.outputBlocked) return;
|
||||
this.socket.emit('gameMessage',this.sendingMsg);
|
||||
};
|
||||
|
||||
IO.prototype.resend = function () {
|
||||
if (!this.sendingMsg) return;
|
||||
this.socket.emit('gameMessage',this.sendingMsg);
|
||||
};
|
||||
|
||||
IO.prototype.getDatas = function () {
|
||||
return this.datas;
|
||||
};
|
||||
|
||||
// For test
|
||||
IO.prototype.toggleIn = function () {
|
||||
return this.inputBlocked = !this.inputBlocked;
|
||||
};
|
||||
|
||||
IO.prototype.toggleOut = function () {
|
||||
return this.outputBlocked = !this.outputBlocked;
|
||||
};
|
1
ImageAndDetail.min.js
vendored
Normal file
161
ImageFileCache.js
Normal file
|
@ -0,0 +1,161 @@
|
|||
'use strict';
|
||||
|
||||
window.ImageFileCache = (function () {
|
||||
|
||||
function checkIndexedDBSupport (callback) {
|
||||
var db = null;
|
||||
function done(supportIndexedDB,supportBlob) {
|
||||
if (db) db.close();
|
||||
callback(!!supportIndexedDB,!!supportBlob);
|
||||
}
|
||||
if (!window.indexedDB) return done();
|
||||
if (!window.IDBKeyRange) return done();
|
||||
if (!window.IDBOpenDBRequest) return done();
|
||||
// shit iOS
|
||||
// var iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
|
||||
// if (iOS) return done();
|
||||
// ios 8
|
||||
var open = indexedDB.open('test indexedDB support',1);
|
||||
if (!('onupgradeneeded' in open)) return done();
|
||||
open.onupgradeneeded = function (event) {
|
||||
db = this.result;
|
||||
db.createObjectStore('one');
|
||||
db.createObjectStore('two',{keyPath: 'key'});
|
||||
};
|
||||
open.onerror = function (event) {
|
||||
done();
|
||||
};
|
||||
open.onsuccess = function (event) {
|
||||
db = this.result;
|
||||
db.onerror = function (event) {
|
||||
done();
|
||||
};
|
||||
var transaction;
|
||||
try {
|
||||
transaction = db.transaction(['one','two'],'readwrite');
|
||||
} catch (e) {
|
||||
return done();
|
||||
}
|
||||
var req = transaction.objectStore('two').put({key: 1});
|
||||
req.onsuccess = function (event) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.responseType = 'blob';
|
||||
if (!window.Blob || !window.URL || (xhr.responseType !== 'blob')) {
|
||||
db.close();
|
||||
return done(true,false);
|
||||
} else {
|
||||
var blob = new Blob(['text'], {type: 'text/plain'});
|
||||
try {
|
||||
req = transaction.objectStore('one').put(blob,'blob');
|
||||
transaction.onabort = function (event) {
|
||||
event.stopPropagation();
|
||||
done(true,false);
|
||||
};
|
||||
transaction.onerror = function (event) {
|
||||
event.stopPropagation();
|
||||
done(true,false);
|
||||
};
|
||||
transaction.oncomplete = function (event) {
|
||||
return done(true,true);
|
||||
};
|
||||
} catch (e) {
|
||||
return done(true,false);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function get (url,type,callback,err) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.responseType = type;
|
||||
xhr.onload = function (e) {
|
||||
if (xhr.status !== 200) {
|
||||
err(xhr,e);
|
||||
} else {
|
||||
callback(xhr,e);
|
||||
}
|
||||
};
|
||||
xhr.onerror = function (e) {
|
||||
err(xhr,e);
|
||||
};
|
||||
xhr.open('GET',url,true);
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function cache (pid,blob) {
|
||||
if (!ImageFileCache.supportBlob) return;
|
||||
if (pid in urlMap) return;
|
||||
var url = window.URL.createObjectURL(blob);
|
||||
urlMap[pid] = url;
|
||||
var open = indexedDB.open('card images',1);
|
||||
open.onupgradeneeded = function (event) {
|
||||
this.result.createObjectStore('images');
|
||||
};
|
||||
open.onsuccess = function (event) {
|
||||
var db = this.result;
|
||||
db.transaction(['images'],'readwrite').objectStore('images').add(blob,pid);
|
||||
};
|
||||
}
|
||||
|
||||
var urlMap = {};
|
||||
var fetchingMap = {};
|
||||
var ImageFileCache = {
|
||||
supportIndexedDB: false,
|
||||
supportBlob: false
|
||||
};
|
||||
var supportObjectURL = false; // 在360浏览器上,ObjectURL可能不能用.
|
||||
|
||||
// 检查支持并读取缓存
|
||||
checkIndexedDBSupport(function (supportIndexedDB,supportBlob) {
|
||||
ImageFileCache.supportIndexedDB = supportIndexedDB;
|
||||
ImageFileCache.supportBlob = supportBlob;
|
||||
if (!supportBlob) return;
|
||||
var open = indexedDB.open('card images',1);
|
||||
open.onupgradeneeded = function (event) {
|
||||
this.result.createObjectStore('images');
|
||||
};
|
||||
open.onsuccess = function (event) {
|
||||
var db = this.result;
|
||||
var checked = false;
|
||||
db.transaction(['images']).objectStore('images').openCursor().onsuccess = function (event) {
|
||||
var cursor = this.result;
|
||||
if (!cursor) return;
|
||||
var pid = cursor.key;
|
||||
var blob = cursor.value;
|
||||
var url = window.URL.createObjectURL(blob);
|
||||
if (!checked) {
|
||||
checked = true;
|
||||
var img = new Image();
|
||||
img.onload = function () {
|
||||
supportObjectURL = true;
|
||||
console.log('supportObjectURL');
|
||||
};
|
||||
img.src = url;
|
||||
}
|
||||
urlMap[pid] = url;
|
||||
cursor.continue();
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
ImageFileCache.getUrlByPid = function (pid) {
|
||||
if (!supportObjectURL) return '';
|
||||
return urlMap[pid] || '';
|
||||
};
|
||||
|
||||
ImageFileCache.fetchAndCache = function (pid,url) {
|
||||
if (!ImageFileCache.supportBlob) return;
|
||||
if (fetchingMap[pid]) return;
|
||||
fetchingMap[pid] = true;
|
||||
get(url,'blob',function (xhr,e) {
|
||||
var blob = xhr.response;
|
||||
cache(pid,blob);
|
||||
},function (xhr,e) {
|
||||
console.log('Failed to load "' + url + '"');
|
||||
fetchingMap[pid] = false;
|
||||
});
|
||||
};
|
||||
|
||||
return ImageFileCache;
|
||||
})();
|
59
ImageManager.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
'use strict';
|
||||
|
||||
window.ImageManager = (function () {
|
||||
|
||||
function newImage (src) {
|
||||
var img = new Image();
|
||||
img.src = src;
|
||||
return img;
|
||||
}
|
||||
|
||||
|
||||
// ImageManager
|
||||
function ImageManager (dir) {
|
||||
this.dir = dir || './';
|
||||
// 缓存
|
||||
this.black = newImage(this.dir + 'images/WIXOSS_BLACK.jpg');
|
||||
this.white = newImage(this.dir + 'images/WIXOSS_WHITE.jpg');
|
||||
this.noimage = newImage(this.dir + 'images/noimage.jpg');
|
||||
this.imageCache = {};
|
||||
this.stateImageMap = {
|
||||
'frozen': newImage(this.dir + 'background/frozen.png'),
|
||||
'charm': newImage(this.dir + 'background/charm.png'),
|
||||
'lancer': newImage(this.dir + 'background/lancer.png'),
|
||||
'doubleCrash': newImage(this.dir + 'background/doubleCrash.png'),
|
||||
'locked': newImage(this.dir + 'background/locked.png'),
|
||||
'assassin': newImage(this.dir + 'background/assassin.png')
|
||||
};
|
||||
}
|
||||
|
||||
ImageManager.prototype.getUrlByPid = function (pid) {
|
||||
var url = window.ImageFileCache.getUrlByPid(pid);
|
||||
if (url) return url;
|
||||
url = this.dir + 'images/' + ('0000' + pid).slice(-4) + '.jpg';
|
||||
window.ImageFileCache.fetchAndCache(pid,url);
|
||||
return url;
|
||||
};
|
||||
|
||||
ImageManager.prototype.getImageByPid = function (pid) {
|
||||
if (!pid) return this.noimage;
|
||||
if (pid in this.imageCache) {
|
||||
return this.imageCache[pid];
|
||||
} else {
|
||||
var src = this.getUrlByPid(pid);
|
||||
var img = newImage(src);
|
||||
this.imageCache[pid] = img;
|
||||
return img;
|
||||
}
|
||||
};
|
||||
|
||||
ImageManager.prototype.getBackImage = function (isWhite) {
|
||||
return isWhite? this.white : this.black;
|
||||
};
|
||||
|
||||
ImageManager.prototype.getStateImage = function (state) {
|
||||
return this.stateImageMap[state];
|
||||
};
|
||||
|
||||
return ImageManager;
|
||||
})();
|
2106
Localize.js
Normal file
2
Localize.min.js
vendored
Normal file
83
MessageBox.js
Normal file
|
@ -0,0 +1,83 @@
|
|||
'use strict';
|
||||
|
||||
function MessageBox () {
|
||||
this.eWarp = document.getElementById('msgbox-warp');
|
||||
this.eWin = document.getElementById('msgbox-window');
|
||||
this.eMsg = document.getElementById('msgbox-msg');
|
||||
this.eInput = document.getElementById('msgbox-input');
|
||||
this.ePreset = document.getElementById('msgbox-preset');
|
||||
this.eOk = document.getElementById('msgbox-button-ok');
|
||||
this.eCancel = document.getElementById('msgbox-button-cancel');
|
||||
}
|
||||
|
||||
MessageBox.prototype.alert = function (msg,callback) {
|
||||
this.eWin.className = 'alert';
|
||||
this.eMsg.textContent = msg;
|
||||
this.eWarp.classList.add('shown');
|
||||
this.eOk.focus();
|
||||
this.eOk.onclick = function (event) {
|
||||
this.close();
|
||||
if (callback) callback();
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
MessageBox.prototype.confirm = function (msg,callback) {
|
||||
this.eWin.className = 'confirm';
|
||||
this.eMsg.textContent = msg;
|
||||
this.eWarp.classList.add('shown');
|
||||
this.eCancel.focus();
|
||||
|
||||
this.eOk.onclick = function (event) {
|
||||
this.close();
|
||||
if (callback) callback(true);
|
||||
}.bind(this);
|
||||
this.eCancel.onclick = function (event) {
|
||||
this.close();
|
||||
if (callback) callback(false);
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
MessageBox.prototype.prompt = function (msg,value,callback) {
|
||||
if (arguments.length === 2) {
|
||||
value = '';
|
||||
callback = arguments[1];
|
||||
}
|
||||
this.eWin.className = 'prompt';
|
||||
this.eMsg.textContent = msg;
|
||||
this.eInput.value = value;
|
||||
this.eWarp.classList.add('shown');
|
||||
this.eInput.select();
|
||||
|
||||
var close = function (value) {
|
||||
this.close();
|
||||
if (callback) callback(value || '');
|
||||
}.bind(this);
|
||||
|
||||
this.eOk.onclick = function (event) {
|
||||
close(this.eInput.value);
|
||||
}.bind(this);
|
||||
this.eCancel.onclick = function (event) {
|
||||
close();
|
||||
}.bind(this);
|
||||
this.eInput.onkeypress = function (event) {
|
||||
var keyCode = event.keyCode || event.which || event.charCode;
|
||||
if (keyCode !== 13) return;
|
||||
close(this.eInput.value);
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
MessageBox.prototype.preset = function (label) {
|
||||
this.eWin.className = 'preset';
|
||||
var children = this.ePreset.children;
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
var child = children[i];
|
||||
child.style.display = 'none';
|
||||
}
|
||||
document.getElementById('preset-'+label).style.display = '';
|
||||
this.eWarp.classList.add('shown');
|
||||
};
|
||||
|
||||
MessageBox.prototype.close = function () {
|
||||
this.eWarp.classList.remove('shown');
|
||||
this.eWin.className = '';
|
||||
};
|
1100
RoomManager.js
Normal file
281
Selector.js
Normal file
|
@ -0,0 +1,281 @@
|
|||
'use strict';
|
||||
|
||||
function Selector (game,spectating) {
|
||||
this.game = game;
|
||||
this.msgs = [];
|
||||
this.selectedIndexes = [];
|
||||
this._autoPopMsg = null;
|
||||
this.spectating = spectating;
|
||||
}
|
||||
|
||||
// Selector.prototype.getMsgByLabel = function (label) {
|
||||
// for (var i = 0; i < this.msgs.length; i++) {
|
||||
// var msg = this.msgs[i];
|
||||
// if (msg.label === label) {
|
||||
// return msg;
|
||||
// }
|
||||
// }
|
||||
// debugger;
|
||||
// return null;
|
||||
// };
|
||||
|
||||
Selector.prototype.addMsg = function (msg) {
|
||||
this.msgs.push(this.parseMsg(msg));
|
||||
};
|
||||
|
||||
Selector.prototype.parseMsg = function (msg) {
|
||||
var newMsg = {
|
||||
label: msg.label,
|
||||
min: msg.min,
|
||||
max: msg.max,
|
||||
careOrder: msg.careOrder
|
||||
};
|
||||
newMsg.title = Localize.labelToTitle(msg.label);
|
||||
newMsg.cards = msg.options.map(function (sid) {
|
||||
return this.game.getObjBySid(sid);
|
||||
},this);
|
||||
newMsg.extraCards = msg.extraCards.map(function (sid,idx) {
|
||||
var card = this.game.getObjBySid(sid);
|
||||
card.pid = msg.extraPids[idx];
|
||||
return card;
|
||||
},this);
|
||||
if (!newMsg.extraCards.length) {
|
||||
newMsg.extraCards = newMsg.cards.slice();
|
||||
}
|
||||
newMsg.descriptions = msg.descriptions.map(function (desc) {
|
||||
return Localize.desc(desc);
|
||||
},this);
|
||||
return newMsg;
|
||||
};
|
||||
|
||||
// Selector.prototype.parseDesc = function (desc) {
|
||||
// var arr = desc.split('-');
|
||||
// var pid = arr[0];
|
||||
// var type = arr[1];
|
||||
// var idx = arr[2];
|
||||
// var info = CardInfo[pid];
|
||||
// return Localize.desc(info,type,idx);
|
||||
// };
|
||||
|
||||
Selector.prototype.showButtons = function () {
|
||||
this.msgs.forEach(function (msg) {
|
||||
var cards = msg.extraCards;
|
||||
if (!cards.length) {
|
||||
this.game.buttonZone.addButton(Localize.noOptions(msg.label),this.selectBind(msg));
|
||||
} else if (msg.label === 'USE_ACTION_EFFECT') {
|
||||
var datas = [];
|
||||
msg.cards.forEach(function (card,idx) {
|
||||
var buttonCarrier;
|
||||
var description = msg.descriptions[idx];
|
||||
if (card.shouldUseDialog()) {
|
||||
if (card.zone.constructor === TileZone) {
|
||||
buttonCarrier = this.game.buttonZone;
|
||||
} else {
|
||||
buttonCarrier = card.zone;
|
||||
}
|
||||
} else {
|
||||
buttonCarrier = card;
|
||||
}
|
||||
var data;
|
||||
for (var i = 0; i < datas.length; i++) {
|
||||
var data= datas[i];
|
||||
if (data.buttonCarrier === buttonCarrier) {
|
||||
data.cards.push(card);
|
||||
data.descriptions.push(description);
|
||||
data.indexes.push(idx);
|
||||
return;
|
||||
};
|
||||
}
|
||||
datas.push({
|
||||
buttonCarrier: buttonCarrier,
|
||||
cards: [card],
|
||||
descriptions: [description],
|
||||
indexes: [idx]
|
||||
});
|
||||
// card.addButton(msg.title,function () {
|
||||
// var descriptions = [];
|
||||
// var indexMap = [];
|
||||
// msg.descriptions.forEach(function (description,idx) {
|
||||
// if (msg.cards[idx] === card) {
|
||||
// indexMap.push(idx);
|
||||
// descriptions.push(description);
|
||||
// }
|
||||
// },this);
|
||||
// if (descriptions.length <= 1) {
|
||||
// this.send(msg,[indexMap[0]]);
|
||||
// } else {
|
||||
// this.game.dialog.selectText(msg.title,descriptions,true,function (idx) {
|
||||
// this.send(msg,[indexMap[idx]]);
|
||||
// }.bind(this));
|
||||
// }
|
||||
// }.bind(this));
|
||||
},this);
|
||||
datas.forEach(function (data) {
|
||||
data.buttonCarrier.addButton(msg.title,function () {
|
||||
if ((data.cards.length === 1) && (data.buttonCarrier.constructor === Card)) {
|
||||
this.send(msg,[data.indexes[0]]);
|
||||
} else {
|
||||
var arg = {
|
||||
min: 1,
|
||||
max: 1,
|
||||
texts: data.descriptions,
|
||||
canClose: true,
|
||||
careOrder: false,
|
||||
targets: data.cards
|
||||
}
|
||||
this.game.dialog.selectSomeCards(msg.title,data.cards,arg,function (selectedIndexes) {
|
||||
var i = selectedIndexes[0];
|
||||
this.send(msg,[data.indexes[i]]);
|
||||
}.bind(this));
|
||||
}
|
||||
}.bind(this));
|
||||
},this);
|
||||
} else {
|
||||
var useDialog = msg.descriptions.length || cards.some(function (card) {
|
||||
return card.shouldUseDialog();
|
||||
},this);
|
||||
if (useDialog) {
|
||||
this._autoPopMsg = msg;
|
||||
var zone = cards[0].zone;
|
||||
var sameZone = cards.every(function (card) {
|
||||
return card.zone === zone;
|
||||
},this);
|
||||
if (!sameZone || zone.constructor === TileZone) {
|
||||
zone = this.game.buttonZone;
|
||||
} else if (msg.label === 'GROW') {
|
||||
// 根据 有k 的反馈,把成长按钮放到LRIG上.
|
||||
zone = this.game.player.lrigZone;
|
||||
}
|
||||
zone.addButton(msg.title,this.popDialogBind(msg));
|
||||
if (!msg.min) {
|
||||
this.game.buttonZone.addButton(Localize.giveUp(msg.label),this.sendBind(msg));
|
||||
}
|
||||
} else {
|
||||
this.showMsgButtons(msg);
|
||||
}
|
||||
}
|
||||
},this);
|
||||
};
|
||||
|
||||
Selector.prototype.select = function (msg,idx) {
|
||||
if (this.spectating) return;
|
||||
if (isNum(idx)) {
|
||||
this.selectedIndexes.push(idx);
|
||||
}
|
||||
if (this.selectedIndexes.length >= msg.max) {
|
||||
this.send(msg);
|
||||
return;
|
||||
}
|
||||
this.removeButtons();
|
||||
this.showMsgButtons(msg);
|
||||
};
|
||||
|
||||
Selector.prototype.selectBind = function (msg,idx) {
|
||||
return this.select.bind(this,msg,idx);
|
||||
};
|
||||
|
||||
Selector.prototype.unselect = function (msg,idx) {
|
||||
if (this.spectating) return;
|
||||
removeFromArr(idx,this.selectedIndexes);
|
||||
this.removeButtons();
|
||||
if (this.selectedIndexes.length) {
|
||||
this.showMsgButtons(msg);
|
||||
} else {
|
||||
this.showButtons();
|
||||
}
|
||||
};
|
||||
|
||||
Selector.prototype.unselectBind = function (msg,idx) {
|
||||
return this.unselect.bind(this,msg,idx);
|
||||
};
|
||||
|
||||
Selector.prototype.showMsgButtons = function (msg) {
|
||||
msg.cards.forEach(function (card,idx) {
|
||||
if (inArr(idx,this.selectedIndexes)) {
|
||||
card.addButton('-'+msg.title,this.unselectBind(msg,idx));
|
||||
} else {
|
||||
card.addButton(msg.title,this.selectBind(msg,idx));
|
||||
}
|
||||
},this);
|
||||
if (this.selectedIndexes.length >= msg.min) {
|
||||
var txt;
|
||||
if (this.selectedIndexes.length) {
|
||||
txt = Localize('buttonTitle','END_SELECT');
|
||||
} else {
|
||||
txt = Localize.giveUp(msg.label);
|
||||
}
|
||||
this.game.buttonZone.addButton(txt,this.sendBind(msg));
|
||||
}
|
||||
};
|
||||
|
||||
Selector.prototype.send = function (msg,selectedIndexes) {
|
||||
if (this.spectating) return;
|
||||
if (!isArr(selectedIndexes)) {
|
||||
selectedIndexes = this.selectedIndexes;
|
||||
}
|
||||
|
||||
this.game.input(msg.label,selectedIndexes.slice());
|
||||
console.log('game.input("'+msg.label+'",['+selectedIndexes.toString()+']);');
|
||||
|
||||
this.clear();
|
||||
};
|
||||
|
||||
Selector.prototype.sendBind = function (msg) {
|
||||
return this.send.bind(this,msg);
|
||||
};
|
||||
|
||||
Selector.prototype.popDialog = function (msg) {
|
||||
var title = Localize.labelToDialogTitle(msg.label);
|
||||
var cards = msg.extraCards;
|
||||
// if (msg.min === 1 && msg.max === 1) {
|
||||
// if (msg.descriptions.length) {
|
||||
// var sample = cards[0];
|
||||
// var sameCard = cards.every(function (card) {
|
||||
// return card === sample;
|
||||
// },this);
|
||||
// if (sameCard) {
|
||||
// this.game.dialog.selectText(title,msg.descriptions,true,function (idx) {
|
||||
// this.send(msg,[idx]);
|
||||
// }.bind(this));
|
||||
// return;
|
||||
// }
|
||||
// } else {
|
||||
// this.game.dialog.selectCard(title,msg.cards,true,function (idx) {
|
||||
// this.send(msg,[idx]);
|
||||
// }.bind(this));
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
var arg = {
|
||||
min: msg.min,
|
||||
max: msg.max,
|
||||
texts: msg.descriptions,
|
||||
canClose: true,
|
||||
careOrder: msg.careOrder,
|
||||
targets: msg.cards
|
||||
};
|
||||
this.game.dialog.selectSomeCards(title,cards,arg,this.sendBind(msg));
|
||||
};
|
||||
|
||||
Selector.prototype.popDialogBind = function (msg) {
|
||||
return this.popDialog.bind(this,msg);
|
||||
};
|
||||
|
||||
Selector.prototype.removeButtons = function () {
|
||||
this.game.removeButtons();
|
||||
};
|
||||
|
||||
Selector.prototype.autoPop = function () {
|
||||
if (this.msgs.length === 1 && this._autoPopMsg) {
|
||||
if (this._autoPopMsg.label === 'SPELL_CUT_IN') return;
|
||||
this.popDialog(this._autoPopMsg);
|
||||
}
|
||||
};
|
||||
|
||||
Selector.prototype.clear = function () {
|
||||
this.removeButtons();
|
||||
this.game.dialog.close();
|
||||
this.selectedIndexes.length = 0;
|
||||
this.msgs.length = 0;
|
||||
this._autoPopMsg = null;
|
||||
};
|
8
StateBitmap.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
function StateBitmap (url) {
|
||||
var bitmap = new createjs.Bitmap(url);
|
||||
bitmap.width = Card.WIDTH;
|
||||
bitmap.height = Card.HEIGHT;
|
||||
return bitmap;
|
||||
}
|
104
Style.js
Normal file
|
@ -0,0 +1,104 @@
|
|||
function Style (defaultStyle) {
|
||||
this.transitingStyle = {};
|
||||
for (var prop in defaultStyle) {
|
||||
this.transitingStyle[prop] = new TransitingValue(defaultStyle[prop]);
|
||||
}
|
||||
this.changed = true;
|
||||
this.checkSkip = null;
|
||||
}
|
||||
|
||||
Style.linear = function (t) {
|
||||
return t;
|
||||
};
|
||||
|
||||
Style.prototype.transit = function (prop,value,duration,timing) {
|
||||
if (this.checkSkip && this.checkSkip()) duration = 0;
|
||||
this.transitingStyle[prop].transitTo(value,duration,timing);
|
||||
this.changed = true;
|
||||
};
|
||||
|
||||
Style.prototype.set = function (prop,value) {
|
||||
this.transit(prop,value);
|
||||
};
|
||||
|
||||
Style.prototype.getComputedStyle = function () {
|
||||
var computedStyle = {};
|
||||
for (var prop in this.transitingStyle) {
|
||||
computedStyle[prop] = this.transitingStyle[prop].getValue();
|
||||
if (!this.transitingStyle[prop].isDone()) this.changed = true;
|
||||
}
|
||||
return computedStyle;
|
||||
};
|
||||
|
||||
Style.prototype.isChanged = function () {
|
||||
var changed = this.changed;
|
||||
this.changed = false;
|
||||
return changed;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function TransitingValue (endValue) {
|
||||
this.changeTime = 0;
|
||||
this.startValue = endValue;
|
||||
this.endValue = endValue;
|
||||
this.duration = 0;
|
||||
this.timing = TransitingValue.cubic;
|
||||
|
||||
this.done = false;
|
||||
}
|
||||
|
||||
TransitingValue.linear = function (t) {
|
||||
return t;
|
||||
};
|
||||
|
||||
// TransitingValue.cos = function (t) {
|
||||
// return (1-Math.cos(t*Math.PI))/2;
|
||||
// };
|
||||
|
||||
TransitingValue.cubic = function (t) {
|
||||
var s = 1-t;
|
||||
return 1-s*s*s;
|
||||
};
|
||||
|
||||
TransitingValue.prototype.now = function () {
|
||||
return Date.now();
|
||||
};
|
||||
|
||||
TransitingValue.prototype.transitTo = function (value,duration,timing) {
|
||||
this.startValue = this.getValue();
|
||||
this.endValue = value;
|
||||
this.duration = duration || 0;
|
||||
this.timing = timing || TransitingValue.cubic;
|
||||
this.changeTime = this.now();
|
||||
this.done = false;
|
||||
};
|
||||
|
||||
TransitingValue.prototype.getValue = function () {
|
||||
var currentTime = this.now();
|
||||
var startTime = this.changeTime;
|
||||
var endTime = startTime + this.duration*1000;
|
||||
|
||||
if (currentTime < startTime) {
|
||||
return this.startValue;
|
||||
}
|
||||
if (currentTime >= endTime || this.startValue === this.endValue) {
|
||||
this.done = true;
|
||||
return this.endValue;
|
||||
}
|
||||
if (!isNum(this.endValue)) {
|
||||
return this.startValue;
|
||||
}
|
||||
|
||||
var factor = this.timing((currentTime-startTime)/(endTime-startTime));
|
||||
return this.startValue + factor*(this.endValue-this.startValue);
|
||||
};
|
||||
|
||||
TransitingValue.prototype.isDone = function () {
|
||||
return this.done;
|
||||
};
|
52
TextDialog.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
'use strict';
|
||||
|
||||
function TextDialog (game) {
|
||||
this.game = game;
|
||||
|
||||
}
|
||||
|
||||
TextDialog.prototype.newElement = function (tag) {
|
||||
return document.createElement(tag);
|
||||
};
|
||||
|
||||
TextDialog.prototype.selectOne = function (title,texts,callback) {
|
||||
var dialog = this;
|
||||
var ol = this.newElement('div');
|
||||
texts.forEach(function (text,idx) {
|
||||
var li = this.newElement('div');
|
||||
li.textContent = text;
|
||||
ol.appendChild(li);
|
||||
|
||||
li.onclick = function (event) {
|
||||
dialog.close();
|
||||
callback(idx);
|
||||
}
|
||||
},this);
|
||||
|
||||
this.titleDiv.textContent = title;
|
||||
this.bodyDiv.innerHTML = '';
|
||||
this.bodyDiv.appendChild(ol);
|
||||
this.okButton.hidden = true;
|
||||
|
||||
this.pop(title);
|
||||
};
|
||||
|
||||
// TextDialog.prototype.selectOne = function (title,texts,callback) {
|
||||
// var ol = this.newElement('div');
|
||||
// texts.forEach(function (text) {
|
||||
// var li = this.newElement('div');
|
||||
// var label = this.newElement('label');
|
||||
// var checkbox = this.newElement('input');
|
||||
// checkbox.type = 'checkbox';
|
||||
// var txt = document.createTextNode(text);
|
||||
|
||||
// label.appendChild(checkbox);
|
||||
// label.appendChild(txt);
|
||||
// li.appendChild(label);
|
||||
// ol.appendChild(li);
|
||||
// },this);
|
||||
|
||||
// this.titleDiv.textContent = title;
|
||||
// this.bodyDiv.innerHTML = '';
|
||||
// this.bodyDiv.appendChild(ol);
|
||||
// };
|
284
Zone.js
Normal file
|
@ -0,0 +1,284 @@
|
|||
'use strict';
|
||||
|
||||
function Zone (cfg) {
|
||||
createjs.Container.prototype.initialize.call(this);
|
||||
|
||||
this.game = cfg.game;
|
||||
this.name = cfg.name;
|
||||
this.x = cfg.x;
|
||||
this.y = cfg.y;
|
||||
|
||||
this.showAmount = !!cfg.showAmount;
|
||||
this._amount = 0;
|
||||
this.opposite = !!cfg.opposite;
|
||||
|
||||
this.cards = [];
|
||||
this.changed = true;
|
||||
|
||||
this.text = new createjs.Text('','bold 12px monospace');
|
||||
this.text.textAlign = 'center';
|
||||
// this.text.textBaseline = 'middle';
|
||||
this.addChild(this.text);
|
||||
|
||||
if (this.opposite) {
|
||||
this.rotation = 180;
|
||||
this.text.rotation = 180;
|
||||
}
|
||||
|
||||
this.game.addZone(this);
|
||||
}
|
||||
|
||||
Zone.prototype = new createjs.Container();
|
||||
Zone.prototype.constructor = Zone;
|
||||
|
||||
Zone.prototype.sortCards = function () {
|
||||
var len = this.cards.length;
|
||||
this.cards.forEach(function (card,i) {
|
||||
card.style.set('zIndex',len-i);
|
||||
},this);
|
||||
};
|
||||
Zone.prototype.addCard = function (card,bottom) {
|
||||
if ((this.name !== 'SigniZone') || (this.name !== 'LrigZone')) {
|
||||
card.removeStates();
|
||||
}
|
||||
if (bottom) {
|
||||
this.cards.push(card);
|
||||
} else {
|
||||
this.cards.unshift(card);
|
||||
}
|
||||
this.sortCards();
|
||||
this.updateCardPosition();
|
||||
};
|
||||
Zone.prototype.removeCard = function (card,bottom) {
|
||||
removeFromArr(card,this.cards);
|
||||
this.sortCards();
|
||||
this.updateCardPosition();
|
||||
};
|
||||
Zone.prototype.getCardIndex = function (card) {
|
||||
return this.cards.indexOf(card);
|
||||
};
|
||||
Zone.prototype.updateCardPosition = function () {};
|
||||
Zone.prototype.update = function () {
|
||||
if (this.showAmount && (this._amount !== this.cards.length)) {
|
||||
this._amount = this.cards.length;
|
||||
var txt = (this._amount === 0)? '' : this._amount;
|
||||
this.setText(txt);
|
||||
}
|
||||
var changed = this.changed;
|
||||
this.changed = false;
|
||||
return changed;
|
||||
};
|
||||
Zone.prototype.addButton = function () {};
|
||||
Zone.prototype.removeButtons = function () {};
|
||||
Zone.prototype.setText = function (txt) {
|
||||
this.changed = true;
|
||||
if (!txt) {
|
||||
this.text.visible = false;
|
||||
return;
|
||||
}
|
||||
this.text.visible = true;
|
||||
this.text.text = txt;
|
||||
};
|
||||
Zone.prototype.setTextColor = function (color) {
|
||||
this.changed = true;
|
||||
if (this.name === 'EnerZone') {
|
||||
this.text.color = 'white';
|
||||
} else {
|
||||
this.text.color = color;
|
||||
}
|
||||
};
|
||||
Zone.prototype.shouldUseDialog = function () {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
function StackZone (cfg) {
|
||||
Zone.apply(this,arguments);
|
||||
|
||||
this.showPower = !!cfg.showPower;
|
||||
this.checkable = !!cfg.checkable;
|
||||
|
||||
this.changed = true;
|
||||
this._power = 0;
|
||||
this.power = 0;
|
||||
|
||||
if (cfg.centerText) {
|
||||
this.text.textBaseline = 'middle';
|
||||
} else {
|
||||
this.text.textBaseline = 'top';
|
||||
this.text.y = Card.HEIGHT/2;
|
||||
if (this.opposite) {
|
||||
this.text.rotation = 180;
|
||||
this.text.textBaseline = 'bottom';
|
||||
}
|
||||
}
|
||||
|
||||
// 状态层
|
||||
this.stateLayer = new createjs.Container();
|
||||
this.stateShape = new createjs.Shape();
|
||||
this.stateLayer.addChild(this.stateShape);
|
||||
this.addChild(this.stateLayer);
|
||||
|
||||
this.buttonLayer = new ButtonList();
|
||||
this.buttonLayer.rotation = -this.rotation;
|
||||
this.addChild(this.buttonLayer);
|
||||
|
||||
if (this.checkable) {
|
||||
this.viewCardsButton = new Button(Localize('buttonTitle','VIEW'),function () {
|
||||
this.game.dialog.showCards(Localize('buttonTitle','VIEW'),this.cards,function () {});
|
||||
}.bind(this));
|
||||
this.viewCardsButton.alpha = 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
StackZone.prototype = Object.create(Zone.prototype);
|
||||
StackZone.prototype.constructor = StackZone;
|
||||
|
||||
StackZone.prototype.updateCardPosition = function () {
|
||||
var covered = false;
|
||||
this.cards.forEach(function (card,idx) {
|
||||
card.moveTo(this.x,this.y,covered,!!idx);
|
||||
if (card.x === this.x && card.y === this.y) {
|
||||
covered = true;
|
||||
}
|
||||
},this);
|
||||
};
|
||||
|
||||
StackZone.prototype.addButton = function (txt,onclick/*,card*/) {
|
||||
var btn = new Button(txt,onclick.bind(this,this));
|
||||
this.buttonLayer.addButton(btn);
|
||||
};
|
||||
|
||||
StackZone.prototype.removeButtons = function () {
|
||||
this.buttonLayer.removeAllButtons();
|
||||
if (this.checkable && this.cards.length>1) {
|
||||
this.buttonLayer.addButton(this.viewCardsButton);
|
||||
}
|
||||
};
|
||||
|
||||
StackZone.prototype.addViewCardsButton = function () {
|
||||
this.buttonLayer.addButton(this.viewCardsButton);
|
||||
};
|
||||
|
||||
Zone.prototype.addStates = function (states) {
|
||||
this.changed = true;
|
||||
this.stateLayer.visible = true;
|
||||
states.forEach(function (state) {
|
||||
var g = this.stateShape.graphics;
|
||||
var w = Card.WIDTH;
|
||||
var h = Card.HEIGHT;
|
||||
if (state === 'powerDown') {
|
||||
g.f('rgba(164,96,222,0.3)').r(-w/2,-h/2,w,h);
|
||||
} else if (state === 'disabled') {
|
||||
g.f('rgba(0,0,0,0.7)').r(-w/2,-h/2,w,h);
|
||||
}
|
||||
},this);
|
||||
};
|
||||
|
||||
Zone.prototype.removeStates = function () {
|
||||
this.changed = true;
|
||||
this.stateLayer.visible = false;
|
||||
this.stateShape.graphics.clear();
|
||||
};
|
||||
|
||||
StackZone.prototype.update = function () {
|
||||
var changed = this.buttonLayer.update() || this.changed;
|
||||
if (this.showPower) {
|
||||
if (this._amount !== this.cards.length) {
|
||||
this._amount = this.cards.length;
|
||||
this.power = this._power = 0;
|
||||
this.setText('');
|
||||
}
|
||||
if (this._power !== this.power) {
|
||||
this._power = this.power;
|
||||
this.setText(this._power);
|
||||
}
|
||||
} else {
|
||||
if (Zone.prototype.update.call(this)) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
this.changed = false;
|
||||
return changed;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
function TileZone (cfg) {
|
||||
Zone.apply(this,arguments); // 这里设置了 x,y ,表示原点坐标.
|
||||
this.up = cfg.up; // true/false: 卡片竖置/横置
|
||||
this.horizontal = cfg.horizontal; // true/false: 水平/竖直分布.
|
||||
this.center = cfg.center; // true/false: 居中/左对齐
|
||||
this.width = cfg.width; // 区域的最大"宽度". (若该区域为竖直分布,则为高度)
|
||||
this.spacing = cfg.spacing; // 卡与卡的边距.
|
||||
this.showAmount = !!cfg.showAmount;
|
||||
|
||||
if (this.horizontal) {
|
||||
this.text.textBaseline = 'middle';
|
||||
if (this.opposite) {
|
||||
this.text.textAlign = 'left';
|
||||
} else {
|
||||
this.text.textAlign = 'right';
|
||||
}
|
||||
} else {
|
||||
this.text.textAlign = 'center';
|
||||
if (this.opposite) {
|
||||
this.text.textBaseline = 'top';
|
||||
} else {
|
||||
this.text.textBaseline = 'bottom';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TileZone.prototype = Object.create(Zone.prototype);
|
||||
TileZone.prototype.constructor = TileZone;
|
||||
|
||||
TileZone.prototype.updateCardPosition = function () {
|
||||
if (!this.cards.length) return;
|
||||
|
||||
var s = this.spacing;
|
||||
var w; // 卡片在轴上所占的"宽度"
|
||||
if (this.horizontal)
|
||||
w = this.up? Card.WIDTH : Card.HEIGHT;
|
||||
else
|
||||
w = this.up? Card.HEIGHT : Card.WIDTH;
|
||||
|
||||
var base; // 首张卡的位置
|
||||
var delta; // 卡与卡中心间隔.
|
||||
var factor = this.opposite? -1 : 1; // 倒转修正系数
|
||||
if ((w+s)*this.cards.length-s <= this.width) {
|
||||
// 可以容纳.
|
||||
delta = w+s;
|
||||
if (this.center) {
|
||||
base = -delta*(this.cards.length-1)/2;
|
||||
} else {
|
||||
base = w/2;
|
||||
}
|
||||
} else {
|
||||
// 容纳不下,挤压
|
||||
delta = (this.width-w)/(this.cards.length-1);
|
||||
if (this.center) {
|
||||
base = w/2 - this.width/2;
|
||||
} else {
|
||||
base = w/2;
|
||||
}
|
||||
}
|
||||
|
||||
// 在zone.cards中,索引为0的卡表示在"顶部"
|
||||
// 因此,卡片在轴上排列时,索引大的排前面,小的排后面.
|
||||
var len = this.cards.length;
|
||||
if (this.horizontal) {
|
||||
this.cards.forEach(function (card,i) {
|
||||
var j = len - i - 1;
|
||||
card.moveTo(this.x + factor*(base+j*delta),this.y);
|
||||
},this);
|
||||
} else {
|
||||
this.cards.forEach(function (card,i) {
|
||||
var j = len - i - 1;
|
||||
card.moveTo(this.x,this.y + factor*(base+j*delta));
|
||||
},this);
|
||||
}
|
||||
};
|
244
ZonePosition.js
Normal file
|
@ -0,0 +1,244 @@
|
|||
'use strict';
|
||||
|
||||
Game.prototype.initZones = function () {
|
||||
this.player = {
|
||||
enerZone: new TileZone({
|
||||
game: this,
|
||||
name: 'EnerZone',
|
||||
x: 92,
|
||||
y: 377,
|
||||
up: false,
|
||||
horizontal: false,
|
||||
center: false,
|
||||
width: 259,
|
||||
spacing: 5,
|
||||
showAmount: true
|
||||
}),
|
||||
signiZones: [
|
||||
new StackZone({
|
||||
game: this,
|
||||
name: 'SigniZone',
|
||||
x: 190,
|
||||
y: 421,
|
||||
showPower: true
|
||||
}),
|
||||
new StackZone({
|
||||
game: this,
|
||||
name: 'SigniZone',
|
||||
x: 288,
|
||||
y: 421,
|
||||
showPower: true
|
||||
}),
|
||||
new StackZone({
|
||||
game: this,
|
||||
name: 'SigniZone',
|
||||
x: 386,
|
||||
y: 421,
|
||||
showPower: true
|
||||
}),
|
||||
],
|
||||
mainDeck: new StackZone({
|
||||
game: this,
|
||||
name: 'MainDeck',
|
||||
x: 471.5,
|
||||
y: 421,
|
||||
showAmount: true
|
||||
}),
|
||||
lrigDeck: new StackZone({
|
||||
game: this,
|
||||
name: 'LrigDeck',
|
||||
x: 544.5,
|
||||
y: 421,
|
||||
showAmount: true,
|
||||
checkable: true
|
||||
}),
|
||||
checkZone: new StackZone({
|
||||
game: this,
|
||||
name: 'CheckZone',
|
||||
x: 190,
|
||||
y: 519
|
||||
}),
|
||||
lrigZone: new StackZone({
|
||||
game: this,
|
||||
name: 'LrigZone',
|
||||
x: 288,
|
||||
y: 519,
|
||||
showAmount: true
|
||||
}),
|
||||
trashZone: new StackZone({
|
||||
game: this,
|
||||
name: 'TrashZone',
|
||||
x: 471.5,
|
||||
y: 519,
|
||||
showAmount: true,
|
||||
checkable: true
|
||||
}),
|
||||
lrigTrashZone: new StackZone({
|
||||
game: this,
|
||||
name: 'LrigTrashZone',
|
||||
x: 544.5,
|
||||
y: 519,
|
||||
showAmount: true,
|
||||
checkable: true
|
||||
}),
|
||||
lifeClothZone: new TileZone({
|
||||
game: this,
|
||||
name: 'LifeClothZone',
|
||||
x: 158.5,
|
||||
y: 604.5,
|
||||
up: false,
|
||||
horizontal: true,
|
||||
center: false,
|
||||
width: 357,
|
||||
spacing: -Card.HEIGHT*2/3,
|
||||
showAmount: true
|
||||
}),
|
||||
excludedZone: new StackZone({
|
||||
game: this,
|
||||
name: 'ExcludedZone',
|
||||
x: 617.5,
|
||||
y: 421
|
||||
}),
|
||||
handZone: new TileZone({
|
||||
game: this,
|
||||
name: 'HandZone',
|
||||
x: 576/2,
|
||||
y: 690,
|
||||
up: true,
|
||||
horizontal: true,
|
||||
center: true,
|
||||
width: 576,
|
||||
spacing: 8
|
||||
})
|
||||
};
|
||||
|
||||
this.opponent = {
|
||||
enerZone: new TileZone({
|
||||
game: this,
|
||||
name: 'EnerZone',
|
||||
x: 576-92,
|
||||
y: 734-377,
|
||||
opposite: true,
|
||||
up: false,
|
||||
horizontal: false,
|
||||
center: false,
|
||||
width: 259,
|
||||
spacing: 5,
|
||||
showAmount: true
|
||||
}),
|
||||
signiZones: [
|
||||
new StackZone({
|
||||
game: this,
|
||||
name: 'SigniZone',
|
||||
x: 576-190,
|
||||
y: 734-421,
|
||||
showPower: true,
|
||||
opposite: true
|
||||
}),
|
||||
new StackZone({
|
||||
game: this,
|
||||
name: 'SigniZone',
|
||||
x: 576-288,
|
||||
y: 734-421,
|
||||
showPower: true,
|
||||
opposite: true
|
||||
}),
|
||||
new StackZone({
|
||||
game: this,
|
||||
name: 'SigniZone',
|
||||
x: 576-386,
|
||||
y: 734-421,
|
||||
showPower: true,
|
||||
opposite: true
|
||||
}),
|
||||
],
|
||||
mainDeck: new StackZone({
|
||||
game: this,
|
||||
name: 'MainDeck',
|
||||
x: 576-471.5,
|
||||
y: 734-421,
|
||||
showAmount: true,
|
||||
opposite: true
|
||||
}),
|
||||
lrigDeck: new StackZone({
|
||||
game: this,
|
||||
name: 'LrigDeck',
|
||||
x: 576-544.5,
|
||||
y: 734-421,
|
||||
showAmount: true,
|
||||
opposite: true
|
||||
}),
|
||||
lrigZone: new StackZone({
|
||||
game: this,
|
||||
name: 'LrigZone',
|
||||
x: 576-288,
|
||||
y: 734-519,
|
||||
showAmount: true,
|
||||
opposite: true
|
||||
}),
|
||||
checkZone: new StackZone({
|
||||
game: this,
|
||||
name: 'CheckZone',
|
||||
x: 576-190,
|
||||
y: 734-519,
|
||||
opposite: true
|
||||
}),
|
||||
trashZone: new StackZone({
|
||||
game: this,
|
||||
name: 'TrashZone',
|
||||
x: 576-471.5,
|
||||
y: 734-519,
|
||||
showAmount: true,
|
||||
opposite: true,
|
||||
checkable: true
|
||||
}),
|
||||
lrigTrashZone: new StackZone({
|
||||
game: this,
|
||||
name: 'LrigTrashZone',
|
||||
x: 576-544.5,
|
||||
y: 734-519,
|
||||
showAmount: true,
|
||||
opposite: true,
|
||||
checkable: true
|
||||
}),
|
||||
lifeClothZone: new TileZone({
|
||||
game: this,
|
||||
name: 'LifeClothZone',
|
||||
x: 576-158.5,
|
||||
y: 734-604.5,
|
||||
opposite: true,
|
||||
up: false,
|
||||
horizontal: true,
|
||||
center: false,
|
||||
width: 357,
|
||||
spacing: -Card.HEIGHT*2/3,
|
||||
showAmount: true
|
||||
}),
|
||||
excludedZone: new StackZone({
|
||||
game: this,
|
||||
name: 'ExcludedZone',
|
||||
x: 576-617.5,
|
||||
y: 734-421,
|
||||
opposite: true
|
||||
}),
|
||||
handZone: new TileZone({
|
||||
game: this,
|
||||
name: 'HandZone',
|
||||
x: 576-576/2,
|
||||
y: 734-690,
|
||||
opposite: true,
|
||||
up: true,
|
||||
horizontal: true,
|
||||
center: true,
|
||||
width: 576,
|
||||
spacing: 8
|
||||
})
|
||||
};
|
||||
this.buttonZone = new StackZone({
|
||||
game: this,
|
||||
name: 'ButtonZone',
|
||||
x: 386,
|
||||
y: 519,
|
||||
centerText: true
|
||||
});
|
||||
};
|
54
about.html
Normal file
|
@ -0,0 +1,54 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
<title>关于我们</title>
|
||||
<style>
|
||||
body, html {
|
||||
font-family: 'Microsoft YaHei','WenQuanYi Zen Hei',sans-serif;
|
||||
background-image: url('background/bg.png');
|
||||
}
|
||||
h2 {
|
||||
border-left: black solid 3px;
|
||||
padding-left: 3px;
|
||||
margin-left: -0.5em;
|
||||
}
|
||||
section {
|
||||
margin-left: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
a {
|
||||
color: blue;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>关于我们</h1>
|
||||
<section>
|
||||
<p><a href="http://webxoss.com/" target="_blank">WEBXOSS</a>是一个自由,免费,无广告,多语言,跨平台,全自动的WIXOSS在线对战平台.</p>
|
||||
<p>请在WEBXOSS中尽情战斗吧!</p>
|
||||
<p>OPEN!!</p>
|
||||
</section>
|
||||
|
||||
<h1 id="contact">联系我们</h1>
|
||||
<section>
|
||||
<p>如果你在游戏中发现了BUG,或者对WEBXOSS有任何意见和建议,随时欢迎联系我们哦~</p>
|
||||
<p>邮箱:<a href="mailto:webxoss@gmail.com" target="_blank">webxoss@gmail.com</a></p>
|
||||
<p>推特:<a href="https://twitter.com/WEBXOSS" target="_blank">@WEBXOSS</a></p>
|
||||
</section>
|
||||
|
||||
<h1 id="support">帮助我们</h1>
|
||||
<section>
|
||||
<del style="color: red; font-weight: bold; text-decoration: line-through;">WEBXOSS需要您的帮助!</del>
|
||||
</section>
|
||||
<section>
|
||||
<p>WEBXOSS已不再接受捐赠,开发维护费用将由我们自己承担。</p>
|
||||
<p>不用担心,WEBXOSS仍将保持免费、无广告,而我们也会继续做到最好。</p>
|
||||
<p>尽情享受战斗吧!</p>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
54
about_en.html
Normal file
|
@ -0,0 +1,54 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
<title>ABOUT US</title>
|
||||
<style>
|
||||
body, html {
|
||||
font-family: Arial,Helvetica,sans-serif;
|
||||
background-image: url('background/bg.png');
|
||||
}
|
||||
h2 {
|
||||
border-left: black solid 3px;
|
||||
padding-left: 3px;
|
||||
margin-left: -0.5em;
|
||||
}
|
||||
section {
|
||||
margin-left: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
a {
|
||||
color: blue;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>ABOUT WEBXOSS</h1>
|
||||
<section>
|
||||
<p><a href="http://webxoss.com/" target="_blank">WEBXOSS</a> is a free, no-ads, multilingual, cross-platform and full automated<br>online Battle-Field for WIXOSS.</p>
|
||||
<p>Enjoy the game!</p>
|
||||
<p>OPEN!!</p>
|
||||
</section>
|
||||
|
||||
<h1 id="contact">CONCAT US</h1>
|
||||
<section>
|
||||
<p>If you find any bug or have any suggestion for WEBXOSS, please concat us:</p>
|
||||
<p>E-Mail:<a href="mailto:webxoss@gmail.com" target="_blank">webxoss@gmail.com</a></p>
|
||||
<p>Twitter:<a href="https://twitter.com/WEBXOSS" target="_blank">@WEBXOSS</a></p>
|
||||
</section>
|
||||
|
||||
<h1 id="support">SUPPORT US</h1>
|
||||
<section>
|
||||
<del style="color: red; font-weight: bold; text-decoration: line-through;">WEBXOSS needs your help!</del>
|
||||
</section>
|
||||
<section>
|
||||
<p>WEBXOSS no more accepts donations. We will pay on ourself.</p>
|
||||
<p>Don't worry, WEBXOSS is still free and no-ads. And we will keep our hard work.</p>
|
||||
<p>Enjoy battling!</p>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
BIN
background/DarkFßen.mp3
Normal file
BIN
background/GreenWi.mp3
Normal file
BIN
background/Grid - 副本.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
background/Grid.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
background/Grid.webp
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
background/Grid2.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
background/JoinRoom.mp3
Normal file
BIN
background/Love Your Enemies.W.mp3
Normal file
BIN
background/Love your enemies.mp3
Normal file
BIN
background/Love your enemies_lq.mp3
Normal file
BIN
background/NevWorry.mp3
Normal file
BIN
background/Süblueß.mp3
Normal file
BIN
background/WhiteAng.mp3
Normal file
BIN
background/assassin.png
Normal file
After Width: | Height: | Size: 761 B |
BIN
background/bg.jpg
Normal file
After Width: | Height: | Size: 91 KiB |
BIN
background/bg.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
background/black.jpg
Normal file
After Width: | Height: | Size: 685 B |
BIN
background/blackGrid.jpg
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
background/blue.jpg
Normal file
After Width: | Height: | Size: 722 B |
BIN
background/blueGrid.jpg
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
background/charm.png
Normal file
After Width: | Height: | Size: 519 B |
BIN
background/doubleCrash.png
Normal file
After Width: | Height: | Size: 884 B |
BIN
background/frozen.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
background/green.jpg
Normal file
After Width: | Height: | Size: 728 B |
BIN
background/greenGrid.jpg
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
background/lancer.png
Normal file
After Width: | Height: | Size: 578 B |
BIN
background/loading.gif
Normal file
After Width: | Height: | Size: 673 B |
BIN
background/locked.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
background/reLEIdEN.mp3
Normal file
BIN
background/red.jpg
Normal file
After Width: | Height: | Size: 756 B |
BIN
background/redGrid.jpg
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
background/white.jpg
Normal file
After Width: | Height: | Size: 689 B |
BIN
background/whiteGrid.jpg
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
background/バトル!.mp3
Normal file
BIN
background/击溃.mp3
Normal file
BIN
background/双重击溃.mp3
Normal file
BIN
background/房间.mp3
Normal file
BIN
background/技艺.mp3
Normal file
BIN
background/攻击.mp3
Normal file
BIN
background/枪兵攻击.mp3
Normal file
BIN
background/界面 按钮.mp3
Normal file
BIN
background/被击溃.mp3
Normal file
BIN
background/魔法.mp3
Normal file
50
build.js
Normal file
|
@ -0,0 +1,50 @@
|
|||
'use strict'
|
||||
|
||||
const map = {
|
||||
'Localize.min.js': ['Localize.js'],
|
||||
'ImageAndDetail.min.js': [
|
||||
'ImageManager.js',
|
||||
'Detail.js',
|
||||
'ImageFileCache.js',
|
||||
],
|
||||
'webxoss.js': [
|
||||
'./lib/util.js',
|
||||
'MessageBox.js',
|
||||
'IO.js',
|
||||
'Card.js',
|
||||
'CardBitmap.js',
|
||||
'StateBitmap.js',
|
||||
'Style.js',
|
||||
'Zone.js',
|
||||
'Game.js',
|
||||
'ZonePosition.js',
|
||||
'Button.js',
|
||||
'ButtonList.js',
|
||||
'Selector.js',
|
||||
'Dialog.js',
|
||||
'GameBackground.js',
|
||||
'FakeSocket.js',
|
||||
'GameAudio.js',
|
||||
'ChatManager.js',
|
||||
'RoomManager.js',
|
||||
],
|
||||
// DeckEditor
|
||||
'./DeckEditor/Deck.min.js': [
|
||||
'./lib/util.js',
|
||||
'./DeckManager.js',
|
||||
'./DeckEditor/Rules.js',
|
||||
'./DeckEditor/Searcher.js',
|
||||
],
|
||||
'./DeckEditor/DeckEditor.js': [
|
||||
'./lib/util.js',
|
||||
'./DeckEditor/editor.js',
|
||||
],
|
||||
}
|
||||
|
||||
const fs = require('fs')
|
||||
const uglify = require('uglify-js')
|
||||
Object.keys(map).forEach(key => {
|
||||
let code = uglify.minify(map[key]).code
|
||||
fs.writeFileSync(key, code)
|
||||
console.log(`${key} done.`)
|
||||
})
|
964
css.css
Normal file
|
@ -0,0 +1,964 @@
|
|||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
body {
|
||||
position: relative;
|
||||
font-family: 'Microsoft YaHei','WenQuanYi Zen Hei',sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
/*height: 739px;*/
|
||||
min-width: 500px;
|
||||
background-image: url('background/bg.png');
|
||||
}
|
||||
table, th, td {
|
||||
border: 1px solid black;
|
||||
padding: 0;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0px;
|
||||
}
|
||||
ol,ul,li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
#Logo {
|
||||
text-align: center;
|
||||
font-size: 60px;
|
||||
}
|
||||
#subtitle {
|
||||
text-align: center;
|
||||
font-size: small;
|
||||
/*cursor: pointer;*/
|
||||
}
|
||||
/*#notice-match {
|
||||
display: none;
|
||||
}
|
||||
#subtitle.match #notice-match {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
color: blue !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
#subtitle.match #link-version {
|
||||
display: none;
|
||||
}
|
||||
#preset-match {
|
||||
line-height: 1.5;
|
||||
}
|
||||
#preset-match .head {
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
#preset-match ol {
|
||||
padding-left: 1em;
|
||||
}
|
||||
#preset-match ol,
|
||||
#preset-match li {
|
||||
list-style-type: decimal;
|
||||
}*/
|
||||
/*[id^="preset-match"] .list {
|
||||
margin: 1em 0;
|
||||
}
|
||||
[id^="preset-match"] .info {
|
||||
transition: all 0.5s;
|
||||
}
|
||||
[id^="preset-match"] .info:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
[id^="preset-match"] em {
|
||||
color: blue;
|
||||
font-style: normal;
|
||||
}
|
||||
[id^="preset-match"] a {
|
||||
color: blue !important;
|
||||
}
|
||||
[id^="preset-match"] .region {
|
||||
font-weight: bold;
|
||||
}
|
||||
[id^="preset-match"] .contact {
|
||||
padding-left: 2em;
|
||||
}*/
|
||||
/* here */
|
||||
#link-support-webxoss {
|
||||
display: none;
|
||||
}
|
||||
#subtitle.support-webxoss #link-support-webxoss {
|
||||
display: block;
|
||||
color: blue !important;
|
||||
text-decoration: underline;
|
||||
}
|
||||
#subtitle.support-webxoss #link-version {
|
||||
display: none;
|
||||
}
|
||||
#link-version {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#div-online-counter {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
font-size: small;
|
||||
text-align: right;
|
||||
}
|
||||
#span-latency.warn {
|
||||
color: red;
|
||||
}
|
||||
|
||||
#msgbox-warp {
|
||||
display: none;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
text-align: center;
|
||||
overflow: auto;
|
||||
}
|
||||
#msgbox-warp.shown {
|
||||
display: block;
|
||||
}
|
||||
#msgbox-window {
|
||||
position: relative;
|
||||
min-width: 200px;
|
||||
display: inline-block;
|
||||
top: 10%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
background-color: white;
|
||||
box-shadow: 0px 0px 15px rgba(0,0,0,0.7);
|
||||
text-align: left;
|
||||
padding: 1em 2em;
|
||||
}
|
||||
/*#msgbox-warp.shown #msgbox-window {
|
||||
top: 10%;
|
||||
opacity: 1;
|
||||
transition: all 0.3s ease-out;
|
||||
}*/
|
||||
#msgbox-body {
|
||||
margin: 1em 0;
|
||||
}
|
||||
#msgbox-msg {
|
||||
white-space: pre;
|
||||
}
|
||||
#msgbox-input {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
min-width: 200px;
|
||||
}
|
||||
#msgbox-foot {
|
||||
text-align: right;
|
||||
}
|
||||
#msgbox-preset {
|
||||
display: none;
|
||||
}
|
||||
#msgbox-window.alert #msgbox-input,
|
||||
#msgbox-window.alert #msgbox-button-cancel {
|
||||
display: none;
|
||||
}
|
||||
#msgbox-window.confirm #msgbox-input {
|
||||
display: none;
|
||||
}
|
||||
#msgbox-window.prompt #msgbox-msg::after {
|
||||
content: ":";
|
||||
}
|
||||
#msgbox-window.preset #msgbox-body,
|
||||
#msgbox-window.preset #msgbox-foot {
|
||||
display: none;
|
||||
}
|
||||
#msgbox-window.preset #msgbox-preset {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* å½•åƒ */
|
||||
#replay-list {
|
||||
min-width: 20em;
|
||||
height: 10em;
|
||||
border: #aaa 1px solid;
|
||||
margin: 0.5em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
#replay-list > li {
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
#replay-list > li:hover {
|
||||
color: blue;
|
||||
}
|
||||
/* é‡è¿ž */
|
||||
#wait-for-reconnect-foot {
|
||||
text-align: right;
|
||||
}
|
||||
.waiting {
|
||||
font-style: italic;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
.waiting::before {
|
||||
content: url("./background/loading.gif");
|
||||
}
|
||||
/* ä»£ç† */
|
||||
#span-set-proxy {
|
||||
cursor: pointer;
|
||||
}
|
||||
#proxy-head {
|
||||
text-align: center;
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
}
|
||||
#proxy-body {
|
||||
width: 400px;
|
||||
/* margin-left: 1em; */
|
||||
text-indent: 1em;
|
||||
}
|
||||
#proxy-foot {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#div-notice {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
max-width: 0;
|
||||
transition: all 1.5s;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
font-size: 80%;
|
||||
color: #aaa;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
#div-notice.shown {
|
||||
padding: 0 1em;
|
||||
max-width: 280px;
|
||||
visibility: visible;
|
||||
}
|
||||
#div-notice.green {
|
||||
color: gray;
|
||||
background-color: #86F986;
|
||||
}
|
||||
|
||||
|
||||
#link-edit-deck {
|
||||
color: blue;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#Hall {
|
||||
margin-left: 1em;
|
||||
}
|
||||
#div-hall-body {
|
||||
width: 480px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/*#div-rooms {
|
||||
width: 480px;
|
||||
}*/
|
||||
|
||||
#room-list {
|
||||
padding-left: 2em;
|
||||
height: 20em;
|
||||
overflow: auto;
|
||||
border: black solid 1px;
|
||||
}
|
||||
#div-options {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.checkbox {
|
||||
display: none;
|
||||
}
|
||||
.checkbox + span {
|
||||
font-size: 85%;
|
||||
}
|
||||
.checkbox + span {
|
||||
color: #FF005D;
|
||||
}
|
||||
.checkbox + span::before {
|
||||
content: '\2718';
|
||||
}
|
||||
.checkbox:checked + span {
|
||||
color: green;
|
||||
}
|
||||
.checkbox:checked + span::before {
|
||||
content: '\2714';
|
||||
}
|
||||
#select-language {
|
||||
border: none;
|
||||
}
|
||||
#room-list > li {
|
||||
cursor: pointer;
|
||||
}
|
||||
#room-list > li.password-required::before {
|
||||
/*color: #888;*/
|
||||
content: '\1F512';
|
||||
}
|
||||
#room-list,#room-list > li {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
#room-list > li.live::before {
|
||||
color: red;
|
||||
content: '\25CFLive ';
|
||||
}
|
||||
#room-list > li.no-mayus-room::after {
|
||||
color: red;
|
||||
content: ' Mayu\'s Room';
|
||||
text-decoration: line-through;
|
||||
}
|
||||
#span-play-replay {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
color: blue;
|
||||
cursor: pointer;
|
||||
}
|
||||
#table-create-room,
|
||||
#table-create-room td {
|
||||
border: none;
|
||||
}
|
||||
|
||||
#span-leave-room {
|
||||
font-weight: bold;
|
||||
color: #009;
|
||||
cursor: pointer;
|
||||
}
|
||||
#container-live {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
/*
|
||||
#room-name {
|
||||
color: #f2442b;
|
||||
}
|
||||
#room-host-nickname {
|
||||
color: #77d25b;
|
||||
}
|
||||
#room-guest-nickname {
|
||||
color: #888;
|
||||
}
|
||||
#room-guest-nickname.ready {
|
||||
color: #6c9af8;
|
||||
}
|
||||
*/
|
||||
|
||||
#Room {
|
||||
text-align: center;
|
||||
}
|
||||
#container-room {
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
position: relative;
|
||||
}
|
||||
#table-room {
|
||||
border-collapse: separate;
|
||||
border-spacing: 2px;
|
||||
}
|
||||
#table-room,
|
||||
#table-room th,
|
||||
#table-room td {
|
||||
border: none;
|
||||
}
|
||||
#table-room td {
|
||||
position: relative;
|
||||
}
|
||||
#table-room td[colspan] {
|
||||
text-align: center;
|
||||
}
|
||||
#td-vs {
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
font-size: 180%;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
text-shadow: black 0 0 5px;
|
||||
}
|
||||
.nickname {
|
||||
display: block;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
width: 170px;
|
||||
border-left: solid;
|
||||
padding-left: 4px;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
transition: background-color 0.8s,border-color 0.8s;
|
||||
}
|
||||
.nickname::before {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
background-color: white;
|
||||
content: ' ';
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
.nickname.clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
.nickname.clickable:hover::before {
|
||||
opacity: 0.2;
|
||||
}
|
||||
#room-name {
|
||||
color: #f2442b;
|
||||
font-size: 150%;
|
||||
font-weight: bold;
|
||||
}
|
||||
#room-host-nickname {
|
||||
color: #77d25b;
|
||||
background-color: #fff;
|
||||
}
|
||||
#room-guest-nickname {
|
||||
color: #888;
|
||||
background-color: #DDD;
|
||||
}
|
||||
#room-guest-nickname.ready {
|
||||
color: #6c9af8;
|
||||
background-color: #fff;
|
||||
}
|
||||
[id^=host-spectator-] {
|
||||
color: #fff;
|
||||
background-color: hsl(106, 80%, 80%);
|
||||
border-color: #77d25b;
|
||||
}
|
||||
[id^=guest-spectator-] {
|
||||
color: white;
|
||||
background-color: hsl(220, 100%, 85%);
|
||||
border-color: #6c9af8;
|
||||
}
|
||||
.nickname.locked {
|
||||
color: #222;
|
||||
background-color: #DDD;
|
||||
border-color: #666;
|
||||
font-weight: bold;
|
||||
}
|
||||
.nickname.locked::after {
|
||||
content: 'Locked';
|
||||
font-style: italic;
|
||||
}
|
||||
[id^=checkbox-spectator-] {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
opacity: 0;
|
||||
}
|
||||
#Room[data-position=guest] [id^=checkbox-spectator-] {
|
||||
visibility: visible;
|
||||
}
|
||||
td:hover [id^=checkbox-spectator-] {
|
||||
opacity: 1;
|
||||
}
|
||||
@media handheld {
|
||||
[id^=checkbox-spectator-] {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@media (pointer:coarse) {
|
||||
[id^=checkbox-spectator-] {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#GameDiv {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
/*background-color: gray;*/
|
||||
}
|
||||
.game-background {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 367px;
|
||||
/*opacity: 0;*/
|
||||
/*transition: opacity 1s;*/
|
||||
min-width: 1096px;
|
||||
}
|
||||
body {
|
||||
transition: background-color 1s;
|
||||
}
|
||||
body[self] .game-background {
|
||||
animation: fade-in 1s;
|
||||
-webkit-animation: fade-in 1s;
|
||||
-moz-animation: fade-in 1s;
|
||||
-ms-animation: fade-in 1s;
|
||||
-o-animation: fade-in 1s;
|
||||
}
|
||||
@keyframes fade-in {
|
||||
0% {opacity: 0;}
|
||||
100% {opacity: 1;}
|
||||
}
|
||||
@-webkit-keyframes fade-in {
|
||||
0% {opacity: 0;}
|
||||
100% {opacity: 1;}
|
||||
}
|
||||
@-moz-keyframes fade-in {
|
||||
0% {opacity: 0;}
|
||||
100% {opacity: 1;}
|
||||
}
|
||||
@-ms-keyframes fade-in {
|
||||
0% {opacity: 0;}
|
||||
100% {opacity: 1;}
|
||||
}
|
||||
@-o-keyframes fade-in {
|
||||
0% {opacity: 0;}
|
||||
100% {opacity: 1;}
|
||||
}
|
||||
body[self] table,
|
||||
body[self] th,
|
||||
body[self] td {
|
||||
border-color: white;
|
||||
}
|
||||
body[self] #detail {
|
||||
color: white;
|
||||
text-shadow: black 0 0 4px;
|
||||
}
|
||||
#background-opponent {
|
||||
transform: rotate(180deg);
|
||||
-webkit-transform: rotate(180deg);
|
||||
-moz-transform: rotate(180deg);
|
||||
-ms-transform: rotate(180deg);
|
||||
-o-transform: rotate(180deg);
|
||||
}
|
||||
#background-self {
|
||||
top: 367px;
|
||||
}
|
||||
#background-opponent-grid {
|
||||
width: 836px;
|
||||
transform: rotate(180deg);
|
||||
-webkit-transform: rotate(180deg);
|
||||
-moz-transform: rotate(180deg);
|
||||
-ms-transform: rotate(180deg);
|
||||
-o-transform: rotate(180deg);
|
||||
transform-origin: 548px;
|
||||
-webkit-transform-origin: 548px;
|
||||
-moz-transform-origin: 548px;
|
||||
-ms-transform-origin: 548px;
|
||||
-o-transform-origin: 548px;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url('background/Grid.webp');
|
||||
}
|
||||
#background-self-grid {
|
||||
top: 367px;
|
||||
width: 836px;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url('background/Grid.webp');
|
||||
}
|
||||
|
||||
body[self=white] #background-self,
|
||||
body[opponent=white] #background-opponent {
|
||||
background-image: url('background/white.jpg');
|
||||
}
|
||||
body[self=white] #background-self-grid,
|
||||
body[opponent=white] #background-opponent-grid {
|
||||
background-image: url('background/whiteGrid.jpg');
|
||||
}
|
||||
|
||||
body[self=black] #background-self,
|
||||
body[opponent=black] #background-opponent {
|
||||
background-image: url('background/black.jpg');
|
||||
}
|
||||
body[self=black] #background-self-grid,
|
||||
body[opponent=black] #background-opponent-grid {
|
||||
background-image: url('background/blackGrid.jpg');
|
||||
}
|
||||
|
||||
body[self=red] #background-self,
|
||||
body[opponent=red] #background-opponent {
|
||||
background-image: url('background/red.jpg');
|
||||
}
|
||||
body[self=red] #background-self-grid,
|
||||
body[opponent=red] #background-opponent-grid {
|
||||
background-image: url('background/redGrid.jpg');
|
||||
}
|
||||
|
||||
body[self=blue] #background-self,
|
||||
body[opponent=blue] #background-opponent {
|
||||
background-image: url('background/blue.jpg');
|
||||
}
|
||||
body[self=blue] #background-self-grid,
|
||||
body[opponent=blue] #background-opponent-grid {
|
||||
background-image: url('background/blueGrid.jpg');
|
||||
}
|
||||
|
||||
body[self=green] #background-self,
|
||||
body[opponent=green] #background-opponent {
|
||||
background-image: url('background/green.jpg');
|
||||
}
|
||||
body[self=green] #background-self-grid,
|
||||
body[opponent=green] #background-opponent-grid {
|
||||
background-image: url('background/greenGrid.jpg');
|
||||
}
|
||||
|
||||
body[self] {
|
||||
background-image: none;
|
||||
}
|
||||
body[self=white] {
|
||||
background-color: #E7FAFE;
|
||||
}
|
||||
body[self=black] {
|
||||
background-color: #250034;
|
||||
}
|
||||
body[self=red] {
|
||||
background-color: #C00B00;
|
||||
}
|
||||
body[self=blue] {
|
||||
background-color: #00A0FE;
|
||||
}
|
||||
body[self=green] {
|
||||
background-color: #004101;
|
||||
}
|
||||
|
||||
#detail {
|
||||
position: absolute;
|
||||
padding: 0 5px;
|
||||
box-sizing: border-box;
|
||||
width: 260px;
|
||||
font-size: 16px;
|
||||
}
|
||||
#detail-card-figure {
|
||||
height: 349px;
|
||||
}
|
||||
#detail-card-image {
|
||||
border-radius: 4%;
|
||||
}
|
||||
#detail-card-data {
|
||||
height: 385px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
position: relative;
|
||||
}
|
||||
#detail-card-wxid {
|
||||
font-size: small;
|
||||
}
|
||||
#detail-card-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
#detail-card-name > a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
#detail-card-name > a:active {
|
||||
color: red;
|
||||
}
|
||||
#detail-card-limiting {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0.5em;
|
||||
}
|
||||
#detail-table {
|
||||
width: 100%;
|
||||
white-space: pre-line;
|
||||
}
|
||||
#detail-table[lang="ru"] {
|
||||
word-break: break-all;
|
||||
}
|
||||
.key {
|
||||
width: 2.5em;
|
||||
text-align: center;
|
||||
}
|
||||
#BattleField {
|
||||
left: 260px;
|
||||
position: absolute;
|
||||
font-size: 18px;
|
||||
}
|
||||
#BattleField .warp {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/* background-color: rgba(255,255,255,0.75); */
|
||||
}
|
||||
#BattleField .dialog {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
background-color: white;
|
||||
box-shadow: 0px 0px 38px rgba(0,0,0,0.5);
|
||||
}
|
||||
#BattleField .title {
|
||||
white-space: pre;
|
||||
}
|
||||
#BattleField .body {
|
||||
margin: 0 18px;
|
||||
max-width: 428px;
|
||||
max-height: 573px;
|
||||
/*min-width: 120px;*/
|
||||
overflow: auto;
|
||||
}
|
||||
#BattleField .title, #BattleField .footer {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin: 5px;
|
||||
}
|
||||
#BattleField .card {
|
||||
width: 126px;
|
||||
height: 176px;
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
margin: 5px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
cursor: default;
|
||||
}
|
||||
#BattleField .card .txt, #BattleField .card .msk, #BattleField .card .num, #BattleField .card .img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
#BattleField .card img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#BattleField .card .txt {
|
||||
max-width: 90%;
|
||||
font-size: 0.8em;
|
||||
font-weight: bold;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
box-shadow: black 0 0 5px;
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
#BattleField .card .num {
|
||||
color: white;
|
||||
font-size: 80px;
|
||||
font-weight: bold;
|
||||
text-shadow: black 0 0 10px;
|
||||
}
|
||||
#BattleField .card .msk {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
#BattleField .card:hover .msk {
|
||||
background-color: white;
|
||||
opacity: 0.1;
|
||||
}
|
||||
#BattleField .card.disabled .msk {
|
||||
background-color: black;
|
||||
opacity: 0.5;
|
||||
}
|
||||
#BattleField .card.selected .msk {
|
||||
background-color: white;
|
||||
opacity: 0.5;
|
||||
}
|
||||
#BattleField .option {
|
||||
margin: 0.5em;
|
||||
transition: color 0.3s;
|
||||
cursor: pointer;
|
||||
}
|
||||
#BattleField .option:hover {
|
||||
color: blue;
|
||||
}
|
||||
#BattleField button {
|
||||
margin: 8px;
|
||||
}
|
||||
#BattleField .closeIcon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
opacity: 0.5;
|
||||
background-size: cover;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAVElEQVR42mNgGLLgKBAfAmJ+JDF+qNhRfBoPAvF/ID4F1cAPZf+HasYJQApPImk+hWYQA7GaidbEgOY8kmxDdt5JYjUfwhI4J4kJnGN4ouPYEE1iAM+rIqZ75+i/AAAAAElFTkSuQmCC);
|
||||
}
|
||||
#BattleField .closeIcon:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
#BattleField .dialog select {
|
||||
width: 100px;
|
||||
}
|
||||
#BattleField .dialog .replay {
|
||||
color: blue;
|
||||
font-weight: normal;
|
||||
font-size: 80%;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#div-replay-controls {
|
||||
position: absolute;
|
||||
left: 846px;
|
||||
}
|
||||
|
||||
#div-surrender {
|
||||
position: absolute;
|
||||
left: 841px;
|
||||
top: 5px;
|
||||
width: 200px;
|
||||
z-index: 5;
|
||||
font-size: 80%;
|
||||
cursor: pointer;
|
||||
}
|
||||
#div-replay-return {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
body:not(.gaming) #Chat {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
width: 410px;
|
||||
}
|
||||
body.gaming {
|
||||
height: 739px;
|
||||
min-width: 1145px;
|
||||
}
|
||||
body.gaming #Chat {
|
||||
position: absolute;
|
||||
left: 845px;
|
||||
bottom: 20px;
|
||||
width: 300px;
|
||||
}
|
||||
body.gaming #chat-dialogue {
|
||||
min-height: initial;
|
||||
max-height: 670px;
|
||||
}
|
||||
#chat-dialogue {
|
||||
min-height: 100px;
|
||||
max-height: 250px;
|
||||
overflow-y: auto;
|
||||
-ms-overflow-style: none;
|
||||
}
|
||||
#chat-dialogue::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
/* #chat-dialogue > div {
|
||||
padding: 0.4em 0;
|
||||
}
|
||||
#chat-dialogue > div.self {
|
||||
text-align: right;
|
||||
}
|
||||
#chat-dialogue > div.opponent {
|
||||
text-align: left;
|
||||
} */
|
||||
#chat-dialogue > div.sys {
|
||||
text-align: center;
|
||||
font-size: 80%;
|
||||
padding: 0;
|
||||
}
|
||||
/* #chat-dialogue > div > span {
|
||||
display: inline-block;
|
||||
max-width: 85%;
|
||||
padding: 0.2em 0.6em;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
#chat-dialogue > div.self > span {
|
||||
border-right: solid #959595 2px;
|
||||
background-color: #F8F8F8;
|
||||
box-shadow: #CCC 0px 1px 2px;
|
||||
}
|
||||
#chat-dialogue > div.opponent > span {
|
||||
border-left: solid #00AEFF 2px;
|
||||
background-color: #E5F6FF;
|
||||
box-shadow: #99DFFF 0px 1px 2px;
|
||||
} */
|
||||
/* div */
|
||||
#chat-dialogue div {
|
||||
float: left;
|
||||
clear: both;
|
||||
max-width: 80%;
|
||||
border-left: solid 2px;
|
||||
margin: 3px 0;
|
||||
padding: 0 5px;
|
||||
border-color: #FF8000;
|
||||
background-color: #FFFFB3;
|
||||
}
|
||||
#chat-dialogue div.opponent {
|
||||
float: right;
|
||||
border-color: #00AEFF;
|
||||
background-color: #E5F6FF;
|
||||
}
|
||||
#chat-dialogue div.spectator {
|
||||
border-color: #959595;
|
||||
background-color: #F8F8F8;
|
||||
}
|
||||
/* name */
|
||||
#chat-dialogue .name::after {
|
||||
content: ':';
|
||||
}
|
||||
#chat-dialogue .name {
|
||||
display: block;
|
||||
font-size: 80%;
|
||||
font-weight: bold;
|
||||
color: hsl(276, 60%, 63%);
|
||||
}
|
||||
#chat-dialogue .opponent .name {
|
||||
color: #3BC20A;
|
||||
}
|
||||
#chat-dialogue .spectator .name {
|
||||
font-weight: normal;
|
||||
color: #959595;
|
||||
}
|
||||
/* content */
|
||||
#chat-dialogue .content {
|
||||
padding-left: 1em;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
/* input */
|
||||
#chat-input-bar {
|
||||
width: 100%;
|
||||
height: 25px;
|
||||
}
|
||||
#chat-input {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
background: rgba(0,0,0,0);
|
||||
border: none;
|
||||
border-bottom: #ddd solid 1px;
|
||||
outline: none;
|
||||
}
|
||||
#chat-input:focus {
|
||||
border-bottom: #bbb solid 1px;
|
||||
}
|
||||
body[self=white] #chat-input,
|
||||
body[opponent=white] #div-surrender {
|
||||
color: black;
|
||||
}
|
||||
body[self=black] #chat-input,
|
||||
body[opponent=black] #div-surrender {
|
||||
color: yellow;
|
||||
}
|
||||
body[self=red] #chat-input,
|
||||
body[opponent=red] #div-surrender {
|
||||
color: white;
|
||||
}
|
||||
body[self=blue] #chat-input,
|
||||
body[opponent=blue] #div-surrender {
|
||||
color: yellow;
|
||||
}
|
||||
body[self=green] #chat-input,
|
||||
body[opponent=green] #div-surrender {
|
||||
color: white;
|
||||
}
|
||||
|
||||
#div-about {
|
||||
text-align: center;
|
||||
font-size: small;
|
||||
margin-top: 1em;
|
||||
}
|
||||
#div-about > a {
|
||||
margin: 0 0.5em;
|
||||
color: #aaa;
|
||||
text-decoration: none
|
||||
}
|
258
index.html
Normal file
|
@ -0,0 +1,258 @@
|
|||
<!DOCTYPE html>
|
||||
<html manifest="webxoss.appcache">
|
||||
<!-- <html> -->
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||||
<title>WEBXOSS | Beta</title>
|
||||
<meta name="description" content="WEBXOSS is a free, no-ads, multilingual, cross-platform and full automated online Battle-Field for WIXOSS.">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<script>
|
||||
var global = window;
|
||||
if (window.location != window.parent.location) window.parent.location = window.location;
|
||||
</script>
|
||||
<link rel="stylesheet" type="text/css" href="./css.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="Hall">
|
||||
<div id="Logo">WEBXOSS</div>
|
||||
<div id="subtitle"><a id="link-support-webxoss" href="about.html#support" target="_blank"></a><a id="link-version" href="versions.txt" target="_blank"><隐忍火蝶></a></div>
|
||||
<div id="div-notice">
|
||||
<span id="span-notice"></span>
|
||||
</div>
|
||||
<div id="div-online-counter">
|
||||
<span id="span-set-proxy">设置代理</span><br><span id="label-online-counter">Online:</span> <span id="span-online-counter"></span><br>
|
||||
<span id="label-latency">Latency:</span><span id="span-latency"></span>
|
||||
</div>
|
||||
<div id="div-hall-body">
|
||||
<div id="div-nickname">
|
||||
<span id="label-nickname">您的昵称:</span><input id="input-nickame" type="text" placeholder="昵称" maxlength="10"> <a id="link-edit-deck" href="./DeckEditor/">编辑卡组</a>
|
||||
</div>
|
||||
<div id="div-rooms">
|
||||
<div style="position: relative;">
|
||||
<div id="div-options">
|
||||
<label><input id="checkbox-bgm" type="checkbox" class="checkbox"><span id="label-bgm">音乐</span></label>
|
||||
<label><input id="checkbox-sound-effect" type="checkbox" class="checkbox" checked="checked"><span id="label-sound-effect">音效</span></label>
|
||||
<select id="select-language">
|
||||
<option value="en">English</option>
|
||||
<option value="zh_CN">简体中文</option>
|
||||
<option value="zh_TW">繁體中文</option>
|
||||
<option value="jp">日本語</option>
|
||||
<option value="ru">русский</option>
|
||||
<option value="it">Italiano</option>
|
||||
</select>
|
||||
</div>
|
||||
<span id="label-room-list">房间列表:</span>
|
||||
</div>
|
||||
<ol id="room-list"></ol>
|
||||
<span id="span-play-replay">录像回放</span>
|
||||
</div>
|
||||
<div id="div-create-room">
|
||||
<table id="table-create-room">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><span id="label-create-room">创建房间:</span></td>
|
||||
<td><input id="input-room-name" type="text" placeholder="房间名字" maxlength="15"></td>
|
||||
<td><label><input id="checkbox-mayus-room" type="checkbox" class="checkbox" checked="checked"><span id="label-mayus-room">茧的房间</span></label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span id="label-create-room-password">房间密码:</span></td>
|
||||
<td><input id="input-create-room-password" type="text" maxlength="15"></td>
|
||||
<td><button id="button-create-room">创建</button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<!-- <div>
|
||||
<span id="label-create-room">创建房间:</span> <input id="input-room-name" type="text" placeholder="房间名字" maxlength="20"> <button id="button-password">密码</button> <button id="button-create-room">创建</button>
|
||||
</div>
|
||||
<div>
|
||||
<span id="label-create-room-password">密码:</span> <input id="input-create-room-password" type="text" maxlength="15">
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div id="div-about">
|
||||
<a id="link-copyright">©2015 WEBXOSS.COM</a><a id="link-about" href="about.html" target="_blank">关于我们</a><a id="link-service" href="service.html" target="_blank">服务条款</a><a id="link-disclaimer" href="service.html#disclaimer" target="_blank">免责声明</a><a id="link-supporters" href="supporters.html" target="_blank" style="color: #697;">捐赠者名单</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="Room" style="display: none;"><div id="container-room">
|
||||
<div>
|
||||
<span id="span-leave-room"><<返回</span>
|
||||
</div>
|
||||
<div>
|
||||
<label id="container-live"><input id="input-live" type="checkbox" checked><span id="label-live">直播</span></label>
|
||||
</div>
|
||||
<table id="table-room">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="100"><span id="room-name"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span id="room-host-nickname" class="nickname"></span></td>
|
||||
<td rowspan="6" id="td-vs"><span>VS</span></td>
|
||||
<td><span id="room-guest-nickname" class="nickname"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span id="host-spectator-0" class="nickname"></span></td>
|
||||
<td><span id="guest-spectator-0" class="nickname"></span> <input type="checkbox" id="checkbox-spectator-0"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span id="host-spectator-1" class="nickname"></span></td>
|
||||
<td><span id="guest-spectator-1" class="nickname"></span> <input type="checkbox" id="checkbox-spectator-1"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span id="host-spectator-2" class="nickname"></span></td>
|
||||
<td><span id="guest-spectator-2" class="nickname"></span> <input type="checkbox" id="checkbox-spectator-2"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span id="host-spectator-3" class="nickname"></span></td>
|
||||
<td><span id="guest-spectator-3" class="nickname"></span> <input type="checkbox" id="checkbox-spectator-3"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span id="host-spectator-4" class="nickname"></span></td>
|
||||
<td><span id="guest-spectator-4" class="nickname"></span> <input type="checkbox" id="checkbox-spectator-4"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="100">
|
||||
<select id="select-decks"></select> <button id="button-start-game">Oben!</button>
|
||||
<label id="container-ready"><input id="input-ready" type="checkbox"><span id="label-ready">准备</span></label>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<!-- <ul id="list-host-spectators"></ul> -->
|
||||
<!-- <ul id="list-guest-spectators"></ul> -->
|
||||
</table>
|
||||
</div></div>
|
||||
<div id="GameDiv" style="display: none;">
|
||||
<div class="game-background" id="background-opponent"></div>
|
||||
<div class="game-background" id="background-opponent-grid"></div>
|
||||
<div class="game-background" id="background-self"></div>
|
||||
<div class="game-background" id="background-self-grid"></div>
|
||||
<div id="detail">
|
||||
<div id="detail-card-figure">
|
||||
<img id="detail-card-image">
|
||||
</div>
|
||||
<div id="detail-card-data">
|
||||
<div id="detail-card-wxid"></div>
|
||||
<div id="detail-card-name"></div>
|
||||
<div id="detail-card-limiting"></div>
|
||||
<table id="detail-table">
|
||||
<tbody id="detail-table-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div id="BattleField">
|
||||
<!-- <canvas id="BattleFieldCanvas" width="576" height="734"></canvas> -->
|
||||
</div>
|
||||
<div id="div-replay-controls" style="display: none;">
|
||||
<button id="button-replay-step">下一步</button> <button id="button-replay-auto">自动播放</button>
|
||||
</div>
|
||||
<div id="div-surrender">
|
||||
<span id="span-surrender">投降</span>
|
||||
<span id="span-leave-game">离开</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="Chat" style="display: none;">
|
||||
<div id="chat-dialogue"></div>
|
||||
<div id="chat-input-bar">
|
||||
<input id="chat-input" type="text" placeholder="在此处聊天" maxlength="256">
|
||||
</div>
|
||||
</div>
|
||||
<div id="msgbox-warp">
|
||||
<div id="msgbox-window">
|
||||
<div id="msgbox-head">
|
||||
<span id="msgbox-title"></span>
|
||||
</div>
|
||||
<div id="msgbox-preset">
|
||||
<div id="preset-replay">
|
||||
<div>
|
||||
<div id="label-replay-list">录像列表:</div>
|
||||
<ol id="replay-list"></ol>
|
||||
</div>
|
||||
<div><span id="label-replay-file">录像文件:</span> <input id="input-replay-file" type="file" accept=".wxrep"></div>
|
||||
<div id="div-replay-return"><button id="button-replay-return">返回</button></div>
|
||||
</div>
|
||||
<div id="preset-reconnect">
|
||||
<div><span id="reconnect-title">连接已断开!</span></div>
|
||||
<div class="waiting"><span id="reconnect-retry">正在重新连接...</span></div>
|
||||
</div>
|
||||
<div id="preset-wait-for-reconnect">
|
||||
<div><span id="wait-for-reconnect-title">对手的连接已断开!</span></div>
|
||||
<div class="waiting"><span id="wait-for-reconnect-retry">正在等待重新连接...</span></div>
|
||||
<div id="wait-for-reconnect-foot"><button id="wait-for-reconnect-button-drop">放弃等待</button></div>
|
||||
</div>
|
||||
<div id="preset-proxy">
|
||||
<div id="proxy-head"><span id="proxy-title">设置代理</span></div>
|
||||
<div id="proxy-body"><span id="proxy-description">使用代理后,你与WEBXOSS服务器之间的数据将由代理服务器转发. 通常情况下,你不必设置代理,但如果掉线情况频繁发生,代理可能会有所帮助.</span></div>
|
||||
<div id="proxy-foot">
|
||||
<select id="select-proxy">
|
||||
<option id="proxy-noproxy" value="">不使用代理</option>
|
||||
<option id="proxy-cloudflare" value="cloudflare.webxoss.com">CloudFlare</option>
|
||||
<option id="proxy-incapsula" value="incapsula.webxoss.com">Incapsula</option>
|
||||
<option id="proxy-provide" value="provide">提供代理服务器...</option>
|
||||
</select>
|
||||
<button id="proxy-button-ok">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="preset-warn">
|
||||
<div>
|
||||
<span>
|
||||
You are visiting this site from an untrusted domain.<br>
|
||||
Please go to <a href="http://webxoss.com/">webxoss.com</a> instead.<br>
|
||||
<br>
|
||||
If you are the administrator of this domain,<br>
|
||||
please contact us via webxoss@gmail.com
|
||||
<span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="msgbox-body">
|
||||
<div><span id="msgbox-msg"></span></div>
|
||||
<div><input type="text" id="msgbox-input"></div>
|
||||
</div>
|
||||
<div id="msgbox-foot">
|
||||
<div><button id="msgbox-button-ok">确定</button> <button id="msgbox-button-cancel">取消</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<audio id="audio-bgm" loop></audio>
|
||||
<audio id="audio-sound-effect" autoplay></audio>
|
||||
|
||||
<script src="./lib/easeljs-0.8.2.min.js" defer="defer"></script>
|
||||
<script src="./socket.io.min.js" defer="defer"></script>
|
||||
<script src="./CardInfo.js" defer="defer"></script>
|
||||
<script src="./CardInfo_ru.js" defer="defer"></script>
|
||||
|
||||
<script src="./Localize.min.js" defer="defer"></script>
|
||||
<script src="./ImageAndDetail.min.js" defer="defer"></script>
|
||||
<script src="./DeckEditor/Deck.min.js" defer="defer"></script>
|
||||
<script src="./webxoss.js" defer="defer"></script>
|
||||
|
||||
<!-- <script src="./Localize.js" defer="defer"></script>
|
||||
<script src="./ImageFileCache.js" defer="defer"></script>
|
||||
<script src="./ImageManager.js" defer="defer"></script>
|
||||
<script src="./Detail.js" defer="defer"></script>
|
||||
<script src="./lib/util.js" defer="defer"></script>
|
||||
<script src="./MessageBox.js" defer="defer"></script>
|
||||
<script src="./IO.js" defer="defer"></script>
|
||||
<script src="./Card.js" defer="defer"></script>
|
||||
<script src="./CardBitmap.js" defer="defer"></script>
|
||||
<script src="./StateBitmap.js" defer="defer"></script>
|
||||
<script src="./Style.js" defer="defer"></script>
|
||||
<script src="./Zone.js" defer="defer"></script>
|
||||
<script src="./Game.js" defer="defer"></script>
|
||||
<script src="./ZonePosition.js" defer="defer"></script>
|
||||
<script src="./Button.js" defer="defer"></script>
|
||||
<script src="./ButtonList.js" defer="defer"></script>
|
||||
<script src="./Selector.js" defer="defer"></script>
|
||||
<script src="./Dialog.js" defer="defer"></script>
|
||||
<script src="./GameBackground.js" defer="defer"></script>
|
||||
<script src="./FakeSocket.js" defer="defer"></script>
|
||||
<script src="./ChatManager.js" defer="defer"></script>
|
||||
<script src="./GameAudio.js" defer="defer"></script>
|
||||
<script src="./DeckManager.js" defer="defer"></script>
|
||||
<script src="./DeckEditor/Rules.js" defer="defer"></script>
|
||||
<script src="./DeckEditor/Searcher.js" defer="defer"></script>
|
||||
<script src="./RoomManager.js" defer="defer"></script> -->
|
||||
</body>
|
||||
</html>
|
16
lib/createjs-2013.12.12.min.js
vendored
Normal file
17
lib/createjs-2015.11.26.min.js
vendored
Normal file
14
lib/easeljs-0.8.2.min.js
vendored
Normal file
55
lib/util.js
Normal file
|
@ -0,0 +1,55 @@
|
|||
'use strict';
|
||||
var concat = Array.prototype.concat.bind([]);
|
||||
var toArr = function (obj) {
|
||||
if (!obj) return [];
|
||||
if (typeof obj === 'string') return [];
|
||||
return Array.prototype.slice.call(obj,0);
|
||||
};
|
||||
var isArr = Array.isArray;
|
||||
var inArr = function (item,arr) {
|
||||
return (toArr(arr).indexOf(item) != -1);
|
||||
};
|
||||
var removeFromArr = function (item,arr) {
|
||||
var idx = arr.indexOf(item);
|
||||
if (idx < 0) {
|
||||
return false;
|
||||
} else {
|
||||
arr.splice(idx,1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
var isStr = function (v) {
|
||||
return (typeof v === 'string');
|
||||
};
|
||||
var isObj = function (v) {
|
||||
return v && (typeof v === 'object') && !isArr(v);
|
||||
};
|
||||
var isNum = function (v) {
|
||||
return (typeof v === 'number');
|
||||
};
|
||||
var isFunc = function (v) {
|
||||
return (typeof v === 'function');
|
||||
};
|
||||
var pEach = function (arr,func,thisp) {
|
||||
return arr.reduce(function (chain,item) {
|
||||
return chain.then(function () {
|
||||
return func(item);
|
||||
});
|
||||
},Promise.resolve());
|
||||
}
|
||||
|
||||
function callConstructor(constructor) {
|
||||
var factoryFunction = constructor.bind.apply(constructor,arguments);
|
||||
return new factoryFunction();
|
||||
}
|
||||
|
||||
function applyToConstructor(constructor,argArray) {
|
||||
// var args = [null].concat(argArray);
|
||||
var args = concat(null,toArr(argArray));
|
||||
var factoryFunction = constructor.bind.apply(constructor,args);
|
||||
return new factoryFunction();
|
||||
}
|
||||
|
||||
function nextTick (callback) {
|
||||
setTimeout(callback,0);
|
||||
}
|
19
package.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "webxoss-client",
|
||||
"version": "1.0.0",
|
||||
"description": "Web client for WEBXOSS",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [
|
||||
"webxoss",
|
||||
"wixoss",
|
||||
"tcg"
|
||||
],
|
||||
"author": "WEBXOSS",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"uglify-js": "^2.7.3"
|
||||
}
|
||||
}
|
38
service.html
Normal file
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>WEBXOSS服务条款</title>
|
||||
<style>
|
||||
body, html {
|
||||
font-family: 'Microsoft YaHei','WenQuanYi Zen Hei',sans-serif;
|
||||
background-image: url('background/bg.png');
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>WEBXOSS服务条款</h1>
|
||||
<h2>总则</h2>
|
||||
<p>
|
||||
在使用WEBXOSS前,您务必阅读并遵守《WEBXOSS服务条款》(以下简称"本条款").<br>
|
||||
一旦您使用了WEBXOSS所提供的服务,即视为您已了解并完全同意本服务条款各项内容.<br>
|
||||
若您对本条款有任何异议,请停止使用WEBXOSS的各项服务.
|
||||
</p>
|
||||
<h2>1. 服务内容</h2>
|
||||
<p>
|
||||
WEBXOSS为用户提供在线对战服务,同时保留变更,中断或终止部分服务的权利.
|
||||
</p>
|
||||
<h2 id="disclaimer">2. 免责声明</h2>
|
||||
<p>
|
||||
WEBXOSS仅提供WIXOSS的在线对战平台,<br>
|
||||
其中所使用的卡牌图片,卡牌信息,及WIXOSS的游戏规则由©<a href="http://www.takaratomy.co.jp/products/wixoss/" target="_blank">TOMY</a>所有,中文版的卡牌信息由©<a href="http://www.china-beetle.com/" target="_blank">甲壳虫</a>所有.<br>
|
||||
卡片的英文信息来自<a href="http://selector-wixoss.wikia.com/" target="_blank">wikia</a>.
|
||||
</p>
|
||||
<h2>3. 服务条款的完善和修改</h2>
|
||||
<p>
|
||||
WEBXOSS保留随时修改服务条款的权利,用户在使用WEBXOSS时,有必要对最新的服务条款进行仔细阅读和重新确认,<br>
|
||||
当发生有关争议时,请以最新的服务条款为准.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|