Created
May 3, 2021 13:18
-
-
Save smvd/a8a83e724549a22d1a078f06ef33b87a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
____ _____ _ ____ __ __ _____ | |
| _ \| ____| / \ | _ \ | \/ | ____| | |
| |_) | _| / _ \ | | | | | |\/| | _| | |
| _ <| |___ / ___ \| |_| | | | | | |___ | |
|_| \_\_____/_/ \_\____/ |_| |_|_____| | |
<--[ GENERAL ]--> | |
This is a simple game meant to be fun yet simple. | |
It uses ANSI codes to make it run without flicker compared to most small terminal games. | |
These codes currently need to be activated on windows 10 so lookup a guide. | |
The command i used to compile the game was: | |
GCC source.c resource.o -o SS.exe -Wall -Werror -W -lpthread | |
GCC : MinGw compiler | |
source.c : Source code | |
resource.o : ICON and version info (not required) | |
-o SS.exe : Set output file to SS.exe | |
-Wall : All warning about questionable code | |
-Werror : Make all warnings into errors | |
-W : Inhibit all warning messages | |
-lpthread : Link the pthread library | |
It was built on windows for windows. | |
But if you are on linux or OS X some google foo should get you some suitable replacements. | |
Under the spaceships section you will find my simple ship designs. | |
Under the controls section you will find the controls for the game | |
Under the info section you will find some basic info about the game build | |
The whole game falls under unlicense, but please plug my channel and leave this readme. | |
I cant force you but i can kindly ask. | |
<--[ SPACESHIPS ]--> | |
PLAYER: | |
/]\ | |
<]()]]C> | |
\]/ | |
ENEMY: | |
/-| | |
<( [>C> | |
\-| | |
<--[ CONTROLS ]--> | |
W : UP | |
S : DOWN | |
Q : QUIT | |
SPACE : FIRE | |
<--[ INFO ]--> | |
Font : Cascadia Code (Its suggested not needed) | |
Reddit : No_War3219 | |
Editor : Sublime text 3 | |
Discord : smvd#4197 | |
Version : 2.0 | |
License : www.unlicense.org | |
Youtube : www.rebrand.ly/eclips-coding | |
Compiler : GCC | |
Platform : WINDOWS | |
Terminal : Windows Terminal CMD (Default, not previeuw) | |
StackOverflow : smvd | |
*/ | |
#include <pthread.h> // Header for multithreading | |
#include <windows.h> // Header for working with windows | |
#include <string.h> // Header for string manipulation | |
#include <conio.h> // Header for general use | |
#include <stdio.h> // Header for input & output | |
#include <time.h> // Header for time | |
#define NC "\e[0m" // NC = ANSI code for white text | |
#define RED "\e[31m" // RED = ANSI code for red text | |
#define GREEN "\e[32m" // GREEN = ANSI code for green text | |
#define YELLOW "\e[33m" // YELLOW = ANSI code for yellow text | |
#define BLUE "\e[34m" // BLUE = ANSI code for blue text | |
typedef struct // Defining custom variable | |
{ | |
int x; // Variable for the X position | |
int y; // Variable for the Y position | |
}PIX; // Variable name = PIX | |
PIX bullets[100]; // Variable array for the bullets | |
PIX enemy; // Variable for the enemy | |
int bulletCount = 0; // Variable for the bullet count | |
int fire = 0; // Variable for the frames since last shot | |
int playerY = 8; // Variable for the player Y position | |
int FIRERATE = 500; // Variable for the fire rate | |
int SPEED = 75; // Variable for the delay between frames | |
pthread_t inputThread; // Varialbe for the input thread | |
char input = '\0'; // Variable for the user input | |
void *In(); // Function to get user input | |
void Move(); // Function to move elements | |
void Draw(); // Function to draw the game | |
void Start(); // Function to prepare the game | |
void HitTest(); // Function to test for hits | |
void SpawnEnemy(); // Function to spawn a new enemy | |
void SpawnBullet(); // Function to spawn a new bullet | |
void DespawnBullet(int idx); // Function to despawn bullet | |
int InPlayer(); // Function to test if in player | |
int IsBullet(int x, int y); // Function to test if there is a bullet at X,Y | |
void *In() // Function for getting user input | |
{ | |
while (1) // Loop for ever | |
{ | |
input = getch(); // Store the pressed key in input | |
} | |
} | |
void Move() // Function to move elements | |
{ | |
enemy.x--; // Remove 1 from the enemy x | |
HitTest(); // Test for hits | |
for ( // For | |
int i = 0; // Variable to hold the loop count | |
i < bulletCount; // While i is less then bullet count | |
i++ // Add 1 to i | |
) | |
{ | |
if (bullets[i].x >= 33) // If bullet x is greater then or equal to 33 | |
{ | |
DespawnBullet(i); // Despawn the bullet | |
} | |
bullets[i].x += 2; // Add 2 to the bullet x | |
} | |
switch (input) // Test if input | |
{ | |
case 'w': // Equals W | |
if (playerY > 1) // If player y is larger then 1 | |
{ | |
playerY--; // Remove 1 from the player y | |
} | |
break; // End test | |
case 's': // Equals S | |
if (playerY < 15) // If player y is less then 15 | |
{ | |
playerY++; // Add 1 to player y | |
} | |
break; // End test | |
case ' ': // Equals SPACE | |
if (fire == 0) // If fire equals 0 | |
{ | |
SpawnBullet(); // Spawn a new bullet | |
} | |
break; // End test | |
case 'q': // Equals Q | |
exit(0); // Exit game | |
break; // End test | |
} | |
input = '\0'; // Set input to 0x00 | |
} | |
void Draw() // Function to draw the game | |
{ | |
char buff[5000]; // Buffer variable | |
strcpy(buff, "\e[20A"); // Copy "move up 20 lines" into the buffer | |
strcat(buff, "\e[34D"); // Append "move back 34 characters" to the buffer | |
strcat(buff, NC "Press Q to quit, W & S to move, SPACE to shoot\n"); // Append "Press Q to quit, W & S to move, SPACE to shoot\n" to the buffer in white | |
for ( // For | |
int y = 0; // Variable to hold the loop count | |
y < 19; // While y is less then 19 | |
y++ // Add 1 to y each loop | |
) | |
{ | |
for ( // For | |
int x = 0; // Variable to hold the loop count | |
x < 34; // While x is less then 34 | |
x++ // Add 1 to x each loop | |
) | |
{ | |
if ( // If | |
x == 0 || // X == 0 | |
x == 33 || // Or X == 3 | |
y == 0 || // Or Y == 0 | |
y == 18 // Or Y == 18 | |
) | |
{ | |
strcat(buff, NC "[]"); // Append "[]" to the buffer in white | |
} | |
else if ( // Else if | |
y == playerY && // Y equals player y | |
( | |
x == 2 || // And x equals 2 | |
x == 3 // Or x equals 3 | |
) | |
) | |
{ | |
if (x == 2) // If x equals 2 | |
{ | |
strcat(buff, GREEN " /"); // Append " /" to the buffer in green | |
} | |
else if (x == 3) // Else if x equals 3 | |
{ | |
strcat(buff, GREEN "]\\"); // Append "]\" to the buffer in green | |
} | |
} | |
else if ( // Else if | |
y == playerY + 1 && // Y equals player y + 1 | |
x >= 2 && // And x is greater then or equal to 2 | |
x <= 5 // And x is less then or equal to 5 | |
) | |
{ | |
switch(x) // Test x | |
{ | |
case 2: // If 2 | |
strcat(buff, GREEN "<]"); // Append "<]" to the buffer in green | |
break; // End test | |
case 3: // If 3 | |
strcat(buff, GREEN "()"); // Append ()"" to the buffer in green | |
break; // End test | |
case 4: // If 4 | |
strcat(buff, GREEN "]]"); // Append "]]" to the buffer in green | |
break; // End test | |
case 5: // If 5 | |
strcat(buff, GREEN "C>"); // Append "C>" to the buffer in green | |
break; // End test | |
} | |
} | |
else if ( // Else if | |
y == playerY + 2 && // Y equals player y + 2 | |
( | |
x == 2 || // And x equals 2 | |
x == 3 // Or x equals 3 | |
) | |
) | |
{ | |
if (x == 2) // If x equals 2 | |
{ | |
strcat(buff, GREEN " \\"); // Append " \" to the buffer in green | |
} | |
else if (x == 3) // Else if x equals 3 | |
{ | |
strcat(buff, GREEN "]/"); // Append "]/" to the buffer in green | |
} | |
} | |
else if (IsBullet(x, y)) // Else if X,Y in bullet | |
{ | |
strcat(buff, RED "()"); // Append "()" to the buffer in red | |
} | |
else if ( // Else if | |
x >= enemy.x && // X is greater then or equal to enemy x | |
x <= enemy.x + 3 && // And x is less then or equal to enemy x + 3 | |
y == enemy.y // And y equals enemy y | |
) | |
{ | |
if (x == enemy.x) // If x equals enemy x | |
{ | |
strcat(buff, BLUE " <"); // Append " <" to the buffer in blue | |
} | |
else if (x == enemy.x + 1) // Else if x equals enemy x + 1 | |
{ | |
strcat(buff, BLUE "( "); // Append "( " to the buffer in blue | |
} | |
else if (x == enemy.x + 2) // Else if x equals enemy x + 2 | |
{ | |
strcat(buff, BLUE "[>"); // Append "[>" to the buffer in blue | |
} | |
else if (x == enemy.x + 3) // Else if x equals enemy x + 3 | |
{ | |
strcat(buff, YELLOW "C>"); // Append "C>" to the buffer in yellow | |
} | |
} | |
else if ( // Else if | |
( | |
x == enemy.x + 1 || // X equals enemy x + 1 | |
x == enemy.x + 2 // Or X equals enemy x + 2 | |
) && // And | |
y == enemy.y - 1 // Y equals enemy y - 1 | |
) | |
{ | |
if (x == enemy.x + 1) // If x equals enemy x + 1 | |
{ | |
strcat(buff, BLUE " /"); // Append " /" to the buffer in blue | |
} | |
else if (x == enemy.x + 2) // Else if x equals enemy x + 2 | |
{ | |
strcat(buff, BLUE "-|"); // Append "-|" to the buffer in blue | |
} | |
} | |
else if ( // Else if | |
( | |
x == enemy.x + 1 || // X equals enemy x + 1 | |
x == enemy.x + 2 // Or X equals enemy x + 2 | |
) && // And | |
y == enemy.y + 1 // Y equals enemy y + 1 | |
) | |
{ | |
if (x == enemy.x + 1) // If x equals enemy x + 1 | |
{ | |
strcat(buff, BLUE " \\"); // Append " \" to the buffer in blue | |
} | |
else if (x == enemy.x + 2) // Else if x equals enemy x + 2 | |
{ | |
strcat(buff, BLUE "-|"); // Append "-|" to the buffer in blue | |
} | |
} | |
else // Else | |
{ | |
strcat(buff, NC " "); // Append " " to the buffer in white | |
} | |
} | |
strcat(buff, "\n"); // Append a new line to the buffer | |
} | |
printf(buff); // Display the buffer | |
} | |
void Start() // Function to setup for the game | |
{ | |
for (int i = 0; i < 20; i++) // Loop 20 times | |
{ | |
printf("\n"); // Write a new line | |
} | |
pthread_create(&inputThread, NULL, In, NULL); // Make a new thread from the function In | |
srand(time(0)); // Set the seed for the random number generator to the current UNIX time stamp | |
SpawnEnemy(); // Spawn a enemy | |
} | |
void HitTest() // Function to test for hits | |
{ | |
if (enemy.x == -1) // If enemy x equals -1 | |
{ | |
exit(0); // End game | |
} | |
if (InPlayer()) // If in player | |
{ | |
exit(0); // End game | |
} | |
for ( | |
int i = 0; // Variable to hold the loop count | |
i < bulletCount; // While i is less then bullet count | |
i++ // Add 1 to i each loop | |
) | |
{ | |
if ( // If | |
bullets[i].y >= enemy.y - 1 && // Bullet y is greater then or equal to enemy y - 1 | |
bullets[i].y <= enemy.y + 1 && // And bullet y is less then or equal to enemy y + 1 | |
bullets[i].x >= enemy.x && // And bullet x is greater then or equal to enemy x | |
bullets[i].x <= enemy.x + 2 // And bullet x is less then or equal to enemy x + 2 | |
) | |
{ | |
SpawnEnemy(); // Spawn enemy | |
DespawnBullet(i); // Despawn bullet | |
} | |
} | |
} | |
void SpawnEnemy() // Function to spawn a enemy | |
{ | |
enemy.y = ((rand() % (16 - 2 + 1)) + 2); // Set enemy y to a random number between 16 and 1 | |
enemy.x = 32; // Set enemy x to 32 | |
} | |
void SpawnBullet() // Function to spawn a bullet | |
{ | |
fire = FIRERATE / SPEED; // Set fire to the fire rate devided by the speed = the ammount of frames untill we have passed FIRERATE milliseconds | |
bullets[bulletCount].x = 6; // Set bullet x to 6 | |
bullets[bulletCount].y = playerY + 1; // Set bullet y to player y + 1 | |
bulletCount++; // Add 1 to bullet count | |
} | |
void DespawnBullet(int idx) // Function to despawn bullet at IDX | |
{ | |
for ( // For | |
int i = idx; // Variable to hold loop value | |
i < bulletCount; // While i is less then bullet count | |
++i // Add 1 to i each loop | |
) | |
{ | |
bullets[i] = bullets[i + 1]; // Replace the value of bullet with the value of the next bullet | |
} | |
bulletCount--; // Remove 1 from the bullet count | |
} | |
int InPlayer() // Function to test if in player | |
{ | |
if ( // If | |
enemy.x == 4 && // Enemy x equals 4 | |
enemy.y == playerY + 1 // And enemy y equals player y + 1 | |
) | |
{ | |
return 1; // Return TRUE | |
} | |
if ( // If | |
enemy.x == 3 && // enemy x equals 3 | |
( | |
enemy.y == playerY || // And enemy y equals player y | |
enemy.y == playerY + 2 // Or enemy y equals player y + 2 | |
) | |
) | |
{ | |
return 1; // Return TRUE | |
} | |
if ( // If | |
enemy.x == 1 && // Enemy x equals 1 | |
( | |
enemy.y == playerY + 3 || // And enemy y equals player y + 3 | |
enemy.y == playerY - 1 // Or enemy y equals player y - 1 | |
) | |
) | |
{ | |
return 1; // Return TRUE | |
} | |
return 0; // Return FALSE | |
} | |
int IsBullet(int x, int y) // Function to test if there is a bullet at X,Y | |
{ | |
for ( // For | |
int i = 0; // Variable to hold loop count | |
i < bulletCount; // While i is less then bullet count | |
i++ // Add 1 to i ever loop | |
) | |
{ | |
if ( // If | |
bullets[i].x == x && // Bullet x equals x | |
bullets[i].y == y // And bullet y equals y | |
) | |
{ | |
return 1; // Return TRUE | |
} | |
} | |
return 0; // Return FALSE | |
} | |
int main() // Main entry point | |
{ | |
Start(); // Setup for the game | |
while (1) // Loop for ever | |
{ | |
Move(); // Make any moves | |
Draw(); // Draw the game | |
if (fire != 0) // If fire isnt equal to 0 | |
{ | |
fire--; // Remove 1 from fire | |
} | |
Sleep(SPEED); // Wait SLEEP milliseconds | |
} | |
Draw(); // Draw the game | |
return 0; // Exit normaly | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment