feat: 初始化项目结构与核心功能

引入项目基础目录结构,包含多语言支持、主要页面与组件、核心游戏逻辑、UI 组件库、加密与本地持久化、自动化 Docker 构建流程、GitHub issue 模板(中英文)、README(中英文)、LICENSE 及开发配置文件。实现 OGame 单机版主要功能模块,为后续开发和扩展奠定基础。
This commit is contained in:
谦君
2025-12-11 14:49:25 +08:00
commit 705ee8c3db
178 changed files with 17258 additions and 0 deletions

194
src/logic/buildingLogic.ts Normal file
View File

@@ -0,0 +1,194 @@
import type { Planet, Resources, BuildQueueItem } from '@/types/game'
import { BuildingType, TechnologyType, ShipType, DefenseType } from '@/types/game'
import { BUILDINGS } from '@/config/gameConfig'
import * as pointsLogic from './pointsLogic'
/**
* 计算建筑升级成本
*/
export const calculateBuildingCost = (buildingType: BuildingType, targetLevel: number): Resources => {
const config = BUILDINGS[buildingType]
const multiplier = Math.pow(config.costMultiplier, targetLevel - 1)
return {
metal: Math.floor(config.baseCost.metal * multiplier),
crystal: Math.floor(config.baseCost.crystal * multiplier),
deuterium: Math.floor(config.baseCost.deuterium * multiplier),
darkMatter: Math.floor(config.baseCost.darkMatter * multiplier),
energy: 0
}
}
/**
* 计算建筑升级时间
*/
export const calculateBuildingTime = (buildingType: BuildingType, targetLevel: number, buildingSpeedBonus: number = 0): number => {
const config = BUILDINGS[buildingType]
const multiplier = Math.pow(config.costMultiplier, targetLevel - 1)
const baseTime = config.baseTime * multiplier
const speedMultiplier = 1 - buildingSpeedBonus / 100
return Math.floor(baseTime * speedMultiplier)
}
/**
* 计算已用空间
*/
export const calculateUsedSpace = (planet: Planet): number => {
let usedSpace = 0
Object.entries(planet.buildings).forEach(([buildingType, level]) => {
if (level > 0) {
const config = BUILDINGS[buildingType as BuildingType]
usedSpace += config.spaceUsage * level
}
})
return usedSpace
}
/**
* 检查建筑升级条件
*/
export const checkBuildingRequirements = (
buildingType: BuildingType,
planet: Planet,
technologies: Partial<Record<TechnologyType, number>>
): boolean => {
const config = BUILDINGS[buildingType]
const requirements = (config as any).requirements
if (!requirements) return true
for (const [key, level] of Object.entries(requirements)) {
const requiredLevel = level as number
if (Object.values(BuildingType).includes(key as BuildingType)) {
if ((planet.buildings[key as BuildingType] || 0) < requiredLevel) {
return false
}
} else if (Object.values(TechnologyType).includes(key as TechnologyType)) {
if ((technologies[key as TechnologyType] || 0) < requiredLevel) {
return false
}
}
}
return true
}
/**
* 检查是否有足够空间建造
*/
export const checkSpaceAvailable = (planet: Planet, buildingType: BuildingType): boolean => {
const usedSpace = calculateUsedSpace(planet)
const buildingConfig = BUILDINGS[buildingType]
const requiredSpace = buildingConfig.spaceUsage
return usedSpace + requiredSpace <= planet.maxSpace
}
/**
* 创建建造队列项
*/
export const createBuildQueueItem = (buildingType: BuildingType, targetLevel: number, buildTime: number): BuildQueueItem => {
const now = Date.now()
return {
id: `build_${now}`,
type: 'building',
itemType: buildingType,
targetLevel,
startTime: now,
endTime: now + buildTime * 1000
}
}
/**
* 处理建造完成
*/
export const completeBuildQueue = (planet: Planet, now: number, onPointsEarned?: (points: number, type: 'building' | 'ship' | 'defense', itemType: string, level?: number, quantity?: number) => void): void => {
planet.buildQueue = planet.buildQueue.filter(item => {
if (now >= item.endTime) {
// 建造完成
if (item.type === 'building') {
const oldLevel = planet.buildings[item.itemType as BuildingType] || 0
const newLevel = item.targetLevel || 0
planet.buildings[item.itemType as BuildingType] = newLevel
// 计算并累积积分
if (onPointsEarned && newLevel > oldLevel) {
const points = pointsLogic.calculateBuildingPoints(item.itemType as BuildingType, oldLevel, newLevel)
onPointsEarned(points, 'building', item.itemType, newLevel)
}
} else if (item.type === 'ship') {
const shipType = item.itemType as ShipType
const quantity = item.quantity || 0
planet.fleet[shipType] = (planet.fleet[shipType] || 0) + quantity
// 计算并累积积分
if (onPointsEarned && quantity > 0) {
const points = pointsLogic.calculateShipPoints(shipType, quantity)
onPointsEarned(points, 'ship', item.itemType, undefined, quantity)
}
} else if (item.type === 'defense') {
const defenseType = item.itemType as DefenseType
const quantity = item.quantity || 0
planet.defense[defenseType] = (planet.defense[defenseType] || 0) + quantity
// 计算并累积积分
if (onPointsEarned && quantity > 0) {
const points = pointsLogic.calculateDefensePoints(defenseType, quantity)
onPointsEarned(points, 'defense', item.itemType, undefined, quantity)
}
} else if (item.type === 'demolish') {
// 拆除完成,降低建筑等级
// 注意:拆除不会扣除积分,积分只增不减
const buildingType = item.itemType as BuildingType
const currentLevel = planet.buildings[buildingType] || 0
planet.buildings[buildingType] = Math.max(0, currentLevel - 1)
}
return false
}
return true
})
}
/**
* 计算拆除返还资源
* @param buildingType 建筑类型
* @param currentLevel 当前等级
* @returns 返还50%的当前等级建造成本
*/
export const calculateDemolishRefund = (buildingType: BuildingType, currentLevel: number): Resources => {
const cost = calculateBuildingCost(buildingType, currentLevel)
return {
metal: Math.floor(cost.metal * 0.5),
crystal: Math.floor(cost.crystal * 0.5),
deuterium: Math.floor(cost.deuterium * 0.5),
darkMatter: Math.floor(cost.darkMatter * 0.5),
energy: 0
}
}
/**
* 计算拆除时间
* @param buildingType 建筑类型
* @param currentLevel 当前等级
* @param buildingSpeedBonus 建筑速度加成
* @returns 拆除时间建造时间的50%
*/
export const calculateDemolishTime = (buildingType: BuildingType, currentLevel: number, buildingSpeedBonus: number = 0): number => {
const buildTime = calculateBuildingTime(buildingType, currentLevel, buildingSpeedBonus)
return Math.floor(buildTime * 0.5)
}
/**
* 创建拆除队列项
* @param buildingType 建筑类型
* @param currentLevel 当前等级
* @param demolishTime 拆除时间
* @returns 拆除队列项
*/
export const createDemolishQueueItem = (buildingType: BuildingType, currentLevel: number, demolishTime: number): BuildQueueItem => {
const now = Date.now()
return {
id: `demolish_${now}`,
type: 'demolish',
itemType: buildingType,
targetLevel: currentLevel - 1, // 目标等级为当前等级-1
startTime: now,
endTime: now + demolishTime * 1000
}
}