Стреляйте в более чем одну пулю в этой игре 1D C ++ - PullRequest
0 голосов
/ 11 января 2019

Прежде всего, позвольте мне показать вам мой код (предположим, он находится в основной функции):

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <conio.h>

int main(){

bool exit = false;

int g_x = 33;
int g_brx = 40;
int g_blx[5];

CONSOLE_SCREEN_BUFFER_INFO csbi;
int columns, rows;

GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
const int WIDTH = columns;//info->dwSize.X;


do {
    //Render
    for (int i = 0; i < WIDTH; i++) {
        if (i == g_x) printf("x");
        else if (i == g_blx[0]) printf("<");
        else if (i == g_blx[1]) printf("<");
        else if (i == g_blx[2]) printf("<");
        else if (i == g_blx[3]) printf("<");
        else if (i == g_blx[4]) printf("<");

        else if (i == g_brx) printf(">");
        else printf("-");
    }

    for (int i = 0; i < 5; i++) {
        //Process input
        if (_kbhit()) {
            char ch = _getch();
            switch (ch) {
            case 'h': if (g_x > 0) g_x--; break;
            case 'l': if (g_x < WIDTH - 1) g_x++; break;
            case 'j': if (g_blx[i] < 0) g_blx[i] = g_x - 1; break;
            case 'k': if (g_brx < 0) g_brx = g_x + 1; break;
            case 27: exit = true; break;
            }
        }
    }

    //Move bullets
    for(int i = 0; i < 5; i++)
        if (g_blx[i] >= 0) g_blx[i]--;
    if (g_brx >= 0) g_brx++;
    if (g_brx >= WIDTH) g_brx = -1;

    Sleep(50);
} while (!exit);
}

Этот код печатает в каждой итерации строку размером WIDTH, которая может быть либо «x» (игрок), «<» (пули, выпущенные влево), «>» (пули, выстреленные вправо side) или "-" (это символ, который используется, когда нет ничего из того, что было напечатано ранее).

Затем он обрабатывает входные данные игроков и определяет, был ли игрок перемещен или была выпущена пуля. Затем он просто перемещает пули. (Я не знаю, правильно ли я объяснил, потому что английский не мой родной язык. В любом случае, я приглашаю вас запустить его, чтобы посмотреть, как он работает).

То, что я пытаюсь сделать (безуспешно), - выстрелить более 1 пули с каждой стороны, хотя сначала я пытаюсь использовать только одну сторону, до 5 пуль. Но я не могу решить это. Я попытался использовать массивы для g_blx и g_brx (переменные маркера), а затем зациклить их, но он просто не будет правильно вводить данные и поэтому не будет печатать 1 маркер после нажатия клавиши.

Любая помощь будет оценена. Заранее большое спасибо.

Ответы [ 2 ]

0 голосов
/ 11 января 2019

Я бы использовал стандартный контейнер C ++, такой как std::vector, для отслеживания ваших маркеров, а также создал бы класс Bullet для хранения свойств каждого маркера, таких как его положение, направление и способ его рисования (в настоящее время). только < или >). Вот пример, сделанный с VS2017 с комментариями в коде:

#include "pch.h"
#include <iostream>
#include <string>
#include <vector>

#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <conio.h>

// a class describing a bullet
class Bullet {
    int speed; // direction
    int x;     // current position
    char ch;   // its visual representation
public:
    // constructor
    Bullet(int X, int Speed, int Ch) : speed(Speed), x(X), ch(Ch) {}
    // accessors
    inline int getX() const { return x; }
    inline char getChar() const { return ch; }
    // telling the bullet to do its thing
    void Move() { x += speed; }
};

// a class to maintain a number of bullets
class BulletList {
    static constexpr size_t MaxNumberOfBullets = 5;
    std::vector<Bullet> bullets; // storage for Bullet objects
    int max_x; // the last column
public:
    // constructor
    BulletList(int columns) : bullets(), max_x(columns-1) {
        bullets.reserve(MaxNumberOfBullets);
    }
    // method to add a bullet (if we haven't reached MaxNumberOfBullets yet)
    bool AddBullet(int x, int speed, char ch) {
        if (bullets.size() < MaxNumberOfBullets) {
            bullets.emplace_back(x, speed, ch);
            return true;
        }
        return false;
    }
    // method to tell all bullets to move and remove
    // those who's left the playing ground
    void MoveBullets() {
        for (auto it = bullets.begin(); it != bullets.end();) {
            it->Move();
            if (it->getX() < 0 || it->getX() > max_x) it = bullets.erase(it);
            else ++it;
        }
    }
    // method to "paint" all bullets in a prepared graphical buffer
    void addBulletsToGraph(std::string& line) const {
        for (const auto&b : bullets) 
            line[b.getX()] = b.getChar();
    }
};

int main() {
    bool exit = false;

    int g_x = 33;

    CONSOLE_SCREEN_BUFFER_INFO csbi;
    int columns, rows;

    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
    rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
    const int WIDTH = columns;//info->dwSize.X;
    BulletList bl(columns);

    do {
        //Render
        std::string graph(columns, '-');  // create a line of '-'
        bl.addBulletsToGraph(graph);      // paint the bullets
        graph[g_x] = 'x';                 // paint the player
        std::cout << graph << std::flush; // print the whole graph at once

        //Process input
        if (_kbhit()) {
            char ch = _getch();
            switch (ch) {
            case 'h': if (g_x > 0) g_x--; break;
            case 'l': if (g_x < WIDTH - 1) g_x++; break;
            case 'j': bl.AddBullet(g_x, 1, '>'); break;
            case 'k': bl.AddBullet(g_x, -1, '<'); break;
            case 27: exit = true; break;
            }
        }

        //Move bullets
        bl.MoveBullets();

        Sleep(50);
    } while (!exit);
}
0 голосов
/ 11 января 2019

Первая ошибка, которую вы совершаете здесь, это попытка разделить пули влево и пули вправо. Должен быть только один массив маркеров, где записи - это позиция маркера, а затем вы используете их положение, чтобы определить, идут ли они вправо или влево. Это легко, так как вы уже определили две клавиши, одну для стрельбы влево и одну для стрельбы вправо. «Хитрая» часть обрабатывает то, что происходит, когда пуля покидает мир: я принял решение сделать так, чтобы они полностью исчезли, а это означает, что каждый раз, когда кто-то покидает экран, пули становится на одну единицу меньше. Я реализовал это, перебирая каждую пулю и «вытягивая их назад», то есть следующая перезаписывает текущую.

Вторая ошибка - основа рендеринга, которую вы используете. Итерации по циклу for, пока вы не наткнетесь на то, что хотите нарисовать, не очень устойчивы. Чтобы исправить это, я ввел массив символов, в котором мы храним все, что хотим нарисовать (игрок, маркеры и '-'), а затем рендеринг - это всего лишь один printf.

Я также взял на себя смелость заставить игру работать только при вводе, так как это меня не смущает. Также изменил ключи на asdf, так как это более эргономично для меня.

#include <stdio.h>
#include <string.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <conio.h>
int main() {

    bool exit = false;

    int PlayerPosition   = 33;
    const int MaxBullets = 50;
    int Bullets[MaxBullets] = {};
    int CurrentBullets = 0;
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    int columns, rows;

    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
    columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
    rows    = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
    const int WIDTH = columns;//info->dwSize.X;

    char* RenderLine = (char*) HeapAlloc(
        GetProcessHeap(), HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, columns + 1
    );
    // Initial render
    for (int i = 0; i < WIDTH; i++) {
        RenderLine[i] = '-';
    }
    RenderLine[PlayerPosition] = 'x';
    printf(RenderLine);
    do {
        //Process input
        char ch = getch();
        if (ch) {
            switch (ch) {
                case 'a': {
                    if (PlayerPosition > 0) {
                        RenderLine[PlayerPosition]   = '-';
                        RenderLine[--PlayerPosition] = 'x';
                    }
                    break;
                }
                case 'f': {
                    if (PlayerPosition < WIDTH - 1) {
                         RenderLine[PlayerPosition]   = '-';
                         RenderLine[++PlayerPosition] = 'x';
                    }
                    break;
                }
                case 'd': {
                    if (CurrentBullets < MaxBullets) {
                        RenderLine[PlayerPosition + 1] = '>';
                        Bullets[CurrentBullets++] = PlayerPosition + 1;
                    }
                    break;
                }
                case 's': {
                    if (CurrentBullets < MaxBullets) {
                        RenderLine[PlayerPosition - 1] = '<';
                        Bullets[CurrentBullets++] = PlayerPosition - 1;
                    }
                    break;
                }
                case 27: exit = true; break; // press escape
            }

            //Render
            printf(RenderLine);
            //Move bullets
            for (int i = 0; i < CurrentBullets; i++) {
                if (Bullets[i] > PlayerPosition) { // move right
                    RenderLine[Bullets[i]]   = '-';
                    if (Bullets[i] == (WIDTH - 1)) { // a bullet has left the screen on the right
                        Bullets[i] = Bullets[--CurrentBullets];
                    } else {
                        RenderLine[++Bullets[i]] = '>';
                    }
                } else if (Bullets[i] < PlayerPosition) { // move right
                    RenderLine[Bullets[i]]   = '-';
                    if (Bullets[i] == 0) { // a bullet has left the screen on the left
                        Bullets[i] = Bullets[--CurrentBullets];
                    } else {
                        RenderLine[--Bullets[i]] = '<';
                    }
                }
            }
        }
    } while (!exit);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...