Laser Pong

This commit is contained in:
nrhck 2019-01-16 01:50:24 +01:00
parent 531a5f0490
commit e6366649a4
25 changed files with 1837 additions and 563 deletions

View File

@ -11,16 +11,12 @@ A software laser server with GUI for up to 4 lasers live actions. Think creative
LJ has 3 main components :
- A tracer per etherdream/laser that take current client point list, correct geometry, recompute in etherdreams coordinates, send it to its controller,... and report etherdream status to the manager.
- A manager that talk to all tracers (which client number point lists to draw, new geometry correction,...), handle the webui functions, OSC commands,...
- A "tracer" per etherdream/laser that take its point list, correct geometry, recompute in etherdreams coordinates, send it to its controller,... and report etherdream status to the manager.
- A "manager" that talk to all tracers (which client number point lists to draw, new geometry correction,...), handle the webui functions, OSC commands,...
- Up to ten clients, that simultaneously send one point list per laser.
You write abd run your laser client software in any redis capable programming langage (50+ : https://redis.io/clients).
Needs at least : an etherdream DAC connected to an ILDA laser, RJ 45 IP network (gigabits only !! no wifi, 100 mpbs doesn't work well with several lasers)
The server approach is based on redis.
LJ supports Linux and OS X. Windows is unkown but welcome, if someone want to jump in and care about it.
@ -32,50 +28,13 @@ LJ supports Linux and OS X. Windows is unkown but welcome, if someone want to ju
(Doc in progress)
- OSC and websocket commands. Very cool : LJ can script or be scripted.
- Web ui : In your browser open webui/index.html. Javascript is needed.
- Web ui : In your browser open webui/index.html. Javascript is needed. By default it connect to localhost. If you want to control a remote server, you need to change the uri line in LJ.js.
- Status update every 0.5 seconds : every etherdream DAC state, number of buffer points sent,...
- "Optimisation" points automatically added, can be changed live for glitch art. Search "resampler" commands.
- A compiled version for os x and linux of nannou.org etherdream+laser emulator is included. For more informations, like license see https://github.com/nannou-org/ether-dream
- A 3D anaglyph client example
- Some fancy examples are available : 3D anaglyph, Laser Pong, Laser Wars
#
# Networking
#
LJ is network based and this is *critical and flickering reason #1* if not managed properly, especially you have several lasers.
Our "always working solution", as we regularly move our gear for different venues :
We use static network configuration. Our Etherdreams controllers have static IPs defined in their SDcard from 192.168.1.1 to 192.168.1.9. Because wifi will always finally sucks for many reasons, our computers (laser server and clients) are *gigabits wired connected* with 192.168.1.10 and after. Don't trust end user gear marketing on wifi, we have a big gigabits switch for laser only stuff. We provide Internet through wifi on different network like 192.168.2.x
Even if etherdreams are 100 Mbits, we use gigabits gear.
By default LJ uses on 127.0.0.1 (localhost) :
- A websocket on port 9001 for WebUI interaction.
- The redis server on port 6379 ('ljayserverip')
- An OSC server on port 8002.
- An OSC client for 'bhoroscIP' port 8001.
- An OSC client for Nozoids support on 'nozoscIP', port 8003.
You need to update LJ.conf to your network/etherdreams IPs and be sure to check command arguments : python main.py --help
The need for a dedicated computer to act as "laser server" usually depends on how many lasers you want to control and your main computer load. If you seen flickering with small point lists, try the dedicated computer option and/or stop process interfering like redis monitoring,...
Program your own "Client" :
-------------------------
- Read the Introduction part in this readme.
- Carefully read all comments in clients examples.
- Generate at least one point list array (say a square).
- Feed your point list array in string format to redis server.
- laserglyph.py is
#
# Install
@ -112,7 +71,7 @@ Order is :
- Redis server once.
- This server. see below.
- Load/reload webUI page from disk in a browser (webui/index.html). Javascript must be enabled.
- A Client, see in clients folder for examples.
- Run a client, see in clients folder for examples.
A typical start is python main.py -L numberoflasers. Use -h to display all possible arguments.
@ -150,6 +109,20 @@ redis-cli -h redisserverIP monitor
#
# Program your own "Client"
#
The server approach is based on redis, so you write and run your laser client software in any redis capable programming langage (50+ : https://redis.io/clients).
- Read the Introduction part in this readme.
- There is a clients folders with examples in different languages.
- Generate at least one point list array (say a square).
- Feed your point list array in string format to redis server.
-
#
# Todo
#
@ -160,6 +133,34 @@ redis-cli -h redisserverIP monitor
- A grid style warp correction process in webUI
#
# Networking
#
LJ is network based and this is *critical and flickering reason #1* if not managed properly, especially if you have several lasers.
Our "always working solution", as we regularly move our gear for different venues :
We use static network configuration. Our Etherdreams controllers have static IPs defined in their SDcard from 192.168.1.1 to 192.168.1.9. Because wifi will always finally sucks for many reasons, our computers (laser server and clients) are *gigabits wired connected* with 192.168.1.10 and after. Don't trust end user gear marketing on wifi, we have a big gigabits switch for laser only stuff. We provide Internet through wifi on different network like 192.168.2.x
Even if etherdreams are 100 Mbits, we use gigabits gear.
By default LJ uses on 127.0.0.1 (localhost) :
- A websocket on port 9001 for WebUI interaction.
- The redis server on port 6379 ('ljayserverip')
- An OSC server on port 8002.
- An OSC client as output on port 8001.
- An OSC client for Nozoids support on 'nozoscIP', port 8003.
You need to update LJ.conf to your network/etherdreams IPs and be sure to check command arguments : python main.py --help
The need for a dedicated computer to act as "laser server" usually depends on how many lasers you want to control and your main computer load. If you seen flickering with small point lists, try the dedicated computer option and/or stop process interfering like redis monitoring,...
#
# Ether dream configuration
#
@ -172,10 +173,10 @@ This program suppose that the ether dream is configured in a certain way especia
/net/netmask 255.255.255.0
/net/gateway 192.168.1.1
/net/gateway 192.168.1.10
/ilda/pps 25000
/ilda/fps 25
About hardware setup, especially if you have several lasers : ILDA cables are insanely expensive. You may consider the Power Over Ethernet 'POE' option. Buy a very small ILDA cable, a POE splitter and connect everything to the ether dream fixed near your laser. You can have then a simple and very long network cable and use a Power Over Ethernet injector or switch closed to the driving computer. Beware some vendors use 24V POE Injector : POE injectors and splitters must match.
About hardware setup, especially if you have several lasers : ILDA cables are insanely expensive. You may consider the Power Over Ethernet 'POE' option. Buy a very small ILDA cable, a POE splitter and connect everything to the ether dream fixed near your laser. You can have then a simple and very long network cable and use a Power Over Ethernet injector or switch close to the driving computer. Beware some vendors use 24V POE Injector : POE injectors and splitters must match.

36
cli.py
View File

@ -22,20 +22,18 @@ def handle():
#have to be done before importing bhorosc.py to get correct port assignment
argsparser = argparse.ArgumentParser(description="LJay")
argsparser.add_argument("-r","--redisIP",help="Redis computer IP address (gstt.LjayServerIP by default)",type=str)
argsparser.add_argument("-i","--iport",help="OSC port number to listen to (8001 by default)",type=int)
argsparser.add_argument("-o","--oport",help="OSC port number to send to (8002 by default)",type=int)
argsparser = argparse.ArgumentParser(description="LJ v0.8")
argsparser.add_argument("-r","--redisIP",help="IP address to bind builtin servers (OSC and websocket) also must be the Redis server IP ",type=str)
argsparser.add_argument("-L","--Lasers",help="Number of lasers connected.",type=int)
argsparser.add_argument("-v","--verbose",help="Debug mode 0,1 or 2.",type=int)
argsparser.add_argument("-x","--invx",help="Invert laser 0 X axis again",action="store_true")
argsparser.add_argument("-y","--invy",help="Invert laser 0 Y axis again",action="store_true")
argsparser.add_argument("-s","--set",help="Only for VJ version. Specify wich generator set to use (default is in gstt.py)",type=int)
argsparser.add_argument("-c","--curve",help="Only for VJ version. Specify with generator curve to use (default is in gstt.py)",type=int)
argsparser.add_argument("-d","--display",help="Point List number displayed in simulator",type=int)
argsparser.add_argument("-a","--align",help="Reset laser 0 alignement values",action="store_true")
argsparser.add_argument("-d","--display",help="Point List number displayed in pygame simulator",type=int)
argsparser.add_argument("-v","--verbose",help="Debug mode 0,1 or 2.",type=int)
argsparser.add_argument("-L","--Lasers",help="Number of lasers connected.",type=int)
argsparser.add_argument("-b","--bhoroscIP",help="Computer IP running bhorosc ('127.0.0.1' by default)",type=str)
argsparser.add_argument("-n","--nozoscIP",help="Computer IP running Nozosc ('127.0.0.1' by default)",type=str)
argsparser.add_argument("-i","--iport",help="port number for builtin LJ OSC server (8002 by default)",type=int)
argsparser.add_argument("-n","--nozoidIP",help="IP for llstr' Nozoid OSC server port 8003 ('127.0.0.1' by default)",type=str)
argsparser.add_argument("-b","--bhoroscIP",help="IP for OSC output ('127.0.0.1' by default)",type=str)
argsparser.add_argument("-o","--oport",help="OSC output port number (8001 by default)",type=int)
@ -98,15 +96,6 @@ def handle():
gstt.LjayServerIP = args.redisIP
# Set / Curves arguments
if args.set != None:
gstt.Set = args.set
print "Set : " + str(gstt.Set)
if args.curve != None:
gstt.Curve = args.curve
print "Curve : " + str(gstt.Curve)
# Point list number used by simulator
if args.display != None:
@ -115,9 +104,6 @@ def handle():
# Lasers = number of laser connected
if args.Lasers != None:
gstt.LaserNumber = args.Lasers
@ -128,8 +114,8 @@ def handle():
else:
gstt.oscIPin = '127.0.0.1'
if args.nozoscIP != None:
gstt.nozoscIP = args.nozoscIP
if args.nozoidIP != None:
gstt.nozoscIP = args.nozoidIP
else:
gstt.nozoscIP = '127.0.0.1'

View File

@ -7,7 +7,7 @@ LICENCE : CC
'''
import redis
import framy
import lj
import math
import time
import numpy as np
@ -34,21 +34,7 @@ observer_altitude = 30000
map_plane_altitude = 0.0
samparray = [0] * 100
vertices = [
(- 1.0, 1.0,- 1.0),
( 1.0, 1.0,- 1.0),
( 1.0,- 1.0,- 1.0),
(- 1.0,- 1.0,- 1.0),
(- 1.0, 1.0, 1.0),
( 1.0, 1.0, 1.0),
( 1.0,- 1.0, 1.0),
(- 1.0,- 1.0, 1.0)
]
# Define the vertices that compose each of the 6 faces. These numbers are
# indices to the vertices list defined above.
#faces = [(0,1,2,3),(1,5,6,2),(5,4,7,6),(4,0,3,7),(0,4,5,1),(3,2,6,7)]
faces = [(0,1,2,3),(1,5,6,2),(5,4,7,6),(4,0,3,7),(0,4,5,1),(3,2,6,7)]
def LeftShift(elevation):
@ -131,54 +117,7 @@ def Proj(x,y,z,angleX,angleY,angleZ):
def Draw2PL():
Shape = []
Left = []
Right = []
counter =0
while 1:
Shape = []
Left = []
Right = []
for fa in faces:
#print ""
#print "face",fa
for point in fa:
#print ""
#print "point ", point
x = vertices[point][0]
y = vertices[point][1]
z = vertices[point][2]
#print x,y,z
#print "left",x+LeftShift(z*25),y,z, Proj(x+LeftShift(z*25),y,z)
#print "right",x+RightShift(z*25),y,z, Proj(x+RightShift(z*25),y,z)
#Shape.append(Proj(x,y,z,0,0,counter))
Left.append( Proj(x+LeftShift(z*5),y,z,0,0,counter))
Right.append(Proj(x+RightShift(z*5),y,z,0,0,counter))
#framy.PolyLineOneColor(Shape, c = white, PL = 0, closed = False)
framy.PolyLineOneColor(Left, c = red, PL = 1, closed = False)
framy.PolyLineOneColor(Right, c = green, PL = 2, closed = False)
'''
framy.rPolyLineOneColor(Shape, c = white, PL = 0, closed = False, xpos = 200, ypos = 250, resize = 1.5, rotx =0, roty =0 , rotz=0)
framy.rPolyLineOneColor(Left, c = red, PL = 1, closed = False, xpos = 200, ypos = 250, resize = 1.5, rotx =0, roty =0 , rotz=0)
framy.rPolyLineOneColor(Right, c = blue, PL = 2, closed = False, xpos = 200, ypos = 250, resize = 1.5, rotx =0, roty =0 , rotz=0)
'''
#print framy.LinesPL(0)
#print framy.LinesPL(1)
#print framy.LinesPL(2)
#counter -= 1
#if counter >360:
# counter =0
def Draw1PL():
def DrawPL():
Shape = []
Left = []
@ -198,8 +137,8 @@ def Draw1PL():
Right.append(Proj(x+RightShift(z*25),step/yfactor,z,0,0,0))
x += 0.02
framy.rPolyLineOneColor(Left, c = red, PL = 0, closed = False, xpos = 0, ypos = 10, resize = 1.5, rotx =0, roty =0 , rotz=0)
framy.rPolyLineOneColor(Right, c = green, PL = 0, closed = False, xpos = 0, ypos = 10, resize = 1.5, rotx =0, roty =0 , rotz=0)
lj.rPolyLineOneColor(Left, c = red, PL = 0, closed = False, xpos = 0, ypos = 10, resize = 1.5, rotx =0, roty =0 , rotz=0)
lj.rPolyLineOneColor(Right, c = green, PL = 0, closed = False, xpos = 0, ypos = 10, resize = 1.5, rotx =0, roty =0 , rotz=0)
Left = []
Right = []
@ -211,8 +150,8 @@ def Draw1PL():
Right.append(Proj(x+RightShift(z*25),step/yfactor,z,0,0,0))
x += 0.02
framy.rPolyLineOneColor(Left, c = red, PL = 0, closed = False, xpos = 0, ypos = 25, resize = 1.5, rotx =0, roty =0 , rotz=0)
framy.rPolyLineOneColor(Right, c = green, PL = 0, closed = False, xpos = 0, ypos = 25, resize = 1.5, rotx =0, roty =0 , rotz=0)
lj.rPolyLineOneColor(Left, c = red, PL = 0, closed = False, xpos = 0, ypos = 25, resize = 1.5, rotx =0, roty =0 , rotz=0)
lj.rPolyLineOneColor(Right, c = green, PL = 0, closed = False, xpos = 0, ypos = 25, resize = 1.5, rotx =0, roty =0 , rotz=0)
Left = []
Right = []
@ -224,11 +163,11 @@ def Draw1PL():
Right.append(Proj(x+RightShift(z*25),step/yfactor,z,0,0,0))
x += 0.02
framy.rPolyLineOneColor(Left, c = red, PL = 0, closed = False, xpos = 0, ypos = 50, resize = 1.5, rotx =0, roty =0 , rotz=0)
framy.rPolyLineOneColor(Right, c = green, PL = 0, closed = False, xpos = 0, ypos = 50, resize = 1.5, rotx =0, roty =0 , rotz=0)
lj.rPolyLineOneColor(Left, c = red, PL = 0, closed = False, xpos = 0, ypos = 50, resize = 1.5, rotx =0, roty =0 , rotz=0)
lj.rPolyLineOneColor(Right, c = green, PL = 0, closed = False, xpos = 0, ypos = 50, resize = 1.5, rotx =0, roty =0 , rotz=0)
framy.LinesPL(0)
lj.DrawPL(0)
time.sleep(0.005)
white = rgb2int(255,255,255)
@ -240,4 +179,4 @@ y0 = ssine(100,5,-0.5)
y1 = ssine(100,5,0)
y2 = ssine(100,5,0.5)
Draw1PL()
DrawPL()

View File

@ -1,115 +0,0 @@
# coding=UTF-8
'''
LJay v0.8.0
LICENCE : CC
pclf, Sam Neurohack
'''
import math
import redis
redisIP = '127.0.0.1'
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
point_list = []
pl = [[],[],[],[]]
def LineTo(xy, c, PL):
pl[PL].append((xy + (c,)))
def Line(xy1, xy2, c, PL):
LineTo(xy1, 0, PL)
LineTo(xy2, c , PL)
def PolyLineOneColor(xy_list, c, PL , closed ):
#print "--"
#print "c",c
#print "xy_list",xy_list
#print "--"
xy0 = None
for xy in xy_list:
if xy0 is None:
xy0 = xy
#print "xy0:",xy0
LineTo(xy0,0, PL)
else:
#print "xy:",xy
LineTo(xy,c, PL)
if closed:
LineTo(xy0,c, PL)
# Computing points coordinates for rPolyline function from 3D and around 0,0 to pygame coordinates
def Pointransf(xy, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
x = xy[0] * resize
y = xy[1] * resize
z = 0
rad = rotx * math.pi / 180
cosaX = math.cos(rad)
sinaX = math.sin(rad)
y2 = y
y = y2 * cosaX - z * sinaX
z = y2 * sinaX + z * cosaX
rad = roty * math.pi / 180
cosaY = math.cos(rad)
sinaY = math.sin(rad)
z2 = z
z = z2 * cosaY - x * sinaY
x = z2 * sinaY + x * cosaY
rad = rotz * math.pi / 180
cosZ = math.cos(rad)
sinZ = math.sin(rad)
x2 = x
x = x2 * cosZ - y * sinZ
y = x2 * sinZ + y * cosZ
#print xy, (x + xpos,y+ ypos)
return (x + xpos,y+ ypos)
'''
to understand why it get negative Y
# 3D to 2D projection
factor = 4 * gstt.cc[22] / ((gstt.cc[21] * 8) + z)
print xy, (x * factor + xpos, - y * factor + ypos )
return (x * factor + xpos, - y * factor + ypos )
'''
# Send 2D point list around 0,0 with 3D rotation resizing and reposition around xpos ypos
#def rPolyLineOneColor(self, xy_list, c, PL , closed, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
def rPolyLineOneColor(xy_list, c, PL , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
xy0 = None
for xy in xy_list:
if xy0 is None:
xy0 = xy
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),0, PL)
else:
LineTo(Pointransf(xy, xpos, ypos, resize, rotx, roty, rotz),c, PL)
if closed:
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),c, PL)
# set all points for given laser. special behavior depends on GridDisplay flag
# 0: point list / 1: Grid
def LinesPL(PL):
#print '/pl/0/'+str(PL), str(pl[PL])
if r.set('/pl/0/'+str(PL), str(pl[PL])) == True:
pl[PL] = []
return True
else:
return False
def ResetPL(self, PL):
pl[PL] = []

View File

@ -0,0 +1,255 @@
"""
Directions Buttons defined correctly only for PS3 and USBJoystick
Represent various videogame controllers
TODO: Various play schemes/configs
XXX: UNTESTED
"""
import re
def setup_controls(joystick):
"""
Joystick wrapper.
"""
if re.search('playstation', joystick.get_name(), re.I):
return Ps3Controller(joystick)
elif re.search('X-box', joystick.get_name(), re.I):
return XboxController(joystick)
elif re.search('Saitek', joystick.get_name(), re.I):
return MySaitekController(joystick)
elif re.search('Thrustmaster dual analog 3.2', joystick.get_name(), re.I):
return MyThrustController(joystick)
elif re.search('2n1 USB', joystick.get_name(), re.I):
return CSLController(joystick)
elif re.search('Joystick', joystick.get_name(), re.I):
return USBController(joystick)
return Controller(joystick)
class Controller(object):
def __init__(self, joystick):
"""Pass a PyGame joystick instance."""
self.js = joystick
def getLeftHori(self):
return self.js.get_axis(2)
def getLeftVert(self):
return self.js.get_axis(3)
def getRightHori(self):
return self.js.get_axis(0)
def getRightVert(self):
return self.js.get_axis(1)
def getLeftTrigger(self):
return self.js.get_button(9)
def getRightTrigger(self):
return self.js.get_button(2)
class XboxController(Controller):
def __init__(self, joystick):
super(XboxController, self).__init__(joystick)
def getLeftHori(self):
return self.js.get_axis(0)
def getLeftVert(self):
return self.js.get_axis(1)
def getRightHori(self):
return self.js.get_axis(3)
def getRightVert(self):
return self.js.get_axis(4)
def getLeftTrigger(self):
return self.js.get_axis(2)
def getRightTrigger(self):
return self.js.get_button(11)
class Ps3Controller(Controller):
#up 4 _DOWN 6 left 7 right 5 croix 14 rond 13 triangle 12
def __init__(self, joystick):
super(Ps3Controller, self).__init__(joystick)
def getLeftHori(self):
return self.js.get_axis(0)
def getLeftVert(self):
return self.js.get_axis(1)
def getRightHori(self):
return self.js.get_axis(2)
def getRightVert(self):
return self.js.get_axis(3)
def getLeftTrigger(self):
# TODO: Verify
return self.js.get_button(8)
def getRightTrigger(self):
# TODO: Verify
return self.js.get_button(9)
def getUp(self):
return self.js.get_button(4)
def getDown(self):
return self.js.get_button(6)
def getLeft(self):
return self.js.get_button(7)
def getRight(self):
return self.js.get_button(5)
def getFire1(self):
return self.js.get_button(14)
def getFire2(self):
return self.js.get_button(13)
class MySaitekController(Controller):
def __init__(self, joystick):
super(MySaitekController, self).__init__(joystick)
def getLeftHori(self):
return self.js.get_axis(0)
def getLeftVert(self):
return self.js.get_axis(1)
def getRightHori(self):
return self.js.get_axis(3)
def getRightVert(self):
return self.js.get_axis(2)
def getLeftTrigger(self):
return self.js.get_button(6)
def getRightTrigger(self):
return self.js.get_button(7)
class MyThrustController(Controller):
def __init__(self, joystick):
super(MyThrustController, self).__init__(joystick)
def getLeftHori(self):
return self.js.get_axis(0)
def getLeftVert(self):
return self.js.get_axis(1)
def getRightHori(self):
return self.js.get_axis(2)
def getRightVert(self):
return self.js.get_axis(3)
def getLeftTrigger(self):
return self.js.get_button(5)
def getRightTrigger(self):
return self.js.get_button(7)
class CSLController(Controller):
def __init__(self, joystick):
super(CSLController, self).__init__(joystick)
def getLeftHori(self):
return self.js.get_axis(2)
def getLeftVert(self):
return self.js.get_axis(3)
def getRightHori(self):
return self.js.get_axis(0)
def getRightVert(self):
return self.js.get_axis(1)
def getLeftTrigger(self):
return self.js.get_button(6)
def getRightTrigger(self):
return self.js.get_button(7)
def getFire1(self):
return self.js.get_button(2)
def getFire2(self):
return self.js.get_button(1)
class USBController(Controller):
# my USB Joystick
#up axis 0 -1 DOWN axis 0 1 left axis 1 1 right axis 1 -1 bouton gauche 10 bouton droite 9
def __init__(self, joystick):
super(USBController, self).__init__(joystick)
def getUp(self):
if self.js.get_axis(0) == -1:
return 1
else:
return 0
def getDown(self):
if self.js.get_axis(0) > 0.9:
return 1
else:
return 0
def getLeft(self):
if self.js.get_axis(1) == 1:
return 1
else:
return 0
def getRight(self):
if self.js.get_axis(1) == -1:
return 1
else:
return 0
def getLeftTrigger(self):
return self.js.get_button(10)
def getRightTrigger(self):
return self.js.get_button(9)
def getFire1(self):
if self.js.get_button(10) == 1:
print "fire 1"
return self.js.get_button(10)
def getFire2(self):
if self.js.get_button(9) == 1:
print "fire 2"
return self.js.get_button(9)

View File

@ -0,0 +1,259 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
LJ Laser Pong entities
v0.1
Sam Neurohack
'''
# STDLIB
import math
import itertools
import sys
import os
import lj
import time
import random
screen_size = [800,600]
top_left = [200,100]
bottom_left = [200,300]
top_right = [600,100]
bottom_right = [600,300]
score_pos = [550,40]
score2_pos = [259,40]
# X Y position on bottom left of each paddle (="flips")
ball_origin = [400,300,200]
text_pos = [300,500,200]
BALL_acc = 0.06
PADDLE_height = 100
PADDLE_width = 10
PADDLE3D_height = 100
PADDLE3D_width = 100
FACT3D = 2
FLIPS_lorigin = [10,300,0]
FLIPS_rorigin = [780,300,400]
flips_attraction = 0.007
xy_center = [screen_size[0]/2,screen_size[1]/2]
DEFAULT_SPOKES = range(0,359,60)
DEFAULT_PLAYER_EXPLODE_COLOR = 0xFFFF00
DEFAULT_SIDE_COUNT = 6
DREARRANGE_SIDES = .02
CRASH_SHAKE_MAX = 6
TDN_CRASH = 200
GAME_FS_QUIT = -1
GAME_FS_MENU = 0
GAME_FS_PLAY = 1
GAME_FS_LAUNCH = 2
GAME_FS_GAMEOVER = 3
BUMPERS_COLOR_YELLOW = 0xFFFF00
BUMPERS_COLOR_RED = 0xFF0000
BUMPERS_COLOR_BLACK = 0x000000
BUMPERS_SIZE_X = 60
BUMPERS_SIZE_Y = 110
BUMPERS_FORCE = 1.1
BALL_SPEED = 5
BALL_MAX = 4
BALL_SIZE_X = 3
BALL_SIZE_Y = 3
LASER_ANGLE = 0
GRAVITY = 0.0001
NO_BGM = False
#NO_BGM = True
def rgb2int(r,g,b):
return int('0x%02x%02x%02x' % (r,g,b),0)
white = rgb2int(255,255,255)
red = rgb2int(255,0,0)
blue = rgb2int(0,0,255)
green = rgb2int(0,255,0)
LOGO = [
# L/o
[[(-140,-100),(-200,20),(40,20)],0xFF00],
# aser
[[(-140,-40),(-100,-40,),(-120,0),(-160,0),(-110,-20)],0xFFFF],
[[(-40,-40),(-60,-40),(-90,-20),(-50,-20),(-80,0),(-100,0)],0xFFFF],
[[(-30,-20),(10,-20),(0,-40),(-20,-40),(-30,-20),(-30,0),(-10,0)],0xFFFF],
[[(20,0),(40,-40),(35,-30),(50,-40),(70,-40)],0xFFFF],
# Pinball
[[(-185,50),(-145,50),(-130,20),(-170,20),(-200,80)],0xFFFF00], #P
[[(-80,40),(-120,40),(-140,80),(-100,80),(-80,40)],0xFFFF], #O
[[(-80,80),(-60,40),(-65,50),(-40,40),(-25,50),(-40,80)],0xFFFF], #N
[[(40,40),(0,40),(-20,80),(20,80),(30,60),(10,60)],0xFFFF], #G
]
LOGO_OFFSET_X = 460
LOGO_OFFSET_Y = 250
def LogoDraw():
'''
Dessine le logo
'''
for pl_color in LOGO:
c = pl_color[1]
xy_list = []
for xy in pl_color[0]:
xy_list.append((LOGO_OFFSET_X + xy[0], LOGO_OFFSET_Y + xy[1]))
#print xy_list
lj.PolyLineOneColor(xy_list, c,0, False)
FlipsLx, FlipsLy = FLIPS_lorigin[0], FLIPS_lorigin[1]
FlipsRx, FlipsRy = FLIPS_rorigin[0], FLIPS_rorigin[1]
FlipsSpeed = 7
def FlipsMove(left_key,right_key,up_key,down_key):
global FlipsLx, FlipsLy, FlipsRx, FlipsRy
if left_key:
FlipsLy -= FlipsSpeed
if FlipsLy < 1:
FlipsLy = 1
if right_key:
FlipsLy += FlipsSpeed
if FlipsLy > screen_size[1] - PADDLE_height:
FlipsLy = screen_size[1] - PADDLE_height
if up_key:
FlipsRy -= FlipsSpeed
if FlipsRy < 1:
FlipsRy = 1
if down_key:
FlipsRy += FlipsSpeed
if FlipsRy > screen_size[1] - PADDLE_height:
FlipsRy = screen_size[1] - PADDLE_height
return FlipsLy, FlipsRy
def FlipsMoveJoy(left_key,right_key,up_key,down_key,lvertax):
if left_key:
FlipsLy -= FlipsSpeed
if FlipsLy < 1:
FlipsLy = 1
if right_key:
FlipsLy += FlipsSpeed
if FlipsLy > screen_size[1] - PADDLE_height:
FlipsLy = screen_size[1] - PADDLE_height
if up_key:
FlipsRy -= FlipsSpeed
if FlipsRy < 1:
FlipsRy = 1
if down_key > 0.01:
FlipsRy += FlipsSpeed
if FlipsRy > screen_size[1] - PADDLE_height:
FlipsRy = screen_size[1] - PADDLE_height
if lvertax:
print lvertax
if lvertax < 0:
FlipsLy -= FlipsSpeed
if FlipsLy < 1:
FlipsLy = 1
elif lvertax > 0.01:
FlipsLy += FlipsSpeed
if FlipsLy > screen_size[1] - PADDLE_height:
FlipsLy = screen_size[1] - PADDLE_height
return FlipsLy, FlipsRy
def FlipsDraw():
lj.PolyLineOneColor([(FlipsLx,FlipsLy),(FlipsLx,FlipsLy + PADDLE_height),(FlipsLx + PADDLE_width , FlipsLy + PADDLE_height),(FlipsLx + PADDLE_width,FlipsLy)], white,0,True)
lj.PolyLineOneColor([(FlipsRx,FlipsRy),(FlipsRx,FlipsRy + PADDLE_height),(FlipsRx + PADDLE_width , FlipsRy + PADDLE_height),(FlipsRx + PADDLE_width,FlipsRy)], white,0,True)
def FiletDraw():
lj.PolyLineOneColor([(screen_size[0]/2,screen_size[1]),(screen_size[0]/2,0)], white, 0,True)
def Score1Draw(score):
#print "score1",score
lj.Text(str(score),white, 0, 350, 50, 1, 0, 0, 0)
def Score2Draw(score):
#print "score2",score
lj.Text(str(score),white, 0, 500, 50, 1, 0, 0, 0)
BallX, BallY = ball_origin[0], ball_origin[1]
BallZoom = 1
def BallMove(xcoord,ycoord):
global BallX,BallY
BallX = xcoord
BallY = ycoord
#print "ball move",xcoord,ycoord
#BallZoom = ?
if BallX < 0:
BallX = 0
elif BallX >= screen_size[0]:
BallX = screen_size[0]
if BallY < 0:
BallY = 0
elif BallY >= screen_size[1]:
BallY = screen_size[1]
def BallDraw():
global BallX,BallY
xmin = 0
xmax = BALL_SIZE_X * 2
ymin = 0
ymax = BALL_SIZE_Y * 2
xmin = (xmin*BallZoom)
ymin = (ymin*BallZoom)
xmax = (xmax*BallZoom)
ymax = (ymax*BallZoom)
xmin += BallX
xmax += BallX
ymin += BallY
ymax += BallY
#print "ball position",xmin,xmax,ymin,ymax
lj.PolyLineOneColor([(xmin,ymin),(xmin,ymax),(xmax,ymax),(xmax,ymin)], white,0,True)

17
clients/games/ljpong/gstt.py Executable file
View File

@ -0,0 +1,17 @@
# coding=UTF-8
'''
Etat global (anciennement singleton de la classe GameState + autres VARIABLES nécessaires partout)"
'''
from globalVars import *
# Etat global général
app_path = ""
# anciennement GameState
fs = GAME_FS_GAMEOVER
plyr = None
score = None
bmprs = None

310
clients/games/ljpong/lj.py Normal file
View File

@ -0,0 +1,310 @@
# coding=UTF-8
'''
LJ v0.8.0
Some LJ functions useful for python clients (was framy.py)
Config
PolyLineOneColor
rPolyLineOneColor
Text
sendlj : remote control
DrawPL
LICENCE : CC
Sam Neurohack
'''
import math
import redis
from OSC import OSCServer, OSCClient, OSCMessage
redisIP = '127.0.0.1'
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
ClientNumber = 0
point_list = []
pl = [[],[],[],[]]
'''
LJIP = "127.0.0.1"
osclientlj = OSCClient()
oscmsg = OSCMessage()
osclientlj.connect((redisIP, 8002))
'''
def sendlj(oscaddress,oscargs=''):
oscmsg = OSCMessage()
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
#print ("sending to bhorosc : ",oscmsg)
try:
osclientlj.sendto(oscmsg, (redisIP, 8002))
oscmsg.clearData()
except:
print ('Connection to LJ refused : died ?')
pass
#time.sleep(0.001
ASCII_GRAPHICS = [
#implementé
[(-50,30), (-30,-30), (30,-30), (10,30), (-50,30)], #0
[(-20,30), (0,-30), (-20,30)], #1
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], #2
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #3
[(30,10), (-30,10), (0,-30), (0,30)], #4
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], #5
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], #6
[(-30,-30), (30,-30), (-30,30)], #7
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], #8
[(30,0), (-30,0), (-30,-10), (0,-30), (30,-30), (30,10), (0,30), (-30,30)], #9
# A implementer
[(-30,10), (30,-10), (30,10), (0,30), (-30,10), (-30,-10), (0,-30), (30,-10)], #:
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], #;
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], #<
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #=
[(30,10), (-30,10), (0,-30), (0,30)], #>
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], #?
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], #@
# Implementé
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], #A
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], #A
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], #B
[(30,30), (-30,30), (-30,-30), (30,-30)], #C
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], #D
[(30,30), (-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], #E
[(-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], #F
[(0,0), (30,0), (30,30), (-30,30), (-30,-30),(30,-30)], #G
[(-30,-30), (-30,30), (-30,0), (30,0), (30,30), (30,-30)], #H
[(0,30), (0,-30)], #I
[(-30,30), (0,-30), (0,-30), (-30,-30), (30,-30)], #J
[(-30,-30), (-30,30), (-30,0), (30,-30), (-30,0), (30,30)], #K
[(30,30), (-30,30), (-30,-30)], #L
[(-30,30), (-30,-30), (0,0), (30,-30), (30,30)], #M
[(-30,30), (-30,-30), (30,30), (30,-30)], #N
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], #O
[(-30,0), (30,0), (30,-30), (-30,-30), (-30,30)], #P
[(30,30), (30,-30), (-30,-30), (-30,30), (30,30),(35,35)], #Q
[(-30,30), (-30,-30), (30,-30), (30,0), (-30,0), (30,30)], #R
[(30,-30), (-30,-30), (-30,0), (30,0), (30,30), (-30,30)], #S
[(0,30), (0,-30), (-30,-30), (30,-30)], #T
[(-30,-30), (-30,30), (30,30), (30,-30)], #U
[(-30,-30), (0,30), (30,-30)], #V
[(-30,-30), (-30,30), (0,0), (30,30), (30,-30)], #W
[(-30,30), (30,-30)], [(-30,-30), (30,30)], #X
[(0,30), (0,0), (30,-30), (0,0), (-30,-30)], #Y
[(30,30), (-30,30), (30,-30), (-30,-30)], #Z
# A implementer
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], #[
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], #\
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #]
[(30,10), (-30,10), (0,-30), (0,30)], #^
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], #_
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], #`
# Implementé
[(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], #a
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20), (-20,0), (20,0)], #b
[(20,20), (-20,20), (-20,-20), (20,-20)], #c
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], #d
[(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], #e
[(-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], #f
[(0,0), (20,0), (20,20), (-20,20), (-20,-20),(20,-20)], #g
[(-20,-20), (-20,20), (-20,0), (20,0), (20,20), (20,-20)], #H
[(0,20), (0,-20)], #I
[(-20,20), (0,-20), (0,-20), (-20,-20), (20,-20)], #J
[(-20,-20), (-20,20), (-20,0), (20,-20), (-20,0), (20,20)], #K
[(20,20), (-20,20), (-20,-20)], #L
[(-20,20), (-20,-20), (0,0), (20,-20), (20,20)], #M
[(-20,20), (-20,-20), (20,20), (20,-20)], #N
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], #O
[(-20,0), (20,0), (20,-20), (-20,-20), (-20,20)], #P
[(20,20), (20,-20), (-20,-20), (-20,20), (20,20),(25,25)], #Q
[(-20,20), (-20,-20), (20,-20), (20,0), (-20,0), (20,20)], #R
[(20,-20), (-20,-20), (-20,0), (20,0), (20,20), (-20,20)], #S
[(0,20), (0,-20), (-20,-20), (20,-20)], #T
[(-20,-20), (-20,20), (20,20), (20,-20)], #U
[(-20,-20), (0,20), (20,-20)], #V
[(-20,-20), (-20,20), (0,0), (20,20), (20,-20)], #W
[(-20,20), (20,-20)], [(-20,-20), (20,20)], #X
[(0,20), (0,0), (20,-20), (0,0), (-20,-20)], #Y
[(20,20), (-20,20), (20,-20), (-20,-20)], #Z
[(-2,15), (2,15)] # Point a la place de {
]
def Config(redisIP,client):
global ClientNumber
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
ClientNumber = client
#print "client configured",ClientNumber
def LineTo(xy, c, PL):
pl[PL].append((xy + (c,)))
def Line(xy1, xy2, c, PL):
LineTo(xy1, 0, PL)
LineTo(xy2, c , PL)
def PolyLineOneColor(xy_list, c, PL , closed ):
#print "--"
#print "c",c
#print "xy_list",xy_list
#print "--"
xy0 = None
for xy in xy_list:
if xy0 is None:
xy0 = xy
#print "xy0:",xy0
LineTo(xy0,0, PL)
LineTo(xy0,c, PL)
else:
#print "xy:",xy
LineTo(xy,c, PL)
if closed:
LineTo(xy0,c, PL)
# Computing points coordinates for rPolyline function from 3D and around 0,0 to pygame coordinates
def Pointransf(xy, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
x = xy[0] * resize
y = xy[1] * resize
z = 0
rad = math.radians(rotx)
cosaX = math.cos(rad)
sinaX = math.sin(rad)
y2 = y
y = y2 * cosaX - z * sinaX
z = y2 * sinaX + z * cosaX
rad = math.radians(roty)
cosaY = math.cos(rad)
sinaY = math.sin(rad)
z2 = z
z = z2 * cosaY - x * sinaY
x = z2 * sinaY + x * cosaY
rad = math.radians(rotz)
cosZ = math.cos(rad)
sinZ = math.sin(rad)
x2 = x
x = x2 * cosZ - y * sinZ
y = x2 * sinZ + y * cosZ
#print xy, (x + xpos,y+ ypos)
return (x + xpos,y+ ypos)
'''
to understand why it get negative Y
# 3D to 2D projection
factor = 4 * gstt.cc[22] / ((gstt.cc[21] * 8) + z)
print xy, (x * factor + xpos, - y * factor + ypos )
return (x * factor + xpos, - y * factor + ypos )
'''
# Send 2D point list around 0,0 with 3D rotation resizing and reposition around xpos ypos
#def rPolyLineOneColor(self, xy_list, c, PL , closed, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
def rPolyLineOneColor(xy_list, c, PL , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
xy0 = None
for xy in xy_list:
if xy0 is None:
xy0 = xy
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),0, PL)
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),c, PL)
else:
LineTo(Pointransf(xy, xpos, ypos, resize, rotx, roty, rotz),c, PL)
if closed:
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),c, PL)
def LinesPL(PL):
print "Stupido !! your code is to old : use DrawPL() instead of LinesPL()"
DrawPL(PL)
def DrawPL(PL):
#print '/pl/0/'+str(PL), str(pl[PL])
if r.set('/pl/'+str(ClientNumber)+'/'+str(PL), str(pl[PL])) == True:
#print '/pl/'+str(ClientNumber)+'/'+str(PL), str(pl[PL])
pl[PL] = []
return True
else:
return False
def ResetPL(self, PL):
pl[PL] = []
def DigitsDots(number,color):
dots =[]
for dot in ASCII_GRAPHICS[number]:
#print dot
dots.append((gstt.xy_center[0]+dot[0],gstt.xy_center[1]+dot[1],color))
#self.point_list.append((xy + (c,)))
return dots
def CharDots(char,color):
dots =[]
for dot in ASCII_GRAPHICS[ord(char)-46]:
dots.append((dot[0],dot[1],color))
return dots
def Text(message,c, PL, xpos, ypos, resize, rotx, roty, rotz):
dots =[]
l = len(message)
i= 0
#print message
for ch in message:
#print ""
# texte centre en x automatiquement selon le nombre de lettres l
x_offset = 26 * (- (0.9*l) + 3*i)
# Digits
if ord(ch)<58:
char_pl_list = ASCII_GRAPHICS[ord(ch) - 48]
else:
char_pl_list = ASCII_GRAPHICS[ord(ch) - 46]
char_draw = []
#dots.append((char_pl_list[0][0] + x_offset,char_pl_list[0][1],0))
for xy in char_pl_list:
char_draw.append((xy[0] + x_offset,xy[1],c))
i +=1
#print ch,char_pl_list,char_draw
rPolyLineOneColor(char_draw, c, PL , False, xpos, ypos, resize, rotx, roty, rotz)
#dots.append(char_draw)

367
clients/games/ljpong/main.py Executable file
View File

@ -0,0 +1,367 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
LJ Laser Pong v0.8
Sam Neurohack
'''
import pygame
import math
import itertools
import sys
import os
'''
is_py2 = sys.version[0] == '2'
if is_py2:
from Queue import Queue
else:
from queue import Queue
'''
import thread
import time
import random
import lj
import entities
from controller import setup_controls
import argparse
score = None
screen_size = [800,600]
top_left = [200,100]
bottom_left = [200,300]
top_right = [600,100]
bottom_right = [600,300]
score_pos = [550,40]
score2_pos = [259,40]
text_pos = [300,500,200]
ball_origin = [400,300,200]
BALL_SPEED = 5
BALL_SIZE_X = 3
BALL_SIZE_Y = 3
BALL_acc = 0.06
PADDLE_height = 100
PADDLE_width = 10
FlipsSpeed = 7
FLIPS_lorigin = [10,300,0]
FLIPS_rorigin = [780,300,400]
FlipsLx, FlipsLy = FLIPS_lorigin[0], FLIPS_lorigin[1]
FlipsRx, FlipsRy = FLIPS_rorigin[0], FLIPS_rorigin[1]
xy_center = [screen_size[0]/2,screen_size[1]/2]
GAME_FS_QUIT = -1
GAME_FS_MENU = 0
GAME_FS_PLAY = 1
GAME_FS_GAMEOVER = 2
GAME_FS_LAUNCH = 2
SCORE_ZOOM_PLAYING = 1.6
SCORE_ZOOM_GAMEOVER = 5.0
SCORE_DZOOM_PLAYING = -0.4
SCORE_DZOOM_GAMEOVER = 0.1
Score1Zoom = SCORE_ZOOM_PLAYING
GRAVITY = 0.0001
fs = GAME_FS_MENU
def rgb2int(r,g,b):
return int('0x%02x%02x%02x' % (r,g,b),0)
white = rgb2int(255,255,255)
red = rgb2int(255,0,0)
blue = rgb2int(0,0,255)
green = rgb2int(0,255,0)
print ("")
print ("Arguments parsing if needed...")
argsparser = argparse.ArgumentParser(description="Laserpong")
argsparser.add_argument("-r","--redisIP",help="IP of the Redis server used by LJ (127.0.0.1 by default) ",type=str)
argsparser.add_argument("-c","--client",help="LJ client number (0 by default)",type=int)
argsparser.add_argument("-l","--laser",help="Laser number to be displayed (0 by default)",type=int)
args = argsparser.parse_args()
if args.client:
ljclient = args.client
else:
ljclient = 0
if args.laser:
plnumber = args.laser
else:
plnumber = 0
# Redis Computer IP
if args.redisIP != None:
redisIP = args.redisIP
else:
redisIP = '127.0.0.1'
lj.Config(redisIP,ljclient)
def StartPlaying(first_time = False):
global fs
lscore = 0
rscore = 0
fs = GAME_FS_LAUNCH
x = ball_origin[0]
y = ball_origin[1]
app_path = os.path.dirname(os.path.realpath(__file__))
pygame.init()
#sounds.InitSounds()
clock = pygame.time.Clock()
Nbpads = pygame.joystick.get_count()
print ("Joypads : ", str(Nbpads))
if Nbpads != 2:
print ('')
print ('')
print ("THIS VERSION NEEDS 2 PADS. PLEASE CONNECT THEM.")
print ('')
sys.exit()
if Nbpads > 1:
pad2 = pygame.joystick.Joystick(1)
pad2.init()
print "Pad2 :", pad2.get_name()
numButtons = pad2.get_numbuttons()
#print ("Axis Pad 2 :", str(pad2.get_numaxes()))
#print ("Buttons Pad 2 :" , str(numButtons))
# joy is pad abstraction to handle many different devices.
joy2 = setup_controls(pad2)
if Nbpads > 0:
pad1 = pygame.joystick.Joystick(0)
pad1.init()
print "Pad1 :",pad1.get_name()
numButtons = pad1.get_numbuttons()
joy1 = setup_controls(pad1)
#print ("Axis Pad 1 :", str(pad1.get_numaxes()))
#print ("Buttons Pad 1 :" , str(numButtons))
update_screen = False
xvel = - 1
yvel = 0
lscore = 0
rscore = 0
ly = FLIPS_lorigin[1]
ry = FLIPS_rorigin[1]
flipsy = [ly, ry]
stick = 0
x = ball_origin[0]
y = ball_origin[1]
keystates = pygame.key.get_pressed()
while fs != GAME_FS_QUIT:
for event in pygame.event.get():
if event.type == pygame.QUIT:
fs = GAME_FS_QUIT
keystates_prev = keystates[:]
keystates = pygame.key.get_pressed()[:]
# Etats du jeu
if fs == GAME_FS_MENU:
if keystates[pygame.K_ESCAPE] and not keystates_prev[pygame.K_ESCAPE]:
fs = GAME_FS_QUIT
elif keystates[pygame.K_SPACE] and not keystates_prev[pygame.K_SPACE]:
StartPlaying(True)
lscore = 0
rscore = 0
if joy1.getFire1() or joy2.getFire1():
StartPlaying(False)
lscore =0
rscore = 0
elif fs == GAME_FS_PLAY:
if keystates[pygame.K_ESCAPE] and not keystates_prev[pygame.K_ESCAPE]:
fs = GAME_FS_MENU
'''
if Nbpads > 0:
print "pad 1 :", joy1.getUp(), joy1.getDown(), joy1.getLeftTrigger(),joy1.getRightTrigger()
print "pad 2 :", joy2.getUp(), joy2.getDown(), joy2.getLeftTrigger(),joy2.getRightTrigger()
'''
# Lost ball / first to ten points ?
#print " ball : " , x, y, " left : ", ly, " right : ", ry
if x < FLIPS_lorigin[0] + PADDLE_width:
print ("ball.y : ", y, " ly : ", ly)
if y > (ly + PADDLE_height + 1) or y < (ly - BALL_SIZE_Y - 1):
rscore += 1
xvel = random.uniform(-1,-0.6)
if rscore == 11:
fs = GAME_FS_MENU
else:
fs = GAME_FS_LAUNCH
else:
x = FLIPS_lorigin[0] + PADDLE_width
xvel *= -1
if x > FLIPS_rorigin[0] - PADDLE_width:
print ("ball.y : ", y, " ry : ", ry)
if y < (ry - BALL_SIZE_Y - 1) or y > (ry + PADDLE_height + 1):
lscore += 1
xvel = random.uniform(1,0.6)
if lscore == 11:
fs = GAME_FS_MENU
else:
fs = GAME_FS_LAUNCH
else:
xvel *= -1
x = FLIPS_rorigin[0] - PADDLE_width
# wall detect
if y < 0:
y = 1
yvel *= -1
if y > screen_size[1]:
y = screen_size[1] - 1
yvel *= -1
# Anim
x += BALL_SPEED * xvel
y += BALL_SPEED * yvel
yvel += GRAVITY
entities.BallMove(x,y)
if Nbpads > 0:
flipsy = entities.FlipsMove(joy1.getUp(),joy1.getDown(),joy2.getUp(),joy2.getDown())
else:
flipsy = entities.FlipsMove(keystates[pygame.K_a],keystates[pygame.K_q],keystates[pygame.K_UP],keystates[pygame.K_DOWN])
ly = flipsy[0]
ry = flipsy[1]
elif fs == GAME_FS_LAUNCH:
'''
if Nbpads > 0:
print "pad 1 :", joy1.getUp(), joy1.getDown(), joy1.getLeftTrigger(),joy1.getRightTrigger()
print "pad 2 :", joy2.getUp(), joy2.getDown(), joy2.getLeftTrigger(),joy2.getRightTrigger()
print pad1.get_axis(0),pad2.get_axis(0)
'''
if keystates[pygame.K_ESCAPE] and not keystates_prev[pygame.K_ESCAPE]:
fs = GAME_FS_MENU
if keystates[pygame.K_SPACE] and not keystates_prev[pygame.K_SPACE]:
fs = GAME_FS_PLAY
yvel = 0
while math.fabs(xvel + yvel) < 1:
#xvel = random.uniform(-1,1)
yvel = random.uniform(-1,1)
if joy1.getFire1() or joy2.getFire1():
fs = GAME_FS_PLAY
yvel = 0
while math.fabs(xvel + yvel) < 1:
#xvel = random.uniform(-1,1)
yvel = random.uniform(-1,1)
x = ball_origin[0]
y = ball_origin[1]
entities.BallMove(x,y)
if Nbpads > 0:
flipsy = entities.FlipsMove(joy1.getUp(),joy1.getDown(),joy2.getUp(),joy2.getDown())
else:
flipsy = entities.FlipsMove(keystates[pygame.K_a],keystates[pygame.K_q],keystates[pygame.K_UP],keystates[pygame.K_DOWN])
ly = flipsy[0]
ry = flipsy[1]
elif fs == GAME_FS_GAMEOVER:
#TODO : MODE GAME OVER, autres opérations d'animation
# Remarque : on peut supprimer le mode GAME OVER et le gérer dans le mode jeu
# si les traitements sont les mêmes
'''
if keystates[pygame.K_SPACE] and not keystates_prev[pygame.K_SPACE]:
StartPlaying(False)
'''
if joy1.getFire1() or joy2.getFire1():
StartPlaying(False)
elif keystates[pygame.K_ESCAPE] and not keystates_prev[pygame.K_ESCAPE]:
fs = GAME_FS_MENU
# Peut-être aussi réinitialiser l'état dans le mode menu
if fs == GAME_FS_PLAY or fs == GAME_FS_GAMEOVER or fs == GAME_FS_LAUNCH:
entities.Score1Draw(lscore)
entities.Score2Draw(rscore)
entities.FlipsDraw()
entities.BallDraw()
entities.FiletDraw()
lj.DrawPL(0)
if fs == GAME_FS_MENU:
entities.LogoDraw()
lj.DrawPL(0)
# TODO : rendre indépendante la fréquence de rafraîchissement de l'écran par
# rapport à celle de l'animation du jeu
clock.tick(100)
pygame.quit()

76
clients/games/ljpong/vectors.py Executable file
View File

@ -0,0 +1,76 @@
# coding=UTF-8
'''
Created on 13 nov. 2014
@author: pclf
'''
import math
class Polar2D(object):
'''
classdocs
'''
def __init__(self, r, theta):
'''
Constructor
'''
self.r = r
self.theta = theta
def Rotate(self, theta):
return Polar2D(self.r, self.theta + theta)
def RotateSelf(self, theta):
self.theta += theta
def Zoom(self, r):
return Polar2D(self.r * r, self.theta)
def ZoomSelf(self, r):
self.r *= r
def RotateZoom(self, r, theta):
return Polar2D(self.r * r, self.theta + theta)
def RotateZoomSelf(self, r, theta):
self.r *= r
self.theta += theta
def ToXY(self):
theta_rd = math.radians(self.theta)
return Vector2D(self.r * math.sin(theta_rd), - self.r * math.cos(theta_rd))
class Vector2D(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector2D(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector2D(self.x - other.x, self.y - other.y)
# __iadd__ et __isub__ si nécessaire
def __mul__(self, k):
return Vector2D(self.x * k, self.y * k)
def __div__(self, k):
return Vector2D(self.x / k, self.y / k)
def ScalarProduct(self, v):
return self.x*v.x + self.y*v.y
def Det(self, v):
return self.x*v.y - self.y*v.x
def MatrixProduct(self, vx, vy):
return Vector2D(self.ScalarProduct(vx),self.ScalarProduct(vy))
def ToTuple(self):
return (self.x,self.y)

View File

@ -1,19 +1,47 @@
# coding=UTF-8
'''
Anaglyphed cube
Anaglyphed rotating cube (for red and green glasses)
This client uses the drawing functions (polyline) provided by LJ in lj.py
You must check in lj.py if the redis server IP is correct.
LICENCE : CC
'''
import redis
import framy
import lj
import math
import time
import argparse
# IP defined in /etd/redis/redis.conf
print ("")
print ("Arguments parsing if needed...")
argsparser = argparse.ArgumentParser(description="Text Cycling for LJ")
argsparser.add_argument("-r","--redisIP",help="IP of the Redis server used by LJ (127.0.0.1 by default) ",type=str)
argsparser.add_argument("-c","--client",help="LJ client number (0 by default)",type=int)
argsparser.add_argument("-l","--laser",help="Laser number to be displayed (0 by default)",type=int)
args = argsparser.parse_args()
if args.client:
ljclient = args.client
else:
ljclient = 0
if args.laser:
plnumber = args.laser
else:
plnumber = 0
# Redis Computer IP
if args.redisIP != None:
redisIP = args.redisIP
else:
redisIP = '127.0.0.1'
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
lj.Config(redisIP,ljclient)
width = 800
@ -21,18 +49,22 @@ height = 600
centerX = width / 2
centerY = height / 2
# 3D to 2D projection parameters
fov = 256
viewer_distance = 2.2
# Anaglyph computation parameters for right and left eyes.
eye_spacing = 100
nadir = 0.5
observer_altitude = 30000
#observer_altitude = 10000
# elevation = z coordinate
# 0.0 or -2000 pop out)
# 0.0, -2000 pop out
map_plane_altitude = 0.0
# Cube coordinates
# Define the vertices that compose each of the 6 faces.
vertices = [
(- 1.0, 1.0,- 1.0),
( 1.0, 1.0,- 1.0),
@ -43,11 +75,10 @@ vertices = [
( 1.0,- 1.0, 1.0),
(- 1.0,- 1.0, 1.0)
]
# Define the vertices that compose each of the 6 faces. These numbers are
# indices to the vertices list defined above.
faces = [(0,1,2,3),(0,4,5,1),(1,5,6,2),(2,3,7,6),(6,5,4,7),(7,3,0,4)]
def LeftShift(elevation):
diff = elevation - map_plane_altitude
@ -93,17 +124,15 @@ def Proj(x,y,z,angleX,angleY,angleZ):
y = - y * factor + centerY
return (x,y)
def Run():
def Draw2PL():
Shape = []
Left = []
Right = []
counter =0
while 1:
Shape = []
Left = []
Right = []
@ -111,101 +140,44 @@ def Draw2PL():
y = vertices[0][1]
z = vertices[0][2]
Left.append( Proj(x+LeftShift(z*5),y,z,0,0,counter))
Right.append(Proj(x+RightShift(z*5),y,z,0,0,counter))
#framy.PolyLineOneColor(Shape, c = white, PL = 0, closed = False)
framy.PolyLineOneColor(Left, c = red, PL = 1, closed = False)
framy.PolyLineOneColor(Right, c = green, PL = 2, closed = False)
for fa in faces:
#print ""
#print "face",fa
for point in fa:
#print ""
#print "point ", point
x = vertices[point][0]
y = vertices[point][1]
z = vertices[point][2]
#print x,y,z
#print "left",x+LeftShift(z*25),y,z, Proj(x+LeftShift(z*25),y,z)
#print "right",x+RightShift(z*25),y,z, Proj(x+RightShift(z*25),y,z)
#Shape.append(Proj(x,y,z,0,0,counter))
Left.append( Proj(x+LeftShift(z*5),y,z,0,0,counter))
Right.append(Proj(x+RightShift(z*5),y,z,0,0,counter))
#framy.PolyLineOneColor(Shape, c = white, PL = 0, closed = False)
framy.PolyLineOneColor(Left, c = red, PL = 1, closed = False)
framy.PolyLineOneColor(Right, c = green, PL = 2, closed = False)
'''
framy.rPolyLineOneColor(Shape, c = white, PL = 0, closed = False, xpos = 200, ypos = 250, resize = 1, rotx =0, roty =0 , rotz=0)
framy.rPolyLineOneColor(Left, c = red, PL = 1, closed = False, xpos = 200, ypos = 250, resize = 1, rotx =0, roty =0 , rotz=0)
framy.rPolyLineOneColor(Right, c = blue, PL = 2, closed = False, xpos = 200, ypos = 250, resize = 1, rotx =0, roty =0 , rotz=0)
'''
#counter += 1
#if counter >360:
# counter =0
def Draw1PL():
Shape = []
Left = []
Right = []
counter =0
while 1:
#Shape = []
Left = []
Right = []
# Polyline will "move" the laser to this first point in black, then move to the next with second point color.
# The cube start always with vertice 0
# LJ tracers will "move" the laser to this first point in black, then move to the next with second point color.
# For more accuracy in dac emulator, repeat this first point.
# Here the cube start always with vertice 0
x = vertices[0][0]
y = vertices[0][1]
z = vertices[0][2]
# Cube Y axis rotation of 'counter' angle and 3d-2d Proj function.
#Left.append( Proj(x+LeftShift(z*5),y,z,0,counter,0))
#Right.append(Proj(x+RightShift(z*5),y,z,0,counter,0))
Left.append( Proj(x+LeftShift(z*5),y,z,0,counter,0))
Right.append(Proj(x+RightShift(z*5),y,z,0,counter,0))
# Add all the cube points face by face.
for fa in faces:
#print ""
#print "face",fa
for point in fa:
#print ""
#print "point ", point
x = vertices[point][0]
y = vertices[point][1]
z = vertices[point][2]
#print x,y,z,counter
#if point == 0:
# print Proj(x+LeftShift(z*5),y,z,0,0,counter)
#print "left", Proj(x+LeftShift(z*25),y,z,0,counter,0)
#print "right",x+RightShift(z*25),y,z, Proj(x+RightShift(z*25),y,z)
#Shape.append(Proj(x,y,z,0,0,counter))
Left.append( Proj(x+LeftShift(z*25),y,z,0,counter,0))
Right.append(Proj(x+RightShift(z*25),y,z,0,counter,0))
#framy.PolyLineOneColor(Shape, c = white, PL = 0, closed = False)
#print Left
framy.PolyLineOneColor(Left, c = red, PL = 0, closed = True)
framy.PolyLineOneColor(Right, c = green, PL = 0, closed = True)
# Drawing step, 2 possibilities
# Red and Green drawn by laser 0
lj.PolyLineOneColor(Left, c = red, PL = 0, closed = True)
lj.PolyLineOneColor(Right, c = green, PL = 0, closed = True)
lj.DrawPL(0)
'''
framy.rPolyLineOneColor(Shape, c = white, PL = 0, closed = False, xpos = 200, ypos = 250, resize = 1, rotx =0, roty =0 , rotz=0)
framy.rPolyLineOneColor(Left, c = red, PL = 1, closed = False, xpos = 200, ypos = 250, resize = 1, rotx =0, roty =0 , rotz=0)
framy.rPolyLineOneColor(Right, c = blue, PL = 2, closed = False, xpos = 200, ypos = 250, resize = 1, rotx =0, roty =0 , rotz=0)
# Red on laser 1 and green on laser 2
lj.PolyLineOneColor(Left, c = red, PL = 1, closed = True)
lj.PolyLineOneColor(Right, c = green, PL = 2, closed = True)
lj.DrawPL(1)
lj.DrawPL(2)
'''
framy.LinesPL(0)
time.sleep(0.1)
counter += 1
if counter >360:
counter =0
@ -216,20 +188,4 @@ blue = rgb2int(0,0,255)
green = rgb2int(0,255,0)
Draw1PL()
#r.set('/pl/0/0', str(pl0))
# S = (e / 2) (d - p) / (a - d)
'''
# /pl/clientnumber/lasernumber pointlist
# Consider you're client 0
# Send to laser 0 (see mainy.conf)
r.set('/pl/0/0', str(pl0))
# Send to laser 1 (see mainy.conf)
r.set('/pl/0/1', str(pl1))
# Send to laser 2 (see mainy.conf)
r.set('/pl/0/2', str(pl1))
'''
Run()

314
clients/lj.py Normal file
View File

@ -0,0 +1,314 @@
# coding=UTF-8
'''
LJ v0.8.1
Some LJ functions useful for python clients (was framy.py)
Config(redisIP, client number)
PolyLineOneColor
rPolyLineOneColor
Text(word, color, PL, xpos, ypos, resize, rotx, roty, rotz) : Display a word
Send(adress,message) : remote control. See commands.py
WebStatus(message) : display message on webui
DrawPL(point list number) : once you stacked all wanted elements, like 2 polylines, send them to lasers.
LICENCE : CC
Sam Neurohack
'''
import math
import redis
from OSC import OSCServer, OSCClient, OSCMessage
redisIP = '127.0.0.1'
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
ClientNumber = 0
point_list = []
pl = [[],[],[],[]]
'''
LJIP = "127.0.0.1"
osclientlj = OSCClient()
oscmsg = OSCMessage()
osclientlj.connect((redisIP, 8002))
'''
def Send(oscaddress,oscargs=''):
oscmsg = OSCMessage()
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
#print ("sending to bhorosc : ",oscmsg)
try:
osclientlj.sendto(oscmsg, (redisIP, 8002))
oscmsg.clearData()
except:
print ('Connection to LJ refused : died ?')
pass
#time.sleep(0.001
def WebStatus(message):
Send("/status",message)
ASCII_GRAPHICS = [
#implementé
[(-50,30), (-30,-30), (30,-30), (10,30), (-50,30)], #0
[(-20,30), (0,-30), (-20,30)], #1
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], #2
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #3
[(30,10), (-30,10), (0,-30), (0,30)], #4
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], #5
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], #6
[(-30,-30), (30,-30), (-30,30)], #7
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], #8
[(30,0), (-30,0), (-30,-10), (0,-30), (30,-30), (30,10), (0,30), (-30,30)], #9
# A implementer
[(-30,10), (30,-10), (30,10), (0,30), (-30,10), (-30,-10), (0,-30), (30,-10)], #:
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], #;
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], #<
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #=
[(30,10), (-30,10), (0,-30), (0,30)], #>
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], #?
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], #@
# Implementé
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], #A
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], #A
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], #B
[(30,30), (-30,30), (-30,-30), (30,-30)], #C
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], #D
[(30,30), (-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], #E
[(-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], #F
[(0,0), (30,0), (30,30), (-30,30), (-30,-30),(30,-30)], #G
[(-30,-30), (-30,30), (-30,0), (30,0), (30,30), (30,-30)], #H
[(0,30), (0,-30)], #I
[(-30,30), (0,-30), (0,-30), (-30,-30), (30,-30)], #J
[(-30,-30), (-30,30), (-30,0), (30,-30), (-30,0), (30,30)], #K
[(30,30), (-30,30), (-30,-30)], #L
[(-30,30), (-30,-30), (0,0), (30,-30), (30,30)], #M
[(-30,30), (-30,-30), (30,30), (30,-30)], #N
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], #O
[(-30,0), (30,0), (30,-30), (-30,-30), (-30,30)], #P
[(30,30), (30,-30), (-30,-30), (-30,30), (30,30),(35,35)], #Q
[(-30,30), (-30,-30), (30,-30), (30,0), (-30,0), (30,30)], #R
[(30,-30), (-30,-30), (-30,0), (30,0), (30,30), (-30,30)], #S
[(0,30), (0,-30), (-30,-30), (30,-30)], #T
[(-30,-30), (-30,30), (30,30), (30,-30)], #U
[(-30,-30), (0,30), (30,-30)], #V
[(-30,-30), (-30,30), (0,0), (30,30), (30,-30)], #W
[(-30,30), (30,-30)], [(-30,-30), (30,30)], #X
[(0,30), (0,0), (30,-30), (0,0), (-30,-30)], #Y
[(30,30), (-30,30), (30,-30), (-30,-30)], #Z
# A implementer
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], #[
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], #\
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #]
[(30,10), (-30,10), (0,-30), (0,30)], #^
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], #_
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], #`
# Implementé
[(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], #a
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20), (-20,0), (20,0)], #b
[(20,20), (-20,20), (-20,-20), (20,-20)], #c
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], #d
[(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], #e
[(-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], #f
[(0,0), (20,0), (20,20), (-20,20), (-20,-20),(20,-20)], #g
[(-20,-20), (-20,20), (-20,0), (20,0), (20,20), (20,-20)], #H
[(0,20), (0,-20)], #I
[(-20,20), (0,-20), (0,-20), (-20,-20), (20,-20)], #J
[(-20,-20), (-20,20), (-20,0), (20,-20), (-20,0), (20,20)], #K
[(20,20), (-20,20), (-20,-20)], #L
[(-20,20), (-20,-20), (0,0), (20,-20), (20,20)], #M
[(-20,20), (-20,-20), (20,20), (20,-20)], #N
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], #O
[(-20,0), (20,0), (20,-20), (-20,-20), (-20,20)], #P
[(20,20), (20,-20), (-20,-20), (-20,20), (20,20),(25,25)], #Q
[(-20,20), (-20,-20), (20,-20), (20,0), (-20,0), (20,20)], #R
[(20,-20), (-20,-20), (-20,0), (20,0), (20,20), (-20,20)], #S
[(0,20), (0,-20), (-20,-20), (20,-20)], #T
[(-20,-20), (-20,20), (20,20), (20,-20)], #U
[(-20,-20), (0,20), (20,-20)], #V
[(-20,-20), (-20,20), (0,0), (20,20), (20,-20)], #W
[(-20,20), (20,-20)], [(-20,-20), (20,20)], #X
[(0,20), (0,0), (20,-20), (0,0), (-20,-20)], #Y
[(20,20), (-20,20), (20,-20), (-20,-20)], #Z
[(-2,15), (2,15)] # Point a la place de {
]
def Config(redisIP,client):
global ClientNumber
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
ClientNumber = client
def LineTo(xy, c, PL):
pl[PL].append((xy + (c,)))
def Line(xy1, xy2, c, PL):
LineTo(xy1, 0, PL)
LineTo(xy2, c , PL)
def PolyLineOneColor(xy_list, c, PL , closed ):
#print "--"
#print "c",c
#print "xy_list",xy_list
#print "--"
xy0 = None
for xy in xy_list:
if xy0 is None:
xy0 = xy
#print "xy0:",xy0
LineTo(xy0,0, PL)
LineTo(xy0,c, PL)
else:
#print "xy:",xy
LineTo(xy,c, PL)
if closed:
LineTo(xy0,c, PL)
# Computing points coordinates for rPolyline function from 3D and around 0,0 to pygame coordinates
def Pointransf(xy, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
x = xy[0] * resize
y = xy[1] * resize
z = 0
rad = rotx * math.pi / 180
cosaX = math.cos(rad)
sinaX = math.sin(rad)
y2 = y
y = y2 * cosaX - z * sinaX
z = y2 * sinaX + z * cosaX
rad = roty * math.pi / 180
cosaY = math.cos(rad)
sinaY = math.sin(rad)
z2 = z
z = z2 * cosaY - x * sinaY
x = z2 * sinaY + x * cosaY
rad = rotz * math.pi / 180
cosZ = math.cos(rad)
sinZ = math.sin(rad)
x2 = x
x = x2 * cosZ - y * sinZ
y = x2 * sinZ + y * cosZ
#print xy, (x + xpos,y+ ypos)
return (x + xpos,y+ ypos)
'''
to understand why it get negative Y
# 3D to 2D projection
factor = 4 * gstt.cc[22] / ((gstt.cc[21] * 8) + z)
print xy, (x * factor + xpos, - y * factor + ypos )
return (x * factor + xpos, - y * factor + ypos )
'''
# Send 2D point list around 0,0 with 3D rotation resizing and reposition around xpos ypos
#def rPolyLineOneColor(self, xy_list, c, PL , closed, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
def rPolyLineOneColor(xy_list, c, PL , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
xy0 = None
for xy in xy_list:
if xy0 is None:
xy0 = xy
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),0, PL)
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),c, PL)
else:
LineTo(Pointransf(xy, xpos, ypos, resize, rotx, roty, rotz),c, PL)
if closed:
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),c, PL)
def LinesPL(PL):
print "Stupido !! your code is to old : use DrawPL() instead of LinesPL()"
DrawPL(PL)
def DrawPL(PL):
#print '/pl/0/'+str(PL), str(pl[PL])
if r.set('/pl/'+str(ClientNumber)+'/'+str(PL), str(pl[PL])) == True:
pl[PL] = []
return True
else:
return False
def ResetPL(self, PL):
pl[PL] = []
def DigitsDots(number,color):
dots =[]
for dot in ASCII_GRAPHICS[number]:
#print dot
dots.append((gstt.xy_center[0]+dot[0],gstt.xy_center[1]+dot[1],color))
#self.point_list.append((xy + (c,)))
return dots
def CharDots(char,color):
dots =[]
for dot in ASCII_GRAPHICS[ord(char)-46]:
dots.append((dot[0],dot[1],color))
return dots
def Text(message,c, PL, xpos, ypos, resize, rotx, roty, rotz):
dots =[]
l = len(message)
i= 0
#print message
for ch in message:
#print ""
# texte centre en x automatiquement selon le nombre de lettres l
x_offset = 26 * (- (0.9*l) + 3*i)
#print i,x_offset
if ord(ch)<58:
char_pl_list = ASCII_GRAPHICS[ord(ch) - 48]
else:
char_pl_list = ASCII_GRAPHICS[ord(ch) - 46]
char_draw = []
#dots.append((char_pl_list[0][0] + x_offset,char_pl_list[0][1],0))
for xy in char_pl_list:
char_draw.append((xy[0] + x_offset,xy[1],c))
i +=1
#print ch,char_pl_list,char_draw
rPolyLineOneColor(char_draw, c, PL , False, xpos, ypos, resize, rotx, roty, rotz)
#dots.append(char_draw)

44
clients/ljremote.py Normal file
View File

@ -0,0 +1,44 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
LJ Remote control via OSC in python
This is different than sending pointlist to draw. See pyclient or laserglyph for that.
Say your client want to display some information on the weUI status field or remote control any other LJ functions.
See commands.py for LJ functions list.
See Doctodo for all webUI elements.
LJ OSC server is listening on port 8002, talk to it.
'''
from OSC import OSCServer, OSCClient, OSCMessage
LJIP = "127.0.0.1"
osclientlj = OSCClient()
oscmsg = OSCMessage()
osclientlj.connect((LJIP, 8002))
def sendlj(oscaddress,oscargs=''):
oscmsg = OSCMessage()
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
#print ("sending to bhorosc : ",oscmsg)
try:
osclientlj.sendto(oscmsg, (LJIP, 8002))
oscmsg.clearData()
except:
print ('Connection to LJ refused : died ?')
pass
#time.sleep(0.001)
# display pouet in status display
sendlj("/status","pouet")
# switch laser 0 ack led to green
sendlj("/lack/0", 1)

View File

@ -1,7 +1,9 @@
# coding=UTF-8
'''
Multi Laser client example
Multi Laser client example with direct send of point lists to redis server.
Remember : LJ will automatically warp geometry according to alignement data. See webUI.
LICENCE : CC
'''
@ -29,32 +31,11 @@ pl1 = [(100,300,rgb2int(255,255,255)),(200,300,rgb2int(255,255,255)),(200,200,r
# /pl/clientnumber/lasernumber pointlist
# Consider you're client 0
# Send to laser 0 (see mainy.conf)
# Send to laser 0 (see LJ.conf)
r.set('/pl/0/0', str(pl0))
# Send to laser 1 (see mainy.conf)
# Send to laser 1 (see LJ.conf)
r.set('/pl/0/1', str(pl1))
# Send to laser 2 (see mainy.conf)
# Send to laser 2 (see LJ.conf)
r.set('/pl/0/2', str(pl1))
'''
You can also use PolyLineOneColor or rPolylineOneColor to stack n point lists to build a "frame"
import framy
# for laser0 :
pl0 = [(100,300),(200,300),(200,200),(100,200)]
framy.PolyLineOneColor(pl0, rgb2int(255,255,255), 0 , closed = False)
# You can add as much polylineOneColor as you want = construct a "frame"
# Then send it to the laser server :
print "All one color lines sent to laser 0 :",framy.LinesPL(0) # Will be True is sent correctly
# instead of PolyLineOneColor you can use rPolylineOneColor to send 2D point list around 0,0 with 3D rotation,resizing and repositioning at xpos ypos
# rPolylineOneColor is very useful to add different polylines to different position. Imagine different game elements.
# rPolyLineOneColor(xy_list, c, PL , closed, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
# Send the pl0 to laser 1
framy.rPolyLineOneColor((pl0, c = rgb2int(255,255,255), PL = 1, closed = False, xpos = 200, ypos = 250, resize = 1, rotx =0, roty =0 , rotz=0)
print "All one color lines sent to laser 1 :",framy.LinesPL(1) # Will be True is sent correctly
'''

View File

@ -1,39 +0,0 @@
REBOL []
outport: open/lines tcp://localhost:13857
on: 1
off: 0
pl0: "[(100,200, 0), (100,300, 65280), (200,300, 65280), (200,200, 65280), (100,200, 65280)]"
oscommand: to-string reduce ["pl/0 " pl0]
insert outport oscommand
for counter 1 2 1 [
;; print counter
oscommand: to-string reduce ["/40h/clear " on]
insert outport oscommand
wait 0.3
]
for counter 1 2 1 [
for raw 0 7 1 [
oscommand: to-string reduce ["/40h/led_row " raw " " on]
insert outport oscommand
wait 0.001
]
]
for counter 1 2 1 [
;; print counter
oscommand: to-string reduce ["/40h/frame 0 126 126 126 126 126 126 0"]
insert outport oscommand
wait 0.3
]
close outport

View File

@ -1,47 +0,0 @@
#!/usr/bin/env python
# coding=UTF-8
"""
TCP server for rebol links like from Amiga
Forward /pl/lasernumber pointslist to redis server
by Sam Neurohack
from /team/laser
"""
import socket, time,random, redis
r = redis.StrictRedis(host=gstt.LjayServerIP, port=6379, db=0)
# TCP listener
TCP_IP = '127.0.0.1'
TCP_PORT = 13857
BUFFER_SIZE = 1024 # Normally 1024, but we want fast response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
print 'Connection address:', addr
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
#print "received data:", data
commands = data.split()
nb_oscargs = len(commands)
print commands
#r.set('/pl/'+str(PL), str(something to code with commands, nb_oscargs))
#conn.send(data) # echo
conn.close()

View File

@ -1,8 +0,0 @@
Red []
#https://github.com/red/red/wiki/[DOC]-Guru-Meditations#how-to-make-http-requests
pl0: "[(100,200, 0), (100,300, 65280), (200,300, 65280), (200,200, 65280), (100,200, 65280)]"
read http://127.0.0.1:13857/path?name="jones"

View File

@ -1,57 +0,0 @@
#!/usr/bin/env python
# coding=UTF-8
"""
Http server for red 0.6.4
Forward /pl/lasernumber pointslist to redis server
by Sam Neurohack
from /team/laser
"""
import redis
r = redis.StrictRedis(host=gstt.LjayServerIP, port=6379, db=0)
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
PORT_NUMBER = 8080
#This class will handles any incoming request from
#the browser
class myHandler(BaseHTTPRequestHandler):
#Handler for the GET requests
def do_GET(self):
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
# Send the html message
self.wfile.write("Hello World !")
# r.set('/pl/'+str(PL), str(self.grid_points))
return
try:
#Create a web server and define the handler to manage the
#incoming request
server = HTTPServer(('', PORT_NUMBER), myHandler)
print 'Started httpserver on port ' , PORT_NUMBER
#Wait forever for incoming htto requests
server.serve_forever()
except KeyboardInterrupt:
print '^C received, shutting down the web server'
server.socket.close()

View File

@ -17,7 +17,7 @@ from /team/laser
#ConfigName = "setexample.conf"
ConfigName = "LJ.conf"
debug = 2
debug = 0
anims= [[],[],[],[]]
@ -28,7 +28,7 @@ LaserNumber = 2
LasClientNumber = 0
MaxLasClient = 3
screen_size = [800,600]
screen_size = [400,400]
xy_center = [screen_size[0]/2,screen_size[1]/2]
LjayServerIP = '192.168.1.13'

View File

@ -170,7 +170,7 @@ def EDpoint(mylaser,(pygamex,pygamey)):
YY = pygamey - gstt.xy_center[1]
CosANGLE = math.cos(gstt.finANGLE[mylaser])
SinANGLE = math.sin(gstt.finANGLE[mylaser])
# Multilaser style
x = (gstt.xy_center[0] + ((XX * CosANGLE) - (YY * SinANGLE)) - gstt.xy_center[0]) * gstt.zoomX[mylaser] + gstt.centerX[mylaser]
y = (gstt.xy_center[1] + ((XX * SinANGLE) + (YY * CosANGLE)) - gstt.xy_center[1]) * gstt.zoomY[mylaser] + gstt.centerY[mylaser]

18
main.py
View File

@ -1,3 +1,6 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
LJ Laser Server v0.8
@ -91,23 +94,23 @@ print "Lasers requested :", gstt.LaserNumber
wsPORT = 9001
# With Bhorosc
# OSC Server : relay OSC message from Bhorosc outport 8002 to UI
# OSC Server : accept OSC message on port 8002
#oscIPin = "192.168.1.10"s
bhoroscIPin = serverIP
bhoroscPORTin = 8002
# OSC Client : relay message from UI to Bhorosc inport 8001
# OSC Client : to send OSC message to an IP port 8001
bhoroscIPout = bhoroscIP
bhoroscPORTout = 8001
# With Nozosc
# OSC Client : relay message from UI to Nozosc inport 8003
# With Nozoid
# OSC Client : to send OSC message to Nozoid inport 8003
NozoscIPout = nozoscIP
NozoscPORTout = 8003
#print bhoroscIPin
print bhoroscIPin
oscserver = OSCServer( (bhoroscIPin, bhoroscPORTin) )
oscserver.timeout = 0
OSCRunning = True
@ -164,7 +167,7 @@ def sendnozosc(oscaddress,oscargs=''):
#time.sleep(0.001)
# OSC default path handler : send OSC message from Bhorosc 8002 to UI via websocket 9001
# OSC default path handler : send incoming OSC message to UI via websocket 9001
def handler(path, tags, args, source):
oscpath = path.split("/")
@ -190,7 +193,7 @@ def osc_frame():
# OSC Thread. OSC handler and Automated status sender to UI.
# OSC server Thread : handler, dacs reports and simulator points sender to UI.
def osc_thread():
while True:
@ -233,6 +236,7 @@ def osc_thread():
sendWSall("/points/" + str(laserid) + " " + str(r.get('/cap/'+str(laserid))))
#print "Sending simu frame from",'/pl/'+str(gstt.LasClientNumber)+'/'+str(gstt.Laser)
#print r.get('/pl/'+str(gstt.LasClientNumber)+'/'+str(gstt.Laser))
sendWSall("/simul" +" "+ r.get('/pl/'+str(gstt.LasClientNumber)+'/'+str(gstt.Laser)))

View File

@ -31,6 +31,8 @@ Etherdream status reports in redis keys:
Geometric corrections :
Doctodo
'''
import socket

BIN
visualiser-linux Executable file

Binary file not shown.

View File

@ -18,7 +18,7 @@
}
</script>
<script src="webaudio-controls.js"></script>
<link rel="stylesheet" href="ljaygrid.css" />
<link rel="stylesheet" href="LJgrid.css" />
<script src="LJ.js"></script>
@ -551,8 +551,37 @@
var ctx = canvas.getContext("2d");
var lastpoint = { x: 0, y: 0, color: 0};
ctx.clearRect(0,0,400,400);
var zoom = 0.5;
var mousePosDown = { x: 0, y: 0};
var mousePosUp = { x: 0, y: 0 };
var mouseMsgDown = '';
var mouseMsgUp = '';
//ctx.save
canvas.addEventListener("mouseup", MouseUp, false);
canvas.addEventListener("mousedown", MouseDown, false);
function getMousePos(canvas,evt)
{
var rect = canvas.getBoundingClientRect();
return { x: evt.clientX - rect.left, y: evt.clientY - rect.top };
}
function MouseDown(evt)
{
mousePosDown = getMousePos(canvas, evt);
mouseMsgDown = mousePosDown.x + ' ' + mousePosDown.y;
_WS.showin(mouseMsgDown);
}
function MouseUp(evt)
{
mousePosUp = getMousePos(canvas, evt);
mouseMsgUp = mousePosUp.x + ' ' + mousePosUp.y;
_WS.showin(mouseMsgUp);
_WS.s.send('/mouse '+mouseMsgDown+' '+mouseMsgUp);
_WS.showin('/mouse '+mouseMsgDown+' '+mouseMsgUp);
}
// Todo : laser point will have black points to go from a polyline to another. Need to discard those black points.
function draw() {
@ -568,7 +597,7 @@
ctx.clearRect(0,0,400,400);
ctx.beginPath();
ctx.moveTo(pl2[0]*0.5, pl2[1]*0.5);
ctx.moveTo(pl2[0]*zoom, pl2[1]*zoom);
lastpoint.color = pl2[2];
// Draw n Lines
@ -578,7 +607,7 @@
// New point has the same color -> add a new line to the new point
if (pl2[2+(i*3)] === lastpoint.color)
{
ctx.lineTo(pl2[i*3]*0.5, pl2[1+(i*3)]*0.5);
ctx.lineTo(pl2[i*3]*zoom, pl2[1+(i*3)]*zoom);
}
// New point has different color -> stroke with previous color
@ -591,13 +620,13 @@
ctx.beginPath();
//ctx.clearRect(0,0,400,400);
ctx.moveTo(pl2[i*3]*0.5, pl2[1+(i*3)]*0.5);
ctx.moveTo(pl2[i*3]*zoom, pl2[1+(i*3)]*zoom);
}
// Last point -> stroke with current color
if (i === (pl2.length/3)-1 )
{
ctx.moveTo(pl2[i*3]*0.5, pl2[1+(i*3)]*0.5);
ctx.moveTo(pl2[i*3]*zoom, pl2[1+(i*3)]*zoom);
ctx.strokeStyle = "#"+((pl2[2+(i*3)]) + Math.pow(16, 6)).toString(16).slice(-6);
ctx.stroke();