Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcoolestdude1 <arielzamparini@gmail.com>2010-02-24 20:51:01 (GMT)
committer coolestdude1 <arielzamparini@gmail.com>2010-02-24 20:51:01 (GMT)
commit677b839ee2945455e61bb8cace2d9ea921b0d4fc (patch)
treebe7262a98fb590c9bf35ff008aa31b327ade9c6c
parent6800d2cda6c657dfa910fd48b522bcb7c0dfcd5b (diff)
cloning my repo back to main for the update
-rw-r--r--activity/Blocku.pngbin0 -> 49171 bytes
-rw-r--r--activity/MANIFEST.in4
-rw-r--r--activity/NEWS0
-rw-r--r--activity/POTFILES.in1
-rw-r--r--activity/activity/activity.info6
-rw-r--r--activity/activity/blocku.svg65
-rw-r--r--activity/blocku.py320
-rw-r--r--activity/blocku_activity.py67
-rw-r--r--activity/data/Thumbs.dbbin0 -> 11776 bytes
-rw-r--r--activity/data/background.pngbin0 -> 3835 bytes
-rw-r--r--activity/data/block.pngbin0 -> 481 bytes
-rw-r--r--activity/data/blocku.pngbin0 -> 23629 bytes
-rw-r--r--activity/data/grid.pngbin0 -> 617 bytes
-rw-r--r--activity/setup.py4
-rw-r--r--activity/sugargame/__init__.py1
-rw-r--r--activity/sugargame/canvas.py56
-rw-r--r--activity/sugargame/event.py241
-rw-r--r--blocku.py140
-rw-r--r--data/Thumbs.dbbin0 -> 11776 bytes
-rw-r--r--data/grid.pngbin0 -> 617 bytes
20 files changed, 879 insertions, 26 deletions
diff --git a/activity/Blocku.png b/activity/Blocku.png
new file mode 100644
index 0000000..e6fed23
--- /dev/null
+++ b/activity/Blocku.png
Binary files differ
diff --git a/activity/MANIFEST.in b/activity/MANIFEST.in
new file mode 100644
index 0000000..d45c18c
--- /dev/null
+++ b/activity/MANIFEST.in
@@ -0,0 +1,4 @@
+include *.py *.txt *.png *.jpg NEWS README
+recursive-include activity *.svg *.info
+include olpcgames/COPYING
+recursive-include olpcgames *.py
diff --git a/activity/NEWS b/activity/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/activity/NEWS
diff --git a/activity/POTFILES.in b/activity/POTFILES.in
new file mode 100644
index 0000000..6c9e6b4
--- /dev/null
+++ b/activity/POTFILES.in
@@ -0,0 +1 @@
+include *.py
diff --git a/activity/activity/activity.info b/activity/activity/activity.info
new file mode 100644
index 0000000..90d5f6b
--- /dev/null
+++ b/activity/activity/activity.info
@@ -0,0 +1,6 @@
+[Activity]
+name = Blocku
+service_name = org.sugarlabs.Blocku
+class = blocku_activity.BlockuActivity
+icon = blocku
+activity_version = 1
diff --git a/activity/activity/blocku.svg b/activity/activity/blocku.svg
new file mode 100644
index 0000000..40e804b
--- /dev/null
+++ b/activity/activity/blocku.svg
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_svg "http://www.w3.org/2000/svg">
+ <!ENTITY ns_xlink " http://www.w3.org/1999/xlink">
+ <!ENTITY stroke_color "#000000">
+ <!ENTITY fill_color "#AAAAAA">
+]>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="45"
+ height="45"
+ id="svg2215"
+ sodipodi:version="0.32"
+ inkscape:version="0.45.1"
+ sodipodi:docname="activity-tictactoe.svg"
+ sodipodi:docbase="/home/mcfletch/olpc/code/productive/Productive.activity/activity"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <metadata
+ id="metadata2232">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs2230" />
+ <sodipodi:namedview
+ inkscape:cy="22.5"
+ inkscape:cx="22.5"
+ inkscape:zoom="20.333333"
+ inkscape:window-height="1127"
+ inkscape:window-width="1600"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:current-layer="svg2215" />
+ <path
+ style="fill:&fill_color;;fill-opacity:0.75;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+ d="M 15.534377,13.195073 C 15.791157,11.763199 17.933873,10.957056 19.095051,10.602777 C 20.105324,9.9896474 22.787279,11.783276 22.898009,11.878244 C 23.416714,11.4045 23.425424,11.364819 23.770372,10.827625 C 23.601381,10.487593 22.939011,9.4960211 22.623866,9.0601604 C 22.623866,9.0601604 22.742529,8.9416821 22.812515,8.8485545 C 23.845529,9.0345464 24.306088,9.4281391 24.871474,9.6093119 C 25.668983,8.6239218 25.446369,9.2835875 25.828152,8.4790083 C 25.13443,8.0435993 21.714652,2.4366571 13.009162,7.2066853 C 9.0621306,9.978134 8.895617,8.7992283 6.932744,9.097028 C 5.2661869,9.464109 3.3873402,9.399673 2.1395212,10.873663 C 1.0843595,12.628037 1.1078166,14.962252 1.6747872,16.900122 C 2.4157932,18.645311 4.1348484,20.102541 6.0059863,20.181304 C 8.0128058,20.306614 8.5055554,18.063138 9.9449657,17.103325 C 11.084352,16.320185 12.66414,14.87405 13.854988,16.927543 C 15.319531,18.689841 17.42612,19.671958 18.836759,21.491545 C 20.428246,22.860338 21.802711,24.499357 23.595734,25.605883 C 25.959172,27.177087 27.743932,29.469159 29.192905,31.938198 C 30.3509,33.066387 30.214635,34.990613 31.186387,36.125386 C 32.955624,37.317013 35.489203,37.310037 36.995239,35.662719 C 38.298566,34.629828 39.238431,33.219156 40.335881,31.969909 C 41.40463,30.61446 41.737725,28.191719 40.036666,27.203889 C 37.921417,25.933868 35.386076,25.826524 33.06998,25.148133 C 31.392091,24.657752 29.525099,24.370514 28.305913,22.933725 C 26.477551,21.069741 24.407817,19.456446 22.158802,18.204958 C 20.689355,17.069909 19.172075,16.000044 17.716766,14.850016 C 16.9591,14.352917 16.087813,13.95948 15.534377,13.195073 z "
+ id="path2242"
+ sodipodi:nodetypes="ccccccccccccccccccccccscccc" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 7.9653982,19.368521 C 8.992869,17.523226 9.0484129,16.552739 9.0744982,15.127094 C 9.152233,13.679143 9.0097453,12.591507 8.3457541,11.372405 C 7.8839907,10.583866 6.0804649,9.1928072 5.6129699,9.3821562"
+ id="path2263"
+ sodipodi:nodetypes="cccc" />
+</svg>
diff --git a/activity/blocku.py b/activity/blocku.py
new file mode 100644
index 0000000..79baaf1
--- /dev/null
+++ b/activity/blocku.py
@@ -0,0 +1,320 @@
+
+"""Main Blocku game logic class
+
+import every thing that the activity needs and run game code
+
+Authored by Fran Rogers and Ariel Zamparini
+"""
+
+#!/usr/bin/python
+import pygame, random, os.path
+from pygame.locals import *
+from pygame import *
+
+try: import gtk
+except ImportError: gtk = None
+
+#see if we can load more than standard BMP
+if not pygame.image.get_extended():
+ raise SystemExit, "Sorry, extended image module required"
+
+#game constants
+SCREENRECT = Rect(0, 0, 640, 480)
+KEYBOARDMOVESPEED = 10
+
+
+def load_image(file):
+ "loads an image, prepares it for play"
+ file = os.path.join('data', file)
+ try:
+ surface = pygame.image.load(file)
+ except pygame.error:
+ raise SystemExit, 'Could not load image "%s" %s'%(file, pygame.get_error())
+ return surface.convert()
+
+def load_images(*files):
+ imgs = []
+ for file in files:
+ imgs.append(load_image(file))
+ return imgs
+
+class dummysound:
+ def play(self): pass
+
+def load_sound(file):
+ if not pygame.mixer: return dummysound()
+ file = os.path.join('data', file)
+ try:
+ sound = pygame.mixer.Sound(file)
+ return sound
+ except pygame.error:
+ print 'Warning, unable to load,', file
+ return dummysound()
+
+class Block(pygame.sprite.Sprite):
+ images = []
+ north=''
+ east=''
+ south=''
+ west=''
+ def __init__(self, n='', e='', s='', w='', x='', y=''):
+ pygame.sprite.Sprite.__init__(self, self.containers)
+ self.image = self.images[0].copy()
+ self.rect = pygame.Rect(x,y,64,64)
+ self.font = pygame.font.Font(None, 20)
+ self.font.set_italic(1)
+ self.color = Color('blue')
+ self.update()
+ self.north = n
+ self.east = e
+ self.south = s
+ self.west = w
+
+ def update(self):
+ #keep the block on the screen
+ self.rect = self.rect.clamp(SCREENRECT)
+ self.image = self.images[0].copy()
+ self.image.blit(self.font.render(str(self.north), 0, self.color),(26,3))
+ self.image.blit(self.font.render(str(self.east), 0, self.color),(47,25))
+ self.image.blit(self.font.render(str(self.south), 0, self.color),(26,47))
+ self.image.blit(self.font.render(str(self.west), 0, self.color),(5,25))
+ # game logic here for snapping to grid ...?
+ # when the block is snapped to the grid clamp the rect there
+ def move(self, direction):
+ # up = 0, right = 1, down = 2, left = 3
+ if direction == 0:
+ self.rect.move_ip(0,-KEYBOARDMOVESPEED)
+ if direction == 1:
+ self.rect.move_ip(KEYBOARDMOVESPEED,0)
+ if direction == 2:
+ self.rect.move_ip(0,KEYBOARDMOVESPEED)
+ if direction == 3:
+ self.rect.move_ip(-KEYBOARDMOVESPEED,0)
+
+ def grab(self, pos):
+ x, y = pos;
+ #print x , y
+ #print self.rect.left, self.rect.top
+ #self.rect = self.rect.move(x, y)
+ #remember the offset here is 32 as this will center the mouse in our 64pixel image
+ self.rect.left = x-32
+ self.rect.top = y-32
+ def rotate(self):
+ temp = self.north
+ self.north = self.east
+ self.east = self.south
+ self.south = self.west
+ self.west = temp
+ #print self.north, self.east, self.south, self.west
+
+class Puzzle:
+ def __init__(self):
+ #self.rule = rule
+ self.blocks = {}
+
+ def add_block(self, block, coords):
+ self.blocks[coords] = block
+
+ def get_blocks(self):
+ return self.blocks
+
+ def shuffle(self):
+ pass
+
+class Game:
+ def __init__(self):
+ # Set up a clock for managing the frame rate.
+ self.clock = pygame.time.Clock()
+
+ self.puzzle = Puzzle()
+
+ self.paused = False
+
+ def set_paused(self, paused):
+ self.paused = paused
+
+ # Called to save the state of the game to the Journal.
+ def write_file(self, file_path):
+ pass
+
+ # Called to load the state of the game from the Journal.
+ def read_file(self, file_path):
+ pass
+
+ # The main game loop.
+ def run(self):
+ self.running = True
+
+ if pygame.mixer and not pygame.mixer.get_init():
+ print 'Warning, no sound'
+ pygame.mixer = None
+
+ #set the screen up
+ winstyle = 0 # |FULLSCREEN
+ bestdepth = pygame.display.mode_ok(SCREENRECT.size, winstyle, 32)
+ screen = pygame.display.set_mode(SCREENRECT.size, winstyle, bestdepth)
+
+
+ # load images here
+ # for gifs img = load_image('filename.gif')
+ # for bmps img = pygame.image.load('filename.bmp') but our function handles that for us
+ # a note for graphics blit means copy pixels from screen.blit()
+ iconImg = load_image('blocku.png')
+ background = load_image('background.png')
+ # load images to pipe to the sprite classes
+ blockImg = load_image('block.png')
+ Block.images = [blockImg]
+ gridImg = load_image('grid.png')
+ # the test will need rects and positions i sugest make some kind of default
+ # this information can be held by each block as they are created but is made here
+
+ #get the image and screen in the same format
+ if background.get_bitsize() == 8:
+ screen.set_palette(background.get_palette())
+ else:
+ background = background.convert()
+
+ background.blit(gridImg,(200,200))
+ screen.blit(background,(0,0))
+ pygame.display.flip()
+
+ #to set the icon up and to decorate the game window
+ icon = pygame.transform.scale(iconImg, (32, 32))
+ pygame.display.set_icon(icon)
+ pygame.display.set_caption('Blocku')
+
+ #this next call is sort of like sprite batch . draw
+ spriteBatch = pygame.sprite.RenderUpdates()
+
+ #main blocku code structs
+ blocks = pygame.sprite.Group()
+ Block.containers = blocks,spriteBatch
+ #blocks are Block(n,s,e,w,x,y) xy= starting position
+ aBlock = Block(1,2,3,4,200,200)
+ bBlock = Block(5,6,7,8,300,300)
+
+ global debugText
+ debugText = ''
+ #see if there is a sprite font
+ if pygame.font:
+ spriteBatch.add(Text('Drawing call test '))
+ spriteBatch.add(mouseUpdate())
+
+ #if a key is down
+ global keyDown
+ keyDown = False
+ # it is important to note that like xna the origin is 0,0
+ # the top left of the current window
+ # print is trace in console
+ # and increases as you go down and to the right
+ # pygame has a collision detector under pygame.sprite.spritecollide(group,group,dokill)
+ # this will return a list of colliders, dokill will remove the colliders from the parrent group if true
+
+ while self.running:
+ # Pump GTK messages.
+ while gtk and gtk.events_pending():
+ gtk.main_iteration()
+
+ # Pump PyGame messages.
+ for e in event.get():
+ if e.type == QUIT or \
+ (e.type == KEYDOWN and e.key == K_ESCAPE):
+ return
+ elif e.type == pygame.VIDEORESIZE:
+ pygame.display.set_mode(e.size, pygame.RESIZABLE)
+ if e.type == MOUSEBUTTONDOWN:
+ event.set_grab(1)
+ elif e.type == MOUSEBUTTONUP:
+ event.set_grab(0)
+
+ # get the state of the keyboard for input
+ keystate = pygame.key.get_pressed()
+ if not keystate[K_SPACE]:
+ keyDown = False
+ # for key test use keystate[key] and a return of true will occur when key down
+ # clear/erase the last drawn sprites
+ spriteBatch.clear(screen, background)
+ # update all the sprites
+ spriteBatch.update()
+ # handle player input
+ if keystate[K_UP]:
+ aBlock.move(0)
+ if keystate[K_RIGHT]:
+ aBlock.move(1)
+ if keystate[K_DOWN]:
+ aBlock.move(2)
+ if keystate[K_LEFT]:
+ aBlock.move(3)
+ if keystate[K_SPACE] and not keyDown:
+ aBlock.rotate()
+ keyDown = True
+
+ #for block in blocks:
+ x, y = mouse.get_pos()
+
+ if event.get_grab():
+ debugText = 'holding mouse button 1'
+ if aBlock.rect.collidepoint(x,y):
+ aBlock.grab(mouse.get_pos())
+ debugText += 'grabed aBlock'
+ elif bBlock.rect.collidepoint(x,y):
+ bBlock.grab(mouse.get_pos())
+ debugText += 'grabed bBlock'
+ else:
+ debugText = ''
+ # note random here is random.random()
+ # note foreach here is for object in
+
+ # draw call for the screen
+ draw = spriteBatch.draw(screen)
+ pygame.display.update(draw)
+
+
+ # Try to stay at 30 FPS
+ self.clock.tick(30)
+
+class Text(pygame.sprite.Sprite):
+ text = ''
+ def __init__(self,txt=''):
+ pygame.sprite.Sprite.__init__(self)
+ self.font = pygame.font.Font(None, 20)
+ self.font.set_italic(1)
+ self.color = Color('blue')
+ self.update()
+ self.rect = self.image.get_rect().move(55, 80)
+ self.text = txt
+
+ def update(self):
+ global debugText
+ msg = self.text + debugText
+ self.image = self.font.render(msg, 0, self.color)
+
+class mouseUpdate(pygame.sprite.Sprite):
+ def __init__(self):
+ pygame.sprite.Sprite.__init__(self)
+ self.font = pygame.font.Font(None, 20)
+ self.font.set_italic(1)
+ self.color = Color('blue')
+ self.update()
+ self.rect = self.image.get_rect().move(50, 220)
+
+ def update(self):
+ msg = 'Mouse Position %s, %s' % mouse.get_pos()
+ self.image = self.font.render(msg, 0, self.color)
+
+# This function is called when the game is run directly from the command line:
+# ./TestGame.py
+def main():
+ # Initialize pygame
+ pygame.init()
+
+ # Initializa game
+ game = Game()
+
+ # Run the game
+ game.run()
+
+#call the "main" function if python is running this script
+if __name__ == '__main__':
+ main()
+
diff --git a/activity/blocku_activity.py b/activity/blocku_activity.py
new file mode 100644
index 0000000..f5856e1
--- /dev/null
+++ b/activity/blocku_activity.py
@@ -0,0 +1,67 @@
+from gettext import gettext as _
+
+import sys
+import gtk
+import pygame
+
+import sugar.activity.activity
+import sugar.graphics.toolbutton
+
+import sugargame.canvas
+
+import blocku
+
+class BlockuActivity(sugar.activity.activity.Activity):
+ def __init__(self, handle):
+ super(BlockuActivity, self).__init__(handle)
+
+ self.paused = False
+
+ # Create the game instance.
+ self.game = blocku.Game()
+
+ # Build the activity toolbar.
+ self.build_toolbar()
+
+ # Build the Pygame canvas.
+ self._pygamecanvas = sugargame.canvas.PygameCanvas(self)
+ # Note that set_canvas implicitly calls read_file when resuming from the Journal.
+ self.set_canvas(self._pygamecanvas)
+
+ # Start the game running.
+ self._pygamecanvas.run_pygame(self.game.run)
+
+ def build_toolbar(self):
+ stop_play = sugar.graphics.toolbutton.ToolButton('media-playback-stop')
+ stop_play.set_tooltip(_("Stop"))
+ stop_play.set_accelerator(_('<ctrl>space'))
+ stop_play.connect('clicked', self._stop_play_cb)
+
+ toolbar = gtk.Toolbar()
+ toolbar.insert(stop_play, 0)
+ toolbar.insert(gtk.SeparatorToolItem(), 1)
+
+ toolbox = sugar.activity.activity.ActivityToolbox(self)
+ toolbox.add_toolbar(_("Pygame"), toolbar)
+
+ toolbox.show_all()
+ self.set_toolbox(toolbox)
+
+ def _stop_play_cb(self, button):
+ # Pause or unpause the game.
+ self.paused = not self.paused
+ self.game.set_paused(self.paused)
+
+ # Update the button to show the next action.
+ if self.paused:
+ button.set_icon('media-playback-start')
+ button.set_tooltip(_("Start"))
+ else:
+ button.set_icon('media-playback-stop')
+ button.set_tooltip(_("Stop"))
+
+ def read_file(self, file_path):
+ self.game.read_file(file_path)
+
+ def write_file(self, file_path):
+ self.game.write_file(file_path)
diff --git a/activity/data/Thumbs.db b/activity/data/Thumbs.db
new file mode 100644
index 0000000..5a1ee92
--- /dev/null
+++ b/activity/data/Thumbs.db
Binary files differ
diff --git a/activity/data/background.png b/activity/data/background.png
new file mode 100644
index 0000000..ea0c732
--- /dev/null
+++ b/activity/data/background.png
Binary files differ
diff --git a/activity/data/block.png b/activity/data/block.png
new file mode 100644
index 0000000..d0c7b96
--- /dev/null
+++ b/activity/data/block.png
Binary files differ
diff --git a/activity/data/blocku.png b/activity/data/blocku.png
new file mode 100644
index 0000000..119d75e
--- /dev/null
+++ b/activity/data/blocku.png
Binary files differ
diff --git a/activity/data/grid.png b/activity/data/grid.png
new file mode 100644
index 0000000..563c13f
--- /dev/null
+++ b/activity/data/grid.png
Binary files differ
diff --git a/activity/setup.py b/activity/setup.py
new file mode 100644
index 0000000..6ed89aa
--- /dev/null
+++ b/activity/setup.py
@@ -0,0 +1,4 @@
+#!/usr/bin/env python
+from sugar.activity import bundlebuilder
+bundlebuilder.start()
+
diff --git a/activity/sugargame/__init__.py b/activity/sugargame/__init__.py
new file mode 100644
index 0000000..7e49527
--- /dev/null
+++ b/activity/sugargame/__init__.py
@@ -0,0 +1 @@
+__version__ = '1.0'
diff --git a/activity/sugargame/canvas.py b/activity/sugargame/canvas.py
new file mode 100644
index 0000000..cf99a13
--- /dev/null
+++ b/activity/sugargame/canvas.py
@@ -0,0 +1,56 @@
+import os
+import gtk
+import gobject
+import pygame
+import event
+
+CANVAS = None
+
+class PygameCanvas(gtk.EventBox):
+ def __init__(self, mainwindow):
+ gtk.EventBox.__init__(self)
+
+ global CANVAS
+ assert CANVAS == None, "Only one PygameCanvas can be created, ever."
+ CANVAS = self
+
+ self._mainwindow = mainwindow
+
+ self.set_flags(gtk.CAN_FOCUS)
+
+ self._socket = gtk.Socket()
+ self.add(self._socket)
+ self.show_all()
+
+ def run_pygame(self, main_fn):
+ # Run the main loop after a short delay. The reason for the delay is that the
+ # Sugar activity is not properly created until after its constructor returns.
+ # If the Pygame main loop is called from the activity constructor, the
+ # constructor never returns and the activity freezes.
+ gobject.idle_add(self._run_pygame_cb, main_fn)
+
+ def _run_pygame_cb(self, main_fn):
+ assert pygame.display.get_surface() is None, "PygameCanvas.run_pygame can only be called once."
+
+ # Preinitialize Pygame with the X window ID.
+ assert pygame.display.get_init() == False, "Pygame must not be initialized before calling PygameCanvas.run_pygame."
+ os.environ['SDL_WINDOWID'] = str(self._socket.get_id())
+ pygame.init()
+
+ # Restore the default cursor.
+ self._socket.get_window().set_cursor(None)
+
+ # Initialize the Pygame window.
+ r = self.get_allocation()
+ pygame.display.set_mode((r.width, r.height), pygame.RESIZABLE)
+
+ # Hook certain Pygame functions with GTK equivalents.
+ translator = event.Translator(self._mainwindow, self)
+ translator.hook_pygame()
+
+ # Run the Pygame main loop.
+ main_fn()
+ return False
+
+ def get_pygame_widget(self):
+ return self._socket
diff --git a/activity/sugargame/event.py b/activity/sugargame/event.py
new file mode 100644
index 0000000..52ca4ab
--- /dev/null
+++ b/activity/sugargame/event.py
@@ -0,0 +1,241 @@
+import gtk
+import gobject
+import pygame
+import pygame.event
+import logging
+
+class _MockEvent(object):
+ def __init__(self, keyval):
+ self.keyval = keyval
+
+class Translator(object):
+ key_trans = {
+ 'Alt_L': pygame.K_LALT,
+ 'Alt_R': pygame.K_RALT,
+ 'Control_L': pygame.K_LCTRL,
+ 'Control_R': pygame.K_RCTRL,
+ 'Shift_L': pygame.K_LSHIFT,
+ 'Shift_R': pygame.K_RSHIFT,
+ 'Super_L': pygame.K_LSUPER,
+ 'Super_R': pygame.K_RSUPER,
+ 'KP_Page_Up' : pygame.K_KP9,
+ 'KP_Page_Down' : pygame.K_KP3,
+ 'KP_End' : pygame.K_KP1,
+ 'KP_Home' : pygame.K_KP7,
+ 'KP_Up' : pygame.K_KP8,
+ 'KP_Down' : pygame.K_KP2,
+ 'KP_Left' : pygame.K_KP4,
+ 'KP_Right' : pygame.K_KP6,
+
+ }
+
+ mod_map = {
+ pygame.K_LALT: pygame.KMOD_LALT,
+ pygame.K_RALT: pygame.KMOD_RALT,
+ pygame.K_LCTRL: pygame.KMOD_LCTRL,
+ pygame.K_RCTRL: pygame.KMOD_RCTRL,
+ pygame.K_LSHIFT: pygame.KMOD_LSHIFT,
+ pygame.K_RSHIFT: pygame.KMOD_RSHIFT,
+ }
+
+ def __init__(self, mainwindow, inner_evb):
+ """Initialise the Translator with the windows to which to listen"""
+ self._mainwindow = mainwindow
+ self._inner_evb = inner_evb
+
+ # Enable events
+ self._mainwindow.set_events(
+ gtk.gdk.KEY_PRESS_MASK | \
+ gtk.gdk.KEY_RELEASE_MASK \
+ )
+
+ self._inner_evb.set_events(
+ gtk.gdk.POINTER_MOTION_MASK | \
+ gtk.gdk.POINTER_MOTION_HINT_MASK | \
+ gtk.gdk.BUTTON_MOTION_MASK | \
+ gtk.gdk.BUTTON_PRESS_MASK | \
+ gtk.gdk.BUTTON_RELEASE_MASK
+ )
+
+ self._mainwindow.set_flags(gtk.CAN_FOCUS)
+ self._inner_evb.set_flags(gtk.CAN_FOCUS)
+
+ # Callback functions to link the event systems
+ self._mainwindow.connect('unrealize', self._quit_cb)
+ self._inner_evb.connect('key_press_event', self._keydown_cb)
+ self._inner_evb.connect('key_release_event', self._keyup_cb)
+ self._inner_evb.connect('button_press_event', self._mousedown_cb)
+ self._inner_evb.connect('button_release_event', self._mouseup_cb)
+ self._inner_evb.connect('motion-notify-event', self._mousemove_cb)
+ self._inner_evb.connect('expose-event', self._expose_cb)
+ self._inner_evb.connect('configure-event', self._resize_cb)
+
+ # Internal data
+ self.__stopped = False
+ self.__keystate = [0] * 323
+ self.__button_state = [0,0,0]
+ self.__mouse_pos = (0,0)
+ self.__repeat = (None, None)
+ self.__held = set()
+ self.__held_time_left = {}
+ self.__held_last_time = {}
+ self.__tick_id = None
+
+ def hook_pygame(self):
+ pygame.key.get_pressed = self._get_pressed
+ pygame.key.set_repeat = self._set_repeat
+ pygame.mouse.get_pressed = self._get_mouse_pressed
+ pygame.mouse.get_pos = self._get_mouse_pos
+
+ def _expose_cb(self, event, widget):
+ pygame.event.post(pygame.event.Event(pygame.VIDEOEXPOSE))
+ return True
+
+ def _resize_cb(self, widget, event):
+ evt = pygame.event.Event(pygame.VIDEORESIZE,
+ size=(event.width,event.height), width=event.width, height=event.height)
+ pygame.event.post(evt)
+ return False # continue processing
+
+ def _quit_cb(self, data=None):
+ self.__stopped = True
+ pygame.event.post(pygame.event.Event(pygame.QUIT))
+
+ def _keydown_cb(self, widget, event):
+ key = event.keyval
+ if key in self.__held:
+ return True
+ else:
+ if self.__repeat[0] is not None:
+ self.__held_last_time[key] = pygame.time.get_ticks()
+ self.__held_time_left[key] = self.__repeat[0]
+ self.__held.add(key)
+
+ return self._keyevent(widget, event, pygame.KEYDOWN)
+
+ def _keyup_cb(self, widget, event):
+ key = event.keyval
+ if self.__repeat[0] is not None:
+ if key in self.__held:
+ # This is possibly false if set_repeat() is called with a key held
+ del self.__held_time_left[key]
+ del self.__held_last_time[key]
+ self.__held.discard(key)
+
+ return self._keyevent(widget, event, pygame.KEYUP)
+
+ def _keymods(self):
+ mod = 0
+ for key_val, mod_val in self.mod_map.iteritems():
+ mod |= self.__keystate[key_val] and mod_val
+ return mod
+
+ def _keyevent(self, widget, event, type):
+ key = gtk.gdk.keyval_name(event.keyval)
+ if key is None:
+ # No idea what this key is.
+ return False
+
+ keycode = None
+ if key in self.key_trans:
+ keycode = self.key_trans[key]
+ elif hasattr(pygame, 'K_'+key.upper()):
+ keycode = getattr(pygame, 'K_'+key.upper())
+ elif hasattr(pygame, 'K_'+key.lower()):
+ keycode = getattr(pygame, 'K_'+key.lower())
+ elif key == 'XF86Start':
+ # view source request, specially handled...
+ self._mainwindow.view_source()
+ else:
+ print 'Key %s unrecognized' % key
+
+ if keycode is not None:
+ if type == pygame.KEYDOWN:
+ mod = self._keymods()
+ self.__keystate[keycode] = type == pygame.KEYDOWN
+ if type == pygame.KEYUP:
+ mod = self._keymods()
+ ukey = unichr(gtk.gdk.keyval_to_unicode(event.keyval))
+ if ukey == '\000':
+ ukey = ''
+ evt = pygame.event.Event(type, key=keycode, unicode=ukey, mod=mod)
+ self._post(evt)
+
+ return True
+
+ def _get_pressed(self):
+ return self.__keystate
+
+ def _get_mouse_pressed(self):
+ return self.__button_state
+
+ def _mousedown_cb(self, widget, event):
+ self.__button_state[event.button-1] = 1
+ return self._mouseevent(widget, event, pygame.MOUSEBUTTONDOWN)
+
+ def _mouseup_cb(self, widget, event):
+ self.__button_state[event.button-1] = 0
+ return self._mouseevent(widget, event, pygame.MOUSEBUTTONUP)
+
+ def _mouseevent(self, widget, event, type):
+ evt = pygame.event.Event(type, button=event.button, pos=(event.x, event.y))
+ self._post(evt)
+ return True
+
+ def _mousemove_cb(self, widget, event):
+ # From http://www.learningpython.com/2006/07/25/writing-a-custom-widget-using-pygtk/
+ # if this is a hint, then let's get all the necessary
+ # information, if not it's all we need.
+ if event.is_hint:
+ x, y, state = event.window.get_pointer()
+ else:
+ x = event.x
+ y = event.y
+ state = event.state
+
+ rel = (x - self.__mouse_pos[0], y - self.__mouse_pos[1])
+ self.__mouse_pos = (x, y)
+
+ self.__button_state = [
+ state & gtk.gdk.BUTTON1_MASK and 1 or 0,
+ state & gtk.gdk.BUTTON2_MASK and 1 or 0,
+ state & gtk.gdk.BUTTON3_MASK and 1 or 0,
+ ]
+
+ evt = pygame.event.Event(pygame.MOUSEMOTION,
+ pos=self.__mouse_pos, rel=rel, buttons=self.__button_state)
+ self._post(evt)
+ return True
+
+ def _tick_cb(self):
+ cur_time = pygame.time.get_ticks()
+ for key in self.__held:
+ delta = cur_time - self.__held_last_time[key]
+ self.__held_last_time[key] = cur_time
+
+ self.__held_time_left[key] -= delta
+ if self.__held_time_left[key] <= 0:
+ self.__held_time_left[key] = self.__repeat[1]
+ self._keyevent(None, _MockEvent(key), pygame.KEYDOWN)
+
+ return True
+
+ def _set_repeat(self, delay=None, interval=None):
+ if delay is not None and self.__repeat[0] is None:
+ self.__tick_id = gobject.timeout_add(10, self._tick_cb)
+ elif delay is None and self.__repeat[0] is not None:
+ gobject.source_remove(self.__tick_id)
+ self.__repeat = (delay, interval)
+
+ def _get_mouse_pos(self):
+ return self.__mouse_pos
+
+ def _post(self, evt):
+ try:
+ pygame.event.post(evt)
+ except pygame.error, e:
+ if str(e) == 'Event queue full':
+ print "Event queue full!"
+ pass
+ else:
+ raise e
diff --git a/blocku.py b/blocku.py
index 67bb2f2..79baaf1 100644
--- a/blocku.py
+++ b/blocku.py
@@ -1,3 +1,11 @@
+
+"""Main Blocku game logic class
+
+import every thing that the activity needs and run game code
+
+Authored by Fran Rogers and Ariel Zamparini
+"""
+
#!/usr/bin/python
import pygame, random, os.path
from pygame.locals import *
@@ -30,21 +38,48 @@ def load_images(*files):
imgs.append(load_image(file))
return imgs
+class dummysound:
+ def play(self): pass
+
+def load_sound(file):
+ if not pygame.mixer: return dummysound()
+ file = os.path.join('data', file)
+ try:
+ sound = pygame.mixer.Sound(file)
+ return sound
+ except pygame.error:
+ print 'Warning, unable to load,', file
+ return dummysound()
+
class Block(pygame.sprite.Sprite):
images = []
- def __init__(self, north=None, east=None, south=None, west=None):
+ north=''
+ east=''
+ south=''
+ west=''
+ def __init__(self, n='', e='', s='', w='', x='', y=''):
pygame.sprite.Sprite.__init__(self, self.containers)
- self.image = self.images[0]
- self.rect = self.image.get_rect().move(300, 300)
- self.north = north
- self.east = east
- self.south = south
- self.west = west
+ self.image = self.images[0].copy()
+ self.rect = pygame.Rect(x,y,64,64)
+ self.font = pygame.font.Font(None, 20)
+ self.font.set_italic(1)
+ self.color = Color('blue')
+ self.update()
+ self.north = n
+ self.east = e
+ self.south = s
+ self.west = w
def update(self):
- pass
- #if (mouseMove)
- # self.rect.move(mouseX-posRelX,mouseY-posRelY)
+ #keep the block on the screen
+ self.rect = self.rect.clamp(SCREENRECT)
+ self.image = self.images[0].copy()
+ self.image.blit(self.font.render(str(self.north), 0, self.color),(26,3))
+ self.image.blit(self.font.render(str(self.east), 0, self.color),(47,25))
+ self.image.blit(self.font.render(str(self.south), 0, self.color),(26,47))
+ self.image.blit(self.font.render(str(self.west), 0, self.color),(5,25))
+ # game logic here for snapping to grid ...?
+ # when the block is snapped to the grid clamp the rect there
def move(self, direction):
# up = 0, right = 1, down = 2, left = 3
if direction == 0:
@@ -55,8 +90,22 @@ class Block(pygame.sprite.Sprite):
self.rect.move_ip(0,KEYBOARDMOVESPEED)
if direction == 3:
self.rect.move_ip(-KEYBOARDMOVESPEED,0)
- #keep the block on the screen
- self.rect = self.rect.clamp(SCREENRECT)
+
+ def grab(self, pos):
+ x, y = pos;
+ #print x , y
+ #print self.rect.left, self.rect.top
+ #self.rect = self.rect.move(x, y)
+ #remember the offset here is 32 as this will center the mouse in our 64pixel image
+ self.rect.left = x-32
+ self.rect.top = y-32
+ def rotate(self):
+ temp = self.north
+ self.north = self.east
+ self.east = self.south
+ self.south = self.west
+ self.west = temp
+ #print self.north, self.east, self.south, self.west
class Puzzle:
def __init__(self):
@@ -96,6 +145,10 @@ class Game:
def run(self):
self.running = True
+ if pygame.mixer and not pygame.mixer.get_init():
+ print 'Warning, no sound'
+ pygame.mixer = None
+
#set the screen up
winstyle = 0 # |FULLSCREEN
bestdepth = pygame.display.mode_ok(SCREENRECT.size, winstyle, 32)
@@ -111,6 +164,7 @@ class Game:
# load images to pipe to the sprite classes
blockImg = load_image('block.png')
Block.images = [blockImg]
+ gridImg = load_image('grid.png')
# the test will need rects and positions i sugest make some kind of default
# this information can be held by each block as they are created but is made here
@@ -120,6 +174,7 @@ class Game:
else:
background = background.convert()
+ background.blit(gridImg,(200,200))
screen.blit(background,(0,0))
pygame.display.flip()
@@ -133,16 +188,24 @@ class Game:
#main blocku code structs
blocks = pygame.sprite.Group()
- Block.containers = spriteBatch
- aBlock = Block()
+ Block.containers = blocks,spriteBatch
+ #blocks are Block(n,s,e,w,x,y) xy= starting position
+ aBlock = Block(1,2,3,4,200,200)
+ bBlock = Block(5,6,7,8,300,300)
+ global debugText
+ debugText = ''
#see if there is a sprite font
if pygame.font:
- spriteBatch.add(Text(text = 'helloworld'))
+ spriteBatch.add(Text('Drawing call test '))
spriteBatch.add(mouseUpdate())
+ #if a key is down
+ global keyDown
+ keyDown = False
# it is important to note that like xna the origin is 0,0
# the top left of the current window
+ # print is trace in console
# and increases as you go down and to the right
# pygame has a collision detector under pygame.sprite.spritecollide(group,group,dokill)
# this will return a list of colliders, dokill will remove the colliders from the parrent group if true
@@ -153,17 +216,22 @@ class Game:
gtk.main_iteration()
# Pump PyGame messages.
- for event in pygame.event.get():
- if event.type == QUIT or \
- (event.type == KEYDOWN and event.key == K_ESCAPE):
+ for e in event.get():
+ if e.type == QUIT or \
+ (e.type == KEYDOWN and e.key == K_ESCAPE):
return
- elif event.type == pygame.VIDEORESIZE:
- pygame.display.set_mode(event.size, pygame.RESIZABLE)
+ elif e.type == pygame.VIDEORESIZE:
+ pygame.display.set_mode(e.size, pygame.RESIZABLE)
+ if e.type == MOUSEBUTTONDOWN:
+ event.set_grab(1)
+ elif e.type == MOUSEBUTTONUP:
+ event.set_grab(0)
# get the state of the keyboard for input
keystate = pygame.key.get_pressed()
+ if not keystate[K_SPACE]:
+ keyDown = False
# for key test use keystate[key] and a return of true will occur when key down
-
# clear/erase the last drawn sprites
spriteBatch.clear(screen, background)
# update all the sprites
@@ -177,6 +245,23 @@ class Game:
aBlock.move(2)
if keystate[K_LEFT]:
aBlock.move(3)
+ if keystate[K_SPACE] and not keyDown:
+ aBlock.rotate()
+ keyDown = True
+
+ #for block in blocks:
+ x, y = mouse.get_pos()
+
+ if event.get_grab():
+ debugText = 'holding mouse button 1'
+ if aBlock.rect.collidepoint(x,y):
+ aBlock.grab(mouse.get_pos())
+ debugText += 'grabed aBlock'
+ elif bBlock.rect.collidepoint(x,y):
+ bBlock.grab(mouse.get_pos())
+ debugText += 'grabed bBlock'
+ else:
+ debugText = ''
# note random here is random.random()
# note foreach here is for object in
@@ -184,21 +269,24 @@ class Game:
draw = spriteBatch.draw(screen)
pygame.display.update(draw)
+
# Try to stay at 30 FPS
self.clock.tick(30)
class Text(pygame.sprite.Sprite):
- def __init__(self,text="blank"):
+ text = ''
+ def __init__(self,txt=''):
pygame.sprite.Sprite.__init__(self)
self.font = pygame.font.Font(None, 20)
self.font.set_italic(1)
self.color = Color('blue')
self.update()
- self.rect = self.image.get_rect().move(50, 200)
- self.text = text
+ self.rect = self.image.get_rect().move(55, 80)
+ self.text = txt
def update(self):
- msg = '' # 'Drawing call test'
+ global debugText
+ msg = self.text + debugText
self.image = self.font.render(msg, 0, self.color)
class mouseUpdate(pygame.sprite.Sprite):
@@ -211,7 +299,7 @@ class mouseUpdate(pygame.sprite.Sprite):
self.rect = self.image.get_rect().move(50, 220)
def update(self):
- msg = '' # 'Mouse Position %s, %s' % mouse.get_pos()
+ msg = 'Mouse Position %s, %s' % mouse.get_pos()
self.image = self.font.render(msg, 0, self.color)
# This function is called when the game is run directly from the command line:
diff --git a/data/Thumbs.db b/data/Thumbs.db
new file mode 100644
index 0000000..5a1ee92
--- /dev/null
+++ b/data/Thumbs.db
Binary files differ
diff --git a/data/grid.png b/data/grid.png
new file mode 100644
index 0000000..563c13f
--- /dev/null
+++ b/data/grid.png
Binary files differ