Compare commits
No commits in common. "Matrix-1.0.0" and "rpi-rgb-led-matrix" have entirely different histories.
Matrix-1.0
...
rpi-rgb-le
584
SnakeGame.cs
584
SnakeGame.cs
|
@ -1,395 +1,241 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Net.Sockets;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System;
|
||||
using SocketLib;
|
||||
using rpi_rgb_led_matrix_sharp;
|
||||
|
||||
namespace SnakeGame {
|
||||
class SnakeGame {
|
||||
private static int width = 32;
|
||||
private static int height = 32;
|
||||
private static string lobbyCode = "";
|
||||
public static class SnakeGame {
|
||||
public static int baseLength = 5;
|
||||
private static Segment food = new();
|
||||
private static List<Snake> snakes = new();
|
||||
private static RGBLedMatrix? _matrix;
|
||||
private static RGBLedCanvas? _canvas;
|
||||
public static bool gameOver, selection;
|
||||
private static int FPS = 10, timeout = 10;
|
||||
private static int frameCount = 0, keypressFrame = 0;
|
||||
private static Snake self = new(width/2, height/2);
|
||||
private static bool gameOver, isReady, isMultiplayer, isPlaying = false;
|
||||
public static List<string> players = new();
|
||||
public static int width = 48, height = 48, sw = 4, sh = 4;
|
||||
public static int frameCount, keypressFrame, selectionIndex;
|
||||
public static Dictionary<string, Color> colors = new() {{"bot", new(0, 255, 0)}};
|
||||
public static Dictionary<string, Snake> snakes = new() {{"bot", new(width / 2, height / 2)}};
|
||||
|
||||
private static void Main() {
|
||||
// Calculate the number of milliseconds in which to display 1 frame
|
||||
int frameMills = 1000/FPS;
|
||||
|
||||
// Decide on Single- or Multiplayer version
|
||||
Console.Clear();
|
||||
while (true) {
|
||||
Console.Clear();
|
||||
Console.WriteLine("################################");
|
||||
Console.WriteLine("Art des Spielens:");
|
||||
Console.WriteLine("0) Schließen");
|
||||
Console.WriteLine("1) Singleplayer");
|
||||
Console.WriteLine("2) Multiplayer");
|
||||
Console.WriteLine("################################");
|
||||
Console.WriteLine();
|
||||
Console.Write("Wahl (0-2): ");
|
||||
string input = Console.ReadLine();
|
||||
|
||||
// Handle user input with switch statement
|
||||
bool ready = true;
|
||||
switch (input) {
|
||||
default:
|
||||
// Invalid input was given
|
||||
Console.Write("Ungültige Eingabe oder Fehler. Bitte erneut versuchen. ");
|
||||
Console.ReadKey(true);
|
||||
ready = false;
|
||||
break;
|
||||
case "0":
|
||||
// Exit program
|
||||
Environment.Exit(0);
|
||||
break;
|
||||
case "1":
|
||||
// Play as Singleplayer: No more operatiosn required
|
||||
break;
|
||||
case "2":
|
||||
// Redirect to multiplayer options, reset if multiplayer wasn't successfully started
|
||||
ready = multiplayerConnect();
|
||||
break;
|
||||
public static void Init(RGBLedMatrix matrix, RGBLedCanvas canvas) {
|
||||
_matrix = matrix;
|
||||
_canvas = canvas;
|
||||
}
|
||||
|
||||
public static void Main(string[] args) {
|
||||
// Initialize snakes
|
||||
foreach (string p in players)
|
||||
if (!snakes.ContainsKey(p)) {
|
||||
snakes.Add(p, new(width / 2, height / 2));
|
||||
Random rng = new();
|
||||
colors.Add(p, new(
|
||||
rng.Next(256),
|
||||
rng.Next(256),
|
||||
rng.Next(256)));
|
||||
}
|
||||
// Only break out of while-Loop on successful selection
|
||||
if (ready)
|
||||
foreach (KeyValuePair<string, Snake> kvp in snakes)
|
||||
if (kvp.Key != "bot" && !players.Contains(kvp.Key)) {
|
||||
snakes.Remove(kvp.Key);
|
||||
colors.Remove(kvp.Key);
|
||||
}
|
||||
|
||||
// Initialize Variables
|
||||
gameOver = false;
|
||||
width = 192 / sw;
|
||||
height = 192 / sh;
|
||||
|
||||
// Check CL_Args for parameters
|
||||
foreach (string arg in args)
|
||||
if (arg == "-b" || arg == "--bot") {
|
||||
keypressFrame = -timeout * FPS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the number of milliseconds in which to display 1 frame
|
||||
int frameMills = 1000 / FPS;
|
||||
|
||||
// Console Output Setup
|
||||
Console.Clear();
|
||||
if (isMultiplayer) {
|
||||
Console.SetCursorPosition(width/2, 0);
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.Write($"Lobby Code: {lobbyCode}");
|
||||
// Notify Server when player is ready
|
||||
Connection.Send(Connection.self, "PlayerReady");
|
||||
isReady = true;
|
||||
}
|
||||
|
||||
// Initialize RGBLedMatrix
|
||||
RGBLedMatrix matrix = new(
|
||||
new RGBLedMatrixOptions {
|
||||
HardwareMapping = "adafruit-hat",
|
||||
LimitRefreshRateHz = 0,
|
||||
GpioSlowdown = 4,
|
||||
Brightness = 100,
|
||||
ChainLength = 1,
|
||||
ScanMode = 1,
|
||||
Rows = 64,
|
||||
Cols = 64,
|
||||
});
|
||||
RGBLedCanvas canvas = matrix.CreateOffscreenCanvas();
|
||||
RGBLedMatrix matrix;
|
||||
RGBLedCanvas canvas;
|
||||
if (_matrix != null && _canvas != null) {
|
||||
matrix = _matrix;
|
||||
canvas = _canvas;
|
||||
}
|
||||
else {
|
||||
matrix = new(
|
||||
new RGBLedMatrixOptions {
|
||||
GpioSlowdown = 5,
|
||||
ChainLength = 3,
|
||||
Parallel = 3,
|
||||
Rows = 64,
|
||||
Cols = 64,
|
||||
});
|
||||
canvas = matrix.CreateOffscreenCanvas();
|
||||
}
|
||||
|
||||
// Initialize stopwatch to measure calculation and display time
|
||||
Stopwatch stopwatch = new();
|
||||
|
||||
// Game Play
|
||||
gameOver = false;
|
||||
while (!gameOver) {
|
||||
// Start stopwatch
|
||||
stopwatch.Restart();
|
||||
// Handle key presses and exiting
|
||||
self.keyHandler();
|
||||
|
||||
// Clear canvas
|
||||
canvas.Clear();
|
||||
|
||||
// If player is absent, automatically steer sneak towards food (very simple)
|
||||
if (frameCount >= keypressFrame+timeout*FPS) {
|
||||
Snake self = snakes["bot"];
|
||||
if (frameCount >= keypressFrame + timeout * FPS) {
|
||||
if (food.x < self.ownPos.x && self.mx != 1) {
|
||||
// Steer snake towards food on its left side
|
||||
self.mx = -1;
|
||||
self.my = 0;
|
||||
} else if (food.x > self.ownPos.x && self.mx != -1) {
|
||||
// Steer snake towards food on its right side
|
||||
self.mx = 1;
|
||||
self.my = 0;
|
||||
} else if (food.y < self.ownPos.y && self.my != 1) {
|
||||
// Steer sake towards food below it
|
||||
self.mx = 0;
|
||||
self.my = -1;
|
||||
} else if (food.y > self.ownPos.y && self.my != -1) {
|
||||
// Steer snake towards food above it
|
||||
self.mx = 0;
|
||||
self.my = 1;
|
||||
self.my = 0;
|
||||
}
|
||||
}
|
||||
// Handle snake movement
|
||||
self.move();
|
||||
// Handle snake dying
|
||||
self.touchHandler(self);
|
||||
if (isMultiplayer)
|
||||
for (int i = 0; i < snakes.Count; i++)
|
||||
self.touchHandler(snakes[i]);
|
||||
// Handle snake eating food
|
||||
self.foodHandler(food);
|
||||
|
||||
// Display own Snake
|
||||
canvas.Clear();
|
||||
Color green = new(0, 255, 0);
|
||||
setSnakePixels(canvas, self, green);
|
||||
|
||||
// Display other Snakes
|
||||
Color blue = new(0, 127, 255);
|
||||
for (int i = 0; i < snakes.Count; i++) {
|
||||
Snake current = snakes[i];
|
||||
setSnakePixels(canvas, current, blue);
|
||||
}
|
||||
|
||||
else if (food.x > self.ownPos.x && self.mx != -1) {
|
||||
// Steer snake towards food on its right side
|
||||
self.mx = 1;
|
||||
self.my = 0;
|
||||
}
|
||||
else if (food.y < self.ownPos.y && self.my != 1) {
|
||||
// Steer sake towards food below it
|
||||
self.mx = 0;
|
||||
self.my = -1;
|
||||
}
|
||||
else if (food.y > self.ownPos.y && self.my != -1) {
|
||||
// Steer snake towards food above it
|
||||
self.mx = 0;
|
||||
self.my = 1;
|
||||
}
|
||||
|
||||
// Move bot around
|
||||
self.move();
|
||||
self.touchHandler(self);
|
||||
self.foodHandler(food);
|
||||
setSnakePixels(canvas, self, colors["bot"]);
|
||||
// Player logic
|
||||
} else
|
||||
foreach (KeyValuePair<string, Snake> kvp in snakes) {
|
||||
if (kvp.Key == "bot")
|
||||
continue;
|
||||
Snake current = kvp.Value;
|
||||
// Handle snake movement
|
||||
current.move();
|
||||
// Handle snake dying
|
||||
foreach (KeyValuePair<string, Snake> opair in snakes) {
|
||||
if (opair.Key == "bot")
|
||||
continue;
|
||||
current.touchHandler(opair.Value);
|
||||
}
|
||||
|
||||
// Handle snake eating food
|
||||
current.foodHandler(food);
|
||||
|
||||
// Display own Snake
|
||||
setSnakePixels(canvas, current, colors[kvp.Key]);
|
||||
}
|
||||
|
||||
// Display shared Food
|
||||
Color red = new(255, 0, 0);
|
||||
canvas.SetPixel(food.x*2, food.y*2, red);
|
||||
canvas.SetPixel(food.x*2+1, food.y*2, red);
|
||||
canvas.SetPixel(food.x*2, food.y*2+1, red);
|
||||
canvas.SetPixel(food.x*2+1, food.y*2+1, red);
|
||||
|
||||
setPixelsOf(canvas, food, red);
|
||||
|
||||
// Swap Frame on Vsync
|
||||
canvas = matrix.SwapOnVsync(canvas);
|
||||
|
||||
// Display Debug / Score
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.SetCursorPosition(0, 0);
|
||||
Console.WriteLine($"Score: {self.length-self.baseLen}");
|
||||
|
||||
// Save previous snakes
|
||||
if (isMultiplayer) {
|
||||
snakes = new();
|
||||
if (isReady)
|
||||
Connection.Send(Connection.self, $"PlayerUpdate {self.ToString()}");
|
||||
}
|
||||
|
||||
// Fix framerate
|
||||
frameCount = (frameCount+1)%1000000;
|
||||
frameCount = (frameCount + 1) % 1000000;
|
||||
int elapsed = (int)stopwatch.ElapsedMilliseconds;
|
||||
if (elapsed < frameMills)
|
||||
Thread.Sleep(frameMills - elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool multiplayerConnect() {
|
||||
// Initialize connection parameters
|
||||
Connection.Initialize();
|
||||
Connection.messageEvents.Add(new("PlayerUpdate", playerUpdate));
|
||||
Connection.messageEvents.Add(new("FoodUpdate", foodUpdate));
|
||||
Connection.messageEvents.Add(new("Created", onGetCode));
|
||||
Connection.messageEvents.Add(new("Joined", onGetFood));
|
||||
Connection.messageEvents.Add(new("ShowLobbies", showLobbies));
|
||||
|
||||
// Ask for user input for IP address and port number
|
||||
Console.WriteLine("Angabe der IP Adresse und Portnummer des anderen Servers");
|
||||
Console.Write("( Format 'IPv4:Port' ): ");
|
||||
string ipIn = Console.ReadLine();
|
||||
if (ipIn.ToLower() == "exit")
|
||||
return false;
|
||||
Connection.ClientConnect(ipIn);
|
||||
|
||||
// Handle lobby-connect
|
||||
while (true) {
|
||||
Console.Clear();
|
||||
Console.WriteLine("################################");
|
||||
Console.WriteLine("Beitreten einer Lobby:");
|
||||
Console.WriteLine("0) Zurück");
|
||||
Console.WriteLine("1) Lobby erstellen");
|
||||
Console.WriteLine("2) Lobby beitreten");
|
||||
Console.WriteLine("################################");
|
||||
Console.WriteLine();
|
||||
Console.Write("Wahl (0-2): ");
|
||||
string input = Console.ReadLine();
|
||||
|
||||
// Handle user input with switch statement
|
||||
bool ready = true;
|
||||
switch (input) {
|
||||
default:
|
||||
// Invalid input was given
|
||||
Console.Write("Ungültige Eingabe oder Fehler. Bitte erneut versuchen. ");
|
||||
Console.ReadKey(true);
|
||||
ready = false;
|
||||
break;
|
||||
case "0":
|
||||
// Return to previous section
|
||||
Connection.self.Close();
|
||||
return false;
|
||||
case "1":
|
||||
// Open new Lobby on connected Server
|
||||
string msg = $"NewLobby {food.ToString()}";
|
||||
Connection.Send(Connection.self, msg);
|
||||
break;
|
||||
case "2":
|
||||
// List opened lobbies and such
|
||||
ready = multiplayerLobbyList();
|
||||
break;
|
||||
}
|
||||
// Only break out of while-Loop on successful selection
|
||||
if (ready)
|
||||
break;
|
||||
}
|
||||
// Wait for server-side response on lobby creation/join
|
||||
while (lobbyCode == "")
|
||||
Thread.Sleep(500);
|
||||
// Exit section in multiplayer mode
|
||||
isMultiplayer = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool multiplayerLobbyList() {
|
||||
// Ask server for open lobbies
|
||||
Connection.Send(Connection.self, "ListLobbies");
|
||||
// Wait until lobby list is received
|
||||
while (lobbyCode == "")
|
||||
Thread.Sleep(500);
|
||||
// Interpret the lobby list
|
||||
string[] listed = lobbyCode.Split('-');
|
||||
lobbyCode = "";
|
||||
|
||||
// Start section for lobby selection
|
||||
int current = 0;
|
||||
while (true) {
|
||||
Console.Clear();
|
||||
Console.WriteLine("################################");
|
||||
Console.WriteLine("Beitreten einer Lobby:");
|
||||
Console.WriteLine("0) Zurück");
|
||||
// Loop through available lobbies from #<current> and up to 5 lobbies ahead
|
||||
for (int i = 1; i < 5; i++)
|
||||
if (current+i < listed.Length+1) {
|
||||
string[] next = listed[current+i-1].Split(',');
|
||||
Console.WriteLine($"{i}) Code: {next[0]} - Spieler: {next[1]}");
|
||||
}
|
||||
// Only display option when there are more available
|
||||
if (listed.Length > current+5)
|
||||
Console.WriteLine("6) Weiter");
|
||||
Console.WriteLine("################################");
|
||||
Console.WriteLine();
|
||||
Console.Write("Wahl (0-2): ");
|
||||
string input = Console.ReadLine();
|
||||
|
||||
// Handle user input with switch statement
|
||||
bool ready = true;
|
||||
switch (input) {
|
||||
default:
|
||||
// Check if input corresponds to a lobby, else an invalid input was given
|
||||
int parse = int.TryParse(input, out parse) ? parse : 0;
|
||||
if (parse <= 0) {
|
||||
// Output invalid input message
|
||||
Console.Write("Ungültige Eingabe oder Fehler. Bitte erneut versuchen. ");
|
||||
Console.ReadKey(true);
|
||||
ready = false;
|
||||
// Select lobby from user input
|
||||
} else
|
||||
lobbyCode = listed[current+parse-1].Split(',')[0];
|
||||
break;
|
||||
case "0":
|
||||
// If not at the beginning of the list, go back in the list
|
||||
if (current != 0) {
|
||||
ready = false;
|
||||
current -= 5;
|
||||
break;
|
||||
}
|
||||
// Otherwise exit section
|
||||
return false;
|
||||
case "6":
|
||||
// Go forward in the list if not already at the end
|
||||
ready = false;
|
||||
if (listed.Length > current+5)
|
||||
current += 5;
|
||||
else {
|
||||
// Output invalid input message
|
||||
Console.Write("Ungültige Eingabe oder Fehler. Bitte erneut versuchen. ");
|
||||
Console.ReadKey(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Only break out of while-Loop on successful selection
|
||||
if (ready)
|
||||
break;
|
||||
}
|
||||
// Join the selected lobby, continue in multiplayer mode
|
||||
Connection.Send(Connection.self, $"JoinLobby {lobbyCode}");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Method to display any given snake on any given canvas with any given color as 2x2 pixels
|
||||
private static void setSnakePixels(RGBLedCanvas canv, Snake other, Color col) {
|
||||
canv.SetPixel(self.ownPos.x*2, self.ownPos.y*2, col);
|
||||
canv.SetPixel(self.ownPos.x*2+1, self.ownPos.y*2, col);
|
||||
canv.SetPixel(self.ownPos.x*2, self.ownPos.y*2+1, col);
|
||||
canv.SetPixel(self.ownPos.x*2+1, self.ownPos.y*2+1, col);
|
||||
foreach (Segment s in self.tailPos) {
|
||||
canv.SetPixel(s.x*2, s.y*2, col);
|
||||
canv.SetPixel(s.x*2+1, s.y*2, col);
|
||||
canv.SetPixel(s.x*2, s.y*2+1, col);
|
||||
canv.SetPixel(s.x*2+1, s.y*2+1, col);
|
||||
setPixelsOf(canv, other.ownPos, col);
|
||||
foreach (Segment s in other.tailPos)
|
||||
setPixelsOf(canv, s, col);
|
||||
}
|
||||
|
||||
// Set Pixel at given coordinates
|
||||
private static void setPixelsOf(RGBLedCanvas canv, Segment seg, Color col) {
|
||||
for (int i = 0; i < sw; i++)
|
||||
for (int j = 0; j < sh; j++)
|
||||
canv.SetPixel(seg.x*sw+i , seg.y*sh+j , col);
|
||||
}
|
||||
|
||||
// Method to choose what a given index has to do
|
||||
public static void enterSelection() {
|
||||
switch (selectionIndex) {
|
||||
case 1:
|
||||
selection = false;
|
||||
break;
|
||||
case 0:
|
||||
selection = false;
|
||||
frameCount = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Async Callback to receive the list of open lobbies
|
||||
private static void showLobbies(Socket other, string rest) {
|
||||
lobbyCode = rest;
|
||||
// Method to End the Game and return to Menu
|
||||
public static void EndGame() {
|
||||
selection = false;
|
||||
gameOver = true;
|
||||
frameCount = 0;
|
||||
keypressFrame = 0;
|
||||
}
|
||||
|
||||
// Async Callback to receive an update from another player
|
||||
private static void playerUpdate(Socket other, string rest) {
|
||||
Snake parsedSnake = Snake.Parse(rest);
|
||||
if (parsedSnake != null)
|
||||
snakes.Add(parsedSnake);
|
||||
// Method to Steer Snake upwards
|
||||
public static void SteerUp(Snake snake) {
|
||||
if (snake.my != 1) {
|
||||
snake.my = -1;
|
||||
snake.mx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Async Callback to receive an update for food
|
||||
private static void foodUpdate(Socket other, string rest) {
|
||||
try {
|
||||
string[] splits = rest.Split(',');
|
||||
food = new(int.Parse(splits[0]), int.Parse(splits[1]));
|
||||
} catch (Exception e) { }
|
||||
// Method to Steer Snake downwards
|
||||
public static void SteerDown(Snake snake) {
|
||||
if (snake.my != -1) {
|
||||
snake.my = 1;
|
||||
snake.mx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Async Callback to receive the lobby code from the server
|
||||
private static void onGetCode(Socket other, string code) {
|
||||
lobbyCode = code;
|
||||
// Method to Steer Snake to the left
|
||||
public static void SteerLeft(Snake snake) {
|
||||
if (snake.mx != 1) {
|
||||
snake.mx = -1;
|
||||
snake.my = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Async Callback to receive the lobby code and current food position in lobby
|
||||
private static void onGetFood(Socket other, string rest) {
|
||||
string[] splits = rest.Split('-');
|
||||
lobbyCode = splits[0];
|
||||
food = Segment.Parse(splits[1]);
|
||||
}
|
||||
|
||||
// Method to reset any given snake to its base parameters
|
||||
private static void resetSelf(Snake other) {
|
||||
// Replace any characters at score
|
||||
int scoreLen = $"Score: {other.length-other.baseLen}".Length;
|
||||
Console.SetCursorPosition(0, 0);
|
||||
for (int i = 0; i < scoreLen; i++)
|
||||
Console.Write(' ');
|
||||
|
||||
// Reset lengt of Snake
|
||||
other.length = other.baseLen;
|
||||
}
|
||||
|
||||
// Method to parse a serialized list of 'Segments' into a List<Segment> Object
|
||||
private static List<Segment> parseSegments(string _segments) {
|
||||
List<Segment> newSegments = new();
|
||||
string[] splits = _segments.Split('-');
|
||||
foreach (string s in splits)
|
||||
newSegments.Add(Segment.Parse(s));
|
||||
return newSegments;
|
||||
// Method to Steer Snake to the right
|
||||
public static void SteerRight(Snake snake) {
|
||||
if (snake.mx != -1) {
|
||||
snake.mx = 1;
|
||||
snake.my = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Class to represent an instance of a Snake
|
||||
public class Snake {
|
||||
public Segment ownPos, lastPos;
|
||||
public List<Segment> tailPos = new();
|
||||
public int length = 0, baseLen = 0;
|
||||
public int mx = 1, my = 0;
|
||||
public Segment ownPos, lastPos;
|
||||
public int length;
|
||||
public int mx = 1, my;
|
||||
|
||||
// Constructor for a simple Snake with x and y coordinates
|
||||
public Snake(int _x, int _y, int _len=5) {
|
||||
baseLen = _len;
|
||||
length = _len;
|
||||
public Snake(int _x, int _y) {
|
||||
length = baseLength;
|
||||
ownPos = new(_x, _y);
|
||||
// Prepare Tail based on length, position and base movement
|
||||
tailPos.Add(new(_x-mx, _y));
|
||||
for (int i = 0; i < _len-1; i++) {
|
||||
for (int i = 0; i < length-1; i++) {
|
||||
Segment previous = tailPos[0];
|
||||
Segment next = new(previous.x-mx, previous.y);
|
||||
tailPos.Insert(0, next);
|
||||
|
@ -412,7 +258,7 @@ namespace SnakeGame {
|
|||
}
|
||||
|
||||
// Constructor to copy a snake from given parameters (to avoid object reference from memory)
|
||||
public Snake(Segment _ownPos, Segment _lastPos, List<Segment> _tailPos, int _mx, int _my, int _length, int _baseLen) {
|
||||
public Snake(Segment _ownPos, Segment _lastPos, List<Segment> _tailPos, int _mx, int _my, int _length) {
|
||||
ownPos = _ownPos.Copy();
|
||||
lastPos = _lastPos.Copy();
|
||||
foreach (Segment t in _tailPos)
|
||||
|
@ -420,36 +266,6 @@ namespace SnakeGame {
|
|||
mx = _mx;
|
||||
my = _my;
|
||||
length = _length;
|
||||
baseLen = _baseLen;
|
||||
}
|
||||
|
||||
// Method to interpret a string as a serialized snake
|
||||
public static Snake Parse(string snake) {
|
||||
Snake parsedSnake = null;
|
||||
// Scratch process if any inconsistencies in the format cause trouble
|
||||
try {
|
||||
string[] attributes = snake.Split(';');
|
||||
parsedSnake = new(
|
||||
Segment.Parse(attributes[0]),
|
||||
Segment.Parse(attributes[1]),
|
||||
parseSegments(attributes[2]),
|
||||
int.Parse(attributes[3]),
|
||||
int.Parse(attributes[4]),
|
||||
int.Parse(attributes[5]),
|
||||
int.Parse(attributes[6])
|
||||
);
|
||||
}
|
||||
catch (Exception) { }
|
||||
|
||||
return parsedSnake;
|
||||
}
|
||||
|
||||
// Serialize this Snake Object into a string
|
||||
public override string ToString() {
|
||||
string segStr = "";
|
||||
for (int i = 0; i < tailPos.Count; i++)
|
||||
segStr += tailPos[i].ToString() + ((i < tailPos.Count-1) ? "-" : "");
|
||||
return $"{ownPos.ToString()};{lastPos.ToString()};{segStr};{mx};{my};{length};{baseLen}";
|
||||
}
|
||||
|
||||
// Check if any given x and y coordinates are part of this Snake Object (including Tail/Segments)
|
||||
|
@ -467,13 +283,13 @@ namespace SnakeGame {
|
|||
bool xC = ownPos.x == other.ownPos.x;
|
||||
bool yC = ownPos.y == other.ownPos.y;
|
||||
if (xC && yC)
|
||||
resetSelf(this);
|
||||
length = baseLength;
|
||||
}
|
||||
|
||||
// Check for tail collision
|
||||
foreach (Segment pos in other.tailPos)
|
||||
if (pos.x == ownPos.x && pos.y == ownPos.y) {
|
||||
resetSelf(this);
|
||||
length = baseLength;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -483,39 +299,6 @@ namespace SnakeGame {
|
|||
if (ownPos.x == _food.x && ownPos.y == _food.y) {
|
||||
length++;
|
||||
food.setRandom(width, height);
|
||||
if (isMultiplayer && this == self)
|
||||
Connection.Send(Connection.self, $"FoodUpdate {food.ToString()}");
|
||||
}
|
||||
}
|
||||
|
||||
// Method to handle a keypress for this snake
|
||||
public void keyHandler() {
|
||||
// If key is pressed, handle logic
|
||||
if (Console.KeyAvailable) {
|
||||
switch (Console.ReadKey(true).Key) {
|
||||
case ConsoleKey.Escape:
|
||||
// Exit program.
|
||||
Environment.Exit(0);
|
||||
break;
|
||||
case ConsoleKey.UpArrow:
|
||||
// Only recognise keypress if not currently heading down
|
||||
if (my != 1) { my = -1; mx = 0; }
|
||||
break;
|
||||
case ConsoleKey.DownArrow:
|
||||
// Only recognise keypress if not currently heading up
|
||||
if (my != -1) { my = 1; mx = 0; }
|
||||
break;
|
||||
case ConsoleKey.LeftArrow:
|
||||
// Only recognise keypress if not currently heading right
|
||||
if (mx != 1) { mx = -1; my = 0; }
|
||||
break;
|
||||
case ConsoleKey.RightArrow:
|
||||
// Only recognise keypress if not currently heading left
|
||||
if (mx != -1) { mx = 1; my = 0; }
|
||||
break;
|
||||
}
|
||||
// Save keypress to detect player activity
|
||||
keypressFrame = frameCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -549,19 +332,6 @@ namespace SnakeGame {
|
|||
setRandom(width, height);
|
||||
}
|
||||
|
||||
// Try parsing any given string into a Segment object. Return 'new Segment(0, 0)' as default.
|
||||
public static Segment Parse(string segment) {
|
||||
string[] splits = segment.Split(',');
|
||||
int _x = int.TryParse(splits[0], out _x) ? _x : 0;
|
||||
int _y = int.TryParse(splits[1], out _y) ? _y : 0;
|
||||
return new(_x, _y);
|
||||
}
|
||||
|
||||
// Serialize Segment object into a string
|
||||
public override string ToString() {
|
||||
return $"{x},{y}";
|
||||
}
|
||||
|
||||
// Set own x and y coordinates randomly according to give width and height boundaries
|
||||
public void setRandom(int _width, int _height) {
|
||||
Random rng = new();
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<!-- Reference to local copy of https://gitlab1.ptb.de/waltem01/csharpsocketserver -->
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SocketTest\Net.Sockets\SocketLib.csproj" />
|
||||
<Reference Include="RGBLedMatrix.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<MainEntryPoint>SnakeGame.SnakeGame</MainEntryPoint>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
|
|
Loading…
Reference in New Issue
Block a user