One of my first programming projects. I tried to learn C and use curses...it is quite embarrassing looking back at it now :D
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

374 lines
8.8 KiB

#include <ncurses.h>
#include <string.h>
#define MAX_PROJECTILES 2
#define MAX_ZOMBIES 1000
#define MAX_ALIVE 10
int scrRows,scrCols;
int viewportWinRows,viewportWinCols;
int lastPressed;
WINDOW* viewportWin;
WINDOW* scoreWin;
struct Projectile{
int isAlive;
char symbol;
int curXpos;
int curYpos;
int prevYpos;
int prevXpos;
int nextYpos;
int nextXpos;
int range;
char direction;
int distanceTraveled;
};
struct Projectile projectiles[MAX_PROJECTILES];
struct Weapon{
char name[10];
int range;
int maxCapacity;
int curCapacity;
char projectileSymbol;
char symbols[8];
};
struct Entity {
char *type;
char symbol;
int curYpos, curXpos;
int nextYpos, nextXpos;
struct Weapon weapons[8];
int curWeapon;
int isAlive;
};
struct Entity player = {.type="player",.symbol='@', .curYpos=1, .curXpos=1, .nextYpos=1, .nextXpos=1 ,.isAlive=1};
struct Entity zombies[MAX_ZOMBIES];
struct Entity allEntities[MAX_ALIVE];
struct Entity zombie = {.type="zombie", .symbol='A', .curYpos=5, .curXpos=5, .nextYpos=5, .nextXpos=5 ,.isAlive=1};
struct Weapon pistol = {.name="Pistol", .range=3, .maxCapacity=12, .curCapacity=12, .symbols="-\\|/-\\|/"};
struct Entity * collisionDetect(int objYpos, int objXpos){
int i;
for(i=1; i<MAX_ALIVE; i++){
if(allEntities[i].isAlive){
if(objYpos==allEntities[i].curYpos && objXpos==allEntities[i].curXpos){
return &allEntities[i];
}
}
}
}
void moveProjectiles(){
int i;
for(i=0; i<MAX_PROJECTILES; i++){
if(projectiles[i].isAlive){
projectiles[i].prevYpos=projectiles[i].curYpos;
projectiles[i].prevXpos=projectiles[i].curXpos;
switch(projectiles[i].direction){
case 'w':{
projectiles[i].curYpos--;
break;
}
case 'a':{
projectiles[i].curXpos--;
break;
}
case 's':{
projectiles[i].curYpos++;
break;
}
case 'd':{
projectiles[i].curXpos++;
break;
}
}
projectiles[i].distanceTraveled++;
mvwaddch(viewportWin, projectiles[i].curYpos, projectiles[i].curXpos, projectiles[i].symbol);
struct Entity * hitEntity = collisionDetect(projectiles[i].curYpos, projectiles[i].curXpos);
if(hitEntity){
if(hitEntity->type=="zombie"){
projectiles[i].isAlive=0;
hitEntity->isAlive=0;
mvwaddch(viewportWin, allEntities[i].curYpos, allEntities[i].curXpos, ' ');
}
}
if(mvwinch(viewportWin,projectiles[i].prevYpos, projectiles[i].prevXpos)==projectiles[i].symbol){
mvwaddch(viewportWin, projectiles[i].prevYpos, projectiles[i].prevXpos, ' ');
}
if(projectiles[i].distanceTraveled>=projectiles[i].range || projectiles[i].curYpos > viewportWinRows || projectiles[i].curYpos < 0 || projectiles[i].curXpos > viewportWinCols || projectiles[i].curXpos < 0){
projectiles[i].isAlive=0;
mvwaddch(viewportWin, projectiles[i].curYpos, projectiles[i].curXpos, ' ');
}
usleep(30000);
}
else{
mvwaddch(viewportWin, projectiles[i].curYpos, projectiles[i].curXpos, ' ');
}
}
}
void fireWeapon(struct Weapon *weaponRef, char *direction){
struct Projectile projectile;
if (!strcmp(weaponRef->name,"Pistol")){
projectile.range=20;
}
projectile.isAlive=1;
projectile.distanceTraveled=0;
projectile.curYpos=allEntities[0].curYpos;
projectile.curXpos=allEntities[0].curXpos;
if(direction=="up"){
projectile.range*=.4;
projectile.direction='w';
projectile.symbol=weaponRef->symbols[2];
}
if(direction=="left"){
projectile.direction='a';
projectile.symbol=weaponRef->symbols[0];
}
if(direction=="down"){
projectile.range*=.4;
projectile.direction='s';
projectile.symbol=weaponRef->symbols[6];
}
if(direction=="right"){
projectile.direction='d';
projectile.symbol=weaponRef->symbols[4];
}
int i;
for(i=0;i<MAX_PROJECTILES;i++){
if(!projectiles[i].isAlive && !projectiles[i+1].isAlive){
projectiles[i]=projectile;
allEntities[0].weapons[allEntities[0].curWeapon].curCapacity--;
break;
}
}
}
void drawScore(){
werase(scoreWin);
box(scoreWin, 0, 0);
mvwprintw(scoreWin, 1, 1, "Current Weapon: %s",allEntities[0].weapons[allEntities[0].curWeapon].name);
mvwprintw(scoreWin, 2, 1, "Ammo: %d/%d",allEntities[0].weapons[allEntities[0].curWeapon].curCapacity,allEntities[0].weapons[allEntities[0].curWeapon].maxCapacity);
wnoutrefresh(scoreWin);
}
void drawViewport(){
box(viewportWin,0,0);
int i;
for(i=0; i<MAX_ALIVE; i++){
if(allEntities[i].isAlive){
mvwaddch(viewportWin, allEntities[i].curYpos, allEntities[i].curXpos, ' ');
mvwaddch(viewportWin, allEntities[i].nextYpos, allEntities[i].nextXpos, allEntities[i].symbol);
allEntities[i].curYpos = allEntities[i].nextYpos;
allEntities[i].curXpos = allEntities[i].nextXpos;
}
}
wnoutrefresh(viewportWin);
doupdate();
}
struct possiblePos{
int x;
int y;
}openPos;
int getOpenPos(){
int chooseAnother=1;
while(chooseAnother){
spaceExists:
openPos.y=(rand()%(viewportWinRows-1)+1);
openPos.x=(rand()%(viewportWinCols-1)+1);
if(mvwinch(viewportWin,openPos.y,openPos.x)==' '){
int i;
for(i=1;i<MAX_ALIVE;i++){
if(allEntities[i].isAlive && allEntities[i].curYpos==openPos.y && allEntities[i].curXpos==openPos.x){
chooseAnother=1;
}
else{
chooseAnother=0;
}
}
}
else{
int x,y;
for(y=0;y<viewportWinRows;y++){
for(x=0;x<viewportWinCols;x++){
if(mvwinch(viewportWin,y,x)==' '){
chooseAnother=1;
goto spaceExists;
}
}
}
return 0;
}
}
return 1;
}
void addZombie(){
if(getOpenPos()){
int i;
for(i=0;i<MAX_ALIVE-1;i++){
if(!allEntities[i].isAlive){
struct Entity zombie;
zombie.curYpos=openPos.y;
zombie.curXpos=openPos.x;
zombie.nextYpos=openPos.y;
zombie.nextXpos=openPos.x;
zombie.type="zombie";
zombie.symbol='Z';
zombie.isAlive=1;
allEntities[i]=zombie;
mvwaddch(viewportWin, allEntities[i].curYpos, allEntities[i].curXpos, allEntities[i].symbol);
wnoutrefresh(viewportWin);
doupdate();
break;
}
}
}
}
void initializeWorld() {
curs_set(0);
getmaxyx(stdscr,scrRows,scrCols);
viewportWin=newwin(scrRows-10,scrCols,0,0);
getmaxyx(viewportWin,viewportWinRows,viewportWinCols);
scoreWin=newwin(10,scrCols,scrRows-10,0);
allEntities[0]=player;
allEntities[0].curYpos=(rand()%(viewportWinRows-2))+1;
allEntities[0].curXpos=(rand()%(viewportWinCols-2))+1;
10;
allEntities[0].nextYpos=allEntities[0].curYpos;
allEntities[0].nextXpos=allEntities[0].curXpos;
allEntities[1]=zombie;
allEntities[1].curYpos=(rand()%(viewportWinRows-2))+1;
allEntities[1].curXpos=(rand()%(viewportWinCols-2))+1;
11;
allEntities[1].nextYpos=allEntities[1].curYpos;
allEntities[1].nextXpos=allEntities[1].curXpos;
}
int main() {
srand(time(NULL));
initscr();
cbreak();
keypad(stdscr, TRUE);
noecho();
initializeWorld();
nodelay(stdscr, TRUE);
int ch;
allEntities[0].weapons[0]=pistol;
allEntities[0].curWeapon=0;
while(1) {
drawScore();
drawViewport();
addZombie();
moveProjectiles();
doupdate();
ch = getch();
switch(ch){
case 'w':
case 'W':{
if(allEntities[0].curYpos > 1){
allEntities[0].nextYpos--;
if(allEntities[0].nextYpos < 0){
allEntities[0].nextYpos = 0;
}
}
break;
}
case 's':
case 'S':{
if(allEntities[0].curYpos < viewportWinRows - 2){
allEntities[0].nextYpos++;
if(allEntities[0].nextYpos > viewportWinRows-1){
allEntities[0].nextYpos = viewportWinRows-1;
}
}
break;
}
case 'a':
case 'A':{
if(allEntities[0].curXpos > 1){
allEntities[0].nextXpos--;
if(allEntities[0].nextXpos < 0){
allEntities[0].nextXpos = 0;
}
}
break;
}
case 'd':
case 'D':{
if(allEntities[0].curXpos < scrCols-2){
allEntities[0].nextXpos++;
if(allEntities[0].nextXpos > viewportWinCols-1){
allEntities[0].nextXpos = viewportWinCols-1;
}
}
break;
}
case 'z':
case 'Z':{
addZombie();
break;
}
case KEY_UP:{
if(allEntities[0].weapons[allEntities[0].curWeapon].curCapacity>0){
fireWeapon(&pistol, "up");
}
break;
}
case KEY_LEFT:{
if(allEntities[0].weapons[allEntities[0].curWeapon].curCapacity>0){
fireWeapon(&pistol, "left");
}
break;
}
case KEY_DOWN:{
if(allEntities[0].weapons[allEntities[0].curWeapon].curCapacity>0){
fireWeapon(&pistol, "down");
}
break;
}
case KEY_RIGHT:{
if(allEntities[0].weapons[allEntities[0].curWeapon].curCapacity>0){
fireWeapon(&pistol, "right");
}
break;
}
default:
if (ch != ERR) {lastPressed=ch;};
break;
}
struct Entity * hitEntity = collisionDetect(allEntities[0].curYpos, allEntities[0].curXpos);
if(hitEntity){
if(hitEntity->type=="zombie"){
mvwprintw(viewportWin,1,10,"TEST");
allEntities[0].isAlive=0;
mvwaddch(viewportWin, allEntities[0].curYpos, allEntities[0].curXpos, ' ');
}
}
}
return 0;
}