User prompt
Please fix the bug: 'Cannot convert undefined or null to object' in or related to this line: 'var characterKeys = Object.keys(characters);' Line Number: 602
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'undefined')' in or related to this line: 'var game = new LK.Game({' Line Number: 329
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'undefined')' in or related to this line: 'var game = new LK.Game({' Line Number: 329
User prompt
Generate the first version of the source code of my game: Elite Arena Survivors.
User prompt
Elite Arena Survivors
Initial prompt
import React, { useRef, useEffect, useState } from 'react'; import ReactDOM from 'react-dom/client'; import * as THREE from 'three'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; const Game = () => { const mountRef = useRef(null); const [enemies, setEnemies] = useState([]); const [gameStarted, setGameStarted] = useState(false); const [selectedCharacter, setSelectedCharacter] = useState(null); const [isMultiplayer, setIsMultiplayer] = useState(false); const [bulletCooldown, setBulletCooldown] = useState(0); const [canShoot, setCanShoot] = useState(true); const [playerId, setPlayerId] = useState(null); const [otherPlayers, setOtherPlayers] = useState({}); const [autoAimEnabled, setAutoAimEnabled] = useState(true); const [shieldActive, setShieldActive] = useState(false); const [shieldHealth, setShieldHealth] = useState(100); const [showSettings, setShowSettings] = useState(false); const [showCharacterInfo, setShowCharacterInfo] = useState(false); const [groundColor, setGroundColor] = useState(0x2d572c); const [level, setLevel] = useState(1); const characters = { normal: { name: "Normal", description: "Balanced character with standard abilities", color: 0x0055ff, bulletSpeed: 1.0, bulletDamage: 10, bulletColor: 0xffff00 }, laserMaster: { name: "Laser Master", description: "Devastating laser specialist with enhanced beam", color: 0xff00ff, bulletSpeed: 0.8, bulletDamage: 5, bulletColor: 0xff00ff, laserDamage: 100, laserWidth: 0.5, laserColor: 0xff00ff, laserRange: 50, superLaser: true }, ranged: { name: "Ranged", description: "Long-range specialist with tracking bullets", color: 0xff5500, bulletSpeed: 1.2, bulletDamage: 8, trackingBullets: true, bulletColor: 0xff5500 }, close: { name: "Close Combat", description: "Short-range specialist with high damage", color: 0x00ff55, bulletSpeed: 0.8, bulletDamage: 15, spreadShot: true, bulletColor: 0x00ff55 }, sniper: { name: "Sniper", description: "Slow but powerful long-range shots", color: 0x9900ff, bulletSpeed: 2.0, bulletDamage: 25, bulletColor: 0x9900ff, piercing: true, chargeShot: true }, explosive: { name: "Explosive", description: "Area damage specialist with explosive rounds", color: 0xff0000, bulletSpeed: 0.7, bulletDamage: 12, bulletColor: 0xff0000, explosiveShot: true, explosionRadius: 3 }, rapid: { name: "Rapid Fire", description: "Fast-firing character with bouncing bullets", color: 0x00ffff, bulletSpeed: 1.5, bulletDamage: 5, bulletColor: 0x00ffff, rapidFire: true, bouncingBullets: true, maxBounces: 3 }, shocktank: { name: "Shock Tank", description: "Yakın mesafede güçlü, yüksek canlı ve şok etkili saldırılar yapan tank", color: 0x4169e1, // Royal Blue bulletSpeed: 0.7, bulletDamage: 25, bulletColor: 0x4682b4, health: 150, armor: 50, closeRangeBonus: true, shockwave: true, shockDamage: 15, shockRadius: 4, shockStunDuration: 2000, tankAura: true, auraRadius: 3 }, shadow: { name: "Shadow Warrior", description: "Görünmezlik ve zehir yeteneklerine sahip ninja", color: 0x4a0080, bulletSpeed: 1.6, bulletDamage: 15, bulletColor: 0x800080, invisibility: true, poisonShot: true, poisonDamage: 5, poisonDuration: 5000, shadowClone: true, maxClones: 3, cloneDuration: 8000 }, tempest: { name: "Tempest Mage", description: "Elementler üzerinde kontrol sahibi büyücü", color: 0x00e5ff, bulletSpeed: 1.4, bulletDamage: 18, bulletColor: 0x00ffff, elementalPowers: true, chainLightning: true, lightningDamage: 12, frostBolt: true, freezeDuration: 3000, tornadoSpell: true, tornadoDuration: 5000 }, ultimate: { name: "Ultimate", description: "Tüm güçlere sahip efsanevi karakter", color: 0xffd700, // Altın rengi bulletSpeed: 1.8, bulletDamage: 20, bulletColor: 0xffd700, // Tüm özellikleri aktif trackingBullets: true, spreadShot: true, piercing: true, explosiveShot: true, rapidFire: true, bouncingBullets: true, maxBounces: 5, laserDamage: 150, laserWidth: 0.8, laserColor: 0xffd700, laserRange: 60, superLaser: true, // Özel ultimate özellikleri multiShot: true, shieldEnabled: true, ultimateRage: true }, // New characters with special abilities timemaster: { name: "Time Master", description: "Zamanı manipüle edebilen güçlü bir karakter", color: 0x00ffcc, bulletSpeed: 1.2, bulletDamage: 15, bulletColor: 0x00ffcc, timeControl: true, slowDuration: 5000, slowFactor: 0.5, timeRewind: true, rewindDuration: 3000 }, teleporter: { name: "Teleporter", description: "Kısa mesafe ışınlanma yeteneğine sahip çevik karakter", color: 0xff00ff, bulletSpeed: 1.3, bulletDamage: 12, bulletColor: 0xff00ff, teleport: true, teleportRange: 10, teleportCooldown: 3000, afterImage: true }, dimensional: { name: "Dimensional Shifter", description: "Boyutlar arası geçiş yapabilen esrarengiz savaşçı", color: 0x9932cc, bulletSpeed: 1.1, bulletDamage: 14, bulletColor: 0x9932cc, dimensionShift: true, shiftDuration: 4000, alternateFireEnabled: true }, graviton: { name: "Graviton Controller", description: "Yerçekimini kontrol edebilen güçlü manipülatör", color: 0x4169e1, bulletSpeed: 0.9, bulletDamage: 18, bulletColor: 0x4169e1, gravityControl: true, gravityRadius: 8, gravityForce: 2, floatDuration: 3000 }, phaseshifter: { name: "Phase Shifter", description: "Madde içinden geçebilen hayalet benzeri karakter", color: 0x98fb98, bulletSpeed: 1.4, bulletDamage: 11, bulletColor: 0x98fb98, phaseThrough: true, phaseDuration: 2000, etherealForm: true }, chronobreaker: { name: "Chrono Breaker", description: "Zaman akışını kırıp düşmanları dondurabilen usta", color: 0xda70d6, bulletSpeed: 1.0, bulletDamage: 16, bulletColor: 0xda70d6, timeFreeze: true, freezeDuration: 4000, timeBurst: true }, voidwalker: { name: "Void Walker", description: "Boşluk enerjisini kullanan gizemli savaşçı", color: 0x483d8b, bulletSpeed: 1.2, bulletDamage: 15, bulletColor: 0x483d8b, voidPowers: true, voidPortal: true, portalDuration: 6000 }, mindweaver: { name: "Mind Weaver", description: "Düşman kontrolü ve yanılsama yaratabilen psişik", color: 0xff69b4, bulletSpeed: 1.1, bulletDamage: 13, bulletColor: 0xff69b4, mindControl: true, illusionCreate: true, controlDuration: 3000 }, quantumleaper: { name: "Quantum Leaper", description: "Kuantum sıçrayışları yapabilen bilim adamı savaşçı", color: 0x40e0d0, bulletSpeed: 1.3, bulletDamage: 14, bulletColor: 0x40e0d0, quantumLeap: true, multiverse: true, leapRange: 15 }, spacetime: { name: "Spacetime Bender", description: "Uzay-zamanı büken ve manipüle eden usta", color: 0xffd700, bulletSpeed: 1.2, bulletDamage: 17, bulletColor: 0xffd700, warpReality: true, timeDilation: true, warpRadius: 10 }, nullifier: { name: "Nullifier", description: "Düşman yeteneklerini geçici olarak devre dışı bırakan uzman", color: 0x8b0000, bulletSpeed: 1.1, bulletDamage: 13, bulletColor: 0x8b0000, nullifyPowers: true, nullifyDuration: 5000, powerDrain: true }, realityshaper: { name: "Reality Shaper", description: "Gerçekliği yeniden şekillendirebilen efsanevi varlık", color: 0xf0e68c, bulletSpeed: 1.4, bulletDamage: 16, bulletColor: 0xf0e68c, realityWarp: true, terraformArea: true, warpDuration: 4000 }, eternitymaster: { name: "Eternity Master", description: "Sonsuzluk güçlerini kullanan antik varlık", color: 0x4682b4, bulletSpeed: 1.3, bulletDamage: 18, bulletColor: 0x4682b4, eternityManip: true, timeLoop: true, loopDuration: 5000 } }; const levelData = { 1: { color: 0x2d572c, enemySpeed: 0.04, enemyHealth: 40, bossHealth: 250 }, 2: { color: 0x654321, enemySpeed: 0.05, enemyHealth: 55, bossHealth: 350 }, 3: { color: 0x808080, enemySpeed: 0.06, enemyHealth: 70, bossHealth: 500 }, 4: { color: 0x800080, enemySpeed: 0.07, enemyHealth: 85, bossHealth: 650 }, 5: { color: 0xff4500, enemySpeed: 0.08, enemyHealth: 100, bossHealth: 800 } }; const enemyTypes = { normal: { color: 0xff3333, speedMod: 1.0, healthMod: 1.2, dodgeChance: 0.2, sizeMod: 1.2 }, bomber: { color: 0xff6600, speedMod: 1.3, healthMod: 0.8, dodgeChance: 0.1, sizeMod: 1.0, explodeOnDeath: true, explosionRadius: 4, explosionDamage: 30 }, sniper: { color: 0x9900ff, speedMod: 0.7, healthMod: 1.0, dodgeChance: 0.4, sizeMod: 1.1, canShoot: true, shootRange: 15, shootCooldown: 2000, bulletSpeed: 0.5, bulletDamage: 15 }, splitter: { color: 0x00ffaa, speedMod: 0.9, healthMod: 1.4, dodgeChance: 0.2, sizeMod: 1.3, splitOnDeath: true, splitCount: 3, childType: 'normal', childSize: 0.6 }, fast: { color: 0x33ff33, speedMod: 1.5, healthMod: 0.9, dodgeChance: 0.4, sizeMod: 0.9 }, tank: { color: 0x3333ff, speedMod: 0.6, healthMod: 2.0, dodgeChance: 0.1, sizeMod: 1.8 }, ranged: { color: 0xffff33, speedMod: 0.8, healthMod: 1.1, dodgeChance: 0.3, sizeMod: 1.3 }, ninja: { color: 0x9933ff, speedMod: 1.3, healthMod: 1.0, dodgeChance: 0.6, sizeMod: 0.8 }, giant: { color: 0x800000, speedMod: 0.4, healthMod: 3.0, dodgeChance: 0.05, sizeMod: 2.5 }, elite: { color: 0xffa500, speedMod: 1.1, healthMod: 1.8, dodgeChance: 0.3, sizeMod: 1.6 }, phantom: { color: 0x800080, speedMod: 1.4, healthMod: 1.5, dodgeChance: 0.5, sizeMod: 1.0, teleport: true, teleportCooldown: 5000, invisibilityDuration: 3000 }, berserker: { color: 0xff4400, speedMod: 1.6, healthMod: 2.2, dodgeChance: 0.2, sizeMod: 1.8, rageMode: true, rageDamageMultiplier: 2.0, rageSpeedMultiplier: 1.5 }, elementalist: { color: 0x00ffaa, speedMod: 1.0, healthMod: 1.7, dodgeChance: 0.4, sizeMod: 1.2, elementalAttacks: true, elementTypes: ['fire', 'ice', 'lightning'], elementDamage: 15 }, necromancer: { color: 0x660066, speedMod: 0.8, healthMod: 2.0, dodgeChance: 0.3, sizeMod: 1.4, summonMinions: true, minionCount: 3, minionHealth: 30 } }; const [health, setHealth] = useState(100); const [showMainMenu, setShowMainMenu] = useState(false); const syncPlayerPosition = () => { if (isMultiplayer && player) { // In a real implementation, this would send position to server // For test mode, we'll just update local state setOtherPlayers(prev => ({ ...prev, [playerId]: { position: player.position.clone(), character: 'normal' } })); } }; const [score, setScore] = useState(0); const [gameOver, setGameOver] = useState(false); const [bulletCount, setBulletCount] = useState(100); const [laserCharge, setLaserCharge] = useState(100); const [bossMode, setBossMode] = useState(false); const [rageMeter, setRageMeter] = useState(0); const [rageActive, setRageActive] = useState(false); useEffect(() => { if (!gameStarted) return; // Don't initialize if game hasn't started let player, scene, camera, renderer, bullets = []; // Rage mode function const activateRageMode = () => { setRageActive(true); // Apply rage effects if (player && player.children) { player.scale.set(1.5, 1.5, 1.5); // Store original colors before changing them player.children.forEach(part => { if (part.userData.isPlayerPart && part.material && part.material.color) { part.userData.originalColor = part.material.color.getHex(); part.userData.originalEmissive = part.material.emissive ? part.material.emissive.getHex() : 0x000000; part.userData.originalEmissiveIntensity = part.material.emissiveIntensity || 0; } }); // Apply rage effects player.children.forEach(part => { if (part.userData.isPlayerPart && part.material && part.material.color) { try { part.material.color.setHex(0xffff00); if (part.material.emissive) { part.material.emissive.setHex(0xffff00); part.material.emissiveIntensity = 0.5; } } catch (error) { console.warn('Failed to update material properties:', error); } } }); // Store player state in userData player.userData.rageMode = { scale: player.scale.clone(), colors: player.children .filter(part => part.userData.isPlayerPart && part.material) .map(part => ({ partId: part.id, color: part.material.color.getHex(), emissive: part.material.emissive.getHex(), emissiveIntensity: part.material.emissiveIntensity })) }; } // Reset after 10 seconds setTimeout(() => { setRageActive(false); setRageMeter(0); if (player && player.children && player.userData.rageMode) { // Restore original scale player.scale.copy(player.userData.rageMode.scale); // Restore original colors player.userData.rageMode.colors.forEach(originalState => { const part = player.children.find(child => child.id === originalState.partId); if (part && part.material) { try { part.material.color.setHex(originalState.color); part.material.emissive.setHex(originalState.emissive); part.material.emissiveIntensity = originalState.emissiveIntensity; } catch (error) { console.warn('Failed to reset material properties:', error); } } }); // Clear rage mode data delete player.userData.rageMode; } }, 10000); }; const keyState = {}; // Setup scene = new THREE.Scene(); const aspect = window.innerWidth / window.innerHeight; camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000); // Load Purple Crystal model and texture const textureLoader = new THREE.TextureLoader(); const effectTexture = textureLoader.load('https://play.rosebud.ai/assets/purple light effect.png?OOme'); // Create Purple Crystal power-up material with effect const crystalMaterial = new THREE.MeshPhongMaterial({ color: 0x800080, emissive: 0x400040, emissiveIntensity: 0.5, transparent: true, opacity: 0.8 }); // Load Purple Crystal model const loader = new GLTFLoader(); loader.load('https://play.rosebud.ai/assets/Purple Crystal.glb?vWMr', (gltf) => { const crystal = gltf.scene; crystal.scale.set(0.5, 0.5, 0.5); crystal.traverse((child) => { if (child.isMesh) { child.material = crystalMaterial; } }); // Add effect plane const effectGeometry = new THREE.PlaneGeometry(2, 2); const effectMaterial = new THREE.MeshBasicMaterial({ map: effectTexture, transparent: true, opacity: 0.6, blending: THREE.AdditiveBlending }); const effect = new THREE.Mesh(effectGeometry, effectMaterial); effect.rotation.x = -Math.PI / 2; effect.position.y = 0.1; // Create power-up group const powerUp = new THREE.Group(); powerUp.add(crystal); powerUp.add(effect); powerUp.userData.type = 'powerup'; powerUp.userData.effect = 'crystal'; // Spawn power-up at random position const spawnPowerUp = () => { const clone = powerUp.clone(); clone.position.set( Math.random() * 180 - 90, 1, Math.random() * 180 - 90 ); // Rotating animation clone.userData.rotate = true; clone.userData.hoverOffset = Math.random() * Math.PI * 2; scene.add(clone); }; // Spawn power-ups periodically setInterval(spawnPowerUp, 15000); }); renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setPixelRatio(window.devicePixelRatio); renderer.setSize(window.innerWidth, window.innerHeight); // Handle screen resize const handleResize = () => { const newAspect = window.innerWidth / window.innerHeight; camera.aspect = newAspect; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); }; window.addEventListener('resize', handleResize); // Ensure mountRef is available before appending if (mountRef.current) { mountRef.current.appendChild(renderer.domElement); } else { console.warn('Mount reference not available'); return () => { window.removeEventListener('resize', handleResize); }; } // Lighting const light = new THREE.AmbientLight(0xffffff, 0.8); scene.add(light); // Ground const groundGeometry = new THREE.PlaneGeometry(200, 200); const groundMaterial = new THREE.MeshBasicMaterial({ color: groundColor, // Seçilen zemin rengi wireframe: true, wireframeLinewidth: 1.5, transparent: true, opacity: 0.8 }); const ground = new THREE.Mesh(groundGeometry, groundMaterial); ground.rotation.x = -Math.PI / 2; scene.add(ground); // Player model const playerGeometry = new THREE.Group(); // Player body const bodyGeometry = new THREE.BoxGeometry(1, 1, 1); const bodyMaterial = new THREE.MeshPhongMaterial({ color: characters[selectedCharacter || 'normal'].color, emissive: characters[selectedCharacter || 'normal'].color, emissiveIntensity: 0.2 }); const body = new THREE.Mesh(bodyGeometry, bodyMaterial); body.userData.isPlayerPart = true; // Player head const headGeometry = new THREE.BoxGeometry(0.6, 0.6, 0.6); const headMaterial = new THREE.MeshPhongMaterial({ color: 0x0044cc, emissive: 0x000000, emissiveIntensity: 0 }); const head = new THREE.Mesh(headGeometry, headMaterial); head.userData.isPlayerPart = true; head.position.y = 0.8; // Player weapon const weaponGeometry = new THREE.BoxGeometry(0.2, 0.2, 1); const weaponMaterial = new THREE.MeshPhongMaterial({ color: 0x666666, emissive: 0x000000, emissiveIntensity: 0 }); const weapon = new THREE.Mesh(weaponGeometry, weaponMaterial); weapon.userData.isPlayerPart = true; weapon.position.set(0.5, 0, 0.5); playerGeometry.add(body); playerGeometry.add(head); playerGeometry.add(weapon); player = playerGeometry; player.position.y = 0.5; scene.add(player); // Camera position camera.position.set(0, 25, 15); // Higher and further back camera.rotation.x = -Math.PI / 2.5; // More top-down angle // Create Enemy const createEnemy = (type = 'normal') => { let enemyGroup = new THREE.Group(); let enemyHealth = levelData[level].enemyHealth; let enemyColor = 0xff0000; let enemySize = 1; // Level-based size and health scaling const levelScaling = 1 + (level - 1) * 0.2; // Each level increases size by 20% const typeData = enemyTypes[type]; enemyColor = typeData.color; enemyHealth *= typeData.healthMod; enemySize *= typeData.speedMod; // Add special enemy abilities if (typeData.teleport) { enemyGroup.canTeleport = true; enemyGroup.lastTeleport = 0; enemyGroup.teleportCooldown = typeData.teleportCooldown; } if (typeData.rageMode) { enemyGroup.canRage = true; enemyGroup.isRaging = false; enemyGroup.rageDamageMultiplier = typeData.rageDamageMultiplier; enemyGroup.rageSpeedMultiplier = typeData.rageSpeedMultiplier; } if (typeData.elementalAttacks) { enemyGroup.hasElementalPowers = true; enemyGroup.currentElement = typeData.elementTypes[0]; enemyGroup.elementDamage = typeData.elementDamage; } if (typeData.summonMinions) { enemyGroup.canSummonMinions = true; enemyGroup.lastSummon = 0; enemyGroup.minionCount = typeData.minionCount; enemyGroup.minionHealth = typeData.minionHealth; } // Add enemy type and dodge properties enemyGroup.type = type; enemyGroup.dodgeChance = typeData.dodgeChance; enemyGroup.lastDodge = 0; enemyGroup.isDodging = false; enemyGroup.dodgeDirection = new THREE.Vector3(); // Enemy body with enhanced features const baseSize = enemySize * typeData.sizeMod * levelScaling; const bodyGeometry = new THREE.BoxGeometry(baseSize, baseSize, baseSize); const bodyMaterial = new THREE.MeshPhongMaterial({ color: enemyColor, metalness: 0.3, roughness: 0.7, emissive: enemyColor, emissiveIntensity: 0.2 }); const body = new THREE.Mesh(bodyGeometry, bodyMaterial); // Enemy spikes const spikeGeometry = new THREE.ConeGeometry(0.2, 0.4, 4); const spikeMaterial = new THREE.MeshPhongMaterial({ color: 0xcc0000 }); const positions = [ { x: 0.5, y: 0, z: 0.5 }, { x: -0.5, y: 0, z: 0.5 }, { x: 0.5, y: 0, z: -0.5 }, { x: -0.5, y: 0, z: -0.5 } ]; positions.forEach(pos => { const spike = new THREE.Mesh(spikeGeometry, spikeMaterial); spike.position.set(pos.x, pos.y, pos.z); enemyGroup.add(spike); }); enemyGroup.add(body); const enemy = enemyGroup; enemy.position.set( Math.random() * 180 - 90, // Expanded spawn area 0.5, Math.random() * 180 - 90 // Expanded spawn area ); enemy.health = 30 + ((level - 1) * 10); // Her level'da düşmanlar 10 can artıyor scene.add(enemy); setEnemies(prev => [...prev, enemy]); }; // Create Boss const createBoss = () => { const bossTypes = { 1: { name: "Guardian", geometry: new THREE.Group(), color: 0xff00ff, health: levelData[level].bossHealth, abilities: ['summonMinions', 'shockwave'], attackCooldown: 3000 }, 2: { name: "Destroyer", geometry: new THREE.Group(), color: 0xff0000, health: levelData[level].bossHealth, abilities: ['laserBeam', 'teleport'], attackCooldown: 2500 }, 3: { name: "Titan", geometry: new THREE.Group(), color: 0x00ff00, health: levelData[level].bossHealth, abilities: ['groundSlam', 'bulletHell'], attackCooldown: 4000 }, 4: { name: "Phantom", geometry: new THREE.Group(), color: 0x0000ff, health: levelData[level].bossHealth, abilities: ['clone', 'vortex'], attackCooldown: 3500 }, 5: { name: "Overlord", geometry: new THREE.Group(), color: 0xffff00, health: levelData[level].bossHealth, abilities: ['allAbilities'], attackCooldown: 2000 } }; const bossLevel = Math.min(level, 5); const bossType = bossTypes[bossLevel]; // Create boss body const bossBody = new THREE.Mesh( new THREE.BoxGeometry(4, 4, 4), new THREE.MeshPhongMaterial({ color: bossType.color, metalness: 0.8, roughness: 0.2, emissive: bossType.color, emissiveIntensity: 0.3 }) ); // Create boss armor pieces const armorGeometry = new THREE.BoxGeometry(1, 1, 1); const armorMaterial = new THREE.MeshPhongMaterial({ color: 0x888888, metalness: 0.9, roughness: 0.1 }); // Add armor pieces const armorPositions = [ { x: 2, y: 0, z: 0 }, { x: -2, y: 0, z: 0 }, { x: 0, y: 2, z: 0 }, { x: 0, y: -2, z: 0 } ]; armorPositions.forEach(pos => { const armor = new THREE.Mesh(armorGeometry, armorMaterial); armor.position.set(pos.x, pos.y, pos.z); bossBody.add(armor); }); // Create boss weapon const weaponGeometry = new THREE.ConeGeometry(0.5, 3, 4); const weaponMaterial = new THREE.MeshPhongMaterial({ color: 0xdd0000, metalness: 0.7, roughness: 0.3 }); const weapon = new THREE.Mesh(weaponGeometry, weaponMaterial); weapon.position.set(2, 0, 2); weapon.rotation.z = Math.PI / 2; bossBody.add(weapon); bossType.geometry.add(bossBody); const boss = bossType.geometry; boss.position.set(0, 2, -20); boss.health = bossType.health; boss.maxHealth = bossType.health; boss.type = 'boss'; boss.name = bossType.name; boss.abilities = bossType.abilities; boss.lastAttack = 0; boss.attackCooldown = bossType.attackCooldown; scene.add(boss); enemies = [boss]; setBossMode(true); }; // Targeting system // Enhanced targeting system const targetGroup = new THREE.Group(); // Main targeting ring const targetRing = new THREE.Mesh( new THREE.RingGeometry(0.5, 0.7, 32), new THREE.MeshBasicMaterial({ color: 0xff0000, side: THREE.DoubleSide, transparent: true, opacity: 0.5 }) ); // Crosshair lines const crosshairMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, transparent: true, opacity: 0.7 }); // Vertical line const verticalLine = new THREE.Mesh( new THREE.PlaneGeometry(0.05, 1), crosshairMaterial ); // Horizontal line const horizontalLine = new THREE.Mesh( new THREE.PlaneGeometry(1, 0.05), crosshairMaterial ); // Corner markers const cornerSize = 0.2; const corners = [ { x: 1, y: 1 }, { x: -1, y: 1 }, { x: -1, y: -1 }, { x: 1, y: -1 } ].map(pos => { const corner = new THREE.Mesh( new THREE.PlaneGeometry(cornerSize, 0.05), crosshairMaterial ); corner.position.set(pos.x * 0.85, pos.y * 0.85, 0); const corner2 = new THREE.Mesh( new THREE.PlaneGeometry(0.05, cornerSize), crosshairMaterial ); corner2.position.set(pos.x * 0.85, pos.y * 0.85, 0); return [corner, corner2]; }).flat(); targetGroup.add(targetRing); targetGroup.add(verticalLine); targetGroup.add(horizontalLine); corners.forEach(corner => targetGroup.add(corner)); scene.add(targetGroup); // Shoot function // Common bullet setup const createBullet = (direction, speed) => { const char = characters[selectedCharacter || 'normal']; // Auto-aim logic const getAutoAimDirection = () => { const closestEnemy = findClosestEnemy(); if (closestEnemy && autoAimEnabled) { const targetDir = new THREE.Vector3(); targetDir.subVectors(closestEnemy.position, player.position); targetDir.y = 0; // Keep shots horizontal return targetDir.normalize(); } const defaultDir = new THREE.Vector3(); camera.getWorldDirection(defaultDir); defaultDir.y = 0; return defaultDir.normalize(); }; const bulletGeometry = new THREE.SphereGeometry(rageActive ? 0.4 : 0.2); const bulletMaterial = new THREE.MeshBasicMaterial({ color: char.bulletColor }); const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial); bullet.position.copy(player.position); bullet.position.y += 0.5; bullet.damage = char.bulletDamage; // Create a new Vector3 for velocity to avoid modifying the original direction bullet.velocity = direction.clone().normalize().multiplyScalar(speed || char.bulletSpeed); // Ensure bullet moves horizontally bullet.velocity.y = 0; // Add special properties based on character type if (char.piercing) bullet.piercing = true; if (char.bouncingBullets) { bullet.bouncing = true; bullet.bounceCount = 0; } if (char.explosiveShot) bullet.explosive = true; scene.add(bullet); bullets.push(bullet); return bullet; }; const shoot = () => { if (bulletCount <= 0 || (isMultiplayer && !canShoot)) { return; // Exit if no bullets or in cooldown } // Apply multiplayer cooldown if (isMultiplayer) { setCanShoot(false); setBulletCooldown(100); // Start cooldown animation const cooldownAnimation = () => { setBulletCooldown(prev => { if (prev <= 0) { setCanShoot(true); return 0; } requestAnimationFrame(cooldownAnimation); return prev - 2; }); }; requestAnimationFrame(cooldownAnimation); } // Ultimate character özel kontrolleri if (selectedCharacter === 'ultimate') { // Multi-shot özelliği const angles = [-30, -15, 0, 15, 30]; // Derece cinsinden açılar angles.forEach(angle => { const direction = new THREE.Vector3(); camera.getWorldDirection(direction); // Açıyı radyana çevir ve yönü döndür const radians = (angle * Math.PI) / 180; direction.applyAxisAngle(new THREE.Vector3(0, 1, 0), radians); const bullet = createBullet(direction, characters.ultimate.bulletSpeed); // Ultimate özellikleri ekle bullet.piercing = true; bullet.bouncing = true; bullet.explosive = true; bullet.tracking = true; bullet.damage = characters.ultimate.bulletDamage; // Özel görsel efektler const glowMaterial = new THREE.MeshBasicMaterial({ color: 0xffd700, transparent: true, opacity: 0.5 }); const glowSphere = new THREE.Mesh( new THREE.SphereGeometry(0.4), glowMaterial ); bullet.add(glowSphere); }); // Ultimate karakteri için mermi sayısını daha az azalt setBulletCount(prev => Math.max(0, prev - 0.5)); return; } const char = characters[selectedCharacter || 'normal']; switch(selectedCharacter) { case 'shocktank': // Tank's close-range shock attack const shockDir = new THREE.Vector3(); camera.getWorldDirection(shockDir); shockDir.y = 0; shockDir.normalize(); // Create shock wave effect const shockWave = new THREE.Mesh( new THREE.RingGeometry(0, characters.shocktank.shockRadius, 32), new THREE.MeshBasicMaterial({ color: 0x4169e1, transparent: true, opacity: 0.6, side: THREE.DoubleSide }) ); shockWave.position.copy(player.position); shockWave.rotation.x = -Math.PI / 2; scene.add(shockWave); // Animate shock wave const expandShockWave = () => { shockWave.scale.x += 0.2; shockWave.scale.y += 0.2; shockWave.material.opacity -= 0.02; if (shockWave.scale.x < 3) { requestAnimationFrame(expandShockWave); } else { scene.remove(shockWave); } }; expandShockWave(); // Create close-range bullet with shock effect const shockBullet = createBullet(shockDir, characters.shocktank.bulletSpeed); shockBullet.shock = true; shockBullet.shockRadius = characters.shocktank.shockRadius; shockBullet.shockDamage = characters.shocktank.shockDamage; shockBullet.shockStunDuration = characters.shocktank.shockStunDuration; break; case 'sniper': // Charged shot with pierce const direction = new THREE.Vector3(); camera.getWorldDirection(direction); direction.y = 0; // Ensure bullet travels horizontally direction.normalize(); setTimeout(() => { if (bulletCount > 0) { // Check if still has bullets createBullet(direction, char.bulletSpeed * 1.5); } }, 1000); // 1 second charge time break; case 'explosive': // Explosive area damage shot const explosiveDir = new THREE.Vector3(); camera.getWorldDirection(explosiveDir); createBullet(explosiveDir); break; case 'rapid': // Rapid fire with bouncing for (let i = 0; i < 3; i++) { setTimeout(() => { if (bulletCount > 0) { const spread = (Math.random() - 0.5) * 0.2; const dir = new THREE.Vector3(); camera.getWorldDirection(dir); dir.x += spread; createBullet(dir); setBulletCount(prev => Math.max(0, prev - 1)); } }, i * 100); } break; case 'close': // Spread shot implementation for (let i = -1; i <= 1; i++) { const direction = new THREE.Vector3(); camera.getWorldDirection(direction); direction.x += i * 0.2; direction.normalize(); createBullet(direction); } break; case 'ranged': // Tracking bullet implementation with camera direction fallback const closestEnemy = findClosestEnemy(); const trackingDir = new THREE.Vector3(); if (closestEnemy) { trackingDir.subVectors(closestEnemy.position, player.position).normalize(); } else { camera.getWorldDirection(trackingDir); } createBullet(trackingDir); break; default: // Normal shot const normalDir = new THREE.Vector3(); camera.getWorldDirection(normalDir); normalDir.y = 0; // Ensure horizontal movement normalDir.normalize(); createBullet(normalDir); } setBulletCount(prev => Math.max(0, prev - 1)); setBulletCount(prev => Math.max(0, prev - 1)); // Ensure selectedCharacter is valid const characterType = selectedCharacter || 'normal'; if (characterType === 'close') { // Spread shot for close combat character for (let i = -1; i <= 1; i++) { const bulletGeometry = new THREE.SphereGeometry(rageActive ? 0.4 : 0.2); const bulletMaterial = new THREE.MeshBasicMaterial({ color: characters.close.color }); const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial); bullet.position.copy(player.position); bullet.position.y += 0.5; const direction = new THREE.Vector3(i * 0.2, 0, -1).normalize(); bullet.velocity = direction.multiplyScalar(characters.close.bulletSpeed); bullet.damage = characters.close.bulletDamage; scene.add(bullet); bullets.push(bullet); } } else { const bulletGeometry = new THREE.SphereGeometry(rageActive ? 0.4 : 0.2); const bulletMaterial = new THREE.MeshBasicMaterial({ color: characters[selectedCharacter || 'normal'].color }); const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial); bullet.position.copy(player.position); bullet.position.y += 0.5; const closestEnemy = findClosestEnemy(); const direction = new THREE.Vector3(); if (closestEnemy && selectedCharacter === 'ranged') { direction.subVectors(closestEnemy.position, bullet.position).normalize(); } else { camera.getWorldDirection(direction); } bullet.velocity = direction.multiplyScalar( characters[selectedCharacter || 'normal'].bulletSpeed ); bullet.damage = characters[selectedCharacter || 'normal'].bulletDamage; scene.add(bullet); bullets.push(bullet); } setBulletCount(prev => { const newCount = prev - 1; return newCount < 0 ? 0 : newCount; }); const bulletGeometry = new THREE.SphereGeometry(rageActive ? 0.4 : 0.2); const bulletMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 }); const bullet = new THREE.Mesh(bulletGeometry, bulletMaterial); // Set bullet starting position at player's weapon bullet.position.copy(player.position); bullet.position.y += 0.5; // Calculate shooting direction const direction = new THREE.Vector3(); const closestEnemy = findClosestEnemy(); if (closestEnemy) { direction.subVectors(closestEnemy.position, bullet.position).normalize(); } else { camera.getWorldDirection(direction); } bullet.velocity = direction.multiplyScalar(1.0); // Increased bullet speed scene.add(bullet); bullets.push(bullet); }; // Mobile Controls const joystickArea = document.createElement('div'); joystickArea.style.cssText = ` position: fixed; left: 20px; bottom: 20px; width: 150px; height: 150px; background: rgba(255, 255, 255, 0.2); border-radius: 50%; touch-action: none; `; document.body.appendChild(joystickArea); // Special powers container const specialPowersContainer = document.createElement('div'); specialPowersContainer.style.cssText = ` position: fixed; right: 20px; top: 50%; transform: translateY(-50%); display: flex; flex-direction: column; gap: 20px; z-index: 1000; `; document.body.appendChild(specialPowersContainer); // Red shoot button const shootButton = document.createElement('div'); shootButton.style.cssText = ` position: fixed; right: 120px; bottom: 30px; width: 80px; height: 80px; background: rgba(255, 0, 0, 0.3); border-radius: 50%; touch-action: none; `; document.body.appendChild(shootButton); // Green laser button const laserButton = document.createElement('div'); laserButton.style.cssText = ` position: fixed; right: 30px; bottom: 30px; width: 80px; height: 80px; background: rgba(0, 255, 0, 0.3); border-radius: 50%; touch-action: none; `; // Replace laser button with shield button in multiplayer const shieldButton = document.createElement('div'); shieldButton.style.cssText = ` position: fixed; right: 30px; bottom: 30px; width: 80px; height: 80px; background: rgba(0, 0, 255, 0.3); border-radius: 50%; touch-action: none; `; // Create special power buttons based on character const createSpecialPowerButtons = () => { // Clear existing buttons while (specialPowersContainer.firstChild) { specialPowersContainer.removeChild(specialPowersContainer.firstChild); } const char = characters[selectedCharacter || 'normal']; // Common special power button style const buttonStyle = ` width: 60px; height: 60px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, 0.3); background: rgba(0, 0, 0, 0.5); color: white; font-size: 24px; display: flex; align-items: center; justify-content: center; touch-action: none; position: relative; `; // Add character-specific power buttons if (char.timeControl) { const timeButton = document.createElement('div'); timeButton.style.cssText = buttonStyle; timeButton.innerHTML = '⏱️'; timeButton.addEventListener('touchstart', activateTimeControl); specialPowersContainer.appendChild(timeButton); } if (char.teleport) { const teleportButton = document.createElement('div'); teleportButton.style.cssText = buttonStyle; teleportButton.innerHTML = '⚡'; teleportButton.addEventListener('touchstart', activateTeleport); specialPowersContainer.appendChild(teleportButton); } if (char.invisibility) { const invisibilityButton = document.createElement('div'); invisibilityButton.style.cssText = buttonStyle; invisibilityButton.innerHTML = '👻'; invisibilityButton.addEventListener('touchstart', activateInvisibility); specialPowersContainer.appendChild(invisibilityButton); } if (char.elementalPowers) { const elementButton = document.createElement('div'); elementButton.style.cssText = buttonStyle; elementButton.innerHTML = '🌪️'; elementButton.addEventListener('touchstart', activateElementalPower); specialPowersContainer.appendChild(elementButton); } }; // Create initial power buttons createSpecialPowerButtons(); if (isMultiplayer) { document.body.appendChild(shieldButton); } else { document.body.appendChild(laserButton); } // Touch controls let joystickActive = false; let joystickOrigin = { x: 0, y: 0 }; let moveDirection = { x: 0, z: 0 }; joystickArea.addEventListener('touchstart', (e) => { joystickActive = true; joystickOrigin.x = e.touches[0].clientX; joystickOrigin.y = e.touches[0].clientY; }); joystickArea.addEventListener('touchmove', (e) => { if (joystickActive) { e.preventDefault(); const deltaX = e.touches[0].clientX - joystickOrigin.x; const deltaY = e.touches[0].clientY - joystickOrigin.y; const distance = Math.min(50, Math.sqrt(deltaX * deltaX + deltaY * deltaY)); const angle = Math.atan2(deltaY, deltaX); moveDirection.x = (distance / 50) * Math.cos(angle); moveDirection.z = (distance / 50) * Math.sin(angle); } }); joystickArea.addEventListener('touchend', () => { joystickActive = false; moveDirection = { x: 0, z: 0 }; }); shootButton.addEventListener('touchstart', (e) => { e.preventDefault(); if (bulletCount > 0) { const characterType = selectedCharacter || 'normal'; if (characterType === 'close') { // Spread shot for close combat character shoot(); } else if (characterType === 'ranged') { // Tracking shot for ranged character shoot(); } else { // Normal shot shoot(); } } }); // Keep keyboard controls for desktop document.addEventListener('keydown', (e) => { keyState[e.key] = true; if (e.key === ' ' && bulletCount > 0) { const characterType = selectedCharacter || 'normal'; if (characterType === 'close') { shoot(); } else if (characterType === 'ranged') { shoot(); } else { shoot(); } } }); document.addEventListener('keyup', (e) => keyState[e.key] = false); // Find closest enemy function const findClosestEnemy = () => { if (enemies.length === 0) return null; let closest = enemies[0]; let minDistance = closest.position.distanceTo(player.position); enemies.forEach(enemy => { const distance = enemy.position.distanceTo(player.position); if (distance < minDistance) { minDistance = distance; closest = enemy; } }); return closest; }; // Game Loop let lastEnemySpawn = 0; let isLaserActive = false; // Create laser beam // Create lightning effect for laser const createLightningEffect = () => { const points = []; const segments = 15; let lastPoint = new THREE.Vector3(); for (let i = 0; i <= segments; i++) { const point = new THREE.Vector3( (Math.random() - 0.5) * 0.2, (Math.random() - 0.5) * 0.2, i / segments ); if (i > 0) { point.add(lastPoint); } points.push(point); lastPoint = point.clone(); } return new THREE.BufferGeometry().setFromPoints(points); }; const laserGeometry = createLightningEffect(); const laserMaterial = new THREE.LineBasicMaterial({ color: 0x00ffff, transparent: true, opacity: 0.8, linewidth: 2 }); const laser = new THREE.Line(laserGeometry, laserMaterial); scene.add(laser); // Update laser position and visibility const updateLaser = () => { const closestEnemy = findClosestEnemy(); if (closestEnemy && isLaserActive && laserCharge > 0) { fireLaser(); // Create dynamic lightning effect const start = new THREE.Vector3( player.position.x, player.position.y + 0.5, player.position.z ); const end = closestEnemy.position.clone(); const direction = end.clone().sub(start); const length = direction.length(); direction.normalize(); const points = []; const segments = 15; const deflection = 0.3; for (let i = 0; i <= segments; i++) { const t = i / segments; const pos = new THREE.Vector3().lerpVectors(start, end, t); if (i > 0 && i < segments) { pos.x += (Math.random() - 0.5) * deflection; pos.y += (Math.random() - 0.5) * deflection; pos.z += (Math.random() - 0.5) * deflection; } points.push(pos); } const positions = new Float32Array(points.length * 3); points.forEach((point, i) => { positions[i * 3] = point.x; positions[i * 3 + 1] = point.y; positions[i * 3 + 2] = point.z; }); laserGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)); laserGeometry.attributes.position.needsUpdate = true; laser.visible = true; } else { laser.visible = false; } }; // Laser attack function const fireLaser = () => { if (laserCharge <= 0) { isLaserActive = false; laser.visible = false; return; } const isLaserMaster = selectedCharacter === 'laserMaster'; const laserDamage = isLaserMaster ? characters.laserMaster.laserDamage : (rageActive ? 50 : 30); const laserWidth = isLaserMaster ? characters.laserMaster.laserWidth : 0.2; const laserColor = isLaserMaster ? characters.laserMaster.laserColor : 0x00ffff; laserMaterial.color.setHex(laserColor); laserMaterial.linewidth = laserWidth; setLaserCharge(prev => { const newCharge = Math.max(0, prev - 2); if (newCharge <= 0) { isLaserActive = false; laser.visible = false; } return newCharge; }); // Update laser charge before firing setLaserCharge(prevCharge => { if (prevCharge <= 0) { isLaserActive = false; laser.visible = false; return 0; } return Math.max(0, prevCharge - 2); }); const closestEnemy = findClosestEnemy(); if (closestEnemy) { setLaserCharge(prev => { const newCharge = Math.max(0, prev - 2); if (newCharge <= 0) { isLaserActive = false; laser.visible = false; } return newCharge; }); closestEnemy.health -= rageActive ? 50 : 30; // More damage during rage mode if (closestEnemy.health <= 0) { scene.remove(closestEnemy); enemies = enemies.filter(e => e !== closestEnemy); setScore(prev => prev + 20); // More points for laser kills } } }; // Shield mechanics const activateShield = () => { if (isMultiplayer && shieldHealth > 0) { setShieldActive(true); // Create shield visual effect const shieldGeometry = new THREE.SphereGeometry(1.5, 32, 32); const shieldMaterial = new THREE.MeshPhongMaterial({ color: 0x0088ff, transparent: true, opacity: 0.3, side: THREE.DoubleSide }); const shield = new THREE.Mesh(shieldGeometry, shieldMaterial); player.add(shield); shield.userData.isShield = true; } }; const deactivateShield = () => { setShieldActive(false); player.children.forEach(child => { if (child.userData.isShield) { player.remove(child); } }); }; const animate = () => { if (!gameOver) { requestAnimationFrame(animate); // Update power-up animations scene.children.forEach(object => { if (object.userData.type === 'powerup') { // Rotate the crystal object.rotation.y += 0.02; // Hovering animation const hoverHeight = Math.sin(Date.now() * 0.002 + object.userData.hoverOffset) * 0.2; object.position.y = 1 + hoverHeight; // Check for player collection if (object.position.distanceTo(player.position) < 2) { // Apply power-up effect if (object.userData.effect === 'crystal') { // Temporary invincibility and damage boost const originalDamage = characters[selectedCharacter].bulletDamage; characters[selectedCharacter].bulletDamage *= 2; // Visual effect on player player.children.forEach(child => { if (child.material) { child.material.emissive = new THREE.Color(0x800080); child.material.emissiveIntensity = 0.8; } }); // Reset after 10 seconds setTimeout(() => { characters[selectedCharacter].bulletDamage = originalDamage; player.children.forEach(child => { if (child.material) { child.material.emissive = new THREE.Color(0x000000); child.material.emissiveIntensity = 0; } }); }, 10000); scene.remove(object); } } } }); // Player Movement (combined mobile and keyboard) if (joystickActive) { player.position.x += moveDirection.x * 0.1; player.position.z += moveDirection.z * 0.1; } else { if (keyState['w']) player.position.z -= 0.1; if (keyState['s']) player.position.z += 0.1; if (keyState['a']) player.position.x -= 0.1; if (keyState['d']) player.position.x += 0.1; } // Update bullets bullets.forEach((bullet, bulletIndex) => { // Handle bouncing bullets if (bullet.bouncing && bullet.bounceCount < characters.rapid.maxBounces) { // Check for boundaries and bounce if (Math.abs(bullet.position.x) > 90 || Math.abs(bullet.position.z) > 90) { bullet.velocity.multiplyScalar(-1); bullet.bounceCount++; } } // Update bullet position while maintaining height const currentY = bullet.position.y; bullet.position.add(bullet.velocity); bullet.position.y = currentY; // Handle explosive bullets if (bullet.explosive) { enemies.forEach(enemy => { const distance = bullet.position.distanceTo(enemy.position); if (distance < characters.explosive.explosionRadius) { enemy.health -= bullet.damage * (1 - distance / characters.explosive.explosionRadius); // Create explosion effect const explosionGeometry = new THREE.SphereGeometry(characters.explosive.explosionRadius); const explosionMaterial = new THREE.MeshBasicMaterial({ color: 0xff6600, transparent: true, opacity: 0.5 }); const explosion = new THREE.Mesh(explosionGeometry, explosionMaterial); explosion.position.copy(bullet.position); scene.add(explosion); // Remove explosion after animation setTimeout(() => { scene.remove(explosion); }, 200); } }); } // Check bullet collisions enemies.forEach((enemy, enemyIndex) => { // Check for shock bullet effects if (bullet.shock && bullet.position.distanceTo(enemy.position) < bullet.shockRadius) { // Apply shock damage and stun effect enemy.health -= bullet.shockDamage; enemy.stunned = true; enemy.lastStunTime = Date.now(); enemy.stunDuration = bullet.shockStunDuration; // Visual feedback for stunned enemy enemy.children.forEach(child => { if (child.material) { child.material.emissive = new THREE.Color(0x4169e1); child.material.emissiveIntensity = 0.5; } }); } if (bullet.position.distanceTo(enemy.position) < 1) { enemy.health -= rageActive ? 20 : 10; // Double damage during rage mode scene.remove(bullet); bullets.splice(bulletIndex, 1); // Handle enemy death effects if (enemy.health <= 0) { // Bomber explosion on death if (enemyTypes[enemy.type].explodeOnDeath) { const explosionRadius = enemyTypes[enemy.type].explosionRadius; const explosionDamage = enemyTypes[enemy.type].explosionDamage; // Create explosion effect const explosion = new THREE.Mesh( new THREE.SphereGeometry(explosionRadius), new THREE.MeshBasicMaterial({ color: 0xff6600, transparent: true, opacity: 0.6 }) ); explosion.position.copy(enemy.position); scene.add(explosion); // Damage player if in range if (player.position.distanceTo(enemy.position) < explosionRadius) { setHealth(prev => Math.max(0, prev - explosionDamage)); } // Remove explosion after animation setTimeout(() => scene.remove(explosion), 300); } // Splitter enemy division if (enemyTypes[enemy.type].splitOnDeath) { const splitCount = enemyTypes[enemy.type].splitCount; const childType = enemyTypes[enemy.type].childType; const childSize = enemyTypes[enemy.type].childSize; for (let i = 0; i < splitCount; i++) { const angle = (i / splitCount) * Math.PI * 2; const distance = 1; const childEnemy = createEnemy(childType); childEnemy.position.x = enemy.position.x + Math.cos(angle) * distance; childEnemy.position.z = enemy.position.z + Math.sin(angle) * distance; childEnemy.scale.multiplyScalar(childSize); } } } if (enemy.health <= 0) { // Drop system if (['elite', 'giant', 'tank'].includes(enemy.type)) { // Create ammo drop const dropGeometry = new THREE.BoxGeometry(0.3, 0.3, 0.3); const dropMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 }); const drop = new THREE.Mesh(dropGeometry, dropMaterial); drop.position.copy(enemy.position); drop.userData.type = 'ammo'; drop.userData.amount = Math.floor(Math.random() * 20) + 10; // 10-30 bullets scene.add(drop); } if (['ranged', 'elite'].includes(enemy.type)) { // Create laser charge drop const chargeGeometry = new THREE.BoxGeometry(0.3, 0.3, 0.3); const chargeMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); const charge = new THREE.Mesh(chargeGeometry, chargeMaterial); charge.position.copy(enemy.position); charge.userData.type = 'laser'; charge.userData.amount = Math.floor(Math.random() * 30) + 20; // 20-50 laser charge scene.add(charge); } scene.remove(enemy); enemies.splice(enemyIndex, 1); // Increase rage meter on kill setRageMeter(prev => { const newRage = Math.min(100, prev + 20); if (newRage >= 100 && !rageActive) { activateRageMode(); } return newRage; }); setScore(prev => { const newScore = prev + 10; // Level atlama kontrolü if (newScore >= level * 50 && level < 5) { setLevel(currentLevel => { const newLevel = currentLevel + 1; // Yeni levelde düşmanları güçlendir enemies.forEach(e => { e.health += 10; }); return newLevel; }); } return newScore; }); if (bossMode && enemies.length === 0) { setGameOver(true); alert('You Won!'); } } } }); }); // Enemy AI enemies.forEach(enemy => { // Enhanced enemy behavior if (enemy.canTeleport && Date.now() - enemy.lastTeleport > enemy.teleportCooldown) { // Teleport near player const angle = Math.random() * Math.PI * 2; const distance = 5 + Math.random() * 5; enemy.position.x = player.position.x + Math.cos(angle) * distance; enemy.position.z = player.position.z + Math.sin(angle) * distance; enemy.lastTeleport = Date.now(); // Add teleport effect const teleportEffect = new THREE.Mesh( new THREE.RingGeometry(0, 1, 32), new THREE.MeshBasicMaterial({ color: 0x800080, transparent: true, opacity: 0.5 }) ); teleportEffect.position.copy(enemy.position); teleportEffect.rotation.x = -Math.PI / 2; scene.add(teleportEffect); setTimeout(() => scene.remove(teleportEffect), 500); } // Berserker rage mode if (enemy.canRage && enemy.health < enemyHealth * 0.5 && !enemy.isRaging) { enemy.isRaging = true; enemy.scale.multiplyScalar(1.3); const material = enemy.children[0].material; material.color.setHex(0xff0000); material.emissive.setHex(0xff0000); material.emissiveIntensity = 0.5; } // Elemental attacks if (enemy.hasElementalPowers && Math.random() < 0.01) { const elementEffect = new THREE.Mesh( new THREE.SphereGeometry(0.3), new THREE.MeshBasicMaterial({ color: enemy.currentElement === 'fire' ? 0xff0000 : enemy.currentElement === 'ice' ? 0x00ffff : 0xffff00 }) ); elementEffect.position.copy(enemy.position); scene.add(elementEffect); const elementDir = new THREE.Vector3(); elementDir.subVectors(player.position, enemy.position).normalize(); elementEffect.velocity = elementDir.multiplyScalar(0.3); bullets.push(elementEffect); } // Necromancer minion summoning if (enemy.canSummonMinions && Date.now() - enemy.lastSummon > 10000) { for (let i = 0; i < enemy.minionCount; i++) { const angle = (i / enemy.minionCount) * Math.PI * 2; const minion = createEnemy('normal'); minion.position.x = enemy.position.x + Math.cos(angle) * 3; minion.position.z = enemy.position.z + Math.sin(angle) * 3; minion.health = enemy.minionHealth; } enemy.lastSummon = Date.now(); } // Skip movement if enemy is stunned if (enemy.stunned && Date.now() - enemy.lastStunTime < enemy.stunDuration) { // Enemy is still stunned, can't move if (Date.now() - enemy.lastStunTime >= enemy.stunDuration) { enemy.stunned = false; // Reset enemy appearance enemy.children.forEach(child => { if (child.material) { child.material.emissive = new THREE.Color(0x000000); child.material.emissiveIntensity = 0; } }); } return; } const direction = new THREE.Vector3(); direction.subVectors(player.position, enemy.position).normalize(); // Check for nearby bullets and dodge if needed const shouldDodge = bullets.some(bullet => { if (bullet.velocity.dot(direction) > 0) return false; // Bullet moving away const distance = bullet.position.distanceTo(enemy.position); return distance < 3 && Math.random() < enemy.dodgeChance; }); if (shouldDodge && Date.now() - enemy.lastDodge > 1000) { enemy.isDodging = true; enemy.lastDodge = Date.now(); // Calculate dodge direction (perpendicular to bullet direction) enemy.dodgeDirection.copy(direction).cross(new THREE.Vector3(0, 1, 0)); if (Math.random() > 0.5) enemy.dodgeDirection.multiplyScalar(-1); } // Update enemy movement const moveDirection = new THREE.Vector3(); if (enemy.isDodging) { moveDirection.copy(enemy.dodgeDirection); if (Date.now() - enemy.lastDodge > 500) { enemy.isDodging = false; } } else { moveDirection.copy(direction); } const typeData = enemyTypes[enemy.type]; const speed = levelData[level].enemySpeed * typeData.speedMod; enemy.position.add(moveDirection.multiplyScalar(speed)); // Enhanced enemy shooting behavior if (enemyTypes[enemy.type].canShoot && Date.now() - (enemy.lastShot || 0) > enemyTypes[enemy.type].shootCooldown && enemy.position.distanceTo(player.position) < enemyTypes[enemy.type].shootRange) { enemy.lastShot = Date.now(); const enemyBulletGeometry = new THREE.SphereGeometry(0.1); const enemyBulletMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 }); const enemyBullet = new THREE.Mesh(enemyBulletGeometry, enemyBulletMaterial); enemyBullet.position.copy(enemy.position); const bulletDirection = new THREE.Vector3(); bulletDirection.subVectors(player.position, enemy.position).normalize(); enemyBullet.velocity = bulletDirection.multiplyScalar(0.3); scene.add(enemyBullet); bullets.push(enemyBullet); } // Check player collision and item collection scene.children.forEach(object => { if (object.userData.type === 'ammo' || object.userData.type === 'laser') { if (object.position.distanceTo(player.position) < 1) { if (object.userData.type === 'ammo') { setBulletCount(prev => Math.min(999, prev + object.userData.amount)); // Cap at 999 bullets } else { setLaserCharge(prev => Math.min(100, prev + object.userData.amount)); // Cap at 100% } scene.remove(object); } } }); if (enemy.position.distanceTo(player.position) < 1) { setHealth(prev => { const newHealth = Math.max(0, prev - 1); if (newHealth <= 0) { // Respawn logic setHealth(100); // Reset player position if (player) { player.position.set(0, 0.5, 0); } // Brief invincibility period player.userData.isInvincible = true; setTimeout(() => { if (player) { player.userData.isInvincible = false; } }, 2000); return 100; isLaserActive = false; setTimeout(() => { alert('Game Over! Final Score: ' + score); }, 100); } return newHealth; }); } }); // Spawn enemies if (!bossMode && Date.now() - lastEnemySpawn > 500 && enemies.length < 80) { // Enhanced enemy type selection with new types const availableTypes = ['normal']; if (level >= 2) availableTypes.push('fast', 'ninja', 'phantom'); if (level >= 3) availableTypes.push('tank', 'giant', 'berserker'); if (level >= 4) availableTypes.push('ranged', 'elite', 'elementalist', 'necromancer'); // Calculate chance for elite enemies based on level const eliteChance = Math.min(0.1 + (level - 1) * 0.05, 0.3); // Up to 30% chance for elite enemies // Chance for stronger enemies // Regular enemy spawn const randomType = availableTypes[Math.floor(Math.random() * availableTypes.length)]; createEnemy(randomType); lastEnemySpawn = Date.now(); // Calculate base spawn weights for each type const spawnWeights = { normal: 1, fast: level >= 2 ? 1.2 : 0, ninja: level >= 2 ? 1.1 : 0, tank: level >= 3 ? 1.3 : 0, giant: level >= 3 ? 1.4 : 0, ranged: level >= 4 ? 1.2 : 0, elite: level >= 4 ? 1.5 : 0 }; // Calculate total weight const totalWeight = Object.entries(spawnWeights) .filter(([type]) => availableTypes.includes(type)) .reduce((sum, [, weight]) => sum + weight, 0); // Random weighted selection let random = Math.random() * totalWeight; let selectedType = 'normal'; for (const [type, weight] of Object.entries(spawnWeights)) { if (availableTypes.includes(type)) { random -= weight; if (random <= 0) { selectedType = type; break; } } } createEnemy(selectedType); lastEnemySpawn = Date.now(); } // Check for boss spawn if (!bossMode && enemies.length === 0 && score >= level * 100) { createBoss(); } // Boss attack patterns if (bossMode && enemies.length > 0) { const boss = enemies[0]; if (Date.now() - boss.lastAttack > boss.attackCooldown) { const ability = boss.abilities[Math.floor(Math.random() * boss.abilities.length)]; switch(ability) { case 'summonMinions': for (let i = 0; i < 3; i++) { createEnemy('normal'); } break; case 'shockwave': const shockwaveGeometry = new THREE.RingGeometry(0, 20, 32); const shockwaveMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, transparent: true, opacity: 0.5 }); const shockwave = new THREE.Mesh(shockwaveGeometry, shockwaveMaterial); shockwave.position.copy(boss.position); shockwave.rotation.x = Math.PI / 2; scene.add(shockwave); // Damage player if in range if (boss.position.distanceTo(player.position) < 10) { setHealth(prev => Math.max(0, prev - 20)); } setTimeout(() => scene.remove(shockwave), 1000); break; case 'laserBeam': const direction = new THREE.Vector3(); direction.subVectors(player.position, boss.position).normalize(); const laserGeometry = new THREE.CylinderGeometry(0.1, 0.1, 20); const laserMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 }); const laser = new THREE.Mesh(laserGeometry, laserMaterial); laser.position.copy(boss.position); laser.lookAt(player.position); laser.rotateX(Math.PI / 2); scene.add(laser); setTimeout(() => scene.remove(laser), 1000); if (player.position.distanceTo(boss.position) < 10) { setHealth(prev => Math.max(0, prev - 15)); } break; } boss.lastAttack = Date.now(); } } // Updated camera follow camera.position.x = player.position.x; camera.position.z = player.position.z + 15; camera.position.y = 25; camera.lookAt(player.position); // Update laser updateLaser(); // Update target position // Update targeting system const closestEnemy = findClosestEnemy(); if (closestEnemy) { targetGroup.position.copy(closestEnemy.position); targetGroup.position.y = 0.5; // Animate targeting elements const time = Date.now() * 0.001; targetGroup.rotation.z = time; // Pulse effect const pulse = Math.sin(time * 5) * 0.2 + 0.8; targetGroup.scale.set(pulse, pulse, 1); targetGroup.visible = true; } else { targetGroup.visible = false; } renderer.render(scene, camera); } }; animate(); // Multiplayer real-time updates const updateInterval = setInterval(() => { if (isMultiplayer && player) { // In a real implementation, this would send to a server const playerState = { position: player.position.clone(), rotation: player.rotation.clone(), health: health, shieldActive: shieldActive, shieldHealth: shieldHealth }; // Update other players (simulation) setOtherPlayers(prev => ({ ...prev, [playerId]: playerState })); } }, 50); // 20 updates per second // Cleanup // Add laser button event listeners laserButton.addEventListener('touchstart', () => { if (laserCharge > 0) { isLaserActive = true; laserMaterial.color.setHSL(Math.random(), 1, 0.5); } else { isLaserActive = false; laser.visible = false; } }); laserButton.addEventListener('touchend', () => { isLaserActive = false; laserMaterial.color.setHex(0xff0000); }); // Add keyboard control for laser document.addEventListener('keydown', (e) => { if (e.key === 'e') { if (laserCharge > 0) { isLaserActive = true; laserMaterial.color.setHex(0x00ff00); } else { isLaserActive = false; laser.visible = false; } } }); document.addEventListener('keyup', (e) => { if (e.key === 'e') { isLaserActive = false; laserMaterial.color.setHex(0xff0000); } }); // Shield controls if (isMultiplayer) { shieldButton.addEventListener('touchstart', activateShield); shieldButton.addEventListener('touchend', deactivateShield); document.addEventListener('keydown', (e) => { if (e.key === 'e') activateShield(); }); document.addEventListener('keyup', (e) => { if (e.key === 'e') deactivateShield(); }); } // Special power activation functions const activateTimeControl = () => { if (!player.userData.timeControlActive) { player.userData.timeControlActive = true; enemies.forEach(enemy => { enemy.userData.originalSpeed = enemy.userData.speed || 0.04; enemy.userData.speed = enemy.userData.originalSpeed * 0.5; }); setTimeout(() => { player.userData.timeControlActive = false; enemies.forEach(enemy => { if (enemy.userData.originalSpeed) { enemy.userData.speed = enemy.userData.originalSpeed; } }); }, 5000); } }; const activateTeleport = () => { if (!player.userData.teleportCooldown) { const direction = new THREE.Vector3(); camera.getWorldDirection(direction); direction.y = 0; direction.normalize(); direction.multiplyScalar(10); player.position.add(direction); // Add teleport effect const teleportEffect = new THREE.Mesh( new THREE.RingGeometry(0, 2, 32), new THREE.MeshBasicMaterial({ color: 0x00ffff, transparent: true, opacity: 0.5 }) ); teleportEffect.position.copy(player.position); teleportEffect.rotation.x = -Math.PI / 2; scene.add(teleportEffect); setTimeout(() => scene.remove(teleportEffect), 500); player.userData.teleportCooldown = true; setTimeout(() => { player.userData.teleportCooldown = false; }, 3000); } }; const activateInvisibility = () => { if (!player.userData.invisibilityActive) { player.userData.invisibilityActive = true; player.children.forEach(child => { if (child.material) { child.material.transparent = true; child.material.opacity = 0.3; } }); setTimeout(() => { player.userData.invisibilityActive = false; player.children.forEach(child => { if (child.material) { child.material.transparent = false; child.material.opacity = 1; } }); }, 5000); } }; const activateElementalPower = () => { if (!player.userData.elementalCooldown) { const elements = ['fire', 'ice', 'lightning']; const element = elements[Math.floor(Math.random() * elements.length)]; const elementalEffect = new THREE.Mesh( new THREE.SphereGeometry(5, 32, 32), new THREE.MeshBasicMaterial({ color: element === 'fire' ? 0xff0000 : element === 'ice' ? 0x00ffff : 0xffff00, transparent: true, opacity: 0.3 }) ); elementalEffect.position.copy(player.position); scene.add(elementalEffect); // Damage nearby enemies enemies.forEach(enemy => { if (enemy.position.distanceTo(player.position) < 5) { enemy.health -= 30; if (element === 'ice') { enemy.userData.frozen = true; setTimeout(() => { enemy.userData.frozen = false; }, 3000); } } }); setTimeout(() => scene.remove(elementalEffect), 1000); player.userData.elementalCooldown = true; setTimeout(() => { player.userData.elementalCooldown = false; }, 8000); } }; return () => { clearInterval(updateInterval); // Clean up renderer if (mountRef.current && renderer) { if (mountRef.current.contains(renderer.domElement)) { mountRef.current.removeChild(renderer.domElement); } renderer.dispose(); } // Clean up control elements if (document.body.contains(joystickArea)) { document.body.removeChild(joystickArea); } if (document.body.contains(shootButton)) { document.body.removeChild(shootButton); } if (document.body.contains(laserButton)) { document.body.removeChild(laserButton); } if (document.body.contains(specialPowersContainer)) { document.body.removeChild(specialPowersContainer); } // Remove event listener window.removeEventListener('resize', handleResize); }; }, [gameOver, gameStarted, selectedCharacter, groundColor]); const [menuState, setMenuState] = useState('main'); // 'main', 'characters', 'settings', 'multiplayer' const [serverStatus, setServerStatus] = useState('disconnected'); // 'disconnected', 'connecting', 'connected' // Local test server connection const connectToTestServer = () => { setServerStatus('connecting'); // Simulate connection delay setTimeout(() => { setServerStatus('connected'); setPlayerId('player_' + Math.random().toString(36).substr(2, 9)); setIsMultiplayer(true); // Only set default character if none is selected if (!selectedCharacter) { setSelectedCharacter('normal'); } setGameStarted(true); }, 1000); }; if (!gameStarted) { return (
{char.description}
{char.description}
/**** * Classes ****/ var Boss = Container.expand(function (level) { var self = Container.call(this); var body = self.attachAsset('boss', { anchorX: 0.5, anchorY: 0.5, tint: 0xff00ff }); self.health = 250 + level * 150; self.maxHealth = self.health; self.speed = 2; self.lastAttack = 0; self.attackCooldown = 3000; self.phase = 1; self.lastX = self.x; self.lastY = self.y; self.update = function () { self.lastX = self.x; self.lastY = self.y; // Move towards player if (player) { var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 200) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } } // Boss attacks if (LK.ticks - self.lastAttack > self.attackCooldown) { self.performAttack(); self.lastAttack = LK.ticks; } // Phase transitions if (self.health < self.maxHealth * 0.5 && self.phase === 1) { self.phase = 2; self.attackCooldown = 2000; body.tint = 0xff0000; } }; self.performAttack = function () { var attack = Math.floor(Math.random() * 3); switch (attack) { case 0: // Bullet spray for (var i = 0; i < 8; i++) { var angle = i / 8 * Math.PI * 2; var bullet = new Bullet(20, 0xff0000, 6); bullet.x = self.x; bullet.y = self.y; bullet.velocityX = Math.cos(angle) * bullet.speed; bullet.velocityY = Math.sin(angle) * bullet.speed; enemyBullets.push(bullet); game.addChild(bullet); } break; case 1: // Laser beam if (player) { var laser = self.attachAsset('laser', { anchorX: 0.5, anchorY: 0.5, tint: 0xff0000 }); var angle = Math.atan2(player.y - self.y, player.x - self.x); laser.rotation = angle; LK.setTimeout(function () { laser.destroy(); }, 1000); } break; case 2: // Summon minions for (var i = 0; i < 3; i++) { var minion = new Enemy('normal', currentLevel); minion.x = self.x + (Math.random() - 0.5) * 200; minion.y = self.y + (Math.random() - 0.5) * 200; enemies.push(minion); game.addChild(minion); } break; } }; self.takeDamage = function (damage) { self.health -= damage; LK.effects.flashObject(self, 0xffffff, 200); if (self.health <= 0) { self.die(); } }; self.die = function () { createExplosion(self.x, self.y, 300); LK.setScore(LK.getScore() + 1000); bossMode = false; self.destroy(); }; return self; }); var Bullet = Container.expand(function (damage, color, speed, abilities) { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5, tint: color || 0xffff00 }); self.damage = damage || 10; self.speed = speed || 12; self.abilities = abilities || {}; self.bounceCount = 0; self.maxBounces = 3; self.lastX = self.x; self.lastY = self.y; self.update = function () { self.lastX = self.x; self.lastY = self.y; self.y += self.velocityY; self.x += self.velocityX; // Bouncing bullets if (self.abilities.bouncingBullets && self.bounceCount < self.maxBounces) { if (self.x < 0 || self.x > 2048) { self.velocityX *= -1; self.bounceCount++; } if (self.y < 0 || self.y > 2732) { self.velocityY *= -1; self.bounceCount++; } } // Remove bullet if out of bounds if (self.x < -100 || self.x > 2148 || self.y < -100 || self.y > 2832) { self.destroy(); } }; return self; }); var Character = Container.expand(function (characterType) { var self = Container.call(this); var characterData = characters[characterType] || characters.normal; var body = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5, tint: characterData.color }); self.characterType = characterType; self.health = characterData.health || 100; self.maxHealth = self.health; self.bulletSpeed = characterData.bulletSpeed; self.bulletDamage = characterData.bulletDamage; self.bulletColor = characterData.bulletColor; self.speed = 8; self.lastShot = 0; self.shootCooldown = 200; self.rageMode = false; self.rageMeter = 0; self.invincible = false; // Special abilities self.abilities = { trackingBullets: characterData.trackingBullets || false, spreadShot: characterData.spreadShot || false, piercing: characterData.piercing || false, explosiveShot: characterData.explosiveShot || false, rapidFire: characterData.rapidFire || false, timeControl: characterData.timeControl || false, teleport: characterData.teleport || false, invisibility: characterData.invisibility || false }; self.activateRage = function () { if (self.rageMeter >= 100) { self.rageMode = true; self.rageMeter = 0; body.tint = 0xffff00; self.scale.set(1.5, 1.5); LK.setTimeout(function () { self.rageMode = false; body.tint = characterData.color; self.scale.set(1, 1); }, 10000); } }; return self; }); var Enemy = Container.expand(function (enemyType, level) { var self = Container.call(this); var enemyData = enemyTypes[enemyType] || enemyTypes.normal; var body = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5, tint: enemyData.color, scaleX: enemyData.sizeMod || 1, scaleY: enemyData.sizeMod || 1 }); self.enemyType = enemyType; self.health = (30 + level * 10) * (enemyData.healthMod || 1); self.maxHealth = self.health; self.speed = (3 + level * 0.5) * (enemyData.speedMod || 1); self.dodgeChance = enemyData.dodgeChance || 0; self.lastDodge = 0; self.isDodging = false; self.dodgeDirection = { x: 0, y: 0 }; self.stunned = false; self.lastStun = 0; self.stunDuration = 0; self.lastShot = 0; self.lastX = self.x; self.lastY = self.y; // Special abilities self.canShoot = enemyData.canShoot || false; self.shootRange = enemyData.shootRange || 300; self.shootCooldown = enemyData.shootCooldown || 2000; self.explodeOnDeath = enemyData.explodeOnDeath || false; self.splitOnDeath = enemyData.splitOnDeath || false; self.update = function () { self.lastX = self.x; self.lastY = self.y; if (self.stunned && LK.ticks - self.lastStun < self.stunDuration) { return; } if (self.stunned) { self.stunned = false; body.tint = enemyData.color; } // Move towards player if (player && !self.isDodging) { var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } } // Dodge bullets if (Math.random() < self.dodgeChance && LK.ticks - self.lastDodge > 60) { self.isDodging = true; self.lastDodge = LK.ticks; self.dodgeDirection.x = (Math.random() - 0.5) * 2; self.dodgeDirection.y = (Math.random() - 0.5) * 2; LK.setTimeout(function () { self.isDodging = false; }, 500); } if (self.isDodging) { self.x += self.dodgeDirection.x * self.speed; self.y += self.dodgeDirection.y * self.speed; } // Enemy shooting if (self.canShoot && player && LK.ticks - self.lastShot > self.shootCooldown) { var distance = Math.sqrt(Math.pow(player.x - self.x, 2) + Math.pow(player.y - self.y, 2)); if (distance < self.shootRange) { self.shoot(); self.lastShot = LK.ticks; } } // Keep enemy on screen self.x = Math.max(30, Math.min(2018, self.x)); self.y = Math.max(30, Math.min(2702, self.y)); }; self.shoot = function () { if (player) { var bullet = new Bullet(15, 0xff0000, 8); bullet.x = self.x; bullet.y = self.y; var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); bullet.velocityX = dx / distance * bullet.speed; bullet.velocityY = dy / distance * bullet.speed; enemyBullets.push(bullet); game.addChild(bullet); } }; self.takeDamage = function (damage) { self.health -= damage; LK.effects.flashObject(self, 0xffffff, 200); if (self.health <= 0) { self.die(); } }; self.die = function () { if (self.explodeOnDeath) { createExplosion(self.x, self.y, 150); } if (self.splitOnDeath) { for (var i = 0; i < 3; i++) { var childEnemy = new Enemy('normal', currentLevel); childEnemy.x = self.x + (Math.random() - 0.5) * 100; childEnemy.y = self.y + (Math.random() - 0.5) * 100; childEnemy.scale.set(0.6, 0.6); enemies.push(childEnemy); game.addChild(childEnemy); } } // Drop power-ups if (Math.random() < 0.3) { createPowerUp(self.x, self.y); } LK.getSound('explosion').play(); self.destroy(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2d572c }); /**** * Game Code ****/ // UI Elements var healthText = new Text2('Health: 100', { size: 40, fill: 0xFFFFFF }); healthText.anchor.set(0, 0); LK.gui.topLeft.addChild(healthText); var scoreText = new Text2('Score: 0', { size: 40, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); var bulletText = new Text2('Bullets: 100', { size: 30, fill: 0xFFFF00 }); bulletText.anchor.set(0, 0); bulletText.y = 50; LK.gui.topLeft.addChild(bulletText); var laserText = new Text2('Laser: 100%', { size: 30, fill: 0x00FFFF }); laserText.anchor.set(0, 0); laserText.y = 90; LK.gui.topLeft.addChild(laserText); var levelText = new Text2('Level: 1', { size: 50, fill: 0xFFD700 }); levelText.anchor.set(1, 0); LK.gui.topRight.addChild(levelText); var rageText = new Text2('RAGE MODE!', { size: 60, fill: 0xFF0000 }); rageText.anchor.set(0.5, 0.5); rageText.visible = false; LK.gui.center.addChild(rageText); var characters = { normal: { name: "Normal", color: 0x0055ff, bulletSpeed: 1.0, bulletDamage: 10, bulletColor: 0xffff00, health: 100 }, laserMaster: { name: "Laser Master", color: 0xff00ff, bulletSpeed: 0.8, bulletDamage: 5, bulletColor: 0xff00ff, health: 100, superLaser: true }, ranged: { name: "Ranged", color: 0xff5500, bulletSpeed: 1.2, bulletDamage: 8, bulletColor: 0xff5500, health: 100, trackingBullets: true }, close: { name: "Close Combat", color: 0x00ff55, bulletSpeed: 0.8, bulletDamage: 15, bulletColor: 0x00ff55, health: 100, spreadShot: true }, sniper: { name: "Sniper", color: 0x9900ff, bulletSpeed: 2.0, bulletDamage: 25, bulletColor: 0x9900ff, health: 100, piercing: true }, explosive: { name: "Explosive", color: 0xff0000, bulletSpeed: 0.7, bulletDamage: 12, bulletColor: 0xff0000, health: 100, explosiveShot: true }, rapid: { name: "Rapid Fire", color: 0x00ffff, bulletSpeed: 1.5, bulletDamage: 5, bulletColor: 0x00ffff, health: 100, rapidFire: true, bouncingBullets: true }, timemaster: { name: "Time Master", color: 0x00ffcc, bulletSpeed: 1.2, bulletDamage: 15, bulletColor: 0x00ffcc, health: 100, timeControl: true }, teleporter: { name: "Teleporter", color: 0xff00ff, bulletSpeed: 1.3, bulletDamage: 12, bulletColor: 0xff00ff, health: 100, teleport: true }, shadow: { name: "Shadow Warrior", color: 0x4a0080, bulletSpeed: 1.6, bulletDamage: 15, bulletColor: 0x800080, health: 100, invisibility: true }, shocktank: { name: "Shock Tank", color: 0x4169e1, bulletSpeed: 0.7, bulletDamage: 25, bulletColor: 0x4682b4, health: 150, shockwave: true }, ultimate: { name: "Ultimate", color: 0xffd700, bulletSpeed: 1.8, bulletDamage: 20, bulletColor: 0xffd700, health: 150, trackingBullets: true, spreadShot: true, piercing: true, explosiveShot: true, rapidFire: true, bouncingBullets: true } }; // Start game if (!gameStarted) { showCharacterSelect(); } var enemyTypes = { normal: { color: 0xff3333, speedMod: 1.0, healthMod: 1.0, dodgeChance: 0.1, sizeMod: 1.0 }, fast: { color: 0x33ff33, speedMod: 1.5, healthMod: 0.8, dodgeChance: 0.3, sizeMod: 0.8 }, tank: { color: 0x3333ff, speedMod: 0.6, healthMod: 2.0, dodgeChance: 0.05, sizeMod: 1.5 }, bomber: { color: 0xff6600, speedMod: 1.2, healthMod: 0.7, dodgeChance: 0.1, sizeMod: 1.0, explodeOnDeath: true }, sniper: { color: 0x9900ff, speedMod: 0.7, healthMod: 1.0, dodgeChance: 0.4, sizeMod: 1.0, canShoot: true, shootRange: 400, shootCooldown: 2000 }, splitter: { color: 0x00ffaa, speedMod: 0.9, healthMod: 1.2, dodgeChance: 0.2, sizeMod: 1.2, splitOnDeath: true }, elite: { color: 0xffa500, speedMod: 1.1, healthMod: 1.8, dodgeChance: 0.3, sizeMod: 1.4 } }; var currentLevel = 1; var levelData = { 1: { enemySpeed: 3, enemyHealth: 30, bossHealth: 250, backgroundColor: 0x2d572c }, 2: { enemySpeed: 4, enemyHealth: 40, bossHealth: 400, backgroundColor: 0x654321 }, 3: { enemySpeed: 5, enemyHealth: 50, bossHealth: 550, backgroundColor: 0x808080 }, 4: { enemySpeed: 6, enemyHealth: 60, bossHealth: 700, backgroundColor: 0x800080 }, 5: { enemySpeed: 7, enemyHealth: 70, bossHealth: 850, backgroundColor: 0xff4500 } }; var player = null; var bullets = []; var enemyBullets = []; var enemies = []; var powerUps = []; var selectedCharacter = 'normal'; var bossMode = false; var gameStarted = false; var bulletCount = 100; var laserCharge = 100; var rageMeter = 0; var rageActive = false; var health = 100; var shieldActive = false; var enemySpawnTimer = 0; var lastPowerUpSpawn = 0; function showCharacterSelect() { var selectContainer = new Container(); selectContainer.x = 1024; selectContainer.y = 1366; var titleText = new Text2('SELECT CHARACTER', { size: 80, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.y = -400; selectContainer.addChild(titleText); var characterKeys = Object.keys(characters); var buttonsPerRow = 3; var buttonWidth = 300; var buttonHeight = 150; var spacing = 50; for (var i = 0; i < characterKeys.length; i++) { var key = characterKeys[i]; var _char = characters[key]; var row = Math.floor(i / buttonsPerRow); var col = i % buttonsPerRow; var button = new Container(); button.x = (col - 1) * (buttonWidth + spacing); button.y = (row - 1) * (buttonHeight + spacing); var buttonBg = LK.getAsset('player', { anchorX: 0.5, anchorY: 0.5, scaleX: 3, scaleY: 2, tint: _char.color }); button.addChild(buttonBg); var buttonText = new Text2(_char.name, { size: 30, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); button.addChild(buttonText); button.characterKey = key; button.interactive = true; button.down = function () { selectedCharacter = this.characterKey; startGame(); }; selectContainer.addChild(button); } game.addChild(selectContainer); } function startGame() { gameStarted = true; game.removeChildren(); // Create player player = new Character(selectedCharacter); player.x = 1024; player.y = 1366; game.addChild(player); // Start background music LK.playMusic('background'); // Initialize enemy spawn timer enemySpawnTimer = 0; lastPowerUpSpawn = 0; // Update UI updateUI(); } function updateUI() { healthText.setText('Health: ' + health); scoreText.setText('Score: ' + LK.getScore()); bulletText.setText('Bullets: ' + bulletCount); laserText.setText('Laser: ' + laserCharge + '%'); levelText.setText('Level: ' + currentLevel); rageText.visible = rageActive; } function createPowerUp(x, y) { var powerUp = new Container(); powerUp.x = x; powerUp.y = y; var types = ['health', 'bullets', 'laser', 'rage']; var type = types[Math.floor(Math.random() * types.length)]; var colors = { health: 0xff0000, bullets: 0xffff00, laser: 0x00ffff, rage: 0xff00ff }; var powerUpGraphics = powerUp.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5, tint: colors[type] }); powerUp.powerUpType = type; powerUp.lastY = y; powerUps.push(powerUp); game.addChild(powerUp); // Remove after 10 seconds LK.setTimeout(function () { if (powerUps.indexOf(powerUp) !== -1) { powerUps.splice(powerUps.indexOf(powerUp), 1); powerUp.destroy(); } }, 10000); } function createExplosion(x, y, size) { var explosion = new Container(); explosion.x = x; explosion.y = y; var explosionGraphics = explosion.attachAsset('explosion', { anchorX: 0.5, anchorY: 0.5, scaleX: size / 120, scaleY: size / 120 }); game.addChild(explosion); LK.getSound('explosion').play(); // Animate explosion tween.to(explosionGraphics, { alpha: 0, scaleX: explosionGraphics.scaleX * 2, scaleY: explosionGraphics.scaleY * 2 }, 500).onComplete(function () { explosion.destroy(); }); // Damage nearby enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; var distance = Math.sqrt(Math.pow(enemy.x - x, 2) + Math.pow(enemy.y - y, 2)); if (distance < size) { enemy.takeDamage(30); } } // Damage player if close if (player) { var playerDistance = Math.sqrt(Math.pow(player.x - x, 2) + Math.pow(player.y - y, 2)); if (playerDistance < size && !player.invincible) { health -= 20; if (health <= 0) { gameOver(); } } } } function spawnEnemy() { var availableTypes = ['normal', 'fast']; if (currentLevel >= 2) availableTypes.push('tank', 'bomber'); if (currentLevel >= 3) availableTypes.push('sniper', 'splitter'); if (currentLevel >= 4) availableTypes.push('elite'); var type = availableTypes[Math.floor(Math.random() * availableTypes.length)]; var enemy = new Enemy(type, currentLevel); // Spawn from edges var side = Math.floor(Math.random() * 4); switch (side) { case 0: // Top enemy.x = Math.random() * 2048; enemy.y = -50; break; case 1: // Right enemy.x = 2098; enemy.y = Math.random() * 2732; break; case 2: // Bottom enemy.x = Math.random() * 2048; enemy.y = 2782; break; case 3: // Left enemy.x = -50; enemy.y = Math.random() * 2732; break; } enemies.push(enemy); game.addChild(enemy); } function spawnBoss() { bossMode = true; // Clear existing enemies for (var i = enemies.length - 1; i >= 0; i--) { enemies[i].destroy(); } enemies = []; var boss = new Boss(currentLevel); boss.x = 1024; boss.y = 300; enemies.push(boss); game.addChild(boss); } function gameOver() { gameStarted = false; LK.stopMusic(); var gameOverText = new Text2('GAME OVER', { size: 100, fill: 0xFF0000 }); gameOverText.anchor.set(0.5, 0.5); gameOverText.x = 1024; gameOverText.y = 1366; game.addChild(gameOverText); var finalScoreText = new Text2('Final Score: ' + LK.getScore(), { size: 50, fill: 0xFFFFFF }); finalScoreText.anchor.set(0.5, 0.5); finalScoreText.x = 1024; finalScoreText.y = 1466; game.addChild(finalScoreText); LK.setTimeout(function () { LK.showGameOver(); }, 3000); } function findClosestEnemy() { if (!player || enemies.length === 0) return null; var closest = null; var minDistance = Infinity; for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var distance = Math.sqrt(Math.pow(enemy.x - player.x, 2) + Math.pow(enemy.y - player.y, 2)); if (distance < minDistance) { minDistance = distance; closest = enemy; } } return closest; } function shootBullet() { if (!player || bulletCount <= 0) return; var _char2 = characters[selectedCharacter]; bulletCount--; if (_char2.spreadShot) { // Spread shot for (var i = -1; i <= 1; i++) { var bullet = new Bullet(_char2.bulletDamage, _char2.bulletColor, _char2.bulletSpeed * 12, _char2); bullet.x = player.x; bullet.y = player.y - 40; bullet.velocityX = i * 3; bullet.velocityY = -bullet.speed; bullets.push(bullet); game.addChild(bullet); } } else if (_char2.trackingBullets) { // Tracking bullets var target = findClosestEnemy(); if (target) { var bullet = new Bullet(_char2.bulletDamage, _char2.bulletColor, _char2.bulletSpeed * 12, _char2); bullet.x = player.x; bullet.y = player.y - 40; var dx = target.x - bullet.x; var dy = target.y - bullet.y; var distance = Math.sqrt(dx * dx + dy * dy); bullet.velocityX = dx / distance * bullet.speed; bullet.velocityY = dy / distance * bullet.speed; bullets.push(bullet); game.addChild(bullet); } } else { // Normal shot var bullet = new Bullet(_char2.bulletDamage, _char2.bulletColor, _char2.bulletSpeed * 12, _char2); bullet.x = player.x; bullet.y = player.y - 40; bullet.velocityX = 0; bullet.velocityY = -bullet.speed; bullets.push(bullet); game.addChild(bullet); } LK.getSound('shoot').play(); rageMeter = Math.min(100, rageMeter + 5); if (rageMeter >= 100 && !rageActive) { player.activateRage(); rageActive = true; } } function fireLaser() { if (!player || laserCharge <= 0) return; var laser = new Container(); laser.x = player.x; laser.y = player.y - 40; var laserGraphics = laser.attachAsset('laser', { anchorX: 0.5, anchorY: 1, tint: 0x00ffff }); game.addChild(laser); LK.getSound('laser').play(); // Damage enemies in laser path for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (Math.abs(enemy.x - laser.x) < 40 && enemy.y < laser.y) { enemy.takeDamage(50); } } laserCharge -= 20; LK.setTimeout(function () { laser.destroy(); }, 200); } // Touch controls var moveDirection = { x: 0, y: 0 }; var shooting = false; var lastShot = 0; var laserActive = false; game.down = function (x, y) { if (!gameStarted) return; // Check if touching shoot area (right side) if (x > 1536) { shooting = true; } else if (x > 1024 && y > 2300) { // Laser button area (bottom right) laserActive = true; } else { // Movement area (left side) if (player) { moveDirection.x = (x - player.x) * 0.1; moveDirection.y = (y - player.y) * 0.1; } } }; game.move = function (x, y) { if (!gameStarted) return; if (x <= 1536 && player) { moveDirection.x = (x - player.x) * 0.1; moveDirection.y = (y - player.y) * 0.1; } }; game.up = function () { shooting = false; laserActive = false; moveDirection = { x: 0, y: 0 }; }; // Add keyboard state tracking var keyState = { w: false, a: false, s: false, d: false, space: false, e: false }; // Keyboard event listeners LK.on('keydown', function (key) { keyState[key] = true; }); LK.on('keyup', function (key) { keyState[key] = false; }); game.update = function () { if (!gameStarted) return; // Player movement if (player) { // Keyboard movement if (keyState.w) player.y -= 8; if (keyState.s) player.y += 8; if (keyState.a) player.x -= 8; if (keyState.d) player.x += 8; // Touch movement player.x += moveDirection.x; player.y += moveDirection.y; // Keep player on screen player.x = Math.max(40, Math.min(2008, player.x)); player.y = Math.max(40, Math.min(2692, player.y)); // Auto-shoot if touching shoot area or pressing space if ((shooting || keyState.space) && LK.ticks - lastShot > 10) { shootBullet(); lastShot = LK.ticks; } // Laser controls if ((laserActive || keyState.e) && LK.ticks % 5 === 0) { fireLaser(); } } // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; var bulletHit = false; // Check collision with enemies for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (bullet.intersects(enemy)) { var damageAmount = bullet.damage * (rageActive ? 2 : 1); enemy.takeDamage(damageAmount); // Explosive bullets if (bullet.abilities.explosiveShot) { createExplosion(bullet.x, bullet.y, 100); } // Piercing bullets don't get destroyed if (!bullet.abilities.piercing) { bullet.destroy(); bullets.splice(i, 1); bulletHit = true; } if (enemy.health <= 0) { enemies.splice(j, 1); LK.setScore(LK.getScore() + 10); rageMeter = Math.min(100, rageMeter + 10); } if (bulletHit) break; } } } // Update enemy bullets for (var i = enemyBullets.length - 1; i >= 0; i--) { var bullet = enemyBullets[i]; // Check collision with player if (player && bullet.intersects(player) && !player.invincible) { health -= 10; bullet.destroy(); enemyBullets.splice(i, 1); if (health <= 0) { gameOver(); } } // Remove if off screen if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) { bullet.destroy(); enemyBullets.splice(i, 1); } } // Update power-ups for (var i = powerUps.length - 1; i >= 0; i--) { var powerUp = powerUps[i]; // Check collision with player if (player && powerUp.intersects(player)) { switch (powerUp.powerUpType) { case 'health': health = Math.min(100, health + 25); break; case 'bullets': bulletCount = Math.min(999, bulletCount + 50); break; case 'laser': laserCharge = Math.min(100, laserCharge + 30); break; case 'rage': rageMeter = Math.min(100, rageMeter + 50); break; } LK.getSound('powerup').play(); powerUp.destroy(); powerUps.splice(i, 1); } } // Enemy collision with player if (player && !player.invincible) { for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.intersects(player)) { health -= 1; LK.effects.flashObject(player, 0xff0000, 100); if (health <= 0) { gameOver(); } } } } // Spawn enemies if (enemySpawnTimer > 0) { enemySpawnTimer--; } else { if (enemies.length < 15 && !bossMode) { spawnEnemy(); enemySpawnTimer = 60 - currentLevel * 5; } } // Spawn power-ups if (LK.ticks - lastPowerUpSpawn > 900) { // Every 15 seconds var x = Math.random() * 1800 + 124; var y = Math.random() * 1800 + 466; createPowerUp(x, y); lastPowerUpSpawn = LK.ticks; } // Check for boss spawn if (!bossMode && enemies.length === 0 && LK.getScore() >= currentLevel * 100) { spawnBoss(); } // Level progression if (bossMode && enemies.length === 0) { currentLevel++; if (currentLevel > 5) { // Victory! LK.showYouWin(); } else { bossMode = false; game.setBackgroundColor(levelData[currentLevel].backgroundColor); } } // Regenerate resources over time if (LK.ticks % 60 === 0) { // Every second bulletCount = Math.min(999, bulletCount + 2); laserCharge = Math.min(100, laserCharge + 1); if (rageActive) { rageMeter = Math.max(0, rageMeter - 2); if (rageMeter <= 0) { rageActive = false; } } } // Update UI updateUI(); // Create mobile control UI elements if (LK.ticks === 1) { // Shoot button var shootButtonBg = LK.getAsset('player', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2, tint: 0xff0000, alpha: 0.3 }); shootButtonBg.x = 1700; shootButtonBg.y = 2400; LK.gui.center.addChild(shootButtonBg); // Laser button var laserButtonBg = LK.getAsset('player', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2, tint: 0x00ffff, alpha: 0.3 }); laserButtonBg.x = 1900; laserButtonBg.y = 2400; LK.gui.center.addChild(laserButtonBg); // Movement area indicator var moveArea = LK.getAsset('player', { anchorX: 0.5, anchorY: 0.5, scaleX: 8, scaleY: 12, tint: 0x555555, alpha: 0.1 }); moveArea.x = 400; moveArea.y = 1366; LK.gui.center.addChild(moveArea); } };
===================================================================
--- original.js
+++ change.js
@@ -446,8 +446,17 @@
bulletColor: 0x800080,
health: 100,
invisibility: true
},
+ shocktank: {
+ name: "Shock Tank",
+ color: 0x4169e1,
+ bulletSpeed: 0.7,
+ bulletDamage: 25,
+ bulletColor: 0x4682b4,
+ health: 150,
+ shockwave: true
+ },
ultimate: {
name: "Ultimate",
color: 0xffd700,
bulletSpeed: 1.8,
@@ -872,13 +881,17 @@
y: 0
};
var shooting = false;
var lastShot = 0;
+var laserActive = false;
game.down = function (x, y) {
if (!gameStarted) return;
// Check if touching shoot area (right side)
if (x > 1536) {
shooting = true;
+ } else if (x > 1024 && y > 2300) {
+ // Laser button area (bottom right)
+ laserActive = true;
} else {
// Movement area (left side)
if (player) {
moveDirection.x = (x - player.x) * 0.1;
@@ -894,50 +907,81 @@
}
};
game.up = function () {
shooting = false;
+ laserActive = false;
moveDirection = {
x: 0,
y: 0
};
};
+// Add keyboard state tracking
+var keyState = {
+ w: false,
+ a: false,
+ s: false,
+ d: false,
+ space: false,
+ e: false
+};
+// Keyboard event listeners
+LK.on('keydown', function (key) {
+ keyState[key] = true;
+});
+LK.on('keyup', function (key) {
+ keyState[key] = false;
+});
game.update = function () {
if (!gameStarted) return;
// Player movement
if (player) {
+ // Keyboard movement
+ if (keyState.w) player.y -= 8;
+ if (keyState.s) player.y += 8;
+ if (keyState.a) player.x -= 8;
+ if (keyState.d) player.x += 8;
+ // Touch movement
player.x += moveDirection.x;
player.y += moveDirection.y;
// Keep player on screen
player.x = Math.max(40, Math.min(2008, player.x));
player.y = Math.max(40, Math.min(2692, player.y));
- // Auto-shoot if touching shoot area
- if (shooting && LK.ticks - lastShot > 10) {
+ // Auto-shoot if touching shoot area or pressing space
+ if ((shooting || keyState.space) && LK.ticks - lastShot > 10) {
shootBullet();
lastShot = LK.ticks;
}
+ // Laser controls
+ if ((laserActive || keyState.e) && LK.ticks % 5 === 0) {
+ fireLaser();
+ }
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
+ var bulletHit = false;
// Check collision with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
- enemy.takeDamage(bullet.damage * (rageActive ? 2 : 1));
+ var damageAmount = bullet.damage * (rageActive ? 2 : 1);
+ enemy.takeDamage(damageAmount);
// Explosive bullets
if (bullet.abilities.explosiveShot) {
createExplosion(bullet.x, bullet.y, 100);
}
// Piercing bullets don't get destroyed
if (!bullet.abilities.piercing) {
bullet.destroy();
bullets.splice(i, 1);
+ bulletHit = true;
}
if (enemy.health <= 0) {
enemies.splice(j, 1);
LK.setScore(LK.getScore() + 10);
+ rageMeter = Math.min(100, rageMeter + 10);
}
- break;
+ if (bulletHit) break;
}
}
}
// Update enemy bullets
@@ -1040,13 +1084,44 @@
}
}
// Update UI
updateUI();
- // Special ability for laser button
- if (LK.ticks % 30 === 0) {
- // Check every half second
- // Simulate laser button press for testing
- if (Math.random() < 0.1) {
- fireLaser();
- }
+ // Create mobile control UI elements
+ if (LK.ticks === 1) {
+ // Shoot button
+ var shootButtonBg = LK.getAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 1.2,
+ scaleY: 1.2,
+ tint: 0xff0000,
+ alpha: 0.3
+ });
+ shootButtonBg.x = 1700;
+ shootButtonBg.y = 2400;
+ LK.gui.center.addChild(shootButtonBg);
+ // Laser button
+ var laserButtonBg = LK.getAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 1.2,
+ scaleY: 1.2,
+ tint: 0x00ffff,
+ alpha: 0.3
+ });
+ laserButtonBg.x = 1900;
+ laserButtonBg.y = 2400;
+ LK.gui.center.addChild(laserButtonBg);
+ // Movement area indicator
+ var moveArea = LK.getAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 8,
+ scaleY: 12,
+ tint: 0x555555,
+ alpha: 0.1
+ });
+ moveArea.x = 400;
+ moveArea.y = 1366;
+ LK.gui.center.addChild(moveArea);
}
};
\ No newline at end of file