2 comments Monday, June 25, 2007

As promised, today I will start a series of small tutorials for the Stackless usage.

The examples will be focused on PSP but they can all be implemented for Pygame, just switch the graphic functions in psp2d.

A great package that helps a lot the development is the psp mockup libraries. They mimic the psp2d module and translates them to Pygame. With an installation of Python and Pygame you can test all your programs in PC before putting them in the PSP.

Well, lets start the tutorial, the code is very documented and can be easily understood, if you have any questions, contact me over the commentaries or my email - carlosedp+themindcaster at gmail.com

The full code package can be downloaded here.

The Stackless for PSP can be downloaded here.

# -*- coding: iso-8859-1 -*-

'''
This is an example on using Stackless Python in PSP. The idea is based on a
tutorial created by Sakya.

Here we have the concept of agent based programming where the player, the NPC
and the render engine as an agent doing its actions.

The player agent waits for the user input captured from the keypad.

The NPC agent starts running aroundn the screen in a predefined pattern.

The render engine does all the drawing job clearing the screen and putting each
agent in its own place.

As you can see, all the logic is very simplified because of the flexibility
stackless gives to us. Every agent can have its own behaviour and optionally
follow some "world" rules defined for example in a separate Agent.

This "World" could detect collisions, handle communications between agents and
interact with other elements. This can be an exercise to the user.

'''
import psp2d, pspos
from time import time
import sys
import stackless

# Set processor and bus speed
pspos.setclock(222)
pspos.setbus(111)

# Creates the screen and its background color (Black)
screen = psp2d.Screen()
screen.clear(psp2d.Color(0,0,0,255))

# Loads the font
font = psp2d.Font('font.png')

# Loads the character movement images
spriteImages = []
spriteImages.append((psp2d.Image('amg1_bk1.png'), psp2d.Image('amg1_bk2.png'))) #Direction = north = 0
spriteImages.append((psp2d.Image('amg1_fr1.png'), psp2d.Image('amg1_fr2.png'))) #Direction = south = 1
spriteImages.append((psp2d.Image('amg1_lf1.png'), psp2d.Image('amg1_lf2.png'))) #Direction = west = 2
spriteImages.append((psp2d.Image('amg1_rt1.png'), psp2d.Image('amg1_rt2.png'))) #Direction = east = 3


# Creates the Agent base class
class Agent(object):
def __init__(self):
self.ch = stackless.channel() # Communication channel (not used here)
self.running = True # Flag to control the running status
stackless.tasklet(self.runAction)() # Creates the agent tasklet

def runAction(self):
# Here we define the main action, a repetition of the function self.action()
while self.running:
# Runs the action
self.action()
# Give other tasklets its turn
stackless.schedule()

def action(self):
# In the base class do nothing
pass

class player(Agent):
def __init__(self, rend):
Agent.__init__(self)
self.rend = rend # Reference to the renderer tasklet
self.boolSprite = False
self.direction = 1
self.speed = 3
self.posX = 30
self.posY = 30
self.lastPad = time()
self.rend.agents.append(self) # Adds this agent to the renderer
self.sprite = spriteImages[self.direction][int(self.boolSprite)]

def action(self):
self.sprite = spriteImages[self.direction][int(self.boolSprite)]
pad = psp2d.Controller()
if pad.cross:
print "exit"
self.rend.exit()
elif pad.triangle:
screen.saveToFile("ms0:/PSP/PHOTO/screenshot.png")
elif pad.down and (not self.lastPad or time() - self.lastPad >= 0.05):
#Draw the player facing south:
self.lastPad = time()
self.direction = 1
if self.posY + self.sprite.height + self.speed <>
self.posY += self.speed
self.boolSprite = not self.boolSprite
elif pad.up and (not self.lastPad or time() - self.lastPad >= 0.05):
#Draw the player facing north:
self.lastPad = time()
self.direction = 0
if self.posY - self.speed >= 0:
self.posY -= self.speed
self.boolSprite = not self.boolSprite
elif pad.left and (not self.lastPad or time() - self.lastPad >= 0.05):
#Draw the player facing west:
self.lastPad = time()
self.direction = 2
if self.posX - self.speed >= 0:
self.posX -= self.speed
self.boolSprite = not self.boolSprite
elif pad.right and (not self.lastPad or time() - self.lastPad >= 0.05):
#Draw the player facing east:
self.lastPad = time()
self.direction = 3
if self.posX + self.sprite.width + self.speed <>
self.posX += self.speed
self.boolSprite = not self.boolSprite

class NPC(Agent):
def __init__(self, rend):
Agent.__init__(self)
self.rend = rend
self.boolSprite = False
self.direction = 0
self.speed = 5
self.posX = 230
self.posY = 230
self.lastPad = time()
self.rend.agents.append(self)
self.sprite = spriteImages[self.direction][int(self.boolSprite)]
self.count = 20

def action(self):
# This NPC runs around the screen changing its direction when touches the border.
self.sprite = spriteImages[self.direction][int(self.boolSprite)]
if self.direction == 0 and (not self.lastPad or time() - self.lastPad >= 0.05):
self.lastPad = time()
if self.posY - self.speed >= 20:
self.posY -= self.speed
self.boolSprite = not self.boolSprite
else:
self.direction = 2
if self.direction == 2 and (not self.lastPad or time() - self.lastPad >= 0.05):
self.lastPad = time()
if self.posX - self.speed > 0:
self.posX -= self.speed
self.boolSprite = not self.boolSprite
else:
self.direction = 1
if self.direction == 1 and (not self.lastPad or time() - self.lastPad >= 0.05):
self.lastPad = time()
if self.posY + self.sprite.height + self.speed <>
self.posY += self.speed
self.boolSprite = not self.boolSprite
else:
self.direction = 3
if self.direction == 3 and (not self.lastPad or time() - self.lastPad >= 0.05):
self.lastPad = time()
if self.posX + self.sprite.width + self.speed <>
self.posX += self.speed
self.boolSprite = not self.boolSprite
else:
self.direction = 0


class render(Agent):
# This is the renderer agent
def __init__(self):
Agent.__init__(self)
self.agents = []

def exit(self):
# When the player calls the exit, tell all Agents to stop running
for agent in self.agents:
agent.running = False
self.running = False

def action(self):
# Each frame the renderer clears the screen, writes the text and draws each
# registered agent.
screen.clear(psp2d.Color(0,0,0,255))
font.drawText(screen, 10, 225, "Move your character with directional")
font.drawText(screen, 10, 240, "Triangle takes screenshot")
font.drawText(screen, 10, 255, "Press X to exit")
for agent in self.agents:
screen.blit(agent.sprite, 0, 0, agent.sprite.width, agent.sprite.height, agent.posX, agent.posY, True)
screen.swap()


# Creates the renderer object
rend = render()
# Creates a player Agent
play = player(rend)
# Creates one NPC that runs around the screen
NPC1 = NPC(rend)

# Starts the game loop
stackless.run()





13 comments Monday, June 18, 2007

About 3 weeks ago, I got a Sony PSP, since only playing games isnt enought for me, I started fiddling around for so called "Homebrew" software for it.

The homebrew community for PSP is quite big and mostly around C coding but surprisingly I found that a guy named Jerome made Python-psp, awesome port of Python 2.4.3 and PSP graphic, sound and network API to Python modules.

Based on that and my bare knowledge of C, I decided to start working on a Stackless Python port for it.

I recently saw the great work from Richard Tew in porting Stackless to Nintendo DS and decided to give a try. Checked out the 2.4.3 PSP port from python-psp repository and merged the Stackless 2.4.4 tag into it.

The first thing to be done, was fixing up some conflicts mostly related to IO and threads. Next Richard pointed me out that the Stackless needs to save and restore stack pointers and this is done in assembly.

Based on trial and error, it took me a day to figure out and have a compiled interpreter.

To finish it all, I ran the stackless unittests and some Stackless applications from the Stackless Examples Project and found that its all working.

I hope other people could try it out and maybe find some bugs, probably I will make the source available and the diff patches too.

The next thing in my roadmap is porting Python and Stackless Python 2.5.1 to PSP, hope it wont be much trouble.

The download is temporarily stored on Stackless Examples project. As soon as I decide to host it or anyone else do, it will be here:

http://stacklessexamples.googlecode.com/files/PSP-Stackless-2.4.4.zip

To install just create a folder in your /PSP/GAME150 folder and place the EBOOT.PBP there.
The python folder is the libraries and must be placed on your memory stick root.

For more information check the Python-psp page.

Thanks a lot for Jerome for the amazing work on the Python port and Richard Tew for the Stackless porting!

Any questions contact me directly.

4 comments Tuesday, May 22, 2007

In the last days, i've been committed to learn C++ so I can port performance critical methods in my Python apps to it. I found a great site - www.cplusplus.com with a nice tutorial worth a look.

I started reading thru a lot of documentation on how to create Python C modules but all those PyObjects and all made a mess in my head.

Looking in the Python-Ogre (Python bindings for the wonderful Ogre3D engine), I found that they use a new code generator for boost-python called Py++.

I heard a lot about boost and its qualities so I figured out that this was the best option and with Py++ to create the wrapper files it became easier.

The problem was not how to create the wrapper files and generate the modules but and install that bunch of packages and modules on windows was a pain.

What you will need:

- Compiler (I'm using VS2005 Express since its free)
- Platform SDK R2 (Windows headers)
- Python (Of course...)
- 2 eggs ... oops... forget this one
- Boost installer for Windows Easier to install, better than compile yourself.
- GCC-XML
- Pygccxml

The resumed installation procedure is:

- Install the compiler and the platform SDK
- Configure your compiler to use the 'libs', 'includes' and 'bins' from the SDK
- Configure the vcvars32.bat file to add the SDK paths to it so the Compile console finds the headers.
- Run the boost installer, it will download the needed packages from a mirror. I installed the base packages and the Python lib.
- Unpack and run 'python setup.py install' on GCC-XML. In my case, it have not compiled with VC2005 so I unpacked myself and followed the instructions here. Then I compiled using the generated solution file.
- Install the pygccxml package 'python setup.py build install'
- Install the py++ package 'python setup.py build install'

Thats it for now... in my next post I will post some examples and procedures for generating the C++ modules.

0 comments Friday, May 11, 2007

Reading a post from a Planet PythonBrasil blog today, our friend Rodrigo Cacilhas has proposed some approaches on the Oddwords puzzle where the objective is to invert the odd words in a phrase.

The post can be seen here: http://kodumaro.blogspot.com/2007/05/oddwording.html

I created a small solution based on list comprehension and the and-or trick. It´s like this:

text= "abc def ghi"

print " ".join([(x%2 == 0 and y or y[::-1]) for x,y in enumerate(text.split())])

It shows how powerful list comprehensions can be.

0 comments

First post, new blog.... well, this will be the place where i will write about programming, tech and discoveries I find around the internet.

Keep your eyes here for great content.