Friday 27 July 2012

Simple Starfield In PyGame

Games are very often highly interactive with even some text adventures operating in real time. I thought it would be fun to go in the opposite direction and create a game with minimal interaction. So I settled on an outer space theme and had a text experiment of a probe travelling through the emptiness of space.

The next step was to create a graphical display and, of course, stars were the first order of business! I looked around at a few star field examples and ended up coding one for myself. Straightforward 2D scrolling is all I want - needs to be calm for the display. The class is nice and simple whilst the demo shows it off fairly well.

Exercise for the reader - can you make a layered demo? I'll share the code on a follow up post. Happy stargazing!




import random
import pygame
import sys
from pygame.locals import *

class starfield(object):
    def __init__(self, pos , size, max, speed):
        self.stars = []
        self.pos = pos
        self.size = size
        self.max = max
        self.speed = speed
        self.box = True
        self.color = (255,255,255)
        self.bordercolor = Color(255,255,255)
        self.backgroundcolor = Color(0,0,0)
        for loop in range(0, max):
            star = [random.randrange(0, size[0] - 1),
                    random.randrange(0, size[1] - 1)]
            self.stars.append(star);
    def draw(self, screen):
        if self.box:
             pygame.draw.rect(screen, self.backgroundcolor, Rect(self.pos[0], self.pos[1], self.size[0],self.size[1]), 0)
             pygame.draw.rect(screen, self.bordercolor, Rect(self.pos[0], self.pos[1], self.size[0],self.size[1]), 1)
        for loop in range(0, self.max):
            p = (self.pos[0] + self.stars[loop][0], self.pos[1] + self.stars[loop][1] )
            screen.set_at(p, self.color)
    def update(self):
        for loop in range(0, self.max):
            self.stars[loop] = (self.stars[loop][0] + self.speed, self.stars[loop][1])
            if self.stars[loop][0]>self.size[0]:
                self.stars[loop] = (0, self.stars[loop][1])

# DEMO
sf = [starfield( (50,50), (550,410), 80, 1 ),
      starfield( (80,150), (200,200), 33, 2 ),
      starfield( (380,150), (200,200), 33, 3 ),
      starfield( (5,5), (80,80), 12, 4 )
      ]

sf[1].color = (255,0,0)
sf[2].color = (0,255,0)
sf[3].color = (0,0,255)


TIMEREVENT = pygame.USEREVENT
UPDATEEVENT = pygame.USEREVENT+1
FPS = 50
pygame.init()
window = pygame.display.set_mode((640, 480))

background = None
background = pygame.Surface(window.get_size())
background.fill((0, 0, 0))

pygame.time.set_timer(TIMEREVENT, int(1000 / FPS))
pygame.time.set_timer(UPDATEEVENT, 50)

while True:

    for event in pygame.event.get():
        if event.type == TIMEREVENT:
            background.fill((0,0,0))
            for s in sf:
                s.draw(background)
            window.blit(background, (0, 0))
            pygame.display.flip()
        elif event.type == UPDATEEVENT:
            for s in sf:
                s.update()
            # Move starfield
            x = sf[3].pos[0] + 2
            y = sf[3].pos[1] + 2
            if x>640: x=-50
            if y>480: y=-40
            sf[3].pos = (x,y)

        elif event.type == pygame.QUIT:
            sys.exit()

Thursday 12 July 2012

Particles Of Blue

Something I have not used in a PyGame game yet is particles of any sort. Thinking over a few ideas for a mining game, it seemed like a fun idea to have some sort of soil. This lead to a quick half-hour of coding and here is the result:


It is not terribly efficient or a good colour for soil but has potential.

Here's the code:
import pygame
import sys
import random

from pygame.event import *
from pygame.locals import *

TIMEREVENT = pygame.USEREVENT
FPS = 50
pygame.init()
window = pygame.display.set_mode((640, 480))
background = None
background = pygame.Surface(window.get_size())
background.fill((0, 0, 0))
pygame.time.set_timer(TIMEREVENT, int(1000 / FPS))
colour3 = Color(0, 0, 255)
ground = Color(0, 255, 0)
y = 100

def DrawText(bg, x, y, text, size=24, color=(255, 255, 255)):
    inst1_font = pygame.font.Font(None, size)
    inst1_surf = inst1_font.render(text, 1, color)
    bg.blit(inst1_surf, [x, y])

class grit(object):
    def __init__(self):
        self.x = random.randint(0,639)
        self.y = random.randint(0,125) - 50
        self.width = random.randint(1, 6)
        self.height = random.randint(1, 6)
        self.color = Color(0, 0, random.randint(119,255))
        self.active = True

def init():
    gritsL = 1000
    agrits = []
    while len(agrits)<gritsL:
        agrits.append(grit())
    return agrits

grits = init()

while True:

    for event in pygame.event.get():
        if event.type == TIMEREVENT:
            background.fill(pygame.Color("black"))
            DrawText(background, 25, 120, "Daftspaniel",126)
            pygame.draw.rect(background, ground, Rect(0, 450, 640,280), 0)
            pygame.draw.rect(background, ground, Rect(300, 250, 340,180), 0)

            for g in grits:
                pygame.draw.rect(background, g.color, Rect(g.x, g.y, g.width, g.height), 0)
                if g.active:
                    if g.y>-1 and g.y<(480-g.height):
                        c = background.get_at((g.x, g.y+g.height));
                        if c.r==0 and c.g==0:
                            g.y = g.y + 5
                        else:
                            g.active = False
                    if g.y<0:
                        g.y = g.y + 5
            window.blit(background, (0, 0))
            pygame.display.flip()
        elif event.type == pygame.KEYDOWN:
            keystate = pygame.key.get_pressed()
            if not keystate[K_w]==1:
                grits = init()
        elif event.type == pygame.QUIT:
            sys.exit()

Any suggested improvements? I would like to use this for a treaure hunt game. Two players digging for gold. Soil lumps might have to be bigger for a game.

Sunday 8 July 2012

Python Tools For Visual Studio

Day to day I use Visual Studio for ASP.net and CSharp. It is okay-ish. I used to like Visual Studio then around version 6/7 it went rather multipurpose/multilanguage and lessened the experience. Nowadays it needs a lot of horsepower and big expensive plugins like Resharper to keep up. 

I have kept the monster of Visual Studio off my ageing Vista era laptop for some time. Sharp Develop is an FOSS IDE that fills that gap nicely. Microsoft do offer Express versions which are good but they are rather frustrating if you have used the full versions!


Anyway Microsoft also produce Python Tools for Visual Studio which can be run on top of the free Visual Studio Shell. PTVS is also free and open source. It supports various versions of Python - not just IronPython (I am currently using it for PyGame with CPython 2.6.6). The code completion is pretty good and, surprisingly, it is not too resource demanding on my ol' Dell Inspiron 1501! It has a long list of features including refactoring, debugging, Django, REPL. Also comes with some extras for Excel and the Xbox Kinect.

I jump around editors quite a lot but I think will hang around PTVS for a good while.

Friday 6 July 2012

The Future Of PyGame

pgreloaded - PyGame Reloaded - Multimedia Framework for Python - Google Project Hosting: "Pygame Reloaded (aka pygame2, pgreloaded) started as a rewrite of the Pygame multimedia and game framework. As of 2012, the development focuses on providing a ctypes-based wrapper around SDL 2.0, along with a rich feature set for creating multimedia applications, games and graphics-based application prototypes." PyGame is built on SDL which has been a long lasting library. SDL has moved though and PyGame inevitably lags. A project exists to 'reboot' PyGame and move onto a newer SDL called Pgreloaded. As it is a Ctypes based wrapper and will allow for the library to run on other Python implementations such as IronPython. There is loss of compatibility with existing PyGame code. A lot of books will need to be rewritten I think! However the benefits of the Reload look promising. PyGame has a good future ahead of it so I am glad to be getting back into it at this time.