- Vec3, Color, Transform, Entity, Scene with decorator API - Components: MeshRenderer, RigidBody, Collider, Script - Physics helpers, Tween animations, Camera follow/orbit - Game templates: platformer, RPG, FPS - Scene save/load (JSON), export to .ly - 12 unit tests passing, 89-entity RPG demo verified
106 lines
3.3 KiB
Python
106 lines
3.3 KiB
Python
"""LityPy Demo - 3D 开放世界 RPG"""
|
|
from lity import *
|
|
|
|
scene = Scene("LityPy RPG Demo", 1280, 720)
|
|
camera = Camera()
|
|
|
|
# 地面
|
|
ground = create_ground(scene, 60, Color(0.25, 0.5, 0.2))
|
|
|
|
# 玩家
|
|
player = scene.create("hero", "cube", pos=Vec3(0, 0.5, 0), color=Color.GREEN)
|
|
player.speed = 5.0
|
|
player.add_rigidbody()
|
|
player.add_collider(size=Vec3(0.5, 1, 0.5))
|
|
|
|
# 村庄建筑
|
|
walls = [
|
|
create_building(scene, -5, -5, 2, 2, 2, Color.RED, Color.GRAY),
|
|
create_building(scene, 3, -6, 2.5, 2.5, 2, Color.BLUE, Color.GRAY),
|
|
create_building(scene, -2, -8, 1.8, 1.8, 1.8, Color.YELLOW, Color(0.45, 0.28, 0.15)),
|
|
create_building(scene, 6, -3, 2, 3, 2, Color.ORANGE, Color.GRAY),
|
|
]
|
|
|
|
# NPC
|
|
npc1 = scene.create("merchant", "cube", pos=Vec3(1, 0.4, -4), color=Color.CYAN, tags=["npc"])
|
|
npc1.dialog = "欢迎来到村庄!"
|
|
npc2 = scene.create("guard", "cube", pos=Vec3(-4, 0.4, -3), color=Color.MAGENTA, tags=["npc"])
|
|
npc2.dialog = "小心森林里的怪物!"
|
|
|
|
# 树木
|
|
for i in range(25):
|
|
x, z = rand(-25, 25), rand(-25, 25)
|
|
if abs(x) < 8 and abs(z) < 10: continue
|
|
create_tree(scene, x, z)
|
|
|
|
# 岩石
|
|
for i in range(10):
|
|
x, z = rand(-25, 25), rand(-25, 25)
|
|
scene.create(f"rock_{i}", "sphere", pos=Vec3(x, 0.3, z),
|
|
scale=Vec3(rand(0.3, 0.8), rand(0.2, 0.5), rand(0.3, 0.8)),
|
|
color=Color(0.5, 0.5, 0.5))
|
|
|
|
# 花
|
|
for i in range(15):
|
|
x, z = rand(-10, 10), rand(-10, 10)
|
|
c = Color(rand(0.6, 1), rand(0.1, 0.5), rand(0.1, 0.5))
|
|
scene.create(f"flower_{i}", "sphere", pos=Vec3(x, 0.15, z),
|
|
scale=Vec3(0.1, 0.1, 0.1), color=c)
|
|
|
|
# 水塘
|
|
scene.create("water", "plane", pos=Vec3(-8, 0.05, -3),
|
|
scale=Vec3(4, 1, 4), color=Color(0.15, 0.3, 0.6, 0.8))
|
|
|
|
# 远山
|
|
for i, (x, z, sx, sy, sz) in enumerate([
|
|
(-20, 15, 8, 3, 8), (22, 12, 10, 4, 10), (0, 25, 12, 3, 8)
|
|
]):
|
|
scene.create(f"hill_{i}", "sphere", pos=Vec3(x, -0.5, z),
|
|
scale=Vec3(sx, sy, sz), color=Color(0.2, 0.4, 0.18))
|
|
|
|
# 敌人
|
|
enemies = []
|
|
for i in range(8):
|
|
x, z = rand(-20, 20), rand(5, 20)
|
|
e = scene.create(f"enemy_{i}", "sphere", pos=Vec3(x, 0.5, z),
|
|
color=Color(0.8, 0.2, 0.1), tags=["enemy"])
|
|
e.hp = 100
|
|
e.speed = 2.0
|
|
e.patrol_center = Vec3(x, 0.5, z)
|
|
enemies.append(e)
|
|
|
|
# ===== 游戏逻辑 =====
|
|
score = 0
|
|
hp = 100
|
|
|
|
@scene.on_frame
|
|
def update(dt):
|
|
global score, hp
|
|
camera.follow(player, offset=Vec3(0, 4, -8), smooth=3.0 * dt)
|
|
|
|
for e in enemies:
|
|
d = e.pos.distance(player.pos)
|
|
if d < 15:
|
|
to_player = (player.pos - e.pos).normalize()
|
|
e.pos = e.pos + to_player * e.speed * dt
|
|
e.rot = Vec3(0, math.atan2(to_player.x, to_player.z), 0)
|
|
if d < 8:
|
|
e.pos = e.pos.lerp(e.patrol_center, dt * 0.5)
|
|
|
|
# 导出场景
|
|
export_scene_ly(scene, "rpg_scene.ly")
|
|
scene.save("rpg_scene.json")
|
|
|
|
print(f"\n=== LityPy RPG Demo ===")
|
|
print(f"场景: {len(scene.entities)} 个实体")
|
|
print(f"玩家: {player.pos}")
|
|
print(f"敌人: {len(enemies)} 个")
|
|
print(f"建筑: {len(walls)} 栋")
|
|
print(f"\n特性展示:")
|
|
print(f" Vec3: {Vec3(1,2,3) + Vec3(4,5,6)}")
|
|
print(f" Color.from_hex: {Color.from_hex('#FF5500')}")
|
|
print(f" lerp: {lerp(0, 10, 0.3)}")
|
|
print(f" rand: {rand(0, 100):.2f}")
|
|
print(f" sin: {math.sin(time_s()):.4f}")
|
|
print(f"\n引擎 API 已就绪,需要编译 C 端集成。")
|