Spaces:
Configuration error
Configuration error
| // 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}`); | |
| }); | |