如何使用 SFML 在贪吃蛇游戏中定义游戏结束?

How can I define a game over in snake game using SFML?

所以最近我一直想在 Microsoft Visual studio 2015 中使用 SFML 用 C++ 制作一个贪吃蛇游戏,我做了一个,实际上我对自己的工作非常满意,但有一个问题,我忘了为它制作一款游戏,但似乎我无法让它发挥作用,这真的让我感到紧张。所以我想我可以使用堆栈溢出的帮助。如果你们能让我知道如何让它工作,我将非常感激,请保持简单明了。 这是我的代码:

// 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;
}

在您的 Tick() 函数中,您可以检查在所有物体都朝给定方向移动后头部是否撞到任何东西。如果是,让 main() 以某种方式知道:例如,return a bool 表示游戏是否结束。假设这个 bool 被称为 over.

因此,在 while (window.isOpen()) 循环中添加 if (over) { window.close(); }(在调用 Tick() 之后)让 main() 到达 return 0; 并完成程序。

编辑:考虑使用 std::deque 使用更少的代码和时间来移动你的蛇:你可以只 pop_back() 离头部最远的蛇瓷砖 push_front()头部当前所在的新图块(打勾后),模拟向前爬行一步。

无论如何,在移动你的蛇之后,你可以检查它的每个 body 方块是否与它的头具有相同的坐标。如果是,则表示您的蛇撞到了它的尾巴,所以游戏结束了。

// 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