474 lines
15 KiB
GDScript
474 lines
15 KiB
GDScript
extends Node2D
|
||
class_name DatawhaleOffice
|
||
## Datawhale 办公室场景
|
||
## 游戏的主要场景
|
||
|
||
# 场景配置
|
||
const SCENE_WIDTH = 2000
|
||
const SCENE_HEIGHT = 1500
|
||
|
||
# Datawhale 品牌色
|
||
const COLOR_PRIMARY = Color(0.118, 0.565, 1.0) # 蓝色 #1E90FF
|
||
const COLOR_SECONDARY = Color(0.0, 0.4, 0.8) # 深蓝 #0066CC
|
||
const COLOR_ACCENT = Color(0.0, 0.749, 1.0) # 亮蓝 #00BFFF
|
||
const COLOR_FLOOR = Color(0.9, 0.9, 0.9) # 浅灰色地板
|
||
const COLOR_WALL = Color(0.4, 0.4, 0.4) # 深灰色墙壁
|
||
const COLOR_FURNITURE = Color(0.545, 0.271, 0.075) # 棕色家具
|
||
|
||
# 节点引用
|
||
@onready var tile_map = $TileMap
|
||
@onready var characters_container = $Characters
|
||
@onready var camera = $Camera2D
|
||
|
||
func _ready():
|
||
"""初始化场景"""
|
||
print("DatawhaleOffice scene loaded")
|
||
print("Scene size: ", SCENE_WIDTH, "x", SCENE_HEIGHT)
|
||
|
||
# 程序化生成场景元素
|
||
_create_scene_elements()
|
||
|
||
# 设置相机限制
|
||
_setup_camera_limits()
|
||
|
||
## 创建场景元素
|
||
func _create_scene_elements():
|
||
"""程序化创建场景的所有视觉元素和碰撞"""
|
||
# 创建地板
|
||
_create_floor()
|
||
|
||
# 创建墙壁(带碰撞)
|
||
_create_walls()
|
||
|
||
# 创建家具(带碰撞)
|
||
_create_furniture()
|
||
|
||
# 创建 Datawhale 品牌元素
|
||
_create_branding()
|
||
|
||
print("Scene elements created")
|
||
|
||
## 设置相机限制
|
||
func _setup_camera_limits():
|
||
"""设置相机边界,防止看到场景外"""
|
||
# 计算视口尺寸(假设默认分辨率 1280x720)
|
||
var viewport_width = 1280
|
||
var viewport_height = 720
|
||
|
||
# 为缩放留出更大的缓冲区,避免缩放时触碰边界造成颠簸
|
||
var buffer_x = viewport_width * 0.8 # 增加水平缓冲区
|
||
var buffer_y = viewport_height * 0.8 # 增加垂直缓冲区
|
||
|
||
# 设置更宽松的相机限制
|
||
camera.limit_left = -buffer_x
|
||
camera.limit_top = -buffer_y
|
||
camera.limit_right = SCENE_WIDTH + buffer_x
|
||
camera.limit_bottom = SCENE_HEIGHT + buffer_y
|
||
|
||
# 启用平滑跟随
|
||
camera.position_smoothing_enabled = true
|
||
camera.position_smoothing_speed = 5.0
|
||
|
||
print("Camera limits set with buffer - Left: ", camera.limit_left, " Top: ", camera.limit_top, " Right: ", camera.limit_right, " Bottom: ", camera.limit_bottom)
|
||
|
||
# 注意:相机的调试控制脚本已在场景文件中直接添加
|
||
# 使用 WASD/方向键移动,Q/E 缩放,R 重置
|
||
|
||
## 获取角色容器
|
||
func get_characters_container() -> Node2D:
|
||
"""
|
||
获取角色容器节点
|
||
@return: 角色容器
|
||
"""
|
||
return characters_container
|
||
|
||
## 设置相机跟随目标
|
||
func set_camera_target(target: Node2D):
|
||
"""
|
||
设置相机跟随的目标
|
||
@param target: 要跟随的节点(通常是玩家角色)
|
||
"""
|
||
if target:
|
||
# 使用 RemoteTransform2D 实现平滑跟随
|
||
var remote_transform = RemoteTransform2D.new()
|
||
remote_transform.remote_path = camera.get_path()
|
||
remote_transform.update_position = true
|
||
remote_transform.update_rotation = false
|
||
remote_transform.update_scale = false
|
||
target.add_child(remote_transform)
|
||
print("Camera following: ", target.name)
|
||
|
||
## 获取场景尺寸
|
||
func get_scene_size() -> Vector2:
|
||
"""
|
||
获取场景尺寸
|
||
@return: 场景尺寸
|
||
"""
|
||
return Vector2(SCENE_WIDTH, SCENE_HEIGHT)
|
||
|
||
## 创建地板
|
||
func _create_floor():
|
||
"""创建地板(纯视觉,无碰撞)"""
|
||
var floor_rect = ColorRect.new()
|
||
floor_rect.name = "Floor"
|
||
floor_rect.size = Vector2(SCENE_WIDTH, SCENE_HEIGHT)
|
||
floor_rect.color = COLOR_FLOOR
|
||
floor_rect.z_index = -10 # 放在最底层
|
||
add_child(floor_rect)
|
||
|
||
## 创建墙壁
|
||
func _create_walls():
|
||
"""创建墙壁(带碰撞)"""
|
||
var walls_container = Node2D.new()
|
||
walls_container.name = "Walls"
|
||
add_child(walls_container)
|
||
|
||
# 墙壁厚度
|
||
var wall_thickness = 20
|
||
|
||
# 上墙
|
||
_create_wall(walls_container, Vector2(0, 0), Vector2(SCENE_WIDTH, wall_thickness))
|
||
# 下墙
|
||
_create_wall(walls_container, Vector2(0, SCENE_HEIGHT - wall_thickness), Vector2(SCENE_WIDTH, wall_thickness))
|
||
# 左墙
|
||
_create_wall(walls_container, Vector2(0, 0), Vector2(wall_thickness, SCENE_HEIGHT))
|
||
# 右墙
|
||
_create_wall(walls_container, Vector2(SCENE_WIDTH - wall_thickness, 0), Vector2(wall_thickness, SCENE_HEIGHT))
|
||
|
||
# 内部分隔墙(创建房间)
|
||
# 垂直分隔墙
|
||
_create_wall(walls_container, Vector2(800, 200), Vector2(wall_thickness, 600))
|
||
# 水平分隔墙
|
||
_create_wall(walls_container, Vector2(200, 800), Vector2(1600, wall_thickness))
|
||
|
||
## 创建单个墙壁
|
||
func _create_wall(parent: Node2D, pos: Vector2, size: Vector2):
|
||
"""创建单个墙壁块"""
|
||
var wall = StaticBody2D.new()
|
||
wall.collision_layer = 1 # Layer 1: Walls
|
||
wall.collision_mask = 0
|
||
|
||
# 视觉表现
|
||
var visual = ColorRect.new()
|
||
visual.size = size
|
||
visual.color = COLOR_WALL
|
||
wall.add_child(visual)
|
||
|
||
# 碰撞形状
|
||
var collision = CollisionShape2D.new()
|
||
var shape = RectangleShape2D.new()
|
||
shape.size = size
|
||
collision.shape = shape
|
||
collision.position = size / 2 # 中心点
|
||
wall.add_child(collision)
|
||
|
||
wall.position = pos
|
||
parent.add_child(wall)
|
||
|
||
## 创建家具
|
||
func _create_furniture():
|
||
"""创建家具(办公桌、椅子等)"""
|
||
var furniture_container = Node2D.new()
|
||
furniture_container.name = "Furniture"
|
||
add_child(furniture_container)
|
||
|
||
# 入口区域 - 欢迎台
|
||
_create_furniture_piece(furniture_container, Vector2(100, 100), Vector2(200, 80), "Reception")
|
||
|
||
# 工作区 - 办公桌(6个)
|
||
for i in range(3):
|
||
for j in range(2):
|
||
var desk_pos = Vector2(100 + i * 250, 300 + j * 200)
|
||
_create_furniture_piece(furniture_container, desk_pos, Vector2(120, 60), "Desk")
|
||
|
||
# 会议区 - 会议桌
|
||
_create_furniture_piece(furniture_container, Vector2(900, 300), Vector2(400, 200), "Meeting Table")
|
||
|
||
# 休息区 - 沙发
|
||
_create_furniture_piece(furniture_container, Vector2(100, 900), Vector2(300, 100), "Sofa")
|
||
_create_furniture_piece(furniture_container, Vector2(100, 1050), Vector2(100, 100), "Coffee Table")
|
||
|
||
## 创建单个家具
|
||
func _create_furniture_piece(parent: Node2D, pos: Vector2, size: Vector2, label: String):
|
||
"""创建单个家具块"""
|
||
var furniture = StaticBody2D.new()
|
||
furniture.name = label
|
||
furniture.collision_layer = 2 # Layer 2: Furniture
|
||
furniture.collision_mask = 0
|
||
|
||
# 视觉表现
|
||
var visual = ColorRect.new()
|
||
visual.size = size
|
||
visual.color = COLOR_FURNITURE
|
||
furniture.add_child(visual)
|
||
|
||
# 碰撞形状
|
||
var collision = CollisionShape2D.new()
|
||
var shape = RectangleShape2D.new()
|
||
shape.size = size
|
||
collision.shape = shape
|
||
collision.position = size / 2
|
||
furniture.add_child(collision)
|
||
|
||
furniture.position = pos
|
||
parent.add_child(furniture)
|
||
|
||
## 创建品牌元素
|
||
func _create_branding():
|
||
"""创建 Datawhale 品牌元素"""
|
||
var branding_container = Node2D.new()
|
||
branding_container.name = "Branding"
|
||
branding_container.z_index = 5 # 确保品牌元素在上层
|
||
add_child(branding_container)
|
||
|
||
# 1. 主 Logo 展示区(展示区中心)
|
||
_create_main_logo(branding_container, Vector2(1400, 400))
|
||
|
||
# 2. 欢迎标识(入口区域)
|
||
_create_welcome_sign(branding_container, Vector2(100, 50))
|
||
|
||
# 3. 成就墙(展示区)
|
||
_create_achievement_wall(branding_container, Vector2(1200, 900))
|
||
|
||
# 4. 装饰性品牌元素
|
||
_create_decorative_elements(branding_container)
|
||
|
||
# 5. 地板品牌标识
|
||
_create_floor_branding(branding_container)
|
||
|
||
## 创建主 Logo
|
||
func _create_main_logo(parent: Node2D, pos: Vector2):
|
||
"""创建主 Datawhale Logo(使用真实图片)"""
|
||
var logo_container = Node2D.new()
|
||
logo_container.name = "MainLogo"
|
||
logo_container.position = pos
|
||
parent.add_child(logo_container)
|
||
|
||
# Logo 路径
|
||
var logo_path = "res://assets/ui/datawhale_logo.png"
|
||
|
||
# 检查 Logo 文件是否存在
|
||
if ResourceLoader.exists(logo_path):
|
||
# 创建白色背景板(让蓝色 logo 更突出)
|
||
var bg_panel = ColorRect.new()
|
||
bg_panel.size = Vector2(450, 120)
|
||
bg_panel.color = Color.WHITE
|
||
bg_panel.position = Vector2(-225, -60)
|
||
logo_container.add_child(bg_panel)
|
||
|
||
# 添加边框效果
|
||
var border = ColorRect.new()
|
||
border.size = Vector2(460, 130)
|
||
border.color = COLOR_PRIMARY
|
||
border.position = Vector2(-230, -65)
|
||
border.z_index = -1
|
||
logo_container.add_child(border)
|
||
|
||
# 使用真实的 Logo 图片
|
||
var logo_sprite = Sprite2D.new()
|
||
logo_sprite.texture = load(logo_path)
|
||
# 362x53 像素的 logo,缩放到合适大小
|
||
# 目标宽度约 400 像素,所以 scale = 400/362 ≈ 1.1
|
||
logo_sprite.scale = Vector2(1.1, 1.1)
|
||
logo_sprite.position = Vector2(0, 0)
|
||
logo_container.add_child(logo_sprite)
|
||
|
||
print("✓ Datawhale logo loaded (362x53 px, scaled to fit)")
|
||
else:
|
||
# 如果 logo 文件不存在,使用占位符
|
||
print("⚠ Logo file not found at: ", logo_path)
|
||
print(" Please place logo at: assets/ui/datawhale_logo.png")
|
||
|
||
# 占位符
|
||
var placeholder = ColorRect.new()
|
||
placeholder.size = Vector2(400, 60)
|
||
placeholder.color = COLOR_PRIMARY
|
||
placeholder.position = Vector2(-200, -30)
|
||
logo_container.add_child(placeholder)
|
||
|
||
var placeholder_text = Label.new()
|
||
placeholder_text.text = "DATAWHALE LOGO HERE (362x53)"
|
||
placeholder_text.position = Vector2(-150, -10)
|
||
placeholder_text.add_theme_font_size_override("font_size", 20)
|
||
placeholder_text.add_theme_color_override("font_color", Color.WHITE)
|
||
logo_container.add_child(placeholder_text)
|
||
|
||
# 副标题(在 logo 下方)
|
||
var subtitle = Label.new()
|
||
subtitle.text = "AI Learning Community"
|
||
subtitle.position = Vector2(-80, 80)
|
||
subtitle.add_theme_font_size_override("font_size", 18)
|
||
subtitle.add_theme_color_override("font_color", COLOR_SECONDARY)
|
||
logo_container.add_child(subtitle)
|
||
|
||
## 创建欢迎标识
|
||
func _create_welcome_sign(parent: Node2D, pos: Vector2):
|
||
"""创建入口欢迎标识(带 logo)"""
|
||
var sign_container = Node2D.new()
|
||
sign_container.name = "WelcomeSign"
|
||
sign_container.position = pos
|
||
parent.add_child(sign_container)
|
||
|
||
# 标识背景(白色,让蓝色 logo 更突出)
|
||
var bg = ColorRect.new()
|
||
bg.size = Vector2(600, 100)
|
||
bg.color = Color.WHITE
|
||
sign_container.add_child(bg)
|
||
|
||
# 蓝色边框
|
||
var border = ColorRect.new()
|
||
border.size = Vector2(610, 110)
|
||
border.color = COLOR_PRIMARY
|
||
border.position = Vector2(-5, -5)
|
||
border.z_index = -1
|
||
sign_container.add_child(border)
|
||
|
||
# Logo(如果存在)
|
||
var logo_path = "res://assets/ui/datawhale_logo.png"
|
||
if ResourceLoader.exists(logo_path):
|
||
var logo_sprite = Sprite2D.new()
|
||
logo_sprite.texture = load(logo_path)
|
||
# 小尺寸显示在欢迎标识中
|
||
logo_sprite.scale = Vector2(0.5, 0.5) # 约 181x26.5 像素
|
||
logo_sprite.position = Vector2(120, 50)
|
||
sign_container.add_child(logo_sprite)
|
||
|
||
# 欢迎文字
|
||
var welcome_text = Label.new()
|
||
welcome_text.text = "Welcome to"
|
||
welcome_text.position = Vector2(20, 15)
|
||
welcome_text.add_theme_font_size_override("font_size", 20)
|
||
welcome_text.add_theme_color_override("font_color", COLOR_SECONDARY)
|
||
sign_container.add_child(welcome_text)
|
||
|
||
# Office 文字
|
||
var office_text = Label.new()
|
||
office_text.text = "Office"
|
||
office_text.position = Vector2(250, 50)
|
||
office_text.add_theme_font_size_override("font_size", 24)
|
||
office_text.add_theme_color_override("font_color", COLOR_SECONDARY)
|
||
sign_container.add_child(office_text)
|
||
|
||
## 创建成就墙
|
||
func _create_achievement_wall(parent: Node2D, pos: Vector2):
|
||
"""创建成就展示墙"""
|
||
var wall_container = Node2D.new()
|
||
wall_container.name = "AchievementWall"
|
||
wall_container.position = pos
|
||
parent.add_child(wall_container)
|
||
|
||
# 墙面背景
|
||
var wall_bg = ColorRect.new()
|
||
wall_bg.size = Vector2(600, 450)
|
||
wall_bg.color = Color(0.95, 0.95, 0.95)
|
||
wall_container.add_child(wall_bg)
|
||
|
||
# 顶部 Logo
|
||
var logo_path = "res://assets/ui/datawhale_logo.png"
|
||
if ResourceLoader.exists(logo_path):
|
||
var logo_sprite = Sprite2D.new()
|
||
logo_sprite.texture = load(logo_path)
|
||
logo_sprite.scale = Vector2(0.6, 0.6) # 约 217x32 像素
|
||
logo_sprite.position = Vector2(300, 30)
|
||
wall_container.add_child(logo_sprite)
|
||
|
||
# 标题
|
||
var title = Label.new()
|
||
title.text = "Our Achievements"
|
||
title.position = Vector2(200, 60)
|
||
title.add_theme_font_size_override("font_size", 24)
|
||
title.add_theme_color_override("font_color", COLOR_PRIMARY)
|
||
wall_container.add_child(title)
|
||
|
||
# 成就卡片
|
||
var achievements = [
|
||
{"title": "10K+ Members", "icon_color": COLOR_PRIMARY},
|
||
{"title": "500+ Projects", "icon_color": COLOR_SECONDARY},
|
||
{"title": "100+ Courses", "icon_color": COLOR_ACCENT},
|
||
{"title": "AI Excellence", "icon_color": COLOR_PRIMARY}
|
||
]
|
||
|
||
for i in range(achievements.size()):
|
||
@warning_ignore("integer_division")
|
||
var row = i / 2 # 整数除法
|
||
var col = i % 2
|
||
var card_pos = Vector2(50 + col * 280, 110 + row * 140)
|
||
_create_achievement_card(wall_container, card_pos, achievements[i])
|
||
|
||
## 创建成就卡片
|
||
func _create_achievement_card(parent: Node2D, pos: Vector2, data: Dictionary):
|
||
"""创建单个成就卡片"""
|
||
var card = ColorRect.new()
|
||
card.size = Vector2(240, 100)
|
||
card.color = Color.WHITE
|
||
card.position = pos
|
||
parent.add_child(card)
|
||
|
||
# 图标
|
||
var icon = ColorRect.new()
|
||
icon.size = Vector2(60, 60)
|
||
icon.color = data["icon_color"]
|
||
icon.position = Vector2(20, 20)
|
||
card.add_child(icon)
|
||
|
||
# 文字
|
||
var text = Label.new()
|
||
text.text = data["title"]
|
||
text.position = Vector2(90, 35)
|
||
text.add_theme_font_size_override("font_size", 18)
|
||
text.add_theme_color_override("font_color", COLOR_SECONDARY)
|
||
card.add_child(text)
|
||
|
||
## 创建装饰性元素
|
||
func _create_decorative_elements(parent: Node2D):
|
||
"""创建装饰性品牌元素"""
|
||
# 蓝色装饰条纹(右侧墙面)
|
||
for i in range(8):
|
||
var stripe = ColorRect.new()
|
||
stripe.size = Vector2(40, 200)
|
||
stripe.color = COLOR_ACCENT
|
||
stripe.color.a = 0.2 + (i % 3) * 0.1 # 渐变透明度
|
||
stripe.position = Vector2(1700 + i * 50, 100 + (i % 2) * 100)
|
||
parent.add_child(stripe)
|
||
|
||
# 品牌色圆点装饰(散布在场景中)
|
||
var dot_positions = [
|
||
Vector2(500, 200), Vector2(700, 250), Vector2(900, 150),
|
||
Vector2(300, 600), Vector2(600, 650), Vector2(1100, 600)
|
||
]
|
||
|
||
for pos in dot_positions:
|
||
var dot = ColorRect.new()
|
||
dot.size = Vector2(30, 30)
|
||
dot.color = COLOR_PRIMARY
|
||
dot.color.a = 0.3
|
||
dot.position = pos
|
||
parent.add_child(dot)
|
||
|
||
## 创建地板品牌标识
|
||
func _create_floor_branding(parent: Node2D):
|
||
"""在地板上创建品牌标识"""
|
||
var logo_path = "res://assets/ui/datawhale_logo.png"
|
||
|
||
if ResourceLoader.exists(logo_path):
|
||
# 使用真实 logo 作为地板水印
|
||
var floor_logo = Sprite2D.new()
|
||
floor_logo.texture = load(logo_path)
|
||
floor_logo.position = Vector2(1000, 700)
|
||
floor_logo.rotation = -0.1
|
||
floor_logo.scale = Vector2(3.0, 3.0) # 大尺寸水印
|
||
floor_logo.modulate.a = 0.08 # 非常淡的水印效果
|
||
floor_logo.z_index = -5
|
||
parent.add_child(floor_logo)
|
||
else:
|
||
# 文字水印作为后备
|
||
var floor_logo = Label.new()
|
||
floor_logo.text = "DATAWHALE"
|
||
floor_logo.position = Vector2(800, 600)
|
||
floor_logo.rotation = -0.1
|
||
floor_logo.add_theme_font_size_override("font_size", 120)
|
||
floor_logo.add_theme_color_override("font_color", COLOR_PRIMARY)
|
||
floor_logo.modulate.a = 0.05
|
||
floor_logo.z_index = -5
|
||
parent.add_child(floor_logo)
|