import { Application, Assets, Sprite, NineSliceSprite, Container, TilingSprite, Text, wordWrap } from 'pixi.js'; async function initGame() { const app = new Application(); await app.init({ resizeTo: window, backgroundAlpha: 0, antialias: true, resolution: window.devicePixelRatio || 1, autoDensity: true, }); document.getElementById('pixi-container').appendChild(app.canvas); try { const assetsToLoad = { //background: 'src/raw-assets/backgrounds/SPR_SciFiMenus_Example_Image_SpookyComputer_01.png', background: 'src/raw-assets/backgrounds/SPR_SciFiMenus_Example_Image_SpaceStation_01.png', uiAtlas: 'src/assets/ui-atlas.json' }; const backgroundTexture = await Assets.load(assetsToLoad.background); const uiSpritesheet = await Assets.load(assetsToLoad.uiAtlas); await document.fonts.load('16px "UI Font"'); await document.fonts.load('16px "Logo Font"'); buildScene(app, backgroundTexture, uiSpritesheet); } catch (error) { console.error("Fehler beim Laden der Assets:", error); } } function buildScene(app, bgTexture, sheet) { // --- Farb-Variablen (pixiJS) --- const COLOR_PANEL_BG = 0x0b192c; // Dunkelblau für Panel & Inputs const COLOR_PATTERN = 0x00f0ff; // Cyan für das Hexagon-Muster const COLOR_TAB_ACTIVE = 0x00f0ff; // Cyan für aktiven Tab const COLOR_TAB_INACTIVE = 0xaaaaaa; // Grau für inaktiven Tab const COLOR_TAB_HOVER = 0xffffff; // Weiß beim Hovern der Tabs const COLOR_BTN_DEFAULT = 0x00aa00; // Dunkelgrün für Registrieren Button const COLOR_BTN_HOVER = 0x00ff00; // Hellgrün beim Hovern des Buttons const COLOR_LOGO = 0x00f0ff; // Farbe des Logos const COLOR_DISCORD_TEXT = 0xdaffde; // Hellgrün für Discord Text const COLOR_DISCORD_TEXT_HOVER = 0xffffff; // Weiß beim Hovern des Discord Links // --- Asset-Namen --- const frameInput = 'SPR_SciFiMenus_Menu_Item_Selected_19'; // Rahmen für Eingabefelder const frameBtn = 'SPR_SciFiMenus_Menu_Item_Selected_10'; // Rahmen für Tabs/Buttons const menuBgName = 'SPR_SciFiMenus_Menu_Item_Background_07'; // Füll Asset für die Rahmen const panelBgName = 'SPR_SciFiMenus_Frame_Box_Large_02_Background'; // Füll Asset für das große Panel const patternBgName = 'SPR_SciFiMenus_Background_Hexagons_01'; // Kachelbares Pattern const panelFmName = 'SPR_SciFiMenus_Frame_Box_Large_02'; // Rahmen für das große Panel // --- Icons --- const iconUserName = 'ICON_SciFiMenus_Menu_Solo_01_Clean'; const iconEmailName = 'ICON_SciFi_Map_Message'; const iconLockName = 'ICON_SciFiMenus_Menu_Lock_Closed_01_Clean'; // --- Logo Ring --- const logoRingName = 'SPR_SciFiMenus_Ring_Medium_13'; // --- Discord Panel --- const discordFrameName = 'SPR_SciFiMenus_Frame_Box_Large_12'; const discordBgName = 'SPR_SciFiMenus_Frame_Box_Large_12_Background'; const discordIconName = 'ICON_Social_Discord'; // --- Hintergrund --- const background = new Sprite(bgTexture); app.stage.addChild(background); // --- Haupt-UI-Container --- const uiContainer = new Container(); app.stage.addChild(uiContainer); const panelBackground = new Sprite(sheet.textures[panelBgName]); panelBackground.tint = COLOR_PANEL_BG; panelBackground.width = 500; panelBackground.height = 520; panelBackground.position.set(0, -10); uiContainer.addChild(panelBackground); // --- Footer Hintergund in PixiJS kacheln const footerBackgroundContainer = new Container(); const footerBackground = new TilingSprite({ texture: sheet.textures['SPR_SciFiMenus_Background_01'], height: 40, }); footerBackground.tileScale.set(1.0); footerBackground.tint = 0x000000; footerBackground.alpha = 1.0; footerBackgroundContainer.addChild(footerBackground); app.stage.addChild(footerBackgroundContainer); const footerPattern = new TilingSprite({ texture: sheet.textures[patternBgName], height: 40, }); footerPattern.tileScale.set(0.3); footerPattern.tint = COLOR_PATTERN; footerPattern.alpha = 0.01; footerBackgroundContainer.addChild(footerPattern); app.stage.addChild(footerBackgroundContainer); // --- Hexagon pattern const pattern = new TilingSprite({ texture: sheet.textures[patternBgName], width: 500, height: 520, }); pattern.tileScale.set(0.3); pattern.position.set(0, -10); pattern.alpha = 0.05; pattern.tint = COLOR_PATTERN; uiContainer.addChild(pattern); // --- Main UI const panelFrame = new NineSliceSprite({ texture: sheet.textures[panelFmName], leftWidth: 510, topHeight: 510, rightWidth: 510, bottomHeight: 510 }); panelFrame.width = 500; panelFrame.height = 500; uiContainer.addChild(panelFrame); // --- Logo --- const logoContainer = new Container(); logoContainer.position.set(250, -120); const logoRing = new Sprite(sheet.textures[logoRingName]); logoRing.anchor.set(0.5); logoRing.tint = COLOR_LOGO; logoRing.alpha = 1.0; logoRing.scale.set(0.2); logoContainer.addChild(logoRing); const logoText = new Text({ text: 'Void-Genesis', style: { fontFamily: 'Logo Font', fontSize: 50, fill: COLOR_LOGO, letterSpacing: 8, } }); logoText.anchor.set(0.5); logoContainer.addChild(logoText); uiContainer.addChild(logoContainer); // --- UI Elemente --- const tabLogin = createUIItem(65, 60, 180, 40, frameBtn, null, COLOR_TAB_INACTIVE, 0.6); const tabRegister = createUIItem(255, 60, 180, 40, frameBtn, null, COLOR_TAB_ACTIVE, 0.4); const inputUser = createUIItem(115, 135, 300, 50, frameInput, iconUserName, COLOR_PANEL_BG, 0.8); const inputEmail = createUIItem(115, 200, 300, 50, frameInput, iconEmailName, COLOR_PANEL_BG, 0.8); const inputLock = createUIItem(115, 265, 300, 50, frameInput, iconLockName, COLOR_PANEL_BG, 0.8); const btnRegister = createUIItem(65, 370, 370, 55, frameBtn, null, COLOR_BTN_DEFAULT, 0.6); // --- Discord Panel --- const discordContainer = new Container(); discordContainer.position.set(640, 380); const discordBackground = new NineSliceSprite({ texture: sheet.textures[discordBgName], leftWidth: 0, topHeight: 0, rightWidth: 0, bottomHeight: 0 }); discordBackground.tint = COLOR_PANEL_BG; discordBackground.width = 255; discordBackground.height = 75; discordContainer.addChild(discordBackground); const discordPattern = new TilingSprite({ texture: sheet.textures[patternBgName], width: 255, height: 75, }); discordPattern.tileScale.set(0.3); discordPattern.tint = COLOR_PATTERN; discordPattern.alpha = 0.05; discordContainer.addChild(discordPattern); const discordFrame = new NineSliceSprite({ texture: sheet.textures[discordFrameName], leftWidth: 0, topHeight: 0, rightWidth: 0, bottomHeight: 0 }); discordFrame.width = 280; discordFrame.height = 85; discordFrame.position.set(-15, -10); discordContainer.addChild(discordFrame); const discordIcon = new Sprite(sheet.textures[discordIconName]); discordIcon.position.set(10, 15); discordIcon.scale.set(0.15); discordIcon.tint = COLOR_TAB_INACTIVE; discordContainer.addChild(discordIcon); const discordText = new Text({ text: 'Offizieller Discord Server', style: { fontFamily: 'UI Font', fontSize: 14, fill: COLOR_TAB_INACTIVE, wordWrap: false, wordWrapWidth: 120 } }); discordText.position.set(60, 25); discordContainer.addChild(discordText); uiContainer.addChild(discordContainer); const htmlTabLogin = document.getElementById('tab-login'); const htmlTabRegistert = document.getElementById('tab-register'); const htmlButton = document.getElementById('btn-register'); let isLoginMode = false; htmlTabLogin.addEventListener('mouseenter', () => { if (!isLoginMode) { tabLogin.fill.tint = COLOR_TAB_HOVER; tabLogin.fill.alpha = 0.8; } }); htmlTabLogin.addEventListener('mouseleave', () => { if (!isLoginMode) { tabLogin.fill.tint = COLOR_TAB_INACTIVE; tabLogin.fill.alpha = 0.4; } }); htmlTabRegistert.addEventListener('mouseenter', () => { if (isLoginMode) { tabRegister.fill.tint = COLOR_TAB_HOVER; tabRegister.fill.alpha = 0.8; } }); htmlTabRegistert.addEventListener('mouseleave', () => { if (isLoginMode) { tabRegister.fill.tint = COLOR_TAB_INACTIVE; tabRegister.fill.alpha = 0.4; } }); htmlButton.addEventListener('mouseenter', () => { btnRegister.fill.tint = COLOR_BTN_HOVER; btnRegister.fill.alpha = 1.0; }); htmlButton.addEventListener('mouseleave', () => { btnRegister.fill.tint = COLOR_BTN_DEFAULT; btnRegister.fill.alpha = 0.6; }); const htmlDiscord = document.getElementById('discord-link'); if (htmlDiscord) { htmlDiscord.addEventListener('mouseenter', () => { discordIcon.tint = COLOR_TAB_HOVER; discordText.style.fill = COLOR_TAB_HOVER; }); htmlDiscord.addEventListener('mouseleave', () => { discordIcon.tint = COLOR_TAB_INACTIVE; discordText.style.fill = COLOR_TAB_INACTIVE; }); } function setLoginMode() { if (isLoginMode) return; isLoginMode = true; tabLogin.fill.tint = COLOR_TAB_ACTIVE; tabLogin.fill.alpha = 0.6; tabRegister.fill.tint = COLOR_TAB_INACTIVE; tabRegister.fill.alpha = 0.4; htmlTabLogin.classList.add('active'); htmlTabRegistert.classList.remove('active'); inputEmail.container.visible = false; document.getElementById('group-email').style.display = 'none'; inputLock.container.y = 200; document.getElementById('password').style.top = '200px'; document.getElementById('group-remember').style.display = 'flex'; htmlButton.textContent = 'LOGIN'; document.getElementById('username').placeholder = 'Username / E-Mail'; document.getElementById('msg-box').textContent = ''; } function setRegisterMode() { if (!isLoginMode) return; isLoginMode = false; tabRegister.fill.tint = COLOR_TAB_ACTIVE; tabRegister.fill.alpha = 0.6; tabLogin.fill.tint = COLOR_TAB_INACTIVE; tabLogin.fill.alpha = 0.4; htmlTabRegistert.classList.add('active'); htmlTabLogin.classList.remove('active'); inputEmail.container.visible = true; document.getElementById('group-email').style.display = 'block'; inputLock.container.y = 265; document.getElementById('password').style.top = '265px'; document.getElementById('group-remember').style.display = 'none'; htmlButton.textContent = 'REGISTRIEREN'; document.getElementById('username').placeholder = 'Enter Username'; document.getElementById('msg-box').textContent = ''; } function createUIItem(x, y, width, height, frameTextureName, iconTextureName, fillTint, fillAlpha) { const itemContainer = new Container(); itemContainer.position.set(x, y); const fill = new NineSliceSprite({ texture: sheet.textures[menuBgName], leftWidth: 120, topHeight: 120, rightWidth: 120, bottomHeight: 120 }); fill.width = width; fill.height = height; fill.tint = fillTint; fill.alpha = fillAlpha; itemContainer.addChild(fill); const frame = new NineSliceSprite({ texture: sheet.textures[frameTextureName], leftWidth: 100, topHeight: 120, rightWidth: 140, bottomHeight: 120 }); frame.width = width; frame.height = height; frame.alpha = 0.8; itemContainer.addChild(frame); if (iconTextureName) { const icon = new Sprite(sheet.textures[iconTextureName]); icon.position.set(-45, (height - (icon.height * 0.15)) / 2 - 5); icon.scale.set(0.15); itemContainer.addChild(icon); } uiContainer.addChild(itemContainer); return { container: itemContainer, fill, frame }; } function resize() { const screenWidth = app.screen.width; const screenHeight = app.screen.height; const scaleX = screenWidth / background.texture.width; const scaleY = screenHeight / background.texture.height; const scale = Math.max(scaleX, scaleY); background.scale.set(scale); background.x = (screenWidth - background.width) / 2; background.y = (screenHeight - background.height) / 2; uiContainer.x = (screenWidth - panelFrame.width) / 2; uiContainer.y = (screenHeight - panelFrame.height) / 2; footerBackground.width = screenWidth; footerPattern.width = screenWidth; footerBackgroundContainer.y = screenHeight - 40; } htmlTabLogin.addEventListener('click', setLoginMode); htmlTabRegistert.addEventListener('click', setRegisterMode); app.renderer.on('resize', resize); resize(); } initGame();