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