SDL2 Kleiner Fehler in Drehroutine (sin() & cos()) für BMP
-
Hallo zusammen ,
ich übersetze gerade den Code eines Tutorials nach SDL2, es geht um eine kleine Routine um eine Bitmap mit sin() und cos() selbst zu drehen. Bisher hat alles gut geklappt aber kurz vor dem Ende bekomme ich ein Problem.
Das Beispiel Sin, cos and bitmaps: rotate_sprite Circ9.c funktioniert nicht richtig. Die Bitmap wird zwar gedreht aber leider völlig falsch. Es handelt sich wahrscheinlich nur um einen kleinen Fehler aber ich finde ihn einfch nicht .Ich habe zwei kleine Header SDL_CRAP und PIXEL_CRAP geschrieben um in dem Hauptcode überichtlicher zu gestalten und den Fokus nur auf das Beispiel aus dem Tutorial zu legen.
Der Fehler liegt garantiert in der Drehroutine in der main(), die anderen Teile habe ich getestet und bekam keine Fehler!!!
Ich nutze VisualStudio 2015 CE und Windows 10.
Wäre klasse wenn Ihr mir helfen könntet.
Vielen Dank für Eure Mühe und Hilfe vorab,
SplifferTutorial:
http://www.helixsoft.nl/articles/circle/sincos.htm
Testimage (muss ins .bmp-Format konvertiert werden):
https://picload.org/view/rciroidw/test.png.html
Hauptcode:
#include<windows.h> #include "SDL_CRAP.h" #include "PIXEL_CRAP.h" int main(int argc, char* argv[]) { SDL_Crap sdlCrap; PIXEL_Crap pixelCrap; sdlCrap.init(); sdlCrap.loadMedia(); // Ziel_Surface erstellen int width = 256; int height = 128; SDL_Surface* DestImageSurface; DestImageSurface = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0); if (DestImageSurface == NULL) { SDL_Log("SDL_CreateRGBSurfaceWithFormat() failed: %s", SDL_GetError()); exit(1); } // Um direkten Zugriff auf die Pixel zu haben d.h. um diese bearbeiten zu können // muss die betreffende Oberfläche abgeschlossen werden (SDL_MUSTLOCK) if (SDL_MUSTLOCK(sdlCrap.SrcImageSurface) == true) // Test ob Oberfläche geschlossen/ geöffnet werden muss { SDL_LockSurface(sdlCrap.SrcImageSurface); // Oberfläche schließen SDL_LockSurface(DestImageSurface); // Oberfläche schließen } int src_x, src_y;// current position in the source bitmap int dest_x, dest_y;// current position in the destination bitmap // src_x and src_y will change each time by dx and dy int dx, dy; // src_x and src_y will be initialized to start_x and start_y // at the beginning of each new line int start_x = 0, start_y = 0; // We create a bit mask to make sure x and y are in bounds. // Unexpected things will happen // if the width or height are not powers of 2. int x_mask = sdlCrap.SrcImageSurface->w - 1; int y_mask = sdlCrap.SrcImageSurface->h - 1; // calculate increments for the coordinates in the source bitmap // for when we move right one pixel on the destination bitmap dx = (cos(1)* 5); dy = (sin(1)* 5); for (dest_y = 0; dest_y < DestImageSurface->h; dest_y++) { // set the position in the source bitmap to the // beginning of this line src_x = start_x; src_y = start_y; for (dest_x = 0; dest_x < DestImageSurface->w; dest_x++) { // Copy a pixel. // This can be optimized a lot by using // direct bitmap access. pixelCrap.putpixel(DestImageSurface, dest_x, dest_y, pixelCrap.getpixel(sdlCrap.SrcImageSurface, (src_x) & x_mask, (src_y) & y_mask)); // advance the position in the source bitmap src_x += dx; src_y += dy; } // for the next line we have a different starting position start_x -= dy; start_y += dx; } if (SDL_MUSTLOCK(sdlCrap.SrcImageSurface) == true) // Test ob Oberfläche geschlossen/ geöffnet werden muss { SDL_UnlockSurface(sdlCrap.SrcImageSurface); // Oberfläche öffnen } SDL_BlitSurface(DestImageSurface, NULL, sdlCrap.ScreenSurface, NULL); // Image auf SrcImageSurface blitten SDL_UpdateWindowSurface(sdlCrap.BasicWindow); // Basisfenster erneuern (updaten) //sdlCrap.SrcImageSurface SDL_Delay(10000); // 10.000 Millisekunden warten sdlCrap.close(); // aufräumen return 0; }
SDL_CRAP:
#pragma once #include "cstdio" #include "../packages/sdl2.2.0.5/build/native/include/SDL.h" class SDL_Crap { private: // Success Flags bool initSuccess = true; bool mediaSuccess = true; public: SDL_Crap() = default; ~SDL_Crap() = default; int SCREEN_X = 800; int SCREEN_Y = 600; SDL_Window* BasicWindow = nullptr; // Fenster auf dem wir die Grafik wiedergeben wollen SDL_Surface* ScreenSurface = nullptr; // Oberfläche die im Basisfenster enthalten ist SDL_Surface* SrcImageSurface = nullptr; // Oberfläche für das Image das geladen werden soll bool init(); bool loadMedia(); void close(); }; inline bool SDL_Crap::init() { if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError()); initSuccess = false; } else { // Create window BasicWindow = SDL_CreateWindow("SDL_2 Image On Screen!!!!", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_X, SCREEN_Y, SDL_WINDOW_SHOWN); if (BasicWindow == nullptr) { printf("Window could not be created! SDL_Error: %s\n", SDL_GetError()); initSuccess = false; } else { ScreenSurface = SDL_GetWindowSurface(BasicWindow); } } return initSuccess; } inline bool SDL_Crap::loadMedia() { // Load splash image SrcImageSurface = SDL_LoadBMP("Test.bmp"); if (SrcImageSurface == nullptr) { printf("Unable to load image %s! SDL Error: %s\n", "girl.bmp", SDL_GetError()); mediaSuccess = false; } return mediaSuccess; } inline void SDL_Crap::close() { SDL_FreeSurface(SrcImageSurface); // Deallocate surface SrcImageSurface = nullptr; SDL_DestroyWindow(BasicWindow); // Destroy window BasicWindow = nullptr; SDL_Quit(); // Quit SDL subsystems }
PIXEL_CRAP:
#pragma once #include "SDL_CRAP.h" class PIXEL_Crap { private: public: PIXEL_Crap() = default; ~PIXEL_Crap() = default; // Return the pixel value at (x, y) // NOTE: The surface must be locked before calling this! Uint32 getpixel(SDL_Surface *surface, int x, int y); /* * Set the pixel at (x, y) to the given value * NOTE: The surface must be locked before calling this! */ void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel); }; inline Uint32 PIXEL_Crap::getpixel(SDL_Surface *surface, int x, int y) { int bpp = surface->format->BytesPerPixel; /* Here p is the address to the pixel we want to retrieve */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; switch (bpp) { case 1: return *p; case 2: return *(Uint16 *)p; case 3: { if (SDL_BYTEORDER == SDL_BIG_ENDIAN) return p[0] << 16 | p[1] << 8 | p[2]; return p[0] | p[1] << 8 | p[2] << 16; } case 4: return *(Uint32 *)p; default: return 0; /* shouldn't happen, but avoids warnings */ } // switch } inline void PIXEL_Crap::putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel) { int bpp = surface->format->BytesPerPixel; /* Here p is the address to the pixel we want to set */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; switch (bpp) { case 1: *p = pixel; break; case 2: *(Uint16 *)p = pixel; break; case 3: if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { p[0] = (pixel >> 16) & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = pixel & 0xff; } else { p[0] = pixel & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = (pixel >> 16) & 0xff; } break; case 4: *(Uint32 *)p = pixel; break; default: break; /* shouldn't happen, but avoids warnings */ } // switch }
-
Spliffer schrieb:
Das Beispiel Sin, cos and bitmaps: rotate_sprite Circ9.c funktioniert nicht richtig. Die Bitmap wird zwar gedreht aber leider völlig falsch. Es handelt sich wahrscheinlich nur um einen kleinen Fehler aber ich finde ihn einfch nicht .
wenn du den fehler beschreiben wuerdest, haettest du bessere chancen hilfe zu erhalten (ich hab z.b. nichtmal sdl2 installiert und nur zum compilieren deines quellcodes nicht so recht lust das zu tun).
grob eine checkliste:
-sin cos sind in radian, fuetterst du die richtig?
-benutzt du die richtigen formate fuer variablen?
-
Hallo rapso,
ja ich denke schon daß ich sin() & cos() richtig füttere und die Variablen müssten auch die richtigen Formate haben sonst würde überhaupr nichts klappen.
Fehlerbeschreibung:
Die Farben des Images sind nicht an der richtigen Stelle und das Image wird auch völlig verkehrt gezeichnet. Es sieht irgendwie eher gespiegelt als gedreht aus.
ich hab z.b. nichtmal sdl2 installiert und nur zum compilieren deines quellcodes nicht so recht lust das zu tun
Klar das verstehe ich! Ich suche mich schon dusslig nach einem SDL2 Forum da man dort wahrscheinlich den Code compilieren würde. Für OpenGL und DX gibt es sowas füe SDL anscheinend nicht. Es ist sehr schwer in Detail zu erklären was nicht funktioniert!
Vielen Dank für Eure Mühe und Hilfe,
Spliffer
-
Alles klar jetzt klappts !!!!
Grüße,
Spliffer