【问题标题】:C++ SFML Collison DetectionC++ SFML 碰撞检测
【发布时间】:2017-07-25 07:57:57
【问题描述】:

我正在尝试制作一个游戏,您可以在其中躲避传入的盒子(东西)。我不知道如何使用 if 语句编写快速简单的碰撞检测。 我试图在“//碰撞检测”中对此进行编码。我想要这样,如果箭头(玩家)碰到盒子,游戏就会关闭。

主菜单.h

 #include <SFML/Graphics.hpp>
 #include <iostream>
 using namespace sf;
 using namespace std;
 #pragma once

 class main_menu
 {
 public:
    void startmenu(RenderWindow &gameDisplay, Font &font1, bool &MainMenu, RectangleShape &start, Event &evnt)
    {
    gameDisplay.setMouseCursorVisible(true);


    Text starttext;
    starttext.setCharacterSize(100);
    starttext.setFont(font1);
    starttext.setString("DODGE");
    starttext.setFillColor(Color(255, 255, 255));
    starttext.setStyle(Text::Bold);

    FloatRect starttextRect = starttext.getLocalBounds();
    starttext.setOrigin(starttextRect.width / 2, starttextRect.height / 2);
    starttext.setPosition(Vector2f(1366 / 2.0f - 30, 768 - 700.0f));




    RectangleShape outlinetop(Vector2f(1366, 50));
    outlinetop.setFillColor(Color(255, 255, 255));
    outlinetop.setPosition(0, 0);

    RectangleShape outlinebottom(Vector2f(1366, 50));
    outlinebottom.setFillColor(Color(255, 255, 255));
    outlinebottom.setPosition(0, 718);

    RectangleShape outlineright(Vector2f(50, 768));
    outlineright.setFillColor(Color(255, 255, 255));
    outlineright.setPosition(1316, 0);

    RectangleShape outlineleft(Vector2f(50, 768));
    outlineleft.setFillColor(Color(255, 255, 255));
    outlineleft.setPosition(0, 0);


    Text startbuttontext;
    startbuttontext.setFont(font1);
    startbuttontext.setCharacterSize(70);
    startbuttontext.setString("PLAY");
    startbuttontext.setFillColor(Color(255, 255, 255));

    FloatRect startbuttontextRect = starttext.getLocalBounds();
    startbuttontext.setOrigin(starttextRect.width / 2, startbuttontextRect.height / 2);
    startbuttontext.setPosition(Vector2f(1366 / 2.0f + 60 - 30, 768 - 480.0f)); 














    if (MainMenu == true)
    {
        Vector2f tempMouse(Mouse::getPosition(gameDisplay));
        if (start.getGlobalBounds().contains(tempMouse) &&
            evnt.type == Event::MouseButtonPressed &&
            evnt.key.code == Mouse::Left)
        {
            MainMenu = false;

        }







        //mouseposx = (Mouse::getPosition(gameDisplay).x);
        //mouseposy = (Mouse::getPosition(gameDisplay).y);


        /*
            while (Mouse::getPosition(gameDisplay).x > 1366 / 2.0 && Mouse::getPosition(gameDisplay).x < 1083)
                while (Mouse::getPosition(gameDisplay).y > 768 - 450 && Mouse::getPosition(gameDisplay).y < 868)
                    if (Mouse::isButtonPressed(Mouse::Left))
                        MainMenu = false;
                        */



        if (Keyboard::isKeyPressed(Keyboard::Q))
        {
            MainMenu = false;
            gameDisplay.close();

        }


        gameDisplay.draw(outlinebottom);
        gameDisplay.draw(outlineleft);
        gameDisplay.draw(outlineright);
        gameDisplay.draw(outlinetop);
        gameDisplay.draw(start);
        gameDisplay.draw(starttext);
        gameDisplay.draw(startbuttontext);
        gameDisplay.display();

    }



}

     };

东西.h

#include <SFML/Graphics.hpp>
#include <iostream>
#include <cstdlib>
using namespace sf;
using namespace std;
#pragma once
int RandomXpos = 0;

class Thing
{
public:
void thingspawn(RenderWindow &gameDisplay, int &enemystartx, int &enemystarty, int &enemywidth, int &enemyheight, RectangleShape &thing, int enemyspeed)
{
    thing.setFillColor(Color(255,255,255));
    if (thing.getPosition().y < 800)
        thing.move(0.0f, 0.4f);
    if (thing.getPosition().y >= 800)
    {
        RandomXpos = rand() % 1000;
        thing.setPosition(RandomXpos, -200);
    }

    }
   };

main.cpp

#include <iostream>
#include <SFML/Graphics.hpp>
#include "things.h"
#include "Main Menu.h"
#include <cstdlib>
#include <Windows.h>
using namespace std;
using namespace sf;




int main()
{
//FreeConsole();
RenderWindow gameDisplay(VideoMode(1366, 768), "Game", Style::Fullscreen);
gameDisplay.clear();
int enemystarty = -200;
int enemystartx = 300;
int enemyheight = 30;
int enemywidth = 300;
int enemyspeed = 0.3;
int enemycount = 1;
int dodged = 0;
int blockcolor = 0;
bool MainMenu = true;


Font font1;
if (!font1.loadFromFile("OCRAEXT.ttf"))
{
    //error...
}

RectangleShape start(Vector2f(400, 100));
start.setFillColor(Color(0, 0, 0));
start.setOutlineThickness(20);
start.setOutlineColor(Color(255, 255, 255));

FloatRect startRect = start.getLocalBounds();
start.setOrigin(startRect.width / 2, startRect.height / 2);
start.setPosition(Vector2f(1366 / 2.0f, 768 - 450.0f));

/*
RectangleShape player(Vector2f(200, 50));
player.setFillColor(Color(0, 0, 255));
player.setPosition(400, 700);
*/

Texture playertexture;
if (!playertexture.loadFromFile("whiter_arrow.jpg"))
{
    //error...
}

Sprite player;
player.setTexture(playertexture);
player.setPosition(300, 600);

RectangleShape thing(Vector2f(enemywidth, enemyheight));
thing.setPosition(300, -200);


Event evnt;







while (gameDisplay.isOpen())
{

    while (gameDisplay.pollEvent(evnt))
    {
        switch (evnt.type)
        {
        case Event::Closed:
            gameDisplay.close();
        case Event::KeyPressed:
            if (Keyboard::isKeyPressed(Keyboard::Q))
                gameDisplay.close();

        }

    }



    main_menu object;
    object.startmenu(gameDisplay, font1, MainMenu, start, evnt);


    while (MainMenu == false)
    {
        gameDisplay.setMouseCursorVisible(false);

        if (Keyboard::isKeyPressed(Keyboard::D))
            if (player.getPosition().x < 1200)
            {
                player.move(0.3f, 0.0f);
            }

        if (Keyboard::isKeyPressed(Keyboard::A))
            if (player.getPosition().x > 50)
            {
                player.move(-0.3f, 0.0f);
            }
        if (Keyboard::isKeyPressed(Keyboard::Q))
            gameDisplay.close();


        Thing thingobject;
        thingobject.thingspawn(gameDisplay, enemystartx, enemystarty, enemywidth, enemyheight, thing, enemyspeed);

        //collision detection
        if (player.getPosition().y <= thing.getPosition().y)
            if (player.getPosition().x == thing.getPosition().x)
                gameDisplay.close();


        gameDisplay.clear();
        gameDisplay.draw(player);
        gameDisplay.draw(thing);
        gameDisplay.display();

    }



    }
  }

【问题讨论】:

    标签: c++ collision-detection sfml 2d-games


    【解决方案1】:

    有很多方法可以在对象集之间进行 2D 碰撞检测(“这些对象中的任何一个是否相互接触”),这超出了本问题的范围。您似乎要问的要简单得多:“两个二维矩形是​​否接触?”。假设您有矩形 r1 和 r2,那么您可以使用:

    collision = r1.x <= r2.x + r2.width && 
       r2.x <= r1.x + r1.width &&
       r1.y <= r2.y + r2.height && 
       r2.y <= r1.y + r1.height;
    

    另外值得注意的是,在游戏中,由于对象速度与帧速率的关系,您必须考虑到移动增量过大的可能性,从而允许对象看起来相互穿过。您可以通过构建包含两个对象之前/之后位置的边界矩形来进行补偿,并首先对其进行测试,然后再深入进行涉及扫描时间体积交集的更复杂的计算。

    【讨论】:

    • 谢谢,我已经设法在不使用边界框的情况下创建碰撞检测,但谢谢:3
    【解决方案2】:

    有 SFML 方法来进行碰撞,它适用于您的情况。

    你可以这样做:

    if ( player.getGlobalBounds().intersects(thing.getGlobalBounds()) )
    {
          // player and thing is collided! do something
    }
    

    @Wheezil 的答案是标准的方法,对于像您的情况这样的轴对齐对象。最好自己实现它,这样你就知道它是如何发生的:)

    【讨论】:

      猜你喜欢
      • 2015-02-01
      • 2014-03-17
      • 2018-09-11
      • 2014-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-06
      • 1970-01-01
      相关资源
      最近更新 更多