我刚开始使用c ++和VS 2013社区中的SDL。 我想绘制一个圆圈,所以我在Google上搜索了http://content.gpwiki.org/index.php/SDL:Tutorials:Drawing_and_Filling_Circles。但是当我试图在一个单独的fill_circle.cpp文件中实现它时,将它包含在我的main.cpp中并调用该函数,我得到错误,表示函数fill_circle()已在fill_circle.obj中定义并且存在冲突其他的库。 所以我试着将drawning函数直接实现到我的main.cpp中,但是我得到了一个类似的错误,说在fill_circle.obj中已经定义了void __cdecl fill_circle(struct SDL_Surface *,int,int,int,unsigned int)。
我不知道如何处理这些错误,并希望有人能帮助我:)。
编辑:在完全删除fill_circle.cpp和debug文件夹并在main.cpp中实现Function之后,programm将编译但在运行时抛出错误。
我的main.cpp:
#include <SDL.h>
#include <iostream>
#include <cmath>
void fill_circle(SDL_Surface *surface, int cx, int cy, int radius, Uint32 pixel)
{
static const int BPP = 4;
double r = (double)radius;
for (double dy = 1; dy <= r; dy += 1.0)
{
// This loop is unrolled a bit, only iterating through half of the
// height of the circle. The result is used to draw a scan line and
// its mirror image below it.
// The following formula has been simplified from our original. We
// are using half of the width of the circle because we are provided
// with a center and we need left/right coordinates.
double dx = floor(sqrt((2.0 * r * dy) - (dy * dy)));
int x = cx - dx;
// Grab a pointer to the left-most pixel for each half of the circle
Uint8 *target_pixel_a = (Uint8 *)surface->pixels + ((int)(cy + r - dy)) * surface->pitch + x * BPP;
Uint8 *target_pixel_b = (Uint8 *)surface->pixels + ((int)(cy - r + dy)) * surface->pitch + x * BPP;
for (; x <= cx + dx; x++)
{
*(Uint32 *)target_pixel_a = pixel;
*(Uint32 *)target_pixel_b = pixel;
target_pixel_a += BPP;
target_pixel_b += BPP;
}
}
}
int main(int argc, char *argv[])
{
//Main loop flag
bool b_Quit = false;
//Event handler
SDL_Event ev;
//SDL window
SDL_Window *window = NULL;
SDL_Surface *windowSurface;
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
std::cout << "Video Initialisation Error: " << SDL_GetError() << std::endl;
}
else
{
window = SDL_CreateWindow("SDL_Project", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_SHOWN);
if (window == NULL)
{
std::cout << "Window Creation Error: " << SDL_GetError() << std::endl;
}
else
{
windowSurface = SDL_GetWindowSurface(window);
fill_circle(windowSurface, 10, 10, 20, 0xffffffff);
//Main loop
while (!b_Quit)
{
//Event Loop
while (SDL_PollEvent(&ev) != 0)
{
//Quit Event
if (ev.type == SDL_QUIT)
{
b_Quit = true;
}
}
SDL_UpdateWindowSurface(window);
}
}
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
答案 0 :(得分:1)
半径为20的圆圈,其半径为&#39;中心在(10,10),就像你有:
fill_circle(windowSurface, 10, 10, 20, 0xffffffff);
将使您处理分配曲面之外的像素
... = (Uint8 *)surface->pixels + ((int)(cy + r - dy)) * surface->pitch + x * BPP;
... = (Uint8 *)surface->pixels + ((int)(cy - r + dy)) * surface->pitch + x * BPP;
这会导致崩溃。
我在某些项目中使用了相同的算法,而在SDL 1.2中,它的编写方式并不是很安全。
答案 1 :(得分:1)
这可以帮到你:
void draw_circle(SDL_Point center, int radius, SDL_Color color)
{
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
for (int w = 0; w < radius * 2; w++)
{
for (int h = 0; h < radius * 2; h++)
{
int dx = radius - w; // horizontal offset
int dy = radius - h; // vertical offset
if ((dx*dx + dy*dy) <= (radius * radius))
{
SDL_RenderDrawPoint(renderer, center.x + dx, center.y + dy);
}
}
}
}
答案 2 :(得分:1)
我刚刚进入这里寻找一个绘制实心圆的想法,并尝试了Ryozuki解决方案,但是它的成本很高,所以我在这里提出一个替代方案。
"../assets/img1.jpg"
您当然需要创建一个void TextureManager::fillCircle(const fig::cSphere _dst){
SDL_SetRenderDrawColor(Game::renderer, 0x00, 0x00, 0xff, 0xff);
int p = std::sqrt(_dst.r * 2) + 4;
for (unsigned char ii = 0; ii < p; ii++) {
float angle = 2 * M_PI / p;
fillTriangle(
fig::cTria{
{
_dst.pos.x + _dst.r*std::cos(ii * angle),
_dst.pos.y + _dst.r*std::sin(ii * angle)
},
{
_dst.pos.x + _dst.r*std::cos((ii + 1) * angle),
_dst.pos.y + _dst.r*std::sin((ii + 1) * angle)
},
_dst.pos }
);
};
SDL_SetRenderDrawColor(Game::renderer, 0xaa, 0xff, 0xaa, 0xff);
}
函数,这将对此有所帮助:
fillTriangle()
关于奇怪的类,它们是:
void TextureManager::fillTriangle(const fig::cTria dst){
fnc::small drawable = 0;
for (fnc::small i = 0; i < 3; i++)
if (dst.points[i]->x == dst.points[(i + 1) % 3]->x) { drawable = (i + 2) % 3 + 1; break; }
else if (dst.points[i]->y == dst.points[(i + 1) % 3]->y) { drawable = (i + 2) % 3 + 4; break; }
if (drawable == 0) {
std::pair<fig::cTria, fig::cTria> t = dst.subdivide(
dst.getboundary().siz.x < dst.getboundary().siz.y
);
fillTriangle(t.first);
fillTriangle(t.second);
}
else if (drawable < 4){
short dx = -dst.points[drawable - 1]->x + dst.points[drawable % 2]->x;
SDL_SetRenderDrawColor(Game::renderer, 0xaa, 0xaa, 0xff, 0xff);
for (short i = 0; true; i = fnc::aproach((float)i, 1, dx)) {
SDL_RenderDrawLine(
Game::renderer,
dst.points[drawable - 1]->x + i,
fnc::lerp(dst.points[drawable - 1]->y, dst.points[(drawable + 1) % 3]->y, (float)i / (float)dx),
dst.points[drawable - 1]->x + i,
fnc::lerp(dst.points[drawable - 1]->y, dst.points[drawable % 3]->y, (float)i / (float)dx)
);
if (i == dx) break;
}
SDL_SetRenderDrawColor(Game::renderer, 0xaa, 0xff, 0xaa, 0xff);
}
else {
drawable -= 3;
short dy = -dst.points[drawable - 1]->y + dst.points[drawable % 2]->y;
SDL_SetRenderDrawColor(Game::renderer, 0xaa, 0xaa, 0xff, 0xff);
for (short i = 0; true; i = fnc::aproach((float)i, 1, dy)) {
SDL_RenderDrawLine(
Game::renderer,
fnc::lerp(dst.points[drawable - 1]->x, dst.points[(drawable + 1) % 3]->x, (float)i / (float)dy),
dst.points[drawable - 1]->y + i,
fnc::lerp(dst.points[drawable - 1]->x, dst.points[drawable % 3]->x, (float)i / (float)dy),
dst.points[drawable - 1]->y + i
);
if (i == dy) break;
}
SDL_SetRenderDrawColor(Game::renderer, 0xaa, 0xff, 0xaa, 0xff);
}
}
,并且using fnc::small = unsigned char;
using fnc::ushort = unsigned short;
using fnc::uint = unsigned int;
只是将三角形分为面积可为“可积分”的两个三角形。我的意思是,某种意义上说,一条线要么完全水平,要么完全垂直。 fig::cTria::subdivide()
返回其中刻有三角形的fig::cTria::boudary()
。
在这里,我找到了解决此问题的另一种方法
fig::cRect
我认为它更快。 希望这对某人有帮助。 如果有人提出建议,他们将不胜感激