This is a read-only archive of the old Scratch 1.x Forums.
Try searching the current Scratch discussion forums.

#1 2012-01-17 02:52:50

Magnie
Scratcher
Registered: 2007-12-12
Posts: 1000+

Soulite - A Pygame Module to keep the Scratch Feel in Programming

So Soulite is a module for Python/Pygame to keep the feeling of Scratch while programming games, etc.

soulite.py:

Code:

#/usr/bin/env python
'''
Soulite is a module for Pygame to keep the Scratch feel
of programming. It tries to keep the Project, Stage,
Sprites and commands in Pygame.

Soulite is made by Magnie (http://www.scratch.mit.edu/users/Magnie)
Scratch is a program made by MIT (http://www.scratch.mit.edu)

This is version of Soulite is version 1.0
'''
import sys
import os

import pygame
from pygame.locals import *

pygame.init()


class Project(object):
    
    def __init__(self):
        self.sprites = {} # 'name' : Sprite()
        self.stage = Stage(background_color=0xFFFFFF)
    
        self.clock = pygame.time.Clock()
    
    def tick(self, ticker):
        "This controls the FPS of the project."
        self.clock.tick(ticker)
    
    def update_all(self):
        "This updates all the sprites of the project."
        for event in pygame.event.get(): 
            if event.type == pygame.QUIT: 
                sys.exit(0) 
        self.stage.screen.blit(self.stage.background, (0, 0))
        for sprite in self.sprites:
            self.sprites[sprite]._update()
        pygame.display.flip()
    
    def new_sprite(self, sprite):
        "Adds a new sprite to the dictionary so it can be updated."
        self.sprites[sprite.name] = sprite


class Stage(object):
    
    def __init__(self, width=512, height=512, caption='Soulite', background_color=0x000000):
        self.width = width
        self.height = height
        self.background_color = background_color
        self.window = pygame.display.set_mode((self.width, self.height))
        self.screen = pygame.display.get_surface()
        
        self.background = pygame.Surface(self.screen.get_size())
        self.background = self.background.convert()
        self.background.fill(self.background_color)
        
        self.backgrounds = {} # 'costume name' : costume
    
    def set_background(self, costume_name):
        "Set the background image."
        self.background = self.backgrounds[costume_name]
    
    def add_background(self, background_file, path='', background_name=''):
        "Add a background image."
        if not background_name:
            background_name = background_file
        
        background_location = os.path.join(path, background_file)
        try:
            background = pygame.image.load(background_location)
            background = background.convert()
        except pygame.error:
            return 'Failed to load image.'
        
        self.backgrounds[costume_name] = background


class Sprite(pygame.sprite.Sprite):
    
    def __init__(self, project, xpos=0, ypos=0, angle=360, name='sprite'):
        pygame.sprite.Sprite.__init__(self)
        self.xpos = xpos
        self.ypos = ypos
        self.angle = angle
        
        self.name = name
        
        self.costumes = {} # 'costume name' : image
        self.current_rect = None
        self.current_costume = ''
        
        self.show_sprite = False
        
        self.key_presses = {} # 'key' : True or False
    
        self.screen = project.stage.screen
        self.project = project
        self.project.new_sprite(self)
    
    # Soulite Functions
    
    def _update(self):
        "This updates the sprites location and display."
        self.current_rect.midtop = (self.xpos, self.ypos)
        try:
            self.update()
        except AttributeError, e:
            print self.name, e
        if self.show_sprite:
            image = self.costumes[self.current_costume]
            image = self.rotate(image, self.angle)
            self.screen.blit(image, (self.xpos, self.ypos))
    
    # Motion Functions
    
    def go_to(self, x, y):
        "This tell the sprite to go to an x and y location on the screen."
        self.xpos = x
        self.ypos = y
    
    def set_x_pos(self, x):
        "This sets the x (left and right axis) position of the sprite."
        self.xpos = x
    
    def set_y_pos(self, y):
        "This sets the y (up and down axis) position of the sprite."
        self.ypos = y
    
    def set_direction(self, angle):
        "This changes the direction the sprite is facing in."
        self.angle = angle
    
    # Looks Functions
    
    def show(self):
        "This allows the sprite to be displayed."
        self.show_sprite = True
    
    def hide(self):
        "Keeps the sprite from being displayed."
        self.show_sprite = False
    
    def set_costume(self, costume_name):
        "This changes the current costume."
        self.current_costume = costume_name
        self.current_rect = self.costumes[costume_name].get_rect()
    
    def add_costume(self, costume_file, path='', costume_name='', colorkey=0xFFFFFF):
        "This loads an image and saves it to the costume dictionary."
        if not costume_name:
            costume_name = costume_file
        
        costume_location = os.path.join(path, costume_file)
        try:
            costume = pygame.image.load(costume_location)
            costume = costume.convert()
            costume.set_colorkey(colorkey, RLEACCEL)
        except pygame.error:
            return 'Failed to load image.'
        self.costumes[costume_name] = costume
    
    def del_costume(self, image_name):
        "This deletes a costume from the costum dictionary."
        if image_name in self.costumes:
            del self.costumes[image_name]
    
    def rotate(self, image, angle): # http://stackoverflow.com/questions/4183208/pygame-rotating-an-image-around-its-center
        """rotate an image while keeping its center and size"""
        orig_rect = image.get_rect()
        rot_image = pygame.transform.rotate(image, angle)
        rot_rect = orig_rect.copy()
        rot_rect.center = rot_image.get_rect().center
        rot_image = rot_image.subsurface(rot_rect).copy()
        return rot_image
    
    # Sensors Functions
    
    def key_pressed(self, bool_key):
        "This command checks if a key is being pressed."
        key = pygame.key.get_pressed()
        temp = False
        exec('''
if key['''+bool_key+''']:
    temp = True''')
        if temp == True:
            return True
        return False
    
    def touching(self, sprite_name):
        "This command checks if the current sprite is touching another sprite."
        hitbox = self.current_rect
        target = self.project.sprites[sprite_name].current_rect
        return hitbox.colliderect(target)

and the example.py project:

Code:

# Example of Soulite

from random import randrange

import soulite

class Sprite1(soulite.Sprite):

    def __init__(self):
        soulite.Sprite.__init__(self, my_project, name="Sprite1")
        
        self.add_costume('cat.png', colorkey=0xabcdef)
        self.set_costume('cat.png')
        self.show()
    
    def update(self):
        if self.key_pressed('K_UP'):
            self.ypos -= 3
        elif self.key_pressed('K_DOWN'):
            self.ypos += 3
    
        if self.key_pressed('K_LEFT'):
            self.xpos -= 3
        elif self.key_pressed('K_RIGHT'):
            self.xpos += 3


class Sprite2(soulite.Sprite):

    def __init__(self):
        soulite.Sprite.__init__(self, my_project, name="Sprite2")
        
        self.add_costume('cat.png', colorkey=0xabcdef)
        self.set_costume('cat.png')
        self.show()
    
    def update(self):
        if self.touching("Sprite1"):
            self.xpos = randrange(0, 512)
            self.ypos = randrange(0, 512)

my_project = soulite.Project()
sprite_1 = Sprite1()
sprite_2 = Sprite2()

while True:
    my_project.tick(15)
    my_project.update_all()

example.py uses the Up, Down, Left, Right keys to move my avatar around to "catch" the duplicate avatar. You will also want to download my avatar here if you want to try out the example.py project.  smile

Suggestions, thoughts?

Last edited by Magnie (2012-01-18 00:25:48)

Offline

 

#2 2012-01-17 03:57:48

Paddle2See
Scratch Team
Registered: 2007-10-27
Posts: 1000+

Re: Soulite - A Pygame Module to keep the Scratch Feel in Programming

This looks very cool!  What version of Python are you using with this?


http://i39.tinypic.com/2nav6o7.gif

Offline

 

#3 2012-01-17 09:55:16

Magnie
Scratcher
Registered: 2007-12-12
Posts: 1000+

Re: Soulite - A Pygame Module to keep the Scratch Feel in Programming

Paddle2See wrote:

This looks very cool!  What version of Python are you using with this?

I'm using Python 2.7 and Pygame 1.8 I think.  smile

Offline

 

#4 2012-01-18 00:26:39

Magnie
Scratcher
Registered: 2007-12-12
Posts: 1000+

Re: Soulite - A Pygame Module to keep the Scratch Feel in Programming

I've updated the soulite.py module and the example.py project.  smile

I wonder how many people are interested in using this...  tongue

Offline

 

#5 2012-01-18 18:32:43

flashgocrazy
Scratcher
Registered: 2011-01-12
Posts: 500+

Re: Soulite - A Pygame Module to keep the Scratch Feel in Programming

Kewl!


◕‿◕

Offline

 

Board footer