Components
ΠΡΠ½ΠΎΠ²Ρ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ²
ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ Π² Wudgine β ΡΡΠΎ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΡ Π΄Π°Π½Π½ΡΡ , ΠΊΠΎΡΠΎΡΡΠ΅ ΠΏΡΠΈΠΊΡΠ΅ΠΏΠ»ΡΡΡΡΡ ΠΊ ΡΡΡΠ½ΠΎΡΡΡΠΌ. ΠΠ½ΠΈ Π½Π΅ ΡΠΎΠ΄Π΅ΡΠΆΠ°Ρ Π»ΠΎΠ³ΠΈΠΊΠΈ, ΡΠΎΠ»ΡΠΊΠΎ Π΄Π°Π½Π½ΡΠ΅.
Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ²
// ΠΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΏΡΠΎΡΡΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°
struct HealthComponent {
float maxHealth = 100.0f;
float currentHealth = 100.0f;
// ΠΠΏΡΠΈΠΎΠ½Π°Π»ΡΠ½ΠΎ: ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ
template<typename Archive>
void serialize(Archive& archive) {
archive(maxHealth, currentHealth);
}
};
// Π Π΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°
world.registerComponent<HealthComponent>();
// ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ° ΠΊ ΡΡΡΠ½ΠΎΡΡΠΈ
Entity player = world.createEntity("Player");
auto& health = player.addComponent<HealthComponent>();
health.maxHealth = 200.0f;
health.currentHealth = 200.0f;
ΠΠΈΠ·Π½Π΅Π½Π½ΡΠΉ ΡΠΈΠΊΠ» ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ²
ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ ΠΈΠΌΠ΅ΡΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΠ΅ ΡΠΎΠ±ΡΡΠΈΡ ΠΆΠΈΠ·Π½Π΅Π½Π½ΠΎΠ³ΠΎ ΡΠΈΠΊΠ»Π°:
- OnCreate: ΠΡΠ·ΡΠ²Π°Π΅ΡΡΡ ΠΏΡΠΈ ΡΠΎΠ·Π΄Π°Π½ΠΈΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°
- OnDestroy: ΠΡΠ·ΡΠ²Π°Π΅ΡΡΡ ΠΏΠ΅ΡΠ΅Π΄ ΡΠ½ΠΈΡΡΠΎΠΆΠ΅Π½ΠΈΠ΅ΠΌ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°
- OnEnable: ΠΡΠ·ΡΠ²Π°Π΅ΡΡΡ ΠΏΡΠΈ Π²ΠΊΠ»ΡΡΠ΅Π½ΠΈΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°
- OnDisable: ΠΡΠ·ΡΠ²Π°Π΅ΡΡΡ ΠΏΡΠΈ ΠΎΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°
// ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ Ρ ΠΌΠ΅ΡΠΎΠ΄Π°ΠΌΠΈ ΠΆΠΈΠ·Π½Π΅Π½Π½ΠΎΠ³ΠΎ ΡΠΈΠΊΠ»Π°
struct AIComponent {
float detectionRadius = 10.0f;
Entity target;
void onCreate() {
Debug::log("AI Component created");
}
void onDestroy() {
Debug::log("AI Component destroyed");
}
void onEnable() {
Debug::log("AI Component enabled");
}
void onDisable() {
Debug::log("AI Component disabled");
}
};
ΠΡΡΡΠΎΠ΅Π½Π½ΡΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ
TransformComponent
ΠΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅Ρ ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, ΠΏΠΎΠ²ΠΎΡΠΎΡ ΠΈ ΠΌΠ°ΡΡΡΠ°Π± ΡΡΡΠ½ΠΎΡΡΠΈ Π² ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π΅:
// ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ TransformComponent
auto& transform = entity.addComponent<TransformComponent>();
transform.position = Vector3(0.0f, 1.0f, 0.0f);
transform.rotation = Quaternion::fromEuler(0.0f, 45.0f, 0.0f);
transform.scale = Vector3(1.0f, 1.0f, 1.0f);
// ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΡ
Vector3 forward = transform.getForward();
Vector3 right = transform.getRight();
Vector3 up = transform.getUp();
// ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°Ρ
Vector3 localPoint = Vector3(1.0f, 0.0f, 0.0f);
Vector3 worldPoint = transform.localToWorld(localPoint);
Vector3 backToLocal = transform.worldToLocal(worldPoint);
HierarchyComponent
Π‘ΠΎΠ·Π΄Π°Π΅Ρ ΠΈΠ΅ΡΠ°ΡΡ ΠΈΡΠ΅ΡΠΊΠΈΠ΅ ΠΎΡΠ½ΠΎΡΠ΅Π½ΠΈΡ ΠΌΠ΅ΠΆΠ΄Ρ ΡΡΡΠ½ΠΎΡΡΡΠΌΠΈ:
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΈΠ΅ΡΠ°ΡΡ
ΠΈΠΈ
Entity parent = world.createEntity("Parent");
Entity child = world.createEntity("Child");
// Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ° ΡΠΎΠ΄ΠΈΡΠ΅Π»Ρ
child.setParent(parent);
// ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π΄ΠΎΡΠ΅ΡΠ½ΠΈΡ
ΡΡΡΠ½ΠΎΡΡΠ΅ΠΉ
auto children = parent.getChildren();
for (auto& childEntity : children) {
Debug::log("Child: {}", childEntity.getName());
}
// ΠΠ±Ρ
ΠΎΠ΄ ΠΈΠ΅ΡΠ°ΡΡ
ΠΈΠΈ
parent.traverseHierarchy([](Entity entity, int depth) {
std::string indent(depth * 2, ' ');
Debug::log("{}Entity: {}", indent, entity.getName());
return true; // ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠΈΡΡ ΠΎΠ±Ρ
ΠΎΠ΄
});
MeshRendererComponent
ΠΡΠ²Π΅ΡΠ°Π΅Ρ Π·Π° ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³ 3D-ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ:
// ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΡΠ΅Π½Π΄Π΅ΡΠ΅ΡΠ° ΠΌΠ΅ΡΠ°
auto& meshRenderer = entity.addComponent<MeshRendererComponent>();
meshRenderer.setMesh("assets/models/character.mesh");
meshRenderer.setMaterial("assets/materials/character.mat");
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΡΠ²ΠΎΠΉΡΡΠ² ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³Π°
meshRenderer.setCastShadows(true);
meshRenderer.setReceiveShadows(true);
meshRenderer.setLayer(RenderLayer::Default);
meshRenderer.setVisible(true);
CameraComponent
ΠΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅Ρ ΠΊΠ°ΠΌΠ΅ΡΡ Π΄Π»Ρ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³Π° ΡΡΠ΅Π½Ρ:
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΊΠ°ΠΌΠ΅ΡΡ
auto& camera = entity.addComponent<CameraComponent>();
camera.setProjectionType(ProjectionType::Perspective);
camera.setFieldOfView(60.0f);
camera.setNearClip(0.1f);
camera.setFarClip(1000.0f);
camera.setPriority(0); // ΠΡΠ½ΠΎΠ²Π½Π°Ρ ΠΊΠ°ΠΌΠ΅ΡΠ°
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΠΏΠΎΡΡΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ
camera.enablePostProcessing(true);
camera.addPostProcessEffect<BloomEffect>();
LightComponent
ΠΠ°Π·ΠΎΠ²ΡΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ Π΄Π»Ρ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠΎΠ² ΡΠ²Π΅ΡΠ°:
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΡΠ²Π΅ΡΠ°
Entity sun = world.createEntity("Sun");
auto& dirLight = sun.addComponent<DirectionalLightComponent>();
dirLight.setDirection(Vector3(-0.5f, -1.0f, -0.3f));
dirLight.setColor(Vector3(1.0f, 0.95f, 0.9f));
dirLight.setIntensity(5.0f);
dirLight.setCastShadows(true);
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΡΠΎΡΠ΅ΡΠ½ΠΎΠ³ΠΎ ΡΠ²Π΅ΡΠ°
Entity lamp = world.createEntity("Lamp");
auto& pointLight = lamp.addComponent<PointLightComponent>();
pointLight.setColor(Vector3(1.0f, 0.8f, 0.6f));
pointLight.setIntensity(2.0f);
pointLight.setRange(10.0f);
pointLight.setCastShadows(true);
RigidbodyComponent
ΠΠΎΠ±Π°Π²Π»ΡΠ΅Ρ ΡΠΈΠ·ΠΈΡΠ΅ΡΠΊΠΎΠ΅ ΡΠ΅Π»ΠΎ Π΄Π»Ρ ΡΠΈΠΌΡΠ»ΡΡΠΈΠΈ ΡΠΈΠ·ΠΈΠΊΠΈ:
// ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΡΠΈΠ·ΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΡΠ΅Π»Π°
auto& rigidbody = entity.addComponent<RigidbodyComponent>();
rigidbody.setMass(10.0f);
rigidbody.setDrag(0.1f);
rigidbody.setAngularDrag(0.05f);
rigidbody.setUseGravity(true);
rigidbody.setKinematic(false);
// ΠΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΡΠΈΠ»
rigidbody.addForce(Vector3(0.0f, 0.0f, 10.0f));
rigidbody.addTorque(Vector3(0.0f, 1.0f, 0.0f));
ColliderComponent
ΠΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅Ρ ΡΠΎΡΠΌΡ Π΄Π»Ρ ΡΠΈΠ·ΠΈΡΠ΅ΡΠΊΠΈΡ ΡΡΠΎΠ»ΠΊΠ½ΠΎΠ²Π΅Π½ΠΈΠΉ:
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΊΠΎΠ»Π»Π°ΠΉΠ΄Π΅ΡΠ°-ΠΊΠΎΡΠΎΠ±ΠΊΠΈ
auto& boxCollider = entity.addComponent<BoxColliderComponent>();
boxCollider.setSize(Vector3(1.0f, 1.0f, 1.0f));
boxCollider.setCenter(Vector3(0.0f, 0.5f, 0.0f));
boxCollider.setMaterial("assets/physics/metal.phymat");
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΡΡΠ΅ΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΠΊΠΎΠ»Π»Π°ΠΉΠ΄Π΅ΡΠ°
auto& sphereCollider = entity.addComponent<SphereColliderComponent>();
sphereCollider.setRadius(0.5f);
sphereCollider.setCenter(Vector3(0.0f, 0.5f, 0.0f));
sphereCollider.setMaterial("assets/physics/rubber.phymat");
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΌΠ΅Ρ-ΠΊΠΎΠ»Π»Π°ΠΉΠ΄Π΅ΡΠ°
auto& meshCollider = entity.addComponent<MeshColliderComponent>();
meshCollider.setMesh("assets/models/terrain.mesh");
meshCollider.setConvex(false);
AudioComponent
ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ Π΄Π»Ρ Π²ΠΎΡΠΏΡΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΡ Π·Π²ΡΠΊΠΎΠ²:
// ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΈΡΡΠΎΡΠ½ΠΈΠΊΠ° Π·Π²ΡΠΊΠ°
auto& audioSource = entity.addComponent<AudioSourceComponent>();
audioSource.setClip("assets/audio/explosion.wav");
audioSource.setVolume(0.8f);
audioSource.setPitch(1.0f);
audioSource.setLoop(false);
audioSource.setSpatialBlend(1.0f); // 3D Π·Π²ΡΠΊ
audioSource.setMinDistance(1.0f);
audioSource.setMaxDistance(20.0f);
// ΠΠΎΡΠΏΡΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΠ΅ Π·Π²ΡΠΊΠ°
audioSource.play();
AnimatorComponent
Π£ΠΏΡΠ°Π²Π»ΡΠ΅Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΠ΅ΠΉ ΠΏΠ΅ΡΡΠΎΠ½Π°ΠΆΠ΅ΠΉ ΠΈ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ²:
// ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π°Π½ΠΈΠΌΠ°ΡΠΎΡΠ°
auto& animator = entity.addComponent<AnimatorComponent>();
animator.setController("assets/animations/character.controller");
// ΠΠΎΡΠΏΡΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΠ΅ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ
animator.play("Walk");
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΎΠ² Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ
animator.setFloat("Speed", 1.5f);
animator.setBool("IsJumping", true);
animator.setTrigger("Attack");
// Π‘ΠΌΠ΅ΡΠΈΠ²Π°Π½ΠΈΠ΅ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΉ
animator.crossFade("Run", 0.2f);
WebUIComponent
ΠΠ½ΡΠ΅Π³ΡΠΈΡΡΠ΅Ρ Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ Π² ΠΈΠ³ΡΠΎΠ²ΡΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΡ:
// ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ°
auto& webUI = entity.addComponent<WebUIComponent>();
webUI.setSource("assets/ui/inventory.html");
webUI.setSize(512, 512);
webUI.setTransparent(true);
webUI.setInteractive(true);
// ΠΠ·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΠ΅ Ρ JavaScript
webUI.callJavaScriptFunction("updateInventory", {{"gold", 100}, {"items", itemsArray}});
// Π Π΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π° ΠΈΠ· JavaScript
webUI.registerCallback("onItemSelected", [](const json& args) {
int itemId = args["itemId"];
Debug::log("Item selected: {}", itemId);
});
ΠΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ
Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ² Ρ Π΄Π°Π½Π½ΡΠΌΠΈ
// ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ Π·Π΄ΠΎΡΠΎΠ²ΡΡ Ρ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΠΌΠΈ ΡΡΠ½ΠΊΡΠΈΡΠΌΠΈ
struct HealthComponent {
float maxHealth = 100.0f;
float currentHealth = 100.0f;
bool isInvulnerable = false;
float regenerationRate = 0.0f;
// ΠΡΠΏΠΎΠΌΠΎΠ³Π°ΡΠ΅Π»ΡΠ½ΡΠ΅ ΠΌΠ΅ΡΠΎΠ΄Ρ (Π½Π΅ Π»ΠΎΠ³ΠΈΠΊΠ°!)
float getHealthPercentage() const {
return currentHealth / maxHealth;
}
bool isDead() const {
return currentHealth <= 0.0f;
}
// Π‘Π΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ
template<typename Archive>
void serialize(Archive& archive) {
archive(maxHealth, currentHealth, isInvulnerable, regenerationRate);
}
};
ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ Ρ ΡΠΎΠ±ΡΡΠΈΡΠΌΠΈ
// ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ Ρ ΡΠΎΠ±ΡΡΠΈΡΠΌΠΈ
struct DamageableComponent {
using DamageEvent = std::function<void(float damageAmount, Entity source)>;
using DeathEvent = std::function<void(Entity killer)>;
float armor = 0.0f;
float damageMultiplier = 1.0f;
DamageEvent onDamage;
DeathEvent onDeath;
// Π‘Π΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ (ΡΠΎΠ±ΡΡΠΈΡ Π½Π΅ ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·ΡΡΡΡΡ)
template<typename Archive>
void serialize(Archive& archive) {
archive(armor, damageMultiplier);
}
};
// ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠΎΠ±ΡΡΠΈΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°
auto& damageable = entity.addComponent<DamageableComponent>();
damageable.onDamage = [](float amount, Entity source) {
Debug::log("Received {} damage from {}", amount, source.getName());
};
damageable.onDeath = [](Entity killer) {
Debug::log("Killed by {}", killer.getName());
};
ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ Ρ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΡΠΌΠΈ
// ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ, Π·Π°Π²ΠΈΡΡΡΠΈΠΉ ΠΎΡ Π΄ΡΡΠ³ΠΈΡ
ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ²
struct HealthUIComponent {
Entity healthBarEntity;
float updateInterval = 0.1f;
float lastUpdateTime = 0.0f;
void onCreate() {
// ΠΡΠΎΠ²Π΅ΡΠΊΠ° Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ
if (!entity.hasComponent<HealthComponent>()) {
Debug::logWarning("HealthUIComponent requires HealthComponent");
}
}
// Π‘Π΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ
template<typename Archive>
void serialize(Archive& archive) {
archive(healthBarEntity, updateInterval);
}
};
Π Π΅ΡΠ»Π΅ΠΊΡΠΈΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ²
Wudgine ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ ΡΠΈΡΡΠ΅ΠΌΡ ΡΠ΅ΡΠ»Π΅ΠΊΡΠΈΠΈ Π΄Π»Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠΉ ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΠΈ ΠΈ ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ²:
// ΠΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ° Ρ ΡΠ΅ΡΠ»Π΅ΠΊΡΠΈΠ΅ΠΉ
struct PlayerComponent {
float moveSpeed = 5.0f;
float jumpForce = 10.0f;
int playerLevel = 1;
std::string playerName = "Player";
REFLECT_COMPONENT(PlayerComponent)
static void registerReflection() {
REFLECT_PROPERTY(moveSpeed, "Move Speed", "Speed at which the player moves")
.setRange(1.0f, 20.0f)
.setDefaultValue(5.0f);
REFLECT_PROPERTY(jumpForce, "Jump Force", "Force applied when jumping")
.setRange(5.0f, 30.0f);
REFLECT_PROPERTY(playerLevel, "Level", "Current player level")
.setRange(1, 100);
REFLECT_PROPERTY(playerName, "Name", "Player's name");
}
};
// ΠΠ²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠ°Ρ ΡΠ΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ
REGISTER_COMPONENT(PlayerComponent)
Π‘Π»Π΅Π΄ΡΡΡΠΈΠ΅ ΡΠ°Π³ΠΈ
Π’Π΅ΠΏΠ΅ΡΡ, ΠΊΠΎΠ³Π΄Π° Π²Ρ ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΠ»ΠΈΡΡ Ρ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°ΠΌΠΈ Π² Wudgine, ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΠΌ: