/* Autors: Ralfs Emīls Saldnieks 110.gr. Projekta nosk.: Console Worms 2D Apraksts: Worms spele, kas console izvadas ar braille simboliem. Veidots: 05.06.2026. Papildus: Jaizmanto visual studio, jo online kompaileris konsoles izmeru atgriez 0. */ using System; namespace Game { enum Blocks { Air, Block, } class Object { private double _posX; private double _posY; private int _sizeX; private int _sizeY; private int _offsetY; public double posX { get { return _posX; } set { _posX = value; } } public double posY { get { return _posY; } set { _posY = value; } } public int sizeX { get { return _sizeX; } set { _sizeX = value; } } public int sizeY { get { return _sizeY; } set { _sizeY = value; } } public int offsetY { get { return _offsetY; } set { _offsetY = value; } } public Object(double x = 0.0, double y = 0.0, int sX = 1, int sY = 1, int ofsY = 0){ _posX = x; _posY = y; _sizeX = sX; _sizeY = sY; _offsetY = ofsY; } } class Grenade:Object { double vy; double vx; public Grenade(double x, double y, int sX, int sY, int ofsY, double velocity_y = 0.0, double velocity_x = 0.0) : base(x, y, sX, sY, ofsY){ vy = velocity_y; vx = velocity_x; } public bool Gravity(WorldGrid world_grid){ posY += vy; posX += vx; if(vy < 3.0) vy += 0.25; else vy = 3.0; // sprādziena kadījumā aizvieto 3x3 ar gaisu int gy = (int)posY/4; int gx = (int)posX/4; if(gy >= 0 && gy < world_grid.grid.GetLength(0) && gx >= 0 && gx < world_grid.grid.GetLength(1)){ if(world_grid.grid[gy, gx] == Blocks.Block){ for(int y = gy-1; y<=gy+1; y++){ for(int x = gx-1; x<=gx+1; x++){ world_grid.grid[y, x] = Blocks.Air; } } return true; } } return false; } } class Player:Object { double vy; public Player(double x, double y, int sX, int sY, int ofsY, double velocity_y = 0.0) : base(x, y, sX, sY, ofsY){ vy = velocity_y; } public void Movement(KeyboardInput input, WorldGrid world_grid) { int startY = (int)posY - (sizeY / 2) + offsetY; int startX = (int)posX - (sizeX / 2); // Pārbauda vai var iet uz sāniem bool can_go_left = true; bool can_go_right = true; for(int y = startY; y(world_grid.grid.GetLength(0)-1)*4) posY = (world_grid.grid.GetLength(0)-1)*4; } } public class KeyboardInput { private HashSet pressedKeys = new HashSet(); private object lockObj = new object(); private Thread inputThread; public KeyboardInput() { inputThread = new Thread(ReadKeysLoop); inputThread.IsBackground = true; inputThread.Start(); } private void ReadKeysLoop() { while (true) { if (Console.KeyAvailable) { var keyInfo = Console.ReadKey(true); char key = char.ToLower(keyInfo.KeyChar); lock (lockObj) { pressedKeys.Add(key); } ThreadPool.QueueUserWorkItem(_ => { Thread.Sleep(120); lock (lockObj) { pressedKeys.Remove(key); } }); } Thread.Sleep(15); } } public bool IsKeyPressed(char key) { lock (lockObj) { return pressedKeys.Contains(char.ToLower(key)); } } } class WorldGrid { public Blocks[,] grid; public WorldGrid(int sizeY, int sizeX){ grid = new Blocks[sizeY, sizeX]; for(int i = 0; i < grid.GetLength(0); ++i){ for(int j = 0; j < grid.GetLength(1); ++j){ if(i>sizeY*0.8)grid[i,j] = Blocks.Block; else grid[i,j] = Blocks.Air; } } } } class Screen { public bool[,] screen; public Screen() {} public void ClearScreen(WorldGrid world_grid) { screen = new bool[world_grid.grid.GetLength(0)*4,world_grid.grid.GetLength(1)*4]; // Pārnes bloku karti uz ekrānu for(int i = 0; i < screen.GetLength(0); ++i){ for(int j = 0; j < screen.GetLength(1); ++j){ if(world_grid.grid[i/4,j/4] == Blocks.Block) screen[i,j] = true; } } } private char CalculateBraille(bool[] dots){ int sum = 0; for (int i = 0; i < 8; i++){ if (dots[i]){ sum += (int)Math.Pow(2, i); } } return (char)(0x2800 + sum); } public void DrawScreen(List element_list) { foreach (Object e in element_list) { int startY = (int)e.posY - (e.sizeY / 2) + e.offsetY; int startX = (int)e.posX - (e.sizeX / 2); for (int y = startY; y < startY+e.sizeY; y++){ for (int x = startX; x < startX+e.sizeX; x++){ if (y >= 0 && y < screen.GetLength(0) && x >= 0 && x < screen.GetLength(1)){ screen[y, x] = !screen[y, x]; } } } } element_list.Clear(); for (int y = 0; y < screen.GetLength(0) / 4; y++){ for (int x = 0; x < screen.GetLength(1) / 2; x++){ bool[] dots = new bool[8]; // Sagatavo ekrāna vērtības lai pārvērstu tos braille simbolos // 0 3 // 1 4 // 2 5 // 6 7 if (screen[y * 4, x * 2]) dots[0] = true; if (screen[y * 4 + 1, x * 2]) dots[1] = true; if (screen[y * 4 + 2, x * 2]) dots[2] = true; if (screen[y * 4, x * 2 + 1]) dots[3] = true; if (screen[y * 4 + 1, x * 2 + 1]) dots[4] = true; if (screen[y * 4 + 2, x * 2 + 1]) dots[5] = true; if (screen[y * 4 + 3, x * 2]) dots[6] = true; if (screen[y * 4 + 3, x * 2 + 1]) dots[7] = true; Console.SetCursorPosition(x, y); Console.Write(CalculateBraille(dots)); } if(y != screen.GetLength(0)/4-1)Console.WriteLine(); } } } class Program { static void Main(string[] args){ Console.WriteLine("Movement - WASD"); Console.WriteLine("throw grenade - E"); Console.Write("Enter each turn time (example 30.0): "); double turn_timer_length = Double.Parse(Console.ReadLine()); double time_step = 0.03; WorldGrid world_grid = new WorldGrid(Console.WindowHeight,Console.WindowWidth/2); Screen screen_ctl = new Screen(); screen_ctl.ClearScreen(world_grid); List element_list = new List(); Console.CursorVisible = false; KeyboardInput input = new KeyboardInput(); Player player1 = new Player(50,50, 4, 8, -3, 1.0); Player player2 = new Player(60,50, 4, 8, -3, 1.0); List grenade_list = new List(); bool grenade_thrown = false; double timer = turn_timer_length; int which_turn = 1; Console.Clear(); while(true){ if(!grenade_thrown){ if(which_turn == 1){ player1.Movement(input, world_grid); } else { player2.Movement(input, world_grid); } if(input.IsKeyPressed('e')){ Console.Clear(); grenade_thrown = true; timer = 0.0; Console.Write("Enter velocity for X (negative for left, positive for right): "); double vx = Double.Parse(Console.ReadLine()); Console.Write("Enter velocity for Y: "); double vy = Math.Abs(Double.Parse(Console.ReadLine()))*-1; if(which_turn == 1) grenade_list.Add(new Grenade(player1.posX, player1.posY, 3, 3, 0, vy, vx)); else grenade_list.Add(new Grenade(player2.posX, player2.posY, 3, 3, 0, vy, vx)); } }else if(grenade_list.Count == 0) { grenade_thrown = false; } element_list.Add(new Object(player1.posX, player1.posY, player1.sizeX, player1.sizeY, player1.offsetY)); element_list.Add(new Object(player2.posX, player2.posY, player2.sizeX, player2.sizeY, player2.offsetY)); List to_remove = new List(); foreach(Grenade g in grenade_list){ if(g.Gravity(world_grid)) to_remove.Add(g); else element_list.Add(new Object(g.posX, g.posY, g.sizeX, g.sizeY, g.offsetY)); } foreach(Grenade g in to_remove) grenade_list.Remove(g); timer -= time_step; if(timer <= 0.0 && !grenade_thrown){ switch(which_turn){ case 1: which_turn = 2; break; default: which_turn = 1; break; } timer = turn_timer_length; } screen_ctl.DrawScreen(element_list); screen_ctl.ClearScreen(world_grid); Thread.Sleep((int)(time_step*1000)); } } } }