diff --git a/idea.md b/idea.md index 9e036cc..1a03f96 100644 --- a/idea.md +++ b/idea.md @@ -23,8 +23,9 @@ [] 苍蓝之殿 1: 红蓝黄门转换 [] 苍蓝之殿 2: -[] 苍蓝之殿 3: +[] 苍蓝之殿 3: 传送门 [] 苍蓝之殿 4: +[] 苍蓝之殿中: 让我们把这些东西结合起来... ### 成就 @@ -96,7 +97,7 @@ dam4.png ---- 存档 59 [] 重构技能树结构 [] 技能树允许自动升级 [] 重构装备系统 -[] 弹幕系统 +[x] 弹幕系统 [x] 优化各种 ui [] 怪物脚下加入阴影 [x] 着色器特效 diff --git a/src/core/main/custom/danmaku.ts b/src/core/main/custom/danmaku.ts index 6355da2..6007a95 100644 --- a/src/core/main/custom/danmaku.ts +++ b/src/core/main/custom/danmaku.ts @@ -109,7 +109,7 @@ export class Danmaku extends EventEmitter { strokeColor: string = 'black'; private posted: boolean = false; - private vNode?: VNode; + vNode?: VNode; private posting: boolean = false; /** @@ -351,6 +351,7 @@ export class Danmaku extends EventEmitter { * 显示这个弹幕 */ show() { + if (this.showing) return; this.showing = true; Danmaku.showList.push(this); Danmaku.showMap.set(this.id, this); @@ -361,6 +362,7 @@ export class Danmaku extends EventEmitter { * 显示结束这个弹幕 */ showEnd() { + if (!this.showing) return; this.showing = false; deleteWith(Danmaku.showList, this); Danmaku.showMap.delete(this.id); diff --git a/src/ui/danmaku.vue b/src/ui/danmaku.vue index 1549fef..c677bd7 100644 --- a/src/ui/danmaku.vue +++ b/src/ui/danmaku.vue @@ -31,19 +31,16 @@ import { mainSetting } from '@/core/main/setting'; import { debounce } from 'lodash-es'; interface ElementMap { - pos: number; ele: HTMLDivElement; danmaku: Danmaku; - style: CSSStyleDeclaration; - width: number; hover: boolean; top: number; + style: CSSStyleDeclaration; } const map = Danmaku.showMap; const eleMap: Map = new Map(); const liked = reactive>({}); -const ticker = new Ticker(); const speed = mainSetting.getValue('ui.danmakuSpeed', 60); @@ -53,10 +50,10 @@ const likeFn = (l: boolean, d: Danmaku) => { watch(Danmaku.showList, list => { list.forEach(v => { - liked[v.id] = v.liked; - v.on('like', likeFn); if (!eleMap.has(v.id)) { nextTick(() => { + liked[v.id] = v.liked; + v.on('like', likeFn); requestAnimationFrame(() => { addElement(v.id); }); @@ -71,59 +68,39 @@ function addElement(id: number) { const div = document.getElementById(`danmaku-${id}`); if (!div) return; - const style = getComputedStyle(div); - const ele: ElementMap = { danmaku, - pos: window.innerWidth + 100, ele: div as HTMLDivElement, - style, - width: parseInt(style.width), hover: false, - top: -1 + top: -1, + style: getComputedStyle(div) }; + div.style.setProperty('--end', `${-div.scrollWidth}px`); + div.style.setProperty( + '--duration', + `${Math.floor((window.innerWidth + div.scrollWidth) / speed)}s` + ); + div.style.setProperty('left', ele.style.left); + div.addEventListener('animationend', () => { + danmaku.showEnd(); + eleMap.delete(id); + }); + eleMap.set(id, ele); calTop(id); } -let lastTime = 0; -ticker.add(time => { - const dt = (time - lastTime) / 1000; - const toDelete: number[] = []; - - eleMap.forEach((value, id) => { - const { danmaku, ele, style, width, hover } = value; - if (!hover) { - const dx = dt * speed; - value.pos -= dx; - ele.style.transform = `translateX(${value.pos.toFixed(2)}px)`; - } - - if (value.pos + width < 0) { - toDelete.push(id); - } - }); - lastTime = time; - - toDelete.forEach(v => { - eleMap.delete(v); - const danmaku = map.get(v); - if (danmaku) { - danmaku.showEnd(); - } - map.delete(v); - }); -}); - function mousein(id: number) { const danmaku = eleMap.get(id)!; danmaku.hover = true; + danmaku.ele.classList.add('danmaku-paused'); } function mouseleave(id: number) { const danmaku = eleMap.get(id)!; danmaku.hover = false; + danmaku.ele.classList.remove('danmaku-paused'); } const touchDebounce = debounce(mouseleave, 3000); @@ -138,15 +115,19 @@ function calTop(id: number) { const used: Set = new Set(); eleMap.forEach(v => { - const { pos, width } = v; + const { ele, style } = v; + const pos = parseInt(style.transform.slice(19, -4)); + const width = ele.scrollWidth; if ( - pos <= window.innerWidth + 125 && - pos + width >= window.innerWidth + 75 + pos <= window.innerWidth + 200 && + pos + width >= window.innerWidth ) { used.add(v.top); } }); let i = -1; + danmaku.top = 0; + danmaku.ele.style.top = `20px`; while (++i < 20) { if (!used.has(i)) { danmaku.top = i; @@ -156,9 +137,7 @@ function calTop(id: number) { } } -onUnmounted(() => { - ticker.destroy(); -}); +onUnmounted(() => {});