简体   繁体   中英

How to get Player to interact with Monster using ncurses library?

I've been trying to create my roguelike type of game for C++ using the ncurses library. After following many different tutorials, I am able to create the Player character, the map, the code to prevent the Player from going through walls and the random movements for the Monster character.

The next problem I'm encountering is implementing a boolean so whenever the Player character interacts with the Monster character, the game will quit (much like the roguelike games). However, I can't seem to get it to function the way I wanted. I think it has to do with the coordinates that I have set for the Player and the Monster but I'm still not sure. Can anyone help me out please?

Here is the code:

#include <iostream>
#include <ncurses.h>

#define MAP_WIDTH 22
#define MAP_HEIGHT 15

#define TILE_FLOOR 0
#define TILE_WALL 1

int PlayerX, PlayerY;

void erase (int y, int x) {
    mvaddch(y, x, '.');
}

int nMapArray[MAP_HEIGHT][MAP_WIDTH] = {
    { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
    { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
    { 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1 },
    { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
    { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1 },
    { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1 },
    { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1 },
    { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
};

bool IsPassable (int nMapX, int nMapY) {            //prevents from walking into walls

    if (nMapX < 0 || nMapX >= MAP_WIDTH || nMapY < 0 || nMapY >= MAP_HEIGHT)
        return false;

    int nTileValue = nMapArray[nMapY][nMapX];

    if( nTileValue == TILE_FLOOR) {
        return true;
    }

    return false;
}

class Monster {
public:
    void Appearance(char monster) {
        this->Monster = monster;
    }

    void SetPos(int x, int y) {
        this->PosX = x;
        this->PosY = y;
    }

    void Movement(int &MonsX, int &MonsY) {
        int x = (rand() % 3 - 1);
        int y = (rand() % 3 - 1);

        if (IsPassable(this->PosX+x, this->PosY+y)) {
            erase(PosY, PosX);
            MonsX = this->PosX += x;
            mvaddch(this->PosY, MonsX, this->Monster);
            refresh();

            erase(PosY, PosX);
            MonsY = this->PosY += y;
            mvaddch(MonsY, this->PosX, this->Monster);
            refresh();
        }
    }


protected:
    int PosX;
    int PosY;
    char Monster;
};

bool MonsterContact (int nMapY, int nMapX, int x, int y) {


    if (nMapArray[nMapY][nMapX] == nMapArray[y][x]) {
        return true;
    }

    return false;
}

void map() {
    for (int y = 0; y < MAP_HEIGHT; y++) {          //loops to print the map

        move(y,0);

        for (int x = 0; x < MAP_WIDTH; x++) {
            switch (nMapArray[y][x]) {
                case TILE_FLOOR:
                    printw(".");
                    break;

                case TILE_WALL:
                    printw("#");
                    break;
            }
        }
    }
};

void init() {               //starts the ncurses screen.
    initscr();
    clear();
    noecho();
    raw();
    keypad(stdscr, TRUE);
    curs_set(0);
}

void game_loop (char Player, int row, int col, int ch) {

    Monster npc;
    npc.SetPos(7, 8);
    npc.Appearance('g');
    int MonsX,MonsY;

    mvaddch(row,col, Player);                   //player movement
    refresh();

    while(true) {

        npc.Movement(MonsX, MonsY);

        ch = getch();

        switch (ch) {

            case 'w':
                if (IsPassable(col, row-1)) {
                erase(row,col);
                row = row - 1;
                mvaddch(row, col, Player);
                    refresh();
                }

                if (MonsterContact(col, row, MonsX, MonsY)) {
                    return();
                }
                break;

            case 's':
                if (IsPassable(col, row+1)) {
                erase(row, col);
                row = row + 1;
                mvaddch(row, col, Player);
                    refresh();
                }

                if (MonsterContact(col, row, MonsX, MonsY)) {
                    return();
                }

                break;

            case 'a':
                if (IsPassable(col-1, row)) {
                erase(row,col);
                col = col - 1;
                mvaddch(row, col, Player);
                    refresh();
                }

                if (MonsterContact(col, row, MonsX, MonsY)) {
                    return();
                }

                break;

            case 'd':
                if (IsPassable(col+1, row)) {
                erase(row,col);
                col = col + 1;
                mvaddch(row,col, Player);
                    refresh();
                }

                if (MonsterContact(col, row, MonsX, MonsY)) {
                    return();
                }

                break;

            case 'q':
                return;

            default:
                break;
        }

    }
}

int main(int argc, const char * argv[]) {

    PlayerX = 2, PlayerY = 1;        //Player initial position.
    char Player = '@';

    init();                     //starts the ncurses screen.

    printw("Press any key to start the game");
    int ch = getch();
    clear();

    map();
    game_loop(Player, PlayerY, PlayerX, ch);

    endwin();

    return 0;
}

I'll sum up what jonhopkins commented on.

This is essentially a result of inconsistency. Your code passes arguments in different orders in different functions (first x, then y in isPassable , but vice versa in MonsterContact ), and uses different names for the same things (row and x are the same.)

Your problem is caused by the fact that you passed col, row into MonsterContact, when you should have passed row, col . Perhaps you subconsciously copied the order of arguments from when you wrote isPassable a little earlier, forgetting that the order of arguments is reversed. Or you momentarily mistakenly thought that col meant y and row meant x.

Always remember to keep your code as consistent as possible, and you can avoid these sorts of mistakes in the future.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM