Jump to content

  • Log In with Google      Sign In   
  • Create Account

PaladinJohn

Member Since 28 Mar 2009
Offline Last Active Jan 16 2013 11:46 PM

Topics I've Started

Pygame - Completely Removing a Sprite from Memory

16 January 2013 - 02:23 PM

Hello!

I'm working on a Breakout style game, and after much testing I've pinpointed my exact problem. Sprites that I've given the .kill() command to and removed from all groups are still persistent in memory and causing issues. Below are a few excerpts of my code, and I'd appreciate if someone could point me in the direction of a better command to use, or perhaps a logic error in my coding.

 

(Note:

spell = ball

shield = paddle)

 

The root of the problem

 

I decided to add some simple items to enhance gameplay. This particular item is supposed to split your ball into three:

 

def itemEffects(self):
    if len(self.spellSprites) == 1:
        if self.spell.angle == 30 or self.spell.angle == 45 or self.spell.angle == 60:
            tempSpellx = self.spell.rect.x
            tempSpelly = self.spell.rect.y
            tempSpellSpeed = self.spell.speed
            tempSpellAngle = self.spell.angle
            self.spellSprites.empty()
            j = 30
            for i in range (0,3):
                self.spell = Spell(self.shield)
                self.spell.setStats(True, tempSpellx, tempSpelly, tempSpellSpeed, j)
                self.spell.setVelX(self.spell.angle)
                self.spell.setVelY(self.spell.angle)
                self.spellSprites.add(self.spell)
                j += 15

Directional movement is locked on 12 seperate angles, 3 for each quadrant. This code checks the quadrant, saves the current balls relevant stats to a temporary variable, clears the entire ball sprite group, then creates three new balls given the saved stats with the three angles for that quadrant. I believe the problem is that the first sprite created in this group remains in memory even after it's .kill() function is invoked.

 

Ball Death

 

Here is the code for when a ball meets it's untimely demise:

 

for theSpell in self.spellSprites:
    if theSpell.rect.centery > 540:
        if len(self.spellSprites) <= 1:
            LIVES -= 1
            self.loadLives()
            self.shield.reset()
            theSpell.kill()
            self.spellSprites.empty()
            self.spell = Spell(self.shield)
            self.spellSprites.add(self.spell)
            self.itemSprites.empty()
            if LIVES < 0:
                SCORE = 0
                LIVES = 2
                self.showTextScreen('Game Over!', 'Press Escape to Quit or Any Key to Play Again.', 2)
        else:
            theSpell.kill()

I thought this would be sufficient to destroy a ball and make everything work ok. Instead, it would appear that the first ball stays in memory.

 

I came to this conclusion because when there is one ball remaining, and the length of the spellSprites group is equal to 1, occasionally when I obtain a power up to split the balls, the current ball will disappear and a life will be lost as if the ball was out of bounds. It is my belief that the extra balls are spawning off of the primary spell who's location is far below paddle, thus instantly trigerring a loss of life as all balls are lost.

 

The Question

 

Is there a way to permenantly delete a sprite out of memory? If not, is there a way that I can access specific sprite objects within the sprite group when they all share the same name? If that's not possible either, is there some other way I can go about trying to solve this problem that I may have overlooked?

 

If there is any other information or code necessary to provide in order to solve this issue, let me know. Thank you for your time and I greatly appreciate any help you are able to give!


Pausing Python (or causing a delay)

09 July 2012 - 07:36 PM

Apologies ahead of time if I'm not articulating my issue clearly enough but I'm having trouble pausing the logic of my program for half a second before resuming to allow a very basic explosion like effect.

Here is the block of code as I currently have it:

[source lang="python"]def eliminate(self, occupiedGrid): if len(self.matchedElements) >= 1: for x in range (0, len(self.matchedElements)): if self.matchedElements[x].type == 2: self.remainingBlocks -= 1 occupiedGrid[xToGrid(self.matchedElements[x].x)][yToGrid(self.matchedElements[x].y)].type = 3 self.draw(self.occupiedGrid) pygame.display.update() time.sleep(0.5) for x in range (0, len(self.matchedElements)): occupiedGrid[xToGrid(self.matchedElements[x].x)][yToGrid(self.matchedElements[x].y)] = 0[/source]
Unfortuantely, this isn't working as intended, as the graphics haven't quite caught up when the pause goes into effect, failing to display the explosion graphic (type 3) and instead skipping right past it. Because of the way the program is written, I can't leave this sequence of events to return to the main loop to artificially create a pause, as this is in the middle of data altering logic and all of the data at this point would be half-altered and create an issue. As a small example, this block of code appears in this sequence of events:

[source lang="python"]def clearObjects(self, occupiedGrid): self.matchedElements = [] self.checkGrid(self.occupiedGrid) self.eliminate(self.occupiedGrid) self.checkLinked(self.occupiedGrid) self.draw(self.occupiedGrid) if self.remainingBlocks == 0: screen.fill((100, 100, 100)) self.showTextScreen('Cleared!', 'Press Escape to Quit or Any Key to Play Again.', 2) self.delay = True[/source]
For the record, I have tested the program by stopping it completely once the type is changed and it displays the graphic just fine. Without a pause, however, the graphic is not up long enough for the human eye to discern it was there in the first place as the program quickly moves to the part where it clears the graphic and creates an empty space in it's place.

Managing a Grid of Objects by their Properties

11 April 2012 - 05:48 PM

First off, apologies for posting a request for help on this same project again, but I'm determined to see it through to it's conclusion no matter how many obstacles get in my way. I've made a personal promise not to ask for outside help unless I've been stuck on the same problem for more than a week, but once again I've hit a brick wall. In my previous threads I didn't recieve any responses and eventually figured out how to solve the problem, but this time I can say with confidence that I've hit the biggest one yet. So, for that, any insight or advice would be very much greatly appreciated. Even if I do not recieve an answer to my problem, even just a different perspective on trying to solve it might help me figure things out on my own. Here's a little background and the problem:

After reading several books on Python cover to cover, I decided that I would attempt to apply my knowledge in creating a game from scratch on my own. Every thing I read suggested Tetris as a baseline, but rather than listen I went with a game I didn't think would be much different in remaking Dr. Mario. I have almost all of the basic game elements finished, with the exception of perhaps the most important: Detecting and clearing lines. I thought I would pass objects onto a grid with an element property that detected what color each game piece was, then search the columns and rows for any sequences of objects with the same element greater than 3, and then clear them. Unfortunately, in troubleshooting my program, I realized that all of the elements in the list are inheriting the current game piece's elements and not retaining their own. This leads me to believe that the method I am using for putting them on the grid is faulty. I can't tell where I messed up, or how I could have done it better since everything graphically is working as it should. Below are the problem areas of the program I believe have a problem somewhere:

def draw(self, occupiedGrid):
	 for x in range(0, NUM_COLUMNS):
	 	 for y in range (0, NUM_ROWS):
	 	 	 if self.occupiedGrid[x][y] != 0:
	 	 	 	 self.element = Element(self.occupiedGrid[x][y].element, self.occupiedGrid[x][y].linked, self.occupiedGrid[x][y].dir)
	 	 	 	 self.element.x = self.occupiedGrid[x][y].x
	 	 	 	 self.element.y = self.occupiedGrid[x][y].y
	 	 	 	 self.element.populate()
	 	 	 	 self.inactiveSprites.add(self.element)

and:

def clearObjects(self, occupiedGrid):
	 self.matchedElements = []

	 for x in range (0, NUM_COLUMNS):
	 	 self.temp_list = []
	 	 for i in range(0, NUM_ROWS):
	 	 	 if self.occupiedGrid[x][i] != 0:
	 	 	 	 self.temp_list.append(self.occupiedGrid[x][i])
	 	 	 if len(self.temp_list) >= 4:
	 	 	 	 self.matchedElements = self.matchedElements + self.temp_list
	 	 	 	 print self.matchedElements[0].element

Please note that clearObjects() is currently written as a debug method and not as what I intend for it to be in the final program. It was at this point that I discovered the grid elements were not appearing as they were supposed to.

Once again, thank you for any one who took a look at this. I know that after I get proper clearing and bpard state settling implemented, everything left is all down hill from there and will take me very little time to finish off the program. If my technique or ideas in implementing this game are completely off as well, feel free to let me know. I would rather be shown new ideas and methods at this early stage in my programming journey than develop bad habits that are hard to get out of later on down the road. I have been demoralized by this project since I started it in late January and still haven't made decent progress all these months later and keep running into problem after problem with my now very apparent limited understanding of programming. For that, I would appreciate any and all insight I can recieve to save me weeks from staring at my computer screen, randomly punching in new code until something clicks by happenstance.

The full code is below in case the problem is contained somewhere outside of these two functions:

import pygame, random
pygame.init()

NUM_COLUMNS = 8
NUM_ROWS = 16

DOWN = 1
LEFT = 2
RIGHT = 3
ROTATE = 4

screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()

class Element(pygame.sprite.Sprite):
	def __init__(self, element, linked, direction):
		self.element = element
		self.dir = direction
		self.linked = linked
		pygame.sprite.Sprite.__init__(self)
		self.imageMaster = pygame.image.load("WMana.xcf")
		self.generateElements()
		self.image = self.imageMaster
		self.rect = self.image.get_rect()
		self.image.set_colorkey((255, 255, 255))
		self.x = 0
		self.y = 0

	def generateElements(self):
		#1 = W, 2 = G, 3 = Y
		if self.element == 0:
			self.element = random.randrange(1, 4)
		if self.linked == True:
			if self.element ==1:
				self.imageMaster = pygame.image.load("piece_white.png")
			elif self.element == 2:
				self.imageMaster = pygame.image.load("piece_green.png")
			elif self.element == 3:
				self.imageMaster = pygame.image.load("piece_yellow.png")  
		if self.linked == False:
			if self.element == 1:
				self.imageMaster = pygame.image.load("WMana.xcf")
			elif self.element == 2:
				self.imageMaster = pygame.image.load("GMana.xcf")
			elif self.element == 3:
				self.imageMaster = pygame.image.load("YMana.xcf")
		self.imageMaster = self.imageMaster.convert()

	def resetElement(self):
		self.element = random.randrange(1,4)
		self.generateElements()

	def populate(self):
		self.image = pygame.transform.rotate(self.imageMaster, self.dir)
		self.rect = self.image.get_rect()
		self.rect.center = (self.x, self.y - 20)		
		
class Mana(pygame.sprite.Sprite):
	def __init__(self, pelement, selement):
		self.pelement = pelement
		self.selement = selement
		pygame.sprite.Sprite.__init__(self)
		self.imageMaster = pygame.image.load("testWW.xcf")
		self.reset()
		self.wait = 0
		self.drop = 12
		self.moving = 0

	def update(self):
		self.rotate()
		self.rect.bottomleft = (self.x, self.y)
		self.wait += 1
		self.checkPos()
		
	def elements(self):
		if self.pelement.element == 1:
			if self.selement.element == 1:
				self.imageMaster = pygame.image.load("testWW.xcf")
			elif self.selement.element == 2:
				self.imageMaster = pygame.image.load("testWG.xcf")
			elif self.selement.element == 3:
				self.imageMaster = pygame.image.load("testWY.xcf")
		elif self.pelement.element == 2:
			if self.selement.element == 1:
				self.imageMaster = pygame.image.load("testGW.xcf")
			elif self.selement.element == 2:
				self.imageMaster = pygame.image.load("testGG.xcf")
			elif self.selement.element == 3:
				self.imageMaster = pygame.image.load("testGY.xcf")
		elif self.pelement.element == 3:
			if self.selement.element == 1:
				self.imageMaster = pygame.image.load("testYW.xcf")
			elif self.selement.element == 2:
				self.imageMaster = pygame.image.load("testYG.xcf")
			elif self.selement.element == 3:
				self.imageMaster = pygame.image.load("testYY.xcf")
		self.imageMaster = self.imageMaster.convert()

	def rotate(self):
		oldBL = self.rect.bottomleft
		self.image = pygame.transform.rotate(self.imageMaster, self.dir)
		self.rect = self.image.get_rect()
		self.rect.bottomleft = oldBL

	def checkPos(self):
		if self.dir == 0 or self.dir == 360:
			self.pelement.x = (self.x + 10)
			self.pelement.y = (self.y + 10)
			self.pelement.dir = 0
			self.selement.x = (self.x + 30)
			self.selement.y = (self.y + 10)
			self.selement.dir = 180
		elif self.dir == 90:
			self.pelement.x = (self.x + 10)
			self.pelement.y = (self.y + 10)
			self.pelement.dir = 90
			self.selement.x = (self.x + 10)
			self.selement.y = (self.y - 10)
			self.selement.dir = 270
		elif self.dir == 180:
			self.pelement.x = (self.x + 30)
			self.pelement.y = (self.y + 10)
			self.pelement.dir = 180
			self.selement.x = (self.x + 10)
			self.selement.y = (self.y + 10)
			self.selement.dir = 0
		elif self.dir == 270:
			self.pelement.x = (self.x + 10)
			self.pelement.y = (self.y - 10)
			self.pelement.dir = 270
			self.selement.x = (self.x + 10)
			self.selement.y = (self.y + 10)
			self.selement.dir = 90

	def land(self, occupiedGrid):
		occupiedGrid[ xToGrid(self.pelement.x) ][ yToGrid(self.pelement.y) ] = self.pelement
		occupiedGrid[ xToGrid(self.selement.x) ][ yToGrid(self.selement.y) ] = self.selement

	def reset(self):
		self.pelement.resetElement()
		self.selement.resetElement()
		self.elements()
		self.image = self.imageMaster
		self.rect = self.image.get_rect()
		self.image.set_colorkey((255, 255, 255))
		self.x = 300
		self.y = 100
		self.dir = 0

	def checkCollision(self, inactiveSprites, occupiedGrid):
		if self.moving == DOWN:
			if self.rect.bottom > 380:
				return True
		if self.moving == LEFT:
			if self.rect.left < 260:
				return True
		if self.moving == RIGHT:
			if self.rect.right > 400:
				return True
			
		for x in range(0,NUM_COLUMNS):
			for y in range(0,NUM_ROWS):
				if self.moving == DOWN:
					if occupiedGrid[xToGrid(self.pelement.x)][yToGrid(self.pelement.y + 20)]:
						return True
					elif occupiedGrid[xToGrid(self.selement.x)][yToGrid(self.selement.y + 20)]:
						return True
				if self.moving == LEFT:
					if occupiedGrid[xToGrid(self.pelement.x - 20)][yToGrid(self.pelement.y)]:
						return True
					elif occupiedGrid[xToGrid(self.selement.x - 20)][yToGrid(self.selement.y)]:
						return True
				if self.moving == RIGHT:
					if occupiedGrid[xToGrid(self.pelement.x + 20)][yToGrid(self.pelement.y)]:
						return True
					elif occupiedGrid[xToGrid(self.selement.x + 20)][yToGrid(self.selement.y)]:
						return True
				if self.moving == ROTATE:
					if occupiedGrid[xToGrid(self.pelement.x)][yToGrid(self.pelement.y)]:
						return True
					if occupiedGrid[xToGrid(self.selement.x)][yToGrid(self.selement.y)]:
						return True

		return False

class Backdrop(pygame.sprite.Sprite):
	def __init__(self):
		pygame.sprite.Sprite.__init__(self)
		self.image = pygame.image.load("Border.xcf")
		self.image = self.image.convert()
		self.rect = self.image.get_rect()

	def update(self):
		self.rect.center = (320, 240)

class Game():
	def __init__(self):
		pygame.display.set_caption("Mana Clash!")
		
		self.background = pygame.Surface(screen.get_size())
		self.background.fill((100, 100, 100))
		screen.blit(self.background, (0, 0))
				
		self.getNewMana()
		self.backdrop = Backdrop()

		self.occupiedGrid = []
		for x in range(0, NUM_COLUMNS):
			self.occupiedGrid.append([])
			for y in range(0, NUM_ROWS):
				self.occupiedGrid[x].append(0)

		self.allSprites = pygame.sprite.OrderedUpdates(self.backdrop, self.mana)
		self.inactiveSprites = pygame.sprite.OrderedUpdates()

	def getNewMana(self):
		self.pelement = Element(0, True, 0)
		self.selement = Element(0, True, 0)
		self.mana = Mana(self.pelement, self.selement)

	def debug(self, occupiedGrid):
		for x in range(0, NUM_COLUMNS):
			for y in range (0, NUM_ROWS):
				if self.occupiedGrid[x][y] != 0:
					print self.occupiedGrid[x][y].element

	def draw(self, occupiedGrid):
		for x in range(0, NUM_COLUMNS):
			for y in range (0, NUM_ROWS):
				if self.occupiedGrid[x][y] != 0:
					self.element = Element(self.occupiedGrid[x][y].element, self.occupiedGrid[x][y].linked, self.occupiedGrid[x][y].dir)
					self.element.x = self.occupiedGrid[x][y].x
					self.element.y = self.occupiedGrid[x][y].y
					self.element.populate()
					self.inactiveSprites.add(self.element)

	def settle(self):
		self.mana.land(self.occupiedGrid)
		self.draw(self.occupiedGrid)
		self.mana.reset()

	def checkKeys(self):
		keys = pygame.key.get_pressed()
		if keys[pygame.K_LEFT]:
			self.mana.moving = 2
			self.mana.checkPos()
			if self.mana.checkCollision(self.inactiveSprites, self.occupiedGrid) == False:
				self.mana.x -= 20
		if keys[pygame.K_RIGHT]:
			self.mana.moving = 3
			if self.mana.dir == 0 or self.mana.dir == 180 or self.mana.dir == 360:
				if self.mana.x <= 340:
					self.mana.checkPos()
					if self.mana.checkCollision(self.inactiveSprites, self.occupiedGrid) == False:
						self.mana.x += 20
			elif self.mana.dir == 90 or self.mana.dir == 270:
				if self.mana.rect.right <= 380:
					self.mana.checkPos()
					if self.mana.checkCollision(self.inactiveSprites, self.occupiedGrid) == False:
						self.mana.x += 20
		if keys[pygame.K_DOWN]:
			self.mana.moving = 1
			self.mana.checkPos()
			if self.mana.checkCollision(self.inactiveSprites, self.occupiedGrid) == False:
				self.mana.y += 20
				self.mana.wait = 0
			elif self.mana.checkCollision(self.inactiveSprites, self.occupiedGrid) == True:
				self.settle()

	def fall(self):
		if self.mana.wait >= self.mana.drop:
			self.mana.wait = 0
			self.mana.moving = 1
			self.mana.checkPos()
			if self.mana.checkCollision(self.inactiveSprites, self.occupiedGrid) == False:
				self.mana.y += 20
			elif self.mana.checkCollision(self.inactiveSprites, self.occupiedGrid) == True:
				self.settle()

	def clearObjects(self, occupiedGrid):
		self.matchedElements = []

		for x in range (0, NUM_COLUMNS):
			self.temp_list = []
			for i in range(0, NUM_ROWS):
				if self.occupiedGrid[x][i] != 0:
					self.temp_list.append(self.occupiedGrid[x][i])
			if len(self.temp_list) >= 4:
				self.matchedElements = self.matchedElements + self.temp_list
				print self.matchedElements[0].element
				

	def mainLoop(self):
		keepGoing = True
		while keepGoing:
			clock.tick(10)
			pygame.mouse.set_visible(False)
			for event in pygame.event.get():
				if event.type == pygame.QUIT:
					keepGoing = False
				elif event.type == pygame.KEYDOWN:
					if event.key == pygame.K_RCTRL:
						if self.mana.dir == 90 or self.mana.dir == 270:
							if self.mana.x == 380:
								self.mana.x -= 20
						self.mana.moving = 4
						self.mana.dir += 90
						self.mana.checkPos()
						if self.mana.checkCollision(self.inactiveSprites, self.occupiedGrid) == True:
							self.mana.dir -= 90
						if self.mana.dir > 360:
							self.mana.dir = 90
					elif event.key == pygame.K_RALT:
						if self.mana.dir == 90 or self.mana.dir == 270:
							if self.mana.x == 380:
								self.mana.x -= 20
						self.mana.moving = 4
						self.mana.dir -= 90
						self.mana.checkPos()
						if self.mana.checkCollision(self.inactiveSprites, self.occupiedGrid) == True:
							self.mana.dir += 90
						if self.mana.dir < 0:
							self.mana.dir = 270

					if event.key == pygame.K_d:
						self.debug(self.occupiedGrid)
					if event.key == pygame.K_s:
						self.clearObjects(self.occupiedGrid)
				
			self.checkKeys()
			self.fall()

			self.allSprites.clear (screen, self.background)
			self.inactiveSprites.clear (screen, self.background)
			self.allSprites.update()
			self.inactiveSprites.update()
			self.allSprites.draw(screen)
			self.inactiveSprites.draw(screen)

			pygame.display.update()

		pygame.mouse.set_visible(True)

def main():
	game = Game()
	game.mainLoop()

def xToGrid(pixel_coordinate):
	return ((pixel_coordinate - 10) - 240) / 20

def yToGrid(pixel_coordinate):
	return ((pixel_coordinate - 10) - 100) / 20

if __name__ == "__main__":
	main()

Better way to do bounding?

27 March 2012 - 01:40 AM

Very simple problem I could use some input on. I'm working on a Dr. Mario-esque game, so a simple falling blocks game with control over a pair of blocks. Currently, I'm having a tough time with bounding in regards to rotating the blocks. Below are two snipets of code that control bounding:

keys = pygame.key.get_pressed()
	 if keys[pygame.K_LEFT]:
	 	 self.x -= 20
	 	 if self.rect.left <= 240:
	 	 	 self.x = 240
	 if keys[pygame.K_RIGHT]:
	 	 if self.rect.right <= 380:
	 	 	 self.x += 20
	 if keys[pygame.K_DOWN]:
	 	 self.y += 20
	 	 self.wait = 0
	 	 if self.rect.bottom >= 400:
	 	 	 self.y = 400

if event.key == pygame.K_RCTRL:
	 if self.mana.dir == 90 or 270:
	 	 if self.mana.x == 380:
	 	 	 self.mana.x -= 20
	 	 self.mana.dir += 90
	 	 if self.mana.dir > 360:
	 	 	 self.mana.dir = 90

For clarity sake, I thought I would also mention that I am rotating objects by the Bottom Left corner of the object to allow easy and accurate snapping to the grid and to better emulate the base material. The problem becomes that if the user presses the rotate button at exactly the right time, the game piece can get out of bounds overlapping the border for the grid the game takes place on. Is there a better way to make sure that there is absolutely no way that any part of my sprite can ever cross a particular point in the window the way I have things now? I tried adding a line of code in the sprite update method that checks to see if the right side of the sprite is past a certain point and if it is to move x back by 20, but it's still exhibiting the same behavior.

This only occurs on the right side, which leads me to believe this may all originate from how I'm rotating the piece and the challenges it produces in managing x in that manner. I'm going to try a few more methods in the morning, but I thought I would post this here to get some additional insight in better ways to manage boundaries.

Linking Images on a Grid

01 March 2012 - 02:44 AM

First off, please excuse me if my jargon is a little rough. I'm still learning the ropes to programming and haven't gotten completely used to accurately explaining things to professionals. That said, I'll do my best to describe the problem I'm currently facing.

To start with I'm using Python and pygame to program a Dr. Mario clone. A lot of what I read reccommended on starting with a Tetris like game as a beginner project, but I thought I'd try out Dr. Mario instead. My current problem is figuring out the best way to transition from one active piece to another while drawing the previous active piece to the game board.

The issue in particular is how I can load a specific graphic for linked pieces and non-linked pieces and how to distinguish them within an array. Currently, the array keeps track of the element, if any, that resides in each square on the grid. While I'm fairly confident I could get the program to load the desired element in each square, I have no clue how to load a single graphic that takes up two spots on the grid while simultaneously keeping them linked after they are no longer active.

Any pointers, tips, or resources (ideally aimed at beginners) would be appreciated. I've done preliminary research but sadly the only sources I could find were not well documented so I couldn't understand them (and I don't want to just copy/paste because then I won't learn any thing.) Below is the pseudo code for those that have never played Dr. Mario so that you can understand what I am trying to do and below that is the full code I have so far. Apologies in advance for not shortening it because I'm afraid I might leave out something vital. Thank you for taking the time to help me out!

Pseudo Code:
Spoiler


Source Code:
import pygame, random
pygame.init()

NUM_COLUMNS = 8
NUM_ROWS = 16

screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()

class Element(pygame.sprite.Sprite):
	def __init__(self, element):
		self.element = element
		pygame.sprite.Sprite.__init__(self)
		self.imageMaster = pygame.image.load("WMana.xcf")
		self.generateElements()
		self.image = self.imageMaster
		self.rect = self.image.get_rect()
		self.image.set_colorkey((255, 255, 255))
		self.x = 0
		self.y = 0

	def generateElements(self):
		#1 = W, 2 = G, 3 = Y
		if self.element == 0:
			self.element = random.randrange(1, 4)
			if self.element == 1:
				self.imageMaster = pygame.image.load("WMana.xcf")
			elif self.element == 2:
				self.imageMaster = pygame.image.load("GMana.xcf")
			elif self.element == 3:
				self.imageMaster = pygame.image.load("YMana.xcf")
			self.imageMaster = self.imageMaster.convert()

	def settle(self, occupiedGrid):
		occupiedGrid[ xToGrid(self.x) ][ yToGrid(self.y) ] = self.element

	def unSettle(self, occupiedGrid):
		occupiedGrid[ xToGrid(self.x) ][ yToGrid(self.y) ] = None

def xToGrid(pixel_coordinate):
	return ((pixel_coordinate - 10) - 240) / 20

def yToGrid(pixel_coordinate):
	return ((pixel_coordinate - 10) - 100) / 20

class Mana(pygame.sprite.Sprite):
	def __init__(self, pelement, selement):
		self.pelement = pelement
		self.selement = selement
		pygame.sprite.Sprite.__init__(self)
		self.imageMaster = pygame.image.load("testWW.xcf")
		self.elements()
		self.image = self.imageMaster
		self.rect = self.image.get_rect()
		self.image.set_colorkey((255, 255, 255))
		self.x = 300
		self.y = 100
		self.dir = 0
		self.wait = 0
		self.drop = 6

	def update(self):
		self.checkKeys()
		self.rotate()
		self.rect.bottomleft = (self.x, self.y)
		self.wait += 1
		if self.wait >= self.drop:
			self.wait = 0
			self.y += 20
			if self.rect.bottom >= 400:
				self.y = 400
		self.checkPos()
		
	def elements(self):
		#1 = W, 2 = G, 3 = Y
		if self.pelement.element == 1:
			if self.selement.element == 1:
				self.imageMaster = pygame.image.load("testWW.xcf")
			elif self.selement.element == 2:
				self.imageMaster = pygame.image.load("testWG.xcf")
			elif self.selement.element == 3:
				self.imageMaster = pygame.image.load("testWY.xcf")
		elif self.pelement.element == 2:
			if self.selement.element == 1:
				self.imageMaster = pygame.image.load("testGW.xcf")
			elif self.selement.element == 2:
				self.imageMaster = pygame.image.load("testGG.xcf")
			elif self.selement.element == 3:
				self.imageMaster = pygame.image.load("testGY.xcf")
		elif self.pelement.element == 3:
			if self.selement.element == 1:
				self.imageMaster = pygame.image.load("testYW.xcf")
			elif self.selement.element == 2:
				self.imageMaster = pygame.image.load("testYG.xcf")
			elif self.selement.element == 3:
				self.imageMaster = pygame.image.load("testYY.xcf")
		self.imageMaster = self.imageMaster.convert()

	def checkKeys(self):
		keys = pygame.key.get_pressed()
		if keys[pygame.K_LEFT]:
			self.x -= 20
			if self.rect.left <= 240:
				self.x = 240
		if keys[pygame.K_RIGHT]:
			if self.rect.right <= 380:
				self.x += 20
		if keys[pygame.K_DOWN]:
			self.y += 20
			self.wait = 0
			if self.rect.bottom >= 400:
				self.y = 400  

	def rotate(self):
		oldBL = self.rect.bottomleft
		self.image = pygame.transform.rotate(self.imageMaster, self.dir)
		self.rect = self.image.get_rect()
		self.rect.bottomleft = oldBL

	def checkPos(self):
		if self.dir == 0 or self.dir == 360:
			self.pelement.x = (self.x + 10)
			self.pelement.y = (self.y + 10)
			self.selement.x = (self.x + 30)
			self.selement.y = (self.y + 10)
		elif self.dir == 90:
			self.pelement.x = (self.x + 10)
			self.pelement.y = (self.y + 10)
			self.selement.x = (self.x + 10)
			self.selement.y = (self.y - 10)
		elif self.dir == 180:
			self.pelement.x = (self.x + 30)
			self.pelement.y = (self.y + 10)
			self.selement.x = (self.x + 10)
			self.selement.y = (self.y + 10)
		elif self.dir == 270:
			self.pelement.x = (self.x + 10)
			self.pelement.y = (self.y - 10)
			self.selement.x = (self.x + 10)
			self.selement.y = (self.y + 10)

	def settle(self, occupiedGrid):
		self.pelement.settle(occupiedGrid)
		self.selement.settle(occupiedGrid)

class Backdrop(pygame.sprite.Sprite):
	def __init__(self):
		pygame.sprite.Sprite.__init__(self)
		self.image = pygame.image.load("Border.xcf")
		self.image = self.image.convert()
		self.rect = self.image.get_rect()

	def update(self):
		self.rect.center = (320, 240)

class Game():
	def __init__(self):
		pygame.display.set_caption("Mana Clash!")
		
		self.background = pygame.Surface(screen.get_size())
		self.background.fill((100, 100, 100))
		screen.blit(self.background, (0, 0))

		self.pelement = Element(0)
		self.selement = Element(0)
		self.mana = Mana(self.pelement, self.selement)
		self.backdrop = Backdrop()

		self.allSprites = pygame.sprite.OrderedUpdates(self.backdrop, self.mana)

		self.occupiedGrid = []
		for x in range(0, NUM_COLUMNS):
			self.occupiedGrid.append([])
			for y in range(0, NUM_ROWS):
				self.occupiedGrid[x].append(0)

	def debug(self):
		for x in range(0, NUM_COLUMNS):
			for y in range(0, NUM_ROWS):
				print self.occupiedGrid
				break

	def mainLoop(self):
		keepGoing = True
		while keepGoing:
			clock.tick(5)
			pygame.mouse.set_visible(False)
			for event in pygame.event.get():
				if event.type == pygame.QUIT:
					keepGoing = False
				elif event.type == pygame.KEYDOWN:
					if event.key == pygame.K_RCTRL:
						self.mana.dir += 90
						if self.mana.dir > 360:
							self.mana.dir = 90
					elif event.key == pygame.K_RALT:
						self.mana.dir -= 90
						if self.mana.dir < 0:
							self.mana.dir = 270

					if event.key == pygame.K_d:
						self.debug()
					if event.key == pygame.K_s:
						self.mana.settle(self.occupiedGrid)

			self.allSprites.clear (screen, self.background)
			self.allSprites.update()
			self.allSprites.draw(screen)

			pygame.display.flip()

		pygame.mouse.set_visible(True)

def main():
	game = Game()
	game.mainLoop()

if __name__ == "__main__":
	main()

PARTNERS