[Tutor] Teach-yourself game design site... for Python?

2008-01-18 Thread James Newton
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

2008-01-16 Thread James Newton
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

2008-01-11 Thread James Newton
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

2008-01-11 Thread James Newton
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

2008-01-10 Thread James Newton
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

2008-01-09 Thread James Newton
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

2008-01-09 Thread James Newton
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

2008-01-07 Thread James Newton
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

2008-01-07 Thread James Newton
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

2008-01-04 Thread James Newton
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)

2008-01-04 Thread James Newton
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