试图弄清楚如何为国际象棋游戏编程存储一些有用的数据。
我决定在Raycaster中存放由车载西洋棋棋子发出的光线;这个问题是关于这种结构的实施。
TL; DR(仅限国际象棋游戏玩家......)
首先,我确定了三种射线:
因此,光线的定义如下:
class Ray {
constructor (owner, kind) {
this.owner = owner // chessman which emits ray
this.kind = kind
this.ref = null
this.sequence = []
}
// is computed afetr construction
expand (ref, sequence) {
this.ref = ref // starting ref (origin of the ray)
this.sequence = sequence // array of refs
}
// is called when ray is inserted into raycaster
interact (otherRay) {
// to be implemented
}
}
光线还有两个特殊的复合属性:
表示此射线实例可能被另一个棋子遮挡的地方,以及另一条射线穿过它的位置,以检测可通行性和干扰(用于铸造)
问题:
如何在RayCaster中高效存储光线?
以优化操作的方式,例如:
建议的解决方案/替代方案
也许是个好人:
维护2个数组映射,一个用于发射,一个用于定位
class RayCaster {
constructor() {
this.startings = new Map()
this.endings = new Map()
}
cast(board) { ...iterate through board and casts individual rays }
add(ray) { ... }
getRefsAttackedBy(ref) { ... }
getRefsAttacking(ref) { ... }
}
那么您对此数据结构(RayCaster)的看法是什么?
答案 0 :(得分:0)
最后,由于地图是时间常数访问,我考虑了双地图实现:
constructor() {
this.startings = new Map()
this.endings = new Map()
this.counters = { rays: 0, interactions: 0 }
}
每张地图都由电路板参考,来自" a1"到" h8"
casts(board) {
this.counters = {
rays: this.raysFrom(board),
interactions: this.computeInteractions()
}
}
添加射线是直截了当的:
raysFrom(board) {
let counter = 0;
board.traverse((ref, chessman) => {
let rays = chessman.cast(ref)
for(let ray of rays) {
this.add(ray)
}
counter += rays.length
})
return counter
}
一个简单的光线:
add (ray) {
let skey = ray.ref
let sRays = this.startings.get(sKey)
if(sRays.indexOf(ray) === -1) {
sRays.push(ray)
}
ray.traverse((seqIdx, seqRef) => {
let seqKey = seqRef.key
let eRays = this.endings.get(seqKey)
if (eRays.indexOf(ray) === -1) {
eRays.push(ray)
}
})
}
计算光线相互作用(交叉和阴影)更复杂:
computeInteractions() {
let counter = 0
// consider all starting rays
for (let {sRef, sRays} of this.startings) {
for (let sRay of sRays) {
sRay.traverse((seqIdx, seqRef) => {
// consider all possible intersections
// into the endings map
let eRays = this.endings.get(seqRef.ref)
for(let eRay of eRays) {
// ensure that rays are different
if (sRay !== eRay) {
sRay.interact(eRay)
eRay.interact(sRay)
}
}
})
}
}
return counter
}
其余工作只是在光线类中确定两条光线如何相互作用(交叉或阴影)
感谢您的建议,最好的问候!