Files
whale-town/scripts/DatawhaleOffice.gd
2025-12-05 19:00:14 +08:00

474 lines
15 KiB
GDScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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)