이제 h5.zhengtuwl.comhtml5와 캔버스 관련 지식과 Doudizhu의 데모를 읽은 후 데모에 있는 자료를 사용하여 Doudizhu를 작성해 보았지만 코드가 잘 리팩토링되지 않았습니다.
말할 것도 별로 없고, 차근차근 설명해보자
common.js 파일이 하나뿐이다
1 리소스 클래스
.var Resource = Class.create();
$.extend(Resource.prototype, {
initialize: function () { },
이미지: [
{ 경로: 'img/bg1.png', x: 0, y : 0, w: 800, h: 480, 데이터: null, 유형: 61, visible: true },
{ 경로: 'img/BeiMian.jpg', x: 320, y: 5, w: 100, h: 121, 데이터: null, 유형: 62, visible: true },
{ 경로: 'img/btn.jpg', x: 300, y: 281, w: 140, h: 50, 데이터: null, 유형: 63 , visible: true, 텍스트: '开始', textX: 366, textY: 310 },
{ x: 0, y: 0, 유형: 66, isText: true, visible: false },
{ 경로: 'img/ 1.jpg', 데이터: null, 유형: 16, 표시: false },
{ 경로: 'img/2.jpg', 데이터: null, 유형: 17, 표시: false },
{ 경로: 'img/ 3.jpg', 데이터: null, 유형: 3, visible: false, se: 1 },
{ 경로: 'img/4.jpg', 데이터: null, 유형: 4, visible: false, se: 1 } ,
{ 경로: 'img/5.jpg', 데이터: null, 유형: 5, visible: false, se: 1 },
{ 경로: 'img/6.jpg', 데이터: null, 유형: 6, visible: false, se: 1 },
{ 경로: 'img/7.jpg', 데이터: null, 유형: 7, visible: false, se: 1 },
{ 경로: 'img/8.jpg', 데이터: null, 유형: 8, visible: false, se: 1 },
{ 경로: 'img/9.jpg', 데이터: null, 유형: 9, visible: false, se: 1 },
{ 경로: 'img/10.jpg', 데이터: null, 유형: 10, visible: false, se: 1 },
{ 경로: 'img/11.jpg', 데이터: null, 유형: 11, visible: false, se : 1 },
{ 경로: 'img/12.jpg', 데이터: null, 유형: 12, visible: false, se: 1 },
{ 경로: 'img/13.jpg', 데이터: null, 유형 : 13, visible: false, se: 1 },
{ 경로: 'img/14.jpg', 데이터: null, 유형: 14, visible: false, se: 1 },
{ 경로: 'img/15. jpg', 데이터: null, 유형: 15, visible: false, se: 1 },
{ 경로: 'img/16.jpg', 데이터: null, 유형: 3, visible: false, se: 4 },
{ 경로: 'img/17.jpg', 데이터: null, 유형: 4, 표시: false, se: 4 },
{ 경로: 'img/18.jpg', 데이터: null, 유형: 5, 표시: false, se: 4 },
{ 경로: 'img/19.jpg', 데이터: null, 유형: 6, visible: false, se: 4 },
{ 경로: 'img/20.jpg', 데이터: null, 유형: 7, visible: false, se: 4 },
{ 경로: 'img/21.jpg', 데이터: null, 유형: 8, visible: false, se: 4 },
{ 경로: 'img /22.jpg', 데이터: null, 유형: 9, visible: false, se: 4 },
{ 경로: 'img/23.jpg', 데이터: null, 유형: 10, visible: false, se: 4 },
{ 경로: 'img/24.jpg', 데이터: null, 유형: 11, visible: false, se: 4 },
{ 경로: 'img/25.jpg', 데이터: null, 유형: 12 , visible: false, se: 4 },
{ 경로: 'img/26.jpg', 데이터: null, 유형: 13, visible: false, se: 4 },
{ 경로: 'img/27.jpg' , 데이터: null, 유형: 14, visible: false, se: 4 },
{ 경로: 'img/28.jpg', 데이터: null, 유형: 15, visible: false, se: 4 },
{ 경로 : 'img/29.jpg', 데이터: null, 유형: 3, visible: false, se: 3 },
{ 경로: 'img/30.jpg', 데이터: null, 유형: 4, visible: false, se: 3 },
{ 경로: 'img/31.jpg', 데이터: null, 유형: 5, visible: false, se: 3 },
{ 경로: 'img/32.jpg', 데이터: null, 유형: 6, visible: false, se: 3 },
{ 경로: 'img/33.jpg', 데이터: null, 유형: 7, visible: false, se: 3 },
{ 경로: 'img/34 .jpg', 데이터: null, 유형: 8, visible: false, se: 3 },
{ 경로: 'img/35.jpg', 데이터: null, 유형: 9, visible: false, se: 3 },
{ 경로: 'img/36.jpg', 데이터: null, 유형: 10, visible: false, se: 3 },
{ 경로: 'img/37.jpg', 데이터: null, 유형: 11, 표시 : false, se: 3 },
{ 경로: 'img/38.jpg', 데이터: null, 유형: 12, visible: false, se: 3 },
{ 경로: 'img/39.jpg', 데이터 : null, 유형: 13, visible: false, se: 3 },
{ 경로: 'img/40.jpg', 데이터: null, 유형: 14, visible: false, se: 3 },
{ 경로: 'img/41.jpg', 데이터: null, 유형: 15, visible: false, se: 3 },
{ 경로: 'img/42.jpg', 데이터: null, 유형: 3, visible: false, se: 2 },
{ 경로: 'img/43.jpg', 데이터: null, 유형: 4, visible: false, se: 2 },
{ 경로: 'img/44.jpg', 데이터: null, 유형: 5, visible: false, se: 2 },
{ 경로: 'img/45.jpg', 데이터: null, 유형: 6, visible: false, se: 2 },
{ 경로: 'img /46.jpg', 데이터: null, 유형: 7, visible: false, se: 2 },
{ 경로: 'img/47.jpg', 데이터: null, 유형: 8, visible: false, se: 2 },
{ 경로: 'img/48.jpg', 데이터: null, 유형: 9, visible: false, se: 2 },
{ 경로: 'img/49.jpg', 데이터: null, 유형: 10 , visible: false, se: 2 },
{ 경로: 'img/50.jpg', 데이터: null, 유형: 11, visible: false, se: 2 },
{ 경로: 'img/51.jpg' , 데이터: null, 유형: 12, visible: false, se: 2 },
{ 경로: 'img/52.jpg', 데이터: null, 유형: 13, visible: false, se: 2 },
{ 경로 : 'img/53.jpg', 데이터: null, 유형: 14, visible: false, se: 2 },
{ 경로: 'img/54.jpg', 데이터: null, 유형: 15, visible: false, se: 2 }
]
});
Resource.Images是素材数组(几个按钮,文本,54张牌,背景图文等), 大家可以下载demo看看
2 、Lables类, Canvas画布上画文本的,比如按钮文字, 相关知识请看canvas教程
var Labels = Class.create();
$.extend(Labels.prototype, {
initialize: function (cxt) {
this.cxt = cxt ;
},
setText: 함수(텍스트, 위치) {
this.cxt.font = 'bold 20px serif';
this.cxt.fillStyle = '#000000';
this.cxt.textAlign = 'center';
this.cxt.fillText(text, postion.x, position.y);
}
字);
这个类的方法setText主要是根据设置体,字体大,字体颜color,여기Canvas上画文本적,this.cxt这个是canvas上文(每个教程的叫法不一样),首先this.cxt.font = 'bold 20px serif';这个是设置字体大小,样式等,this.cxt.fillStyle = '# 000000';这个
是设置字体颜color,this.cxt.textAlign = 'center';这个是设置字体对齐方式,this.cxt.fillText(text, position.x, position.y);这个是开始캔버스上画文本,postion.x, position.y分别是x坐标和y坐标。
3、DdZGame游戏类,主要功能就是初始化斗地主,发牌主等,流牌未完待续,后续更新
var DdZGame = Class.create();
DdZGame.Statics = { DealedNums: 0, isLeftFirstDeal: true };
$.extend(DdZGame.prototype, {
initialize: function () {
DdZGame.Statics.IsGetLander = false ;
DdZGame.Statics.DealTime = 66;
this.leftPokers = [];
this.rightPokers = [];
this.myPokers = [];
this.LastPokers = [];//最后3张牌
this.leftPlays = [];
this.rightPlays = [];
this.myPlays = [];
this.myBtnPostion = { y: 245, x: 162 };
this.isStart = false;
이것 .Res = new Resource();
this.allPokers = new Array();
this.Lander = 0;//地主,1右边,2My,3左边
this.isGetLander = {};
this.G m캔버스 = document.getElementById('gmCanvas');
this.cxt = this.GmCanvas.getContext('2d');
this.Lbl = new Labels(this.cxt);
this.init();
this .initEvt();
},
initEvt: function () {
this.GmCanvas.onclick = $.proxy(function (e) {
var box = this.GmCanvas.getBoundingClientRect();
DdZGame.Statics.MousePostion = { x: e.pageX - box.left, y: e.pageY - box.top };
this.onControlClick();
}, this);
},
onControlClick: 함수 () {
var isClick = false;
for (var i = 0; 나는 < this.Controls.length; i++) {
var c = this.Controls[i];
var position = DdZGame.Statics.MousePostion;
if (c.onClick) {
if (postion.x >= c.x 위치.x callback.call(this);
}
, this);
}, this));
},
drawImage: function (callback, isUnVisibleLast) {//isVisibleLast 是否让底牌不可见
$.each(this.Controls, $.proxy(function (i, o) ) {
if (!o.visible)
true를 반환합니다.
if (o.type == 62) {
var x = 0;
for (var i = 0; i < 54 - DdZGame.Statics.DealedNums ; i++) {
if (i == 0) x = o.x;
this.cxt.drawImage(o.data, o.x, o.y, o.w, o.h);
o. x++;
}
o.x = x;
}
else if (!o.isText) {
this.cxt.drawImage(o.data, o.x, o.y, o.w, o.h);
}
if (o.type == 63) {
this.Lbl.setText(o .text, { x: o.textX, y: o.textY });
if (!o.onClick)
o.onClick = $.proxy(function () {
o.onClick = null;
o.visible = false;
this.drawImage();
this.Dealing();
}, this);
}
if (o.type == 66) {
this.Lbl.setText(o.text , { x: o.x, y: o.y });
}
}, this));
/*克隆*/
var copyLeftPokers = this.leftPokers.slice();
var copyRightPokers = this.rightPokers.slice ();
var copyMyPokers = this.myPokers.slice();
var copyLastPokers = this.LastPokers.slice();
var isDealEndLeft = false;
var isDealEndRight = false;
var isDealEndMy = false;
var isDealEndLast = false;
var beiMain = $.grep(this.Res.Images, $.proxy(function (o, i) { return o.type == 62; }, this))[0];
var DrawPokers = 함수 (arry, 방향, isBeiMian, identiy, 축) {
if (arry && arry.length > 0) {
var o = arry[0];
var x = 0, y = 0;
if (!DdZGame.Statics[방향]) {
DdZGame.Statics[방향] = this[방향];
}
if (!o.x) {
x = DdZGame. 정적[방향].x;
y = DdZGame.Statics[방향].y;
o.x = this[방향].x;
o.y = this[방향].y;
}
else {
x = o.x; ㅋㅋㅋ ;???? {
o.w = 105;
o.h = 150;
}
var img = o.data;
if (isBeiMian) {
img = beiMain.data;
}
else if (방향 == 'myPannel') {
o.onClick = $.proxy(function () {
if (!this. isStart)
return;
if (!o.isPlay) {
o.isPlay = true;
> o.isPlay = false;
o.y += 30;
}
DdZGame 이 .drawImage(img, x, y);
DdZGame.Statics[방향][축] += identiy;
arry.splice(0, 1);
if (DdZGame.Statics.DealTime > 0)
DdZGame.Statics[direction + 'handle'] = setTimeout($.proxy(function () {
DrawPokers.call(this, arry, 방향, isBeiMian, identiy, 축);
}, 이), DdZGame. Statics.DealTime);
else
DrawPokers.call(this, arry, direct, isBeiMian, identiy, axis);
}
else if (Dd ZGame.Statics[방향 + '핸들'] || DdZGame.Statics.DealTime == 0) {
clearTimeout(DdZGame.Statics[direction + 'handle']);
if (direction == 'leftPannel' && copyLeftPokers.length == 0) {
isDealEndLeft = true;
}
if (direction == 'rightPannel' && copyRightPokers.length == 0) {
isDealEndRight = true;
}
if (direction == 'myPannel' && copyMyPokers. 길이 == 0) {
isDealEndMy = true;
}
if (direction == 'lastPannel' && copyLastPokers.length == 0) {
isDealEndLast = true;
}
if (isDealEndLeft && isDealEndRight && isDealEndMy && isDealEndLast) {
/*发牌完毕*/
/*抢地主* /
if (콜백)
콜백();
}
}
};
DrawPokers.call(this, copyLeftPokers, 'leftPannel', true, 26, 'y');
DrawPokers.call(this, copyRightPokers , 'rightPannel', true, 26, 'y');
DrawPokers.call(this, copyMyPokers, 'myPannel', false, 19, 'x');
DrawPokers.call(this, copyLastPokers, 'lastPannel', isUnVisibleLast, 126, 'x');
},
init: function () {
this.loadImages(this.drawImage);
},
Dealing: function () {//发牌
this. 왼쪽 패널 = { x : 5, y: 18 };
this.rightPannel = { x: 691, y: 18 };
this.myPannel = { x: 198, y: 330 };
this.lastPannel = { x: 243, y: 5 };
if (DdZGame.Statics.DealedNums >= 51) { //发牌完毕
$.each(this.allPokers, $.proxy(function (i, o) {
o.visible = true;
this.LastPokers.push(o);
}, this));
this.myPokers.sort(function (a, b) {
if (a.type != b.type)
return b .type - a.type;
return b.se - a.se;
});
$.grep(this.Res.Images, $.proxy(function (o, i) { return o.type == 62 ; }, this))[0].visible = false;
this.drawImage($.proxy(function () { this.GetLander(); }, this), true);
}
else {
/*1 、왼쪽*/
var index = Math.floor(Math.random() * (this.allPokers.length - 1) + 0);
var c = this.allPokers.splice(index, 1);
c[0 ].visible = true;
this.leftPokers.push(c[0]);
DdZGame.Statics.DealedNums++;
/*2、right*/
index = Math.floor(M ath.random() * (이것은 .allPokers.length - 1) + 0);
c = this.allPokers.splice(index, 1);
c[0].visible = true;
this.rightPokers.push(c[0]);
DdZ게임 .Statics.DealedNums++;
index = Math.floor(Math.random() * (this.allPokers.length - 1) + 0);
c = this.allPokers.splice(index, 1);
c[0 ].visible = 사실;
this.myPokers.push(c[0]);
DdZGame.Statics.DealedNums++;
this.Dealing();
}
},
GetLander: 함수 (firstGet, minScore, curScore ) {
/*随机출谁先叫地主*/
//if (curScore && !this.isGetLander[1] && !this.isGetLander[2] && !this.isGetLander[3]) {
// //**게임 종료 !
/ /Alert ( ''人 人 抢 地主 ');
// return;
//}
var var postion = {1 : {y : 100, x : 640}, 3 : {y : 100, x : 126} , 2: { x: 216, y: 297 } };
if (!curScore) {
if (!minScore)
minScore = 1;
if (!firstGet)
firstGet = Math.floor(Math.random() * (3 - 1 + 1) + 1);
if (firstGet == 1 || firstGet == 3) { //电脑抢地主
if (this.isGetLander[firstGet] == -1 || this.isGetLander [firstGet]) {
$.each(this.Controls, $.proxy(function (i, o) {
if (o.Lander) {
o.visible = false;
}
}, 이));
var max = 0;
if (this.isGetLander[1] > this.isGetLander[2]) {
max = this.isGetLander[1];
this.Lander = 1;
}
else {
max = this.isGetLander[2];
this.Lander = 2;
}
if (max < this.isGetLander[3]) {
max = this.isGetLander[3];
this.Lander = 3;
}
if (최대 == 0) {
alert('게임 종료 !') ;
return;
}
var txt = max + '분';
var t = {};
var tObj = $.grep(this.Res.Images, function (o, i) { return o.type = = 66; })[0];
$.extend(t, tObj);//复제对象
if (this.CurScore == 4) {
txt = '불抢';
}
t.text = txt ;???? this.Controls.push(t);
//this.drawImage($.proxy(function () {
// this.FanDiPai(this.Lander);
//}, this));
this.F anDiPai(this.Lander);
return;
> .isGetLander[firstGet] = 이것입니다. CurScore == 4 ? -1 : this.CurScore;
var txt = this.CurScore + '分';
var t = {};
var tObj = $.grep(this.Res.Images, function (o, i) 돌아오다 .type == 66; })[0];
$.extend(t, tObj);//复제对象
if (this.CurScore == 4) {
txt = '불抢';
}
t .text = txt;
t.x = position[firstGet].x;
t.y = position[firstGet].y;
t.visible = true;
this.Controls.push(t);
if (this.CurScore == 3) {
this.Lander = firstGet;
//DdZGame.Statics.IsGetLander = true;
//DdZGame.Statics.DealTime = 0;
var dz = {};
$.extend(dz, tObj );//复제제对象
dz.text = '地主';
dz.x = t.x + 30;
dz.y = t.y;
dz.visible = true;
this.Controls.push(dz);
//this.drawImage($.proxy(function () { this.Play(this.Lander, '电脑地主'); }, this));//电脑抢到地主优先ude牌
this.FanDiPai(this.Lander);
return;
}
else {
if (this.CurScore == 4) {
var test = 'abcdefg ';
}
var nextGet = firstGet == 1 ? 2 : 1;
minScore = this.CurScore == 4 ? minScore : this.CurScore + 1;
this.CurScore = this.CurScore == 4 ? 0 : this.CurScore;
DdZGame.Statics.DealTime = 0;
this.drawImage($.proxy(function () { this.GetLander(nextGet, minScore); }, this), true);//电脑抢到地主优先ude牌
return;
}
}
}
if (curScore) {
/*代码写的很垃圾,这点没용면向对象*/
/*내가 집주인에게 전화했습니다. 버튼을 숨겨야 합니다*/ } }
This var tObj = $.grep(this.Res.Images, function ( o, i) { return o.type == 66; }) [0];
~ ~ 44
this.Controls.push(t);
this.isGetLander[2] = curScore == 4 ? -1 : curScore;
if (this.CurScore == 3 | | (this.isGetLander[1] && this.isGetLander[3] && this.CurScore != 4 ;) var dz = {};
$.extend(dz, tObj) dz.text = ' 집주인';
dz.true;
this.Controls.push(dz); /this.drawImage($.proxy(function () { this.Play(this.Lander, '내가 집주인입니다'); }, this), false);//컴퓨터가 집주인을 잡고 카드를 먼저 사용합니다
This.FanDiPai( this.Lander);
This.CurScore = this.CurScore == 4 ? 0 : this.CurScore;
if ( !this.isGetLander[3]) {
DdZGame.Statics.DealTime = 0; Return;}}
else {//이 있었으므로 집주인의 점수가 집주인을 더 사로잡았습니다.
var 최대 =
경우 (this.isgetlander [1] & gt; this.isgetlander [2]) {
max = this.isGetLander[1]; this.Lander = 1 max = this.isGetLander[2];
if (max < this .isGetLander[3] ) {
this.Lander = 3;
}
if (max == 0) {
alert('Game Over !');
return;
}
var txt = '地主';
var t = {};
var tObj = $.grep(this.Res.Images, function (o, i) { return o.type == 66; })[0];
$.extend(t, tObj);//复system对象
t. text = txt;
t.x = position[this.Lander].x;
t.y = position[this.Lander].y;
if (this.Lander != 2) { ㅋㅋㅋ ㅋㅋㅋ push(t);
//DdZGame.Statics.DealTime = 0;
//this.drawImage($.proxy(function () { this.Play(this.Lander, '抢地主啊'); this), false);
this.FanDiPai(this.Lander);
return;
}
}
}
그렇지 않은 경우(이 .isGetLander[2] == -1 || this.isGetLander[2]) {
$.each(this.Controls, $.proxy(function (i, o) {
if (o.Lander) {
o.visible = false;
}
}, 이) );
var max = 0;
if (this.isGetLander[1] > this.isGetLander[2]) {
max = this.isGetLander[1];
.Lander = 1;
}
else {
max = this.isGetLander[2];
this.Lander = 2;
}
if (max < this.isGetLander[3]) {
max = this.isGetLander[3];
this.Lander = 3; # var txt = max + '分';
var t = {};
var tObj = $. grep(this.Res.Images, function (o, i) { return o.type == 66; })[0];
$.extend(t, tObj);//复제对象
if (this.CurScore = = 4) {
txt = '불抢';
}
t.text = txt;
t.x = position[this.Lander].x;
t.y = position[this.Lander].y;
t.visible = true;
this.Controls.push(t);
//DdZGame.Statics.DealTime = 0;
//this.drawImage($.proxy(function () { this.Play(this.Lander, '抢地主啊'); }, this), false);
this .FanDiPai(this.Lander);
return;
}
//if (DdZGame.Statics.IsGetLander) {
// return;
//}
//DdZGame.Statics.IsGetLander = true;//是否재抢地主
console.log('我抢地主');
var btnObj = $.grep(this.Res.Images, $.proxy(function (o, i) {
return o.type == 63;
}, this))[0];
if (!this.CurScore) {
this.CurScore = 0;
}
var txtX = 0;
for (var i = 1; i <= 3; i++) {
만약 (i > this.CurScore) {
var btn = {};
$.extend(btn, btnObj);
btn.text = i + '分';
btn.x = this.myBtnPostion.x;
btn 이 btn.textY = 286;
btn.h = 50;
btn.w = 81;
btn.Lander = true;
btn.onClick = (function (i, obj) { return function () { obj.GetLander(3, i + 1, i); }; })(i, this)
DdZGame.Statics.DealTime = 0;
this.Controls.push(btn);
this.myBtnPostion.x += btn.w + 10;
}
}
if (DdZGame.Statics .DealTime == 0) {
var btn = {};
$.extend(btn, btnObj);
btn.text = '불抢';
btn.x = this.myB tnPostion.x;
btn.y = this.myBtnPostion.y;
btn.visible = true;
btn.type = 63;
btn.textX = this.myBtnPostion.x + 30;
btn.textY = 286;
btn.h = 50;
btn. w = 81;
btn.Lander = true;
btn.onClick = $.proxy(function () { this.GetLander(3, minScore, 4); }, this);
this.Controls.push(btn); + p = '';
if (착륙자 == 1 ) {
p = 'rightPokers';
}
else if (lander == 2) {
p = 'myPokers';
}
else if (lander == 3) {
p = 'leftPokers';
}
/*谁抢到地主,底牌归谁*/
$.each(this.LastPokers, $.proxy(function (i, o) {
var c = {};
$.extend(c, o);
c.x = null;
c.y = null;
this[p].push(c);
test = c.path;
}, this));
if (lander == 2) {
this.myPokers.sort( 함수 (a, b) {
a.x = null;
a.y = null;
b.x = null;
b.y = null;
if (a.type != b.type)
return b.type - a.type;
return b.se - a.se;
});
this.myPannel = { x: 198, y: 330 };
DdZGame.Statics['myPannel'] = null;
}
this.drawImage($.proxy (function () { this.isStart = true; this.Play(lander, '是地主啊'); }, this), false);
},
Play: function (lander, msg) {//出牌
//alert('');
}
});
코드 보기
initialize:这个函数是构造函数,初始化一些起始变。
initE vt这个里是初始化canvas事件,캔버스点击事件不imagesvg那样,因为canvas是一帧一帧画上去的,html dom里是看不到里素,javascript自然也无法获取到canvas里的某个元素,那canvas元素点击事件是怎么处理的了?
首先定义下canvas这个画布的事件,然后定义获取鼠标的坐标,再算流坐标,再算也标,因为每个元也也对己的坐标宽高,所以可以根据这个坐标判断这个坐标是否는 某个元素内。
onControlClick: 这个函数是根据上面算出的坐标,判断此坐标에서哪个元素内,如果에서 元素内,并且定义了onclick函数(注:此处并不是真정적 元素事件,只是对象的一个函数属性),然后调用 onclick函数, 执行是应的代码。
loadImages : 这个是加载所,图 Images 加载完 木 木 木 ,就开始init: 这个函数就是调用loadImages函数 然后所有图 Pictures 加载完毕之后,调用回调函数 ,incanvas上画初始的元素
Dealing : 这个是发牌,每方的牌tour是随机的,if(DdZGame.Statics.DealedNums > = 51)发了51张牌之后,就剩3张底牌,然后再把这51张牌 and3张底牌画incanvas上
GetLander :这个是抢地主,谁先抢地主是随机的,如果是先随机到电脑抢地主,那抢地主的分数也是随机的。
위 내용은 Html5 Doudizhu 체스와 카드는 Doudizhu 게임 코드 분석을 실현하기 위해 Canvas를 설정합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!