0

我一直在尝试使用 ncurses 库为 C++ 创建我的 roguelike 类型的游戏。在学习了许多不同的教程之后,我能够创建玩家角色、地图、防止玩家穿过墙壁的代码以及怪物角色的随机移动。

我遇到的下一个问题是实现一个布尔值,所以每当玩家角色与怪物角色交互时,游戏就会退出(很像 roguelike 游戏)。但是,我似乎无法让它以我想要的方式运行。我认为这与我为玩家和怪物设置的坐标有关,但我仍然不确定。谁能帮帮我?

这是代码:

#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;
}
4

1 回答 1

1

我会总结一下 jonhopkins 的评论。

这本质上是不一致的结果。您的代码在不同的函数中以不同的顺序传递参数(首先是 x,然后是 y isPassable,但反之亦然MonsterContact),并且对相同的事物使用不同的名称(行和 x 是相同的。)

col, row您的问题是由于您在应该通过的时候通过了 MonsterContact 的事实引起的row, col。也许你下意识地复制了你isPassable之前写的参数的顺序,忘记了参数的顺序是颠倒的。或者你暂时错误地认为 col 表示 y 而 row 表示 x。

永远记住保持你的代码尽可能的一致,这样你就可以避免将来出现这些错误。

于 2016-12-20T19:07:12.727 回答