mirror of
https://github.com/unanmed/HumanBreak.git
synced 2026-11-03 10:14:34 +08:00
feat: 多云天气
This commit is contained in:
1 parent
8b40e53c2c
commit
49a2b8d4b9
19 files changed
+151
-77
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { Patch, PatchClass } from '@motajs/legacy-common';
|
||||
import { WeatherController } from '../weather';
|
||||
import { WeatherController } from '../render/weather';
|
||||
import { isNil } from 'lodash-es';
|
||||
|
||||
// todo: 添加弃用警告 logger.warn(56)
|
||||
|
||||
@@ -54,6 +54,7 @@ export * from './fx';
|
||||
export * from './legacy';
|
||||
export * from './ui';
|
||||
export * from './utils';
|
||||
export * from './weather';
|
||||
export * from './renderer';
|
||||
export * from './shared';
|
||||
export * from './use';
|
||||
@@ -80,6 +80,7 @@ const MainScene = defineComponent(() => {
|
||||
const hideStatus = ref(false);
|
||||
const locked = ref(false);
|
||||
const weather = new WeatherController();
|
||||
weather.extern('main');
|
||||
|
||||
onMounted(() => {
|
||||
if (map.value) {
|
||||
@@ -201,7 +202,6 @@ const MainScene = defineComponent(() => {
|
||||
const step = core.status.stepPostfix;
|
||||
if (!step) return;
|
||||
const ctx = canvas.ctx;
|
||||
ctx.save();
|
||||
ctx.fillStyle = '#fff';
|
||||
step.forEach(({ x, y, direction }) => {
|
||||
ctx.fillRect(x * 32 + 12, y * 32 + 12, 8, 8);
|
||||
@@ -222,7 +222,6 @@ const MainScene = defineComponent(() => {
|
||||
}
|
||||
}
|
||||
});
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
//#region 交互监听
|
||||
|
||||
@@ -297,7 +297,6 @@ export const RightStatusBar = defineComponent<StatusBarProps<IRightHeroStatus>>(
|
||||
let linked = false;
|
||||
const drawMinimap = (canvas: MotaOffscreenCanvas2D) => {
|
||||
const ctx = canvas.ctx;
|
||||
ctx.save();
|
||||
ctx.scale(
|
||||
1 / core.domStyle.scale / devicePixelRatio,
|
||||
1 / core.domStyle.scale / devicePixelRatio
|
||||
@@ -320,7 +319,6 @@ export const RightStatusBar = defineComponent<StatusBarProps<IRightHeroStatus>>(
|
||||
) ?? '';
|
||||
minimapDrawer.locateMap(minimapDrawer.nowFloor);
|
||||
minimapDrawer.drawMap();
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
watch(
|
||||
|
||||
@@ -376,11 +376,9 @@ export const GameTitle = defineComponent<GameTitleProps>(props => {
|
||||
createMaskGradient(ctx);
|
||||
}
|
||||
const pos = maskPos.value;
|
||||
ctx.save();
|
||||
ctx.translate(pos, 0);
|
||||
ctx.fillStyle = maskGradient!;
|
||||
ctx.fillRect(0, 0, MAIN_WIDTH + MAIN_HEIGHT + 200, MAIN_HEIGHT);
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
const renderTitle = (canvas: MotaOffscreenCanvas2D) => {
|
||||
@@ -388,7 +386,6 @@ export const GameTitle = defineComponent<GameTitleProps>(props => {
|
||||
if (titleGradient === null) {
|
||||
createTitleGradient(ctx);
|
||||
}
|
||||
ctx.save();
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.font = titleFont;
|
||||
@@ -400,12 +397,10 @@ export const GameTitle = defineComponent<GameTitleProps>(props => {
|
||||
blur(1px)
|
||||
`;
|
||||
ctx.fillText(core.firstData.title, 320, 50);
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
const renderCursor = (canvas: MotaOffscreenCanvas2D) => {
|
||||
const ctx = canvas.ctx;
|
||||
ctx.save();
|
||||
ctx.translate(0, 5);
|
||||
ctx.scale(1, cursorScale);
|
||||
ctx.beginPath();
|
||||
@@ -415,7 +410,6 @@ export const GameTitle = defineComponent<GameTitleProps>(props => {
|
||||
ctx.strokeStyle = '#fff';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
return () => (
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { onUnmounted } from 'vue';
|
||||
import { WeatherController } from '../../weather';
|
||||
|
||||
let weatherId = 0;
|
||||
import { WeatherController } from '../weather';
|
||||
|
||||
export function useWeather(): [WeatherController] {
|
||||
const weather = new WeatherController(`@weather-${weatherId}`);
|
||||
weatherId++;
|
||||
const weather = new WeatherController();
|
||||
|
||||
onUnmounted(() => {
|
||||
weather.destroy();
|
||||
|
||||
@@ -77,8 +77,9 @@ export class WeatherController implements IWeatherController {
|
||||
level: number = 5
|
||||
): IWeatherInstance<R, T> | null {
|
||||
const obj = this.getWeatherObject<R, T>(weather);
|
||||
if (!obj) return null;
|
||||
if (!obj || !this.container) return null;
|
||||
const element = obj.create(level);
|
||||
element.size(this.container.width, this.container.height);
|
||||
const instance = new WeatherInstance(obj, element);
|
||||
instance.setZIndex(this.zIndex + this.active.size);
|
||||
this.active.add(instance);
|
||||
@@ -92,6 +93,13 @@ export class WeatherController implements IWeatherController {
|
||||
this.active.delete(instance);
|
||||
}
|
||||
|
||||
clearWeather(): void {
|
||||
this.active.forEach(v => {
|
||||
v.weather.destroy();
|
||||
});
|
||||
this.active.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将此控制器暴露至全局,允许使用 {@link WeatherController.get} 获取到实例
|
||||
* @param id 暴露给全局的 id
|
||||
@@ -102,10 +110,7 @@ export class WeatherController implements IWeatherController {
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.active.forEach(v => {
|
||||
v.weather.destroy();
|
||||
});
|
||||
this.active.clear();
|
||||
this.clearWeather();
|
||||
WeatherController.ticker.remove(this.tick);
|
||||
if (!isNil(this.externId)) {
|
||||
WeatherController.extern.delete(this.externId);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { WeatherController } from './controller';
|
||||
import { CloudWeather, RainWeather, SnowWeather, SunWeather } from './presets';
|
||||
import { CloudWeather, RainWeather } from './presets';
|
||||
|
||||
export function createWeather() {
|
||||
WeatherController.register('cloud', CloudWeather);
|
||||
WeatherController.register('rain', RainWeather);
|
||||
WeatherController.register('snow', SnowWeather);
|
||||
WeatherController.register('sun', SunWeather);
|
||||
// WeatherController.register('snow', SnowWeather);
|
||||
// WeatherController.register('sun', SunWeather);
|
||||
}
|
||||
|
||||
export * from './presets';
|
||||
|
||||
@@ -1,16 +1,82 @@
|
||||
import { Sprite } from '@motajs/render-core';
|
||||
import { MotaOffscreenCanvas2D, Sprite } from '@motajs/render-core';
|
||||
import { Weather } from '../weather';
|
||||
|
||||
export class CloudWeather extends Weather<Sprite> {
|
||||
tick(timestamp: number): void {
|
||||
throw new Error('Method not implemented.');
|
||||
/** 云层的不透明度 */
|
||||
private alpha: number = 0;
|
||||
/** 水平速度 */
|
||||
private vx: number = 0;
|
||||
/** 竖直速度 */
|
||||
private vy: number = 0;
|
||||
/** 水平位置 */
|
||||
private cx: number = 0;
|
||||
/** 竖直位置 */
|
||||
private cy: number = 0;
|
||||
/** 云层移动的最大速度 */
|
||||
private maxSpeed: number = 1;
|
||||
/** 云层图像 */
|
||||
private image: HTMLImageElement | null = null;
|
||||
/** 上一次执行速度变换的时刻 */
|
||||
private lastDvTime = 0;
|
||||
|
||||
private drawCloud(canvas: MotaOffscreenCanvas2D) {
|
||||
const ctx = canvas.ctx;
|
||||
if (!this.image) return;
|
||||
ctx.globalAlpha = this.alpha;
|
||||
const { width, height } = this.image;
|
||||
for (let x = -1; x < 2; x++) {
|
||||
for (let y = -1; y < 2; y++) {
|
||||
const dx = x * width + this.cx;
|
||||
const dy = y * height + this.cy;
|
||||
if (dx > canvas.width || dy > canvas.height) continue;
|
||||
if (dx + width < 0 || dy + height < 0) continue;
|
||||
ctx.drawImage(this.image, dx, dy, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tick(time: number): void {
|
||||
if (!this.element || !this.image) return;
|
||||
this.element.update();
|
||||
if (time - this.lastDvTime > 50) {
|
||||
this.lastDvTime = time;
|
||||
const dvx = ((Math.random() - 0.5) * this.level) / 20;
|
||||
const dvy = ((Math.random() - 0.5) * this.level) / 20;
|
||||
if (Math.sign(dvx) === Math.sign(this.vx)) {
|
||||
const ratio = Math.sqrt(
|
||||
(this.maxSpeed - Math.abs(this.vx)) / this.maxSpeed
|
||||
);
|
||||
const value = Math.abs(dvx) * ratio;
|
||||
this.vx += value * Math.sign(dvx);
|
||||
} else {
|
||||
this.vx += dvx;
|
||||
}
|
||||
if (Math.sign(dvy) === Math.sign(this.vy)) {
|
||||
const ratio = Math.sqrt(
|
||||
(this.maxSpeed - Math.abs(this.vy)) / this.maxSpeed
|
||||
);
|
||||
const value = Math.abs(dvy) * ratio;
|
||||
this.vy += value * Math.sign(dvy);
|
||||
} else {
|
||||
this.vy += dvy;
|
||||
}
|
||||
}
|
||||
this.cx += this.vx;
|
||||
this.cy += this.vy;
|
||||
this.cx %= this.image.width;
|
||||
this.cy %= this.image.height;
|
||||
}
|
||||
|
||||
createElement(level: number): Sprite {
|
||||
throw new Error('Method not implemented.');
|
||||
const element = new Sprite('static', true);
|
||||
element.setRenderFn(canvas => this.drawCloud(canvas));
|
||||
this.maxSpeed = Math.sqrt(level) * 5;
|
||||
this.vx = ((Math.random() - 0.5) * this.maxSpeed) / 2;
|
||||
this.vy = ((Math.random() - 0.5) * this.maxSpeed) / 2;
|
||||
this.alpha = Math.sqrt(level) / 10;
|
||||
this.image = core.material.images.images['cloud.png'];
|
||||
return element;
|
||||
}
|
||||
|
||||
onDestroy(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
onDestroy(): void {}
|
||||
}
|
||||
@@ -75,6 +75,11 @@ export interface IWeatherController {
|
||||
*/
|
||||
deactivate(instance: IWeatherInstance): void;
|
||||
|
||||
/**
|
||||
* 清空天气
|
||||
*/
|
||||
clearWeather(): void;
|
||||
|
||||
/**
|
||||
* 摧毁这个控制器
|
||||
*/
|
||||
|
||||
Reference in new issue
Block a user