Как я могу определить игру в игре со змеями, используя SFML? - PullRequest
0 голосов
/ 06 февраля 2020

так недавно я хотел сделать игру-змею на C ++ с использованием SFML в Microsoft Visual Studio 2015, и я сделал ее, и я на самом деле очень доволен своей работой, но есть проблема, что я забыл закончить игру для этого и кажется, что я не мог заставить это работать, и это действительно имело меня на краю. Поэтому я подумал, что смогу воспользоваться помощью переполнения стека. Я был бы очень признателен, если бы вы, ребята, сообщили мне, как заставить это работать, и, пожалуйста, сделайте это простым и понятным. Вот мой код:

// GraphicalLoopSnakeGame.cpp : Defines the entry point for the console application.

#include "stdafx.h"
#include <ctime>
#include <SFML/Graphics.hpp>

using namespace sf;

int N = 30, M = 20;
int size = 16;
int w = size * N;
int h = size * M;

int dir, num = 4;

struct Snake {
    int x, y;
} s[100];

struct Fruit {
    int x, y;
} f;

void Tick() {
    for(int i = num; i > 0; --i) {
        s[i].x = s[i - 1].x;
        s[i].y = s[i - 1].y;
    }

    if(dir == 0) s[0].y += 1;
    if(dir == 1) s[0].x -= 1;
    if(dir == 2) s[0].x += 1;
    if(dir == 3) s[0].y -= 1;

    if((s[0].x == f.x) && (s[0].y == f.y)) {
        num++;
        f.x = rand() % N;
        f.y = rand() % M;
    }

    if(s[0].x > N) s[0].x = 0;
    if(s[0].x < 0) s[0].x = N;
    if(s[0].y > M) s[0].y = 0;
    if(s[0].y < 0) s[0].y = M;

    for(int i = 1; i < num; i++)
        if(s[0].x == s[i].x && s[0].y == s[i].y) num = i;
}

int main() {
    srand(time(0));
    RenderWindow window(VideoMode(w, h), "Snake Game!");

    Texture t1, t2, t3;

    t1.loadFromFile("images/white.png");
    t2.loadFromFile("images/red.png");
    t3.loadFromFile("images/green.png");

    Sprite sprite1(t1);
    Sprite sprite2(t2);
    Sprite sprite3(t3);

    Clock clock;
    float timer = 0, delay = 0.13;

    f.x = 10;
    f.y = 10;

    while(window.isOpen()) {
        float time = clock.getElapsedTime().asSeconds();
        clock.restart();
        timer += time;

        Event e;
        while(window.pollEvent(e)) {
            if(e.type == Event::Closed) window.close();
        }

        if(Keyboard::isKeyPressed(Keyboard::Left)) dir = 1;
        if(Keyboard::isKeyPressed(Keyboard::Right)) dir = 2;
        if(Keyboard::isKeyPressed(Keyboard::Up)) dir = 3;
        if(Keyboard::isKeyPressed(Keyboard::Down)) dir = 0;
        if(Keyboard::isKeyPressed(Keyboard::W)) dir = 3;
        if(Keyboard::isKeyPressed(Keyboard::D)) dir = 2;
        if(Keyboard::isKeyPressed(Keyboard::A)) dir = 1;
        if(Keyboard::isKeyPressed(Keyboard::S)) dir = 0;

        if(timer > delay) {
            timer = 0;
            Tick();
        }

        ////// draw  ///////
        window.clear();

        for(int i = 0; i < N; i++)
            for(int j = 0; j < M; j++) {
                sprite1.setPosition(i * size, j * size);
                window.draw(sprite1);
            }

        for(int i = 0; i < num; i++) {
            sprite2.setPosition(s[i].x * size, s[i].y * size);
            window.draw(sprite2);
        }

        sprite3.setPosition(f.x * size, f.y * size);
        window.draw(sprite3);

        window.display();
    }

    return 0;
}

1 Ответ

1 голос
/ 06 февраля 2020

В вашей функции Tick() вы можете проверить, сталкивается ли голова с чем-либо после того, как все движется в заданном направлении. Если это так, дайте main() знать об этом как-нибудь: например, вернуть bool, который выражает, если игра окончена. Допустим, это bool называется over.

Итак, добавьте if (over) { window.close(); } внутри вашего while (window.isOpen()) l oop (сразу после вызова Tick()), чтобы main() достиг return 0; и фини sh программа.

РЕДАКТИРОВАТЬ: Подумайте об использовании std::deque для перемещения вашей змеи с использованием меньшего количества кода и времени: вы сможете просто pop_back() плитку змеи, расположенную дальше всего от головы, и push_front() новой плитке, где голова в данный момент (после тика), имитирует ползание на один шаг вперед.

В любом случае, после перемещения вашей змеи вы можете проверить каждую из его плиток тела, имеет ли она те же координаты, что и ее голова. Если это так, значит ваша змея врезалась в хвост, и игра окончена.

// in Tick():
// ...other logic...
tiles.pop_back();
tiles.push_front(new_head_position);
for (/* each tile of your snake except its head */) {
  if (tile.x == head.x && tile.y == head.y) {
    return false; // game over
  }
}
return true; // everything is fine
...