diff --git a/FlipdotSender.py b/FlipdotSender.py index d66c5b2..cf11f84 100644 --- a/FlipdotSender.py +++ b/FlipdotSender.py @@ -15,8 +15,10 @@ class FlipdotSender(object): C_BLACK = 0 C_WHITE = 255 + lastimgmap = [] + def __init__(self, udphost, udpport, img_size=(80,16), font_size=8, font_size_scroll=12, - font_offset1=(0,-1), font_offset2=(0,7), + font_offset1=(0,0), font_offset2=(0,8), #font_family='/usr/share/fonts/gnu-free/FreeMono.ttf', font_family='/usr/share/fonts/truetype/ttf-dejavu/DejaVuSansMono.ttf', #font_family='/usr/share/fonts/truetype/freefont/FreeMono.ttf', @@ -51,8 +53,8 @@ class FlipdotSender(object): def _array2packet(self, a): return [self._list2byte(a[i*8:i*8+8]) for i in range(int(len(a)/8))] - - def _send(self, image): + ''' + def _send(self, image): #old function, backup imgmap = [] for pixel in image.getdata(): r, g, b, a = pixel @@ -60,10 +62,45 @@ class FlipdotSender(object): imgmap.append(1) else: imgmap.append(0) + + lastimgmap=imgmap packet = self._array2packet(imgmap) + self._sock.sendto(bytes(packet), (self._udphost, self._udpport))''' + + def _send(self, image,fadespeed=0): #changes slowly 'fadespeed'-pixels at a time + #if fadespeed=0 -> change instant. + #time to change= 1280/25*0.2 + imgmap = [] + for pixel in image.getdata(): + r, g, b, a = pixel + if r == FlipdotSender.C_WHITE: + imgmap.append(1) + else: + imgmap.append(0) + + imgmaptmp=FlipdotSender.lastimgmap + + if fadespeed>0: + #diff=np.sum(np.array(imgmaptmp) != np.array(imgmap)) #different pixels + pixelchangeind=np.arange(self._img_size[0]*self._img_size[1]) + np.random.shuffle(pixelchangeind) + for _i,ind in enumerate(pixelchangeind): + if ind1: draw.text(self._font_offset2, splitted_text[1], font=font, fill=FlipdotSender.C_WHITE) - self._send(image) + self._send(image,fadespeed) + + def send_textFull(self, text,fadespeed=0): + image = Image.new("RGBA", self._img_size, FlipdotSender.C_BLACK) + draw = ImageDraw.Draw(image) + draw.fontmode = "1" # No AA + + l=1000 #init very high + splitpoint=40 #very high + currentfontsize=12+1 #init with max font size + font = ImageFont.truetype(self._font_family, currentfontsize) + + while(l>80): #while text too long and font not too small + if currentfontsize>8: + currentfontsize=currentfontsize-1 #reduce size and try if fits + else: #if fontsize too small, try cutting sentence (2 lines) + splitpoint=splitpoint-1 + + font = ImageFont.truetype(self._font_family, currentfontsize) + l=draw.textsize(text[0:splitpoint], font=font)[0] + print("Textlength="+str(l)+" split="+str(splitpoint)) + + if splitpoint==40: #not splitted + draw.text((0,int((16-currentfontsize)/2) ), text, font=font, fill=FlipdotSender.C_WHITE) + else: + draw.text((0,-1), text[0:splitpoint], font=font, fill=FlipdotSender.C_WHITE) + draw.text((0,-1+currentfontsize), text[splitpoint:], font=font, fill=FlipdotSender.C_WHITE) + + + self._send(image,fadespeed) + def send_marquee(self, str, speed=3): offset = self._img_size[0] diff --git a/hangman.py b/hangman.py index 341045b..0f57864 100644 --- a/hangman.py +++ b/hangman.py @@ -3,7 +3,7 @@ from PIL import Image, ImageFont, ImageDraw import sys, os import fileinput from random import randint - +from FlipdotSender import FlipdotSender class Hangman(object): ''' @@ -17,6 +17,7 @@ class Hangman(object): global C_HM global FPS global FONT_SIZE_word + global G_ALLOWNUMERIC C_BLACK = 0 C_WHITE = 255 @@ -25,12 +26,13 @@ class Hangman(object): C_HM=C_TEXT FPS=2 FONT_SIZE_word=9 #was 9 + G_ALLOWNUMERIC=True #hangman/alterebro-pixel-font.ttf size=14, -2 and 6 - def __init__(self, udphost, udpport, img_size=(80,16)): + def __init__(self, udphost, udpport, pflipdot=None,img_size=(80,16)): ''' Constructor ''' @@ -39,11 +41,14 @@ class Hangman(object): if not type(udpport) is int or udpport > 65536: raise TypeError('port has to be int and > 65536 !!') self._udpport = udpport + self._flipdot=pflipdot + self._img_size = img_size self._fo_word= (15, -1) #(15, -1) self._fo_word2= (15, 7) #(15,7) #self._wordlist="/home/pi/mqtt-to-flipdot/hangman/nomenliste_de.txt" - self._wordlist="/home/pi/mqtt-to-flipdot/hangman/crodict_nomen.txt" + #self._wordlist="/home/pi/mqtt-to-flipdot/hangman/crodict_nomen.txt" + self._wordlist="/home/pi/mqtt-to-flipdot/hangman/nerdwords.txt" self._gamestate=0# 0=start 1=ingame 2=lose 3=win self._g_word="test" #word self._g_displword="" #display word @@ -64,9 +69,10 @@ class Hangman(object): self._maxwlen=26 self._words=[] - fobj = open(self._wordlist) + fobj = open(self._wordlist, encoding="utf-8") for line in fobj: - string=line.rstrip() + string=line.rstrip().upper() #remove whitespaces and make uppercase + string=string.replace(" ","+") #if using another replacement, also change in validateWord and generateDisplayWord if (self._validateWord(string)==1): if (len(string)>=self._minwlen and len(string)<=self._maxwlen): self._words.append(string) @@ -83,7 +89,8 @@ class Hangman(object): self._g_chars="" self._generateDisplword() self._g_gamestate=1 - self._sock.sendto(bytes(self._array2packet(self._draw())), (self._udphost, self._udpport)) + self._sendPacket(self._draw()) + #self._sock.sendto(bytes(self._array2packet(self._draw())), (self._udphost, self._udpport)) def _list2byte(self, l): @@ -118,6 +125,8 @@ class Hangman(object): a=s elif (oc>=48 and oc<=57 and G_ALLOWNUMERIC==1):#0-9 a=s + elif (s[c]=="-" or s[c]==" " or s[c]=="+"):#or - or whitespace (will be given characters) + a=s else: return 0 return 1 @@ -130,13 +139,15 @@ class Hangman(object): cha=self._g_word[i] #current character show=0 for c in range(0,len(self._g_chars)): - if cha.lower()==self._g_chars[c]: #if current char is opened + if cha.lower()==self._g_chars[c]: #if current char is opened show=1 + if cha==" " or cha=="-" or cha=="+": #show spaces and - and _ + show=1 if show==1: #if character cha is opened self._g_displword+=cha #show else: - self._g_displword+="-" #do not show + self._g_displword+="'" #do not show def _countFails(self): fails=0 @@ -257,6 +268,12 @@ class Hangman(object): def _drawWinScreen(self,draw): self._drawGameScreen(draw) + def _sendPacket(self,imgmap): + if self._flipdot is not None: + self._flipdot.sendPacket(imgmap) + else: + self._sock.sendto(bytes(self._array2packet(imgmap)), (self._udphost, self._udpport)) + def step(self,strinput): #returns 0 if game ended @@ -272,7 +289,7 @@ class Hangman(object): #draw() #test - self._sock.sendto(bytes(self._array2packet(self._draw())), (self._udphost, self._udpport)) + self._sendPacket(self._draw()) print("Display:"+self._g_displword) print("Used:"+self._g_chars) print("fails:"+str(self._countFails())) @@ -284,14 +301,14 @@ class Hangman(object): #C_TEXT=C_BG #invert text #C_BG=c_t #invert text self._g_displword=self._g_word - self._sock.sendto(bytes(self._array2packet(self._draw())), (self._udphost, self._udpport)) + self._sendPacket(self._draw()) print("verloren, das Wort war:"+self._g_word) self._g_gamestate=0 return 2 elif self._g_gamestate==3: - self._sock.sendto(bytes(self._array2packet(self._draw())), (self._udphost, self._udpport)) + self._sendPacket(self._draw()) print("gewonnen") self._g_gamestate=0 return 3 diff --git a/mqtt-to-flipdot.py b/mqtt-to-flipdot.py index 8055b4d..fe4b837 100644 --- a/mqtt-to-flipdot.py +++ b/mqtt-to-flipdot.py @@ -7,6 +7,8 @@ from hangman import Hangman global mode mode="standby" +global gametimeout +gametimeout=0 def on_connect(client, userdata, flags, rc): print("Connected with result code " + str(rc)) @@ -19,13 +21,15 @@ def on_connect(client, userdata, flags, rc): def on_message(client, userdata, msg): print(msg.topic + " " + str(msg.payload.decode("utf-8"))) global mode + global gametimeout if mode=="standby": + gametimeout=0 if msg.topic == "raum2/flipdot/scroll/set": payload = msg.payload.decode("utf-8") - if (payload[0]).isdigit(): + if len(payload)>0 and (payload[0]).isdigit(): speed = int(payload[0]) text = payload[1:] else: @@ -35,7 +39,18 @@ def on_message(client, userdata, msg): flipdot.send_marquee(text, speed) if msg.topic == "raum2/flipdot/text/set": payload = msg.payload.decode("utf-8") - flipdot.send_text(payload) + + if len(payload)>0 and payload[0]=='~': + payload=payload[1:] #remove first char + flipdot.send_text(payload,25) #send_text with animation + flipdot.send_text(payload) #without animation + + if msg.topic == "raum2/flipdot/textFull/set": + payload = msg.payload.decode("utf-8") + if len(payload)>0 and payload[0]=='~': + payload=payload[1:] + flipdot.send_textFull(payload,50) + flipdot.send_textFull(payload) if msg.topic == "raum2/flipdot/image/set": payload = msg.payload.decode("utf-8") @@ -49,12 +64,15 @@ def on_message(client, userdata, msg): if payload=="#start": hangman.setup() + gametimeout=int(round(time.time() * 1000)) client.publish("raum2/flipdot/hangman","started") mode="hangman" elif (mode=="hangman") and (len(payload)>0): #try entered character + gametimeout=int(round(time.time() * 1000)) trychar=payload[-1] gamestatus=hangman.step(trychar) + client.publish("raum2/flipdot/hangman","char="+trychar.upper()) if gamestatus!=1: #game has ended mode="standby" if gamestatus==2: #gameover @@ -72,7 +90,7 @@ def on_message(client, userdata, msg): flipdot = FlipdotSender("2001:67c:275c:a9::c", 2323) -hangman= Hangman("2001:67c:275c:a9::c", 2323) +hangman= Hangman("2001:67c:275c:a9::c", 2323,flipdot) @@ -84,6 +102,13 @@ client.loop_start() while True: + millis = int(round(time.time() * 1000)) + if gametimeout!=0: + if millis-120000 > gametimeout: #timeout + print("Game Timeout") + mode="standby" + gametimeout=0 + time.sleep(2)