2017-06-18 41 views
2

我發現這個SFML tutorial寫早在2009年,我試圖將其轉換爲2.4。動態照明計劃到2.x轉換

我一直沒能到這兩條線轉換:

win.draw(sf::Shape::Rectangle(le.Blocks[0].fRect, sf::Color(255, 0, 0))); 

rt.draw(sf::Shape(sf::Shape::Line(l.position, end, 1, l.color))); 

我一直在嘗試使用SF :: RectangleShape轉換的建議過在SFML論壇,但我只是無法找到正確的論點來適應。這是完整的代碼轉換爲2.x,除了這兩行。

如果有人會好心地「完成」轉換我將非常感激,我敢肯定,這將教程是幫助他人。

MAIN:

#include <SFML/Graphics.hpp> 
#include <iostream> 
#include "LightEngine.h" 

int main() 
{ 
    sf::RenderWindow win(sf::VideoMode(800, 600), "Light Tutorial"); 
    sf::Event event; 

    LightEngine le; 

    Light light; 
    light.radius = 600; 
    light.angleSpread = 100; 
    light.position = sf::Vector2f(100, 150); 
    le.Lights.push_back(light); 

    Block block; 
    block.fRect = sf::FloatRect(0, 0, 50, 50); 
    le.Blocks.push_back(block); 


    while (win.isOpen()) 
    { 
     while (win.pollEvent(event)) 
     { 
      if (event.type == sf::Event::Closed) win.close(); 
     } 

     win.clear(); 

     le.Blocks[0].fRect.left = sf::Mouse::getPosition(win).x; 
     le.Blocks[0].fRect.top = sf::Mouse::getPosition(win).y; 
     /*HERE*/ win.draw(sf::Shape::Rectangle(le.Blocks[0].fRect, sf::Color(255, 0, 0))); 
     le.Step(win); 

     win.display(); 
    } 
} 

LightEngine.h

#pragma once//don't allow this header to be included more than once 
#include "Light.hpp" 
#include "Block.hpp" 
#include <vector> 
#include <SFML/Graphics/RenderTarget.hpp> //Place to draw on 
#include <SFML/Graphics/Shape.hpp> //SFML programmable Shapes 

class LightEngine 
{ 
public: 
    void Step(sf::RenderTarget &rt); 

    std::vector <Light> Lights; //Container for Lights 

    std::vector <Block> Blocks; //Container for Blocks 
private: 

    void ShineLight(Light &lig, sf::RenderTarget &rt); 

    static const float Distance(const sf::Vector2f &p1, const sf::Vector2f &p2); 
    static const sf::Vector2f GetCenter(const sf::FloatRect &fr); //Get the center of a rectangle 


    struct FindDistance //if a light's radius manages to intersect multiple blocks, we need to find the sortest distance to shorten the light 
    { 
     FindDistance(); 
     float shortest; 
     bool LightHitsBlock(Light &l, Block &b, const float cur_ang, float &reflength); 
     bool start; //to get the first distance to refer off of 
    }; 

    FindDistance findDis; 
}; 

LightEngine.cpp

#include "LightEngine.h" 


LightEngine::FindDistance::FindDistance() 
{ 
    start = false; 
    shortest = 0; 
} 

const sf::Vector2f LightEngine::GetCenter(const sf::FloatRect &fr) 
{ 
    return sf::Vector2f(fr.left + (fr.width/2), fr.top + (fr.height/2)); 
} 

const float LightEngine::Distance(const sf::Vector2f &p1, const sf::Vector2f &p2) 
{ 
    //We need to look at this as a triangle 

    /* 
    /|p1.y 
    /| 
    /| 
    / | 
    / | 
    / |b 
    / | 
    /  | 
    /  | 
    /  | 
    ----------- 
    a  p2.y 
    p1.x   p2.x 

    */ 

    float a = p2.x - p1.x; //width length 
    float b = p2.y - p1.y; //height length 
    float c = sqrt((a * a) + (b * b)); //Pythagorean Theorem. (c² = a² + b²). c = squareroot(a² + b²) 

    return c; 
} 

void LightEngine::Step(sf::RenderTarget &rt) 
{ 
    for (unsigned i = 0; i < Lights.size(); i++) 
    { 
     ShineLight(Lights[i], rt); //Shine all lights 
    } 
} 

void LightEngine::ShineLight(Light &l, sf::RenderTarget &rt) 
{ 
    /* 
    remember back in the Light class, we had something called 'angleSpread' ? 
    that's to create a tunnel, or arc shaped light. Like this: 
    /) 
    /) 
    / ) 
    / ) 
    <  ) 
    \  ) 
    \ ) 
    \ ) 
    \) 

    Obviously it'll look better than an ascii drawing 
    */ 

    float current_angle = l.angle - (l.angleSpread/2); //This will rotate the angle back far enough to get a desired arc 

                 /* 
                 Lights Angle (if it was at 0): 

                 ------------- 

                 Current_Angle: 
                 /
                 /
                 /
                 (slanted) 

                 */ 

    float dyn_len = l.radius; //dynamic length of the light. This will be changed in the function LightHitsBlock() 

    float addto = 1.f/l.radius; 
    for (current_angle; current_angle < l.angle + (l.angleSpread/2); current_angle += addto * (180.f/3.14f)) //we need to add to the current angle, until it reaches the end of the arc. we divide 1.f by radius for a more solid shape. Otherwize you could see lines seperating 
    { 
     dyn_len = l.radius; //Reset the length 
     findDis.start = true; //Start of finding a light, we need to reset 
     findDis.shortest = 0; //Reset the shortest. 



     if (l.dynamic) //can this change? 
     { 
      for (unsigned i = 0; i < Blocks.size(); i++) 
      { 
       findDis.LightHitsBlock(l, Blocks[i], current_angle, dyn_len); 
      } 
     } 


     float radians = current_angle * (3.14f/180); //Convert to radians for trig functions 

     sf::Vector2f end = l.position; 
     end.x += cos(radians) * dyn_len; 
     end.y += sin(radians) * dyn_len; 
     /*HERE*/rt.draw(sf::Shape(sf::Shape::Line(l.position, end, 1, l.color))); 
    } 
} 

bool LightEngine::FindDistance::LightHitsBlock(Light &l, Block &b, float cur_ang, float &refleng) 
{ 
    if (b.allowBlock) //can this even block? 
    { 
     float distance = Distance(l.position, GetCenter(b.fRect)); 

     if (l.radius >= distance) //check if it's radius is even long enough to hit a block 
     { 
      float radians = cur_ang * (3.14f/180); //convert cur_ang to radians for trig functions 
      sf::Vector2f pointpos = l.position; 

      pointpos.x += cos(radians) * distance; 
      pointpos.y += sin(radians) * distance; 
      //By doing this, we check if the angle is in the direciton of the block. 

      if (b.fRect.contains(pointpos)) //If it was, than the point would be intersecting the rectangle of the block 
      { 
       if (start || distance < shortest) //If this is the first block, or it has a shorter distance 
       { 
        start = false; //definately not the start so other blocks can't automatically set the distance 
        shortest = distance; //shortest is set to this 
        refleng = distance; //This is where the dynamic comes in, it changes the length of the reference towhere it's going to stop after it hits the distance from the point to the block 
       } 
       return true; 
      } 
     } 
    } 
    return false; 
} 

Block.hpp

#pragma once//don't allow this header to be included more than once 
#include <SFML/Graphics/Rect.hpp> 

class Block 
{ 
public: 
    Block() 
    { 
     allowBlock = true; 
     fRect = sf::FloatRect(0, 0, 0, 0); 
    } 
    /* Like the light class, you can do this in an initializer list, whatever works for you 

    Block() 
    : fRect(0,0,0,0), allowBlock(false) 
    { 
    } 
    */ 

    sf::FloatRect fRect; //Area that will be blocking light 
    bool allowBlock; //Sometimes we want to keep a block, but don't want it to actually block until a certain point 
}; 

回答

2

win.draw(SF ::形狀::矩形(le.Blocks [0] .fRect,SF ::顏色(255,0,0)));

將是:

sf::RectangleShape rshape; 

rshape.setSize(sf::Vector2f(le.Blocks[0].fRect.width, le.Blocks[0].fRect.height)); 
rshape.setPosition(le.Blocks[0].fRect.left, le.Blocks[0].fRect.top); 
rshape.setFillColor(sf::Color(255, 0, 0)); 

win.draw(rshape); 

因此:

rt.draw(SF ::形狀::線(l.position,結束,1,l.color));

由於沒有線的形狀了:

sf::Vertex line[] = 
{ 
    sf::Vertex(l.position, l.color), 
    sf::Vertex(end, l.color) 
}; 

rt.draw(line, 2, sf::Lines); 
+0

幹得好,謝謝你。對於想要使用代碼的人來說,只需添加一件事:rshape.setSize參數應該位於sf :: Vector2f –

+0

@ NathanielG.M中。你是對的,謝謝,我糾正了它。 – nvoigt