Web Technologies
ΠΠ±Π·ΠΎΡ
Wudgine ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΡ Ultralight Π΄Π»Ρ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΈ Π²Π΅Π±-ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ Π² ΠΈΠ³ΡΠΎΠ²ΠΎΠΉ Π΄Π²ΠΈΠΆΠΎΠΊ. ΠΡΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΈΠ΅ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ, HUD ΠΈ Π΄ΡΡΠ³ΠΈΠ΅ ΡΠ»Π΅ΠΌΠ΅Π½ΡΡ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΡ Π²Π΅Π±-ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ.
ΠΡΠ΅ΠΈΠΌΡΡΠ΅ΡΡΠ²Π° ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ Π²Π΅Π±-ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ
ΠΠ½Π°ΠΊΠΎΠΌΡΠ΅ ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ
ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ HTML, CSS ΠΈ JavaScript Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ UI Π²ΠΌΠ΅ΡΡΠΎ ΠΈΠ·ΡΡΠ΅Π½ΠΈΡ Π½ΠΎΠ²ΡΡ ΡΠΈΡΡΠ΅ΠΌ.
ΠΠΈΠ±ΠΊΠΈΠΉ Π΄ΠΈΠ·Π°ΠΉΠ½
Π‘ΠΎΠ·Π΄Π°Π²Π°ΠΉΡΠ΅ ΡΠ»ΠΎΠΆΠ½ΡΠ΅ ΠΈ ΠΎΡΠ·ΡΠ²ΡΠΈΠ²ΡΠ΅ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ CSS.
ΠΡΡΡΡΠ°Ρ ΠΈΡΠ΅ΡΠ°ΡΠΈΡ
ΠΠ·ΠΌΠ΅Π½ΡΠΉΡΠ΅ UI Π±Π΅Π· ΠΏΠ΅ΡΠ΅ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΠΈ ΠΈΠ³ΡΡ.
ΠΠΎΡΡΡΠΏΠ½ΠΎΡΡΡ Π΄Π»Ρ Π΄ΠΈΠ·Π°ΠΉΠ½Π΅ΡΠΎΠ²
ΠΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π΄ΠΈΠ·Π°ΠΉΠ½Π΅ΡΠ°ΠΌ ΡΠ°Π±ΠΎΡΠ°ΡΡ Ρ UI Π±Π΅Π· Π·Π½Π°Π½ΠΈΡ C++.
ΠΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ° Π²Π΅Π±-ΠΏΠΎΠ΄ΡΠΈΡΡΠ΅ΠΌΡ
ΠΠ΅Π±-ΠΏΠΎΠ΄ΡΠΈΡΡΠ΅ΠΌΠ° Wudgine ΡΠΎΡΡΠΎΠΈΡ ΠΈΠ· ΡΠ»Π΅Π΄ΡΡΡΠΈΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠ²:
- WebView β ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ Π΄Π»Ρ ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ Π²Π΅Π±-ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ³ΠΎ
- JavaScript Bridge β ΠΌΠΎΡΡ Π΄Π»Ρ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΡ ΠΌΠ΅ΠΆΠ΄Ρ C++ ΠΈ JavaScript
- Renderer Integration β ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΡ Ρ ΡΠΈΡΡΠ΅ΠΌΠΎΠΉ ΡΠ΅Π½Π΄Π΅ΡΠΈΠ½Π³Π°
- Input System β ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»ΡΡΠΊΠΎΠ³ΠΎ Π²Π²ΠΎΠ΄Π°
// ΠΡΠΈΠΌΠ΅Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ WebView
WebView webView = WebView::Create(800, 600);
webView.LoadURL("file:///assets/ui/main-menu.html");
// Π Π΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ JavaScript API
webView.SetJavaScriptCallback("startGame", [](const JSArgs& args) {
// ΠΠ°ΠΏΡΡΠΊ ΠΈΠ³ΡΡ
gameManager.startNewGame();
return JSValue::Undefined();
});
Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ UI Ρ ΠΏΠΎΠΌΠΎΡΡΡ HTML/CSS
ΠΠ°Π·ΠΎΠ²Π°Ρ ΡΡΡΡΠΊΡΡΡΠ° UI-ΡΠ°ΠΉΠ»Π°
<!-- assets/ui/main-menu.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Main Menu</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="menu-container">
<h1 class="game-title">My Awesome Game</h1>
<div class="menu-buttons">
<button id="start-game">Start Game</button>
<button id="options">Options</button>
<button id="exit">Exit</button>
</div>
</div>
<script src="main-menu.js"></script>
</body>
</html>
Π‘ΡΠΈΠ»ΠΈΠ·Π°ΡΠΈΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ CSS
/* assets/ui/styles.css */
body {
margin: 0;
padding: 0;
font-family: 'Game Font', sans-serif;
background-color: transparent;
overflow: hidden;
user-select: none;
}
.menu-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
background: linear-gradient(rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.9));
}
.game-title {
font-size: 48px;
color: #ffcc00;
text-shadow: 0 0 10px rgba(255, 204, 0, 0.5);
margin-bottom: 50px;
}
.menu-buttons {
display: flex;
flex-direction: column;
gap: 20px;
}
button {
background-color: #333;
color: white;
border: 2px solid #ffcc00;
padding: 15px 30px;
font-size: 24px;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s ease;
min-width: 200px;
}
button:hover {
background-color: #ffcc00;
color: #333;
transform: scale(1.05);
}
ΠΠ½ΡΠ΅ΡΠ°ΠΊΡΠΈΠ²Π½ΠΎΡΡΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ JavaScript
// assets/ui/main-menu.js
document.addEventListener('DOMContentLoaded', () => {
// ΠΠ½ΠΎΠΏΠΊΠ° "Start Game"
document.getElementById('start-game').addEventListener('click', () => {
// ΠΡΠ·ΠΎΠ² C++ ΡΡΠ½ΠΊΡΠΈΠΈ ΡΠ΅ΡΠ΅Π· JavaScript Bridge
window.engine.startGame();
});
// ΠΠ½ΠΎΠΏΠΊΠ° "Options"
document.getElementById('options').addEventListener('click', () => {
window.location.href = 'options.html';
});
// ΠΠ½ΠΎΠΏΠΊΠ° "Exit"
document.getElementById('exit').addEventListener('click', () => {
window.engine.exitGame();
});
// ΠΠ½ΠΈΠΌΠ°ΡΠΈΡ ΠΏΠΎΡΠ²Π»Π΅Π½ΠΈΡ ΠΌΠ΅Π½Ρ
const menuButtons = document.querySelectorAll('.menu-buttons button');
menuButtons.forEach((button, index) => {
button.style.opacity = '0';
button.style.transform = 'translateY(20px)';
setTimeout(() => {
button.style.opacity = '1';
button.style.transform = 'translateY(0)';
}, 100 * (index + 1));
});
});
JavaScript Bridge
JavaScript Bridge ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΎΠ²Π°ΡΡ ΠΌΠ΅ΠΆΠ΄Ρ C++ ΠΊΠΎΠ΄ΠΎΠΌ ΠΈ JavaScript:
// Π Π΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ C++ ΡΡΠ½ΠΊΡΠΈΠΉ Π΄Π»Ρ Π²ΡΠ·ΠΎΠ²Π° ΠΈΠ· JavaScript
WebView webView = WebView::Create(800, 600);
// Π Π΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ ΡΡΠ½ΠΊΡΠΈΠΈ startGame
webView.SetJavaScriptCallback("startGame", [](const JSArgs& args) {
gameManager.startNewGame();
return JSValue::Undefined();
});
// Π Π΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ ΡΡΠ½ΠΊΡΠΈΠΈ exitGame
webView.SetJavaScriptCallback("exitGame", [](const JSArgs& args) {
application.quit();
return JSValue::Undefined();
});
// ΠΠ΅ΡΠ΅Π΄Π°ΡΠ° Π΄Π°Π½Π½ΡΡ
Π² JavaScript
JSObject globalObject = webView.GetGlobalObject();
globalObject["playerName"] = "Hero";
globalObject["playerLevel"] = 5;
globalObject["playerHealth"] = 100;
// ΠΡΠ·ΠΎΠ² C++ ΡΡΠ½ΠΊΡΠΈΠΉ ΠΈΠ· JavaScript
document.getElementById('start-button').addEventListener('click', () => {
// ΠΡΠ·ΠΎΠ² C++ ΡΡΠ½ΠΊΡΠΈΠΈ
window.engine.startGame();
});
// ΠΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π΄Π°Π½Π½ΡΡ
ΠΈΠ· C++
const playerName = window.playerName;
const playerLevel = window.playerLevel;
const playerHealth = window.playerHealth;
document.getElementById('player-info').textContent =
`${playerName} (Level ${playerLevel}) - HP: ${playerHealth}`;
ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ WebUI
ΠΠ»Ρ ΠΈΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΈ Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ° Π² ΡΡΠ΅Π½Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ WebUI:
// Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΡΡΡΠ½ΠΎΡΡΠΈ Ρ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠΎΠΌ WebUI
Entity uiEntity = world.createEntity();
auto& transform = uiEntity.addComponent<Transform>();
auto& webUI = uiEntity.addComponent<WebUI>();
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° WebUI ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΠ°
webUI.setSize(800, 600);
webUI.setURL("file:///assets/ui/hud.html");
webUI.setTransparentBackground(true);
webUI.setInteractive(true);
// Π Π΅Π³ΠΈΡΡΡΠ°ΡΠΈΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ° ΡΠΎΠ±ΡΡΠΈΠΉ
webUI.setEventCallback([](const WebUIEvent& event) {
if (event.type == WebUIEventType::Message && event.message == "use_item") {
int itemId = event.data["itemId"].GetInt();
inventory.useItem(itemId);
}
});
ΠΡΠ»Π°Π΄ΠΊΠ° Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ²
Wudgine ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ Π΄Π»Ρ ΠΎΡΠ»Π°Π΄ΠΊΠΈ Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ²:
- ΠΠ½ΡΠΏΠ΅ΠΊΡΠΎΡ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ²: ΠΏΡΠΎΡΠΌΠΎΡΡ ΠΈ ΡΠ΅Π΄Π°ΠΊΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ DOM ΠΈ CSS
- ΠΠΎΠ½ΡΠΎΠ»Ρ JavaScript: Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ JavaScript ΠΊΠΎΠ΄Π° ΠΈ ΠΏΡΠΎΡΠΌΠΎΡΡ ΠΎΡΠΈΠ±ΠΎΠΊ
- Π‘Π΅ΡΠ΅Π²ΠΎΠΉ ΠΌΠΎΠ½ΠΈΡΠΎΡ: ΠΎΡΡΠ»Π΅ΠΆΠΈΠ²Π°Π½ΠΈΠ΅ Π·Π°Π³ΡΡΠ·ΠΊΠΈ ΡΠ΅ΡΡΡΡΠΎΠ²
- ΠΡΠ»Π°Π΄ΠΊΠ° Π² ΡΠ΅Π°Π»ΡΠ½ΠΎΠΌ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ: ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ ΠΏΡΠΈΠΌΠ΅Π½ΡΡΡΡΡ ΠΌΠ³Π½ΠΎΠ²Π΅Π½Π½ΠΎ
// ΠΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΎΠ² ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°
WebViewConfig config;
config.enableDevTools = true;
WebView webView = WebView::Create(800, 600, config);
// ΠΡΠΊΡΡΡΠΈΠ΅ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΠΎΠ² ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°
webView.ShowDevTools();
ΠΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ
Π Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°ΡΠΈΠΈ ΠΏΠΎ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ Π²Π΅Π±-ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ²:
- ΠΠΈΠ½ΠΈΠΌΠΈΠ·ΠΈΡΡΠΉΡΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ DOM-ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ²
- ΠΠ·Π±Π΅Π³Π°ΠΉΡΠ΅ ΡΠ»ΠΎΠΆΠ½ΡΡ CSS-ΡΠ΅Π»Π΅ΠΊΡΠΎΡΠΎΠ²
- ΠΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΡΠΉΡΠ΅ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΡ ΠΈ ΡΠ΅ΡΡΡΡΡ
- ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ CSS-Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ Π²ΠΌΠ΅ΡΡΠΎ JavaScript
- ΠΠ³ΡΠ°Π½ΠΈΡΡΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ΅Π½Π΅ΠΉ ΠΈ ΡΠΈΠ»ΡΡΡΠΎΠ²
- Π Π°Π·Π΄Π΅Π»ΡΠΉΡΠ΅ ΡΠ»ΠΎΠΆΠ½ΡΠ΅ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ Π½Π° Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ WebView
ΠΡΠΈΠΌΠ΅ΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ
ΠΠ½ΡΡΡΠΈΠΈΠ³ΡΠΎΠ²ΠΎΠΉ HUD
<!-- assets/ui/hud.html -->
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="hud.css">
</head>
<body>
<div class="hud-container">
<div class="health-bar">
<div class="health-fill" id="health-fill"></div>
<span class="health-text" id="health-text">100/100</span>
</div>
<div class="ammo-counter" id="ammo-counter">30/120</div>
<div class="minimap" id="minimap"></div>
</div>
<script src="hud.js"></script>
</body>
</html>
ΠΠ½Π²Π΅Π½ΡΠ°ΡΡ
<!-- assets/ui/inventory.html -->
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="inventory.css">
</head>
<body>
<div class="inventory-grid" id="inventory-grid">
<!-- Π―ΡΠ΅ΠΉΠΊΠΈ ΠΈΠ½Π²Π΅Π½ΡΠ°ΡΡ Π±ΡΠ΄ΡΡ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Ρ ΡΠ΅ΡΠ΅Π· JavaScript -->
</div>
<div class="item-details" id="item-details">
<h3 class="item-name">ΠΡΠ±Π΅ΡΠΈΡΠ΅ ΠΏΡΠ΅Π΄ΠΌΠ΅Ρ</h3>
<p class="item-description"></p>
<div class="item-actions">
<button id="use-item" disabled>ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ</button>
<button id="drop-item" disabled>ΠΡΠ±ΡΠΎΡΠΈΡΡ</button>
</div>
</div>
<script src="inventory.js"></script>
</body>
</html>
Π‘Π»Π΅Π΄ΡΡΡΠΈΠ΅ ΡΠ°Π³ΠΈ
Π’Π΅ΠΏΠ΅ΡΡ, ΠΊΠΎΠ³Π΄Π° Π²Ρ ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΠ»ΠΈΡΡ Ρ Π²Π΅Π±-ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΡΠΌΠΈ Π² Wudgine, ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΠΌ: