Moved all bindings to the "bindings" sub-directory
Renamed the CSFML directory to c Renamed the DSFML directory to d --> bindings must now be updated to match the new organization! git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1630 4e206d99-4929-0410-ac5d-dfc041789085
BIN
bindings/d/samples/dsfml/bin/Data/background.jpg
Normal file
After Width: | Height: | Size: 154 KiB |
BIN
bindings/d/samples/dsfml/bin/Data/ball.tga
Normal file
BIN
bindings/d/samples/dsfml/bin/Data/ball.wav
Normal file
BIN
bindings/d/samples/dsfml/bin/Data/bluerallyecarleft.bmp
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
bindings/d/samples/dsfml/bin/Data/bluerallyecarright.bmp
Normal file
After Width: | Height: | Size: 27 KiB |
16
bindings/d/samples/dsfml/bin/Data/blur.sfx
Normal file
|
@ -0,0 +1,16 @@
|
|||
texture framebuffer
|
||||
float offset
|
||||
|
||||
effect
|
||||
{
|
||||
vec2 offx = vec2(offset, 0.0);
|
||||
vec2 offy = vec2(0.0, offset);
|
||||
|
||||
vec4 c0 = framebuffer(_in);
|
||||
vec4 c1 = framebuffer(_in - offy);
|
||||
vec4 c2 = framebuffer(_in + offy);
|
||||
vec4 c3 = framebuffer(_in - offx);
|
||||
vec4 c4 = framebuffer(_in + offx);
|
||||
|
||||
_out = c0 * 0.2 + c1 * 0.2 + c2 * 0.2 + c3 * 0.2 + c4 * 0.2;
|
||||
}
|
BIN
bindings/d/samples/dsfml/bin/Data/car_idle.wav
Normal file
BIN
bindings/d/samples/dsfml/bin/Data/cheeseburger.ttf
Normal file
10
bindings/d/samples/dsfml/bin/Data/colorize.sfx
Normal file
|
@ -0,0 +1,10 @@
|
|||
texture framebuffer
|
||||
vec3 color
|
||||
|
||||
effect
|
||||
{
|
||||
vec4 pixel = framebuffer(_in);
|
||||
float gray = pixel.r * 0.39 + pixel.g * 0.50 + pixel.b * 0.11;
|
||||
|
||||
_out = vec4(gray * color, 1.0) * 0.6 + pixel * 0.4;
|
||||
}
|
BIN
bindings/d/samples/dsfml/bin/Data/crosshair.bmp
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
bindings/d/samples/dsfml/bin/Data/crosshair.tga
Normal file
12
bindings/d/samples/dsfml/bin/Data/fisheye.sfx
Normal file
|
@ -0,0 +1,12 @@
|
|||
texture framebuffer
|
||||
vec2 mouse
|
||||
|
||||
effect
|
||||
{
|
||||
float len = distance(_in, mouse) * 7.0;
|
||||
|
||||
if (len < 1.0)
|
||||
_out = framebuffer(_in + (_in - mouse) * len);
|
||||
else
|
||||
_out = framebuffer(_in);
|
||||
}
|
6
bindings/d/samples/dsfml/bin/Data/nothing.sfx
Normal file
|
@ -0,0 +1,6 @@
|
|||
texture framebuffer
|
||||
|
||||
effect
|
||||
{
|
||||
_out = framebuffer(_in);
|
||||
}
|
BIN
bindings/d/samples/dsfml/bin/Data/opengl/background.jpg
Normal file
After Width: | Height: | Size: 140 KiB |
BIN
bindings/d/samples/dsfml/bin/Data/opengl/texture.jpg
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
bindings/d/samples/dsfml/bin/Data/paddle.tga
Normal file
BIN
bindings/d/samples/dsfml/bin/Data/wave.jpg
Normal file
After Width: | Height: | Size: 23 KiB |
12
bindings/d/samples/dsfml/bin/Data/wave.sfx
Normal file
|
@ -0,0 +1,12 @@
|
|||
texture framebuffer
|
||||
texture wave
|
||||
vec2 offset
|
||||
|
||||
effect
|
||||
{
|
||||
vec2 texoffset = wave(_in * offset).xy;
|
||||
texoffset -= vec2(0.5, 0.5);
|
||||
texoffset *= 0.05;
|
||||
|
||||
_out = framebuffer(_in + texoffset);
|
||||
}
|
BIN
bindings/d/samples/dsfml/bin/libsndfile-1.dll
Normal file
BIN
bindings/d/samples/dsfml/bin/openal32.dll
Normal file
230
bindings/d/samples/dsfml/dfl/DFLSample.d
Normal file
|
@ -0,0 +1,230 @@
|
|||
module dflsample;
|
||||
|
||||
import dsfml.system.all;
|
||||
import dsfml.window.all;
|
||||
|
||||
// DFL and Derelict must be present.
|
||||
import dfl.all;
|
||||
|
||||
import Derelict.opengl.gl;
|
||||
import Derelict.opengl.glu;
|
||||
|
||||
|
||||
// An enum for each controls methods
|
||||
enum ControlMethod
|
||||
{
|
||||
MOUSE,
|
||||
KEYBOARD
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
DerelictGL.load();
|
||||
DerelictGLU.load();
|
||||
//Start the message loop
|
||||
Application.run(new MyForm());
|
||||
}
|
||||
|
||||
//A simple form with a groupbox to choose input method and the openGL control
|
||||
class MyForm : Form
|
||||
{
|
||||
GLControl m_gl;
|
||||
GroupBox m_gbx;
|
||||
RadioButton m_rb1;
|
||||
RadioButton m_rb2;
|
||||
|
||||
this()
|
||||
{
|
||||
m_gbx = new GroupBox();
|
||||
m_gbx.dock = DockStyle.TOP;
|
||||
m_gbx.height = 40;
|
||||
m_gbx.text = "Choose your input";
|
||||
this.controls.add(m_gbx);
|
||||
|
||||
m_rb1 = new RadioButton();
|
||||
m_rb1.text = "Mouse";
|
||||
m_rb1.location = Point(10, 15);
|
||||
m_rb1.checked = true;
|
||||
m_rb1.click ~= &radioButtonClick;
|
||||
m_gbx.controls.add(m_rb1);
|
||||
|
||||
m_rb2 = new RadioButton();
|
||||
m_rb2.text = "Keyboard";
|
||||
m_rb2.location = Point(m_rb1.width + 10, 15);
|
||||
m_rb2.click ~= &radioButtonClick;
|
||||
m_gbx.controls.add(m_rb2);
|
||||
|
||||
m_gl = new GLControl();
|
||||
m_gl.dock = DockStyle.FILL;
|
||||
m_gl.controlMethod = ControlMethod.MOUSE;
|
||||
this.controls.add(m_gl);
|
||||
|
||||
this.text = "DFL Opengl Integration Sample";
|
||||
}
|
||||
|
||||
private void radioButtonClick(Control c, EventArgs ea)
|
||||
{
|
||||
m_gl.controlMethod(c.text == "Mouse" ? ControlMethod.MOUSE : ControlMethod.KEYBOARD);
|
||||
m_gl.focus();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Our OpenGL control
|
||||
class GLControl : Control
|
||||
{
|
||||
Window m_win;
|
||||
Input i;
|
||||
Timer m_timer;
|
||||
GLfloat rotx = 0.f, roty = 0.f;
|
||||
ControlMethod m_method = ControlMethod.MOUSE;
|
||||
|
||||
this ()
|
||||
{
|
||||
super();
|
||||
this.setStyle(ControlStyles.SELECTABLE | ControlStyles.ALL_PAINTING_IN_WM_PAINT | ControlStyles.WANT_ALL_KEYS, true);
|
||||
|
||||
//We set a timer to ensure periodic refresh of the window
|
||||
m_timer = new Timer();
|
||||
m_timer.interval(10);
|
||||
m_timer.tick ~= &this.onTick;
|
||||
|
||||
}
|
||||
|
||||
public void controlMethod(ControlMethod m)
|
||||
{
|
||||
m_method = m;
|
||||
}
|
||||
|
||||
//Override of the onHandleCreated method of Control
|
||||
//integration of DSFML window in a control need a valid handle
|
||||
protected void onHandleCreated(EventArgs ea)
|
||||
{
|
||||
super.onHandleCreated(ea);
|
||||
|
||||
//Construction of the window
|
||||
m_win = new Window(cast(WindowHandle)this.handle);
|
||||
|
||||
//Get the input for further use
|
||||
i = m_win.getInput();
|
||||
|
||||
//Now that the Window is instanciated, we can start the timer.
|
||||
m_timer.start();
|
||||
|
||||
//Some opengl initializations functions
|
||||
glClearDepth(1.f);
|
||||
glClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(90.f, 1.f, 1.f, 500.f);
|
||||
}
|
||||
|
||||
//We handle Mouse leaving and entering the control to hide or show the cursor
|
||||
protected void onMouseEnter(MouseEventArgs mea)
|
||||
{
|
||||
super.onMouseEnter(mea);
|
||||
Cursor.current.hide();
|
||||
}
|
||||
|
||||
protected void onMouseLeave(MouseEventArgs mea)
|
||||
{
|
||||
super.onMouseLeave(mea);
|
||||
Cursor.current.show();
|
||||
}
|
||||
|
||||
//If the window is resize, we need to modify openGL view
|
||||
protected void onResize(EventArgs ea)
|
||||
{
|
||||
super.onResize(ea);
|
||||
glViewport(0, 0, this.width, this.height);
|
||||
}
|
||||
|
||||
protected void onTick(Timer t, EventArgs ea)
|
||||
{
|
||||
draw();
|
||||
}
|
||||
|
||||
protected void onPaint(PaintEventArgs pea)
|
||||
{
|
||||
super.onPaint(pea);
|
||||
draw();
|
||||
}
|
||||
|
||||
private void handleKeys()
|
||||
{
|
||||
if (i.isKeyDown(KeyCode.UP))
|
||||
rotx += 1.f;
|
||||
if (i.isKeyDown(KeyCode.DOWN))
|
||||
rotx += -1.f;
|
||||
if (i.isKeyDown(KeyCode.LEFT))
|
||||
roty += -1.f;
|
||||
if (i.isKeyDown(KeyCode.RIGHT))
|
||||
roty += 1.f;
|
||||
|
||||
}
|
||||
private void handleMousePos()
|
||||
{
|
||||
rotx = i.getMouseY() - (this.height / 2.0);
|
||||
roty = i.getMouseX() - (this.width / 2.0);
|
||||
}
|
||||
|
||||
private void draw()
|
||||
{
|
||||
if (m_method == ControlMethod.KEYBOARD)
|
||||
handleKeys();
|
||||
else
|
||||
handleMousePos();
|
||||
|
||||
m_win.setActive(true);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.f, 0.f, -200.f);
|
||||
glRotatef(rotx, 1.f, 0.f, 0.f);
|
||||
glRotatef(roty, 0.f, 1.f, 0.f);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(1.f, 0.f, 0.f);
|
||||
glVertex3f(-50.f, -50.f, -50.f);
|
||||
glVertex3f(-50.f, 50.f, -50.f);
|
||||
glVertex3f( 50.f, 50.f, -50.f);
|
||||
glVertex3f( 50.f, -50.f, -50.f);
|
||||
|
||||
glColor3f(0.f, 1.f, 0.f);
|
||||
glVertex3f(-50.f, -50.f, 50.f);
|
||||
glVertex3f(-50.f, 50.f, 50.f);
|
||||
glVertex3f( 50.f, 50.f, 50.f);
|
||||
glVertex3f( 50.f, -50.f, 50.f);
|
||||
|
||||
glColor3f(0.f, 0.f, 1.f);
|
||||
glVertex3f(-50.f, -50.f, -50.f);
|
||||
glVertex3f(-50.f, 50.f, -50.f);
|
||||
glVertex3f(-50.f, 50.f, 50.f);
|
||||
glVertex3f(-50.f, -50.f, 50.f);
|
||||
|
||||
glColor3f(1.f, 1.f, 0.f);
|
||||
glVertex3f(50.f, -50.f, -50.f);
|
||||
glVertex3f(50.f, 50.f, -50.f);
|
||||
glVertex3f(50.f, 50.f, 50.f);
|
||||
glVertex3f(50.f, -50.f, 50.f);
|
||||
|
||||
glColor3f(1.f, 0.f, 1.f);
|
||||
glVertex3f(-50.f, -50.f, 50.f);
|
||||
glVertex3f(-50.f, -50.f, -50.f);
|
||||
glVertex3f( 50.f, -50.f, -50.f);
|
||||
glVertex3f( 50.f, -50.f, 50.f);
|
||||
|
||||
glColor3f(0.f, 1.f, 1.f);
|
||||
glVertex3f(-50.f, 50.f, 50.f);
|
||||
glVertex3f(-50.f, 50.f, -50.f);
|
||||
glVertex3f( 50.f, 50.f, -50.f);
|
||||
glVertex3f( 50.f, 50.f, 50.f);
|
||||
glEnd();
|
||||
|
||||
m_win.display();
|
||||
}
|
||||
}
|
33
bindings/d/samples/dsfml/dsss.conf
Normal file
|
@ -0,0 +1,33 @@
|
|||
[*]
|
||||
buildflags += -I../../import -Ivoip
|
||||
|
||||
[pong/pong.d]
|
||||
target = bin/pong
|
||||
|
||||
[postFX/postFX.d]
|
||||
target = bin/postFX
|
||||
|
||||
[socket/socketclient.d]
|
||||
target = bin/client
|
||||
|
||||
[socket/socketserver.d]
|
||||
target = bin/server
|
||||
|
||||
[sound3d/sound3d.d]
|
||||
target = bin/sound3d
|
||||
|
||||
[soundstream/soundstream.d]
|
||||
target = bin/soundstream
|
||||
|
||||
[view/view.d]
|
||||
target = bin/view
|
||||
|
||||
[voip/entry.d]
|
||||
target = bin/voip
|
||||
|
||||
version (Windows){
|
||||
version (DFL){
|
||||
[dfl/dflsample.d]
|
||||
target = bin/dflSample
|
||||
}
|
||||
}
|
155
bindings/d/samples/dsfml/opengl/opengl.d
Normal file
|
@ -0,0 +1,155 @@
|
|||
module opengl;
|
||||
|
||||
import dsfml.system.all;
|
||||
import dsfml.audio.all;
|
||||
import dsfml.window.all;
|
||||
import dsfml.graphics.all;
|
||||
|
||||
import std.perf;
|
||||
|
||||
import derelict.opengl.gl;
|
||||
import derelict.opengl.glu;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Create the main window
|
||||
auto window = new RenderWindow(VideoMode(800, 600), "DSFML OpenGL", Style.Default, ContextSettings(24,8,0,3,1));
|
||||
|
||||
DerelictGL.load();
|
||||
DerelictGLU.load();
|
||||
|
||||
// Create a sprite for the background
|
||||
auto backgroundImage = new Image("Data/opengl/background.jpg");
|
||||
auto background = new Sprite(backgroundImage);
|
||||
|
||||
// Load an OpenGL texture.
|
||||
// We could directly use an Image as an OpenGL texture (with its Bind() member function),
|
||||
// but here we want more control on it (generate mipmaps, ...) so we create a new one from the image pixels
|
||||
GLuint texture = 0;
|
||||
{
|
||||
auto image = new Image("Data/opengl/texture.jpg");
|
||||
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, image.width, image.height, GL_RGBA, GL_UNSIGNED_BYTE, image.getPixelsArray().ptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
}
|
||||
|
||||
// Enable Z-buffer read and write
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE);
|
||||
glClearDepth(1.f);
|
||||
|
||||
// Setup a perspective projection
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
gluPerspective(90.f, 1.f, 1.f, 500.f);
|
||||
|
||||
// Bind our texture
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glColor4f(1.f, 1.f, 1.f, 1.f);
|
||||
|
||||
// Create a clock for measuring the time elapsed
|
||||
auto clock = new PerformanceCounter();
|
||||
clock.start();
|
||||
|
||||
// Start game loop
|
||||
while (window.isOpened())
|
||||
{
|
||||
// Process events
|
||||
Event event;
|
||||
while (window.getEvent(event))
|
||||
{
|
||||
// Close window : exit
|
||||
if (event.Type == EventType.Closed)
|
||||
window.close();
|
||||
|
||||
// Escape key : exit
|
||||
if ((event.Type == EventType.KeyPressed) && (event.Key.Code == KeyCode.Escape))
|
||||
window.close();
|
||||
|
||||
// Adjust the viewport when the window is resized
|
||||
if (event.Type == EventType.Resized)
|
||||
glViewport(0, 0, event.Size.Width, event.Size.Height);
|
||||
}
|
||||
|
||||
// Draw the background
|
||||
window.saveGLStates();
|
||||
window.draw(background);
|
||||
window.restoreGLStates();
|
||||
|
||||
// Activate the window before using OpenGL commands.
|
||||
// This is useless here because we have only one window which is
|
||||
// always the active one, but don't forget it if you use multiple windows
|
||||
window.active = true;
|
||||
|
||||
// Clear the depth buffer
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// We get the position of the mouse cursor, so that we can move the box accordingly
|
||||
float x = window.input.mouseX * 200.f / window.width - 100.f;
|
||||
float y = -window.input.mouseY * 200.f / window.height + 100.f;
|
||||
|
||||
// Apply some transformations
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(x, y, -100.f);
|
||||
|
||||
clock.stop();
|
||||
glRotatef(clock.microseconds() * 0.000001 * 50, 1.f, 0.f, 0.f);
|
||||
glRotatef(clock.microseconds() * 0.000001 * 30, 0.f, 1.f, 0.f);
|
||||
glRotatef(clock.microseconds() * 0.000001 * 90, 0.f, 0.f, 1.f);
|
||||
|
||||
// Draw a cube
|
||||
float size = 20.f;
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
glTexCoord2f(0, 0); glVertex3f(-size, -size, -size);
|
||||
glTexCoord2f(0, 1); glVertex3f(-size, size, -size);
|
||||
glTexCoord2f(1, 1); glVertex3f( size, size, -size);
|
||||
glTexCoord2f(1, 0); glVertex3f( size, -size, -size);
|
||||
|
||||
glTexCoord2f(0, 0); glVertex3f(-size, -size, size);
|
||||
glTexCoord2f(0, 1); glVertex3f(-size, size, size);
|
||||
glTexCoord2f(1, 1); glVertex3f( size, size, size);
|
||||
glTexCoord2f(1, 0); glVertex3f( size, -size, size);
|
||||
|
||||
glTexCoord2f(0, 0); glVertex3f(-size, -size, -size);
|
||||
glTexCoord2f(0, 1); glVertex3f(-size, size, -size);
|
||||
glTexCoord2f(1, 1); glVertex3f(-size, size, size);
|
||||
glTexCoord2f(1, 0); glVertex3f(-size, -size, size);
|
||||
|
||||
glTexCoord2f(0, 0); glVertex3f(size, -size, -size);
|
||||
glTexCoord2f(0, 1); glVertex3f(size, size, -size);
|
||||
glTexCoord2f(1, 1); glVertex3f(size, size, size);
|
||||
glTexCoord2f(1, 0); glVertex3f(size, -size, size);
|
||||
|
||||
glTexCoord2f(0, 1); glVertex3f(-size, -size, size);
|
||||
glTexCoord2f(0, 0); glVertex3f(-size, -size, -size);
|
||||
glTexCoord2f(1, 0); glVertex3f( size, -size, -size);
|
||||
glTexCoord2f(1, 1); glVertex3f( size, -size, size);
|
||||
|
||||
glTexCoord2f(0, 1); glVertex3f(-size, size, size);
|
||||
glTexCoord2f(0, 0); glVertex3f(-size, size, -size);
|
||||
glTexCoord2f(1, 0); glVertex3f( size, size, -size);
|
||||
glTexCoord2f(1, 1); glVertex3f( size, size, size);
|
||||
|
||||
glEnd();
|
||||
|
||||
// Draw some text on top of our OpenGL object
|
||||
window.saveGLStates();
|
||||
Text text = new Text("DSFML / OpenGL demo"c);
|
||||
text.position = Vector2f(250.f, 450.f);
|
||||
text.color = Color(255, 255, 255, 170);
|
||||
window.draw(text);
|
||||
window.restoreGLStates();
|
||||
|
||||
// Finally, display the rendered frame on screen
|
||||
window.display();
|
||||
}
|
||||
|
||||
// Don't forget to destroy our texture
|
||||
glDeleteTextures(1, &texture);
|
||||
}
|
202
bindings/d/samples/dsfml/pong/pong.d
Normal file
|
@ -0,0 +1,202 @@
|
|||
module pong;
|
||||
|
||||
import dsfml.system.all;
|
||||
import dsfml.audio.all;
|
||||
import dsfml.window.all;
|
||||
import dsfml.graphics.all;
|
||||
|
||||
version (Tango)
|
||||
{
|
||||
import tango.io.Stdout;
|
||||
import tango.math.Math;
|
||||
}
|
||||
else
|
||||
{
|
||||
import std.math;
|
||||
import std.perf;
|
||||
import std.random;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// Defines PI
|
||||
const float PI = 3.14159f;
|
||||
|
||||
// Create the window of the application
|
||||
RenderWindow app = new RenderWindow(VideoMode(800, 600, 32), "SFML Pong");
|
||||
|
||||
app.useVerticalSync(false);
|
||||
|
||||
Input i = app.input;
|
||||
|
||||
// Load the sounds used in the game
|
||||
Sound BallSound = new Sound(new SoundBuffer("Data/ball.wav"));
|
||||
|
||||
// Load the images used in the game
|
||||
Image PaddleImage = new Image("Data/paddle.tga");
|
||||
Image BallImage = new Image("Data/ball.tga");
|
||||
|
||||
|
||||
// Initialize the end text
|
||||
Text End = new Text(""c);
|
||||
Font font = new Font("Data/cheeseburger.ttf");
|
||||
End.font = font;
|
||||
End.characterSize = 60;
|
||||
End.move(150.f, 200.f);
|
||||
End.color = Color(50, 50, 250);
|
||||
|
||||
Text fps = new Text(""c, font, 30);
|
||||
fps.move(50.f, 50.f);
|
||||
fps.color = Color.BLACK;
|
||||
|
||||
// Create the sprites of the background, the paddles and the ball
|
||||
Sprite LeftPaddle = new Sprite(PaddleImage);
|
||||
Sprite RightPaddle = new Sprite(PaddleImage);
|
||||
Sprite Ball = new Sprite(BallImage);
|
||||
|
||||
LeftPaddle.move(10, (app.view.getHeight() - LeftPaddle.size.y) / 2);
|
||||
RightPaddle.move(app.view.getWidth() - RightPaddle.size.x - 10, (app.view.getHeight() - RightPaddle.size.y) / 2);
|
||||
Ball.move((app.view.getWidth() - Ball.size.x) / 2, (app.view.getHeight() - Ball.size.y) / 2);
|
||||
|
||||
// Define the paddles properties
|
||||
auto AITimer = new PerformanceCounter();
|
||||
const long AITime = 100; // 100 ms
|
||||
float LeftPaddleSpeed = 400.f;
|
||||
float RightPaddleSpeed = 400.f;
|
||||
|
||||
// Define the ball properties
|
||||
float BallSpeed = 400.f;
|
||||
float BallAngle = 0.f;
|
||||
do
|
||||
{
|
||||
// Make sure the ball initial angle is not too much vertical
|
||||
BallAngle = uniform(0.f, 2 * PI);
|
||||
} while (abs(cos(BallAngle)) < 0.7f);
|
||||
|
||||
bool IsPlaying = true;
|
||||
|
||||
Event evt;
|
||||
uint iFps = 0;
|
||||
auto fpsClock = new PerformanceCounter();
|
||||
|
||||
while (app.isOpened())
|
||||
{
|
||||
app.clear(Color(255, 255, 255, 255));
|
||||
|
||||
// Handle events
|
||||
while (app.getEvent(evt))
|
||||
{
|
||||
// Window closed or escape key pressed : exit
|
||||
if ((evt.Type == EventType.Closed) ||
|
||||
((evt.Type == EventType.KeyPressed) && (evt.Key.Code == KeyCode.Escape)))
|
||||
{
|
||||
app.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsPlaying)
|
||||
{
|
||||
// Move the player's paddle
|
||||
if (i.isKeyDown(KeyCode.Up) && (LeftPaddle.position.y > 5.f))
|
||||
LeftPaddle.move(0.f, -LeftPaddleSpeed * app.frameTime);
|
||||
if (i.isKeyDown(KeyCode.Down) && (LeftPaddle.position.y < app.view.getHeight() - LeftPaddle.size.y - 5.f))
|
||||
LeftPaddle.move(0.f, LeftPaddleSpeed * app.frameTime);
|
||||
|
||||
// Move the computer's paddle
|
||||
if (((RightPaddleSpeed < 0.f) && (RightPaddle.position.y > 5.f)) ||
|
||||
((RightPaddleSpeed > 0.f) && (RightPaddle.position.y < app.view.getHeight() - RightPaddle.size.y - 5.f)))
|
||||
{
|
||||
RightPaddle.move(0.f, RightPaddleSpeed * app.frameTime);
|
||||
}
|
||||
|
||||
// Update the computer's paddle direction according to the ball position
|
||||
AITimer.stop();
|
||||
if (AITimer.milliseconds > AITime)
|
||||
{
|
||||
AITimer.start();
|
||||
if ((RightPaddleSpeed < 0) && (Ball.position.y + Ball.size.y > RightPaddle.position.y + RightPaddle.size.y))
|
||||
RightPaddleSpeed = -RightPaddleSpeed;
|
||||
if ((RightPaddleSpeed > 0) && (Ball.position.y < RightPaddle.position.y))
|
||||
RightPaddleSpeed = -RightPaddleSpeed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Move the ball
|
||||
float Factor = BallSpeed * app.frameTime;
|
||||
Ball.move(cos(BallAngle) * Factor, sin(BallAngle) * Factor);
|
||||
|
||||
// Check collisions between the ball and the screen
|
||||
if (Ball.position.x < 0.f)
|
||||
{
|
||||
IsPlaying = false;
|
||||
End.text("You lost !\n(press escape to exit)"c);
|
||||
}
|
||||
|
||||
if (Ball.position.x + Ball.size.x > app.view.getWidth())
|
||||
{
|
||||
IsPlaying = false;
|
||||
End.text("You won !\n(press escape to exit)"c);
|
||||
}
|
||||
|
||||
if (Ball.position.y < 0.f)
|
||||
{
|
||||
BallSound.play();
|
||||
BallAngle = -BallAngle;
|
||||
Ball.y = 0.1f;
|
||||
}
|
||||
|
||||
if (Ball.position.y + Ball.size.y > app.view.getHeight())
|
||||
{
|
||||
BallSound.play();
|
||||
BallAngle = -BallAngle;
|
||||
Ball.y = app.view.getHeight() - Ball.size.y - 0.1f;
|
||||
}
|
||||
// Check the collisions between the ball and the paddles
|
||||
// Left Paddle
|
||||
if (Ball.position.x < LeftPaddle.position.x + LeftPaddle.size.x &&
|
||||
Ball.position.x > LeftPaddle.position.x + (LeftPaddle.size.x / 2.0f) &&
|
||||
Ball.position.y + Ball.size.y >= LeftPaddle.position.y &&
|
||||
Ball.position.y <= LeftPaddle.position.y + LeftPaddle.size.y)
|
||||
{
|
||||
BallSound.play();
|
||||
BallAngle = PI - BallAngle;
|
||||
Ball.x = LeftPaddle.position.x + LeftPaddle.size.x + 0.1f;
|
||||
}
|
||||
|
||||
// Right Paddle
|
||||
if (Ball.position.x + Ball.size.x > RightPaddle.position.x &&
|
||||
Ball.position.x + Ball.size.x < RightPaddle.position.x + (RightPaddle.size.x / 2.0f) &&
|
||||
Ball.position.y + Ball.size.y >= RightPaddle.position.y &&
|
||||
Ball.position.y <= RightPaddle.position.y + RightPaddle.size.y)
|
||||
{
|
||||
BallSound.play();
|
||||
BallAngle = PI - BallAngle;
|
||||
Ball.x = RightPaddle.position.x - Ball.size.x - 0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the background, paddles and ball sprites
|
||||
|
||||
app.draw(LeftPaddle);
|
||||
app.draw(RightPaddle);
|
||||
app.draw(Ball);
|
||||
|
||||
fpsClock.stop();
|
||||
if(fpsClock.seconds >= 1)
|
||||
{
|
||||
fps.text = std.string.format("%d fps", iFps);
|
||||
iFps = 0;
|
||||
fpsClock.start();
|
||||
}
|
||||
++iFps;
|
||||
app.draw(fps);
|
||||
// If the game is over, display the end message
|
||||
if (!IsPlaying)
|
||||
app.draw(End);
|
||||
|
||||
// Display things on screen
|
||||
app.display();
|
||||
}
|
||||
}
|
117
bindings/d/samples/dsfml/postFX/postFX.d
Normal file
|
@ -0,0 +1,117 @@
|
|||
module postfx;
|
||||
|
||||
import dsfml.graphics.all;
|
||||
import dsfml.system.all;
|
||||
import dsfml.window.all;
|
||||
|
||||
const char[][5] EFFECTS = ["nothing", "blur", "colorize", "fisheye", "wave"];
|
||||
|
||||
void main()
|
||||
{
|
||||
int actualIndex;
|
||||
|
||||
// Check that the system can use post effects
|
||||
if (PostFX.canUsePostFX() == false)
|
||||
assert(0, "Your system doesn't support Post Effects.");
|
||||
|
||||
// Create the main window
|
||||
RenderWindow app = new RenderWindow(VideoMode(800, 600), "SFML PostFX");
|
||||
app.setFramerateLimit(100);
|
||||
|
||||
// Load a cute background image to display :)
|
||||
Sprite background = new Sprite(new Image("Data/background.jpg"));
|
||||
|
||||
// Load the image needed for the wave effect
|
||||
Image WaveImage = new Image("Data/wave.jpg");
|
||||
|
||||
// Load all effects
|
||||
PostFX[char[]] Effects;
|
||||
foreach(char[] c; EFFECTS)
|
||||
{
|
||||
Effects[c] = new PostFX("Data/" ~ c ~ ".sfx");
|
||||
}
|
||||
PostFX currentEffect = Effects[EFFECTS[actualIndex]];
|
||||
|
||||
// Do specific initializations
|
||||
Effects["nothing"].setTexture("framebuffer", null);
|
||||
Effects["blur"].setTexture("framebuffer", null);
|
||||
Effects["blur"].setParameter("offset", 0.f);
|
||||
Effects["colorize"].setTexture("framebuffer", null);
|
||||
Effects["colorize"].setParameter("color", 1.f, 1.f, 1.f);
|
||||
Effects["fisheye"].setTexture("framebuffer", null);
|
||||
Effects["wave"].setTexture("framebuffer", null);
|
||||
Effects["wave"].setTexture("wave", WaveImage);
|
||||
|
||||
Font f = new Font("Data/cheeseburger.ttf");
|
||||
|
||||
// Define a string for displaying current effect description
|
||||
Text curFXStr = new Text("Current effect is " ~ EFFECTS[actualIndex]);
|
||||
curFXStr.setFont(f);
|
||||
curFXStr.setPosition(20.f, 0.f);
|
||||
|
||||
// Define a string for displaying help
|
||||
Text infoStr = new Text("Move your mouse to change the effect parameters\nPress numpad + and - to change effect\nWarning : some effects may not work\ndepending on your graphics card"c);
|
||||
infoStr.setFont(f);
|
||||
infoStr.setPosition(20.f, 460.f);
|
||||
infoStr.setColor(Color(200, 100, 150));
|
||||
|
||||
// Start the game loop
|
||||
while (app.isOpened())
|
||||
{
|
||||
// Process events
|
||||
Event evt;
|
||||
while (app.getEvent(evt))
|
||||
{
|
||||
// Close window : exit
|
||||
if (evt.Type == Event.EventType.CLOSED ||
|
||||
evt.Type == Event.EventType.KEYPRESSED && evt.Key.Code == KeyCode.ESCAPE)
|
||||
app.close();
|
||||
|
||||
if (evt.Type == Event.EventType.KEYPRESSED)
|
||||
{
|
||||
// Add key : next effect
|
||||
if (evt.Key.Code == KeyCode.ADD)
|
||||
{
|
||||
if (actualIndex == 4)
|
||||
actualIndex = 0;
|
||||
else
|
||||
actualIndex++;
|
||||
currentEffect = Effects[EFFECTS[actualIndex]];
|
||||
curFXStr.setText("Current effect is " ~ EFFECTS[actualIndex]);
|
||||
}
|
||||
|
||||
// Subtract key : previous effect
|
||||
if (evt.Key.Code == KeyCode.SUBTRACT)
|
||||
{
|
||||
if (actualIndex == 0)
|
||||
actualIndex = 4;
|
||||
else
|
||||
actualIndex--;
|
||||
currentEffect = Effects[EFFECTS[actualIndex]];
|
||||
curFXStr.setText("Current effect is " ~ EFFECTS[actualIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the mouse position in the range [0, 1]
|
||||
float X = app.getInput().getMouseX() / cast(float) app.getWidth();
|
||||
float Y = app.getInput().getMouseY() / cast(float) app.getHeight();
|
||||
|
||||
// Update the current effect
|
||||
if (EFFECTS[actualIndex] == "blur") currentEffect.setParameter("offset", X * Y * 0.1f);
|
||||
else if (EFFECTS[actualIndex] == "colorize") currentEffect.setParameter("color", 0.3f, X, Y);
|
||||
else if (EFFECTS[actualIndex] == "fisheye") currentEffect.setParameter("mouse", X, 1.f - Y);
|
||||
else if (EFFECTS[actualIndex] == "wave") currentEffect.setParameter("offset", X, Y);
|
||||
|
||||
// Draw background and apply the post-fx
|
||||
app.draw(background);
|
||||
app.draw(currentEffect);
|
||||
|
||||
// Draw interface strings
|
||||
app.draw(curFXStr);
|
||||
app.draw(infoStr);
|
||||
|
||||
// Finally, display the rendered frame on screen
|
||||
app.display();
|
||||
}
|
||||
}
|
66
bindings/d/samples/dsfml/socket/socketclient.d
Normal file
|
@ -0,0 +1,66 @@
|
|||
module socketclient;
|
||||
|
||||
import dsfml.system.all;
|
||||
import dsfml.network.all;
|
||||
|
||||
version (Tango)
|
||||
{
|
||||
import tango.io.Console;
|
||||
import tango.io.Stdout;
|
||||
}
|
||||
else
|
||||
{
|
||||
import std.stdio;
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
//The TCP socket
|
||||
SocketTCP client = new SocketTCP();
|
||||
//Try to connect to server (on localhost for this sample)
|
||||
client.connect(9000, IPAddress.LOCALHOST);
|
||||
|
||||
display("Connected to server."w);
|
||||
|
||||
//Prepare a packet with a string
|
||||
Packet p = new Packet();
|
||||
p.set("Hello from the client !"w);
|
||||
if (client.send(p) != SocketStatus.DONE) // Assert on error
|
||||
assert(0);
|
||||
|
||||
//Clear the packet
|
||||
p.clear();
|
||||
|
||||
//Wait for the response of the server and display it
|
||||
if (client.receive(p) != SocketStatus.DONE)
|
||||
assert(0);
|
||||
wchar[] c;
|
||||
p.get(c);
|
||||
display("Packet received : "w ~ c);
|
||||
read();
|
||||
}
|
||||
|
||||
void display(wchar[] c)
|
||||
{
|
||||
version (Tango)
|
||||
{
|
||||
Stdout(c).newline;
|
||||
}
|
||||
else
|
||||
{
|
||||
writefln("%s", c);
|
||||
}
|
||||
}
|
||||
|
||||
void read()
|
||||
{
|
||||
version (Tango)
|
||||
{
|
||||
Cin.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
readln();
|
||||
}
|
||||
}
|
83
bindings/d/samples/dsfml/socket/socketserver.d
Normal file
|
@ -0,0 +1,83 @@
|
|||
module socketserver;
|
||||
|
||||
import dsfml.system.all;
|
||||
import dsfml.network.all;
|
||||
|
||||
version (Tango)
|
||||
{
|
||||
import tango.io.Console;
|
||||
import tango.io.Stdout;
|
||||
}
|
||||
else
|
||||
{
|
||||
import std.stdio;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
//We create a TCP socket for listening incomming client
|
||||
SocketTCP listener = new SocketTCP();
|
||||
|
||||
//Set a random port for the listener
|
||||
if (!listener.listen(9000))
|
||||
assert(0);
|
||||
|
||||
//Creation of TCP socket
|
||||
SocketTCP client = new SocketTCP();
|
||||
IPAddress ipClient;
|
||||
|
||||
display("Waiting for client."w);
|
||||
|
||||
if (listener.accept(client, ipClient) == SocketStatus.DONE) //This call blocks until client connection
|
||||
{
|
||||
display("New client connected."w);
|
||||
//The packet for retrieving the client message
|
||||
Packet p = new Packet();
|
||||
display("Waiting for data"w);
|
||||
if (client.receive(p) != SocketStatus.DONE) //Assert on reception error
|
||||
assert(0);
|
||||
|
||||
|
||||
//Display the string send by the client
|
||||
wchar[] c;
|
||||
p.get(c);
|
||||
display("Packet received : "w ~ c);
|
||||
|
||||
//Clear the packet (We could use a new one)
|
||||
p.clear();
|
||||
|
||||
//and send response to client
|
||||
client.send(p.set("Hello from the server !"w));
|
||||
}
|
||||
read();
|
||||
}
|
||||
|
||||
/**
|
||||
* Multilib string display
|
||||
*/
|
||||
void display(wchar[] c)
|
||||
{
|
||||
version (Tango)
|
||||
{
|
||||
Stdout(c).newline;
|
||||
}
|
||||
else
|
||||
{
|
||||
writefln("%s", c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy function to prevent console closing on windows
|
||||
*/
|
||||
void read()
|
||||
{
|
||||
version (Tango)
|
||||
{
|
||||
Cin.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
readln();
|
||||
}
|
||||
}
|
185
bindings/d/samples/dsfml/sound3d/sound3d.d
Normal file
|
@ -0,0 +1,185 @@
|
|||
module sound3d;
|
||||
|
||||
import dsfml.system.all;
|
||||
import dsfml.window.all;
|
||||
import dsfml.graphics.all;
|
||||
import dsfml.audio.all;
|
||||
|
||||
void main()
|
||||
{
|
||||
//We create our window with a limit of 100 and a white backcolor.
|
||||
RenderWindow app = new RenderWindow (VideoMode(800, 600, 32), "Sound Spatialization Sample");
|
||||
app.useVerticalSync(true);
|
||||
|
||||
Font f = new Font("Data/cheeseburger.ttf");
|
||||
|
||||
//Some instructions
|
||||
Text s = new Text("Click anywhere on screen to change listener position.\nPress + or - to modify the speed of the car."c, f);
|
||||
|
||||
s.characterSize = 34;
|
||||
s.setPosition(20, 30);
|
||||
s.color = Color.BLACK;
|
||||
|
||||
//We prepare our images and the sound
|
||||
string[2] images = ["Data/bluerallyecarleft.bmp", "Data/bluerallyecarright.bmp"];
|
||||
Car c = new Car(images, "Data/car_idle.wav");
|
||||
|
||||
int carSpeed = 100;
|
||||
|
||||
//Set default position for the car and the listener
|
||||
c.position = Vector2f(0, 300);
|
||||
SoundListener.position = Vector2f(400, 300);
|
||||
|
||||
c.startPlaying();
|
||||
|
||||
//Start the main loop
|
||||
while (app.isOpened())
|
||||
{
|
||||
app.clear(Color.WHITE);
|
||||
Event evt;
|
||||
//The event loop
|
||||
while (app.getEvent(evt))
|
||||
{
|
||||
// if the window is closed, we can leave the game loop
|
||||
if (evt.Type == EventType.Closed)
|
||||
app.close();
|
||||
// we handle the click event to change listener position
|
||||
else if (evt.Type == EventType.MouseButtonPressed && evt.MouseButton.Button == MouseButtons.Left)
|
||||
{
|
||||
Input i = app.input;
|
||||
SoundListener.position = Vector2f(i.mouseX, i.mouseY);
|
||||
}
|
||||
// and eventual keys press
|
||||
else if (evt.Type == EventType.KeyPressed)
|
||||
{
|
||||
//Change the car speed
|
||||
if (evt.Key.Code == KeyCode.Add)
|
||||
{
|
||||
carSpeed += 25;
|
||||
}
|
||||
else if (evt.Key.Code == KeyCode.Substract)
|
||||
{
|
||||
carSpeed -= 25;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//We move constantly our car.
|
||||
c.move(Vector2f(app.frameTime * carSpeed, 0));
|
||||
|
||||
//Draw all the sprite and string on render window
|
||||
app.draw(s);
|
||||
app.draw(c.sprite);
|
||||
app.draw(SoundListener.sprite);
|
||||
|
||||
//And finally display the window
|
||||
app.display();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Encapsulate the listener position and the visor sprite.
|
||||
// There is only one listener so all the methods are statics.
|
||||
class SoundListener
|
||||
{
|
||||
static Sprite s_crosshair;
|
||||
static Vector2f s_p;
|
||||
|
||||
static this()
|
||||
{
|
||||
Image crosshairImg = new Image("Data/crosshair.tga");
|
||||
crosshairImg.createMaskFromColor(Color.WHITE);
|
||||
|
||||
s_crosshair = new Sprite(crosshairImg);
|
||||
s_crosshair.setOrigin(s_crosshair.size.x / 2, s_crosshair.size.y / 2);
|
||||
|
||||
//Listener.setTarget(1.f, 0.f, 0.f);
|
||||
}
|
||||
|
||||
// Adjust position of the listener
|
||||
@property static void position(Vector2f p)
|
||||
{
|
||||
Listener.setPosition(p.x, p.y, 5.f);
|
||||
s_crosshair.setPosition(p.x, p.y);
|
||||
}
|
||||
|
||||
@property static Sprite sprite()
|
||||
{
|
||||
return s_crosshair;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Class encapsulating all data for our car
|
||||
class Car
|
||||
{
|
||||
Vector2f m_actual;
|
||||
Sprite m_sprite;
|
||||
Sound m_sound;
|
||||
bool reverse;
|
||||
Image[2] imgs;
|
||||
|
||||
//Constructor with with a fixed size string array of image path, and a string for the sound path
|
||||
this (string[2] images, string soundFilename)
|
||||
{
|
||||
//load images and create filter
|
||||
imgs[0] = new Image(images[0]); imgs[1] = new Image(images[1]);
|
||||
|
||||
foreach(img; imgs)
|
||||
img.createMaskFromColor(Color(97, 68, 43));
|
||||
|
||||
m_sprite = new Sprite(imgs[0]);
|
||||
m_sprite.setOrigin(m_sprite.size.x / 2, m_sprite.size.y / 2);
|
||||
|
||||
SoundBuffer buff = new SoundBuffer(soundFilename);
|
||||
|
||||
//load our sound with loop enabled
|
||||
m_sound = new Sound(buff, true);
|
||||
m_sound.attenuation = .05f;
|
||||
}
|
||||
|
||||
// Begin the sound play
|
||||
void startPlaying()
|
||||
{
|
||||
m_sound.play();
|
||||
}
|
||||
|
||||
// Set the position of the car on the window
|
||||
// Used to setup the begin car window and sound location
|
||||
@property void position(Vector2f p)
|
||||
{
|
||||
m_sprite.setPosition(p.x, p.y);
|
||||
m_sound.setPosition(p.x, 0, p.y);
|
||||
}
|
||||
|
||||
//Move the car (visual and sound position)
|
||||
//If the car leave the screen, we change the sprite image and reverse moving
|
||||
void move(Vector2f vec)
|
||||
{
|
||||
// if the car is beyond the right screen limit
|
||||
if (!reverse && m_sprite.position.x > 850)
|
||||
{
|
||||
m_sprite.setImage(imgs[1]);
|
||||
reverse = true;
|
||||
}
|
||||
// same as above but for left limit
|
||||
else if (reverse && vec.x + m_sprite.position.x < -50)
|
||||
{
|
||||
m_sprite.setImage(imgs[0]);
|
||||
reverse = false;
|
||||
}
|
||||
|
||||
if (reverse)
|
||||
vec = -vec;
|
||||
|
||||
m_sprite.move(vec);
|
||||
Vector2f pos = m_sprite.position;
|
||||
m_sound.setPosition(pos.x , pos.y, 0);
|
||||
}
|
||||
|
||||
@property Sprite sprite()
|
||||
{
|
||||
return m_sprite;
|
||||
}
|
||||
}
|
97
bindings/d/samples/dsfml/soundstream/soundstream.d
Normal file
|
@ -0,0 +1,97 @@
|
|||
module soundstream;
|
||||
|
||||
import dsfml.system.all;
|
||||
import dsfml.audio.all;
|
||||
|
||||
version (Tango)
|
||||
{
|
||||
import tango.io.Console;
|
||||
import tango.io.Stdout;
|
||||
}
|
||||
else
|
||||
{
|
||||
import std.stdio;
|
||||
}
|
||||
|
||||
// SoundStream is an abstract class.
|
||||
// You need to implement onStart() and onGetData()
|
||||
// Don't forget to call initialize() before any usage or playback will fail.
|
||||
class MySoundStream : SoundStream
|
||||
{
|
||||
SoundBuffer m_buff;
|
||||
short[] m_data;
|
||||
size_t m_cursor;
|
||||
|
||||
this()
|
||||
{
|
||||
// We initialize the stream with some sound informations
|
||||
super(1, 11025);
|
||||
|
||||
// We create a sound buffer to load samples from files
|
||||
m_buff = new SoundBuffer("Data/car_idle.wav");
|
||||
m_data = m_buff.samples[0..m_buff.samplesCount];
|
||||
}
|
||||
|
||||
protected:
|
||||
/*
|
||||
bool onStart()
|
||||
{
|
||||
// No specifics things to do, just return true.
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
override bool onGetData(out short[] data)
|
||||
{
|
||||
// We ensure that we have enough data to send
|
||||
if (m_cursor + this.sampleRate > m_data.length)
|
||||
return false;
|
||||
|
||||
// Assign data in the buffer ...
|
||||
data = m_data[m_cursor..m_cursor + this.sampleRate];
|
||||
// ... and increment the cursor
|
||||
m_cursor += this.sampleRate;
|
||||
return true;
|
||||
}
|
||||
|
||||
override void onSeek(float timeOffset)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
MySoundStream stream = new MySoundStream();
|
||||
|
||||
display("Playing sound !\n Press enter to stop playback.");
|
||||
stream.play();
|
||||
read(); // prevent console from closing
|
||||
stream.stop();
|
||||
}
|
||||
|
||||
void display(string c)
|
||||
{
|
||||
version (Tango)
|
||||
{
|
||||
Stdout(c).newline;
|
||||
}
|
||||
else
|
||||
{
|
||||
writeln(c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy function to prevent console closing on windows
|
||||
*/
|
||||
void read()
|
||||
{
|
||||
version (Tango)
|
||||
{
|
||||
Cin.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
readln();
|
||||
}
|
||||
}
|
69
bindings/d/samples/dsfml/view/view.d
Normal file
|
@ -0,0 +1,69 @@
|
|||
module view;
|
||||
|
||||
import dsfml.system.all;
|
||||
import dsfml.window.all;
|
||||
import dsfml.graphics.all;
|
||||
|
||||
void main()
|
||||
{
|
||||
RenderWindow window = new RenderWindow(VideoMode(800, 600), "View sample");
|
||||
window.framerateLimit = 100;
|
||||
Input input = window.input;
|
||||
Vector2f top;
|
||||
FloatRect bound;
|
||||
Shape s;
|
||||
bool mousePressed;
|
||||
|
||||
Sprite background = new Sprite(new Image("Data/background.jpg"));
|
||||
|
||||
Font f = new Font("Data/cheeseburger.ttf");
|
||||
Text str = new Text("Create a selection of the background with your mouse.\nPress Enter to zoom to this selection.\nPress Escape to return to the default view."c, f);
|
||||
|
||||
while (window.isOpened())
|
||||
{
|
||||
Event evt;
|
||||
|
||||
while (window.getEvent(evt))
|
||||
{
|
||||
if ( evt.Type == EventType.MouseButtonPressed &&
|
||||
evt.MouseButton.Button == MouseButtons.Left)
|
||||
{
|
||||
top = window.convertCoords(input.mouseX, input.mouseY);
|
||||
mousePressed = true;
|
||||
|
||||
}
|
||||
else if ( evt.Type == EventType.MouseButtonReleased &&
|
||||
evt.MouseButton.Button == MouseButtons.Left)
|
||||
{
|
||||
mousePressed = false;
|
||||
}
|
||||
else if ( evt.Type == EventType.MouseMoved &&
|
||||
mousePressed)
|
||||
{
|
||||
Vector2f bottom = window.convertCoords(input.mouseX, input.mouseY);
|
||||
bound = FloatRect(top.x, top.y, bottom.x-top.x, bottom.y-top.y);
|
||||
s = Shape.rectangle(bound.left, bound.top, bound.width, bound.height, Color(0, 0, 0, 0), 1, Color.BLACK);
|
||||
}
|
||||
else if ( evt.Type == EventType.KeyPressed &&
|
||||
evt.Key.Code == KeyCode.Return)
|
||||
{
|
||||
if (bound != FloatRect())
|
||||
window.view = new View(bound);
|
||||
s = null;
|
||||
}
|
||||
else if ( evt.Type == EventType.KeyPressed &&
|
||||
evt.Key.Code == KeyCode.Escape)
|
||||
{
|
||||
window.view = window.defaultView;
|
||||
}
|
||||
else if ( evt.Type == EventType.Closed)
|
||||
window.close();
|
||||
|
||||
}
|
||||
|
||||
window.draw(background);
|
||||
window.draw(str);
|
||||
if (s !is null) window.draw(s);
|
||||
window.display();
|
||||
}
|
||||
}
|
72
bindings/d/samples/dsfml/voip/client.d
Normal file
|
@ -0,0 +1,72 @@
|
|||
module client;
|
||||
|
||||
import util;
|
||||
|
||||
|
||||
// Specialization of audio recorder for sending recorded audio
|
||||
// data through the network
|
||||
class NetworkRecorder : SoundRecorder
|
||||
{
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
this(SocketTCP Socket)
|
||||
{
|
||||
mySocket = Socket;
|
||||
}
|
||||
|
||||
~this()
|
||||
{
|
||||
delete mySocket;
|
||||
}
|
||||
protected:
|
||||
override bool onStart()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
override void onStop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
override bool onProcessSamples(short[] samples)
|
||||
{
|
||||
// Pack the audio samples into a network packet
|
||||
Packet PacketOut = new Packet();
|
||||
PacketOut.set(AudioData);
|
||||
PacketOut.append((cast(byte*)samples.ptr)[0..samples.length * short.sizeof]);
|
||||
// Send the audio packet to the server
|
||||
return mySocket.send(PacketOut) == SocketStatus.DONE;
|
||||
}
|
||||
|
||||
SocketTCP mySocket; ///< Socket used to communicate with the server
|
||||
}
|
||||
|
||||
void runClient(IPAddress adr, int port)
|
||||
{
|
||||
// Create a TCP socket for communicating with server
|
||||
SocketTCP Socket = new SocketTCP();
|
||||
|
||||
// Connect to the specified server
|
||||
if (!Socket.connect(port, adr))
|
||||
return;
|
||||
|
||||
// Wait for user input...
|
||||
Cout("Press enter to start recording audio").newline;
|
||||
Cin.get();
|
||||
|
||||
// Create a instance of our custom recorder
|
||||
NetworkRecorder Recorder = new NetworkRecorder(Socket);
|
||||
|
||||
// Start capturing audio data
|
||||
Recorder.start(44100);
|
||||
Cout("Press enter to stop recording audio").newline;
|
||||
Cin.get();
|
||||
Recorder.stop();
|
||||
|
||||
// Send a "end-of-stream" packet
|
||||
Packet PacketOut = new Packet();
|
||||
PacketOut.set(EndOfStream);
|
||||
Socket.send(PacketOut);
|
||||
}
|
46
bindings/d/samples/dsfml/voip/entry.d
Normal file
|
@ -0,0 +1,46 @@
|
|||
module entry;
|
||||
|
||||
import util;
|
||||
import server;
|
||||
import client;
|
||||
|
||||
int main(char[][] args)
|
||||
{
|
||||
char[][] argc = args.dup;
|
||||
if (argc.length > 1)
|
||||
{
|
||||
if ( argc[1] == "-c" &&
|
||||
argc.length == 4)
|
||||
{
|
||||
IPAddress adr = IPAddress(argc[2]);
|
||||
|
||||
if (adr.isValid() &&
|
||||
parse(argc[3]) <= 60000 &&
|
||||
parse(argc[3]) >= 1000)
|
||||
{
|
||||
runClient(adr, parse(argc[3]));
|
||||
}
|
||||
else
|
||||
printUsage();
|
||||
}
|
||||
else if ( argc[1] == "-s" &&
|
||||
argc.length == 3 &&
|
||||
parse(argc[2]) <= 60000 &&
|
||||
parse(argc[2]) >= 1000)
|
||||
{
|
||||
runServer(parse(argc[2]));
|
||||
|
||||
}
|
||||
else
|
||||
printUsage();
|
||||
}
|
||||
else
|
||||
printUsage();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void printUsage()
|
||||
{
|
||||
Cout("Usage :\n voip.exe [-c [ip address] | -s] [port] \n -c = run as client\n -s = run as server\n ip address = address of the server\n port = port between 1000 and 65000\n").newline;
|
||||
}
|
162
bindings/d/samples/dsfml/voip/server.d
Normal file
|
@ -0,0 +1,162 @@
|
|||
module server;
|
||||
|
||||
import util;
|
||||
|
||||
class NetworkAudioStream : SoundStream
|
||||
{
|
||||
public:
|
||||
static this()
|
||||
{
|
||||
s_sync = new Object();
|
||||
}
|
||||
|
||||
// Default constructor
|
||||
this()
|
||||
{
|
||||
myListener = new SocketTCP();
|
||||
myClient = new SocketTCP();
|
||||
// Set the sound parameters
|
||||
super(1, 44100);
|
||||
}
|
||||
|
||||
// Destructor
|
||||
~this()
|
||||
{
|
||||
// Close the sockets
|
||||
delete myClient;
|
||||
delete myListener;
|
||||
}
|
||||
|
||||
// Run the server, stream audio data from the client
|
||||
void start(int Port)
|
||||
{
|
||||
if (!myHasFinished)
|
||||
{
|
||||
// Listen to the given port for incoming connections
|
||||
if (!myListener.listen(Port))
|
||||
return;
|
||||
Cout("Listening").newline;
|
||||
myListener.accept(myClient);
|
||||
Cout("New Client").newline;
|
||||
// Start playback
|
||||
play();
|
||||
|
||||
// Start receiving audio data
|
||||
receiveLoop();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Start playback
|
||||
play();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
override bool onStart()
|
||||
{
|
||||
// Reset the playing offset
|
||||
myOffset = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
override bool onGetData(out short[] data)
|
||||
{
|
||||
// We have reached the end of the buffer and all audio data have been played : we can stop playback
|
||||
if ((myOffset == mySamples.length) && myHasFinished)
|
||||
return false;
|
||||
// No new data has arrived since last update : wait until we get some
|
||||
while (myOffset == mySamples.length && !myHasFinished)
|
||||
sleep(0.01f);
|
||||
|
||||
synchronized(s_sync)
|
||||
{
|
||||
myTempBuffer = mySamples[myOffset..mySamples.length];
|
||||
// Update the playing offset
|
||||
myOffset += myTempBuffer.length;
|
||||
}
|
||||
|
||||
data = myTempBuffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void receiveLoop()
|
||||
{
|
||||
while (!myHasFinished)
|
||||
{
|
||||
// Get waiting audio data from the network
|
||||
Packet PacketIn = new Packet();
|
||||
if (myClient.receive(PacketIn) != SocketStatus.DONE)
|
||||
break;
|
||||
|
||||
// Extract the message ID
|
||||
ubyte Id;
|
||||
PacketIn.get(Id);
|
||||
|
||||
if (Id == AudioData)
|
||||
{
|
||||
// Extract audio samples from the packet, and append it to our samples buffer
|
||||
|
||||
synchronized(s_sync)
|
||||
{
|
||||
byte* temp = PacketIn.getData().ptr;
|
||||
temp++;
|
||||
|
||||
mySamples ~= (cast(short*)temp)[0..(PacketIn.getDataSize - byte.sizeof ) / short.sizeof];
|
||||
}
|
||||
}
|
||||
else if (Id == EndOfStream)
|
||||
{
|
||||
// End of stream reached : we stop receiving audio data
|
||||
myHasFinished = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Something's wrong...
|
||||
myHasFinished = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SocketTCP myListener;
|
||||
SocketTCP myClient;
|
||||
short[] mySamples;
|
||||
short[] myTempBuffer;
|
||||
size_t myOffset;
|
||||
bool myHasFinished;
|
||||
|
||||
static Object s_sync;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Launch a server and wait for incoming audio data from
|
||||
// a connected client
|
||||
void runServer(int Port)
|
||||
{
|
||||
// Build an audio stream to play sound data as it is received through the network
|
||||
NetworkAudioStream audioStream = new NetworkAudioStream;
|
||||
audioStream.start(Port);
|
||||
|
||||
// Loop until the sound playback is finished
|
||||
while (audioStream.getStatus() != SoundStatus.STOPPED)
|
||||
{
|
||||
// Leave some CPU time for other threads
|
||||
sleep(0.1f);
|
||||
}
|
||||
|
||||
Cout("Enter to replay").newline;
|
||||
Cin.get();
|
||||
// Replay the sound (just to make sure replaying the received data is OK)
|
||||
audioStream.play();
|
||||
|
||||
// Loop until the sound playback is finished
|
||||
while (audioStream.getStatus() != SoundStatus.STOPPED)
|
||||
{
|
||||
// Leave some CPU time for other threads
|
||||
sleep(0.1f);
|
||||
}
|
||||
}
|
49
bindings/d/samples/dsfml/voip/util.d
Normal file
|
@ -0,0 +1,49 @@
|
|||
module util;
|
||||
|
||||
const ubyte AudioData = 1;
|
||||
const ubyte EndOfStream = 2;
|
||||
|
||||
public import dsfml.system.all;
|
||||
public import dsfml.audio.all;
|
||||
public import dsfml.network.all;
|
||||
|
||||
version(Tango)
|
||||
{
|
||||
public import tango.io.Console;
|
||||
public import tango.text.convert.Integer;
|
||||
}
|
||||
else
|
||||
{
|
||||
public import std.stdio;
|
||||
|
||||
//simple abstraction of Cout & Cin for phobos
|
||||
class Cout
|
||||
{
|
||||
static Cout s_c;
|
||||
static this()
|
||||
{
|
||||
s_c = new Cout();
|
||||
}
|
||||
|
||||
static Cout opCall(char[] str)
|
||||
{
|
||||
writefln("%s", str);
|
||||
return s_c;
|
||||
}
|
||||
void newline()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class Cin
|
||||
{
|
||||
static char[] get()
|
||||
{
|
||||
return readln();
|
||||
}
|
||||
}
|
||||
|
||||
public import std.string : atoi;
|
||||
alias atoi parse;
|
||||
}
|