SDL——面向对象的方式

发布于 2024-12-02 00:09:33 字数 5327 浏览 2 评论 0原文

如果这篇文章太长,请道歉。我只是想让 SDL 以面向对象的方式工作 - 在我克服这一点之前,我继续前进是没有意义的。花了相当多的时间编译这个并出现错误。我将发布我的头文件和源代码,以及我的 makefile 和输出以查看发生了什么。

这是render.h

#ifndef RENDER_H
#define RENDER_H

#include <string>
#include <SDL/SDL.h>

using std::string;

class Render
{
public:
        Render(string filename, int x, int y, SDL_Surface * destination);
    ~Render();
private:
    SDL_Surface * m_optimizedImage;

    void load_image(string filename);
    void apply_surface(int x, int y, SDL_Surface * source, SDL_Surface * destination);
};

#endif

...和render.cpp

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <string>
#include "render.h"

using std::string;

Render::Render(string filename, int x, int y, SDL_Surface * destination)
{
    this->m_optimizedImage = NULL;
    load_image(filename);
    apply_surface(x, y, m_optimizedImage, destination);

}

Render::~Render()
{
    delete m_optimizedImage;
}

void Render::load_image(string filename)
{
    SDL_Surface * loadedImage = IMG_Load(filename.c_str());

    if (loadedImage != NULL)
    {
        m_optimizedImage = SDL_DisplayFormat(loadedImage);

        SDL_FreeSurface(loadedImage);
    }
}

void Render::apply_surface(int x, int y, SDL_Surface * source, SDL_Surface * destination)
{
    SDL_Rect offset;

    offset.x = x;
    offset.y = y;

    SDL_BlitSurface(source, NULL, destination, &offset);

}

...和screenwriter.h

#include <iostream>
#include <SDL/SDL.h>



#ifndef SCREENWRITER_H
#define SCREENWRITER_H

class ScreenWriter
{
public:

    ~ScreenWriter();

    bool flip_screen();
    void delay_screen(int milliseconds);

    bool get_screen_state() const;
    static ScreenWriter& get_instance();

    SDL_Surface * get_screen() const;
private:
    ScreenWriter();

    void initialize();
    bool m_screenFailure;

    SDL_Surface * m_screen;

};

#endif

...和screenwriter .cpp

#include <SDL/SDL.h>
#include "screenwriter.h"

#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define SCREEN_BPP 32

ScreenWriter::ScreenWriter()
{
    this->m_screenFailure = false;
    initialize();
}

ScreenWriter::~ScreenWriter()
{

    SDL_Quit();
}

ScreenWriter& ScreenWriter::get_instance() 
{
    static ScreenWriter instance;

    return instance;
}

SDL_Surface * ScreenWriter::get_screen() const
{
    return m_screen;
}

bool ScreenWriter::get_screen_state() const
{
    return this->m_screenFailure;
}

void ScreenWriter::delay_screen(int milliseconds)
{
    SDL_Delay(milliseconds);
}

int ScreenWriter::flip_screen()
{

    if (SDL_Flip(m_screen) == -1)
    {
        return 1;
    }
    else
    {

        SDL_Flip(m_screen);
        return 0;
    }

}

void ScreenWriter::initialize()
{
        if (SDL_Init(SDL_INIT_EVERYTHING == -1))
        {
                std::cout << "SDL_Init has failed";
        }
        else
        {

                SDL_Init(SDL_INIT_EVERYTHING);
                //initialize screen
                this->m_screen = SDL_SetVideoMode(SCREEN_WIDTH,
                                                  SCREEN_HEIGHT,
                                                  SCREEN_BPP,
                                                  SDL_SWSURFACE);

                if (m_screen == NULL)
                {
                        this->m_screenFailure = true;
                }
                else
                {
                        this->m_screenFailure = false;
                }

                //set caption header
                SDL_WM_SetCaption("Hello WOrld", NULL);
        }

}

...当然ma​​in.cpp

#include <iostream>
#include <SDL/SDL.h>
#include "screenwriter.h"
#include "render.h"

int main(int argc, char * args[])
{
    std::cout << "hello world!" << std::endl;

    ScreenWriter * instance = ScreenWriter::get_instance();

    instance->flip_screen();

    Render render = new Render("look.png", 0, 0, instance->get_screen());

    delete instance();

    return 0;
}

...我的输出

g++ -c main.cpp render.h screenwriter.h -lSDL -lSDL_image
main.cpp: In function ‘int main(int, char**)’:
main.cpp:10:55: error: cannot convert ‘ScreenWriter’ to ‘ScreenWriter*’ in initialization
main.cpp:12:69: error: conversion from ‘Render*’ to non-scalar type ‘Render’ requested
make: *** [main.o] Error 1

...我的ma​​kefile

program : main.o render.o screenwriter.o
    g++ -o program main.o render.o screenwriter.o -lSDL -lSDL_image

main.o : main.cpp render.h screenwriter.h
    g++ -c main.cpp render.h screenwriter.h -lSDL -lSDL_image

render.o : render.h render.cpp
    g++ -c render.h render.cpp -lSDL

screenwriter.o : screenwriter.h screenwriter.cpp
    g++ -c screenwriter.h screenwriter.cpp -lSDL -lSDL_image

clean:
    rm program main.o render.o screenwriter.o 

细节

我的目标是将 ScreenWriter 作为单例实现通过初始化设置 allegro 并根据需要标记所有内容。第二个目标依赖于渲染,通过指定 x 和 y 坐标以及要渲染的文件的路径来渲染以加载到地图上。这在程序上很容易做到,但我已经准备好在这方面尝试 OO 设计。

那么,有什么想法吗?

Apologize if this is too long of a post. I'm merely trying to get SDL to work in an object oriented fashion - there's no point in me moving on until I get past this point. Been spending a fair amount of time compiling this and getting errors. I'll post my header files and sources, along with my makefile and an output to see what's going on.

Here's render.h:

#ifndef RENDER_H
#define RENDER_H

#include <string>
#include <SDL/SDL.h>

using std::string;

class Render
{
public:
        Render(string filename, int x, int y, SDL_Surface * destination);
    ~Render();
private:
    SDL_Surface * m_optimizedImage;

    void load_image(string filename);
    void apply_surface(int x, int y, SDL_Surface * source, SDL_Surface * destination);
};

#endif

...and render.cpp:

#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <string>
#include "render.h"

using std::string;

Render::Render(string filename, int x, int y, SDL_Surface * destination)
{
    this->m_optimizedImage = NULL;
    load_image(filename);
    apply_surface(x, y, m_optimizedImage, destination);

}

Render::~Render()
{
    delete m_optimizedImage;
}

void Render::load_image(string filename)
{
    SDL_Surface * loadedImage = IMG_Load(filename.c_str());

    if (loadedImage != NULL)
    {
        m_optimizedImage = SDL_DisplayFormat(loadedImage);

        SDL_FreeSurface(loadedImage);
    }
}

void Render::apply_surface(int x, int y, SDL_Surface * source, SDL_Surface * destination)
{
    SDL_Rect offset;

    offset.x = x;
    offset.y = y;

    SDL_BlitSurface(source, NULL, destination, &offset);

}

...and screenwriter.h:

#include <iostream>
#include <SDL/SDL.h>



#ifndef SCREENWRITER_H
#define SCREENWRITER_H

class ScreenWriter
{
public:

    ~ScreenWriter();

    bool flip_screen();
    void delay_screen(int milliseconds);

    bool get_screen_state() const;
    static ScreenWriter& get_instance();

    SDL_Surface * get_screen() const;
private:
    ScreenWriter();

    void initialize();
    bool m_screenFailure;

    SDL_Surface * m_screen;

};

#endif

...and screenwriter.cpp:

#include <SDL/SDL.h>
#include "screenwriter.h"

#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define SCREEN_BPP 32

ScreenWriter::ScreenWriter()
{
    this->m_screenFailure = false;
    initialize();
}

ScreenWriter::~ScreenWriter()
{

    SDL_Quit();
}

ScreenWriter& ScreenWriter::get_instance() 
{
    static ScreenWriter instance;

    return instance;
}

SDL_Surface * ScreenWriter::get_screen() const
{
    return m_screen;
}

bool ScreenWriter::get_screen_state() const
{
    return this->m_screenFailure;
}

void ScreenWriter::delay_screen(int milliseconds)
{
    SDL_Delay(milliseconds);
}

int ScreenWriter::flip_screen()
{

    if (SDL_Flip(m_screen) == -1)
    {
        return 1;
    }
    else
    {

        SDL_Flip(m_screen);
        return 0;
    }

}

void ScreenWriter::initialize()
{
        if (SDL_Init(SDL_INIT_EVERYTHING == -1))
        {
                std::cout << "SDL_Init has failed";
        }
        else
        {

                SDL_Init(SDL_INIT_EVERYTHING);
                //initialize screen
                this->m_screen = SDL_SetVideoMode(SCREEN_WIDTH,
                                                  SCREEN_HEIGHT,
                                                  SCREEN_BPP,
                                                  SDL_SWSURFACE);

                if (m_screen == NULL)
                {
                        this->m_screenFailure = true;
                }
                else
                {
                        this->m_screenFailure = false;
                }

                //set caption header
                SDL_WM_SetCaption("Hello WOrld", NULL);
        }

}

...and of course main.cpp:

#include <iostream>
#include <SDL/SDL.h>
#include "screenwriter.h"
#include "render.h"

int main(int argc, char * args[])
{
    std::cout << "hello world!" << std::endl;

    ScreenWriter * instance = ScreenWriter::get_instance();

    instance->flip_screen();

    Render render = new Render("look.png", 0, 0, instance->get_screen());

    delete instance();

    return 0;
}

...my output:

g++ -c main.cpp render.h screenwriter.h -lSDL -lSDL_image
main.cpp: In function ‘int main(int, char**)’:
main.cpp:10:55: error: cannot convert ‘ScreenWriter’ to ‘ScreenWriter*’ in initialization
main.cpp:12:69: error: conversion from ‘Render*’ to non-scalar type ‘Render’ requested
make: *** [main.o] Error 1

...my makefile

program : main.o render.o screenwriter.o
    g++ -o program main.o render.o screenwriter.o -lSDL -lSDL_image

main.o : main.cpp render.h screenwriter.h
    g++ -c main.cpp render.h screenwriter.h -lSDL -lSDL_image

render.o : render.h render.cpp
    g++ -c render.h render.cpp -lSDL

screenwriter.o : screenwriter.h screenwriter.cpp
    g++ -c screenwriter.h screenwriter.cpp -lSDL -lSDL_image

clean:
    rm program main.o render.o screenwriter.o 

the nitty gritty:

My goal with this is to have ScreenWriter implemented as a singleton to setup allegro and flag everything as needed through initialization. The second objective relies on render to just render by specifying x and y coordinates, along with a path to the file to render to load on the map. This is easy to do procedurally, but I'm ready to experiment with OO design on this.

So, any thoughts?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一笑百媚生 2024-12-09 00:09:33

您有两个语法错误,从您的错误中可以清楚地看出:

ScreenWriter * instance = ScreenWriter::get_instance();

应该是

ScreenWriter & instance = ScreenWriter::get_instance();

因为 get_instance 返回引用,而不是指针,

Render render = new Render("look.png", 0, 0, instance->get_screen());

应该是

Render * render = new Render("look.png", 0, 0, instance->get_screen());

因为 new 返回指针,而不是对象或参考。

另外,

delete instance();

应该是

delete render;

因为前者不仅完全错误,而且没有用于 new 分配的任何内容。然而,render 是。因此,您必须删除它以避免内存泄漏。

我不明白问题的“任何想法”部分,因为它没有说明什么。英语不是我的母语,所以如果我错过了什么,请原谅我。

You have two syntax errors which are clear from your errors:

ScreenWriter * instance = ScreenWriter::get_instance();

should be

ScreenWriter & instance = ScreenWriter::get_instance();

because get_instance returns a reference, not a pointer, and

Render render = new Render("look.png", 0, 0, instance->get_screen());

should be

Render * render = new Render("look.png", 0, 0, instance->get_screen());

because new returns a pointer, not an object or reference.

Also,

delete instance();

should be

delete render;

because not only is the former completely wrong, but it's not being used on anything allocated by new. render is, however. So you have to delete it to avoid a memory leak.

I don't understand the "any thoughts" part of the question because it doesn't say about what. English isn't my first language though, so forgive me if I missed something.

梦行七里 2024-12-09 00:09:33

渲染图像后翻转屏幕。当您对某些内容进行位块传输时,它会被位块传输到缓冲区上。 SDL_Flip() 只是交换这些缓冲区,以便可以看到您的 o/p。所以我想你应该替换这两行。

Flip the screen after rendering the image. When you blit something, it's blitted on a buffer. SDL_Flip() just swaps those buffers so that your o/p can be seen. So you should be replacing those two lines, I guess.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文