背景
兄弟们,之前我开发了支持联机对战的五子棋、斗地主、UNO。在大家的呼吁之下,我准备开发「象棋」啦!
😄 不出意外,国庆假期,联机象棋就能跟大家见面了!
给大家同步下进展:今天,我绘制了象棋的棋盘,是用SVG绘制的。
象棋棋盘什么样子
![image.png [教你做小游戏] 用SVG画一个象棋棋盘_掘金·日新计划](https://s2.51cto.com/images/blog/202210/01000807_633714679deb223273.webp?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
图片来自维基百科「象棋」。
象棋是9*10的棋盘,虽然中间有一条「楚河汉界」,但是可以忽略不计。你就把象棋当作9*10的棋盘,共计90个位置就可以了。而且那条「楚河汉界」的宽度刚好是一个格子的宽度。
此外,在将帅的九宫格位置,分别有斜线,组成叉叉形状。
此外,在5个兵卒、2个炮的位置,分别有标记点,也需要画出来。
定义好SVG骨架
<svg id="svg" viewBox="-6,-6,92,102" xmlns="http://www.w3.org/2000/svg">
...
</svg>
我们不妨设每个格子宽度为10,那么整个棋盘大小应该是80*90(注意:棋子可以放在角落,虽然能放置9*10=90个棋子,但是其实格线组成的正方形是8*9个)。但是考虑到边线上的棋子,SVG骨架宽度应该超过80*90。我们设棋子半径为4.5,那么SVG骨架尺寸应该超过89*99。这里我们为了美观,再留白一些,设置尺寸为92*102,上下左右都比80*90多余6,是足够完全展示边角的棋子的。
此外,为了计算方便,我们设置坐标时,都要用棋子的中心点来设置,而且需要是10的整数倍。所以SVG视野范围就从(-6, -6)开始了,这样可以保证左上角的棋子坐标是(0, 0)。
绘制边框
通过path绘制。
<path stroke="brown" stroke-width="0.5" fill="none" d="M0,0h80v90h-80z"
我们这就绘制了一个矩形,尺寸是80*90。
绘制格线
我们继续完善上述的path,在d后面补充就可以了。需要补充8条横线、7+7条竖线(注意竖线不要超过楚河汉界)。
<path stroke="brown" stroke-width="0.5" fill="none" d="M0,0h80v90h-80zM0,10h80M0,20h80M0,30h80M0,40h80M0,50h80M0,60h80M0,70h80M0,80h80M10,0v40M20,0v40M30,0v40M40,0v40M50,0v40M60,0v40M70,0v40M10,50v40M20,50v40M30,50v40M40,50v40M50,50v40M60,50v40M70,50v40M30,0l20,20M50,0l-20,20"
绘制斜线
最后在path的d里补充M30,70l20,20M50,70l-20,20
,画2个叉叉:
<path stroke="brown" stroke-width="0.5" fill="none" d="M0,0h80v90h-80zM0,10h80M0,20h80M0,30h80M0,40h80M0,50h80M0,60h80M0,70h80M0,80h80M10,0v40M20,0v40M30,0v40M40,0v40M50,0v40M60,0v40M70,0v40M10,50v40M20,50v40M30,50v40M40,50v40M50,50v40M60,50v40M70,50v40M30,0l20,20M50,0l-20,20M30,70l20,20M50,70l-20,20"
绘制标记点
这里可以复用,我们利用svg的<defs>
定义组件:
<defs>
<path id="mark-right" stroke="brown" stroke-width="0.4" fill="none" d="M1,-2.8v1.8h1.8M1,2.8v-1.8h1.8"
<path id="mark-left" stroke="brown" stroke-width="0.4" fill="none" d="M-1,-2.8v1.8h-1.8M-1,2.8v-1.8h-1.8"
<path id="mark" stroke="brown" stroke-width="0.4" fill="none" d="M1,-2.8v1.8h1.8M1,2.8v-1.8h1.8M-1,-2.8v1.8h-1.8M-1,2.8v-1.8h-1.8"
</defs>
我们定义了3个组件,分别表示「只有右侧的标记点」、「只有左侧的标记点」、「完整的标记点」,也是通过path实现的。
每个标记点的四分之一都是一个小折线,我设置了小折线的宽度、长度均为1.8,并且和标记点中心的水平、垂直距离均是1.2。这是我根据网上的棋盘截图,抓像素计算的大概比例。看起来确实很舒服。
然后通过use
引用组件即可:
<use xlink:href="#mark" x="10" y="20"
<use xlink:href="#mark" x="70" y="20"
<use xlink:href="#mark-right" x="0" y="30"
<use xlink:href="#mark" x="20" y="30"
<use xlink:href="#mark" x="40" y="30"
<use xlink:href="#mark" x="60" y="30"
<use xlink:href="#mark-left" x="80" y="30"
<use xlink:href="#mark-right" x="0" y="60"
<use xlink:href="#mark" x="20" y="60"
<use xlink:href="#mark" x="40" y="60"
<use xlink:href="#mark" x="60" y="60"
<use xlink:href="#mark-left" x="80" y="60"
<use xlink:href="#mark" x="10" y="70"
<use xlink:href="#mark" x="70" y="70"
写下楚河汉界
用text
写楚河汉界,为了让他们垂直水平居中,我使用了文本的text-anchor=middle
和alignment-baseline=central
属性,这时候只要设置x和y为整个棋盘的中心点就可以了。为了让「楚河汉界」四个字中间有固定距离,我使用了全角空格。
<text x="40" y="45" text-anchor="middle" alignment-baseline="central" fill="brown" font-size="6">楚河 漢界</text>
预览效果
写在最后
我是HullQin,独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费无广告。还独立开发了《合成大西瓜重制版》。还开发了《Dice Crush》参加Game Jam 2022。喜欢可以关注我噢~我有空了会分享做游戏的相关技术,会在这2个专栏里分享:《教你做小游戏》、《极致用户体验》。