Size Matters.

I’ve arrived in Canada to spend Christmas with the parents.

Consequently, there is of course an update on my programming.

I’ve spent the evening editing what I’ll now start calling my pyGame Engine so that the window resolution can be scaled on the fly to any aspect ratio, and the game’s images will all redraw themselves as this happens.

This means that you can resize the window as much as you want, and it will not a) ‘stretch’ the images, or upscale them, or compress them. The sprites are just redrawn to fit the new screen size. Just like vector graphics, you could, technically speaking, make the screen as large as you want and the image will get bigger and bigger without loosing detail. b) affect the gameplay. It does this via resizing all the hit-boxes and etc. (and maybe eventually the speeds of the charactors) according to the new size. This does mean, however, that altering the aspect ratio will make the main charactor rather fatter than normal :P

Is this (fun to program) upgrade any use? I don’t know. It depends if you want to make my game’s visuals all go wierdly askew, or if you want to play the game on a monitor with a resolution of 2860×1280.

I might incorporate this into the game itself, so that different levels/obstacles or whatever change the screen. I think a trap of some kind which makes the window size smaller and smaller as you get closer to it would be hilarious.

Posted in Anything Else | Leave a comment

Eventual Update.

I’ve been quiet of late.

I spent two weeks working as a sound operator on the university’s production of The Tempest, which was really good fun and a great way to learn some new bits and pieces. It does, however, take up a surprisingly large amount of your time.

In between shows and rehearsals, I’ve been working on some recording and mastering projects for my course, all of which are due in before the main project discussed in this blog.

Hence the silence.

I’ve worked on the game code a little bit in the background, but there’s not much to actually show yet.

Hang tight!

Posted in Anything Else, University | Tagged | Leave a comment

Pixels.

I’ve spent the last few hours working on some pixel art.

I wanted to experiment to see if I could come up with anything half-decent. I am happy to say that with the help of Derek Yu’s awesome tutorial mediocrity was achieved!

pixel1-2

The little fella’ is also available for viewing on the gallery page.

Posted in Anything Else | Tagged | Leave a comment

New Sound.

Not done a lot of programming today, I’ve instead been doing some music-y magic-y happy(-y?) stuff.

A lot of the tracks weren’t so great, but one track was alright, and it’s now on the music page. It’s called ‘simpleBit’.

That kinda sums it up really. Made in a few hours with Reason 5/Record 1.5 and ‘mastered’ in Reaper (a program I am seriously starting to love) in about 15 minutes.

I think it sounds nice and happy, but you tell me.

Posted in Music | Tagged , , , | Leave a comment

Some Objects.

I really hope that the little bits of Object-Oriented Programming within Pygame that I’m learning will eventually pay dividends.

Mostly using my small amount of Python Classes knowledge and sjbrown’s awesome tutorial I’ve written the code appended at the bottom of this post.

It’s a lot of lines and took me several hours and all it does is draw the charactor and quit when you ask it to. You’re meant to be able to move the charactor with the arrow keys but that don’t work it’s very basic and the display updating still feels like a bit of hack. Lots of progress to do. I just now tried to get his emotions to work but that ain’t happening.

I’m assured that these harder methods at the start will yield better results once the project really gets going and grows out of itself. I sure hope so.

Here’s OOGame.py:

#! /bin/python
import os, sys, math, random, subprocess, pygame, charactor
from pygame.locals import *

#----Constants----
IP = '127.0.0.1'
PORT = 65563
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
#-----------------

class PumpEvent:
    def __init__(self):
        self.name = "Pump Event"

class QuitEvent:
    def __init__(self):
        self.name = "Quit Event"

class PlayerMoveEvent:
    def __init__(self, direction):
        self.name = "Player Move Event"
        self.direction = direction

class PlayerSpawnEvent:
    def __init__(self):
        self.name = "Player Spawn Event" 

class PlayerEmotionEvent:
    def __init__(self, emotion):
        self.name = "Player Emotion Event"
        self.eMover = emotion

class Manager:
    def __init__(self):
        printer("Manager Started")
        from weakref import WeakKeyDictionary
        self.listeners = WeakKeyDictionary([])
        self.remListeners = []
        self.addListeners = []
        self.eventQueue = []

    def addListener(self, listener):
        self.addListeners.append(listener)

    def remlistener(self, listener):
        self.remListeners.append(listener)

    def updateListenerLists(self):
        for i in self.addListeners:
            self.listeners[i] = 1
        for i in self.remListeners:
            if i in self.listeners:
                del self.listeners[i]

    def post(self, event):
        self.eventQueue.append(event)
        if isinstance(event, PumpEvent):
            self.updateListenerLists()
            self.doQueue()
        else:
            printer("Event: %s" % event.name)

    def doQueue(self):
        i = 0
        while i < len(self.eventQueue):
            event = self.eventQueue[i]
            for a in self.listeners:
                old = len(self.eventQueue)
                a.pump(event)
            i += 1
            if self.addListeners:
                self.updateListenerLists()
        self.eventQueue = []

class Controller:
    def __init__(self, manager):
        printer("Controller Started")
        self.manager = manager
        self.manager.addListener(self)

    def pump(self, event):
        if isinstance(event, PumpEvent):
            for i in pygame.event.get():
                if i.type == QUIT:
                    self.manager.post(QuitEvent())
                if i.type == KEYDOWN:
                    if i.key == K_ESCAPE:
                        self.manager.post(QuitEvent())
                    if i.key == K_LEFT:
                        self.manager.post(PlayerMoveEvent('left'))
                    if i.key == K_RIGHT:
                        self.manager.post(PlayerMoveEvent('right'))
                    if i.key == K_SPACE:
                        self.manager.post(PlayerSpawnEvent())
                    if i.key == K_UP:
                        self.manager.post(PlayerEmotionEvent(1))
                    if i.key == K_DOWN:
                        self.manager.post(PlayerEmotionEvent(-1))
                #if i.type == KEYUP:
                #   if i.key == K_LEFT:
                #       self.manager.post(Player

class Mouse:
    def __init__(self, manager):
        printer("Mouse Started")
        self.manager = manager
        self.manager.addListener(self)

    def pump(self, event):
        if isinstance(event, PumpEvent):
            self.x, self.y = pygame.mouse.get_pos()

class Charactor(pygame.sprite.Sprite):
    def __init__(self):
        printer("Charactor Started")

    def create(self, x, y, width, height, emotion, screen):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.emotion = emotion
        self.screen = screen
        self.draw()
        self.spawned = True

    def draw(self):
        self.screen.fill((0,0,0))
        self.charactor = charactor.charactor(self.x, self.y, self.width, self.height, self.emotion, self.screen)

    def move(self, direction):
        printer(self.x, self.y)
        printer(direction)
        if direction == 'left':
            self.x -= 50
            self.draw()
        elif direction == 'right':
            self.x += 50
            self.draw()

    def emotion(self, eMover):
        if eMover > 5:
            eMover = 1
        elif eMover < 1:
            eMover = 5
        self.emotion += eMover
        self.draw()

class View:
    def __init__(self, manager):
        printer("View Started")
        self.manager = manager
        self.manager.addListener(self)
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        self.dirtyRects = []

    def pump(self, event):
        if isinstance(event, PlayerSpawnEvent):
            myCharactor.create(0,200,200,160,3, self.screen)
            pygame.display.flip()
        if isinstance(event, PlayerMoveEvent):
            myCharactor.move(event.direction)
        #if isinstance(event, PlayerEmotionEvent):
         #   printer(event)
          #  myCharactor.emotion(event.eMover)
        self.update()

    def update(self):
        pygame.display.update()
        #printer("update")

class Looper:
    def __init__(self, manager):
        printer("Looper Started")
        self.manager = manager
        self.manager.addListener(self)
        self.looping = True

    def loop(self):
        while self.looping:
            self.manager.post(PumpEvent())

    def pump(self, event):
        if isinstance(event, QuitEvent):
            self.looping = False            

class Game:
    def __init__(self, manager):
        global myCharactor
        printer("Game Started")
        self.manager = manager
        self.manager.addListener(self)
        self.manager.post(PlayerSpawnEvent())
        myCharactor = Charactor()

    def pump(self, event):
        if isinstance(event, QuitEvent):
            pygame.quit()
            sys.exit()

def main():
    pygame.init()
    myManager = Manager()

    myController = Controller(myManager)
    myLooper = Looper(myManager)
    myView = View(myManager)
    myGame = Game(myManager)

    myLooper.loop()

def printer(*msg):
    print(msg)

if __name__ == '__main__':
    main()

And charactor.py as imported from OOGame.py:

import sys, os, subprocess, math, random
import pygame
from pygame.locals import *

def tri(posX, posY, triWidth, triHeight, flip, color, screen):
    x1 = posX
    x2 = posX + (triWidth/2)
    x3 = posX + triWidth
    if flip:
        y1 = posY - triHeight
        y2 = posY
        y3 = posY - triHeight
    else:
        y1 = posY
        y2 = posY - triHeight
        y3 = posY
    return pygame.draw.polygon(screen, color, [(x1,y1), (x2,y2), (x3,y3)]) 

def charactor(posX, posY, charWidth, charHeight, emotion, display):
    """
    Draws a charactor figure, with one of these five available emotions:
    1 = aghast
    2 = grumpy
    3 = normal
    4 = cool
    5 = happiest
    """
    footHeight = charHeight/4
    truPosY = posY
    posY = posY - footHeight
    #main body
    color = (20, 155, 15)
    tri(posX, posY, charWidth, charHeight, False, color, display) #body
    tri(posX + (charWidth/6), truPosY, charWidth/4, footHeight, True, color, display) #left foot
    tri(posX + (charWidth/1.69), truPosY, charWidth/4, footHeight, True, color, display) #right foot
    if emotion == 1 or emotion == 2:
        mouthFlip = False
        mouthPosX = posX + (charWidth/4.5)
        mouthPosY = posY - (charHeight/16)
        mouthWidth = charWidth/1.8
        mouthHeight = charHeight/3.5
        leftEyePosX = posX + (charWidth/2.8)
        rightEyePosX = posX + (charWidth/2)
        eyeWidth = charWidth/6.5
        eyeHeight = charHeight/6
        if emotion == 1:
            eyeFlip = False
            eyePosY = posY - (charHeight/2)
        else:
            eyeFlip = True
            eyePosY = posY - (charHeight/2.5)
    elif emotion == 3 or emotion == 4:
        mouthFlip = True
        mouthPosX = posX + (charWidth/4)
        mouthPosY = posY - (charHeight/16)
        mouthWidth = charWidth/2
        mouthHeight = charHeight/3.5
        leftEyePosX = posX + (charWidth/2.8)
        rightEyePosX = posX + (charWidth/2)
        eyeWidth = charWidth/6.5
        eyeHeight = charHeight/6
        if emotion == 3:
            eyeFlip = False
            eyePosY = posY - (charHeight/2)
        else:
            eyeFlip = True
            eyePosY = posY - (charHeight/2.5)
    else:
        mouthFlip = True
        eyeFlip = False
        mouthPosX = posX + (charWidth/4.4)
        mouthPosY = posY - (charHeight/18)
        mouthWidth = charWidth/1.8
        mouthHeight = charHeight/3
        leftEyePosX = posX + (charWidth/3)
        rightEyePosX = posX + (charWidth/2)
        eyePosY = posY - (charHeight/2)
        eyeWidth = charWidth/5.5
        eyeHeight = charHeight/4.5
    #face
    color = (0,0,0)
    tri(mouthPosX, mouthPosY, mouthWidth, mouthHeight, mouthFlip, color, display) #mouth
    tri(leftEyePosX, eyePosY, eyeWidth, eyeHeight, eyeFlip, color, display) #left eye
    tri(rightEyePosX, eyePosY, eyeWidth, eyeHeight, eyeFlip, color, display) #right eye

def enemy(posX, posY, charWidth, charHeight, screen):
    footHeight = charHeight/4
    truPosY = posY
    posY = posY - footHeight
    color = (20,155,150)
    tri(posX + (charWidth/6), truPosY, charWidth/4, footHeight + (charHeight/2), False, color, screen) #left foot
    tri(posX + (charWidth/1.69), truPosY, charWidth/4, footHeight + (charHeight/2), False, color, screen) #right foot
    tri(posX, posY, charWidth, charHeight, True, color, screen) #body
    color = (0,0,0)
    tri(posX + (charWidth/4), posY - (charHeight/1.7), charWidth/5.5, charHeight/5, True, color, screen) #left eye
    tri(posX + (charWidth/1.76), posY - (charHeight/1.7), charWidth/5.5, charHeight/5, True, color, screen) #right eye

def eventManager():
    global speaking, click, x, y
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                pygame.quit()
                sys.exit()
            elif event.key == K_w:
                click = 1
            elif event.key == K_a:
                click = 2
            elif event.key == K_s:
                click = 3
            elif event.key == K_d:
                click = 4
            elif event.key == K_x:
                click = 5
        if event.type == MOUSEBUTTONDOWN:
            if click == 5:
                click = 1
            else:
                click += 1
        if event.type == MOUSEMOTION:
            x, y = event.pos

def draw():
    global x, y, click
    screen.fill((0,0,0))
    charactor(50, 200, 160, 120, 1, screen)
    charactor(250, 200, 160, 120, 2, screen)
    charactor(450, 200, 160, 120, 3, screen)
    charactor(650, 200, 160, 120, 4, screen)
    charactor(850, 200, 160, 120, 5, screen)
    enemy(50, 400, 160, 120, screen)
    charactor(x,y, 200, 160, click, screen)
    pygame.display.update()

def main():
    global screen, click, x, y
    pygame.init()
    screen = pygame.display.set_mode((1050, 480))
    pygame.display.set_caption("Charactor.py")
    x,y = 1,1
    print("Welcome to The Future! You're running: \n Python %s \n Pygame %s" % (sys.version, pygame.ver))
    while True:
        eventManager()
        draw()

click = 1

if __name__ == '__main__':
    main()
Posted in Programming | Tagged , | Leave a comment

Sounds.

I spent this evening after band practice experimenting with some sounds in Propellerhead’s Record 1.5 and Reason 5.0.

This resulted in a track called tenseToExciting (descriptive, eh?). It’s on my music page here.

I might at some point do a proper look into how I made the sounds. They didn’t actually take that long, and I was pleased with the unpredictability of some of them. It might be fixed media (ah-ha! my arch nemesis!) but you can still utilise some pseudo-random effects.

Posted in Music | Tagged , , | Leave a comment

Distancing.

Today had a slight tail of productivity after most of the hours being spent avoiding CISCO revision and ‘researching’ Killer 7. Damn freaky game.

I did a tiny bit of work to see how easy it would be do get Pygame to calculate the distance between two objects, and send this information to Pure Data.

Turns out: Very Easy.

What will follow is a simple (and ugly) python script which creates a window with two rectangles, one of which is controlled by the mouse, and the other by both the arrow keys and the WASD keys. When this is linked to my Pure Data module (not included), the smaller the distance then the more the original sine wave signal gets modulated, both with frequency modulation and amplitude modulation.

I aim to use this sort of effect within the game as an immersive sign of danger for the player.

Here’s the script:

import pygame, os, sys, math, subprocess
from pygame.locals import *

#------GLOBALS-----
IP = "127.0.0.1"
PORT = 65665
#------------------

#---EXTERNAL PROGRAM HANDLING----
if os.name == "nt":
    print "You're on Windows! Please tell me you illegally downloaded this."
    def sendOSC(msg, address='/default'):
        """
        Hello There! This is a docstring!
        """
        import simpleOSC
        simpleOSC.initOSCClient(IP,PORT)
        message = simpleOSC.sendOSCMsg(address, msg)

    def espeak(speech, voice='english'):
        args = ['C:/Program Files (x86)/eSpeak/command_line/espeak.exe', '-v', voice, speech]
        p = subprocess.Popen(args)

    def pd(patch='seq1'):
        args = ['C:/pd/bin/pd.exe', '-nogui', patch]
        p = subprocess.Popen(args)
elif os.name == "posix":
    print "You're on Linux! You hacker, you!"
    def sendOSC(msg, address='/default'):
        import liblo
        target = liblo.Address(IP,PORT)
        libloMsg = liblo.Message(address)
        for a in msg:
            libloMsg.add(a)
        liblo.send(target, libloMsg)

    def pd(patch='seq1'):
        args = ['jackd', '-d' 'alsa']
        args2 = ['pasuspender', '--', '/usr/bin/pdextended', '-jack', patch]
        p = subprocess.Popen(args)
        p2 = subprocess.Popen(args2)

    def espeak(speech, voice='english'):
        args = ['"usr/bin/espeak"', '-v', voice, speech]
        p = subprocess.Popen(args)
else:
    print "OS has not been recognised. This is either a bug, or you're using a Macintosh computing system. Either way you need help."
    pygame.quit()
    sys.exit()
#------------------------------

def getDist((x1,y1), (x2,y2)):
	return math.sqrt((x1-x2)**2 + (y1-y2)**2)

def main():
	"""
	The Game Loop.

	Fear It.
	"""
	pygame.init()
	screen = pygame.display.set_mode((640,480))
	aX, aY = 100,100
	bX, bY = 300,300

	movebX = 0
	movebY = 0

	while True:

		for event in pygame.event.get():
			if event.type == QUIT:
				pygame.quit()
				sys.exit()
			if event.type == KEYDOWN:
				if event.key == K_UP or event.key == K_w:
					movebY = -1
				if event.key == K_DOWN or event.key == K_s:
					movebY = 1
				if event.key == K_LEFT or event.key == K_a:
					movebX = -1
				if event.key == K_RIGHT or event.key == K_d:
					movebX = 1
				if event.key == K_ESCAPE:
					pygame.quit()
					sys.exit()
			elif event.type == KEYUP:
				if event.key == K_UP or event.key == K_w:
					movebY = 0
				if event.key == K_DOWN or event.key == K_s:
					movebY = 0
				if event.key == K_LEFT or event.key == K_a:
					movebX = 0
				if event.key == K_RIGHT or event.key == K_d:
					movebX = 0

		aX, aY = pygame.mouse.get_pos()

		bX += movebX
		bY += movebY

		screen.lock()
		screen.fill((0,0,0))
		shapeA = pygame.draw.rect(screen, (255,255,255), (aX,aY,100,100), 1)
		shapeB = pygame.draw.rect(screen, (255,255,0), (bX,bY,100,100), 1)
		screen.unlock()

		sendOSC([int(getDist((aX,aY),(bX,bY)))])

		pygame.display.update()

if __name__ == '__main__': main()

P.S. (geddit?): My housemate helped me come up with an awesome idea the other day: The Metatrap. It’s the idea of an in-game obstacle which doesn’t necessarily impede/annoy/hurt the charactor on screen, but one that impedes/annoys/hurts the player controlling him. Still, while it does have potential, I would have to make sure it doesn’t just make someone mad at me. They might hit me then :(

Posted in Programming | Tagged , | Leave a comment

Emoting with triangles.

A (somewhat) central idea behind my game is that simplistic graphics are a) easier to draw and b) easier to relate to. The human brain is a fantastic tool for applying emotions to things, and a big cheesy grin on just about anything can instantly make it humane.

I intend to utilise this within my game, as it makes my job easier (I’m not an artist by nature or trade) and arguably offers a more personal experience. When you have to ‘humanise’ an object yourself, you use elements of your own creativity and experiences and it becomes easier to care about the character. It’s the same concept as when reading a book, you give each character their own image and voice, only loosely based on the author’s own descriptions of such.

Or maybe only I do that. Until I saw the films, I always imagined Professor Snape from Harry Potter looked like Dr. Fred Edison from Day of the Tentacle.

I ramble. I’ve just spent a small amount of time in Processing on a idea I came up with a week ago which was “can I create a character purely from triangles?”

You tell me.

concept-tri-char

Posted in Anything Else | Tagged | Leave a comment

A banner, and a matter of self-motivation.

I’ve created a banner, oh wow!

All the shapes and thingies were made in Processing, the text is just a color-inverted screenshot of a Pure Data file I made for the purpose (it does of course still function as an actual audio patch, hitting the left button slowing increases the pitch of a saw wave, and the right button lowers it). The seperate images were loaded into GIMP and then I fooled around learning how to use transparency, mask layers and the move tool (surprisingly tricky, that one).

Of the second atom of the title, recently I’ve been impressed by my own tendencies to get stuff done. I have a university project in for tomorrow, and yet I mostly finished a few days ago and have just been doing a few touch-ups and getting my tutor to have a quick look at it. How will this responsibility last? We shall see.

I’m really enjoying learning Processing at the moment (I still think it’s a stupid name, though, ever tried googling for things related to it?) and I think I might use it to flesh out the character designs for my upcoming game. According to my timeplans, I should be working on designing and researching the game and the audio while working on some audio prototypes. So I’ll do that then (how responsible is that?).

Posted in Anything Else, University | Tagged , , , | Leave a comment

I made a thing!

Look at it go!

This was created in Processing when I was messing around drawing circles.

It’s not actually meant to do this. Ah well.

Posted in Programming | Tagged , | Leave a comment