Spielchen in Tkinter

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
Benutzeravatar
HorstJENS
User
Beiträge: 123
Registriert: Donnerstag 9. Februar 2006, 21:41
Wohnort: Wien, Österreich
Kontaktdaten:

Hallo, ich erlaube mir mein erstes Tkinter-Spielchen den kritischen Blicken der Öffentlichkeit auszusetzen.
Da ich nicht weiß wie man Grafiken als attachment posten kann ersuche ich darum das komplette programm als zipfile von
http://members.chello.at/horst.jens/files.htm , file: scheresteinpapier0_15.zip zu holen.

Hier der Sourcecode (läuft nicht ohne Grafiken, siehe oben):

Code: Alles auswählen

#!/usr/bin/env python 
# -*- encoding: latin-1 -*- 
#Schere, Stein, Papier von Horst JENS
# Version 0.15
#Dieses Program steht seit 9/2006 unter der 
# GNU General Public License
# siehe http://www.gnu.de/gpl-ger.html
# oder http://de.wikipedia.org/wiki/GNU_General_Public_License
#Autor: Horst.Jens@gmx.at
# Threadprogrammierung aus "Python 2.x Das Einsteigerseminar" von Martin Uzak, bhv Verlag"

from Tkinter import *
import random
import time
import thread
import os
#import sys


class meinSpiel:
    def __init__(self, master):
        self.master = master
        self.datadir = os.path.join(os.getcwd(), 'data') # get the path to the data subdirectory
        self.logfilename = "logfile.txt"
        self.lastline = ""
        self.spiele = 0 # number of games played
        self.computersiege = 0 # number of computer victorys
        self.spielersiege = 0  # number of player victorys
        #--- Vorbereitung---
        if os.name == "posix":
            if not os.path.isdir(os.path.join(os.environ["HOME"],".rockpaperscissors")):
                os.mkdir(os.path.join(os.environ["HOME"], ".rockpaperscissors"))
            if os.path.isfile(os.path.join(os.environ["HOME"],".rockpaperscissors","logfile.txt")):
                self.logfilename = os.path.join(os.environ["HOME"],".rockpaperscissors","logfile.txt")
                self.lastline = self.getlastline() # open and close logfile
                (self.spiele, self.computersiege, self.spielersiege) = self.alteWerte()
            else:
                self.logfilename = os.path.join(os.environ["HOME"],".rockpaperscissors","logfile.txt")
                (self.spiele, self.computersiege, self.spielersiege) = (0,0,0)
                self.newlogfile() # create an empty logfile
        else: # mac or windows
            if os.path.isfile("logfile.txt"):
                #self.logfilename = "logfile.txt"
                self.lastline = self.getlastline()
                (self.spiele, self.computersiege, self.spielersiege) = self.alteWerte()
            else:
                (self.spiele, self.computersiege, self.spielersiege) = (0,0,0)
                self.newlogfile()
        #--- Ende der Vorbereitung ---
        #self.root = Tk()
        self.master.title('Schere - Stein - Papier')
        self.schereklein=PhotoImage(file=os.path.join(self.datadir,"schereklein.gif"))
        self.papierklein=PhotoImage(file=os.path.join(self.datadir,"papierklein.gif"))
        self.steinklein=PhotoImage(file=os.path.join(self.datadir,"steinklein.gif"))
        self.scherekleinc=PhotoImage(file=os.path.join(self.datadir,"scherekleinc.gif"))
        self.papierkleinc=PhotoImage(file=os.path.join(self.datadir,"papierkleinc.gif"))
        self.steinkleinc=PhotoImage(file=os.path.join(self.datadir,"steinkleinc.gif"))
        self.computerklein=PhotoImage(file=os.path.join(self.datadir,"computerklein.gif"))
        self.spielergewinnt = False # playerwins 
        self.computergewinnt = False # computerwins
        self.wintext = ""
        self.winagain = False # player wins again
        self.looseagain = False # player looses again
        self.titel = ""
        self.tiefe = {"schere":40, "stein":120, "papier":200}
        self.spritenamer = {"schere":self.schereklein,
                            "stein":self.steinklein,
                            "papier":self.papierklein}
        self.spritenamel = {"schere":self.scherekleinc,
                            "stein":self.steinkleinc,
                            "papier":self.papierkleinc}
        #self.gesamtbild=PhotoImage(file="rock_paper_scissors.gif")
        #self.grundlage = Label(self.master, image=self.gesamtbild,)
        self.grundlage = Label(self.master,  bg="blue") # maybe better without bg ?
        #     LabelFrame,  text = "Computer (links) gegen Spieler (rechts)",
        self.grundlage.grid()       
        self.leader = ""
        self.leadercalc()
        self.punktestand=StringVar(self.grundlage)
        self.punktestand.set(self.leader + "\nRunde: %s - %s:%s" % (self.spiele, self.computersiege, self.spielersiege))
        self.labelcomputer=Label(self.grundlage, image=self.computerklein).grid(row=1, rowspan=3, column=1)
        self.buttonexit=Button(self.grundlage, text="aufhören", command=self.master.quit).grid(row=3,column=1)
        self.labelscore=Label(self.grundlage, textvariable = self.punktestand)
        self.labelscore.grid(row=1, column=1)
        self.label1=Label(self.grundlage, image=self.scherekleinc).grid(row=1, column=2)
        self.label2=Label(self.grundlage, image=self.steinkleinc).grid(row=2, column=2)
        self.label3=Label(self.grundlage, image=self.papierkleinc).grid(row=3, column=2)
        self.canvas=Canvas(self.grundlage, width=200, height=240)
        self.canvas.grid(row=1, rowspan=3, column=3) # now grid take care of my canvas
        self.buttonschere=Button(self.grundlage, text="Schere", image=self.schereklein)
        self.buttonschere.bind("<Button-1>", lambda event: self.klickauswertung("schere"))
        self.buttonschere.grid(row=1, column=4)
        self.buttonstein=Button(self.grundlage, text="Stein", image=self.steinklein) # command=self.machepfeil
        self.buttonstein.bind("<Button-1>", lambda event: self.klickauswertung("stein"))
        self.buttonstein.grid(row=2, column=4)        
        self.buttonpapier=Button(self.grundlage, text="Papier", image=self.papierklein)
        self.buttonpapier.bind("<Button-1>", lambda event: self.klickauswertung("papier"))
        self.buttonpapier.grid(row=3, column=4)

    ##    def gameover(self):
    ##        """ quit the game """
    ##        logfile.close()
    ##        self.master.quit
    ##        print "bye-bye"

    def getlastline(self):
        """read the logfile, returns the last line"""
        x = file(self.logfilename, "r")
        while True:
            line = x.readline()
            if len(line)==0: #eof
                break
            lastline = line
        x.close()
        return lastline
  
    def alteWerte(self):
        """ set some values using the lastline from the logfile"""
        try:
            return (int(self.lastline.split("Runde: ")[1].split(" ")[0]),
                    int(self.lastline.split("(computer:spieler):")[1].split(":")[0]),
                    int(self.lastline.split("(computer:spieler):")[1].split(":")[1]),)
        except:
            #print "Fehler in logfile. Ich beginne logfile neu zu schreiben"
            #newlogfile(logfilename)
            raise SystemExit, "Fehler in 'logfile.txt'. Bitte den logfile.txt löschen"

    def newlogfile(self):
        """create a new logfile"""
        logfile = file(self.logfilename,"w")
        logfile.write("== Start ==\n")
        logfile.write("Zeit:%s Runde: %s Computer spielt: %s Spieler spielt: %s Punkte (computer:spieler): %s:%s" %  (time.localtime(), 0, "nichts","nichts", 0, 0) + "\n")
        logfile.close()

    def leadercalc(self):
        if self.computersiege > self.spielersiege:
            self.leader = "COMPUTER:Spieler"
        elif self.computersiege < self.spielersiege:
            self.leader = "Computer:SPIELER"
        else:
            self.leader = "Computer:Spieler"

    def klickauswertung(self, spielerauswahl):
        """the game logic of playing one game"""
        self.spiele += 1
        self.titel = "Spiel Nr. %s Computer %s : %s Player" % (self.spiele, self.computersiege, self.spielersiege)
        computer = random.choice(["schere", "stein", "papier"])
        if ((spielerauswahl == "stein" and computer == "schere") or 
            (spielerauswahl == "schere" and computer == "papier") or   
            (spielerauswahl == "papier" and computer == "stein")):
            self.spielergewinnt = True
            self.computergewinnt = False
            self.wintext = "Du gewinnst :-)"
            self.spielersiege += 1
        elif ((computer =="stein" and spielerauswahl == "schere") or
              (computer =="schere" and spielerauswahl == "papier") or
              (computer =="papier" and spielerauswahl == "stein")):
            self.spielergewinnt = False
            self.computergewinnt = True
            self.wintext = "Du verlierst :-("
            self.computersiege += 1
        else:
            self.wintext = "Unentschieden"
            self.spielergewinnt = False
            self.computergewinnt = False
        # now i start a new thread of each "sprite" in the canvas!
        thread.start_new_thread(self.animation,(spielerauswahl, True))
        thread.start_new_thread(self.animation,(computer, False))
        thread.start_new_thread(self.makeflytext,(self.wintext,))
        self.punktestand.set(self.leader + "\nRunde: %s - %s:%s" % (self.spiele, self.computersiege,self.spielersiege))
        timetuple = time.localtime()
        #self.pretext = "Computer played %s, you played %s." % (computer.lower(), spielerauswahl.lower()) 
        #self.pretext += "\nResult: " + self.wintext
        logfile = file(self.logfilename, "a")
        #logfile.write(self.pretext)
        logfile.write("Zeit:%s Runde: %s Computer spielt: %s Spieler spielt: %s Punkte (computer:spieler): %s:%s" %  (timetuple, self.spiele, computer, spielerauswahl, self.computersiege, self.spielersiege) + "\n")
        logfile.close()
        self.leadercalc() # who leads the game ?
        

    def makeflytext(self, wintext):
        """ create and move 'text-sprites' on the canvas. Also kill the sprites"""
        try:
            time.sleep(1)
            sleeptime = .001 # more sleeptime makes movement slower
            starttime = time.time()
            flytext = self.canvas.create_text(50,50,text = wintext)
            if wintext == "Unentschieden":
                self.canvas.itemconfig(flytext, fill="black")
            elif wintext == "Du verlierst :-(":
                self.canvas.itemconfig(flytext, fill="red")
            else:
                self.canvas.itemconfig(flytext, fill="blue")
            self.canvas.lower(flytext)
            while time.time() - starttime < 1.5:
                self.canvas.move(flytext, 0, -1)
                time.sleep(sleeptime)
                sleeptime += .001 # this should lower the flyspeed over time
            self.canvas.delete(flytext)
        except:
            print "Fehler bei flytext"
    
    def animation(self, auswahl, human):
        """ create, move and kill 2 sprites"""
        try:
            lifetime = 3
            sleeptime = .01
            slowtime = .015
            starttime=time.time()
            if human:
                spritestart = 235
                bedingung1 = "self.canvas.coords(sprite)[0] > 150"
                bedingung2 = "self.canvas.coords(sprite)[0] < 235"
                xmove = -1
                spriteimage = self.spritenamer[auswahl]
            else: #computer
                spritestart = -35
                bedingung1 = "self.canvas.coords(sprite)[0] < 60"
                bedingung2 = "self.canvas.coords(sprite)[0] > -35"
                xmove = 1
                spriteimage = self.spritenamel[auswahl]
            sprite = self.canvas.create_image(spritestart, self.tiefe[auswahl], image=spriteimage)   
            while eval(bedingung1) and time.time() - starttime < lifetime:
                self.canvas.move(sprite, xmove,0)
                if self.canvas.coords(sprite)[1] < 120:
                    self.canvas.move(sprite, 0, 1)
                elif self.canvas.coords(sprite)[1] > 121:
                    self.canvas.move(sprite, 0, -1)
                time.sleep(sleeptime)
            if (self.computergewinnt and human) or (self.spielergewinnt and not human):
                lifetime +=2
                while eval(bedingung2) and time.time()-starttime < lifetime:
                    self.canvas.move(sprite, xmove *- 1,0)
                    time.sleep(sleeptime)
            elif (self.spielergewinnt and human) or (self.computergewinnt and not human):
                lifetime +=2
                while eval(bedingung2) and time.time() - starttime < lifetime:
                    self.canvas.move(sprite, xmove ,0)
                    time.sleep(slowtime)
            while time.time() - starttime < lifetime:
                time.sleep(sleeptime)
            self.canvas.delete(sprite)
        except:
            print "Fehler bei animation"

#-- this is the game --

#-- Tkinter main loop --
root = Tk()
spiel=meinSpiel(root)
root.mainloop()
http://spielend-programmieren.at
schlangenbeschwörer
User
Beiträge: 419
Registriert: Sonntag 3. September 2006, 15:11
Wohnort: in den weiten von NRW
Kontaktdaten:

Hi HorstJENS,
ich finde das Spiel eigentlich ganz cool, nur diese kleinen "Optik-Fehler" im Bildaufba bei der Animation, wenn man zuschnell hintereinander klickt, sind ein wenig störend. Ich weiß aber auch nicht, woher die kommen (hab nur kurz über den Code geschaut).Ich würde aber,wenns nicht zu ändern ist, vieleicht die Animation etwas schneller laufen lassen und während des Threads eine "Klick-Sperre" einbauen, sodass immer nur eine Animation ausgeführt wird. Ist es außerdem normal bzw. eingeplant, dass die Bilder auf der linken Seite am Anfang verschwinden und nicht wiederaufgebaut werden? Ansonsten echt gute Idee. :wink:
Gruß jj
abgdf

Witzig und gut programmiert.

Nur: Kommt es bei diesem Spiel nicht gerade auf die Psychologie zwischen zwei menschlichen Spielern an ?

Viele Grüße
Antworten