[Tutor] Teach-yourself game design site... for Python?
Hi folks, I've just come across this article on the BBC site: http://news.bbc.co.uk/2/hi/technology/7189694.stm You can see some of the games that are either created collaboratively or designed to be improved collaboratively at: http://www.myglife.org/usa/Boulder-GameDev/en/play/othergames Here's the home page for the My G-Life site: http://www.myglife.org/ So my question is: is there something similar in the Python community? James ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Programming Ideas, need some focus
Eric Abrahamsen wrote I spent some time this afternoon googling the One Laptop Per Child (OLPC) project (the GUI is done with Python and PyGTK), to see if there were any collaborative open-source projects I could contribute to. Seems like a perfect opportunity to get a little more Python experience and actually do something useful. I found lots of noble exhortations to help, but very little in the way of specifics. Does anyone know of any ongoing projects that could use volunteers? Of the middling-capable range? Hi Eric, I've got a project that I could use help on :-) I'm a long-time game developer, but a newbie to Python. I'm currently working on a Snakes and Ladders game, as I see this as a good way for young children to learn: * Putting numbers in the right order * Associating a value with the name of a number * fFamiliarity with written numbers * Taking turns * ... and a whole range of concepts associated with numeracy. You can find my latest build at: http://olpc-dev.fuelindustries.com/snakes_080116.zip. Things that need to be done: * Distribute counters evenly if there are more than one on the same square * Set up a multi-user environment, so that players can join a game hosted on a different machine * Provide a system for selecting the voice-over language and other preferences * Tweak the game play * Ensure that the activity is as miserly with CPU-time and disk space as possible * ... Nice to have: * Allow users to select their own graphics (created in a different activity) for the background, dice and counters * Add an arrow or a pointing finger to indicate which square to click on next * Advanced mode using: - two dice - drag and drop to move the counter to its final square * Choice of writing system for the numbers * ... I've just received a couple of XO machines from the Give One Get One initiative, and am currently looking into getting the game to run on the laptop. I have a number of other game ideas that I want to bring to the XO: * Matching images (more flexible than the built-in Memorize game) * Drawing Letters * Abacus Shapes * Black boxes (a game to develop mental imagery) * Picture Book Reader I also have plans for an activity that helps children to understand musical notation, without having to learn the theory or the practice first. But that is currently way out of my depth, as far as my Python abilities are concerned. I'm based in Ottawa, Canada. Do Snakes and Ladders (or any of the other ideas) inspire you? James ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
[Tutor] Iterating backwards
Hi Pygamers, I have created a series of pygame sprites. Visually, these sprites represent counters and may overlap. I want to determine which sprite the user clicked on. This seems to me to be a fairly standard feature of a game interface, so I imagine that there is already a standard technique for achieving it. My current implementation (see below) is to use a for statement on the pygame.sprite group that contains the sprites. This means that I have to test all the sprites to determine the top-most sprite that is under the mouse. The sprites are blitted to the screen in the order they were added to the sprite group, so the sprite that appears on top is the last one in the group. I'd like to start at the top-most sprite and work backwards through the sprites in the group, and then use break to stop as soon as I find a sprite whose rect collides with the mouse position. In my code below, I've tried replacing the line... for vCounter in counters: # the pygame.sprite.RenderPlain() group ... with: vRange = range(len(counters)) vRange.reverse() for ii in vRange: vCounter = counters[ii] However this results in an error: #TypeError: 'Group' object is unindexable Is there a way to iterate backwards through a pygame sprite group? Or can you recommend an alternative method to achieve the same ends? My overall aim is to make the sprite the user clicks on jump to the top, so the order of the sprites in the group will change over time. Thanks in advance, James --- Here's my barebones code. It assumes that there are three 64 x 64 pixel image files named Counter_1.png through Counter_3.png in a subfolder named data. import os import pygame # Add QUIT, KEYDOWN and other event names to module namespace from pygame.locals import * # COUNTER class Counter(pygame.sprite.Sprite): Creates a counter sprite from an image and places it in a tiled pattern relative to other counters def __init__(self, aIndex): pygame.sprite.Sprite.__init__(self) self.index = aIndex # Create a surface that we need to name image to overwrite # the Sprite's own .image property, which remains as None vFileName = Counter_+str(aIndex + 1)+.png vPath = os.path.join('data', vFileName) self.image = pygame.image.load(vPath).convert() self.rect = self.image.get_rect() # Scatter the counters so they overlap self.rect.move_ip(aIndex * 24, aIndex * 24) def is_opaque_at(self, x, y): if self.rect.collidepoint(x, y): return True return False # COUNTER # MAIN def main(): Demonstrates the use of pygames RenderUpdates sprite group # Initialization pygame.init() clock = pygame.time.Clock() screen = pygame.display.set_mode((120, 120)) counters = pygame.sprite.RenderPlain() for i in range(0, 3): vCounter = Counter(i) vCounter.add(counters) # Infinite loop while True: clock.tick(5) # 5 frames per second is quite sufficient for event in pygame.event.get(): if event.type in (QUIT, KEYDOWN): pygame.quit() return elif event.type == MOUSEBUTTONDOWN: vPos = pygame.mouse.get_pos() vIndex = None for vCounter in counters: vClicked = vCounter.is_opaque_at(*vPos) if vClicked: vIndex = vCounter.index print Sprite +str(vIndex)+ is under the mouse #break # Uncomment to return the *lowest* sprite if vIndex != None: print vIndex counters.draw(screen) pygame.display.update() # Infinite loop # MAIN if __name__ == '__main__': main() ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Iterating backwards
Kent Johnson wrote: I guess counters is iterable but not a sequence. Try this: for vCounter in reversed(list(counters)): Hi Kent, Thanks for your help. This solves my problem: vPos = pygame.mouse.get_pos() for vCounter in reversed(list(counters)): if vCounter.rect.collidepoint(*vPos): # vCounter now points to the sprite we want to treat break :-) James ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
[Tutor] Opening a window to fit an image
Hi Python Pros, I want to create a window to fit an image that I read in on the fly. I'm using pygame to load images and to create the window. I find I have to use pygame.display.set_mode() twice: once to allow me to use pygame.image.loadfile(), and once to reset the window size after I have been able to determine the size of the loaded image. Does this have any undesired side-effects? Is there a better way of doing this? Here's the relevant extract of my script. import os import pygame def main(): pygame.init() # You must use display.set_mode() before you can use image.load # If you don't, you get an error: No video mode has been set screen = pygame.display.set_mode((1, 1)) # Now we can load an image file and find out its size vFile = 'image.bmp' # in same folder as script background = pygame.image.load(vFile).convert() vRect = background.get_rect() # Reset the display mode to fit the image screen = pygame.display.set_mode((vRect[2], vRect[3])) # Show the image in the window screen.blit(background, (0, 0)) pygame.display.update() # SNIP: code to make application exit gracefully main() Thanks in advance for your help, James ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
[Tutor] Scope and elegance revisited
Hi Python Purists! I want all instances of a given class to share a piece of information, but I want to set that information on the fly. I have found that this works: class Foo(object): # class_variable = None # There is no real need to declare this def __init__(self): print self.__class__.class_variable def main(): Foo.class_variable = Done Foo() if __name__ == '__main__': main() Running the script prints out Done as expected. However, this looks ugly to me. Is there a more elegant way of doing this? To give you the context: my application allows you to select a skin for the user interface. I want to set the access path to the skin folder as a class variable, so that all instances of that class use images from the appropriate folder. The access path will be read in from a preferences file before any instances of the class are created. Thanks in advance for your advice. James ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Scope and elegance revisited
Kent Johnson wrote: To give you the context: my application allows you to select a skin for the user interface. I want to set the access path to the skin folder as a class variable, so that all instances of that class use images from the appropriate folder. The access path will be read in from a preferences file before any instances of the class are created. Why do you have multiple instances of the class? You might be interested in the Borg pattern: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531 Hi Kent, Thanks for your suggestion. The folder in question contains images for counters for a board game. Each player instance will use a separate counter image, but all counter images will be chosen from the same folder. It looks as if the Borg pattern would make all players use the same counter image. Or am I misunderstanding something? James ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
[Tutor] Scope and elegance
Hi Python Practicioners! I'm trying to come to terms with how Python handles the scope of objects. In particular, I'd like to create an instance of one class and make it available inside instances of other classes. Something like: # Test 1- # I want a global instance of this class... class Foo(object): def doFoo(self): return foo # So that I can call one of its functions from another instance class Bar(object): def doBar(self): # I'd like be able to call a global object, but this fails: # global name 'foo_instance' is not defined return foo_instance.doFoo() def main(): foo_instance = Foo() bar_instance = Bar() print bar_instance.doBar() if __name__ == '__main__': main() # I know that I can pass a pointer to foo_instance as a parameter to the Bar() call. For example, this will work: # Test 2 - class Foo(object): def doFoo(self): return foo class Bar(object): def doBar(self, aFooInstance): return aFooInstance.doFoo() def main(): foo_instance = Foo() bar_instance = Bar() print bar_instance.doBar(foo_instance) if __name__ == '__main__': main() # I know that I can also create a global instance outside the main() function. This will also work: # Test 3 - class Foo(object): def doFoo(self): return foo class Bar(object): def doBar(self): return foo_instance.doFoo() foo_instance = Foo() def main(): bar_instance = Bar() print bar_instance.doBar() if __name__ == '__main__': main() # However, this assumes that the Foo instance() is independent of anything that needs to be done inside the main() function. To put the question in context: in the Snakes and Ladders game that I am making, I have a board divided into 100 squares. I want a Counter instance to know which position on the Board it should move to. I may have several Counter instances, but only one Board instance. Each Counter knows the index number of the square it should move to. The Board instance knows how to convert that index number into a screen position. I want the Counter instances to be able to ask the Board instance for that screen position. Is it unPythonic of me to: a) Want to create the Board instance inside the main() function AND b) Want the Board instance to be globally available so that Counters and other objects can talk to it directly? Or is there just a declaration that I have overlooked that can make an instance created inside a function visible inside any instance? I am not so much concerned in getting this to work (I can already do that); I am more concerned with understanding how to treat this in the most Pythonesque way. Thanks in advance for your insights, James ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Scope and elegance
Kent Johnson [mailto:[EMAIL PROTECTED] wrote: Why does a Counter need to know about screen position? It sounds like the Counter might be doing too much. Maybe the Counters should be attributes of the Board which can ask them their index numbers and do the appropriate drawing? Maybe the code that is drawing the counter should ask the Board where to draw it? I can't tell for sure but it sounds like your design might be inside out. Hi Kent, Thanks for your reply. It has encouraged me to think in new directions. James ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
[Tutor] Snakes and Ladders
Hi Python People! I've recently started learning Python in order to create educational content for the One Laptop Per Child project: http://www.laptop.org/en/vision/index.shtml The first application I'm working on is a game of Snakes and Ladders, to help younger children understand the concepts of counting and placing numbers in the right order. You can find a first draft of the game here: http://olpc-dev.fuelindustries.com/snakes_080104.zip To play, click on the dice to obtain a number, then click on the board squares in the right order. When you've counted up to the number on the dice, you'll need to click on the dice again to continue. I'm looking for help with a number of issues (I'll treat each of the issues in a separate thread). To start with what I hope will be an easy one: *** I'm importing a graphic named Counter_1.png for the counter. I'd like its background to be transparent, using the PNG's built-in alpha channel. As this is for the OLPC laptop, where every electron is precious, I want to load the minimum number of modules to have the minimum processor overhead. What is the cheapest way (in terms of RAM usage and CPU cycles) to display a PNG image with alpha-transparency? I am aware of the VisionEgg demo at... http://visionegg.org/svn/trunk/visionegg/demo/alpha_texture.py ... but I am concerned that this would be overkill for a simple 2D application: VisionEgg requires a mini-series of other modules before it will work. Or should I forgo alpha-transparency and simply use pygame's image.set_colorkey(), which will give me a pixelated edge to the transparent parts of the image? *** Thanks in advance, James ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Snakes and Ladders (is: PNG transparency)
Hello again Python Programmers! To reply to my own question: -Original Message- I'm importing a graphic named Counter_1.png for the counter. I'd like its background to be transparent, using the PNG's built-in alpha channel. -- I've modified the code at... http://rene.f0o.com/mywiki/LectureFour#head-52d34285fd010fdc1164ea8ccbe 77980cac42b61 ... so that it uses pygame's image.convert_alpha() if the loaded image appears to have an alpha channel (see below). My code does this by checking if image.get_masks()[3] is non-zero. However, the pygame documentation at... http://www.pygame.org/docs/ref/surface.html#Surface.get_masks ... states that .get_masks() is not needed for normal Pygame usage. This suggests to me that I am missing a more standard way of detecting if an pygame.image has an alpha channel. Is my technique likely to fail? Is there a better way of doing this? Thanks in advance for your insights, James def load_image(filename, colorkey=None): # INPUT: filename should be an absolute or relative path to an # image file #colorkey should be None, an rgb tuple, or -1, in which # case the color of the top left pixel will be used. # ACTION: Attempts to read in an image from filename, and (if # required) applies a transparency mask to it. # OUTPUT: Returns a pygame Surface try: image = pygame.image.load(filename) except pygame.error, message: print Cannot load image:, filename raise SystemExit, message # Make a new copy of a Surface and convert it to screen depth vAlpha = image.get_masks()[3] # (255, 65280, 16711680, -16777216) for an RGBA image # (31744, 992, 31, 0) for a 2-bit/pixel rgbx BMP image if vAlpha != 0: # The image has an alpha channel image = image.convert_alpha() else: # The image has no alpha channel, but we may have a colorkey image = image.convert() if colorkey is not None: if colorkey is -1: colorkey = image.get_at((0, 0)) image.set_colorkey(colorkey, RLEACCEL) return image ___ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor