Skip to content

Commit 944ef5a

Browse files
committed
💄 优化节点创建闪电特效
1 parent 1b5b735 commit 944ef5a

5 files changed

Lines changed: 218 additions & 39 deletions

File tree

src/core/algorithm/random.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ export namespace Random {
2424
return new Vector(randomFloat(min.x, max.x), randomFloat(min.y, max.y));
2525
}
2626

27+
/**
28+
* 返回在单位圆上的随机点(落在圆周上)
29+
*/
30+
export function randomVectorOnNormalCircle(): Vector {
31+
const randomDegrees = randomFloat(0, 360);
32+
return new Vector(1, 0).rotateDegrees(randomDegrees);
33+
}
34+
2735
/**
2836
* 泊松分布随机数
2937
* @param lambda 泊松分布参数

src/core/dataStruct/shape/Rectangle.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ export class Rectangle extends Shape {
5959
public get rightBottom(): Vector {
6060
return new Vector(this.right, this.bottom);
6161
}
62+
63+
public get width(): number {
64+
return this.size.x;
65+
}
66+
public get height(): number {
67+
return this.size.y;
68+
}
6269
getRectangle(): Rectangle {
6370
return this.clone();
6471
}

src/core/effect/concrete/EntityCreateLineEffect.tsx

Lines changed: 88 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,103 @@
1-
import { Color } from "../../dataStruct/Color";
1+
import { Random } from "../../algorithm/random";
22
import { ProgressNumber } from "../../dataStruct/ProgressNumber";
33
import { Rectangle } from "../../dataStruct/shape/Rectangle";
44
import { Vector } from "../../dataStruct/Vector";
5+
import { StageStyleManager } from "../../stageStyle/StageStyleManager";
56
import { Effect } from "../effect";
6-
import { LineCuttingEffect } from "./LineCuttingEffect";
7+
import { ZapLineEffect } from "./ZapLineEffect";
78

89
export class EntityCreateLineEffect extends Effect {
910
constructor(
1011
public override timeProgress: ProgressNumber,
1112
public rect: Rectangle,
1213
) {
1314
super(timeProgress);
14-
const fromColor = new Color(100, 100, 100, 0);
15-
const toColor = new Color(255, 255, 255, 1);
16-
const shiftingLength = 0;
1715
// 子特效
18-
this.subEffects = [
19-
new LineCuttingEffect(
20-
new ProgressNumber(0, timeProgress.maxValue),
21-
rect.leftTop.add(new Vector(-shiftingLength, -shiftingLength)),
22-
rect.rightTop,
23-
fromColor.clone(),
24-
toColor.clone(),
25-
10,
26-
),
27-
new LineCuttingEffect(
28-
new ProgressNumber(0, timeProgress.maxValue),
29-
rect.rightTop.add(new Vector(shiftingLength, -shiftingLength)),
30-
rect.rightBottom,
31-
fromColor.clone(),
32-
toColor.clone(),
33-
10,
34-
),
35-
new LineCuttingEffect(
36-
new ProgressNumber(0, timeProgress.maxValue),
37-
rect.rightBottom.add(new Vector(shiftingLength, shiftingLength)),
38-
rect.leftBottom,
39-
fromColor.clone(),
40-
toColor.clone(),
41-
10,
42-
),
43-
new LineCuttingEffect(
44-
new ProgressNumber(0, timeProgress.maxValue),
45-
rect.leftBottom.add(new Vector(-shiftingLength, shiftingLength)),
46-
rect.leftTop,
47-
fromColor,
48-
toColor,
49-
10,
50-
),
51-
];
16+
this.subEffects = [];
17+
// 顶部线
18+
for (let i = 0; i < 10; i++) {
19+
const topStartLocation = new Vector(
20+
Random.randomFloat(this.rect.left, this.rect.right),
21+
this.rect.top,
22+
);
23+
const topEndLocation = topStartLocation.add(
24+
topStartLocation.subtract(this.rect.center).multiply(100),
25+
);
26+
const zapLineEffect = new ZapLineEffect(
27+
topStartLocation,
28+
topEndLocation,
29+
50,
30+
20,
31+
45,
32+
StageStyleManager.currentStyle.StageObjectBorderColor,
33+
this.timeProgress.clone(),
34+
2,
35+
);
36+
this.subEffects.push(zapLineEffect);
37+
}
38+
// 底部线
39+
for (let i = 0; i < 10; i++) {
40+
const bottomStartLocation = new Vector(
41+
Random.randomFloat(this.rect.left, this.rect.right),
42+
this.rect.bottom,
43+
);
44+
const bottomEndLocation = bottomStartLocation.add(
45+
bottomStartLocation.subtract(this.rect.center).multiply(100),
46+
);
47+
const zapLineEffect = new ZapLineEffect(
48+
bottomStartLocation,
49+
bottomEndLocation,
50+
50,
51+
20,
52+
45,
53+
StageStyleManager.currentStyle.StageObjectBorderColor,
54+
this.timeProgress.clone(),
55+
2,
56+
);
57+
this.subEffects.push(zapLineEffect);
58+
}
59+
// 左侧线
60+
for (let i = 0; i < 10; i++) {
61+
const leftStartLocation = new Vector(
62+
this.rect.left,
63+
Random.randomFloat(this.rect.top, this.rect.bottom),
64+
);
65+
const leftEndLocation = leftStartLocation.add(
66+
leftStartLocation.subtract(this.rect.center).multiply(100),
67+
);
68+
const zapLineEffect = new ZapLineEffect(
69+
leftStartLocation,
70+
leftEndLocation,
71+
50,
72+
20,
73+
45,
74+
StageStyleManager.currentStyle.StageObjectBorderColor,
75+
this.timeProgress.clone(),
76+
2,
77+
);
78+
this.subEffects.push(zapLineEffect);
79+
}
80+
// 右侧线
81+
for (let i = 0; i < 10; i++) {
82+
const rightStartLocation = new Vector(
83+
this.rect.right,
84+
Random.randomFloat(this.rect.top, this.rect.bottom),
85+
);
86+
const rightEndLocation = rightStartLocation.add(
87+
rightStartLocation.subtract(this.rect.center).multiply(100),
88+
);
89+
const zapLineEffect = new ZapLineEffect(
90+
rightStartLocation,
91+
rightEndLocation,
92+
50,
93+
20,
94+
45,
95+
StageStyleManager.currentStyle.StageObjectBorderColor,
96+
this.timeProgress.clone(),
97+
2,
98+
);
99+
this.subEffects.push(zapLineEffect);
100+
}
52101
}
53102

54103
static from(rectangle: Rectangle): EntityCreateLineEffect {
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { Random } from "../../algorithm/random";
2+
import { Color, mixColors } from "../../dataStruct/Color";
3+
import { ProgressNumber } from "../../dataStruct/ProgressNumber";
4+
import { Vector } from "../../dataStruct/Vector";
5+
import { CurveRenderer } from "../../render/canvas2d/basicRenderer/curveRenderer";
6+
import { Renderer } from "../../render/canvas2d/renderer";
7+
import { Camera } from "../../stage/Camera";
8+
import { Effect } from "../effect";
9+
10+
/**
11+
* 一条闪电线特效
12+
* 从start点开始,朝着end点前进,
13+
* 经过n短折线,每段折线的长度为l,每次偏转角度为-maxRotateDegrees~maxRotateDegrees之间随机
14+
* 最终不一定到达end点,因为有随机偏移
15+
*/
16+
export class ZapLineEffect extends Effect {
17+
constructor(
18+
start: Vector,
19+
private end: Vector,
20+
private n: number,
21+
private l: number,
22+
private maxRotateDegrees: number,
23+
private color: Color,
24+
public timeProgress: ProgressNumber,
25+
private lineWidth = 10,
26+
) {
27+
super(timeProgress);
28+
this.end = end;
29+
this.n = n;
30+
this.l = l;
31+
this.maxRotateDegrees = maxRotateDegrees;
32+
this.currentPoints.push(start);
33+
}
34+
35+
private currentPoints: Vector[] = [];
36+
37+
tick(): void {
38+
super.tick();
39+
if (this.currentPoints.length < this.n + 1) {
40+
// 开始增加点
41+
const lastPoint = this.currentPoints[this.currentPoints.length - 1];
42+
const direction = Vector.fromTwoPoints(lastPoint, this.end).normalize();
43+
const randomDegrees = Random.randomFloat(
44+
-this.maxRotateDegrees,
45+
this.maxRotateDegrees,
46+
);
47+
const newLocation = lastPoint.add(
48+
direction.rotateDegrees(randomDegrees).multiply(this.l),
49+
);
50+
this.currentPoints.push(newLocation);
51+
}
52+
}
53+
54+
static normal(
55+
startLocation: Vector,
56+
endLocation: Vector,
57+
color: Color,
58+
): ZapLineEffect {
59+
return new ZapLineEffect(
60+
startLocation,
61+
endLocation,
62+
10,
63+
100,
64+
15,
65+
color,
66+
new ProgressNumber(0, 50),
67+
);
68+
}
69+
70+
render(): void {
71+
const currentColor = mixColors(
72+
this.color,
73+
Color.Transparent,
74+
this.timeProgress.rate,
75+
);
76+
const viewLocations = this.currentPoints.map((p) =>
77+
Renderer.transformWorld2View(p),
78+
);
79+
CurveRenderer.renderSolidLineMultipleWithShadow(
80+
viewLocations,
81+
currentColor,
82+
(1 - this.timeProgress.rate) * this.lineWidth * Camera.currentScale,
83+
this.color,
84+
10,
85+
);
86+
}
87+
}

src/core/render/canvas2d/basicRenderer/curveRenderer.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,34 @@ export namespace CurveRenderer {
5353
Canvas.ctx.stroke();
5454
}
5555

56+
/**
57+
* 绘制折线实线,带有阴影
58+
* @param locations
59+
* @param color
60+
* @param width
61+
* @param shadowColor
62+
* @param shadowBlur
63+
*/
64+
export function renderSolidLineMultipleWithShadow(
65+
locations: Vector[],
66+
color: Color,
67+
width: number,
68+
shadowColor: Color,
69+
shadowBlur: number,
70+
): void {
71+
Canvas.ctx.beginPath();
72+
Canvas.ctx.moveTo(locations[0].x, locations[0].y);
73+
for (let i = 1; i < locations.length; i++) {
74+
Canvas.ctx.lineTo(locations[i].x, locations[i].y);
75+
}
76+
Canvas.ctx.lineWidth = width;
77+
Canvas.ctx.strokeStyle = color.toString();
78+
Canvas.ctx.shadowColor = shadowColor.toString();
79+
Canvas.ctx.shadowBlur = shadowBlur;
80+
Canvas.ctx.stroke();
81+
Canvas.ctx.shadowBlur = 0;
82+
}
83+
5684
/**
5785
* 绘制一条虚线
5886
*

0 commit comments

Comments
 (0)