关于C#:在SFML中未使用sprite显示的图像

Images not displayed using sprites in SFML

我已经使用C 17在Linux Mint 18.1上学习了SFML 2.3.2,以学习如何使用GUI。作为Hello World之后的第二个项目,我试图重现Snake,即旧手机已预装的游戏。到目前为止,大多数内容都可以使用,除了一些较小的例外,我稍后必须处理,其中一些是由于游戏尚未完全完成引起的。

请确保我理解正确,因为我以前从未使用过低级语言来处理GUI和图像。首先,将图像加载到纹理中,然后将纹理添加到sprite中,然后将该sprite绘制到窗口上?

该程序可以完美编译,正确初始化所有内容,并且运行时没有重大无法解释的问题。除非图像不显示。sprite在那里并以其默认的单色背景色显示,但不显示任何图像。

我该怎么做,以及如何解决?谢谢!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
// HEADERS
#include <iostream>
#include <SFML/Graphics.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/Sprite.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/System/String.hpp>
#include <SFML/Window/Keyboard.hpp>

// CREATE NEW FONT
sf::Font create_font()
{
    sf::Font f;
    bool id = f.loadFromFile("/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-B.ttf");

    if (id == false)
    {
        std::cerr <<"Font:\\tCould not be loaded." << std::endl;
    }
    else
    {
        std::cerr <<"Font:\\tLoaded successfully." << std::endl;
    }

    return f;

}

// CREATE NEW SPRITE USING TEXTURE, GIVEN ARE PATH WITH COORDINATES AND DIMENSIONS
sf::Sprite load_img(std::string path, long x, long y, long w, long h)
{
    sf::Texture t;
    bool id = t.loadFromFile(path);

    if (id == false)
    {
        std::cerr <<"Texture:\\t" << path <<"\\tFailed to load." << std::endl;
    }
    else
    {
        std::cerr <<"Texture:\\t" << path <<"\\tLoaded successfully." << std::endl;
    }

    sf::Sprite s(t);
    s.setTextureRect(sf::IntRect((int)x, (int)y, (int)w, (int)h));
    s.setPosition(x, y);
    return s;
}


// MAIN FUNCTION
int main()
{
    // DECLARING/DEFINING VARIABLES
    unsigned long window_width = 512;
    unsigned long window_height = 512;
    unsigned long score = 0;
    unsigned long head_old_position_x, head_old_position_y;
    std::string title ="Snek";
    std::string wdir ="/home/kate/Documents/coding/snek/";

    // WINDOW
    sf::RenderWindow window(sf::VideoMode(window_width, window_height), title);
    window.setFramerateLimit(60);

    // SPRITES
    sf::Sprite background = load_img(wdir +"img/background.png", 0, 0, 512, 512);
    sf::Sprite head = load_img(wdir +"img/head.png", 47, 39, 8, 8);
    sf::Sprite body = load_img(wdir +"img/body.png", 39, 39, 8, 8);
    sf::Sprite poison = load_img(wdir +"img/poison.png", 119, 119, 8, 8);
    sf::Sprite trap = load_img(wdir +"img/trap.png", 159, 159, 8, 8);
    sf::Sprite candy = load_img(wdir +"img/candy.png", 199, 199, 8, 8);

    // FONT
    sf::Font font = create_font();

    // TEXT
    sf::Text score_display(title, font, 20);
    sc// HEADERS
#include <iostream>
#include <SFML/Graphics.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/Sprite.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/System/String.hpp>
#include <SFML/Window/Keyboard.hpp>

// CREATE NEW FONT
sf::Font create_font()
{
    sf::Font f;
    bool id = f.loadFromFile("/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-B.ttf");

    if (id == false)
    {
        std::cerr <<"Font:\\tCould not be loaded." << std::endl;
    }
    else
    {
        std::cerr <<"Font:\\tLoaded successfully." << std::endl;
    }

    return f;

}

// CREATE NEW SPRITE USING TEXTURE, GIVEN ARE PATH WITH COORDINATES AND DIMENSIONS
sf::Sprite load_img(std::string path, long x, long y, long w, long h)
{
    sf::Texture t;
    bool id = t.loadFromFile(path);

    if (id == false)
    {
        std::cerr <<"Texture:\\t" << path <<"\\tFailed to load." << std::endl;
    }
    else
    {
        std::cerr <<"Texture:\\t" << path <<"\\tLoaded successfully." << std::endl;
    }

    sf::Sprite s(t);
    s.setTextureRect(sf::IntRect((int)x, (int)y, (int)w, (int)h));
    s.setPosition(x, y);
    return s;
}


// MAIN FUNCTION
int main()
{
    // DECLARING/DEFINING VARIABLES
    unsigned long window_width = 512;
    unsigned long window_height = 512;
    unsigned long score = 0;
    unsigned long head_old_position_x, head_old_position_y;
    std::string title ="Snek";
    std::string wdir ="/home/kate/Documents/coding/snek/";

    // WINDOW
    sf::RenderWindow window(sf::VideoMode(window_width, window_height), title);
    window.setFramerateLimit(60);

    // SPRITES
    sf::Sprite background = load_img(wdir +"/img/background.png", 0, 0, 512, 512);
    sf::Sprite head = load_img(wdir +"/img/head.png", 47, 39, 8, 8);
    sf::Sprite body = load_img(wdir +"/img/body.png", 39, 39, 8, 8);
    sf::Sprite poison = load_img(wdir +"/img/poison.png", 119, 119, 8, 8);
    sf::Sprite trap = load_img(wdir +"/img/trap.png", 159, 159, 8, 8);
    sf::Sprite candy = load_img(wdir +"/img/candy.png", 199, 199, 8, 8);

    // FONT
    sf::Font font = create_font();

    // TEXT
    sf::Text score_display(title, font, 20);
    score_display.setString(std::to_string(score));
    score_display.setPosition(5, 5);

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

            head_old_position_x = head.getPosition().x;
            head_old_position_y = head.getPosition().y;

            // MOVEMENT BASED ON KEYBOARD INPUT
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
            {
                head.setPosition(head.getPosition().x - 8, head.getPosition().y);
                body.setPosition(head_old_position_x, head_old_position_y);
            }

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
            {
                head.setPosition(head.getPosition().x, head.getPosition().y - 8);
                body.setPosition(head_old_position_x, head_old_position_y);
            }

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
            {
                head.setPosition(head.getPosition().x + 8, head.getPosition().y);
                body.setPosition(head_old_position_x, head_old_position_y);
            }

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
            {
                head.setPosition(head.getPosition().x, head.getPosition().y + 8);
                body.setPosition(head_old_position_x, head_old_position_y);
            }


            if (body.getPosition().x == candy.getPosition().x && body.getPosition().y == candy.getPosition().y)
            {
                score ++;
                score_display.setString(std::to_string(score));
            }


            // REFRESH WINDOW
            window.clear();
            window.draw(background);
            window.draw(head);
            window.draw(body);
            window.draw(poison);
            window.draw(trap);
            window.draw(candy);
            window.draw(score_display);
            window.display();
        }
    }

    return 0;
}
ore_display.setString(std::to_string(score));
    score_display.setPosition(5, 5);

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

            head_old_position_x = head.getPosition().x;
            head_old_position_y = head.getPosition().y;

            // MOVEMENT BASED ON KEYBOARD INPUT
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
            {
                head.setPosition(head.getPosition().x - 8, head.getPosition().y);
                body.setPosition(head_old_position_x, head_old_position_y);
            }

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
            {
                head.setPosition(head.getPosition().x, head.getPosition().y - 8);
                body.setPosition(head_old_position_x, head_old_position_y);
            }

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
            {
                head.setPosition(head.getPosition().x + 8, head.getPosition().y);
                body.setPosition(head_old_position_x, head_old_position_y);
            }

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
            {
                head.setPosition(head.getPosition().x, head.getPosition().y + 8);
                body.setPosition(head_old_position_x, head_old_position_y);
            }


            if (body.getPosition().x == candy.getPosition().x && body.getPosition().y == candy.getPosition().y)
            {
                score ++;
                score_display.setString(std::to_string(score));
            }


            // REFRESH WINDOW
            window.clear();
            window.draw(background);
            window.draw(head);
            window.draw(body);
            window.draw(poison);
            window.draw(trap);
            window.draw(candy);
            window.draw(score_display);
            window.display();
        }
    }

    return 0;
}


好吧,我想我已经知道了。

可能未显示任何内容,因为事件循环中包含所有绘图内容

尝试将这些内容放入while(window.isOpen())循环范围。


您已经丢失了对纹理的引用。在您的情况下,纹理是load_img()函数中的局部变量。

在任何sprite使用它时,应保持纹理加载并可用。

我建议您阅读SFML教程的这一部分,其中解释了此问题。


您的纹理超出范围,请参阅对象何时"超出范围"?更多细节。您可以在load_img函数中声明纹理,但是在退出load_img并返回sprite之后,将删除sf::Texture t;

因此这是一个更新的函数,您可以在其中将纹理存储在load_img函数之外,并通过引用将其传递。仅显示相关部分。首先,将纹理传递给load_img函数。删除sf::Texture t;

1
2
3
4
5
sf::Sprite load_img(std::string path, long x, long y, long w, long h, sf::Texture& t)
{
    bool id = t.loadFromFile(path);
    [...]
}

声明纹理并将其传递给load_img函数。

1
2
sf::Texture headtexture;
sf::Sprite head = load_img(wdir +"img/head.png", 47, 39, 8, 8, headtexture);

如果对所有sprite进行此操作,它将起作用并正确显示图像/sprite。

编辑2017年9月25日

根据评论,这是一个不带功能的最小工作示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// HEADERS
#include <iostream>
#include <SFML/Graphics.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/Font.hpp>
#include <SFML/Graphics/Image.hpp>
#include <SFML/Graphics/Rect.hpp>
#include <SFML/Graphics/Sprite.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/System/String.hpp>
#include <SFML/Window/Keyboard.hpp>

// MAIN FUNCTION
int main()
{
    // DECLARING/DEFINING VARIABLES
    unsigned long window_width = 512;
    unsigned long window_height = 512;
    std::string title ="Snek";
    std::string wdir ="/home/kate/Documents/coding/snek/";

    // WINDOW
    sf::RenderWindow window(sf::VideoMode(window_width, window_height), title);
    window.setFramerateLimit(60);

    // SPRITES
    sf::Texture headtexture;
    sf::Sprite head;

    headtexture.loadFromFile(wdir +"img/head.png");
    head.setTexture(headtexture);
    head.setTextureRect(sf::IntRect(47, 39, 8, 8));
    head.setPosition(30, 30);

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

            // REFRESH WINDOW
            window.clear();
            window.draw(head);
            window.display();
        }
    }

    return 0;
}