Reputation: 11
I've already searched and found nothing about this topic, so I'll ask here.
I'm starting to develop very basic games, and I want to load a picture into my background. I'm using a eBook on Python to help me do this and, according to it, the following code is right:
from tkinter import *
import time
import random
Width = 1000
Height = (Width/12)*9
class Game:
def __init__(self):
self.tk = Tk()
self.tk.title("Monster Rush")
self.tk.resizable(0, 0)
self.tk.wm_attributes("-topmost", 1)
self.canvas = Canvas(self.tk, width=Width, height=Height, highlightthickness=0)
self.canvas.pack()
self.tk.update()
self.canvas_height = 500
self.canvas_width = 500
self.bg = PhotoImage(file="anipedra.gif")
w = self.bg.width()
h = self.bg.height()
for x in range(0, 5):
for y in range(0, 5):
self.canvas.create_image(x * w, y * h, image=self.bg, anchor='nw')
self.sprites = []
self.running = True
def mainloop(self):
while 1:
if self.running == True:
for sprite in self.sprites:
sprite.move()
self.tk.update_idletasks()
self.tk.update()
time.sleep(0.01)
class Enemy(Game):
def __init__(self):
self.e = Game()
self.e.mainloop()
class Player(Game):
def __init__(self):
self.e = Game()
self.e.mainloop()
Troll = Enemy()
Grunt = Enemy()
Minion = Enemy()
Player = Player()
But every time I run this:
Traceback (most recent call last):
File "C:\Users\Nuno\Desktop\Python\Projectos\Monster Rush\Monster Rush (T.D.).py", line 47, in <module>
Troll = Enemy()
File "C:\Users\Nuno\Desktop\Python\Projectos\Monster Rush\Monster Rush (T.D.).py", line 39, in __init__
self.e = Game()
File "C:\Users\Nuno\Desktop\Python\Projectos\Monster Rush\Monster Rush (T.D.).py", line 20, in __init__
self.bg = PhotoImage(file="background.gif")
File "C:\Users\Nuno\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 3393, in __init__
Image.__init__(self, 'photo', name, cnf, master, **kw)
File "C:\Users\Nuno\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 3349, in __init__
self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't recognize data in image file "background.gif"
If it is the .gif in the above code (or any other format):
The file stops responding and crashes.
Can anyone help me?
Upvotes: 1
Views: 1625
Reputation: 109
Maybe this ! Some image software's can and do at times change the extension endings to image files. They can capitalize the extensions on demand. Such as .gif to .GIF or jpeg to JPEG etc. You wont realize this until you upload the files onto a website, then you will see the capitalized extensions. Googles infamous Picaso Download did this to my computer and i had to do a re system install to fix it. Not related but Windows alters the jpeg format also in secrecy in some older XP versions. Have someone test your code on another machine.
Upvotes: 0
Reputation: 386352
The error in your stack trace is saying that the file isn't really a GIF file. Are you certain it is actually a gif file, or could it be some other file that someone renamed to have .gif as a suffix?
You also have several critical design flaws.
In a well designed tkinter app you must always have exactly one root window. You're creating four (or eight...) -- one for each player and enemy object.
You have classes that both inherit from Game
and create a Game
instance itself. This makes absolutely no sense. Either inherit from Game or create an instance, but don't do both. Though, since Game
creates a root window, it makes no sense to create more than one Game
object.
You aren't using the event loop properly. You aren't ever letting tkinter process certain events. You have your own infinite loop in which you call update_idletasks()
, but that only handles screen refreshes and other "idle" events. It won't handle key presses or mouse clicks. You call update
but it outside of the infinite loop so it never gets called.
sleep
in a GUI. It does exactly what it says: it puts your application to sleep. While it's sleeping it won't refresh the screen and it won't process mouse or keyboard events. The application is truly dead.While I don't know exactly what your intentions are, you can probably rewrite your own custom mainloop
to leverage the real event loop by doing something like this:
def mainloop(self):
if self.running == True:
for sprite in self.sprites:
sprite.move()
self.tkafter(30, self.mainloop)
You need to set 30
to represent how fast you want the display to update. The value is in milliseconds, so 30 represents 30fps. Also, you need to call the mainloop
function of the root window exactly once so that it can process events.
Upvotes: 2