diff options
author | coolestdude1 <arielzamparini@gmail.com> | 2010-02-24 20:51:01 (GMT) |
---|---|---|
committer | coolestdude1 <arielzamparini@gmail.com> | 2010-02-24 20:51:01 (GMT) |
commit | 677b839ee2945455e61bb8cace2d9ea921b0d4fc (patch) | |
tree | be7262a98fb590c9bf35ff008aa31b327ade9c6c | |
parent | 6800d2cda6c657dfa910fd48b522bcb7c0dfcd5b (diff) |
cloning my repo back to main for the update
-rw-r--r-- | activity/Blocku.png | bin | 0 -> 49171 bytes | |||
-rw-r--r-- | activity/MANIFEST.in | 4 | ||||
-rw-r--r-- | activity/NEWS | 0 | ||||
-rw-r--r-- | activity/POTFILES.in | 1 | ||||
-rw-r--r-- | activity/activity/activity.info | 6 | ||||
-rw-r--r-- | activity/activity/blocku.svg | 65 | ||||
-rw-r--r-- | activity/blocku.py | 320 | ||||
-rw-r--r-- | activity/blocku_activity.py | 67 | ||||
-rw-r--r-- | activity/data/Thumbs.db | bin | 0 -> 11776 bytes | |||
-rw-r--r-- | activity/data/background.png | bin | 0 -> 3835 bytes | |||
-rw-r--r-- | activity/data/block.png | bin | 0 -> 481 bytes | |||
-rw-r--r-- | activity/data/blocku.png | bin | 0 -> 23629 bytes | |||
-rw-r--r-- | activity/data/grid.png | bin | 0 -> 617 bytes | |||
-rw-r--r-- | activity/setup.py | 4 | ||||
-rw-r--r-- | activity/sugargame/__init__.py | 1 | ||||
-rw-r--r-- | activity/sugargame/canvas.py | 56 | ||||
-rw-r--r-- | activity/sugargame/event.py | 241 | ||||
-rw-r--r-- | blocku.py | 140 | ||||
-rw-r--r-- | data/Thumbs.db | bin | 0 -> 11776 bytes | |||
-rw-r--r-- | data/grid.png | bin | 0 -> 617 bytes |
20 files changed, 879 insertions, 26 deletions
diff --git a/activity/Blocku.png b/activity/Blocku.png Binary files differnew file mode 100644 index 0000000..e6fed23 --- /dev/null +++ b/activity/Blocku.png 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 Binary files differnew file mode 100644 index 0000000..5a1ee92 --- /dev/null +++ b/activity/data/Thumbs.db diff --git a/activity/data/background.png b/activity/data/background.png Binary files differnew file mode 100644 index 0000000..ea0c732 --- /dev/null +++ b/activity/data/background.png diff --git a/activity/data/block.png b/activity/data/block.png Binary files differnew file mode 100644 index 0000000..d0c7b96 --- /dev/null +++ b/activity/data/block.png diff --git a/activity/data/blocku.png b/activity/data/blocku.png Binary files differnew file mode 100644 index 0000000..119d75e --- /dev/null +++ b/activity/data/blocku.png diff --git a/activity/data/grid.png b/activity/data/grid.png Binary files differnew file mode 100644 index 0000000..563c13f --- /dev/null +++ b/activity/data/grid.png 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 @@ -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 Binary files differnew file mode 100644 index 0000000..5a1ee92 --- /dev/null +++ b/data/Thumbs.db diff --git a/data/grid.png b/data/grid.png Binary files differnew file mode 100644 index 0000000..563c13f --- /dev/null +++ b/data/grid.png |