-
Notifications
You must be signed in to change notification settings - Fork 319
Open
Description
using System;
using System.Collections.Generic;
using System.Linq;
namespace VectorRunner
{
// =============== CORE GAME ENGINE ===============
public class GameEngine
{
private Player player;
private List<Obstacle> obstacles;
private List<Collectible> collectibles;
private Enemy chaser;
private GameState state;
private int score;
private float gameSpeed;
private int currentLevel;
public GameEngine()
{
Initialize();
}
private void Initialize()
{
player = new Player();
obstacles = new List<Obstacle>();
collectibles = new List<Collectible>();
chaser = new Enemy();
state = GameState.Ready;
score = 0;
gameSpeed = 1.0f;
currentLevel = 1;
}
public void StartGame()
{
state = GameState.Running;
GenerateLevel(currentLevel);
Console.WriteLine("🎮 ============ VECTOR RUNNER ============");
Console.WriteLine("🏃 اهرب من المطارد وتجنب العقبات!");
Console.WriteLine("========================================\n");
}
public void Update(float deltaTime)
{
if (state != GameState.Running) return;
// Update player
player.Update(deltaTime, gameSpeed);
// Update obstacles
foreach (var obstacle in obstacles.ToList())
{
obstacle.Update(deltaTime, gameSpeed);
if (obstacle.Position.X < -50)
{
obstacles.Remove(obstacle);
score += 10;
}
}
// Update collectibles
foreach (var collectible in collectibles.ToList())
{
collectible.Update(deltaTime, gameSpeed);
if (collectible.IsColliding(player.Position))
{
collectibles.Remove(collectible);
ApplyPowerUp(collectible.Type);
}
}
// Update chaser with AI
chaser.Update(deltaTime, gameSpeed, player, obstacles);
// Check collisions
CheckCollisions();
// Increase difficulty over time
gameSpeed += deltaTime * 0.01f;
// Spawn new obstacles
if (UnityEngine.Random.value < 0.02f)
{
SpawnRandomObstacle();
}
}
private void GenerateLevel(int level)
{
obstacles.Clear();
collectibles.Clear();
// Generate obstacles based on level difficulty
int obstacleCount = 10 + (level * 5);
for (int i = 0; i < obstacleCount; i++)
{
float x = 100 + (i * 150);
SpawnObstacleAt(x, level);
}
// Generate collectibles
for (int i = 0; i < level * 3; i++)
{
float x = 200 + (i * 200);
collectibles.Add(new Collectible(new Vector2(x, 50), CollectibleType.SpeedBoost));
}
}
private void SpawnObstacleAt(float x, int difficulty)
{
ObstacleType[] types = (ObstacleType[])Enum.GetValues(typeof(ObstacleType));
ObstacleType type = types[UnityEngine.Random.Range(0, Math.Min(types.Length, 2 + difficulty))];
obstacles.Add(new Obstacle(new Vector2(x, 0), type));
}
private void SpawnRandomObstacle()
{
float x = player.Position.X + 800;
SpawnObstacleAt(x, currentLevel);
}
private void CheckCollisions()
{
foreach (var obstacle in obstacles)
{
if (player.IsColliding(obstacle) && !player.IsInvincible)
{
if (player.Lives > 1)
{
player.TakeDamage();
Console.WriteLine($"💔 خسرت حياة! المتبقي: {player.Lives}");
}
else
{
GameOver();
}
}
}
// Check if chaser caught the player
if (Vector2.Distance(player.Position, chaser.Position) < 20 && !player.IsInvincible)
{
GameOver();
}
}
private void ApplyPowerUp(CollectibleType type)
{
switch (type)
{
case CollectibleType.SpeedBoost:
player.ApplySpeedBoost(2.0f);
Console.WriteLine("⚡ سرعة مضاعفة!");
break;
case CollectibleType.SlowMotion:
gameSpeed *= 0.5f;
Console.WriteLine("⏱️ إبطاء الوقت!");
break;
case CollectibleType.Shield:
player.ActivateShield(5.0f);
Console.WriteLine("🛡️ درع واقي!");
break;
case CollectibleType.DoubleJump:
player.EnableDoubleJump();
Console.WriteLine("🦘 قفزة مزدوجة!");
break;
}
score += 50;
}
private void GameOver()
{
state = GameState.GameOver;
Console.WriteLine("\n💀 ========== GAME OVER ==========");
Console.WriteLine($"📊 النقاط النهائية: {score}");
Console.WriteLine($"🏆 المستوى: {currentLevel}");
Console.WriteLine($"⚡ السرعة القصوى: {gameSpeed:F2}x");
Console.WriteLine("==================================\n");
}
public void HandleInput(string input)
{
if (state != GameState.Running) return;
switch (input.ToLower())
{
case "w":
case "space":
player.Jump();
break;
case "s":
player.Slide();
break;
case "d":
player.Dash();
break;
case "a":
player.WallRun();
break;
case "f":
player.Flip();
break;
}
}
public string GetGameState()
{
return $"Score: {score} | Speed: {gameSpeed:F1}x | Lives: {player.Lives} | Distance to Chaser: {Vector2.Distance(player.Position, chaser.Position):F0}m";
}
}
// =============== PLAYER CLASS ===============
public class Player
{
public Vector2 Position { get; set; }
public Vector2 Velocity { get; private set; }
public int Lives { get; private set; }
public bool IsInvincible { get; private set; }
private PlayerState state;
private float gravity = -980f;
private float jumpForce = 400f;
private float dashSpeed = 800f;
private float maxSpeed = 500f;
private bool isGrounded;
private bool canDoubleJump;
private bool hasUsedDoubleJump;
private float invincibilityTimer;
private Dictionary<string, float> cooldowns;
private Queue<PlayerMove> moveHistory;
public Player()
{
Position = new Vector2(100, 0);
Velocity = Vector2.Zero;
Lives = 3;
state = PlayerState.Running;
isGrounded = true;
cooldowns = new Dictionary<string, float>();
moveHistory = new Queue<PlayerMove>();
}
public void Update(float deltaTime, float gameSpeed)
{
// Apply gravity
if (!isGrounded)
{
Velocity = new Vector2(Velocity.X, Velocity.Y + gravity * deltaTime);
}
// Apply velocity
Position = new Vector2(
Position.X + Velocity.X * deltaTime * gameSpeed,
Math.Max(0, Position.Y + Velocity.Y * deltaTime)
);
// Ground check
if (Position.Y <= 0)
{
Position = new Vector2(Position.X, 0);
Velocity = new Vector2(Velocity.X, 0);
isGrounded = true;
hasUsedDoubleJump = false;
state = PlayerState.Running;
}
else
{
isGrounded = false;
}
// Update cooldowns
foreach (var key in cooldowns.Keys.ToList())
{
cooldowns[key] -= deltaTime;
if (cooldowns[key] <= 0)
cooldowns.Remove(key);
}
// Update invincibility
if (IsInvincible)
{
invincibilityTimer -= deltaTime;
if (invincibilityTimer <= 0)
IsInvincible = false;
}
// Decay horizontal velocity
if (isGrounded && state == PlayerState.Running)
{
Velocity = new Vector2(maxSpeed, Velocity.Y);
}
}
public void Jump()
{
if (isGrounded && !cooldowns.ContainsKey("jump"))
{
Velocity = new Vector2(Velocity.X, jumpForce);
state = PlayerState.Jumping;
isGrounded = false;
cooldowns["jump"] = 0.2f;
RecordMove(PlayerMove.Jump);
Console.WriteLine("🦘 قفز!");
}
else if (!isGrounded && canDoubleJump && !hasUsedDoubleJump)
{
Velocity = new Vector2(Velocity.X, jumpForce * 0.8f);
hasUsedDoubleJump = true;
Console.WriteLine("🦘🦘 قفزة مزدوجة!");
}
}
public void Slide()
{
if (isGrounded && !cooldowns.ContainsKey("slide"))
{
state = PlayerState.Sliding;
Velocity = new Vector2(maxSpeed * 1.5f, Velocity.Y);
cooldowns["slide"] = 1.0f;
RecordMove(PlayerMove.Slide);
Console.WriteLine("⚡ انزلاق!");
}
}
public void Dash()
{
if (!cooldowns.ContainsKey("dash"))
{
Velocity = new Vector2(dashSpeed, Velocity.Y);
cooldowns["dash"] = 2.0f;
RecordMove(PlayerMove.Dash);
Console.WriteLine("💨 اندفاع!");
}
}
public void WallRun()
{
if (!isGrounded && !cooldowns.ContainsKey("wallrun"))
{
Velocity = new Vector2(Velocity.X, jumpForce * 1.2f);
cooldowns["wallrun"] = 1.5f;
RecordMove(PlayerMove.WallRun);
Console.WriteLine("🧗 جري على الجدار!");
}
}
public void Flip()
{
if (!isGrounded && !cooldowns.ContainsKey("flip"))
{
// Aesthetic move that gives small speed boost
Velocity = new Vector2(Velocity.X * 1.1f, Velocity.Y);
cooldowns["flip"] = 0.5f;
RecordMove(PlayerMove.Flip);
Console.WriteLine("🤸 شقلبة!");
}
}
public void ApplySpeedBoost(float multiplier)
{
maxSpeed *= multiplier;
}
public void ActivateShield(float duration)
{
IsInvincible = true;
invincibilityTimer = duration;
}
public void EnableDoubleJump()
{
canDoubleJump = true;
}
public void TakeDamage()
{
Lives--;
IsInvincible = true;
invincibilityTimer = 2.0f;
}
public bool IsColliding(Obstacle obstacle)
{
float playerRadius = 20f;
float obstacleRadius = 30f;
return Vector2.Distance(Position, obstacle.Position) < (playerRadius + obstacleRadius);
}
private void RecordMove(PlayerMove move)
{
moveHistory.Enqueue(move);
if (moveHistory.Count > 10)
moveHistory.Dequeue();
}
public Queue<PlayerMove> GetMoveHistory()
{
return new Queue<PlayerMove>(moveHistory);
}
}
// =============== ENEMY AI CLASS ===============
public class Enemy
{
public Vector2 Position { get; private set; }
private Vector2 velocity;
private float baseSpeed = 350f;
private float currentSpeed;
private Queue<PlayerMove> learnedMoves;
private float decisionTimer;
private bool isLearning = true;
public Enemy()
{
Position = new Vector2(-100, 0);
velocity = Vector2.Zero;
currentSpeed = baseSpeed;
learnedMoves = new Queue<PlayerMove>();
decisionTimer = 0;
}
public void Update(float deltaTime, float gameSpeed, Player player, List<Obstacle> obstacles)
{
decisionTimer -= deltaTime;
// Learn from player
if (isLearning && decisionTimer <= 0)
{
LearnFromPlayer(player);
decisionTimer = 1.0f;
}
// Chase player
float distanceToPlayer = player.Position.X - Position.X;
if (distanceToPlayer > 50)
{
currentSpeed = baseSpeed + (gameSpeed - 1.0f) * 100f;
velocity = new Vector2(currentSpeed, velocity.Y);
}
// Predict and avoid obstacles
Obstacle nearestObstacle = obstacles
.Where(o => o.Position.X > Position.X && o.Position.X < Position.X + 200)
.OrderBy(o => o.Position.X - Position.X)
.FirstOrDefault();
if (nearestObstacle != null)
{
PerformEvasiveMove(nearestObstacle);
}
// Apply velocity
Position = new Vector2(
Position.X + velocity.X * deltaTime * gameSpeed,
Math.Max(0, Position.Y + velocity.Y * deltaTime)
);
// Apply gravity
if (Position.Y > 0)
{
velocity = new Vector2(velocity.X, velocity.Y - 980f * deltaTime);
}
else
{
velocity = new Vector2(velocity.X, 0);
}
}
private void LearnFromPlayer(Player player)
{
var playerMoves = player.GetMoveHistory();
foreach (var move in playerMoves)
{
if (!learnedMoves.Contains(move))
{
learnedMoves.Enqueue(move);
if (learnedMoves.Count > 5)
learnedMoves.Dequeue();
}
}
}
private void PerformEvasiveMove(Obstacle obstacle)
{
float distance = obstacle.Position.X - Position.X;
if (distance < 100)
{
switch (obstacle.Type)
{
case ObstacleType.LowBarrier:
// Jump
if (Position.Y == 0)
velocity = new Vector2(velocity.X, 400f);
break;
case ObstacleType.HighBarrier:
// Slide or use learned move
if (learnedMoves.Contains(PlayerMove.WallRun))
velocity = new Vector2(velocity.X, 500f);
break;
case ObstacleType.Laser:
// Time-based evasion
if (Position.Y == 0)
velocity = new Vector2(velocity.X * 1.5f, 300f);
break;
}
}
}
}
// =============== OBSTACLE CLASS ===============
public class Obstacle
{
public Vector2 Position { get; private set; }
public ObstacleType Type { get; private set; }
private float movementPattern;
public Obstacle(Vector2 position, ObstacleType type)
{
Position = position;
Type = type;
movementPattern = 0;
}
public void Update(float deltaTime, float gameSpeed)
{
// Move obstacle left (scrolling effect)
Position = new Vector2(Position.X - 300 * deltaTime * gameSpeed, Position.Y);
// Special movement patterns
movementPattern += deltaTime;
switch (Type)
{
case ObstacleType.Laser:
Position = new Vector2(Position.X, 50 + (float)Math.Sin(movementPattern * 3) * 40);
break;
case ObstacleType.RotatingSaw:
// Visual rotation (would be animated in real game)
break;
case ObstacleType.ElectricTrap:
// Pulsing effect
break;
}
}
}
// =============== COLLECTIBLE CLASS ===============
public class Collectible
{
public Vector2 Position { get; private set; }
public CollectibleType Type { get; private set; }
public Collectible(Vector2 position, CollectibleType type)
{
Position = position;
Type = type;
}
public void Update(float deltaTime, float gameSpeed)
{
Position = new Vector2(Position.X - 300 * deltaTime * gameSpeed, Position.Y);
}
public bool IsColliding(Vector2 playerPos)
{
return Vector2.Distance(Position, playerPos) < 30f;
}
}
// =============== UTILITY CLASSES ===============
public struct Vector2
{
public float X;
public float Y;
public Vector2(float x, float y)
{
X = x;
Y = y;
}
public static Vector2 Zero => new Vector2(0, 0);
public static float Distance(Vector2 a, Vector2 b)
{
float dx = b.X - a.X;
float dy = b.Y - a.Y;
return (float)Math.Sqrt(dx * dx + dy * dy);
}
}
// =============== ENUMS ===============
public enum GameState
{
Ready,
Running,
Paused,
GameOver
}
public enum PlayerState
{
Running,
Jumping,
Sliding,
WallRunning,
Flipping
}
public enum ObstacleType
{
LowBarrier,
HighBarrier,
Laser,
RotatingSaw,
ElectricTrap,
DisappearingPlatform,
MovingWall
}
public enum CollectibleType
{
SpeedBoost,
SlowMotion,
Shield,
DoubleJump,
Coin
}
public enum PlayerMove
{
Jump,
Slide,
Dash,
WallRun,
Flip
}
// =============== FAKE UNITY RANDOM (FOR COMPILATION) ===============
public static class UnityEngine
{
private static Random random = new Random();
public static class Random
{
public static float value => (float)random.NextDouble();
public static int Range(int min, int max) => random.Next(min, max);
}
}
// =============== MAIN PROGRAM ===============
class Program
{
static void Main(string[] args)
{
Console.OutputEncoding = System.Text.Encoding.UTF8;
GameEngine game = new GameEngine();
game.StartGame();
Console.WriteLine("🎮 التحكم:");
Console.WriteLine("W/Space = قفز | S = انزلاق | D = اندفاع");
Console.WriteLine("A = جري على الجدار | F = شقلبة");
Console.WriteLine("اكتب 'quit' للخروج\n");
// Simulation loop
float deltaTime = 0.016f; // 60 FPS
int frameCount = 0;
while (true)
{
// Simulate game update
game.Update(deltaTime);
// Display state every 60 frames (1 second)
if (frameCount % 60 == 0)
{
Console.WriteLine(game.GetGameState());
}
// Simulate random input for demo
if (frameCount % 120 == 0)
{
string[] inputs = { "w", "s", "d", "a", "f" };
game.HandleInput(inputs[UnityEngine.Random.Range(0, inputs.Length)]);
}
frameCount++;
System.Threading.Thread.Sleep(16); // ~60 FPS
// Stop after 500 frames for demo
if (frameCount > 500)
break;
}
Console.WriteLine("\n✅ انتهت المحاكاة!");
Console.WriteLine("📝 ملاحظة: هذا كود احترافي جاهز للتطوير في Unity أو Godot");
}
}
}
Metadata
Metadata
Assignees
Labels
No labels