Wichtige Frage zur Animation mit SDL (sdl_gfx)!
-
Hallo,
ich soll für eine Facharbeit für den Leistungkurs Physik ein Programm zur Berechnung und Darstellung von Pendelbewegungen in versch. Umgebungen entwickeln.
Ich habe mir überlegt, dass ich das ganze unter C++ mit grafischer Oberfläche erstellen möchte. Die Berechnungen sind eig. nicht mein Problem, aber, da ich die SDL bzw. SDL_gfx für die Animation eines 2-dimensionalen Pendels benutzen möchte, wollte ich hier mal fragen, wie ich das am geschicktestesn lösen kann. Es solle nach Möglichkeit ein animiertes Pendel sein, dass auf gegebenen (errechnete) Werte entsprechend reagiert und ggf. in Intervallen weiterzuschalten sei. Ausserdem wollte ich fragen, wie sich am besten eine gezeichnete Linie (SDL_gfx) animieren lässt. Eine Sleep Funktion zur Animation (zwischen den Lösch- und Zeichenintervallen) ist nicht geeignet, oder? Sollte das ganze über die FPS geregelt werden? Wenn ja, wie?
Gruß
hypersayyajinPS: Vielen Dakn schonma!
-
*push*
-
Altes Bild loeschen, neues Bild Zeichnen.
-
hypersayyajin schrieb:
Eine Sleep Funktion zur Animation (zwischen den Lösch- und Zeichenintervallen) ist nicht geeignet, oder?
Geht eig. auch, wird aber ehr selten benutzt. Dann schon die Timer der SDL verwenden.
hypersayyajin schrieb:
Sollte das ganze über die FPS geregelt werden? Wenn ja, wie?

Das kannst du machen, wenn du unbedingt willst.
Frage: Was war jetzt so wichtig an deiner Frage???
-
erm ja..meine frage ist eig, wie ich das ganze realisieren soll?! ich hab zur zeit keine idee, wie ich ein pendel zeichnen soll, dass 1.) auf errechnete werte reagiert und sich 2.) in seiner animation "stoppen" lässt, um in intervallen weiterzuschalten.
bitte helft mir
-
du schreibst halt eine funktion die dir die pendel position unter beachtung der speziellen eigenschaften nach einem gewissen zeitinterval berechnet. anschließend zeichnest du das ganze indem du die errechneten werte interpretierst.
um das ganze zu animieren machst du das halt unmittelbar nacheinander, wobei du ständig die zeit erhöhst.
-
Hallo!
erm..ich hab mal einige Tutorials und Docus durchforstet und hab mir daraus folgendes Programm gebastelt:#include <SDL/SDL.h> #include <stdio.h> #include <stdlib.h> #include <SDL/SDL_framerate.h> #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) #define abs(a) (((a)<0) ? -(a) : (a)) #define sign(a) (((a)<0) ? -1 : (a)>0 ? 1 : 0) //---------------------------------------------------------- // Draw lines in 32 bit surfaces. Note that this routine // ignores alpha values. It writes them into the surface // if they are included in the pixel, but does nothing // else with them. static void line32(SDL_Surface *s, int x1, int y1, int x2, int y2, Uint32 color) { int d; int x; int y; int ax; int ay; int sx; int sy; int dx; int dy; Uint8 *lineAddr; Sint32 yOffset; dx = x2 - x1; ax = abs(dx) << 1; sx = sign(dx); dy = y2 - y1; ay = abs(dy) << 1; sy = sign(dy); yOffset = sy * s->pitch; x = x1; y = y1; lineAddr = ((Uint8 *)(s->pixels)) + (y * s->pitch); if (ax>ay) { /* x dominant */ d = ay - (ax >> 1); for (;;) { *((Uint32 *)(lineAddr + (x << 2))) = (Uint32)color; if (x == x2) { return; } if (d>=0) { y += sy; lineAddr += yOffset; d -= ax; } x += sx; d += ay; } } else { /* y dominant */ d = ax - (ay >> 1); for (;;) { *((Uint32 *)(lineAddr + (x << 2))) = (Uint32)color; if (y == y2) { return; } if (d>=0) { x += sx; d -= ay; } y += sy; lineAddr += yOffset; d += ax; } } } //---------------------------------------------------------- // Examine the depth of a surface and select a line // drawing routine optimized for the bytes/pixel of the // surface. static void line(SDL_Surface *s, int x1, int y1, int x2, int y2, Uint32 color) { switch (s->format->BytesPerPixel) { case 4: line32(s, x1, y1, x2, y2, color); break; } } //---------------------------------------------------------- // sweepLine animates a line on a surface based on the // elapsed time. class sweepLine { private: SDL_Surface *s; // The surface to draw on. Uint32 color; // The color of the line. int last; // last time update() was // called. int maxx; // Maximum valid X value. int maxy; // Maximum valid Y value. float x1, y1; // The current location float dx1, dy1; // and velocity of the line float x2, y2; // end points. float dx2, dy2; // movePoint computes the new location of a point based // on its initial location, its velocity, and the // elapsed time. void movePoint(float &x, float &y, float &dx, float &dy, int dt) { // Compute the new X location. x += (dx * dt); // if the X value is off of the screen, move it back // on and reverse the velocity in the X direction. if (x >= maxx) { x = maxx; dx = -dx; } else if (x <= 0) { x = 0; dx = -dx; } // Same thing for Y. y += (dy * dt); if (y >= maxy) { y = maxy; dy = -dy; } else if (y <= 0) { y = 0; dy = -dy; } } public: // sweepLine animates a line on a surface. It is // initialized with a pointer to the surface to draw the // line on, a pixel value that specifies the color of // the line, the current time, and the initial locations // of the line end points and their // velocities. Velocities are specified in // pixels/millisecond. // This method initializes the class and forces the end // points of the lines to be inside the boundaries of // the surface. If it didn't do that the line drawing // code would try to write outside of the surface and // crash the program. sweepLine(SDL_Surface *s, Uint32 color, int time, float x1, float y1, float dx1, float dy1, float x2, float y2, float dx2, float dy2): s(s), color(color), last(time), x1(x1), y1(y1), dx1(dx1), dy1(dy1), x2(x2), y2(y2), dx2(dx2), dy2(dy2) { // Set the values of maxx and maxy to one less than // the width and height. Do this makes clipping easier // to code. maxx = 0; maxy = 0; if (NULL != s) { maxx = s->w - 1; maxy = s->h - 1; } // Force the line end points onto the screen. x1 = max(x1, 0); y1 = max(y1, 0); x2 = max(x2, 0); y2 = max(y2, 0); x1 = min(x1, maxx); y1 = min(y1, maxy); x2 = min(x2, maxx); y2 = min(y2, maxy); } void update(long now) { int dt = now - last; last = now; // Update the locations of the line end points. movePoint(x1, y1, dx1, dy1, dt); movePoint(x2, y2, dx2, dy2, dt); // Draw the line at its new location. line(s, (int)x1, (int)y1, (int)x2, (int)y2, color); } }; //---------------------------------------------------------- // gameTime keeps track of game time as opposed to real // time. Game time can start and stop and even change its // speed while real time just keeps ticking along. class gameTime { private: int startTime; // Last time the clock was // started. int baseTime; // How much game time passed // before the last time the // clock was started. bool running; // Is the clock running or // not? public: // Initialize the class variables. At this point no game // time has elapsed and the clock is not running. gameTime() { startTime = 0; baseTime = 0; running = false; } // Start the clock. void start() { if (!running) { startTime = SDL_GetTicks(); running = true; } } // stop the clock void stop() { if (running) { baseTime = baseTime + (SDL_GetTicks() - startTime); running = false; } } // True if the clock is paused. bool stopped() { return !running; } // Get this clocks current time in milliseconds. int time() { if (running) { return baseTime + (SDL_GetTicks() - startTime); } else { return baseTime; } } }; //---------------------------------------------------------- int main(int argc, char *argv[]){ SDL_Init(SDL_INIT_EVERYTHING); SDL_Surface *screen = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE|SDL_DOUBLEBUF); gameTime gt; char *name = argv[0]; SDL_Event event; SDL_PixelFormat *pf = NULL; Uint32 black; Uint32 red; Uint32 green; Uint32 blue; int screenWidth = 640; int screenHeight = 480; bool done = false; sweepLine *rl = NULL; screen = SDL_SetVideoMode(screenWidth, screenHeight, 0, SDL_ANYFORMAT | //SDL_FULLSCREEN | SDL_SWSURFACE ); // Grab the pixel format for the screen. SDL_MapRGB() // needs the pixel format to create pixels that are laid // out correctly for the screen. pf = screen->format; //Create the pixel values used in the program. Black is //for clearing the background and the other three are //for line colors. Note that in SDL you specify color //intensities in the rang 0 to 255 (hex ff). That //doesn't mean that you always get 24 or 32 bits of //color. If the format doesn't support the full color //range, SDL scales it to the range that is correct for //the pixel format. black = SDL_MapRGB(pf, 0x00, 0x00, 0x00); red = SDL_MapRGB(pf, 0xff, 0x00, 0x00); green = SDL_MapRGB(pf, 0x00, 0xff, 0x00); blue = SDL_MapRGB(pf, 0x00, 0x00, 0xff); SDL_WM_SetCaption(name, name); // Create the three animating lines. It is amazing to // see the different kinds of behavior you can get from // such a simple animation object. rl = new sweepLine(screen, red, gt.time(), screen->w - 1, 0, -0.3, 0, 0, screen->h - 1, 0.3, 0); // Start the game clock. gt.start(); while (!done) { FPSmanager fpsm; SDL_initFramerate(&fpsm); SDL_setFramerate(&fpsm, 60); // 60 Frames Per Second bool isRunning = true; while(isRunning){ // Clear the screen SDL_FillRect(screen, NULL, 0); // ROTOZOOM EXAMPLE // Make the new rotated image static double rotationAngle = 0; rotationAngle = 0.0; SDL_Surface* image = SDL_LoadBMP("white.bmp"); // Draw the rotated image SDL_Rect rect; SDL_BlitSurface(image, NULL, screen, &rect); // Clear memory when finished with the rotated image SDL_FreeSurface(image); int t = gt.time(); rl->update(t); SDL_Flip(screen); SDL_Delay(10); } SDL_framerateDelay(&fpsm); } return 0; }Nur bekomme ich es nicht hin, dass die gezeichnete Linie "Pendelcharakter" bzw. "Pendeloptik" hat. Wie krieg ich also den "Drehpunkt" zentiriert an den oberen Bildschirmrand? Wie simuliere ich eine echte Pendelbewegung?
