Наверх

Посты по тегу игра

Фильтр и сортировка

Зажигательный блог

ShadowWisp

Делаю игру в годот 4.0.3 часть 3

Всем привет это снова я ShadowWisp давно не виделись у меня вышло обновление и 

Я вышел на новый уровень ведь теперь я не фоткаю комп а делаю скрины прямо на нём! А ещё 

Я наконец начал делать нормальные фотографии для поста ладно хватит рассказывать про себя поговорим про игру

Во первых я наконец сделал анимацию раньше я не мог понять как но 2 дня и я всё понял но увы видео вроде плохо работают но

Забыл сказать тут пока только 2 кадра но они работаю

Забыл сказать тут пока только 2 кадра но они работаю

В тт возможно скоро сниму видео я не уверен пока ладно хватит про тт я переделал меню 

Как то плохо получилось сфоткать

Как то плохо получилось сфоткать

Так же под прошлым постом мне сказал делать уроки сам Рикардио также они победили в голосовании поэтому скоро возможно будет 1 урок

Кстати помните в описании я сказал про праздники? Так вот я сделал анимацию но это мини праздник а большой

Я попал в топ 500 блогов! Спасибо всем кто меня поддержал я очень благодарен.

Скажу почему меня не было во первых я был у бабушки на несколько дней но там я тоже работал рисовал анимацию и тайлмап но он пока не закончен 

Можете глянуть кстати моё первое видео в тт а ещё я хотел отправить фото этого поста в полный размер

Для первого фото я считаю это прикольно

Для первого фото я считаю это прикольно

Кстати я передумал насчёт названия имба от нуба звучит ну не особо по кубически поэтому предлагайте свои варианты в комментариях

Еле вспомнил про планы на будущее начнём 1 сделать нормальный первый уровень а не просто сцена с невидимыми стенами

2 поменять персонажа который стоит в меню 3 сделать больше кадров что б выглядело по живее 4 придумать название игры

Ну и 5 доделать тайл мап когда доделаю расскажу что это ну а на этом всё всем пока 👋 скоро увидимся!

Старое меню

Старое меню

какая версия меню лучше?2

Теги: Видео-игрыGodot игра
2
7
9
2комментария33просмотра

Зажигательный блог

ShadowWisp

Делаю игру в годот 4.0.3 2 часть

Всем привет с вами снова я ShadowWisp👋👋👋👋👋 и сразу хочу сказать что я создал тт канал под этим ником

В нём тоже буду что то публиковать но это также будет здесь но там возможно будут видео

Я решил сделать состава что и когда идёт:
1 приветствие 1-4

2 меню  5-8 блок
3 новые текстуры 9-14
4 скрипты 15-17
5 уровень 1 18-24
6 персонаж 25-28
7 планы и прощание 29-32

И так покажу вам саму игру и заодно буду всё объяснять вам типо что и когда добавил  поехали

Вот оно меню!

Вот оно меню!

Ну я сделал так сказать обычное меню для своей игры, потом его надо будет переделать но это в будущем

Кстати его я добавил постепенно сначала трава что бы её трогать с небом и иконкой этого поста

Потом добавил текстур новых кстати сейчас покажу это и поставил их также переместил иконку поста

Солнце

Солнце

Дерево

Дерево

Листья

Листья

Персонаж

Персонаж

Вот вроде все персонажи теперь сразу прошу извините если буду пистаь с ошибками просто у меня глаз почему то опух и мне закапали теперь плохо видно

А потом я просто забуду про пост как два дня уже это делал и переходим дальше к скриптам я решил их отправить

Меню

Меню 

Персонаж

Персонаж

Вот новые и старые скрипты если что я потом может объясню если надо что за что отвечает

А теперь покажу первый уровень там ещё ничего толком нет но я создал карту это уже круто

Вот он

Вот он

Он двинулся?

Он двинулся?

Э куда!?

Э куда!?

О он вернулся

О он вернулся

Надо было с этого начинать

Надо было с этого начинать

Так вот это весь первый уровень а ещё я хотел кое что рассказать но понял что это входит в персонаж

Ну а теперь собственно персонаж и всё про него 1 он умеет ходить и прыгать 2
За ним ходит камера и я сделал так что бы она не уходила куда не надо

3 шестым будет его фото 4 у него нет анимации жаль:( 5 он также стлит в меню и он является главным героем

6

6

Наконец я закончил с персонажем но . не знаю он не крутой по моеиу поэтому наверно что нибудь сделаю

Ну и вот мои планы наконц я до них добрался их очень много 
1 переделать меню 2 переделать чуть гг 3 сделать первый уровень первым уровнем

4 сделать второй уровень 5 сделать магазин и валюту это будут имбурики тепо рубль  от имба от нуба

 6 Сделать или попытаться сделать скины 7сделать анимацию персонажа 8 возможно с позволения от sasha.go тоже делать уроки но для своей версии и от вашего хотения

Фух вроде всё впервые делаю такой длинный пост в целых 32 блока! Но ладно я вроде всем поделился и могу попрощаться что же всем пока и удачи вам!! 👋👋

мне делать уроки для вас?2

Теги: Видео-игрыИнформатика играGodot
0
7
7
6комментариев39просмотров

Архивная

Mentos

Я СОЗДАЛ СВОЮ ИГРУ | by Mentos

Какая-то нездоровая тематика с вашим программированием и играми пошла..так почему бы к нему не присоединиться?

Mentos present'a..

★ Я СОЗДАЛ СВОЮ ИГРУ ★

Да. Такое резкое заявление не может остаться не замеченным и грубо так говоря неоставленным без вашего внимания. Good day to all and take it easy, as they say! By Mentos!

Под этим спойлером ниже, скрывается HTML-код (открытый браузерный код, который самый простой в освоении на данный момент). НЕ ОТКРЫВАЙТЕ ЭТОТ КОД, ПРОСТО ТАК, ЧТОБЫ НЕ ЛИСТАТЬ ВНИЗ ОЧЕНЬ МНОГО ТЕКСТА. 

КОД: 

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes, maximum-scale=1.5">
    <title>Formula Manager 2026 – F1 & Formula E</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
        body { background: linear-gradient(135deg, #0a0f1e 0%, #1a1f2e 100%); min-height: 100vh; display: flex; justify-content: center; align-items: center; padding: 20px; }
        .app-container { max-width: 960px; width: 100%; }
        .main-menu, .game-container { background: rgba(20, 25, 40, 0.95); backdrop-filter: blur(20px); border-radius: 32px; padding: 24px; box-shadow: 0 25px 50px -12px rgba(0,0,0,0.8); color: #e0e0e0; margin-bottom: 20px; }
        .main-menu h2 { text-align: center; margin-bottom: 24px; font-size: 2rem; }
        .menu-buttons { display: flex; gap: 16px; justify-content: center; flex-wrap: wrap; }
        .menu-btn { border: none; color: white; padding: 20px 30px; border-radius: 24px; font-size: 1.5rem; font-weight: 700; cursor: pointer; transition: 0.2s; width: 280px; text-align: center; }
        .menu-btn.f1 { background: #e10600; } .menu-btn.f1:hover { background: #ff1a1a; }
        .menu-btn.fe { background: #0066cc; } .menu-btn.fe:hover { background: #0080ff; }
        .game-wrapper { display: none; }
        .game-wrapper.active { display: block; }
        .back-btn { border: none; color: white; padding: 10px 18px; border-radius: 30px; font-weight: 600; cursor: pointer; margin-bottom: 16px; }
        .back-btn.f1 { background: #e10600; } .back-btn.fe { background: #0066cc; }

        .game-container h1 { font-size: 2rem; font-weight: 700; text-align: center; margin-bottom: 8px; }
        .game-container .subtitle { text-align: center; font-size: 0.9rem; color: #8a8f9a; margin-bottom: 20px; border-bottom: 1px solid #2a2f3a; padding-bottom: 16px; }
        .single-video { text-align: center; margin-bottom: 20px; }
        .single-video iframe { border-radius: 16px; max-width: 100%; display: none; }
        .video-link { display: inline-flex; align-items: center; justify-content: center; gap: 8px; background: #e10600; color: white; text-decoration: none; font-weight: 600; padding: 10px 24px; border-radius: 30px; font-size: 0.95rem; transition: background 0.2s; }
        .video-link:hover { background: #ff1a1a; }
        .team-selector { background: #0d1117; border-radius: 20px; padding: 20px; margin-bottom: 20px; border: 1px solid #2a2f3a; }
        select { width: 100%; padding: 12px; background: #161b25; border: 1px solid #2a2f3a; color: white; border-radius: 12px; font-size: 1rem; margin-bottom: 10px; }
        .team-preview { background: #161b25; border-radius: 16px; padding: 16px; margin-top: 12px; border: 1px solid #2a2f3a; display: none; }
        .team-preview.active { display: block; }
        .stats-panel { display: flex; justify-content: space-between; background: #0d1117; border-radius: 20px; padding: 16px 20px; margin-bottom: 20px; border: 1px solid #2a2f3a; flex-wrap: wrap; }
        .stat { text-align: center; min-width: 80px; }
        .stat-value { font-size: 1.8rem; font-weight: 700; color: #fff; }
        .stat-label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.5px; color: #8a8f9a; }
        .money { color: #f0b90b; } .money.negative { color: #ff6b6b; }
        .tabs { display: flex; gap: 8px; margin-bottom: 20px; flex-wrap: wrap; }
        .tab { flex: 1; background: #161b25; border: 1px solid #2a2f3a; color: #8a8f9a; padding: 12px 8px; border-radius: 16px; font-weight: 600; font-size: 0.9rem; cursor: pointer; transition: all 0.2s; text-align: center; min-width: 70px; }
        .tab.active { color: white; }
        .view { display: none; animation: fade 0.2s ease; } .view.active { display: block; }
        @keyframes fade { from { opacity: 0.3; } to { opacity: 1; } }
        .card { background: #161b25; border-radius: 20px; padding: 18px; margin-bottom: 16px; border: 1px solid #2a2f3a; }
        .card h3 { font-size: 1.1rem; margin-bottom: 14px; display: flex; align-items: center; gap: 8px; }
        .pilot-row, .upgrade-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; }
        .pilot-name { font-weight: 700; } .pilot-skill { font-size: 0.85rem; color: #a0a5b0; }
        button { background: #2a2f3a; border: none; color: white; padding: 10px 18px; border-radius: 30px; font-weight: 600; font-size: 0.85rem; cursor: pointer; transition: 0.2s; border: 1px solid #3a3f4a; }
        button:hover { background: #3a3f4a; } button.primary { font-weight: 700; } button:disabled { opacity: 0.4; pointer-events: none; }
        .progress-bg { height: 8px; background: #0d1117; border-radius: 10px; margin: 6px 0 12px; overflow: hidden; }
        .progress-fill { height: 100%; width: 0%; border-radius: 10px; transition: width 0.3s; }
        .race-log { background: #0d1117; border-radius: 16px; padding: 12px; max-height: 250px; overflow-y: auto; font-size: 0.85rem; color: #b0b5c0; margin: 12px 0; }
        table { width: 100%; border-collapse: collapse; margin: 10px 0; font-size: 0.85rem; }
        th, td { padding: 6px 8px; border-bottom: 1px solid #2a2f3a; text-align: left; } th { color: #8a8f9a; font-weight: 600; }
        .race-info { font-size: 0.9rem; color: #a0a5b0; margin-top: 6px; }
        .button-group { display: flex; gap: 10px; margin-top: 12px; } .button-group button { flex: 1; }
        .modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); justify-content: center; align-items: center; z-index: 100; }
        .modal.active { display: flex; }
        .modal-content { background: #1a1f2e; border-radius: 24px; padding: 20px; max-width: 700px; width: 90%; max-height: 80vh; overflow-y: auto; color: #e0e0e0; border: 1px solid #2a2f3a; }
        .modal-content h2 { margin-bottom: 12px; }
        .modal-content button { margin-top: 12px; }

        .f1-theme .tab.active { background: #e10600; border-color: #e10600; }
        .f1-theme button.primary { background: #e10600; border-color: #e10600; }
        .f1-theme .progress-fill { background: #e10600; }
        .f1-theme h1 { background: linear-gradient(to right, #e10600, #ff6b6b); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }

        .fe-theme .tab.active { background: #0066cc; border-color: #0066cc; }
        .fe-theme button.primary { background: #0066cc; border-color: #0066cc; }
        .fe-theme .progress-fill { background: #0066cc; }
        .fe-theme h1 { background: linear-gradient(to right, #0066cc, #00aaff); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
    </style>
</head>
<body>
<div class="app-container" id="appContainer">
    <div id="mainMenu" class="main-menu">
        <h2>🏁 Formula Manager 2026</h2>
        <div class="menu-buttons">
            <button class="menu-btn f1" id="playF1Btn">🏎️ F1 Manager 2026</button>
            <button class="menu-btn fe" id="playFEBtn">⚡ Formula E 2025/26</button>
        </div>
    </div>

    <div id="f1Container" class="game-wrapper">
        <button class="back-btn f1" id="backFromF1">↩️ Главное меню</button>
        <div id="f1Root" class="f1-theme game-container"></div>
    </div>

    <div id="feContainer" class="game-wrapper">
        <button class="back-btn fe" id="backFromFE">↩️ Главное меню</button>
        <div id="feRoot" class="fe-theme game-container"></div>
    </div>
</div>

<script>
    (function() {
        function hideAllGames() {
            document.getElementById('f1Container').classList.remove('active');
            document.getElementById('feContainer').classList.remove('active');
            document.getElementById('mainMenu').style.display = 'block';
        }

        class RacingGame {
            constructor(rootId, theme, data) {
                this.root = document.getElementById(rootId);
                this.theme = theme;
                this.data = data;
                this.state = {
                    playerTeamIndex: -1,
                    isSpectator: true,
                    teams: JSON.parse(JSON.stringify(data.teams)),
                    budget: 0,
                    points: 0,
                    currentRace: 1,
                    upgradeCost: 8,
                    raceInProgress: false,
                    standings: [],
                    driverStandings: [],
                    raceHistory: [],
                    qualifyingGrid: []
                };
                this.init();
            }

            init() {
                this.renderStaticHTML();
                this.attachEvents();
                this.resetStandings();
                this.updateUI();
            }

            renderStaticHTML() {
                this.root.innerHTML = `
                    <h1>${this.data.title}</h1>
                    <div class="subtitle">${this.data.subtitle}</div>
                    ${this.theme === 'f1' ? `
                    <div class="single-video">
                        <iframe src="https://vkvideo.ru/video_ext.php?oid=-90428826&id=456246874&hd=2" width="100%" height="300" frameborder="0" allow="autoplay; encrypted-media; fullscreen; picture-in-picture" allowfullscreen onload="this.style.display='block'; this.nextElementSibling.style.display='none';" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline-flex';"></iframe>
                        <a class="video-link" href="https://vkvideo.ru/video-90428826_456246874" target="_blank" style="display: inline-flex;">▶️ Открыть видео ВК</a>
                    </div>` : ''}
                    <div class="team-selector" id="teamSelectPanel">
                        <label style="color:#a0a5b0; margin-bottom:6px; display:block;">Выберите команду или режим наблюдателя:</label>
                        <select id="teamSelect"><option value="">-- Выберите команду --</option></select>
                        <div id="teamPreview" class="team-preview">
                            <h3 style="margin:0 0 12px; font-size:1rem;" id="previewConstructor"></h3>
                            <div class="pilot-row"><span class="pilot-name" id="previewPilot1"></span><span class="pilot-skill" id="previewPilot1Skill"></span></div>
                            <div class="pilot-row"><span class="pilot-name" id="previewPilot2"></span><span class="pilot-skill" id="previewPilot2Skill"></span></div>
                            <div id="previewCarStats" style="margin: 10px 0;"></div>
                            <div style="font-weight:600; margin-top:8px;">Бюджет: <span id="previewBudget" class="money"></span> млн $</div>
                        </div>
                        <div class="button-group">
                            <button id="startCareerBtn" class="primary">🚀 Начать карьеру</button>
                            <button id="spectatorBtn" class="primary" style="background:#4a4f5a; border-color:#4a4f5a;">👁️ Режим наблюдателя</button>
                        </div>
                    </div>
                    <div id="gameUI" style="display:none;">
                        <div class="stats-panel" id="spectatorPanel" style="display: flex;">
                            <div class="stat"><span class="stat-value" id="raceDisplay">1/${this.data.totalRaces}</span><div class="stat-label">Этап</div></div>
                            <div class="stat"><span class="stat-value" style="color:${this.theme === 'f1' ? '#e10600' : '#0066cc'};">👁️</span><div class="stat-label">Наблюдатель</div></div>
                        </div>
                        <div class="stats-panel" id="managerPanel" style="display: none;">
                            <div class="stat"><span class="stat-value money" id="budgetDisplay">0</span><div class="stat-label">Млн $</div></div>
                            <div class="stat"><span class="stat-value" id="pointsDisplay">0</span><div class="stat-label">Очки команды</div></div>
                            <div class="stat"><span class="stat-value" id="raceDisplay2">1/${this.data.totalRaces}</span><div class="stat-label">Этап</div></div>
                            <div class="stat"><span class="stat-value" id="teamNameDisplay">-</span><div class="stat-label">Команда</div></div>
                        </div>
                        <div class="tabs" id="tabsContainer"></div>
                        <div id="teamView" class="view">
                            <div class="card"><h3>🏆 Пилоты</h3><div id="pilot1Info" class="pilot-row"></div><div id="pilot2Info" class="pilot-row"></div><div style="margin-top:12px; font-size:0.85rem; color:#8a8f9a;">Свободные агенты (3 млн за контракт)</div></div>
                            <div class="card"><h3>⚙️ Характеристики машины</h3><div id="carStats"></div></div>
                        </div>
                        <div id="upgradesView" class="view">
                            <div class="card"><h3>📈 Улучшения (8 млн $)</h3><div id="upgradeList"></div></div>
                        </div>
                        <div id="raceView" class="view">
                            <div class="card">
                                <h3>📍 <span id="grandPrixName"></span></h3>
                                <div class="race-info"><div>🏟️ <span id="trackName"></span></div><div>📅 <span id="raceDate"></span></div><div>🔄 Кругов: <span id="raceLaps"></span></div></div>
                                <button id="startRaceBtn" class="primary" style="width:100%; margin-top:16px;">🚦 Старт уик-энда</button>
                                <div id="raceProgress" style="display:none; margin-top:16px;"><div class="progress-bg"><div id="raceProgressBar" class="progress-fill" style="width:0%"></div></div><div id="raceStatusText" class="stat-label" style="text-align:center;">Квалификация...</div></div>
                                <div id="raceLog" class="race-log" style="display:none;"></div>
                                <div id="raceResult" style="margin-top:12px;"></div>
                            </div>
                        </div>
                        <div id="standingsView" class="view"><div class="card"><h3>🏆 Кубок конструкторов</h3><div id="standingsTable"></div></div></div>
                        <div id="driversView" class="view"><div class="card"><h3>👤 Личный зачёт пилотов</h3><div id="driversTable"></div></div></div>
                        <div id="historyView" class="view">
                            <div class="card"><h3>📋 Результаты гонок</h3><select id="historySelect" style="margin-bottom:15px;"><option value="">-- Выберите этап --</option></select><div id="historyTable"></div></div>
                        </div>
                        <div id="newsView" class="view">
                            <div class="card">
                                <h3>📰 Новости</h3>
                                <button id="refreshNewsBtn" class="primary" style="margin-bottom:12px;">🔄 Обновить новости</button>
                                <div id="newsFeed"></div>
                            </div>
                        </div>
                    </div>
                    <div id="statsModal" class="modal">
                        <div class="modal-content">
                            <h2>🏁 <span id="modalRaceName"></span></h2>
                            <div id="modalTable"></div>
                            <button id="closeModalBtn" class="primary">Закрыть</button>
                        </div>
                    </div>
                `;
                const select = this.root.querySelector('#teamSelect');
                this.data.teams.forEach((team, idx) => {
                    const opt = document.createElement('option');
                    opt.value = idx; opt.textContent = team.name;
                    select.appendChild(opt);
                });
            }

            attachEvents() {
                const root = this.root;
                root.querySelector('#teamSelect').addEventListener('change', (e) => this.showTeamPreview(parseInt(e.target.value)));
                root.querySelector('#startCareerBtn').addEventListener('click', () => {
                    const idx = parseInt(root.querySelector('#teamSelect').value);
                    if (isNaN(idx) || idx < 0) { alert('Выберите команду!'); return; }
                    this.setMode(true, idx);
                });
                root.querySelector('#spectatorBtn').addEventListener('click', () => this.setMode(false));
                root.querySelector('#startRaceBtn').addEventListener('click', () => this.simulateRace());
                root.querySelector('#closeModalBtn').addEventListener('click', () => root.querySelector('#statsModal').classList.remove('active'));
                root.querySelector('#historySelect').addEventListener('change', (e) => this.showHistoryTable(e.target.value));
                root.querySelector('#refreshNewsBtn').addEventListener('click', () => this.generateNews());
                root.addEventListener('click', (e) => {
                    if (e.target.classList.contains('hire-btn')) this.hirePilot(parseInt(e.target.dataset.pilotIndex));
                    if (e.target.classList.contains('upgrade-btn')) this.applyUpgrade(e.target.dataset.key);
                });
                window.addEventListener('click', (e) => {
                    if (e.target === root.querySelector('#statsModal')) root.querySelector('#statsModal').classList.remove('active');
                });
            }

            generateNews() {
                const newsDiv = this.root.querySelector('#newsFeed');
                const templates = [
                    "{driver} из команды {team} одержал победу в последнем Гран-при!",
                    "Слухи: {driver} может перейти в {team2} в следующем сезоне.",
                    "Обзор: {team} представила обновлённую аэродинамику на этапе в {location}.",
                    "Контракт: {driver} продлил соглашение с {team} на 2 года.",
                    "Технический сбой: у {driver} отказал двигатель на прогревочном круге.",
                    "Погода внесла коррективы: гонка в {location} прошла под дождём.",
                    "Интервью: {driver} заявил, что машина стала быстрее после обновлений.",
                    "{team} объявила о партнёрстве с новым спонсором.",
                    "Столкновение: {driver} и {driver2} сошли с трассы на первом круге.",
                    "Квалификация: {driver} завоевал поул-позицию в {grandPrix}."
                ];
                const drivers = this.state.teams.flatMap(t => t.drivers.map(d => d.name));
                const teams = this.state.teams.map(t => t.name);
                const locations = this.data.schedule.map(s => s.location);

                let html = '';
                for (let i = 0; i < 5; i++) {
                    const template = templates[Math.floor(Math.random() * templates.length)];
                    let news = template
                        .replace(/{driver}/g, () => drivers[Math.floor(Math.random() * drivers.length)])
                        .replace(/{driver2}/g, () => drivers[Math.floor(Math.random() * drivers.length)])
                        .replace(/{team}/g, () => teams[Math.floor(Math.random() * teams.length)])
                        .replace(/{team2}/g, () => teams[Math.floor(Math.random() * teams.length)])
                        .replace(/{location}/g, () => locations[Math.floor(Math.random() * locations.length)])
                        .replace(/{grandPrix}/g, () => this.data.schedule[Math.floor(Math.random() * this.data.schedule.length)].grandPrix);
                    html += `<div class="card" style="margin-bottom:8px; padding:10px;">${news}</div>`;
                }
                newsDiv.innerHTML = html;
            }

            showTeamPreview(index) {
                const previewDiv = this.root.querySelector('#teamPreview');
                if (isNaN(index) || index < 0) { previewDiv.classList.remove('active'); return; }
                const team = this.data.teams[index];
                this.root.querySelector('#previewConstructor').textContent = team.constructor;
                this.root.querySelector('#previewPilot1').textContent = team.drivers[0].name;
                this.root.querySelector('#previewPilot1Skill').textContent = `Мастерство: ${team.drivers[0].skill}`;
                this.root.querySelector('#previewPilot2').textContent = team.drivers[1].name;
                this.root.querySelector('#previewPilot2Skill').textContent = `Мастерство: ${team.drivers[1].skill}`;
                const carDiv = this.root.querySelector('#previewCarStats');
                carDiv.innerHTML = '';
                ['Аэродинамика','Двигатель','Шасси','Надёжность'].forEach((label,i) => {
                    const keys = ['aero','engine','chassis','reliability'];
                    const val = team.car[keys[i]];
                    carDiv.innerHTML += `<div style="margin-bottom:6px;"><div style="display:flex;justify-content:space-between;"><span>${label}</span><span>${val}</span></div><div class="progress-bg"><div class="progress-fill" style="width:${val}%;"></div></div></div>`;
                });
                this.root.querySelector('#previewBudget').textContent = team.budget;
                previewDiv.classList.add('active');
            }

            resetStandings() {
                this.state.standings = this.state.teams.map(t => ({ teamName: t.name, points: 0 }));
                this.state.driverStandings = [];
                this.state.teams.forEach(t => t.drivers.forEach(d => this.state.driverStandings.push({ name: d.name, teamName: t.name, points: 0 })));
                this.state.raceHistory = [];
                this.state.qualifyingGrid = [];
            }

            setMode(careerMode, teamIndex = -1) {
                this.state.isSpectator = !careerMode;
                this.state.playerTeamIndex = careerMode ? teamIndex : -1;
                this.state.budget = careerMode ? this.data.teams[teamIndex].budget : 0;
                this.state.points = 0;
                this.state.currentRace = 1;
                this.resetStandings();
                this.root.querySelector('#teamSelectPanel').style.display = 'none';
                this.root.querySelector('#gameUI').style.display = 'block';

                if (careerMode) {
                    this.root.querySelector('#managerPanel').style.display = 'flex';
                    this.root.querySelector('#spectatorPanel').style.display = 'none';
                    this.root.querySelector('#teamNameDisplay').textContent = this.data.teams[teamIndex].constructor;
                    this.root.querySelector('#tabsContainer').innerHTML = `
                        <div class="tab active" data-view="team">👥 Команда</div>
                        <div class="tab" data-view="upgrades">🔧 Разработка</div>
                        <div class="tab" data-view="race">🏁 Гонка</div>
                        <div class="tab" data-view="standings">📊 Команды</div>
                        <div class="tab" data-view="drivers">👤 Пилоты</div>
                        <div class="tab" data-view="history">📋 Гонки</div>
                        <div class="tab" data-view="news">📰 Новости</div>
                    `;
                    this.showView('team');
                } else {
                    this.root.querySelector('#managerPanel').style.display = 'none';
                    this.root.querySelector('#spectatorPanel').style.display = 'flex';
                    this.root.querySelector('#teamView').style.display = 'none';
                    this.root.querySelector('#upgradesView').style.display = 'none';
                    this.root.querySelector('#tabsContainer').innerHTML = `
                        <div class="tab active" data-view="race">🏁 Гонка</div>
                        <div class="tab" data-view="standings">📊 Команды</div>
                        <div class="tab" data-view="drivers">👤 Пилоты</div>
                        <div class="tab" data-view="history">📋 Гонки</div>
                        <div class="tab" data-view="news">📰 Новости</div>
                    `;
                    this.showView('race');
                }
                this.attachTabEvents();
                this.updateUI();
            }

            attachTabEvents() {
                this.root.querySelectorAll('.tab').forEach(tab => {
                    tab.addEventListener('click', () => {
                        this.root.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
                        tab.classList.add('active');
                        this.showView(tab.dataset.view);
                    });
                });
            }

            showView(viewName) {
                const views = this.root.querySelectorAll('.view');
                views.forEach(v => v.classList.remove('active'));
                const target = this.root.querySelector(`#${viewName}View`);
                if (target) {
                    target.classList.add('active');
                    if (viewName === 'history') this.updateHistoryView();
                    if (viewName === 'news') this.generateNews();
                }
            }

            updateUI() {
                const root = this.root;
                root.querySelector('#raceDisplay').textContent = `${this.state.currentRace}/${this.data.totalRaces}`;
                const rd2 = root.querySelector('#raceDisplay2');
                if (rd2) rd2.textContent = `${this.state.currentRace}/${this.data.totalRaces}`;
                if (this.state.currentRace <= this.data.totalRaces) {
                    const gp = this.data.schedule[this.state.currentRace-1];
                    root.querySelector('#grandPrixName').textContent = gp.grandPrix;
                    root.querySelector('#trackName').textContent = gp.track ? `${gp.track} (${gp.location})` : gp.location;
                    root.querySelector('#raceDate').textContent = gp.date || '';
                    root.querySelector('#raceLaps').textContent = gp.laps;
                }
                if (!this.state.isSpectator && this.state.playerTeamIndex !== -1) {
                    const team = this.state.teams[this.state.playerTeamIndex];
                    root.querySelector('#budgetDisplay').textContent = this.state.budget;
                    root.querySelector('#pointsDisplay').textContent = this.state.points;
                    this.renderPilot('pilot1Info', team.drivers[0], 0);
                    this.renderPilot('pilot2Info', team.drivers[1], 1);
                    const carDiv = root.querySelector('#carStats');
                    carDiv.innerHTML = '';
                    ['Аэродинамика','Двигатель','Шасси','Надёжность'].forEach((label,i) => {
                        const keys = ['aero','engine','chassis','reliability'];
                        const val = team.car[keys[i]];
                        carDiv.innerHTML += `<div style="margin-bottom:10px;"><div style="display:flex;justify-content:space-between;"><span>${label}</span><span>${val}</span></div><div class="progress-bg"><div class="progress-fill" style="width:${val}%;"></div></div></div>`;
                    });
                    const upDiv = root.querySelector('#upgradeList');
                    upDiv.innerHTML = '';
                    ['Аэродинамика','Двигатель','Шасси','Надёжность'].forEach((label,i) => {
                        const keys = ['aero','engine','chassis','reliability'];
                        const cur = team.car[keys[i]];
                        const can = this.state.budget >= this.state.upgradeCost && cur < 99;
                        upDiv.innerHTML += `<div class="upgrade-row"><span>${label} <span class="upgrade-stat">${cur}</span> → ${Math.min(cur+7,99)}</span><button class="upgrade-btn" data-key="${keys[i]}" ${can?'':'disabled'}>+7 (8 млн)</button></div>`;
                    });
                }
                const btn = root.querySelector('#startRaceBtn');
                if (this.state.raceInProgress) { btn.disabled = true; btn.textContent = '🏎️ Гонка идёт...'; }
                else if (this.state.currentRace > this.data.totalRaces) { btn.disabled = true; btn.textContent = '🏆 Сезон завершён'; }
                else { btn.disabled = false; btn.textContent = '🚦 Старт уик-энда'; }
                this.renderStandings();
                this.renderDriverStandings();
                if (root.querySelector('#historyView').classList.contains('active')) this.updateHistoryView();
            }

            renderPilot(id, pilot, idx) {
                const el = this.root.querySelector(`#${id}`);
                if (!el) return;
                el.innerHTML = `<div><div class="pilot-name">${pilot.name}</div><div class="pilot-skill">Мастерство: ${pilot.skill}</div></div><button class="hire-btn" data-pilot-index="${idx}" ${this.state.budget<3?'disabled':''}>🔄 Нанять (3 млн)</button>`;
            }

            renderStandings() {
                const sorted = [...this.state.standings].sort((a,b) => b.points - a.points);
                let html = '<table><tr><th>#</th><th>Команда</th><th>Очки</th></tr>';
                sorted.forEach((s,i) => html += `<tr><td>${i+1}</td><td>${s.teamName}</td><td>${s.points}</td></tr>`);
                this.root.querySelector('#standingsTable').innerHTML = html + '</table>';
            }
            renderDriverStandings() {
                const sorted = [...this.state.driverStandings].sort((a,b) => b.points - a.points);
                let html = '<table><tr><th>#</th><th>Пилот</th><th>Команда</th><th>Очки</th></tr>';
                sorted.forEach((d,i) => html += `<tr><td>${i+1}</td><td>${d.name}</td><td>${d.teamName}</td><td>${d.points}</td></tr>`);
                this.root.querySelector('#driversTable').innerHTML = html + '</table>';
            }

            updateHistoryView() {
                const select = this.root.querySelector('#historySelect');
                const tableDiv = this.root.querySelector('#historyTable');
                select.innerHTML = '<option value="">-- Выберите этап --</option>';
                this.state.raceHistory.forEach((race, index) => {
                    const option = document.createElement('option');
                    option.value = index; option.textContent = race.grandPrix;
                    select.appendChild(option);
                });
                if (this.state.raceHistory.length > 0) {
                    select.value = this.state.raceHistory.length - 1;
                    this.showHistoryTable(this.state.raceHistory.length - 1);
                } else {
                    tableDiv.innerHTML = '<p style="color:#8a8f9a;">Нет завершённых гонок.</p>';
                }
            }

            showHistoryTable(index) {
                const tableDiv = this.root.querySelector('#historyTable');
                if (this.state.raceHistory[index]) {
                    const race = this.state.raceHistory[index];
                    let html = `<p style="margin-bottom:8px; font-weight:600;">🏁 ${race.grandPrix}</p>`;
                    html += `<table><tr><th>#</th><th>Пилот</th><th>Команда</th><th>Старт</th><th>Финиш</th></tr>`;
                    race.results.forEach((r, i) => {
                        const start = r.startPosition || '–';
                        const finish = r.dnf ? '💔 DNF' : `P${r.position}`;
                        html += `<tr><td>${i+1}</td><td>${r.name}</td><td>${r.team}</td><td>${start}</td><td>${finish}</td></tr>`;
                    });
                    html += '</table>';
                    tableDiv.innerHTML = html;
                }
            }

            runQualifying() {
                const drivers = [];
                this.state.teams.forEach(team => {
                    team.drivers.forEach(driver => {
                        drivers.push({ name: driver.name, skill: driver.skill, team: team.name, car: team.car });
                    });
                });
                const getPace = d => {
                    const carAvg = (d.car.aero + d.car.engine + d.car.chassis) / 3;
                    return d.skill * 0.65 + carAvg * 0.35;
                };
                const attempt = d => getPace(d) + (Math.random() * 1.2 - 0.6);
                const q1 = drivers.map(d => ({ ...d, time: attempt(d) })).sort((a,b) => b.time - a.time);
                const q1Eliminated = q1.slice(17);
                const q2Participants = q1.slice(0, 17);
                const q2 = q2Participants.map(d => ({ ...d, time: attempt(d) })).sort((a,b) => b.time - a.time);
                const q2Eliminated = q2.slice(11);
                const q3Participants = q2.slice(0, 11);
                const q3 = q3Participants.map(d => ({ ...d, time: attempt(d) })).sort((a,b) => b.time - a.time);
                const grid = [];
                q3.forEach((d, i) => grid.push({ name: d.name, team: d.team, gridPos: i+1 }));
                q2Eliminated.forEach((d, i) => grid.push({ name: d.name, team: d.team, gridPos: 12 + i }));
                q1Eliminated.forEach((d, i) => grid.push({ name: d.name, team: d.team, gridPos: 18 + i }));
                return grid;
            }

            simulateRace() {
                if (this.state.raceInProgress || this.state.currentRace > this.data.totalRaces) return;
                this.state.raceInProgress = true;
                this.updateUI();
                const root = this.root;
                const logEl = root.querySelector('#raceLog');
                const bar = root.querySelector('#raceProgressBar');
                const status = root.querySelector('#raceStatusText');
                root.querySelector('#raceProgress').style.display = 'block';
                logEl.style.display = 'block';
                logEl.innerHTML = '';
                root.querySelector('#raceResult').innerHTML = '';
                bar.style.width = '0%';
                status.textContent = 'Квалификация...';

                const log = msg => {
                    const div = document.createElement('div');
                    div.textContent = '🔹 ' + msg;
                    logEl.appendChild(div);
                    logEl.scrollTop = logEl.scrollHeight;
                };

                const grid = this.runQualifying();
                this.state.qualifyingGrid = grid;
                log('📋 Стартовая решётка:');
                grid.forEach(d => log(`${d.gridPos}. ${d.name} (${d.team})`));

                const allDrivers = grid.map(g => {
                    const team = this.state.teams.find(t => t.name === g.team);
                    const driver = team.drivers.find(d => d.name === g.name);
                    return {
                        name: g.name, skill: driver?.skill || 80,
                        teamName: g.team,
                        teamIdx: this.state.teams.findIndex(t => t.name === g.team),
                        car: team?.car,
                        startPosition: g.gridPos,
                        position: 0, dnf: false
                    };
                });
                allDrivers.forEach(d => d.power = d.skill * 0.55 + (d.car.aero + d.car.engine + d.car.chassis)/3 * 0.45);

                const totalLaps = this.data.schedule[this.state.currentRace-1].laps;
                let lap = 0;
                log(`🚥 ${this.data.schedule[this.state.currentRace-1].grandPrix} стартовал! (${totalLaps} кругов)`);

                const interval = setInterval(() => {
                    lap++;
                    bar.style.width = (lap/totalLaps*100)+'%';
                    status.textContent = `Круг ${lap}/${totalLaps}`;

                    allDrivers.forEach(d => {
                        if (d.dnf) return;
                        if (Math.random() < Math.max(0, (100 - d.car.reliability)/100) * 0.025) {
                            d.dnf = true;
                            log(`💥 ${d.name} (${d.teamName}) сошёл!`);
                        }
                    });

                    const active = allDrivers.filter(d => !d.dnf);
                    active.sort((a,b) => (b.power + Math.random()*10) - (a.power + Math.random()*10));
                    active.forEach((d, idx) => d.position = idx+1);

                    if (lap >= totalLaps) {
                        clearInterval(interval);
                        this.finishRace(allDrivers, log);
                    }
                }, 120);
            }

            finishRace(allDrivers, log) {
                this.state.raceInProgress = false;
                this.root.querySelector('#raceStatusText').textContent = '🏁 Финиш!';

                const raceResultData = allDrivers.map(d => ({
                    name: d.name, team: d.teamName,
                    startPosition: d.startPosition,
                    position: d.position, dnf: d.dnf
                })).sort((a,b) => a.position - b.position);

                this.state.raceHistory.push({
                    grandPrix: this.data.schedule[this.state.currentRace-1].grandPrix,
                    results: raceResultData
                });

                const pointsTable = [25,18,15,12,10,8,6,4,2,1];
                const teamPts = {};
                allDrivers.forEach(d => { if (!d.dnf && d.position <= 10) teamPts[d.teamIdx] = (teamPts[d.teamIdx]||0) + pointsTable[d.position-1]; });
                for (const [idx, pts] of Object.entries(teamPts)) {
                    const i = parseInt(idx);
                    const stand = this.state.standings.find(s => s.teamName === this.state.teams[i].name);
                    if (stand) stand.points += pts;
                    if (!this.state.isSpectator && i === this.state.playerTeamIndex) this.state.points += pts;
                }
                allDrivers.forEach(d => {
                    if (!d.dnf && d.position <= 10) {
                        const entry = this.state.driverStandings.find(ds => ds.name === d.name && ds.teamName === d.teamName);
                        if (entry) entry.points += pointsTable[d.position-1];
                        else this.state.driverStandings.push({ name: d.name, teamName: d.teamName, points: pointsTable[d.position-1] });
                    }
                });

                if (!this.state.isSpectator && this.state.playerTeamIndex !== -1) {
                    const myDrivers = allDrivers.filter(d => d.teamIdx === this.state.playerTeamIndex);
                    let prize = 5; myDrivers.forEach(d => { if (!d.dnf && d.position <= 10) prize += (11 - d.position); });
                    this.state.budget += prize; this.state.budget -= this.state.teams[this.state.playerTeamIndex].drivers.length * 1;
                    log(`💰 Призовые: +${prize} млн | Зарплаты: -${this.state.teams[this.state.playerTeamIndex].drivers.length} млн`);
                }

                this.state.currentRace++;
                this.updateUI();
                this.showStatsModal(this.state.qualifyingGrid, raceResultData);
            }

            showStatsModal(grid, raceResults) {
                const root = this.root;
                root.querySelector('#modalRaceName').textContent = this.data.schedule[this.state.currentRace-2]?.grandPrix || 'Последняя гонка';
                let html = '<h3>📋 Стартовая решётка</h3><table><tr><th>#</th><th>Пилот</th><th>Команда</th></tr>';
                grid.forEach(d => html += `<tr><td>${d.gridPos}</td><td>${d.name}</td><td>${d.team}</td></tr>`);
                html += '</table><br><h3>🏁 Результаты гонки</h3>';
                html += '<table><tr><th>#</th><th>Пилот</th><th>Команда</th><th>Старт</th><th>Финиш</th></tr>';
                raceResults.forEach((r, i) => {
                    const start = r.startPosition || '–';
                    const finish = r.dnf ? '💔 DNF' : `P${r.position}`;
                    html += `<tr><td>${i+1}</td><td>${r.name}</td><td>${r.team}</td><td>${start}</td><td>${finish}</td></tr>`;
                });
                html += '</table>';
                root.querySelector('#modalTable').innerHTML = html;
                root.querySelector('#statsModal').classList.add('active');
            }

            hirePilot(index) {
                if (this.state.raceInProgress || this.state.budget < 3 || this.state.playerTeamIndex === -1 || this.state.isSpectator) return;
                const newDriver = this.data.freeAgents[Math.floor(Math.random()*this.data.freeAgents.length)];
                this.state.budget -= 3;
                const team = this.state.teams[this.state.playerTeamIndex];
                const oldName = team.drivers[index].name;
                this.state.driverStandings = this.state.driverStandings.filter(d => !(d.name === oldName && d.teamName === team.name));
                this.state.driverStandings.push({ name: newDriver.name, teamName: team.name, points: 0 });
                team.drivers[index] = { name: newDriver.name, skill: newDriver.skill };
                this.updateUI();
            }

            applyUpgrade(key) {
                if (this.state.raceInProgress || this.state.budget < this.state.upgradeCost || this.state.playerTeamIndex === -1 || this.state.isSpectator) return;
                const team = this.state.teams[this.state.playerTeamIndex];
                if (team.car[key] >= 99) return;
                this.state.budget -= this.state.upgradeCost;
                team.car[key] = Math.min(99, team.car[key]+7);
                this.updateUI();
            }
        }

        const f1Data = {
            title: '🏎️ F1 MANAGER 2026',
            subtitle: 'Классическая симуляция · Gucci Lamborghini · Календарь 2026',
            totalRaces: 24,
            teams: [
                { name: "BWT Alpine F1 Team", constructor: "Alpine", drivers: [{ name: "Пьер Гасли", skill: 87 }, { name: "Франко Колапинто", skill: 84 }], car: { aero: 80, engine: 78, chassis: 77, reliability: 80 }, budget: 52 },
                { name: "Aston Martin Aramco Honda", constructor: "Aston Martin", drivers: [{ name: "Фернандо Алонсо", skill: 88 }, { name: "Лэнс Стролл", skill: 79 }], car: { aero: 70, engine: 72, chassis: 70, reliability: 72 }, budget: 45 },
                { name: "Audi Revolut F1 Team", constructor: "Audi", drivers: [{ name: "Габриэль Бортолето", skill: 83 }, { name: "Нико Хюлькенберг", skill: 86 }], car: { aero: 72, engine: 70, chassis: 70, reliability: 74 }, budget: 46 },
                { name: "Cadillac Formula 1 Team", constructor: "Cadillac", drivers: [{ name: "Серхио Перес", skill: 84 }, { name: "Валттери Боттас", skill: 86 }], car: { aero: 71, engine: 73, chassis: 70, reliability: 73 }, budget: 44 },
                { name: "Scuderia Ferrari HP", constructor: "Ferrari", drivers: [{ name: "Шарль Леклер", skill: 91 }, { name: "Льюис Хэмилтон", skill: 94 }], car: { aero: 93, engine: 92, chassis: 91, reliability: 88 }, budget: 65 },
                { name: "TGR Haas F1 Team", constructor: "Haas", drivers: [{ name: "Эстебан Окон", skill: 81 }, { name: "Оливер Берман", skill: 79 }], car: { aero: 70, engine: 72, chassis: 68, reliability: 73 }, budget: 42 },
                { name: "McLaren Mastercard Formula 1 Team", constructor: "McLaren", drivers: [{ name: "Ландо Норрис", skill: 92 }, { name: "Оскар Пиастри", skill: 90 }], car: { aero: 91, engine: 90, chassis: 90, reliability: 86 }, budget: 62 },
                { name: "Mercedes-AMG Petronas F1 Team", constructor: "Mercedes", drivers: [{ name: "Джордж Расселл", skill: 93 }, { name: "Кими Антонелли", skill: 90 }], car: { aero: 94, engine: 94, chassis: 93, reliability: 90 }, budget: 68 },
                { name: "Gucci Lamborghini F1 Team", constructor: "Lamborghini", drivers: [{ name: "Лиам Лоусон", skill: 85 }, { name: "Никола Цолов", skill: 81 }], car: { aero: 79, engine: 77, chassis: 76, reliability: 79 }, budget: 50 },
                { name: "Oracle Red Bull Racing", constructor: "Red Bull Racing", drivers: [{ name: "Макс Ферстаппен", skill: 95 }, { name: "Изак Хаджар", skill: 88 }], car: { aero: 90, engine: 91, chassis: 89, reliability: 87 }, budget: 64 },
                { name: "Atlassian Williams F1 Team", constructor: "Williams", drivers: [{ name: "Александр Албон", skill: 82 }, { name: "Карлос Сайнс-мл.", skill: 83 }], car: { aero: 73, engine: 74, chassis: 72, reliability: 75 }, budget: 44 }
            ],
            schedule: [
                { country: "🇦🇺", grandPrix: "Гран-при Австралии", location: "Мельбурн", track: "Альберт-Парк", date: "16 марта", laps: 58 },
                { country: "🇨🇳", grandPrix: "Гран-при Китая", location: "Шанхай", track: "Международный автодром Шанхая", date: "23 марта", laps: 56 },
                { country: "🇯🇵", grandPrix: "Гран-при Японии", location: "Судзука", track: "Судзука", date: "6 апреля", laps: 53 },
                { country: "🇧🇭", grandPrix: "Гран-при Бахрейна", location: "Сахир", track: "Международный автодром Бахрейна", date: "13 апреля", laps: 57 },
                { country: "🇸🇦", grandPrix: "Гран-при Саудовской Аравии", location: "Джидда", track: "Городская трасса Джидда", date: "20 апреля", laps: 50 },
                { country: "🇺🇸", grandPrix: "Гран-при Майами", location: "Майами", track: "Международный автодром Майами", date: "4 мая", laps: 57 },
                { country: "🇮🇹", grandPrix: "Гран-при Эмилии-Романьи", location: "Имола", track: "Автодром Энцо и Дино Феррари", date: "18 мая", laps: 63 },
                { country: "🇲🇨", grandPrix: "Гран-при Монако", location: "Монте-Карло", track: "Городская трасса Монте-Карло", date: "25 мая", laps: 78 },
                { country: "🇪🇸", grandPrix: "Гран-при Испании", location: "Монмело", track: "Барселона-Каталунья", date: "1 июня", laps: 66 },
                { country: "🇨🇦", grandPrix: "Гран-при Канады", location: "Монреаль", track: "Автодром имени Жиля Вильнёва", date: "15 июня", laps: 70 },
                { country: "🇦🇹", grandPrix: "Гран-при Австрии", location: "Шпильберг", track: "Ред Булл Ринг", date: "29 июня", laps: 71 },
                { country: "🇬🇧", grandPrix: "Гран-при Великобритании", location: "Силверстон", track: "Сильверстоун", date: "6 июля", laps: 52 },
                { country: "🇧🇪", grandPrix: "Гран-при Бельгии", location: "Спа", track: "Спа-Франкоршам", date: "27 июля", laps: 44 },
                { country: "🇭🇺", grandPrix: "Гран-при Венгрии", location: "Будапешт", track: "Хунгароринг", date: "3 августа", laps: 70 },
                { country: "🇳🇱", grandPrix: "Гран-при Нидерландов", location: "Зандворт", track: "Зандворт", date: "31 августа", laps: 72 },
                { country: "🇮🇹", grandPrix: "Гран-при Италии", location: "Монца", track: "Монца", date: "7 сентября", laps: 53 },
                { country: "🇦🇿", grandPrix: "Гран-при Азербайджана", location: "Баку", track: "Городская трасса Баку", date: "21 сентября", laps: 51 },
                { country: "🇸🇬", grandPrix: "Гран-при Сингапура", location: "Сингапур", track: "Марина-Бей", date: "5 октября", laps: 62 },
                { country: "🇺🇸", grandPrix: "Гран-при США", location: "Остин", track: "Трасса Америк", date: "19 октября", laps: 56 },
                { country: "🇲🇽", grandPrix: "Гран-при Мехико", location: "Мехико", track: "Автодром имени братьев Родригес", date: "26 октября", laps: 71 },
                { country: "🇧🇷", grandPrix: "Гран-при Сан-Паулу", location: "Сан-Паулу", track: "Интерлагос", date: "9 ноября", laps: 71 },
                { country: "🇺🇸", grandPrix: "Гран-при Лас-Вегаса", location: "Лас-Вегас", track: "Городская трасса Лас-Вегас", date: "22 ноября", laps: 50 },
                { country: "🇶🇦", grandPrix: "Гран-при Катара", location: "Лусаил", track: "Международный автодром Лусаил", date: "30 ноября", laps: 57 },
                { country: "🇦🇪", grandPrix: "Гран-при Абу-Даби", location: "Абу-Даби", track: "Яс Марина", date: "7 декабря", laps: 58 }
            ],
            freeAgents: [
                { name: "Даниэль Риккардо", skill: 80 }, { name: "Мик Шумахер", skill: 77 },
                { name: "Роберт Шварцман", skill: 76 }, { name: "Тео Пуршер", skill: 75 }, { name: "Джек Дуэн", skill: 74 }
            ]
        };

        const feData = {
            title: '⚡ FORMULA E MANAGER 2025/26',
            subtitle: 'Синие тона · Реальные команды и пилоты · 16 этапов',
            totalRaces: 16,
            teams: [
                { name: "Jaguar TCS Racing", constructor: "Jaguar", drivers: [{ name: "Митч Эванс", skill: 95 }, { name: "Антониу Феликс да Кошта", skill: 92 }], car: { aero: 90, engine: 92, chassis: 91, reliability: 88 }, budget: 58 },
                { name: "Porsche Formula E Team", constructor: "Porsche", drivers: [{ name: "Паскаль Верляйн", skill: 96 }, { name: "Нико Мюллер", skill: 90 }], car: { aero: 91, engine: 93, chassis: 92, reliability: 87 }, budget: 60 },
                { name: "Mahindra Racing", constructor: "Mahindra", drivers: [{ name: "Эдоардо Мортара", skill: 89 }, { name: "Ник де Врис", skill: 90 }], car: { aero: 88, engine: 87, chassis: 89, reliability: 86 }, budget: 55 },
                { name: "Andretti Formula E", constructor: "Andretti", drivers: [{ name: "Джейк Деннис", skill: 91 }, { name: "Фелипе Другович", skill: 89 }], car: { aero: 89, engine: 88, chassis: 88, reliability: 85 }, budget: 56 },
                { name: "Nissan Formula E Team", constructor: "Nissan", drivers: [{ name: "Оливер Роуленд", skill: 92 }, { name: "Норман Нато", skill: 78 }], car: { aero: 87, engine: 89, chassis: 86, reliability: 84 }, budget: 54 },
                { name: "Envision Racing", constructor: "Envision", drivers: [{ name: "Себастьен Буэми", skill: 86 }, { name: "Джоэль Эрикссон", skill: 82 }], car: { aero: 82, engine: 83, chassis: 81, reliability: 82 }, budget: 50 },
                { name: "Citroën Racing", constructor: "Citroën", drivers: [{ name: "Ник Кэссиди", skill: 84 }, { name: "Жан-Эрик Вернь", skill: 84 }], car: { aero: 84, engine: 85, chassis: 84, reliability: 83 }, budget: 52 },
                { name: "Cupra Kiro", constructor: "Cupra Kiro", drivers: [{ name: "Хосеп-Мария Марти", skill: 83 }, { name: "Дэн Тиктум", skill: 75 }], car: { aero: 79, engine: 80, chassis: 78, reliability: 79 }, budget: 48 },
                { name: "DS Penske", constructor: "DS Penske", drivers: [{ name: "Тейлор Барнард", skill: 75 }, { name: "Максимилиан Гюнтер", skill: 75 }], car: { aero: 75, engine: 76, chassis: 74, reliability: 77 }, budget: 46 },
                { name: "Lola Yamaha ABT Formula E Team", constructor: "Lola Yamaha ABT", drivers: [{ name: "Лукас ди Грасси", skill: 78 }, { name: "Зейн Мэлони", skill: 72 }], car: { aero: 74, engine: 78, chassis: 73, reliability: 76 }, budget: 45 }
            ],
            schedule: [
                { country: "🇲🇽", grandPrix: "Mexico City E-Prix", location: "Мехико", laps: 36 },
                { country: "🇸🇦", grandPrix: "Diriyah E-Prix", location: "Джидда", laps: 37 },
                { country: "🇧🇷", grandPrix: "São Paulo E-Prix", location: "Сан-Паулу", laps: 34 },
                { country: "🇩🇪", grandPrix: "Berlin E-Prix", location: "Берлин", laps: 40 },
                { country: "🇲🇨", grandPrix: "Monaco E-Prix", location: "Монте-Карло", laps: 29 },
                { country: "🇨🇳", grandPrix: "Shanghai E-Prix", location: "Шанхай", laps: 32 },
                { country: "🇮🇹", grandPrix: "Rome E-Prix", location: "Рим", laps: 27 },
                { country: "🇬🇧", grandPrix: "London E-Prix", location: "Лондон", laps: 35 },
                { country: "🇺🇸", grandPrix: "New York E-Prix", location: "Нью-Йорк", laps: 38 },
                { country: "🇫🇷", grandPrix: "Paris E-Prix", location: "Париж", laps: 31 },
                { country: "🇰🇷", grandPrix: "Seoul E-Prix", location: "Сеул", laps: 33 },
                { country: "🇮🇩", grandPrix: "Jakarta E-Prix", location: "Джакарта", laps: 30 },
                { country: "🇿🇦", grandPrix: "Cape Town E-Prix", location: "Кейптаун", laps: 32 },
                { country: "🇦🇷", grandPrix: "Buenos Aires E-Prix", location: "Буэнос-Айрес", laps: 34 },
                { country: "🇯🇵", grandPrix: "Tokyo E-Prix", location: "Токио", laps: 35 },
                { country: "🇦🇺", grandPrix: "Sydney E-Prix", location: "Сидней", laps: 33 }
            ],
            freeAgents: [
                { name: "Стоффель Вандорн", skill: 82 }, { name: "Робин Фряйнс", skill: 79 },
                { name: "Андре Лоттерер", skill: 77 }
            ]
        };

        let f1Game, feGame;
        document.getElementById('playF1Btn').addEventListener('click', () => {
            document.getElementById('mainMenu').style.display = 'none';
            document.getElementById('f1Container').classList.add('active');
            if (!f1Game) f1Game = new RacingGame('f1Root', 'f1', f1Data);
        });
        document.getElementById('playFEBtn').addEventListener('click', () => {
            document.getElementById('mainMenu').style.display = 'none';
            document.getElementById('feContainer').classList.add('active');
            if (!feGame) feGame = new RacingGame('feRoot', 'fe', feData);
        });
        document.getElementById('backFromF1').addEventListener('click', hideAllGames);
        document.getElementById('backFromFE').addEventListener('click', hideAllGames);
    })();
</script>
</body>
</html>

Инструкция по открытию игры:

  • Игра доступна лишь на ПеКарне. Так что тем у кого нет ПК, могу сказать только Press F
  • Напишите любому из ИИ этот код и напишите по типу такого:
Я СОЗДАЛ СВОЮ ИГРУ | by Mentos
  • Небольшой совет. Если у вас есть ПК, но не имеете сейчас к нему доступа, дождитесь его. Потому что, если вы, будете копировать код с телефона, то вам придется это делать частями и согласитесь: это довольно не удобно. 
  • ИИ перепишет этот код и автоматически у вас появится кнопочка ОТКРЫТЬ или СКАЧАТЬ(желательно скачать, для удобства, много она не весит - всего 55,7 КБ(!) )
  • Играть!

Также я жду фидбека по поводу самой игры и возможным предложениям по самой игре. Буду рад услышать.

Десяток скриншотов по самой игре: 

Я СОЗДАЛ СВОЮ ИГРУ | by Mentos Я СОЗДАЛ СВОЮ ИГРУ | by Mentos Я СОЗДАЛ СВОЮ ИГРУ | by Mentos Я СОЗДАЛ СВОЮ ИГРУ | by Mentos Я СОЗДАЛ СВОЮ ИГРУ | by Mentos Я СОЗДАЛ СВОЮ ИГРУ | by Mentos Я СОЗДАЛ СВОЮ ИГРУ | by Mentos Я СОЗДАЛ СВОЮ ИГРУ | by Mentos Я СОЗДАЛ СВОЮ ИГРУ | by Mentos

Ţĥē Éŋđ

Теги: Видео-игрыАвто-спорт играMentos
0
15
15
17комментариев188просмотров

-Блог-

Грибник

Возобновление Игры

Возобновление Игры

Прошло приличное количества времени с момента заморозки стратегической игры и перед фактическим началом я бы хотел сделать парочку релизов, задать пару вопросов и освежить память для себя и игроков (некоторые из-них несколько раз забывали за кого они играют)

1. Игроки:
ССРВ (Вландия) - Mofistus 
США (Арказия) -  13th Raven  Gendarme
Деерская Республика - аболтус
Тропико - Селектронски 
Дальноруссия - Не Топлес
Отмечаю вас, чтобы напомнить и заодно уточню (напишите в лс или в коментариях) хотите ли вы продолжить игру? 
Если вы хотите отказаться, то можете это сделать и я заменю вас другим игроком (Если же те, кто следит за игрой, желают быть своего рода в "резерве" - вы сможете получить роль или занять место отказавшегося

2. Платформа:
Хотел уточнить у игроков, где проводить игру. Telegram был бы удобнее и практичнее для ведения игры, однако данный вопрос оставлю на усмотрение участников, я лишь высказал рекомендации.

3. Механики
Вероятно многие забыли основные концепции и механики игры вы можете освежить память здесь:

Что же касается новых механик и определенной переработки стратегии то вот, что было сделано за прошедшее время:
1. Была изменена и отредактирована глобальная карта, где были добавлены ранее не вписанные в лор страны.

2. Переработка системы решений. Теперь помимо прежний концепции "Событие - Варианты действий" Будут те событии, где игрок сможет определенно импровизировать, а не полагаться на заранее подготовленные ответы.

3. "Энциклопедия" и расширенная статистика. Сам я планировал создание более творческой и свободной стратегии, где игроки помимо строгих игровых механик могут уточнить у меня информацию, запросить отчет о состоянии дел в конкретных отраслях и данные о других странах. Теперь ивенты у вас могут быть выделены* некоторые термины и слова, о которых вы можете узнать больше, также участник может запросить у меня информацию о "любой" интересующей его теме в рамках игрового процесса.  

Обновленная карта

Обновленная карта

ИТОГИ
Формально игра началась, но пока я жду ответа участников о их готовности и желании продолжить (в противном случаи будет проведена скорейшей замене отказавшихся)  В скорейшем времени всех участникам будет отправлены сообщения о прошедших событиях и принятых решений, а таже бланк глобальных целей и задач на игру.

Возобновление Игры

Где продолжаем игру?13

Теги: СобытияГосударстваСтратегии игра
2
9
11
13комментариев162просмотра

Из кулис творца

marpik

Что мы нарисовали в ГартикФон
Этот парень родился спортсменом

Этот парень родился спортсменом

Жиртресса

Жиртресса

Русалка уже не та

Русалка уже не та

НеТопицца

НеТопицца

МужЖен герой молний

МужЖен герой молний

Мистер и миссис смит (д)

Мистер и миссис смит (д)

Крош с жирафом внизу

Крош с жирафом внизу

Под конец крыша слетела у всех

Под конец крыша слетела у всех

Из других режимов не выйдет, я сохраняла как гифки( тут такое хрен добавишь

Следующая игра

Мы можем играть еще (от 4ех человек до 10 человек)!

Кто угодно может присоединиться и играть вместе с нами. Теперь мы можем выбрать день и время (первоначально суббота в 20:00 по МСК)
Мы созвонимся теперь не в зум, а в гуглмит 

ТАКЖЕ
Мы можем собираться играть в разные игры или даже смотреть фильмы, сериалы и обсуждать после просмотра (можно выбрать время пораньше, чтоб до ночи не сидеть)

Пишите, что бы вы хотели в первую очередь. И что по времени и субботе?

Теги: Digital-АртPikucoГартикфон игра
2
18
20
17комментариев232просмотра

Из кулис творца

marpik

Созыв в ГартикФон 6.06.26 в 20:00 по МСК!!!

ГартикФон 6.06.26 в 20:00 по МСК!

Созыв в ГартикФон 6.06.26 в 20:00 по МСК!!!

Можно и групповой созвон устроить! Го играть и веселиться вместе в рисовательно-писательную игру!

Чтобы участвовать - напиши в комментах "участвую". Ссылки пришлю в лс, скорее всего, за мин10  

Сама игра
МАКСИМУМ 10 ЧЕЛОВЕК. 

Созвон можно устроить в гуглмит, зуме или дискорде?

Пойдешь?9

Теги: Pikuco играГартикфон
0
14
14
14комментариев147просмотров

Modèn Enfòmasyon Gazette

Владимир ✞

Роблокс заблокировали... и Слава Богу!

1. Игровая экономика Роблокса построена так, что ребёнку нажать «купить» проще, чем родителю объяснить, зачем это надо. Виртуальная валюта Robux, скины и «коробочки-сюрпризы» стимулируют импульсивные покупки — у детей нет экономического понимания расходов, но есть доступная кнопка. 

Роблокс заблокировали... и Слава Богу!

Это не просто трата денег — исследователи и журналисты сравнивают с практиками, которые учат детей тратить без осознания.

2. Большая часть контента создаётся игроками/разработчиками. Чтобы всё отфильтровать — нужна армия модераторов и умные алгоритмы. На практике автоматические фильтры ошибаются: либо пропускают опасное (педофильский контент, сцены насилия). 

Роблокс заблокировали... и Слава Богу!

Итог — дети могут наткнуться на неприемлемое, а создатели — потерять аккаунты без понятного объяснения.

3. Роблокс оказался в поле зрения властей и юристов: есть иски о сборе данных детей без согласия родителей, иски по вопросам безопасности и даже правовые претензии от штатов. Когда платформа, ориентированная на детей, регулярно попадает в юридические сводки — это знак, что что-то системно не работает.

Роблокс заблокировали... и Слава Богу!

 4. Внутренняя социальная среда игровых пространств — как в любой большой сети: от буллинга до мошенничества (аккаунты, перепродажа, подставные конкурсы). Для детей это особенно рискованно: доверчивость + доступность чата/встреч = уязвимость к манипуляциям и мошенникам. 

Роблокс заблокировали... и Слава Богу!

Журналисты и исследователи неоднократно фиксировали такие случаи и описывали «тревожный разрыв» между веселым фасадом платформы и реальным опытом детей. 

Собираемая игровыми платформами аналитика — это важно для бизнеса, но опасно для детей. Против Роблокса поданы иски, где говорится о скрытом отслеживании и коммерческом использовании детских данных без прозрачного согласия родителей. Это не «теория заговоров», а юридические претензии, которые требуют ответа.

Вывод: Играйте в шашки ру и будет вам счастье.

Рады блокировке роблокс? 10

Теги: Видео-игрыЗаконодательствоРоблокс игра
7
13
20
11комментариев138просмотров
Загрузка...