Overview
ΠΠ²Π΅Π΄Π΅Π½ΠΈΠ΅
Wudgine ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ ΠΌΠΎΡΠ½ΡΡ ΡΠΈΡΡΠ΅ΠΌΡ Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ², ΠΎΡΠ½ΠΎΠ²Π°Π½Π½ΡΡ Π½Π° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ΅ Ultralight, ΠΊΠΎΡΠΎΡΠ°Ρ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°ΠΌ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡ ΠΈΠ³ΡΠΎΠ²ΡΠ΅ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΡ Π²Π΅Π±-ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ.
ΠΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ° Π²Π΅Π±-ΠΏΠΎΠ΄ΡΠΈΡΡΠ΅ΠΌΡ
Π‘ΠΈΡΡΠ΅ΠΌΠ° Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ² Wudgine ΡΠΎΡΡΠΎΠΈΡ ΠΈΠ· ΡΠ»Π΅Π΄ΡΡΡΠΈΡ ΠΎΡΠ½ΠΎΠ²Π½ΡΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ²:
- WebView: ΠΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ Π΄Π»Ρ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³Π° Π²Π΅Π±-ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ³ΠΎ
- JavaScript Bridge: ΠΠΎΡΡ ΠΌΠ΅ΠΆΠ΄Ρ C++ ΠΈ JavaScript Π΄Π»Ρ Π΄Π²ΡΡΡΠΎΡΠΎΠ½Π½Π΅ΠΉ ΠΊΠΎΠΌΠΌΡΠ½ΠΈΠΊΠ°ΡΠΈΠΈ
- WebUI Component: ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ ECS Π΄Π»Ρ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΈ Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ² Π² ΠΈΠ³ΡΠΎΠ²ΡΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΡ
- WebUI System: Π‘ΠΈΡΡΠ΅ΠΌΠ° ECS Π΄Π»Ρ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ ΠΈ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³Π° Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ²
- WebUI Resource: Π Π΅ΡΡΡΡ Π΄Π»Ρ Π·Π°Π³ΡΡΠ·ΠΊΠΈ ΠΈ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ Π²Π΅Π±-ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΡΠΌ
ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΠΈ
Π Π΅Π½Π΄Π΅ΡΠΈΠ½Π³ HTML/CSS
Wudgine ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ Π±ΠΎΠ»ΡΡΠΈΠ½ΡΡΠ²ΠΎ ΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΡΡΠ°Π½Π΄Π°ΡΡΠΎΠ² HTML5 ΠΈ CSS3, Π²ΠΊΠ»ΡΡΠ°Ρ:
- Flexbox ΠΈ Grid Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ Π°Π΄Π°ΠΏΡΠΈΠ²Π½ΡΡ ΠΌΠ°ΠΊΠ΅ΡΠΎΠ²
- CSS-Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ ΠΈ ΠΏΠ΅ΡΠ΅Ρ ΠΎΠ΄Ρ
- Π¨ΡΠΈΡΡΡ ΠΈ ΠΈΠΊΠΎΠ½ΠΊΠΈ
- SVG-Π³ΡΠ°ΡΠΈΠΊΠ°
- ΠΠ΅Π΄ΠΈΠ°-Π·Π°ΠΏΡΠΎΡΡ Π΄Π»Ρ Π°Π΄Π°ΠΏΡΠΈΠ²Π½ΠΎΠ³ΠΎ Π΄ΠΈΠ·Π°ΠΉΠ½Π°
<!-- ΠΡΠΈΠΌΠ΅Ρ HTML-ΡΡΡΡΠΊΡΡΡΡ Π΄Π»Ρ ΠΈΠ³ΡΠΎΠ²ΠΎΠ³ΠΎ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ° -->
<div class="game-ui">
<header class="top-bar">
<div class="health-container">
<div class="health-bar" style="width: 75%"></div>
</div>
<div class="resources">
<span class="gold">1250</span>
<span class="gems">7</span>
</div>
</header>
<div class="inventory-grid">
<!-- Π―ΡΠ΅ΠΉΠΊΠΈ ΠΈΠ½Π²Π΅Π½ΡΠ°ΡΡ Π±ΡΠ΄ΡΡ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Ρ ΡΠ΅ΡΠ΅Π· JavaScript -->
</div>
<footer class="action-bar">
<button class="action-button" data-action="attack">ΠΡΠ°ΠΊΠ°</button>
<button class="action-button" data-action="defend">ΠΠ°ΡΠΈΡΠ°</button>
<button class="action-button" data-action="special">ΠΡΠΎΠ±ΡΠΉ Π½Π°Π²ΡΠΊ</button>
</footer>
</div>
/* ΠΡΠΈΠΌΠ΅Ρ CSS Π΄Π»Ρ ΠΈΠ³ΡΠΎΠ²ΠΎΠ³ΠΎ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ° */
.game-ui {
display: flex;
flex-direction: column;
height: 100%;
font-family: 'GameFont', sans-serif;
color: #e0e0e0;
}
.top-bar {
display: flex;
justify-content: space-between;
padding: 10px;
background: rgba(0, 0, 0, 0.7);
}
.health-container {
width: 200px;
height: 20px;
background: #333;
border: 2px solid #555;
border-radius: 10px;
overflow: hidden;
}
.health-bar {
height: 100%;
background: linear-gradient(to right, #f00, #f55);
transition: width 0.3s ease-out;
}
.inventory-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 10px;
padding: 20px;
flex-grow: 1;
}
.inventory-slot {
aspect-ratio: 1;
background: rgba(0, 0, 0, 0.5);
border: 2px solid #555;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.action-bar {
display: flex;
justify-content: space-around;
padding: 10px;
background: rgba(0, 0, 0, 0.7);
}
.action-button {
padding: 10px 20px;
background: linear-gradient(to bottom, #555, #333);
border: 2px solid #777;
border-radius: 5px;
color: #e0e0e0;
font-weight: bold;
cursor: pointer;
transition: all 0.2s;
}
.action-button:hover {
background: linear-gradient(to bottom, #666, #444);
transform: scale(1.05);
}
.action-button:active {
background: linear-gradient(to bottom, #444, #222);
transform: scale(0.95);
}
JavaScript-ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ
Wudgine ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ Π΄Π²ΡΡΡΠΎΡΠΎΠ½Π½ΡΡ ΠΊΠΎΠΌΠΌΡΠ½ΠΈΠΊΠ°ΡΠΈΡ ΠΌΠ΅ΠΆΠ΄Ρ C++ ΠΈ JavaScript:
// Π Π΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ C++ ΡΡΠ½ΠΊΡΠΈΠΈ Π΄Π»Ρ Π²ΡΠ·ΠΎΠ²Π° ΠΈΠ· JavaScript
auto& webUI = entity.getComponent<WebUIComponent>();
webUI.registerFunction("addItemToInventory", [](const json& args) -> json {
int itemId = args["itemId"];
std::string itemName = args["name"];
// ΠΠΎΠ³ΠΈΠΊΠ° Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΡ ΠΏΡΠ΅Π΄ΠΌΠ΅ΡΠ° Π² ΠΈΠ½Π²Π΅Π½ΡΠ°ΡΡ
InventoryManager::getInstance().addItem(itemId, itemName);
// ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ Π² JavaScript
return {
{"success", true},
{"newCount", InventoryManager::getInstance().getItemCount(itemId)}
};
});
// ΠΡΠ·ΠΎΠ² JavaScript-ΡΡΠ½ΠΊΡΠΈΠΈ ΠΈΠ· C++
json result = webUI.callJavaScriptFunction("updateInventoryUI", {
{"items", InventoryManager::getInstance().getAllItems()},
{"maxSlots", 25}
});
bool success = result["success"];
// ΠΡΠ·ΠΎΠ² C++ ΡΡΠ½ΠΊΡΠΈΠΈ ΠΈΠ· JavaScript
function onAddItemButtonClick(itemId, itemName) {
// ΠΡΠ·ΠΎΠ² Π·Π°ΡΠ΅Π³ΠΈΡΡΡΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠΉ C++ ΡΡΠ½ΠΊΡΠΈΠΈ
const result = engine.call('addItemToInventory', {
itemId: itemId,
name: itemName
});
if (result.success) {
console.log(`ΠΡΠ΅Π΄ΠΌΠ΅Ρ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½! ΠΠΎΠ²ΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ: ${result.newCount}`);
showNotification(`ΠΠΎΠ»ΡΡΠ΅Π½ ΠΏΡΠ΅Π΄ΠΌΠ΅Ρ: ${itemName}`);
}
}
// Π€ΡΠ½ΠΊΡΠΈΡ, Π²ΡΠ·ΡΠ²Π°Π΅ΠΌΠ°Ρ ΠΈΠ· C++
function updateInventoryUI(data) {
const inventoryContainer = document.querySelector('.inventory-grid');
inventoryContainer.innerHTML = '';
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΡΠ»ΠΎΡΠΎΠ² ΠΈΠ½Π²Π΅Π½ΡΠ°ΡΡ
for (let i = 0; i < data.maxSlots; i++) {
const slot = document.createElement('div');
slot.className = 'inventory-slot';
// ΠΡΠ»ΠΈ Π² ΡΡΠΎΠΌ ΡΠ»ΠΎΡΠ΅ Π΅ΡΡΡ ΠΏΡΠ΅Π΄ΠΌΠ΅Ρ
const item = data.items[i];
if (item) {
slot.innerHTML = `
<img src="assets/items/${item.icon}" alt="${item.name}">
<span class="item-count">${item.count}</span>
<div class="item-tooltip">${item.name}</div>
`;
slot.setAttribute('data-item-id', item.id);
slot.addEventListener('click', () => onItemClick(item.id));
}
inventoryContainer.appendChild(slot);
}
return { success: true };
}
// Π Π΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ ΡΡΠ½ΠΊΡΠΈΠΈ Π΄Π»Ρ Π²ΡΠ·ΠΎΠ²Π° ΠΈΠ· C++
engine.register('updateInventoryUI', updateInventoryUI);
ΠΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ Ρ ECS
Wudgine ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ WebUIComponent
Π΄Π»Ρ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΈ Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ² Π² ΡΡΡΠ½ΠΎΡΡΠΈ ECS:
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΡΡΡΠ½ΠΎΡΡΠΈ Ρ Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠΌ
Entity uiEntity = world.createEntity("InventoryUI");
// ΠΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ° WebUI
auto& webUI = uiEntity.addComponent<WebUIComponent>();
webUI.setSource("assets/ui/inventory.html");
webUI.setSize(800, 600);
webUI.setTransparent(true);
webUI.setInteractive(true);
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΠΏΠΎΠ·ΠΈΡΠΈΠΈ ΠΈ ΡΠ°Π·ΠΌΠ΅ΡΠ° Π² 3D-ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π΅
auto& transform = uiEntity.getComponent<TransformComponent>();
transform.position = Vector3(0.0f, 1.7f, 0.5f);
transform.rotation = Quaternion::fromEuler(0.0f, 180.0f, 0.0f);
transform.scale = Vector3(0.002f, 0.002f, 0.002f);
// Π Π΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ² ΡΠΎΠ±ΡΡΠΈΠΉ
webUI.onLoadComplete([&uiEntity]() {
Debug::log("UI Π·Π°Π³ΡΡΠΆΠ΅Π½: {}", uiEntity.getName());
// ΠΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ UI ΠΏΠΎΡΠ»Π΅ Π·Π°Π³ΡΡΠ·ΠΊΠΈ
auto& webUI = uiEntity.getComponent<WebUIComponent>();
webUI.callJavaScriptFunction("initializeUI", {
{"playerName", "ΠΠ΅ΡΠΎΠΉ"},
{"level", 5},
{"maxHealth", 100},
{"currentHealth", 75}
});
});
ΠΡΠΈΠΌΠ΅ΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ
ΠΠ½ΡΡΡΠΈΠΈΠ³ΡΠΎΠ²ΠΎΠΉ HUD
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ HUD
Entity hud = world.createEntity("PlayerHUD");
auto& webUI = hud.addComponent<WebUIComponent>();
webUI.setSource("assets/ui/hud.html");
webUI.setSize(1920, 1080);
webUI.setFullscreen(true);
webUI.setTransparent(true);
webUI.setInteractive(false);
// Π‘ΠΈΡΡΠ΅ΠΌΠ° Π΄Π»Ρ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ HUD
class HUDSystem : public ISystem {
private:
World* m_world;
Entity m_player;
Entity m_hud;
public:
HUDSystem(World* world) : m_world(world) {
m_player = world->findEntityByName("Player");
m_hud = world->findEntityByName("PlayerHUD");
}
void update(float deltaTime) override {
if (!m_player.isValid() || !m_hud.isValid()) return;
auto& health = m_player.getComponent<HealthComponent>();
auto& inventory = m_player.getComponent<InventoryComponent>();
auto& webUI = m_hud.getComponent<WebUIComponent>();
// ΠΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ HUD
webUI.callJavaScriptFunction("updateHUD", {
{"health", health.currentHealth},
{"maxHealth", health.maxHealth},
{"stamina", m_player.getComponent<StaminaComponent>().currentStamina},
{"maxStamina", m_player.getComponent<StaminaComponent>().maxStamina},
{"gold", inventory.gold},
{"ammo", inventory.getAmmoCount()}
});
}
};
ΠΠ½Π²Π΅Π½ΡΠ°ΡΡ ΠΈ ΠΌΠ΅Π½Ρ
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΈΠ½Π²Π΅Π½ΡΠ°ΡΡ
Entity inventoryUI = world.createEntity("InventoryUI");
auto& webUI = inventoryUI.addComponent<WebUIComponent>();
webUI.setSource("assets/ui/inventory.html");
webUI.setSize(1200, 800);
webUI.setVisible(false); // ΠΠ·Π½Π°ΡΠ°Π»ΡΠ½ΠΎ ΡΠΊΡΡΡ
webUI.setInteractive(true);
// Π Π΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ² ΡΠΎΠ±ΡΡΠΈΠΉ
webUI.registerFunction("useItem", [&inventoryUI](const json& args) -> json {
int itemId = args["itemId"];
// ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΈΠ³ΡΠΎΠΊΠ°
Entity player = world.findEntityByName("Player");
if (!player.isValid()) {
return {{"success", false}, {"error", "Player not found"}};
}
// ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΡΠ΅Π΄ΠΌΠ΅ΡΠ°
bool success = player.getComponent<InventoryComponent>().useItem(itemId);
return {{"success", success}};
});
// Π‘ΠΈΡΡΠ΅ΠΌΠ° Π΄Π»Ρ ΠΎΡΠΊΡΡΡΠΈΡ/Π·Π°ΠΊΡΡΡΠΈΡ ΠΈΠ½Π²Π΅Π½ΡΠ°ΡΡ
class InventoryUISystem : public ISystem {
private:
World* m_world;
Entity m_inventoryUI;
InputManager* m_inputManager;
public:
InventoryUISystem(World* world, InputManager* inputManager)
: m_world(world), m_inputManager(inputManager) {
m_inventoryUI = world->findEntityByName("InventoryUI");
// Π Π΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ° ΠΊΠ»Π°Π²ΠΈΡΠΈ
m_inputManager->registerKeyCallback(KeyCode::I, [this](bool pressed) {
if (pressed) {
toggleInventory();
}
});
}
void toggleInventory() {
if (!m_inventoryUI.isValid()) return;
auto& webUI = m_inventoryUI.getComponent<WebUIComponent>();
bool isVisible = webUI.isVisible();
webUI.setVisible(!isVisible);
if (!isVisible) {
// ΠΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ Π΄Π°Π½Π½ΡΡ
ΠΏΡΠΈ ΠΎΡΠΊΡΡΡΠΈΠΈ ΠΈΠ½Π²Π΅Π½ΡΠ°ΡΡ
Entity player = m_world->findEntityByName("Player");
if (player.isValid()) {
auto& inventory = player.getComponent<InventoryComponent>();
webUI.callJavaScriptFunction("updateInventoryUI", {
{"items", inventory.getAllItems()},
{"maxSlots", inventory.getMaxSlots()}
});
}
}
}
};
ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ
ΠΠ»Ρ ΠΎΠΏΡΠΈΠΌΠ°Π»ΡΠ½ΠΎΠΉ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ² ΡΠ»Π΅Π΄ΡΠΉΡΠ΅ ΡΡΠΈΠΌ ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°ΡΠΈΡΠΌ:
- ΠΠΈΠ½ΠΈΠΌΠΈΠ·ΠΈΡΡΠΉΡΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ DOM-ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ²
- ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ CSS-Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ Π²ΠΌΠ΅ΡΡΠΎ JavaScript-Π°Π½ΠΈΠΌΠ°ΡΠΈΠΉ
- ΠΠ·Π±Π΅Π³Π°ΠΉΡΠ΅ ΡΠ»ΠΎΠΆΠ½ΡΡ ΡΠ΅Π»Π΅ΠΊΡΠΎΡΠΎΠ² CSS
- ΠΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΡΠΉΡΠ΅ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ ΡΠΏΡΠ°ΠΉΡΡ
- ΠΠΈΠ½ΠΈΠΌΠΈΠ·ΠΈΡΡΠΉΡΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ Π²ΡΠ·ΠΎΠ²ΠΎΠ² ΠΌΠ΅ΠΆΠ΄Ρ C++ ΠΈ JavaScript
- ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ ΠΏΡΠ»ΠΈΠ½Π³ Π΄Π»Ρ ΡΠ°ΡΡΠΎ ΡΠΎΠ·Π΄Π°Π²Π°Π΅ΠΌΡΡ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ²
// ΠΡΠΈΠΌΠ΅Ρ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΏΡΠ»ΠΈΠ½Π³Π° ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ²
class ElementPool {
constructor(tagName, className, parent, initialCount = 10) {
this.pool = [];
this.parent = parent;
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π½Π°ΡΠ°Π»ΡΠ½ΠΎΠ³ΠΎ ΠΏΡΠ»Π° ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ²
for (let i = 0; i < initialCount; i++) {
const element = document.createElement(tagName);
element.className = className;
element.style.display = 'none';
parent.appendChild(element);
this.pool.push(element);
}
}
get() {
// ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠ° ΠΈΠ· ΠΏΡΠ»Π° ΠΈΠ»ΠΈ ΡΠΎΠ·Π΄Π°Π½ΠΈΠ΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ
let element;
if (this.pool.length > 0) {
element = this.pool.pop();
} else {
element = document.createElement(tagName);
element.className = className;
this.parent.appendChild(element);
}
element.style.display = '';
return element;
}
release(element) {
// ΠΠΎΠ·Π²ΡΠ°Ρ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠ° Π² ΠΏΡΠ»
element.style.display = 'none';
this.pool.push(element);
}
}
// ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΡΠ»Π° Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΡΠ°ΡΡΠΈΡ
const particleContainer = document.querySelector('.particle-container');
const particlePool = new ElementPool('div', 'particle', particleContainer, 50);
function createParticle(x, y) {
const particle = particlePool.get();
particle.style.left = `${x}px`;
particle.style.top = `${y}px`;
// ΠΠ½ΠΈΠΌΠ°ΡΠΈΡ ΡΠ°ΡΡΠΈΡΡ
setTimeout(() => {
particlePool.release(particle);
}, 1000);
}
ΠΡΠ»Π°Π΄ΠΊΠ° Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ²
Wudgine ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ Π΄Π»Ρ ΠΎΡΠ»Π°Π΄ΠΊΠΈ Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ²:
- ΠΡΡΡΠΎΠ΅Π½Π½Π°Ρ ΠΊΠΎΠ½ΡΠΎΠ»Ρ JavaScript
- ΠΠ½ΡΠΏΠ΅ΠΊΡΠΎΡ DOM-ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ²
- ΠΡΠ»Π°Π΄ΠΊΠ° ΡΠ΅ΡΠ΅Π²ΡΡ Π·Π°ΠΏΡΠΎΡΠΎΠ²
- ΠΡΠΎΡΠΈΠ»ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ
// ΠΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΎΠ² ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ° Π΄Π»Ρ Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ°
auto& webUI = entity.getComponent<WebUIComponent>();
webUI.enableDevTools(true);
// ΠΡΠ²ΠΎΠ΄ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ Π² ΠΊΠΎΠ½ΡΠΎΠ»Ρ JavaScript
webUI.executeJavaScript("console.log('ΠΡΠ»Π°Π΄ΠΎΡΠ½ΠΎΠ΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅');");
// ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΎΡΠΈΠ±ΠΎΠΊ JavaScript
webUI.onJavaScriptError([](const std::string& errorMessage,
const std::string& sourceFile,
int lineNumber) {
Debug::logError("JavaScript Error: {} in {} at line {}",
errorMessage, sourceFile, lineNumber);
});
Π‘Π»Π΅Π΄ΡΡΡΠΈΠ΅ ΡΠ°Π³ΠΈ
Π’Π΅ΠΏΠ΅ΡΡ, ΠΊΠΎΠ³Π΄Π° Π²Ρ ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΠ»ΠΈΡΡ Ρ ΠΎΡΠ½ΠΎΠ²Π°ΠΌΠΈ Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ² Π² Wudgine, ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΠΌ: