Jump to content

  • Log In with Google      Sign In   
  • Create Account

Managing a Grid of Objects by their Properties


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
No replies to this topic

#1 PaladinJohn   Members   -  Reputation: 130

Like
0Likes
Like

Posted 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()


Sponsor:



Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS