spielgeruest_mini.py
spielgeruest_mini.py
—
Python Source,
7 KB (7997 bytes)
Dateiinhalt
from visual import *
from threading import Thread
PORT = 50000
class Feld(frame):
def __init__(self, nummer, farbe, groesse=1):
frame.__init__(self)
self.nummer=nummer
self.feld = box(frame=self, material=materials.plastic, width=groesse, length=groesse, height=groesse/20, color=farbe)
class Spielfigur(frame):
def __init__(self, farbe, besitzer, nummer, groesse=1):
frame.__init__(self)
self.besitzer = besitzer
self.nummer = nummer
self.feldnr = 0 #Nummer des Feldes, auf dem die Figur steht
self.body = cone(frame=self, color=farbe, axis=(0,1,0), # Kegelkoerper
radius=0.375*groesse, material=materials.wood)
self.head = sphere(frame=self, color=farbe, y=1*groesse,# Kugelkopf
radius=0.25*groesse,material=materials.wood)
class Spielbrett(Thread):
def __init__(self):
Thread.__init__(self)
self.figurenliste = []
self.felderliste = []
self.aufbauen()
def aufbauen(self):
zahl = 5
for i in range (zahl*zahl):
if i%2==0:
c = color.white
else:
c = color.red
x = Feld(i,c)
x.pos=(i%zahl*2,0,i/zahl*2)
self.felderliste.append(x)
z = Spielfigur(color.green, 0, 0)
self.figurenliste.append(z)
u = Spielfigur(color.yellow, 1, 0)
self.figurenliste.append(u)
u.pos = self.felderliste[zahl*zahl-1].pos
def figur_setzen(self,spielernr,figurnr,zielnr):
#erst die richtige Figur in der Liste finden
for f in self.figurenliste:
if f.besitzer==spielernr and f.nummer==figurnr:
figur = f
break
#dann das richtige feld in der anderen Liste finden
for feld in self.felderliste:
if feld.nummer == zielnr:
figur.pos=feld.pos
figur.feldnr = feld.nummer
break
def run(self):
pick = None
spielernr = -1 #die spielernummer
figurnr = -1 #die figurnummer
zielnr = -1 #die zielposition (als nummer)
while True:
rate(30)
if scene.mouse.events:
sme = scene.mouse.getevent()
#wenn ein Objekt geklickt und bewegt wird
if sme.drag and sme.pick:
#testen, ob zu einer figur gehoert
for f in self.figurenliste:
if sme.pick in f.objects:
spielernr = f.besitzer
figurnr = f.nummer
break
else:
f = None
drag_pos = sme.pickpos # where on the object
drag_pos.y = 0 #### neu
pick = f
#wenn eine Figur losgelassen wird, wird das naechstgelegene Feld ermittelt
elif sme.drop and pick:
zielnr=pick.feldnr #vorerst ist die alte Position der Figur das Ziel
#Suchen nach naechstgelegenem neuen Feld
for feld in self.felderliste:
feldmitte = feld.pos#kann noch verbessert werden
if mag(feldmitte - pick.pos) < .8:
zielnr=feld.nummer
#gefunden!
break
#--------------------#
self.controller.weiterleiten(str(spielernr)+","+str(figurnr)+","+str(pick.feldnr)+","+str(zielnr))
#--------------------#
#self.figur_setzen(spielernr,figurnr,zielnr)
pick = None
#wenn eine Figur angeklickt worden ist, wird ihre Position der Maus angepasst
if pick:
# project onto xy plane, even if scene rotated:
new_pos = scene.mouse.project(normal=(0,1,0))
if new_pos != drag_pos: # if mouse has moved
#offset for where the ball was clicked:
pick.pos += new_pos - drag_pos
drag_pos = new_pos # update drag position
pick.pos = new_pos + pick.pos - drag_pos
drag_pos = new_pos # update drag position
'''Diese Klasse ermoeglicht die Netzkommunikation. Bau sie in dein Projekt ein.
Die eigentliche Spielklasse braucht ein Referenzattribut auf ein Objekt dieser Steuerungs-Klasse,
und kann dann mittels der Steuerungs-Methode weiterleiten(nachricht) einen String an die
Steuerung schicken, die ihrerseits das an den Server weiterleitet. (Was der Server macht, steht
in der Datei "server_class.py", die sich im selben Verzeichnis befinden muss.)
Der Konstruktor verlangt ein Objekt, dem er die Nachrichten des Servers schicken soll, also das
eigentliche Spiel, und optional einen Port. Jedes Team sollte eine eigene fuenstellige Portnummer
waehlen.'''
class Steuerung(Thread):
def __init__(self, spiel, port=50000):
Thread.__init__(self)
self.view=spiel
# UDP-Client, der den Server als Subprozess startet
import subprocess # Modul zum Starten von Subprozessen
import socket # Modul fuer Netzwerkkommunikation
self.PORT = port
#Anlegen eines Socket
self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # AF_INET = IPv4, SOCK_DGRAM = UDP
self.s.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1) # Broadcast ermoeglichen
#Testen, ob es schon einen Server auf diesem Port gibt, notfalls selber starten
try:
self.s.sendto("print 'wer hoert mich?'",
('255.255.255.255', self.PORT)) # sende Nachricht 'an alle'
self.s.settimeout(2) # warte 1/2 Sekunde..
print (self.s.recvfrom(64)[0]) # gibt Servermeldung aus
#ein Problem, wenn timeout einmal gesetzt ist...
self.s.settimeout(3000)
except: # reagiert auf Zeitueberschreitung
print ("Kein Server vorhanden - starte Server") # Rueckmeldung
subprocess.Popen(['python','server_class.py',str(self.PORT)]) # Server starten
self.s.setblocking(1) # nicht-blockierend
self.s.sendto("print 'hallo'", ('255.255.255.255', self.PORT))
self.start()
#Endlosmethode zum Abhoeren des Ports auf Nachrichten
def run(self):
while True:
nachricht = self.s.recvfrom(128)[0]
self.auswerten(nachricht)
#Methode zum Auswerten der eingegangenen Nachricht
def auswerten(self,nachricht):
exec (nachricht)
#Methode zum Weiterleiten, wird von Spiel genutzt
def weiterleiten(self, nachricht):
# HIER CODE EINFUEGEN, DER AUSGEFUEHRT WERDEN SOLL
teile=nachricht.split(",")
nachricht = "self.view.figur_setzen("+teile[0]+","+teile[1]+","+teile[3]+")"
self.s.sendto(nachricht, ('255.255.255.255', self.PORT)) # versenden der Nachricht an Tupel(IP, PORT)
if __name__ == "__main__":
spiel = Spielbrett() #das eigentliche Spiel
steuerung = Steuerung(spiel, PORT) #Die Steuerung, mit dem Spiel und einem Port als Argument
spiel.controller = steuerung #Setzen des Referenzattributs
spiel.start() #Das Spiel muss von Thread erben, hier wird dessen run-Methode gestartet