bearophile wrote: > http://rosettacode.org/wiki/Animate_a_pendulum
Here's the D version using the direct to screen functions. I ported the C# version, since the APIs were most alike. (Not really surprising... C# and I both thinly wrapped GDI.) === import std.math; import simpledisplay; void main() { auto win = new SimpleWindow(512, 512); real angle = PI / 2; real angleVelocity = 0; immutable real dt = 0.1; int length = 150; win.eventLoop(50, () { auto anchorX = win.width / 2 - 12; auto anchorY = win.height / 4; auto ballX = anchorX + cast(int) (sin(angle) * length); auto ballY = anchorY + cast(int) (cos(angle) * length); auto angleAcceleration = -9.81 / length * sin(angle); angleVelocity += angleAcceleration * dt; angle += angleVelocity * dt; auto painter = win.draw(); painter.fillColor = Color(255, 255, 255); painter.drawRectangle(0, 0, win.width, win.height); painter.outlineColor = Color(0, 0, 0); painter.drawLine(anchorX, anchorY, ballX, ballY); painter.fillColor = Color(0, 0, 0); painter.drawEllipse(anchorX - 3, anchorY - 4, anchorX + 3, anchorY + 4); painter.fillColor = fromHsl(30, 0.8, 0.4); painter.drawEllipse(ballX - 7, ballY - 7, ballX + 7, ballY + 7); } ); } === Exit the program by closing the window. Some comments. First, you'll see that the pulse timer is implemented, allowing the animation to easily happen. Then, there's a dozen lines to actually do the drawing, starting with auto painter = win.draw(); win.draw (name might change) returns a ScreenPainter struct, which gives access to the drawing directly in the window, via a handful of native api calls. This struct is necessary to handle some state and cleanup that the native APIs require. (It's destructor does it all for you though, so no need to think about it here.) You can draw images, text, pixels (slowly), lines, rectangles, arcs, and polygons with solid colors for filling and outline. It's the lowest common denominator between Windows GDI and Xlib. I agree with what Michel said earlier about it being a lot of fairly pointless effort to go further than this. Instead, we'll offer a rich set of cross-platform functions to draw to an image, and simply copy those images to the windows when we want to get fancy. (That's easy to do here: painter.drawImage(x, y, image); ) Moving on, I first clear the screen by drawing a large, white rectangle over the window. fillColor and outlineColor are settable properties that are implicitly used in the drawing functions. (This reflects how pens and brushes are tied to the HDC on Windows and foreground and background colors are tied to the GC on X - you don't pass colors to the individual functions on either native API either.) Following Windows' lead, all the functions use the two separate colors, one for the outline of the shape and one for filling it in, hence their names. Note that only outline is used for drawline lines and pixels. If you want to draw a shape without filling it in, first set the fill color to transparent: painter.fillColor = Color.transparent; (Color.transparent is a static method to conveniently return a color with alpha = 0.) Also in there, you can see me using the fromHsl helper function to return a Color specifying HSL values instead of RGB. Finally, I said this draws directly to the screen, but it actually doesn't... it double buffers underneath. No need to call a buffer.flip function though. ScreenPainter's destructor does it for you. You don't have to think about it. The buffer is preserved across calls and used to automatically handle WM_PAINT/Expose messages. ====== There's still a handful of little things and a lot of error checking needed, but I'm pretty happy with this as the screen drawing base. It covers all the easy stuff. The hard stuff will be in platform independent images. Anyway, here's the updated simpledisplay.d: http://arsdnet.net/dcode/simpledisplay.d