Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- namespace ascii_game
- {
- /*
- * Open world
- *
- * GAME ENGINE ARCHITECTURE
- * some game data
- * Player (position, health)
- * Enemies (positions, health, various)
- * World data (buildings, dungeons, forests, fields)
- * Some text to describe what's happening (responds to events)
- * Characters (position, health, dialogue)
- * Elements and effects
- * Randomly generated
- * Save progress (file I/O)
- * Game Loop
- * keep track of the time
- * input
- * simulation (other loops, conditions, score/stats)
- * render
- * */
- // A struct is not allocated on the heap the way
- // a class is. It is allocated on the Stack
- // The heap refers essentially to some random place in RAM
- // For instance an array of structs are going to be adjacent
- // in memory, instead of all over RAM
- struct Vector2
- {
- // Position, Direction, Rotation, Velocity
- public int x;
- public int y;
- public Vector2(int newX, int newY)
- {
- x = newX;
- y = newY;
- }
- public Vector2(Vector2 a)
- {
- x = a.x;
- y = a.y;
- }
- }
- static class GameMath
- {
- static public bool Equals(Vector2 a, Vector2 b)
- {
- return a.x == b.x && a.y == b.y;
- }
- }
- class Game
- {
- bool running = true;
- Vector2 screenDimensions;
- Vector2 playerPosition;
- int playerHealth;
- int playerXP;
- int playerStrength;
- Vector2 bigRatPosition;
- int bigRatHealth;
- Vector2 cougarPosition;
- int cougarHealth;
- int cougarStrength;
- MyRandom random;
- public Game()
- {
- random = new MyRandom();
- random.Seed(1001);
- screenDimensions = new Vector2(24, 16);
- playerPosition = new Vector2(12, 8);
- playerHealth = 100;
- playerStrength = 2;
- bigRatPosition = new Vector2(20, 12);
- bigRatHealth = 25;
- cougarHealth = 125;
- cougarPosition = new Vector2(4, 4);
- cougarStrength = 5;
- }
- Vector2 GetPlayerInput()
- {
- ConsoleKeyInfo keyInfo = Console.ReadKey(true);
- char c = keyInfo.KeyChar;
- Vector2 movementDirection = new Vector2(0, 0);
- if (c == 'w')
- {
- movementDirection.y--;
- }
- if (c == 's')
- {
- movementDirection.y++;
- }
- if (c == 'a')
- {
- movementDirection.x--;
- }
- if (c == 'd')
- {
- movementDirection.x++;
- }
- if (c == ' ')
- {
- }
- // Read the rest of the keys when they are holding down a key because
- // we'll get input faster than we can render
- while (Console.KeyAvailable)
- {
- Console.ReadKey(true);
- }
- return movementDirection;
- }
- struct Message
- {
- // @TODO: we should really start taking types of messages
- // for instance a Hit message,
- // a dead message,
- // XP message
- // push-back message
- String thing;
- String hitter;
- int damage;
- public Message (String thing_, String hitter_, int damage_) {
- thing = thing_;
- hitter = hitter_;
- damage = damage_;
- }
- public void PrintMessage()
- {
- Console.Write(thing);
- Console.Write(" was hit by ");
- Console.Write(hitter);
- Console.Write(" for ");
- Console.Write(damage);
- Console.WriteLine();
- }
- }
- public void Update()
- {
- int messageCount = 0;
- Message[] messages = new Message[4];
- while (running) {
- messageCount = 0;
- // Input
- // Player update
- Vector2 movementDirection = GetPlayerInput();
- playerPosition.x += movementDirection.x;
- playerPosition.y += movementDirection.y;
- bool playerMoved = !GameMath.Equals(movementDirection, new Vector2(0, 0));
- // Rat update
- bool ratMoved = true;
- Vector2 prevRatPosition = new Vector2(bigRatPosition);
- Vector2 ratDirection = new Vector2(random.RandomInclusive(-1, 1), 0);
- if (ratDirection.x == 0)
- {
- ratDirection.y = random.RandomInclusive(-1, 1);
- }
- bigRatPosition.x += ratDirection.x;
- bigRatPosition.y += ratDirection.y;
- bool cougarMoved = false;
- Vector2 prevCougarPosition = new Vector2(cougarPosition);
- Vector2 cougarDirection = new Vector2(random.RandomInclusive(0, 0), 0);
- if (cougarDirection.x == 0)
- {
- cougarDirection.y = random.RandomInclusive(0, 0);
- }
- cougarPosition.x += cougarDirection.x;
- cougarPosition.y += cougarDirection.y;
- bool ratHit = false;
- bool cougarHit = false;
- bool playerHit = false;
- bool playerGainedXP = false;
- // handle case where they move into each other
- // means that they never actually occupy the same spot
- // direction (1, 0)
- // rat dir (-1, 0)
- bool playerMoveInvalid = false;
- if (cougarHealth > 0)
- {
- if (GameMath.Equals(playerPosition, cougarPosition))
- {
- if (cougarMoved)
- {
- playerHealth -= 25;
- playerHit = true;
- // TODO: push player back really far based on strength
- }
- if (playerMoved)
- {
- if (cougarStrength < playerStrength)
- {
- cougarHealth -= 10;
- cougarPosition.x += movementDirection.x;
- cougarPosition.y += movementDirection.y;
- }
- else
- {
- playerHit = true;
- playerHealth -= 25;
- playerMoveInvalid = true;
- messages[messageCount++] = new Message("Player", "Cougar", 25);
- }
- cougarHit = true;
- }
- }
- else if (GameMath.Equals(playerPosition, prevCougarPosition))
- {
- playerPosition.x -= movementDirection.x;
- playerPosition.y -= movementDirection.y;
- if (cougarMoved)
- {
- playerHealth -= 5;
- playerHit = true;
- }
- if (playerMoved)
- {
- cougarHealth -= 10;
- cougarPosition.x += movementDirection.x;
- cougarPosition.y += movementDirection.y;
- cougarHit = true;
- }
- }
- if (cougarHealth <= 0)
- {
- playerXP += 50000;
- playerGainedXP = true;
- }
- }
- if (bigRatHealth > 0)
- {
- if (GameMath.Equals(playerPosition, bigRatPosition))
- {
- if (ratMoved)
- {
- playerHealth -= 5;
- playerHit = true;
- messages[messageCount++] = new Message("Player", "Rat", 5);
- }
- if (playerMoved)
- {
- bigRatHealth -= 10;
- bigRatPosition.x += movementDirection.x;
- bigRatPosition.y += movementDirection.y;
- ratHit = true;
- messages[messageCount++] = new Message("Rat", "Player", 10);
- }
- }
- else if (GameMath.Equals(playerPosition, prevRatPosition))
- {
- playerPosition.x -= movementDirection.x;
- playerPosition.y -= movementDirection.y;
- if (ratMoved)
- {
- playerHealth -= 5;
- playerHit = true;
- messages[messageCount++] = new Message("Player", "Rat", 5);
- }
- if (playerMoved)
- {
- bigRatHealth -= 10;
- bigRatPosition.x += movementDirection.x;
- bigRatPosition.y += movementDirection.y;
- messages[messageCount++] = new Message("Rat", "Player", 10);
- ratHit = true;
- }
- }
- if (bigRatHealth <= 0)
- {
- playerXP += 5;
- playerGainedXP = true;
- }
- }
- if (playerMoveInvalid)
- {
- playerPosition.x -= movementDirection.x;
- playerPosition.y -= movementDirection.y;
- }
- // Render
- Console.Clear();
- // Instead of this just put things in a string and print it
- Vector2 cursorPosition = new Vector2(0, 0);
- for (int y = 0; y < screenDimensions.y; y++)
- {
- for (int x = 0; x < screenDimensions.x; x++)
- {
- cursorPosition.x = x;
- cursorPosition.y = y;
- if (GameMath.Equals(playerPosition, cursorPosition))
- {
- Console.Write("@");
- }
- else if (bigRatHealth > 0 && GameMath.Equals(bigRatPosition, cursorPosition))
- {
- Console.Write("R");
- }
- else if (cougarHealth > 0 && GameMath.Equals(cougarPosition, cursorPosition))
- {
- Console.Write("C");
- }
- else
- {
- Console.Write(".");
- }
- }
- Console.WriteLine();
- }
- if (cougarHit)
- {
- if (cougarHealth > 0)
- {
- Console.WriteLine("Cougar was barely hurt");
- }
- }
- if (playerGainedXP)
- {
- Console.WriteLine("Player gained 5 XP");
- }
- for (int i = 0; i < messageCount; i++) {
- messages[i].PrintMessage();
- }
- }
- }
- }
- class MyRandom
- {
- int seed;
- int state;
- int multiplier = 98765;
- int increment = 100554387;
- // Only seed once per instance of class
- // public means that other "calling sites" can look
- // at the variable, or use the function, or change
- // the value of the variable, etc
- public void Seed(int n)
- {
- seed = n;
- state = seed;
- }
- public int Random()
- {
- state = state * multiplier + increment;
- int result = state;
- // Since it right shifts and only 0s will fill in the left
- // 1000 >> 3 = 0001
- // this number is guaranteed(?) to be non-negative so keep in mind
- //return (result >> 16) & 0x7FFF;
- return result;
- }
- // Method/function overloading is when the functions share the same name
- // but take different arguments
- public int Random(int upperLimit)
- {
- int result = Random() % upperLimit;
- return result;
- }
- // Note that this upper limit is exclusive, not inclusive
- public int Random(int lowerLimit, int upperLimit)
- {
- int range = upperLimit - lowerLimit;
- int result = lowerLimit + (Random() % range);
- if (result < lowerLimit)
- {
- result += range;
- }
- return result;
- }
- // six sided dice RandomInclusive(1, 6);
- public int RandomInclusive(int lowerLimit, int upperLimit)
- {
- return Random(lowerLimit, upperLimit + 1);
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- Game game = new Game();
- game.Update();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement