Examples¶
If you downloaded a source archive or cloned pySFML from github, these examples will be located in the examples subdirectory of the project’s root. A package named ‘pysfml-examples’ is also available for Debian-based Linux distributions, which allows you to run arbitrary examples by invoking a command of the following form from a terminal:
pysfml-<example name>
For example:
pysfml-sound
Ftp¶
1import os
2import sfml.network as sf
3
4# python 2.* compatability
5try: input = raw_input
6except NameError: pass
7
8# choose the server address
9address = input("Enter the FTP server address: ")
10address = sf.IpAddress.from_string(address)
11
12# create the server object which with you will communicate
13server = sf.Ftp()
14
15# connect to the server
16response = server.connect(address)
17print(response)
18if not response.ok: exit()
19
20# ask for user name and password
21user = input("User name: ")
22password = input("Password: ")
23
24# login to the server
25response = server.login(user, password)
26print(response)
27if not response.ok: exit()
28
29# main menu
30choice = 0
31while True:
32 print("===========================================================")
33 print("Choose an action:")
34 print("1. Print working directory")
35 print("2. Print contents of working directory")
36 print("3. Change directory")
37 print("4. Create directory")
38 print("5. Delete directory")
39 print("6. Rename file")
40 print("7. Remove file")
41 print("8. Download file")
42 print("9. Upload file")
43 print("0. Disconnect\n\n")
44
45 choice = int(input("Your choice: "))
46
47 os.system('clear')
48
49 if choice == 1:
50 # print the current server directory
51 response = server.get_working_directory()
52 print(response)
53 print("Current directory is {0}".format(response.get_directory()))
54 elif choice == 2:
55 # print the contents of the current server directory
56 response = server.get_directory_listing()
57 print(response)
58 for filename in response.filenames:
59 print(filename)
60 elif choice == 3:
61 # change the current directory
62 directory = input("Choose a directory: ")
63 response = server.change_directory(directory)
64 print(response)
65 elif choice == 4:
66 # create a new directory
67 directory = input("Name of the directory to create: ")
68 response = server.create_directory(directory)
69 print(response)
70 elif choice == 5:
71 # remove an existing directory
72 directory = input("Name of the directory to remove: ")
73 response = server.delete_directory(directory)
74 print(response)
75 elif choice == 6:
76 # rename a file
77 source = input("Name of the file to rename: ")
78 destination = input("New name: ")
79 response = server.rename_file(source, destination)
80 print(response)
81 elif choice == 7:
82 # remove an existing directory
83 filename = input("Name of the file to remove: ")
84 response = server.delete_file(filename)
85 print(response)
86 elif choice == 8:
87 # download a file from server
88 filename = input("Filename of the file to download (relative to current directory): ")
89 directory = input("Directory to download the file to: ")
90 response = server.download(filename, directory)
91 print(response)
92 elif choice == 9:
93 # upload a file to server
94 filename = input("Path of the file to upload (absolute or relative to working directory): ")
95 directory = input("Directory to upload the file to (relative to current directory): ")
96 response = server.upload(filename, directory)
97 print(response)
98 elif choice == 0:
99 break
100 else:
101 # wrong choice
102 print("Invalid choice!")
103 os.system('clear')
104
105 if choice == 0:
106 break
107
108# disconnect from the server
109print("Disconnecting from server...")
110response = server.disconnect()
111
112# wait until the user presses 'enter' key
113input("Press enter to exit...")
Pong¶
1from __future__ import division
2
3from math import cos, sin, fabs, pi
4from random import randint
5
6from sfml import sf
7
8
9# define some constants
10game_size = sf.Vector2(800, 600)
11paddle_size = sf.Vector2(25, 100)
12ball_radius = 10.
13
14# create the window of the application
15w, h = game_size
16window = sf.RenderWindow(sf.VideoMode(w, h), "pySFML - Pong")
17window.vertical_synchronization = True
18
19# load the sounds used in the game
20ball_sound_buffer = sf.SoundBuffer.from_file("data/ball.wav")
21ball_sound = sf.Sound(ball_sound_buffer)
22
23# create the left paddle
24left_paddle = sf.RectangleShape()
25left_paddle.size = paddle_size - (3, 3)
26left_paddle.outline_thickness = 3
27left_paddle.outline_color = sf.Color.BLACK
28left_paddle.fill_color = sf.Color(100, 100, 200)
29left_paddle.origin = paddle_size / 2
30
31# create the right paddle
32right_paddle = sf.RectangleShape()
33right_paddle.size = paddle_size - (3, 3)
34right_paddle.outline_thickness = 3
35right_paddle.outline_color = sf.Color.BLACK
36right_paddle.fill_color = sf.Color(200, 100, 100)
37right_paddle.origin = paddle_size / 2
38
39# create the ball
40ball = sf.CircleShape()
41ball.radius = ball_radius - 3
42ball.outline_thickness = 3
43ball.outline_color = sf.Color.BLACK
44ball.fill_color = sf.Color.WHITE
45ball.origin = (ball_radius / 2, ball_radius / 2)
46
47# load the font
48font = sf.Font.from_file("data/sansation.ttf")
49
50# initialize the pause message
51pause_message = sf.Text()
52pause_message.font = font
53pause_message.character_size = 40
54pause_message.position = (170, 150)
55pause_message.color = sf.Color.WHITE
56pause_message.string = "Welcome to pySFML pong!\nPress space to start the game"
57
58# define the paddles properties
59ai_timer = sf.Clock()
60ai_time = sf.seconds(0.1)
61paddle_speed = 400.
62right_paddle_speed = 0.
63ball_speed = 400.
64ball_angle = 0. # to be changed later
65
66clock = sf.Clock()
67is_playing = False
68
69while window.is_open:
70
71 # handle events
72 for event in window.events:
73 # window closed or escape key pressed: exit
74 if type(event) is sf.CloseEvent:
75 window.close()
76
77 # space key pressed: play
78 if type(event) is sf.KeyEvent and event.pressed and event.code is sf.Keyboard.SPACE:
79 if not is_playing:
80 # (re)start the game
81 is_playing = True
82 clock.restart()
83
84 # reset the position of the paddles and ball
85 left_paddle.position = (10 + paddle_size.x / 2, game_size.y / 2)
86 right_paddle.position = (game_size.x - 10 - paddle_size.x / 2, game_size.y / 2)
87 ball.position = game_size / 2
88
89 # reset the ball angle
90 while True:
91 # make sure the ball initial angle is not too much vertical
92 ball_angle = (randint(0, 32767) % 360) * 2 * pi / 360
93 if not fabs(cos(ball_angle)) < 0.7: break
94
95 if is_playing:
96 delta_time = clock.restart().seconds
97
98 # move the player's paddle
99 if sf.Keyboard.is_key_pressed(sf.Keyboard.UP) and left_paddle.position.y - paddle_size.y / 2 > 5:
100 left_paddle.move((0, -paddle_speed * delta_time))
101
102 elif sf.Keyboard.is_key_pressed(sf.Keyboard.DOWN) and left_paddle.position.y + paddle_size.y / 2 < game_size.y - 5:
103 left_paddle.position += (0, paddle_speed * delta_time)
104
105 # move the computer' paddle
106 if (right_paddle_speed < 0 and right_paddle.position.y - paddle_size.x / 2 > 5) or (right_paddle_speed > 0 and right_paddle.position.y + paddle_size.y / 2 < game_size.y - 5):
107 right_paddle.position += (0, right_paddle_speed * delta_time)
108
109
110 # update the computer's paddle direction according to the ball position
111 if ai_timer.elapsed_time > ai_time:
112 ai_timer.restart()
113 if ball.position.y + ball_radius > right_paddle.position.y + paddle_size.y / 2:
114 right_paddle_speed = paddle_speed
115 elif ball.position.y - ball_radius < right_paddle.position.y - paddle_size.y / 2:
116 right_paddle_speed = - paddle_speed
117 else:
118 right_paddle_speed = 0
119
120 # move the ball
121 factor = ball_speed * delta_time
122 ball.move((cos(ball_angle) * factor, sin(ball_angle) * factor))
123
124 # check collisions between the ball and the screen
125 if ball.position.x - ball_radius < 0:
126 is_playing = False
127 pause_message.string = "You lost!\nPress space to restart or\nescape to exit"
128
129 if ball.position.x + ball_radius > game_size.x:
130 is_playing = False
131 pause_message.string = "You won !\nPress space to restart or\nescape to exit"
132
133 if ball.position.y - ball_radius < 0:
134 ball_sound.play()
135 ball_angle = - ball_angle
136 ball.position.y = ball_radius + 0.1
137
138 if ball.position.y + ball_radius > game_size.y:
139 ball_sound.play()
140 ball_angle = - ball_angle
141 ball.position.y = game_size.y - ball_radius - 0.1
142
143 # check the collisions between the ball and the paddles
144 # left paddle
145 if ball.position.x - ball_radius < left_paddle.position.x + paddle_size.x / 2 and ball.position.x - ball_radius > left_paddle.position.x and ball.position.y + ball_radius >= left_paddle.position.y - paddle_size.y / 2 and ball.position.y - ball_radius <= left_paddle.position.y + paddle_size.y / 2:
146 if ball.position.y > left_paddle.position.y:
147 ball_angle = pi - ball_angle + (randint(0, 32767) % 20) * pi / 180
148 else:
149 ball_angle = pi - ball_angle - (randint(0, 32767) % 20) * pi / 180
150
151 ball_sound.play()
152 ball.position = (left_paddle.position.x + ball_radius + paddle_size.x / 2 + 0.1, ball.position.y)
153
154 # right paddle
155 if ball.position.x + ball_radius > right_paddle.position.x - paddle_size.x / 2 and ball.position.x + ball_radius < right_paddle.position.x and ball.position.y + ball_radius >= right_paddle.position.y - paddle_size.y / 2 and ball.position.y - ball_radius <= right_paddle.position.y + paddle_size.y / 2:
156 if ball.position.y > right_paddle.position.y:
157 ball_angle = pi - ball_angle + (randint(0, 32767) % 20) * pi / 180
158 else:
159 ball_angle = pi - ball_angle - (randint(0, 32767) % 20) * pi / 180
160
161 ball_sound.play()
162 ball.position = (right_paddle.position.x - ball_radius - paddle_size.x / 2 - 0.1, ball.position.y)
163
164 window.clear(sf.Color(50, 200, 50))
165
166 if is_playing:
167 # draw the paddles and the ball
168 window.draw(left_paddle)
169 window.draw(right_paddle)
170 window.draw(ball)
171
172 else:
173 # draw the pause message
174 window.draw(pause_message)
175
176 # display things on screen
177 window.display()
PyQt4¶
1import sys, platform
2
3try:
4 import sip
5 from PyQt4.QtCore import *
6 from PyQt4.QtGui import *
7except ImportError:
8 print("Install PyQt4 and sip from Riverbank.")
9
10from sfml import sf
11
12
13class QSFMLCanvas(QWidget):
14 def __init__(self, parent, position, size, frameTime=0):
15 QWidget.__init__(self, parent)
16 self.initialized = False
17
18 w = size.width()
19 h = size.height()
20
21 self._HandledWindow = sf.HandledWindow()
22 self._HandledWindow.view.size = (w, h)
23 self.__dict__['draw'] = self._HandledWindow.draw
24 self.__dict__['clear'] = self._HandledWindow.clear
25 self.__dict__['view'] = self._HandledWindow.view
26 self.__dict__['display'] = self._HandledWindow.display
27
28 # setup some states to allow direct rendering into the widget
29 self.setAttribute(Qt.WA_PaintOnScreen)
30 self.setAttribute(Qt.WA_OpaquePaintEvent)
31 self.setAttribute(Qt.WA_NoSystemBackground)
32
33 # set strong focus to enable keyboard events to be received
34 self.setFocusPolicy(Qt.StrongFocus);
35
36 # setup the widget geometry
37 self.move(position);
38 self.resize(size);
39
40 # setup the timer
41 self.timer = QTimer()
42 self.timer.setInterval(frameTime)
43
44 def onInit(self): pass
45
46 def onUpdate(self): pass
47
48 def sizeHint(self):
49 return self.size()
50
51 def paintEngine(self):
52 # let the derived class do its specific stuff
53 self.onUpdate()
54
55 # display on screen
56 self.display()
57
58 def showEvent(self, event):
59 if not self.initialized:
60 # under X11, we need to flush the commands sent to the server
61 # to ensure that SFML will get an updated view of the windows
62 # create the SFML window with the widget handle
63 if platform.system() == 'Linux':
64 from ctypes import cdll
65 x11 = cdll.LoadLibrary("libX11.so")
66
67 display = sip.unwrapinstance(QX11Info.display())
68 x11.XFlush(display)
69
70 self._HandledWindow.create(self.winId())
71
72 # let the derived class do its specific stuff
73 self.onInit()
74
75 # setup the timer to trigger a refresh at specified framerate
76 self.connect(self.timer,SIGNAL('timeout()'), self, SLOT('repaint()'))
77 self.timer.start()
78
79 self.initialized = True
80
81 def paintEvent(self, event):
82 return None
Shader¶
1from __future__ import division
2
3from random import randint
4from math import cos
5
6from sfml import sf
7
8class Effect(sf.Drawable):
9 def __init__(self, name):
10 sf.Drawable.__init__(self)
11
12 self._name = name
13 self.is_loaded = False
14
15 def _get_name(self):
16 return self._name
17
18 def load(self):
19 self.is_loaded = sf.Shader.is_available() and self.on_load()
20
21 def update(self, time, x, y):
22 if self.is_loaded:
23 self.on_update(time, x, y)
24
25 def draw(self, target, states):
26 if self.is_loaded:
27 self.on_draw(target, states)
28 else:
29 error = sf.Text("Shader not\nsupported")
30 error.font = sf.Font.from_file("data/sansation.ttf")
31 error.position = (320, 200)
32 error.character_size = 36
33 target.draw(error, states)
34
35 name = property(_get_name)
36
37class Pixelate(Effect):
38 def __init__(self):
39 Effect.__init__(self, 'pixelate')
40
41 def on_load(self):
42 try:
43 # load the texture and initialize the sprite
44 self.texture = sf.Texture.from_file("data/background.jpg")
45 self.sprite = sf.Sprite(self.texture)
46
47 # load the shader
48 self.shader = sf.Shader.from_file(fragment="data/pixelate.frag")
49 self.shader.set_parameter("texture")
50
51 except IOError as error:
52 print("An error occured: {0}".format(error))
53 exit(1)
54
55 return True
56
57 def on_update(self, time, x, y):
58 self.shader.set_parameter("pixel_threshold", (x + y) / 30)
59
60 def on_draw(self, target, states):
61 states.shader = self.shader
62 target.draw(self.sprite, states)
63
64
65class WaveBlur(Effect):
66 def __init__(self):
67 Effect.__init__(self, 'wave + blur')
68
69 def on_load(self):
70 with open("data/text.txt") as file:
71 self.text = sf.Text(file.read())
72 self.text.font = sf.Font.from_file("data/sansation.ttf")
73 self.text.character_size = 22
74 self.text.position = (30, 20)
75
76 try:
77 # load the shader
78 self.shader = sf.Shader.from_file("data/wave.vert", "data/blur.frag")
79
80 except IOError as error:
81 print("An error occured: {0}".format(error))
82 exit(1)
83
84 return True
85
86 def on_update(self, time, x, y):
87 self.shader.set_parameter("wave_phase", time)
88 self.shader.set_parameter("wave_amplitude", x * 40, y * 40)
89 self.shader.set_parameter("blur_radius", (x + y) * 0.008)
90
91 def on_draw(self, target, states):
92 states.shader = self.shader
93 target.draw(self.text, states)
94
95
96class StormBlink(Effect):
97 def __init__(self):
98 Effect.__init__(self, 'storm + blink')
99
100 self.points = sf.VertexArray()
101
102 def on_load(self):
103 # create the points
104 self.points.primitive_type = sf.PrimitiveType.POINTS
105
106 for i in range(40000):
107 x = randint(0, 32767) % 800
108 y = randint(0, 32767) % 600
109 r = randint(0, 32767) % 255
110 g = randint(0, 32767) % 255
111 b = randint(0, 32767) % 255
112 self.points.append(sf.Vertex(sf.Vector2(x, y), sf.Color(r, g, b)))
113
114 try:
115 # load the shader
116 self.shader = sf.Shader.from_file("data/storm.vert", "data/blink.frag")
117
118 except IOError as error:
119 print("An error occured: {0}".format(error))
120 exit(1)
121
122 return True
123
124 def on_update(self, time, x, y):
125 radius = 200 + cos(time) * 150
126 self.shader.set_parameter("storm_position", x * 800, y * 600)
127 self.shader.set_parameter("storm_inner_radius", radius / 3)
128 self.shader.set_parameter("storm_total_radius", radius)
129 self.shader.set_parameter("blink_alpha", 0.5 + cos(time*3) * 0.25)
130
131 def on_draw(self, target, states):
132 states.shader = self.shader
133 target.draw(self.points, states)
134
135class Edge(Effect):
136 def __init__(self):
137 Effect.__init__(self, "edge post-effect")
138
139 def on_load(self):
140 # create the off-screen surface
141 self.surface = sf.RenderTexture(800, 600)
142 self.surface.smooth = True
143
144 # load the textures
145 self.background_texture = sf.Texture.from_file("data/sfml.png")
146 self.background_texture.smooth = True
147
148 self.entity_texture = sf.Texture.from_file("data/devices.png")
149 self.entity_texture.smooth = True
150
151 # initialize the background sprite
152 self.background_sprite = sf.Sprite(self.background_texture)
153 self.background_sprite.position = (135, 100)
154
155 # load the moving entities
156 self.entities = []
157
158 for i in range(6):
159 sprite = sf.Sprite(self.entity_texture, (96 * i, 0, 96, 96))
160 self.entities.append(sprite)
161
162 # load the shader
163 self.shader = sf.Shader.from_file(fragment="data/edge.frag")
164 self.shader.set_parameter("texture")
165
166 return True
167
168 def on_update(self, time, x, y):
169 self.shader.set_parameter("edge_threshold", 1 - (x + y) / 2)
170
171 # update the position of the moving entities
172 for i, entity in enumerate(self.entities):
173 x = cos(0.25 * (time * i + (len(self.entities) - i))) * 300 + 350
174 y = cos(0.25 * (time * (len(self.entities) - i) + i)) * 200 + 250
175 entity.position = (x, y)
176
177 # render the updated scene to the off-screen surface
178 self.surface.clear(sf.Color.WHITE)
179 self.surface.draw(self.background_sprite)
180
181 for entity in self.entities:
182 self.surface.draw(entity)
183
184 self.surface.display()
185
186 def on_draw(self, target, states):
187 states.shader = self.shader
188 target.draw(sf.Sprite(self.surface.texture), states)
189
190
191if __name__ == "__main__":
192 # create the main window
193 window = sf.RenderWindow(sf.VideoMode(800, 600), "pySFML - Shader")
194 window.vertical_synchronization = True
195
196 # create the effects
197 effects = (Pixelate(), WaveBlur(), StormBlink(), Edge())
198 current = 0
199
200 # initialize them
201 for effect in effects: effect.load()
202
203 # create the message background
204 try:
205 text_background_texture = sf.Texture.from_file("data/text-background.png")
206
207 except IOError as error:
208 print("An error occured: {0}".format(error))
209 exit(1)
210
211 text_background = sf.Sprite(text_background_texture)
212 text_background.position = (0, 520)
213 text_background.color = sf.Color(255, 255, 255, 200)
214
215 # load the messages font
216 try:
217 font = sf.Font.from_file("data/sansation.ttf")
218
219 except IOError as error:
220 print("An error occured: {0}".format(error))
221 exit(1)
222
223 # create the description text
224 description = sf.Text("Current effect: {0}".format(effects[current].name), font, 20)
225 description.position = (10, 530)
226 description.color = sf.Color(80, 80, 80)
227
228 # create the instructions text
229 instructions = sf.Text("Press left and right arrows to change the current shader", font, 20)
230 instructions.position = (280, 555)
231 instructions.color = sf.Color(80, 80, 80)
232
233 clock = sf.Clock()
234
235 # start the game loop
236 while window.is_open:
237
238 # update the current example
239 x, y = sf.Mouse.get_position(window) / window.size
240 effects[current].update(clock.elapsed_time.seconds, x, y)
241
242 # process events
243 for event in window.events:
244
245 # close window: exit
246 if type(event) is sf.CloseEvent:
247 window.close()
248
249 if type(event) is sf.KeyEvent and event.pressed:
250 # escapte key: exit
251 if event.code == sf.Keyboard.ESCAPE:
252 window.close()
253
254 # left arrow key: previous shader
255 elif event.code is sf.Keyboard.LEFT:
256 if current == 0: current = len(effects) - 1
257 else: current -= 1
258
259 description.string = "Current effect: {0}".format(effects[current].name)
260
261 # right arrow key: next shader
262 elif event.code is sf.Keyboard.RIGHT:
263 if current == len(effects) - 1: current = 0
264 else: current += 1
265
266 description.string = "Current effect: {0}".format(effects[current].name)
267
268
269 # clear the window
270 window.clear(sf.Color(255, 128, 0))
271
272 # draw the current example
273 window.draw(effects[current])
274
275 # draw the text
276 window.draw(text_background)
277 window.draw(instructions)
278 window.draw(description)
279
280 # finally, display the rendered frame on screen
281 window.display()
Sockets¶
1import sfml.network as sf
2
3# python 2.* compatability
4try: input = raw_input
5except NameError: pass
6
7def run_tcp_server():
8 """ Launch a server. The server waits for an incoming connection,
9 sends a message and waits for the answer. """
10
11 try:
12 # create a server socket to accept new connections
13 listener = sf.TcpListener()
14
15 # listen to the given port for incoming connections
16 listener.listen(PORT)
17
18 print("Server is listening to port {0}, waiting for connections...".format(PORT))
19
20 # wait for a connection
21 socket = listener.accept()
22 print("Client connected: {0}".format(socket.remote_address))
23
24 # send a message to the connected client
25 message = "Hi, I'm the server"
26 socket.send(message.encode('utf-8'))
27 print("Message sent to the client: {0}".format(message))
28
29 # recieve a message back from the client
30 answer = socket.receive(128).decode('utf-8')
31 print("Answer received from the client: {0}".format(answer))
32
33 except sf.SocketException as error:
34 print("An error occured!")
35 print(error)
36 return
37
38def run_tcp_client():
39 """ Create a client. The client is connected to a server, displays
40 the welcome message and sends an answer. """
41
42 server = input("Type the address or name of the server to connect to: ")
43 server = sf.IpAddress.from_string(server)
44
45 # create a socket for communicating with the server
46 socket = sf.TcpSocket()
47
48 # connect to the server
49 try:
50 socket.connect(server, PORT)
51 print("Connected to server {0}".format(server))
52
53 # receive a message from the server
54 message = socket.receive(128).decode('utf-8')
55 print("Message received from the server: {0}".format(message))
56
57 # send an answer to the server
58 answer = "Hi, I'm a client"
59 socket.send(answer.encode('utf-8'))
60 print("Message sent to the server: {0}".format(answer))
61
62 except sf.SocketException as error:
63 print("An error occured!")
64 print(error)
65 return
66
67def run_udp_server():
68 """ Launch a server. The server waits for a message then sends an
69 answer. """
70
71 # create a socket to receive a message from anyone
72 socket = sf.UdpSocket()
73
74 try:
75 # listen to messages on the specified port
76 socket.bind(PORT)
77 print("Server is listening to port {0}, waiting for message...".format(PORT))
78
79 # wait for a message
80 message, ip, port = socket.receive(128)
81 print("Message received from client {0}: {1}".format(ip, message.decode('utf-8')))
82
83 # send an answer to the client
84 answer = "Hi, I'm the server"
85 socket.send(answer.encode('utf-8'), ip, port)
86 print("Message sent to the client: {0}".format(answer))
87
88 except sf.SocketException as error:
89 print("An error occured!")
90 print(error)
91 return
92
93def run_udp_client():
94 """ Send a message to the server, wait for the answer. """
95
96 # ask for the server address
97 server = input("Type the address or name of the server to connect to: ")
98 server = sf.IpAddress.from_string(server)
99
100 # create a socket for communicating with the server
101 socket = sf.UdpSocket()
102
103 try:
104 # send a message to the server
105 message = "Hi, I'm a client"
106 socket.send(message.encode('utf-8'), server, PORT)
107 print("Message sent to the server: {0}".format(message))
108
109 # receive an answer from anyone (but most likely from the server)
110 answer, ip, port = socket.receive(128)
111 print("Message received from {0}: {1}".format(ip, answer.decode('utf-8')))
112
113 except sf.SocketException as error:
114 print("An error occured!")
115 print(error)
116 return
117
118if __name__ == "__main__":
119 # choose an arbitrary port for opening sockets
120 PORT = 50001
121
122 # TCP or UDP ?
123 print("Do you want to use TCP (t) or UDP (u) ?")
124 protocol = input()
125
126 # client or server ?
127 print("Do you want to be a server (s) or a client (c) ?")
128 who = input()
129
130 if protocol == 't':
131 if who == 's': run_tcp_server()
132 else: run_tcp_client()
133 else:
134 if who == 's': run_udp_server()
135 else: run_udp_client()
136
137 input("Press any key to exit...")
Sound capture¶
1from sfml import sf
2
3# python 2.* compatability
4try: input = raw_input
5except NameError: pass
6
7def main():
8 # check that the device can capture audio
9 if not sf.SoundRecorder.is_available():
10 print("Sorry, audio capture is not supported by your system")
11 return
12
13 # choose the sample rate
14 sample_rate = int(input("Please choose the sample rate for sound capture (44100 is CD quality): "))
15
16 # wait for user input...
17 input("Press enter to start recording audio")
18
19 # here we'll use an integrated custom recorder, which saves the captured data into a sf.SoundBuffer
20 recorder = sf.SoundBufferRecorder()
21
22 # audio capture is done in a separate thread, so we can block the main thread while it is capturing
23 recorder.start(sample_rate)
24 input("Recording... press enter to stop")
25 recorder.stop()
26
27 # get the buffer containing the captured data
28 buffer = recorder.buffer
29
30 # display captured sound informations
31 print("Sound information:")
32 print("{0} seconds".format(buffer.duration))
33 print("{0} samples / seconds".format(buffer.sample_rate))
34 print("{0} channels".format(buffer.channel_count))
35
36 # choose what to do with the recorded sound data
37 choice = input("What do you want to do with captured sound (p = play, s = save) ? ")
38
39 if choice == 's':
40 # choose the filename
41 filename = input("Choose the file to create: ")
42
43 # save the buffer
44 buffer.to_file(filename);
45 else:
46 # create a sound instance and play it
47 sound = sf.Sound(buffer)
48 sound.play();
49
50 # wait until finished
51 while sound.status == sf.Sound.PLAYING:
52 # leave some CPU time for other threads
53 sf.sleep(sf.milliseconds(100))
54
55 # finished !
56 print("Done !")
57
58 # wait until the user presses 'enter' key
59 input("Press enter to exit...")
60
61if __name__ == "__main__":
62 main()
Sound¶
1from sfml import sf
2
3def play_sound():
4 # load a sound buffer from a wav file
5 buffer = sf.SoundBuffer.from_file("data/canary.wav")
6
7 # display sound informations
8 print("canary.wav:")
9 print("{0} seconds".format(buffer.duration))
10 print("{0} samples / sec".format(buffer.sample_rate))
11 print("{0} channels".format(buffer.channel_count))
12
13 # create a sound instance and play it
14 sound = sf.Sound(buffer)
15 sound.play();
16
17 # loop while the sound is playing
18 while sound.status == sf.Sound.PLAYING:
19 # leave some CPU time for other processes
20 sf.sleep(sf.milliseconds(100))
21
22def play_music():
23 # load an ogg music file
24 music = sf.Music.from_file("data/orchestral.ogg")
25
26 # display music informations
27 print("orchestral.ogg:")
28 print("{0} seconds".format(music.duration))
29 print("{0} samples / sec".format(music.sample_rate))
30 print("{0} channels".format(music.channel_count))
31
32 # play it
33 music.play();
34
35 # loop while the music is playing
36 while music.status == sf.Music.PLAYING:
37 # leave some CPU time for other processes
38 sf.sleep(sf.milliseconds(100))
39
40if __name__ == "__main__":
41 play_sound()
42 play_music()
43
44 input("Press enter to exit...")
Voip¶
1from sfml import sf
2import client, server
3
4# python 2.* compatability
5try: input = raw_input
6except NameError: pass
7
8# choose a random port for opening sockets (ports < 1024 are reserved)
9PORT = 2435
10
11# client or server ?
12print("Do you want to be a server (s) or a client (c) ?")
13who = input()
14
15if who == 's':
16 server.do_server(PORT)
17else:
18 client.do_client(PORT)
19
20input("Press any key to exit...")
1from sfml import sf
2from struct import pack
3from random import randint
4
5# python 2.* compatability
6try: input = raw_input
7except NameError: pass
8
9AUDIO_DATA, END_OF_STREAM = list(range(1, 3))
10
11class NetworkRecorder(sf.SoundRecorder):
12 def __init__(self, host, port):
13 sf.SoundRecorder.__init__(self)
14
15 self.host = host # address of the remote host
16 self.port = port # remote port
17 self.socket = sf.TcpSocket() # socket used to communicate with the server
18
19 def on_start(self):
20 try: self.socket.connect(self.host, self.port)
21 except sf.SocketException as error: return False
22
23 return True
24
25 def on_process_samples(self, chunk):
26 # pack the audio samples
27 data = pack("B", AUDIO_DATA)
28 data += pack("I", len(chunk.data))
29 data += chunk.data
30
31 # send the audio packet
32 try: self.socket.send(data)
33 except sf.SocketException: return False
34
35 return True
36
37 def on_stop(self):
38 # send a "end-of-stream" signal
39 self.socket.send(bytes(END_OF_STREAM))
40
41 # close the socket
42 self.socket.disconnect()
43
44def do_client(port):
45 # check that the device can capture audio
46 if not sf.SoundRecorder.is_available():
47 print("Sorry, audio capture is not supported by your system")
48 return
49
50 # ask for server address
51 server = input("Type address or name of the server to connect to: ")
52 server = sf.IpAddress.from_string(server)
53
54 # create an instance of our custom recorder
55 recorder = NetworkRecorder(server, port)
56
57 # wait for the user input...
58 input("Press enter to start recording audio")
59
60 # start capturing audio data
61 recorder.start(44100)
62 input("Recording... press enter to stop")
63 recorder.stop()
1import threading
2from time import sleep
3from sfml import sf
4from struct import unpack
5
6# python 2.* compatability
7try: input = raw_input
8except NameError: pass
9
10AUDIO_DATA, END_OF_STREAM = list(range(1, 3))
11
12class NetworkAudioStream(sf.SoundStream):
13 def __init__(self):
14 sf.SoundStream.__init__(self)
15
16 self.offset = 0
17 self.has_finished = False
18 self.listener = sf.TcpListener()
19 self.samples = sf.Chunk()
20
21 # set the sound parameters
22 self.initialize(1, 44100)
23
24 def start(self, port):
25 if not self.has_finished:
26 try:
27 # listen to the given port for incoming connections
28 self.listener.listen(port)
29 print("Server is listening to port {0}, waiting for connections... ".format(port))
30
31 # wait for a connection
32 self.client = self.listener.accept()
33 print("Client connected: {0}".format(self.client.remote_address))
34
35 except sf.SocketException: return
36
37 # start playback
38 self.play()
39
40 # start receiving audio data
41 self.receive_loop()
42
43 else:
44 # start playback
45 self.play()
46
47 def on_get_data(self, chunk):
48 # we have reached the end of the buffer and all audio data have been played : we can stop playback
49 if self.offset >= len(self.samples) and self.has_finished:
50 return False
51
52 # no new data has arrived since last update : wait until we get some
53 while self.offset >= len(self.samples) and not self.has_finished:
54 sf.sleep(sf.milliseconds(10))
55
56 # don't forget to lock as we run in two separate threads
57 lock = threading.Lock()
58 lock.acquire()
59
60 # fill audio data to pass to the stream
61 chunk.data = self.samples.data[self.offset*2:]
62
63 # update the playing offset
64 self.offset += len(chunk)
65
66 lock.release()
67
68 return True
69
70 def on_seek(self, time_offset):
71 self.offset = time_offset.milliseconds * self.sample_rate * self.channel_count // 1000
72
73 def receive_loop(self):
74 lock = threading.RLock()
75
76 while not self.has_finished:
77 # get waiting audio data from the network
78 data = self.client.receive(1)
79
80 # extract the id message
81 id = unpack("B", data)[0]
82
83 if id == AUDIO_DATA:
84 # extract audio samples from the packet, and append it to our samples buffer
85 data = self.client.receive(4)
86 sample_count = unpack("I", data)[0]
87
88 samples = self.client.receive(sample_count)
89
90 # don't forget the other thread can access the sample array at any time
91 lock.acquire()
92 self.samples.data += samples
93 lock.release()
94
95 elif id == END_OF_STREAM:
96 # end of stream reached : we stop receiving audio data
97 print("Audio data has been 100% received!")
98 self.has_finished = True
99
100 else:
101 # something's wrong...
102 print("Invalid data received...")
103 self.has_finished = True
104
105def do_server(port):
106 # build an audio stream to play sound data as it is received through the network
107 audio_stream = NetworkAudioStream()
108 audio_stream.start(port)
109
110 # loop until the sound playback is finished
111 while audio_stream.status != sf.SoundStream.STOPPED:
112 # leave some CPU time for other threads
113 sf.sleep(sf.milliseconds(100))
114
115
116 # wait until the user presses 'enter' key
117 input("Press enter to replay the sound...")
118
119 # replay the sound (just to make sure replaying the received data is OK)
120 audio_stream.play();
121
122 # loop until the sound playback is finished
123 while audio_stream.status != sf.SoundStream.STOPPED:
124 sf.sleep(sf.milliseconds(100))
Embedding¶
1// Including Python.h first is mandatory!
2#include <Python.h>
3
4#include <unistd.h>
5#include <iostream>
6
7// Make sure to include the SFML headers before the pySFML ones
8#include <SFML/Graphics.hpp>
9#include <pysfml/graphics_api.h>
10
11int main(int argc, char *argv[])
12{
13 // Initialization (mandatory stuff)
14 Py_SetProgramName(argv[0]);
15 Py_Initialize();
16
17 // Add the current path to sys.path to find our script
18 char cwd[1024];
19 if (!getcwd(cwd, sizeof(cwd))) {
20 std::cout << "Couldn't get the current path" << std::endl;
21 return EXIT_FAILURE; }
22 PyObject *sys = PyImport_ImportModule("sys");
23 PyObject *path = PyObject_GetAttrString(sys, "path");
24 PyList_Append(path, PyString_FromString(cwd));
25
26 // Import our script that creates a texture
27 PyObject* script = PyImport_ImportModule("script");
28 if(!script)
29 PyErr_Print();
30
31 // Retrieve the texture
32 PyTextureObject *texture;
33 texture = (PyTextureObject*)PyObject_GetAttrString(script, "texture");
34
35 // Create a window and display the texture for five seconds
36 sf::RenderWindow window(sf::VideoMode(640, 480), "pySFMl - Embedding Python");
37
38 window.clear();
39 window.draw(sf::Sprite(*texture->p_this));
40 window.display();
41
42 sf::sleep(sf::seconds(5));
43
44 // Then, terminate properly...
45 Py_Finalize();
46
47 return EXIT_SUCCESS;
48}
1from sfml import sf
2
3texture = sf.Texture.from_file("image.jpg")
Extending¶
1cimport libcpp.sfml as sf
2from pysfml.graphics cimport Image
3
4def flip_image(Image image):
5 image.p_this.flipHorizontally()
6 image.p_this.flipVertically()
1from sfml import sf
2
3import pyximport; pyximport.install()
4import extension
5
6window = sf.RenderWindow(sf.VideoMode(640, 480), "sfml")
7
8image = sf.Image.from_file("image.jpg")
9extension.flip_image(image)
10
11texture = sf.Texture.from_image(image)
12
13window.clear()
14window.draw(sf.Sprite(texture))
15window.display()
16
17sf.sleep(sf.seconds(5))
Spacial Music¶
1from sfml import sf
2
3def main(song):
4 window = sf.RenderWindow(sf.VideoMode(600, 600), "pySFML - Spacial Music")
5 window.framerate_limit = 60
6
7 # load one font, one song and two textures
8 try:
9 font = sf.Font.from_file("data/sansation.ttf")
10 music = sf.Music.from_file(song)
11
12 texture = sf.Texture.from_file("data/speaker.gif")
13 speaker = sf.Sprite(texture)
14 speaker.position = -texture.size // 2
15
16 texture = sf.Texture.from_file("data/head_kid.png")
17 hears = sf.Sprite(texture)
18 hears.origin = texture.size // 2
19
20 except IOError:
21 exit(1)
22
23 # create a text that display instructions
24 instructions = "Up/Down Move hears along Y axis\n"
25 instructions += "Left/Right Move hears along X axis\n"
26 instructions += "Plus/Minus Move hears along Z axis"
27 instructions = sf.Text(instructions, font, 12)
28 instructions.position = (70, 250)
29 instructions.color = sf.Color.BLACK
30
31 # make sure the song is monothread so it can be spacialized
32 if music.channel_count != 1:
33 print("Only sounds with one channel (mono sounds) can be spatialized.")
34 print("This song ({0}) has {1} channels.".format(SONG, music.channels_count))
35 exit(1)
36
37 # setup the music properties
38 music.relative_to_listener = False
39 music.min_distance = 200
40 music.attenuation = 1
41
42 # initialize some values before entering the main loop
43 position = sf.Vector3(-250, -250, 0)
44 sf.Listener.set_position(position)
45
46 x, y, _ = position
47 hears.position = (x, y)
48
49 running = True
50
51 # move the view to make coord (0, 0) appears on the center of the screen
52 window.default_view.move(-300, -300)
53
54 # start the music before entering the main loop
55 music.loop = True
56 music.play()
57
58 # start the main loop
59 while running:
60 for event in window.events:
61 if type(event) is sf.CloseEvent:
62 running = False
63
64 elif type(event) is sf.KeyEvent and event.pressed:
65 if event.code is sf.Keyboard.UP:
66 position.y -= 5
67
68 elif event.code is sf.Keyboard.DOWN:
69 position.y += 5
70
71 elif event.code is sf.Keyboard.LEFT:
72 position.x -= 5
73
74 elif event.code is sf.Keyboard.RIGHT:
75 position.x += 5
76
77 elif event.code is sf.Keyboard.ADD:
78 if position.z < 400:
79 position.z += 5
80
81 elif event.code is sf.Keyboard.SUBTRACT:
82 if position.z > -400:
83 position.z -= 5
84
85 # update the listener and the hears position
86 sf.Listener.set_position(position)
87
88 x, y, z = position
89 hears.position = (x, y)
90 hears.ratio = (1, 1) + sf.Vector2(z, z)/400.
91
92 # clear screen, draw images and text and display them
93 window.clear(sf.Color.WHITE)
94
95 if position.z >= 0:
96 window.draw(speaker)
97 window.draw(hears)
98 else:
99 window.draw(hears)
100 window.draw(speaker)
101
102 window.draw(instructions)
103 window.display()
104
105 window.close()
106
107
108if __name__ == "__main__":
109 main("data/mario.flac")