#!/usr/bin/env python # -*- coding: utf-8 -*- ''' ------------------------------------------ WireChem - The new chemistry game Programme principal (C) Copyright 2013-2014 Nicolas Hordé Licence GPL V3.0 ------------------------------------------ ''' import datetime import math import pyglet import copy import csv import random import time import operator import shelve import os import sys from pyglet.gl import * from pyglet.window import mouse from pyglet.window import key from pyglet import clock from pyglet import image from os.path import expanduser ''' *********************************************************************************************** ''' ''' Fonctions de chargement ''' #Enregistre les données utilisateurs def sync(): global Uworlds,finished write(gethome()+"/dbdata",["Uworlds","finished"]) #Vérifie l'existence de la base de donnée utilisateur def verifyhome(): global Uworlds,finished if not os.path.exists(gethome()): os.makedirs(gethome()) if not os.path.exists(gethome()+"/dbdata"): Uworlds=[[{0:0}]] finished=[(0,0)] sync() #Trouve le chemin vers le repertoire utilisateur def gethome(): home = expanduser("~")+"/.wirechem" return home #Ecrit les variables spécifiés dans la base selectionnée (utilisateur ou système) def write(afile,var): d=shelve.open(afile,writeback=True) for k in var: d[k]=copy.deepcopy(globals()[k]) d.sync() d.close() #Lit une base de donnée def read(afile): d=shelve.open(afile,writeback=True) for k in d.keys(): globals()[k]=copy.deepcopy(d[k]) d.close() #Charge le dictionnaire sous forme de variables def load(d): for k in d.keys(): if k[0]!="_": globals()[k]=copy.deepcopy(d[k]) #Référence les variables def reference(var,noms): if len(noms)==2: for y in range(len(var)): for x in range(len(var[y])): var[y][x][noms[0]]=y var[y][x][noms[1]]=x else: for x in range(len(var[y])): var[x][y][noms[0]]=x #duplique les références def duplicateref(d): for k in d.keys(): d[d[k]['nom']]=d[k] ''' *********************************************************************************************** ''' ''' Sauvegarde/Restauration ''' def readlevel(w,l,user): global tuto,worlds,cout,selected,sizex,sizey,stat,tech tuto='' if user: if w1 and sys.argv[1]=='debug': debug=1 else: debug=0 ''' *********************************************************************************************** ''' ''' initialisation ''' debug=0 worlds={} world=level=0 init() ''' *********************************************************************************************** ''' ''' Classes graphiques ''' #Classe d'un rectangle class arect(object): def __init__(self, window, x1, y1, x2, y2, color): self.window=window self.vertex_list = window.batch.add(4, pyglet.gl.GL_QUADS, None,('v2i', [x1, y1, x2, y1, x2, y2, x1, y2]),('c4B', color * 4)) #Classe d'un texte editable class atext(object): def __init__(self,window,text,x,y,width,color,font,size): self.x=x self.y=y self.loaded='' self.text=text self.color=color self.document = pyglet.text.document.UnformattedDocument(text) self.document.set_style(0, len(self.document.text),dict(font_name=font,font_size=size,color=color,background_color=(200, 200, 200,0))) font = self.document.get_font() height = font.ascent - font.descent self.window=window self.layout = pyglet.text.layout.IncrementalTextLayout(self.document, width, height, multiline=False, batch=self.window.batch, group=self.window.p3) self.layout.register_event_type('self.on_layout_update') self.caret = pyglet.text.caret.Caret(self.layout) self.caret.visible = False self.layout.x = self.x self.layout.y = self.y def update(self): self.layout.begin_update() self.layout.x = self.x self.layout.y = self.y self.layout.document.text=self.text self.layout.document.set_style(0, len(self.layout.document.text),dict(color=self.color)) self.layout.end_update() def on_layout_update(self): print "**************************" if self.loaded!='': eval(self.loaded+"="+self.text) def hit_test(self, x, y): return (0 < x - self.layout.x < self.layout.width and 0 < y - self.layout.y < self.layout.height) #Bouton sensible a plusieurs évènements class abutton(object): def update(self,dt): if type(self.evalx) is str: self.x=eval(self.evalx) if type(self.evaly) is str: self.y=eval(self.evaly) try: self.vertex_list.delete() except: foo=0 try: self.vertex_list2.delete() except: foo=0 try: self.vertex_list3.delete() except: foo=0 try: self.sprite.delete() except: foo=0 if self.isvisible(): if self.typeof=='color': if not self.isactive(): color=(self.content[0],self.content[1],self.content[2],127) else: color=(self.content[0],self.content[1],self.content[2],255) self.vertex_list = self.window.batch.add(4,pyglet.gl.GL_QUADS, self.window.p1, ('v2i', (self.x, self.y, self.x+self.width, self.y, self.x+self.width, self.y+self.height, self.x, self.y+self.height)), ('c4B', color * 4)) elif self.typeof=='function': self.vertex_list = eval(self.content) else: if self.typeof=='multicon': image = self.content[self.index] else: image = self.content if self.width==0 or self.height==0: self.width=image.width self.height=image.height self.sprite = pyglet.sprite.Sprite(image, x=self.x, y=self.y, batch=self.window.batch, group=self.window.p1) if self.width/float(self.height) < image.width/float(image.height): self.sprite.scale=float(self.width)/image.width else: self.sprite.scale=float(self.height)/image.height if not self.isactive(): self.sprite.color=(60,60,60) else: self.sprite.color=(255,255,255) if type(self.selected) is tuple: color=(self.selected[0],self.selected[1],self.selected[2],255) self.vertex_list2 = self.window.batch.add(4,pyglet.gl.GL_LINE_LOOP, self.window.p2, ('v2i', (self.x, self.y, self.x+self.width, self.y, self.x+self.width, self.y+self.height, self.x, self.y+self.height)), ('c4B', color * 4)) elif type(self.selected) is list and self.isactive(): self.sprite.color=(self.selected[0],self.selected[1],self.selected[2]) if self.hilite and int(time.time())%2==0: color=(255,0,0,128) self.vertex_list3 = self.window.batch.add(4,pyglet.gl.GL_QUADS, self.window.p2, ('v2i', (self.x, self.y, self.x+self.width, self.y, self.x+self.width, self.y+self.height, self.x, self.y+self.height)), ('c4B', color * 4)) def __init__(self, window, name, x, y, width, height , active, hilite, visible, selected, content, hint, typeof, text, text2): self.name=name self.time=0 self.index=0 self.enter=0 self.window=window self.evalx=x self.evaly=y self.x=x self.y=y self.width=width self.height=height self.active=active self.hilite=hilite self.visible=visible self.content=content self.typeof=typeof self.hint=hint self.selected=selected self.window.push_handlers(self.on_mouse_press) self.window.push_handlers(self.on_mouse_motion) self.window.push_handlers(self.on_mouse_drag) self.window.push_handlers(self.on_mouse_release) self.window.push_handlers(self.on_mouse_scroll) self.updateclock=clock.schedule_interval(self.update,1) self.update(0) def delete(self): self.vertex_list.delete() del self self=None def launch(self,state): global debug name=self.name.split('_') if len(name)>1 and hasattr(self.window, "on_mouse_"+state['event']+"_"+name[0]) and callable(eval("self.window.on_mouse_"+state['event']+"_"+name[0])): eval("self.window.on_mouse_"+state['event']+"_"+name[0]+"("+str(name[1])+","+str(state)+")") if debug>0: print state,self.name if hasattr(self.window, "on_mouse_"+state['event']+"_"+self.name) and callable(eval("self.window.on_mouse_"+state['event']+"_"+self.name)): if self.typeof=='multicon': self.index+=1 if self.index>=len(self.content): self.index=0 self.update(0) eval("self.window.on_mouse_"+state['event']+"_"+self.name+"("+str(state)+")") if debug>0: print state,self.name def on_mouse_press(self, x, y, button, modifiers): if x>self.x and y>self.y and xself.x and y>self.y and xself.x and y>self.y and xself.x and y>self.y and xself.x and y>self.y and x1024: self.loc[2]=-1 if self.loc[1]>768: self.loc[3]=-1 if self.loc[0]<0: self.loc[2]=1 if self.loc[1]<0: self.loc[3]=1 def update(self): global world,worlds,finished for obj in worlds[world]: if obj.has_key('special'): break if 'obj' in locals(): self.labels[0].text=obj['element'] self.labels[0].color=(self.colors[world][0],self.colors[world][1],self.colors[world][2],100) self.labels[0].x=(1024-self.labels[0].content_width)/2-50 self.labels[0].y=75*self.height/768 if 'obj' in locals(): self.labels[0].text=obj['element'] else: self.labels[0].text='' for l in range(len(self.buttons)): self.buttons[l].update(0) for l in range(10): if l>=len(worlds[world]): self.levels[l].x=-300 self.untitled[l].x=-300 self.untitled2[l].x=-300 self.lock[l].x=-300 self.levels[l].update(0) self.untitled2[l].update() self.untitled[l].update() continue ele=worlds[world][l] self.levels[l].active=(world,l) in finished or debug==2 self.levels[l].x=ele['_xx'] self.levels[l].y=ele['_yy']/768.0*self.height self.levels[l].setselected([255,120+int(ele['_xx']/1024.0*135),155+int(ele['_xx']/1024.0*100)]) self.levels[l].content=self.images[world] self.levels[l].update(0) self.untitled[l].text=ele['element'] self.untitled[l].update() self.untitled[l].x=ele['_xx']+(self.images[world].width-self.untitled[l].layout.content_width)/2 self.untitled[l].y=ele['_yy']/768.0*self.height+20 self.untitled[l].color=(int(ele['_xx']/1024.0*150), int(ele['_xx']/1024.0*150), int(ele['_xx']/1024.0*150),255) self.untitled[l].update() self.untitled2[l].text=ele['nom'].decode('utf-8') self.untitled2[l].x=ele['_xx']+(self.images[world].width-self.untitled2[l].layout.content_width)/2 self.untitled2[l].y=ele['_yy']/768.0*self.height-20 self.untitled2[l].loaded='worlds['+str(world)+']['+str(l)+']["nom"]' if (world,l) in finished or debug==2: self.untitled2[l].color=(255,255,255,255) else: self.untitled2[l].color=(90,90,90,255) self.untitled2[l].update() self.lock[l].visible=(world,l) not in finished and not debug==2 self.lock[l].x=ele['_xx']+10 self.lock[l].y=ele['_yy']/768.0*self.height+50 if 'obj' in locals() and ele['description']==obj['description']: self.special.x=ele['_xx'] self.special.y=ele['_yy']/768.0*self.height if 'obj' not in locals(): self.special.x=-300 def drawLaser(self,x1,y1,x2,y2,width,power,color,randomize): while(width > 0): if randomize!=0: glLineStipple(random.randint(0,randomize),random.randint(0,65535)) glLineWidth(width) glBegin(GL_LINES) glColor3ub(min(color[0]+power*width,255),min(color[1]+power*width,255),min(color[2]+power*width,255)) glVertex2i(x1,y1) glVertex2i(x2,y2) width=width-1 glEnd() glLineStipple(1,65535) def draw(self,dt): global loc,world,worlds,thex,they,debug glClear(GL_COLOR_BUFFER_BIT); #self.fond.anchor_x=self.loc[0] #self.fond.anchor_y=self.loc[1] if debug<2: glColor4ub(255,255,255,160) self.fond.blit(self.loc[0],self.loc[1]) self.fond.blit(self.loc[0]-1024,self.loc[1]) self.fond.blit(self.loc[0]-1024,self.loc[1]-768) self.fond.blit(self.loc[0],self.loc[1]-768) #self.fond.blit_tiled(0, 0, 0, self.width, self.height) for ele in worlds[world]: for n in ele['link']: if world==n[0]: src=(int(ele['_xx']+self.images[0].width/2),int(ele['_yy']/768.0*self.height+self.images[0].height/2)) dest=(int(worlds[n[0]][n[1]]['_xx']+self.images[0].width/2),int(worlds[n[0]][n[1]]['_yy']/768.0*self.height+self.images[0].height/2)) else: src=(int(ele['_xx']+self.images[0].width/2),int(ele['_yy']/768.0*self.height+self.images[0].height/2)) dest=(int(1024),int(worlds[n[0]][n[1]]['_yy']/768.0*self.height+50)) if dest[0]-src[0]!=0: angle=math.atan(float(dest[1]-src[1])/float(dest[0]-src[0])) else: angle=270*3.14/180.0 if dest[0]-src[0]<0: angle=angle+180*3.14/180.0 src=(src[0]+int(self.sizes[world][0]*math.cos(angle)),src[1]+int(self.sizes[world][1]*math.sin(angle))) if world==n[0]: dest=(dest[0]-int(self.sizes[world][0]*math.cos(angle)),dest[1]-int(self.sizes[world][1]*math.sin(angle))) if n in finished or debug==2: params=(random.randint(0,8),20,self.colors[world],12) else: params=(2,20,[40,40,40],0) self.drawLaser(src[0],src[1],dest[0],dest[1],params[0],params[1],params[2],params[3]) if debug==2 and world==n[0]: if dest[0]-src[0]!=0: angle=math.atan(float(dest[1]-src[1])/float(dest[0]-src[0])) else: angle=270*3.14/180.0 if dest[0]-src[0]<0: angle=angle+180*3.14/180.0 self.drawLaser(dest[0],dest[1],dest[0]-int(20*math.cos(angle+30*3.14/180)),dest[1]-int(20*math.sin(angle+30*3.14/180)),params[0],params[1],params[2],params[3]) self.drawLaser(dest[0],dest[1],dest[0]-int(20*math.cos(angle-30*3.14/180)),dest[1]-int(20*math.sin(angle-30*3.14/180)),params[0],params[1],params[2],params[3]) if world>0: for ele in worlds[world-1]: for n in ele['link']: if n[0]==world: src=(int(0),int(worlds[n[0]][n[1]]['_yy']/768.0*self.height+self.images[0].height/2)) dest=(int(worlds[n[0]][n[1]]['_xx']+self.images[0].width/2),int(worlds[n[0]][n[1]]['_yy']/768.0*self.height+self.images[0].height/2)) if dest[0]-src[0]!=0: angle=math.atan(float(dest[1]-src[1])/float(dest[0]-src[0])) else: angle=270*3.14/180.0 if dest[0]-src[0]<0: angle=angle+180*3.14/180.0 dest=(dest[0]-int(self.sizes[world][0]*math.cos(angle)),dest[1]-int(self.sizes[world][1]*math.sin(angle))) if n in finished or debug==2: params=(random.randint(0,8),20,self.colors[world],12) else: params=(2,20,[40,40,40],0) self.drawLaser(src[0],src[1],dest[0],dest[1],params[0],params[1],params[2],params[3]) if type(self.selected) is tuple: if self.selected[0]==world: self.drawLaser(int(worlds[self.selected[0]][self.selected[1]]['_xx']+self.images[0].width/2),int(worlds[self.selected[0]][self.selected[1]]['_yy']/768.0*self.height+self.images[0].height/2),int(thex),int(they),random.randint(0,8),20,self.colors[world],12) else: self.drawLaser(int(0),int(worlds[self.selected[0]][self.selected[1]]['_yy']/768.0*self.height+self.images[0].height/2),int(thex),int(they),random.randint(0,8),20,self.colors[world],12) self.batch.draw() ### Evenement générer par classe abutton ### def on_mouse_press_logo(self, state): global debug if debug==1: debug=2 self.buttons[0].setselected([255,0,0]) elif debug==2: debug=1 self.buttons[0].setselected(False) self.update() def on_mouse_press_menu_2(self, state): pyglet.app.exit() def on_mouse_press_menu_1(self, state): global world if world>0: world-=1 self.update() def on_mouse_press_menu_0(self, state): global world if worldn: element-=1 if element!=n: ele['link'][l]=(ele['link'][l][0],element) l+=1 else: del ele['link'][l] else: l+=1 return ### Evenement de la fenetre ### def on_mouse_drag(self,x , y, dx, dy, buttons, modifiers): global thex,they,world,worlds if debug<2: return if type(self.selected) is tuple: thex=x they=y return if x>1024-20 and world+1