// server.js - سيرفر لعبة حرب الدبابات أونلاين const express = require('express'); const http = require('http'); const socketIO = require('socket.io'); const path = require('path'); const app = express(); const server = http.createServer(app); const io = socketIO(server, { cors: { origin: "*", methods: ["GET", "POST"] } }); // خدمة الملفات الثابتة (HTML, CSS, JS) app.use(express.static(path.join(__dirname, 'public'))); // تخزين الغرف واللاعبين let rooms = {}; let waitingPlayers = []; // دالة لإنشاء Seed فريد للخريطة function generateTerrainSeed() { return { seed1: Math.random() * 100, seed2: Math.random() * 100, amplitudes: { amplitude1: 100, amplitude2: 50, freq1: 0.002, freq2: 0.01 } }; } // دالة لمعالجة اختيارات الخريطة function getTerrainSettings(mapType) { const settings = { amplitude1: 100, amplitude2: 50, freq1: 0.002 }; if (mapType === 'desert') { settings.amplitude1 = 60; settings.amplitude2 = 20; settings.freq1 = 0.001; } else if (mapType === 'snow') { settings.amplitude1 = 150; settings.amplitude2 = 60; settings.freq1 = 0.003; } else if (mapType === 'moon') { settings.amplitude1 = 40; settings.amplitude2 = 80; settings.freq1 = 0.005; } return settings; } // عند اتصال لاعب جديد io.on('connection', (socket) => { console.log('🎮 لاعب اتصل:', socket.id); // استقبال طلب الانضمام للعبة socket.on('joinGame', (data) => { const mapType = data.mapType || 'forest'; const playerSkin = data.playerSkin || 'classic'; // ابحث عن غرفة فارغة أو أنشئ واحدة جديدة let roomId = null; let playerNum = 1; for (let id in rooms) { if (rooms[id].players.length === 1) { roomId = id; playerNum = 2; break; } } if (!roomId) { roomId = 'room_' + Date.now() + '_' + Math.random(); rooms[roomId] = { players: [], mapType: mapType, terrainSeed: generateTerrainSeed(), terrainSettings: getTerrainSettings(mapType), currentTurn: 1, gameState: 'WAITING', player1Data: null, player2Data: null }; playerNum = 1; } // أضف اللاعب للغرفة socket.join(roomId); rooms[roomId].players.push(socket.id); // احفظ بيانات اللاعب if (playerNum === 1) { rooms[roomId].player1Data = { socketId: socket.id, skin: playerSkin, x: 300, health: 100, fuel: 100 }; } else { rooms[roomId].player2Data = { socketId: socket.id, skin: playerSkin, x: 2700, health: 100, fuel: 100 }; } // أرسل للاعب معرّف الغرفة ورقم اللاعب socket.emit('playerAssigned', { playerNum: playerNum, roomId: roomId, terrainSeed: rooms[roomId].terrainSeed, terrainSettings: rooms[roomId].terrainSettings, mapType: mapType }); if (playerNum === 1) { socket.emit('waitingForPlayer', { message: 'في انتظار لاعب ثاني...' }); } else { // اللاعب الثاني دخل، الآن الغرفة جاهزة rooms[roomId].gameState = 'PLAYING'; io.to(roomId).emit('gameStart', { player1Skin: rooms[roomId].player1Data.skin, player2Skin: rooms[roomId].player2Data.skin, mapType: mapType }); } // عند قطع الاتصال socket.on('disconnect', () => { console.log('❌ لاعب قطع الاتصال:', socket.id); socket.leave(roomId); if (rooms[roomId]) { rooms[roomId].players = rooms[roomId].players.filter(id => id !== socket.id); if (rooms[roomId].players.length === 0) { delete rooms[roomId]; } else { // أخبر اللاعب الآخر أن خصمه غادر io.to(roomId).emit('playerDisconnected', { message: 'اللاعب الآخر قطع الاتصال' }); } } }); // استقبال حركة الدبابة socket.on('playerMove', (data) => { if (rooms[roomId]) { // مرر الحركة للاعب الآخر socket.to(roomId).emit('enemyMoved', { playerNum: playerNum === 1 ? 1 : 2, x: data.x, fuel: data.fuel }); // احفظ البيانات الحالية if (playerNum === 1) { rooms[roomId].player1Data.x = data.x; rooms[roomId].player1Data.fuel = data.fuel; } else { rooms[roomId].player2Data.x = data.x; rooms[roomId].player2Data.fuel = data.fuel; } } }); // استقبال الإطلاق (إطلاق القذيفة) socket.on('playerFire', (data) => { if (rooms[roomId]) { // مرر بيانات الإطلاق للاعب الآخر socket.to(roomId).emit('enemyFired', { playerNum: playerNum === 1 ? 1 : 2, angle: data.angle, power: data.power, x: data.x, y: data.y }); } }); // استقبال إصابة (ضرر على دبابة) socket.on('damageDealt', (data) => { if (rooms[roomId]) { socket.to(roomId).emit('takeDamage', { damage: data.damage, health: data.targetHealth }); // احفظ الصحة if (playerNum === 1) { rooms[roomId].player2Data.health = data.targetHealth; } else { rooms[roomId].player1Data.health = data.targetHealth; } } }); // استقبال نهاية الدور socket.on('turnEnd', (data) => { if (rooms[roomId]) { rooms[roomId].currentTurn = rooms[roomId].currentTurn === 1 ? 2 : 1; // أخبر كلا اللاعبين أن الدور انتهى io.to(roomId).emit('nextTurn', { currentTurn: rooms[roomId].currentTurn }); } }); // استقبال انتهاء اللعبة socket.on('gameOver', (data) => { if (rooms[roomId]) { io.to(roomId).emit('gameEnded', { winner: data.winner, winnerName: playerNum === 1 ? 'اللاعب الأول' : 'اللاعب الثاني' }); // احذف الغرفة setTimeout(() => { delete rooms[roomId]; }, 5000); } }); }); }); // بدء السيرفر const PORT = process.env.PORT || 7860; server.listen(PORT, () => { console.log(`🚀 سيرفر لعبة حرب الدبابات يعمل على المنفذ ${PORT}`); console.log(`📍 الرابط: http://localhost:${PORT}`); });