• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.

PaladinJohn

Members
  • Content count

    22
  • Joined

  • Last visited

Community Reputation

130 Neutral

About PaladinJohn

  • Rank
    Member
  1. 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!
  2. Just wanted to post an update saying that I discovered the issue after getting some sleep. The delay was working just fine, but I had made the mistake of forgetting to call this lovely block of text before the pygame.display.update() [source lang="python"]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)[/source] After giving it it's own function and a minor tweak to the code I got it to work as intended. Thank you to any one that might have been puzzling over this.
  3. 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.
  4. 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: [code]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)[/code] and: [code]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[/code] 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: [code] 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()[/code]
  5. 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: [code]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[/code] [code]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[/code] 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.
  6. Sorry to bump this, but I'm still trying to work through this issue. Do you think that perhaps if I passed the entire Object onto the grid rather than the number that corresponds to the particular element, that might work? That way I could use the Direction of the sprite to tell if two objects next to each other are linked. Of course, doing that means I would have to seperate the sprites into two halves to properly load an image onto the grid. Unfortuantely, I don't know how I would continue to register the two seperate sprites as one entity other than perhaps making it a sprite group in which case I would probably have to scrap everything I have and redesign the program for a fourth time from the ground up and I'm hesitant to do that when I'm not even sure that my idea will work properly. I know programming isn't supposed to be an easy process, but I can't help but feel that I'm doing things terribly innefficiently and taking unnecessary steps to accomplish something very simple. More so, I'm worried that there isn't a lot of information out there to bridge the gap from beginner to intermediate when it comes to game programming in Python. I can find tons of beginner examples that I know and understand but don't come close to performing the tasks I need, but every thing above that seems to be using advanced techniques that are performing tasks far above my current skill level. I'm hesitant to ask, but perhaps should I try a different programming language since I seem to have gotten stuck in the mud with Python? C# seems to have much better community support and documentation and is widely used. I chose Python because I liked the syntax and the logic was very easy to follow compared to my previous forays into programming. If any one that has started with Python as their first step into serious programming can give me a little insight on how they managed to overcome the hurdle in making the jump from beginner to intermediate I would appreciate it.
  7. 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]1. The player drops Mana from the top of the screen to elemental energy "Blocks". - Mana comes in three forms, Light, Wind, and Earth. - Mana comes in groups of two and may be combinations of any of the above. - Mana may be rotated 90 degrees at a time Clockwise or Counter Clockwise. - Players will see the next mana group to fall while controlling the active group. - When a Mana Pair collides with a Block, other Mana, or the bottom of the board it becomes a part of the game board. - After the board is done settling, the next Mana Pair is introduced and gameplay continues. 2. All of the action happens in an 8 x 16 Vertical Rectangle grid. 3. Blocks will be placed at random with in the bottom 12 rows of the Box. - Number of blocks starts at 4 for level 1 difficulty, increases by 4 for each level afterwards. - Blocks are destroyed when four of the same color line up. 4. The user 'wins' when all of the blocks in the current level are destroyed and moves onto the next difficulty level. - There will be 20 stages in all making a max of 80 blocks. 5. If a pair of Mana collides with anything immediately upon being introduced, the user loses. 6. The user will be able to manually configure the rate of descent before the game begins between SLOW, MID, and FAST. --------------- Mana: - Mana movement is controlled by the arrows, rotated with ctrl and alt. - Has two elemental properties at random that may be the same. - Four of a same color in a row clears all objects of that color. - If a portion of the Group is destroyed, the rest will become single instances of the coresponding mana and fall straight down. Blocks: - Blocks do not move and remain stationary. - Blocks are cleared along with the Mana.[/spoiler] Source Code: [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()[/code]
  8. Not sure if any one was following this post, but after three days of staring at my screen, I finally found a solution to the problem. I wanted to modify the original Engine as little as possible, but I found it impossible to achieve the results I was looking for without it. Essentially, I added another variable cumGrav to track the cumulative effects of gravity during each frame. If a sprite does not check for gravity, it will have no effect. I guess now that I've figured that out, I do have a more general question in regards to Engines: Is it normal to have to tinker with engine code to get something to work properly? Was the engine I was working with just extremely narrow in focus and literally made it impossible to properly code my games with it alone? Am I missing some trick of the trade that gets an engine to do what you want it to when the code in the engine does not? Finally, are all engines this frustrating to work with compared to working without, or will the more popular engines make coding easier in every regard? Thank you for any who spent some time pondering my coding dilemma before I found the answer.
  9. After sleeping on it, and looking at it again, I think I've found what the problem with the program is. Mainly, the SuperSprite's update() method contains both __calcVector() and __calcPosition(). In the original program, __calcVector() is only called once at the initialization of the fire() function, while __calcPosition() is called every frame. In this program, both are called every frame making any changes to dy irrelevant as it gets over written when __calcVector() is called again in the next frame. My new question is, since they're both private functions in update(), is there no way to over write them, meaning the game is impossible to program with this engine, or is there some technique I do not know yet that might help me get the effect I'm looking for?
  10. I'm trying to familiarize myself with writing code utilizing an engine, so I thought I would recreate a simple game I made before with a very basic game engine. It all works well except for one flaw... this version does not take gravity into account like my original version does! I've even pretty much copy/pasted the block of code that controls that part of the program, leading me to believe there is something that I am sorely missing. I've spent 2 hours so far trying to jury rig the code in every possible way I can think of, but none of it will work. If any one can look over the following code and let me know where I may have gone wrong, I would appreciate it. (Also, not sure why indentation isn't working in some areas when it is clearly indented in the box I'm typing this in.) [b]Original Code (Works as intended):[/b] [spoiler][code]class Turret(pygame.sprite.Sprite): def __init__(self, shell): pygame.sprite.Sprite.__init__(self) self.imageMaster = pygame.image.load("turret.gif") self.imageMaster = self.imageMaster.convert() self.rect = self.imageMaster.get_rect() self.rect.center = (320, 240) self.turnRate = 10 self.dir = 0 self.shell = shell self.power = 5 def update(self): self.checkKeys() self.rotate() def checkKeys(self): keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: self.dir += self.turnRate if self.dir > 360: self.dir = self.turnRate if keys[pygame.K_RIGHT]: self.dir -= self.turnRate if self.dir < 0: self.dir = 360 - self.turnRate if keys[pygame.K_UP]: self.power += 1 if self.power > 20: self.power = 20 if keys[pygame.K_DOWN]: self.power -= 1 if self.power < 0: self.power = 0 if keys[pygame.K_SPACE]: self.shell.x = self.rect.centerx self.shell.y = self.rect.centery self.shell.speed = self.power self.shell.dir = self.dir self.shell.calcVector() def rotate(self): oldCenter = self.rect.center self.image = pygame.transform.rotate(self.imageMaster, self.dir) self.rect = self.image.get_rect() self.rect.center = oldCenter class Shell(pygame.sprite.Sprite): def __init__(self, screen): pygame.sprite.Sprite.__init__(self) self.screen = screen self.image = pygame.Surface((10, 10)) self.image.fill((0xff, 0xff, 0xff)) self.image.set_colorkey((0xff, 0xff, 0xff)) pygame.draw.circle(self.image, (0, 0, 0), (5, 5), 5) self.image = pygame.transform.scale(self.image, (5, 5)) self.rect = self.image.get_rect() self.rect.center = (-100, -100) self.speed = 0 self.dir = 0 self.gravity = .5 self.dx = 0 self.dy = 0 self.reset() def update(self): self.calcPos() self.checkBounds() self.rect.center = (self.x, self.y) def calcVector(self): radians = self.dir * math.pi / 180 self.dx = self.speed * math.cos(radians) self.dy = self.speed * math.sin(radians) self.dy *= -1 def calcPos(self): self.x += self.dx self.y += self.dy self.dy += self.gravity def checkBounds(self): screen = self.screen if self.x > screen.get_width(): self.reset() if self.x < 0: self.reset() if self.y > screen.get_height(): self.reset() if self.y < 0: self.reset() def reset(self): self.x = -100 self.y = -100 self.speed = 0[/code][/spoiler] [b]With Game Engine (No effect of gravity on the shell): [/b][spoiler][code]class Turret(gameEngine.SuperSprite): def __init__(self, scene): gameEngine.SuperSprite.__init__(self, scene) self.setImage("turret.gif") self.setPosition((320, 240)) self.power = 5 def checkEvents(self): self.checkKeys() def checkKeys(self): keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: self.turnBy(10) if keys[pygame.K_RIGHT]: self.turnBy(-10) if keys[pygame.K_UP]: self.power += 1 if self.power > 20: self.power = 20 if keys[pygame.K_DOWN]: self.power -= 1 if self.power < 0: self.power = 0 if keys[pygame.K_SPACE]: self.scene.shell.fire() class Shell(gameEngine.SuperSprite): def __init__(self, scene): gameEngine.SuperSprite.__init__(self, scene) self.setImage("bullet.gif") self.imageMaster = pygame.transform.scale(self.imageMaster, (5, 5)) self.setBoundAction(self.HIDE) self.setSpeedLimits(20, 0) self.setGravity(.5) self.reset() def fire(self): self.setPosition((self.scene.turret.x, self.scene.turret.y)) self.setAngle(self.scene.turret.rotation) self.setSpeed(self.scene.turret.power) def reset(self): self.setPosition((-100, -100)) self.setSpeed(0)[/code][/spoiler] [b]Game Engine Code for SuperSprites: [/b][spoiler][code]class BasicSprite(pygame.sprite.Sprite): """ use this sprite when you want to directly control the sprite with dx and dy or want to extend in another direction than DirSprite """ def __init__(self, scene): pygame.sprite.Sprite.__init__(self) self.screen = scene.screen self.image = pygame.Surface((25, 25)) self.image.fill((255, 0, 0)) self.rect = self.image.get_rect() self.x = 100 self.y = 100 self.dx = 0 self.dy = 0 def update(self): self.x += self.dx self.y += self.dy self.checkBounds() self.rect.center = (self.x, self.y) def checkBounds(self): scrWidth = self.screen.get_width() scrHeight = self.screen.get_height() if self.x > scrWidth: self.x = 0 if self.x < 0: self.x = scrWidth if self.y > scrHeight: self.y = 0 if self.y < 0: self.y = scrHeight class SuperSprite(pygame.sprite.Sprite): """ An enhanced Sprite class expects a gameEngine.Scene class as its one parameter Use methods to change image, direction, speed Will automatically travel in direction and speed indicated Automatically rotates to point in indicated direction Five kinds of boundary collision """ def __init__(self, scene): pygame.sprite.Sprite.__init__(self) self.scene = scene self.screen = scene.screen #create constants self.WRAP = 0 self.BOUNCE = 1 self.STOP = 2 self.HIDE = 3 self.CONTINUE = 4 #create a default text image as a placeholder #This will usually be changed by a setImage call self.font = pygame.font.Font("freesansbold.ttf", 30) self.imageMaster = self.font.render(">sprite>", True, (0, 0,0), (0xFF, 0xFF, 0xFF)) self.image = self.imageMaster self.rect = self.image.get_rect() #create properties #most will be changed through method calls self.x = 200 self.y = 200 self.dx = 0 self.dy = 0 self.dir = 0 self.rotation = 0 self.speed = 0 self.gravity = 0 self.maxSpeed = 10 self.minSpeed = -3 self.boundAction = self.WRAP self.pressed = False self.oldCenter = (100, 100) def update(self): self.oldCenter = self.rect.center self.checkEvents() self.__rotate() self.__calcVector() self.__calcPosition() self.checkBounds() self.rect.center = (self.x, self.y) def checkEvents(self): """ overwrite this method to add your own event code """ pass def __rotate(self): """ PRIVATE METHOD change visual orientation based on rotation property. automatically called in update. change rotation property directly or with rotateBy(), setAngle() methods """ oldCenter = self.rect.center self.oldCenter = oldCenter self.image = pygame.transform.rotate(self.imageMaster, self.rotation) self.rect = self.image.get_rect() self.rect.center = oldCenter def __calcVector(self): """ calculates dx and dy based on speed, dir automatically called in update() """ theta = self.dir / 180.0 * math.pi self.dx = math.cos(theta) * self.speed self.dy = math.sin(theta) * self.speed self.dy *= -1 def __calcPosition(self): """ calculates the sprites position adding dx and dy to x and y. automatically called in update() """ self.x += self.dx self.y += self.dy self.dy += self.gravity def checkBounds(self): """ checks boundary and acts based on self.BoundAction. WRAP: wrap around screen (default) BOUNCE: bounce off screen STOP: stop at edge of screen HIDE: move off stage and wait CONTINUE: keep going at present course and speed automatically called by update() """ scrWidth = self.screen.get_width() scrHeight = self.screen.get_height() #create variables to simplify checking offRight = offLeft = offTop = offBottom = offScreen = False if self.x > scrWidth: offRight = True if self.x < 0: offLeft = True if self.y > scrHeight: offBottom = True if self.y < 0: offTop = True if offRight or offLeft or offTop or offBottom: offScreen = True if self.boundAction == self.WRAP: if offRight: self.x = 0 if offLeft: self.x = scrWidth if offBottom: self.y = 0 if offTop: self.y = scrHeight elif self.boundAction == self.BOUNCE: if offLeft or offRight: self.dx *= -1 if offTop or offBottom: self.dy *= -1 self.updateVector() self.rotation = self.dir elif self.boundAction == self.STOP: if offScreen: self.speed = 0 elif self.boundAction == self.HIDE: if offScreen: self.speed = 0 self.setPosition((-1000, -1000)) elif self.boundAction == self.CONTINUE: pass else: # assume it's CONTINUE - keep going forever pass def setSpeed(self, speed): """ immediately sets the objects speed to the given value. """ self.speed = speed def setGravity(self, amount): self.gravity = amount def speedUp(self, amount): """ changes speed by the given amount Use a negative value to slow down """ self.speed += amount if self.speed < self.minSpeed: self.speed = self.minSpeed if self.speed > self.maxSpeed: self.speed = self.maxSpeed def setAngle(self, dir): """ sets both the direction of motion and visual rotation to the given angle If you want to set one or the other, set them directly. Angle measured in degrees """ self.dir = dir self.rotation = dir def turnBy (self, amt): """ turn by given number of degrees. Changes both motion and visual rotation. Positive is counter-clockwise, negative is clockwise """ self.dir += amt if self.dir > 360: self.dir = amt if self.dir < 0: self.dir = 360 - amt self.rotation = self.dir def rotateBy(self, amt): """ change visual orientation by given number of degrees. Does not change direction of travel. """ self.rotation += amt if self.rotation > 360: self.rotation = amt if self.rotation < 0: self.rotation = 360 - amt def setImage (self, image): """ loads the given file name as the master image default setting should be facing east. Image will be rotated automatically """ self.imageMaster = pygame.image.load(image) self.imageMaster = self.imageMaster.convert() def setDX(self, dx): """ changes dx value and updates vector """ self.dx = dx self.updateVector() def addDX(self, amt): """ adds amt to dx, updates vector """ self.dx += amt self.updateVector() def setDY(self, dy): """ changes dy value and updates vector """ self.dy = dy self.updateVector() def addDY(self, amt): """ adds amt to dy and updates vector """ self.dy += amt self.updateVector() def setComponents(self, components): """ expects (dx, dy) for components change speed and angle according to dx, dy values """ (self.dx, self.dy) = components self.updateVector() def setBoundAction (self, action): """ sets action for boundary. Values are self.WRAP (wrap around edge - default) self.BOUNCE (bounce off screen changing direction) self.STOP (stop at edge of screen) self.HIDE (move off-stage and stop) self.CONTINUE (move on forever) Any other value allows the sprite to move on forever """ self.boundAction = action def setPosition (self, position): """ place the sprite directly at the given position expects an (x, y) tuple """ (self.x, self.y) = position def moveBy (self, vector): """ move the sprite by the (dx, dy) values in vector automatically calls checkBounds. Doesn't change speed or angle settings. """ (dx, dy) = vector self.x += dx self.y += dy self.__checkBounds() def forward(self, amt): """ move amt pixels in the current direction of travel """ #calculate dx dy based on current direction radians = self.dir * math.pi / 180 dx = amt * math.cos(radians) dy = amt * math.sin(radians) * -1 self.x += dx self.y += dy def addForce(self, amt, angle): """ apply amt of thrust in angle. change speed and dir accordingly add a force straight down to simulate gravity in rotation direction to simulate spacecraft thrust in dir direction to accelerate forward at an angle for retro-rockets, etc. """ #calculate dx dy based on angle radians = angle * math.pi / 180 dx = amt * math.cos(radians) dy = amt * math.sin(radians) * -1 self.dx += dx self.dy += dy self.updateVector() def updateVector(self): #calculate new speed and angle based on dx, dy #call this any time you change dx or dy self.speed = math.sqrt((self.dx * self.dx) + (self.dy * self.dy)) dy = self.dy * -1 dx = self.dx radians = math.atan2(dy, dx) self.dir = radians / math.pi * 180 def setSpeedLimits(self, max, min): """ determines maximum and minimum speeds you will allow through speedUp() method. You can still directly set any speed you want with setSpeed() Default values: max: 10 min: -3 """ self.maxSpeed = max self.minSpeed = min def dataTrace(self): """ utility method for debugging print major properties extend to add your own properties """ print "x: %d, y: %d, speed: %.2f, dir: %.f, dx: %.2f, dy: %.2f" % \ (self.x, self.y, self.speed, self.dir, self.dx, self.dy) def mouseDown(self): """ boolean function. Returns True if the mouse is clicked over the sprite, False otherwise """ self.pressed = False if pygame.mouse.get_pressed() == (1, 0, 0): if self.rect.collidepoint(pygame.mouse.get_pos()): self.pressed = True return self.pressed def clicked(self): """ Boolean function. Returns True only if mouse is pressed and released over sprite """ released = False if self.pressed: if pygame.mouse.get_pressed() == (0, 0, 0): if self.rect.collidepoint(pygame.mouse.get_pos()): released = True return released def collidesWith(self, target): """ boolean function. Returns True if the sprite is currently colliding with the target sprite, False otherwise """ collision = False if self.rect.colliderect(target.rect): collision = True return collision def collidesGroup(self, target): """ wrapper for pygame.sprite.spritecollideany() function simplifies checking sprite - group collisions returns result of collision check (sprite from group that was hit or None) """ collision = pygame.sprite.spritecollideany(self, target) return collision def distanceTo(self, point): """ returns distance to any point in pixels can be used in circular collision detection """ (pointx, pointy) = point dx = self.x - pointx dy = self.y - pointy dist = math.sqrt((dx * dx) + (dy * dy)) return dist def dirTo(self, point): """ returns direction (in degrees) to a point """ (pointx, pointy) = point dx = self.x - pointx dy = self.y - pointy dy *= -1 radians = math.atan2(dy, dx) dir = radians * 180 / math.pi dir += 180 return dir def drawTrace(self, color=(0x00, 0x00, 0x00)): """ traces a line between previous position and current position of object """ pygame.draw.line(self.scene.background, color, self.oldCenter, self.rect.center, 3) self.screen.blit(self.scene.background, (0, 0))[/code][/spoiler] Just in case the error is not in any of that code provided, here is the entire source code for all three programs. [b]Old Program (Complete): [/b][spoiler][code]import pygame, math, random pygame.init() class Turret(pygame.sprite.Sprite): def __init__(self, shell): pygame.sprite.Sprite.__init__(self) self.imageMaster = pygame.image.load("turret.gif") self.imageMaster = self.imageMaster.convert() self.rect = self.imageMaster.get_rect() self.rect.center = (320, 240) self.turnRate = 10 self.dir = 0 self.shell = shell self.power = 5 def update(self): self.checkKeys() self.rotate() def checkKeys(self): keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: self.dir += self.turnRate if self.dir > 360: self.dir = self.turnRate if keys[pygame.K_RIGHT]: self.dir -= self.turnRate if self.dir < 0: self.dir = 360 - self.turnRate if keys[pygame.K_UP]: self.power += 1 if self.power > 20: self.power = 20 if keys[pygame.K_DOWN]: self.power -= 1 if self.power < 0: self.power = 0 if keys[pygame.K_SPACE]: self.shell.x = self.rect.centerx self.shell.y = self.rect.centery self.shell.speed = self.power self.shell.dir = self.dir self.shell.calcVector() def rotate(self): oldCenter = self.rect.center self.image = pygame.transform.rotate(self.imageMaster, self.dir) self.rect = self.image.get_rect() self.rect.center = oldCenter class Label(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) self.font = pygame.font.SysFont("None", 30) self.text = "" self.center = (320, 240) def update(self): self.image = self.font.render(self.text, 1, (0, 0, 0,)) self.rect = self.image.get_rect() self.rect.center = self.center class Shell(pygame.sprite.Sprite): def __init__(self, screen): pygame.sprite.Sprite.__init__(self) self.screen = screen self.image = pygame.Surface((10, 10)) self.image.fill((0xff, 0xff, 0xff)) self.image.set_colorkey((0xff, 0xff, 0xff)) pygame.draw.circle(self.image, (0, 0, 0), (5, 5), 5) self.image = pygame.transform.scale(self.image, (5, 5)) self.rect = self.image.get_rect() self.rect.center = (-100, -100) self.speed = 0 self.dir = 0 self.gravity = .5 self.dx = 0 self.dy = 0 self.reset() def update(self): self.calcPos() self.checkBounds() self.rect.center = (self.x, self.y) def calcVector(self): radians = self.dir * math.pi / 180 self.dx = self.speed * math.cos(radians) self.dy = self.speed * math.sin(radians) self.dy *= -1 def calcPos(self): self.x += self.dx self.y += self.dy self.dy += self.gravity def checkBounds(self): screen = self.screen if self.x > screen.get_width(): self.reset() if self.x < 0: self.reset() if self.y > screen.get_height(): self.reset() if self.y < 0: self.reset() def reset(self): self.x = -100 self.y = -100 self.speed = 0 class Target(pygame.sprite.Sprite): def __init__(self, screen): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load("target.gif") self.image = self.image.convert() self.rect = self.image.get_rect() self.screen = screen self.reset() def reset(self): screen = self.screen self.rect.centery = random.randrange(0, screen.get_height()) self.rect.centerx = random.randrange(0, screen.get_width()) def main(): screen = pygame.display.set_mode((640, 480)) pygame.display.set_caption ("Rotating Turret") background = pygame.Surface(screen.get_size()) background.fill((0, 250, 0)) screen.blit(background, (0, 0)) shell = Shell(screen) turret = Turret(shell) lblOutput = Label() lblOutput.center = (110, 20) target = Target(screen) allSprites = pygame.sprite.OrderedUpdates(shell, turret, lblOutput, target) clock = pygame.time.Clock() keepGoing = True while keepGoing: clock.tick(30) for event in pygame.event.get(): if event.type == pygame.QUIT: keepGoing = False if shell.rect.colliderect(target.rect): target.reset() shell.reset() lblOutput.text = "Angle: %d Power: %d" % (turret.dir, turret.power) allSprites.clear(screen, background) allSprites.update() allSprites.draw(screen) pygame.display.flip() if __name__ == "__main__": main()[/code][/spoiler] [b]New Program (Complete): [/b][spoiler][code]import pygame, random, gameEngine class Turret(gameEngine.SuperSprite): def __init__(self, scene): gameEngine.SuperSprite.__init__(self, scene) self.setImage("turret.gif") self.setPosition((320, 240)) self.power = 5 def checkEvents(self): self.checkKeys() def checkKeys(self): keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: self.turnBy(10) if keys[pygame.K_RIGHT]: self.turnBy(-10) if keys[pygame.K_UP]: self.power += 1 if self.power > 20: self.power = 20 if keys[pygame.K_DOWN]: self.power -= 1 if self.power < 0: self.power = 0 if keys[pygame.K_SPACE]: self.scene.shell.fire() class Shell(gameEngine.SuperSprite): def __init__(self, scene): gameEngine.SuperSprite.__init__(self, scene) self.setImage("bullet.gif") self.imageMaster = pygame.transform.scale(self.imageMaster, (5, 5)) self.setBoundAction(self.HIDE) self.setSpeedLimits(20, 0) self.reset() def fire(self): self.setPosition((self.scene.turret.x, self.scene.turret.y)) self.setAngle(self.scene.turret.rotation) self.setSpeed(self.scene.turret.power) def reset(self): self.setPosition((-100, -100)) self.setSpeed(0) class Target(gameEngine.SuperSprite): def __init__(self, scene): gameEngine.SuperSprite.__init__(self, scene) self.setImage("target.gif") self.reset() def reset(self): x = random.randint(0, self.screen.get_width()) y = random.randint(0, self.screen.get_height()) self.setPosition((x, y)) class Game(gameEngine.Scene): def __init__(self): gameEngine.Scene.__init__(self) self.setCaption("Rotating Turret") self.turret = Turret(self) self.shell = Shell(self) self.target = Target(self) self.gravity = .5 self.lblOutput = gameEngine.Label() self.lblOutput.center = (110, 20) self.lblOutput.size = (225, 20) self.sprites = [self.lblOutput, self.shell, self.turret, self.target] self.background.fill((0, 245, 0)) def update(self): self.updateInfo() self.shell.dy += self.gravity if self.shell.collidesWith(self.target): self.target.reset() self.shell.reset() def updateInfo(self): info = "Angle: %d Power: %d" % (self.turret.dir, self.turret.power) self.lblOutput.text = info def main(): game = Game() game.start() if __name__ == "__main__": main()[/code][/spoiler] [b]Game Engine (Complete): [/b][spoiler][code]import pygame, math pygame.init() class BasicSprite(pygame.sprite.Sprite): """ use this sprite when you want to directly control the sprite with dx and dy or want to extend in another direction than DirSprite """ def __init__(self, scene): pygame.sprite.Sprite.__init__(self) self.screen = scene.screen self.image = pygame.Surface((25, 25)) self.image.fill((255, 0, 0)) self.rect = self.image.get_rect() self.x = 100 self.y = 100 self.dx = 0 self.dy = 0 def update(self): self.x += self.dx self.y += self.dy self.checkBounds() self.rect.center = (self.x, self.y) def checkBounds(self): scrWidth = self.screen.get_width() scrHeight = self.screen.get_height() if self.x > scrWidth: self.x = 0 if self.x < 0: self.x = scrWidth if self.y > scrHeight: self.y = 0 if self.y < 0: self.y = scrHeight class SuperSprite(pygame.sprite.Sprite): """ An enhanced Sprite class expects a gameEngine.Scene class as its one parameter Use methods to change image, direction, speed Will automatically travel in direction and speed indicated Automatically rotates to point in indicated direction Five kinds of boundary collision """ def __init__(self, scene): pygame.sprite.Sprite.__init__(self) self.scene = scene self.screen = scene.screen #create constants self.WRAP = 0 self.BOUNCE = 1 self.STOP = 2 self.HIDE = 3 self.CONTINUE = 4 #create a default text image as a placeholder #This will usually be changed by a setImage call self.font = pygame.font.Font("freesansbold.ttf", 30) self.imageMaster = self.font.render(">sprite>", True, (0, 0,0), (0xFF, 0xFF, 0xFF)) self.image = self.imageMaster self.rect = self.image.get_rect() #create properties #most will be changed through method calls self.x = 200 self.y = 200 self.dx = 0 self.dy = 0 self.dir = 0 self.rotation = 0 self.speed = 0 self.gravity = 0 self.maxSpeed = 10 self.minSpeed = -3 self.boundAction = self.WRAP self.pressed = False self.oldCenter = (100, 100) def update(self): self.oldCenter = self.rect.center self.checkEvents() self.__rotate() self.__calcVector() self.__calcPosition() self.checkBounds() self.rect.center = (self.x, self.y) def checkEvents(self): """ overwrite this method to add your own event code """ pass def __rotate(self): """ PRIVATE METHOD change visual orientation based on rotation property. automatically called in update. change rotation property directly or with rotateBy(), setAngle() methods """ oldCenter = self.rect.center self.oldCenter = oldCenter self.image = pygame.transform.rotate(self.imageMaster, self.rotation) self.rect = self.image.get_rect() self.rect.center = oldCenter def __calcVector(self): """ calculates dx and dy based on speed, dir automatically called in update() """ theta = self.dir / 180.0 * math.pi self.dx = math.cos(theta) * self.speed self.dy = math.sin(theta) * self.speed self.dy *= -1 def __calcPosition(self): """ calculates the sprites position adding dx and dy to x and y. automatically called in update() """ self.x += self.dx self.y += self.dy self.dy += self.gravity def checkBounds(self): """ checks boundary and acts based on self.BoundAction. WRAP: wrap around screen (default) BOUNCE: bounce off screen STOP: stop at edge of screen HIDE: move off stage and wait CONTINUE: keep going at present course and speed automatically called by update() """ scrWidth = self.screen.get_width() scrHeight = self.screen.get_height() #create variables to simplify checking offRight = offLeft = offTop = offBottom = offScreen = False if self.x > scrWidth: offRight = True if self.x < 0: offLeft = True if self.y > scrHeight: offBottom = True if self.y < 0: offTop = True if offRight or offLeft or offTop or offBottom: offScreen = True if self.boundAction == self.WRAP: if offRight: self.x = 0 if offLeft: self.x = scrWidth if offBottom: self.y = 0 if offTop: self.y = scrHeight elif self.boundAction == self.BOUNCE: if offLeft or offRight: self.dx *= -1 if offTop or offBottom: self.dy *= -1 self.updateVector() self.rotation = self.dir elif self.boundAction == self.STOP: if offScreen: self.speed = 0 elif self.boundAction == self.HIDE: if offScreen: self.speed = 0 self.setPosition((-1000, -1000)) elif self.boundAction == self.CONTINUE: pass else: # assume it's CONTINUE - keep going forever pass def setSpeed(self, speed): """ immediately sets the objects speed to the given value. """ self.speed = speed def setGravity(self, amount): self.gravity = amount def speedUp(self, amount): """ changes speed by the given amount Use a negative value to slow down """ self.speed += amount if self.speed < self.minSpeed: self.speed = self.minSpeed if self.speed > self.maxSpeed: self.speed = self.maxSpeed def setAngle(self, dir): """ sets both the direction of motion and visual rotation to the given angle If you want to set one or the other, set them directly. Angle measured in degrees """ self.dir = dir self.rotation = dir def turnBy (self, amt): """ turn by given number of degrees. Changes both motion and visual rotation. Positive is counter-clockwise, negative is clockwise """ self.dir += amt if self.dir > 360: self.dir = amt if self.dir < 0: self.dir = 360 - amt self.rotation = self.dir def rotateBy(self, amt): """ change visual orientation by given number of degrees. Does not change direction of travel. """ self.rotation += amt if self.rotation > 360: self.rotation = amt if self.rotation < 0: self.rotation = 360 - amt def setImage (self, image): """ loads the given file name as the master image default setting should be facing east. Image will be rotated automatically """ self.imageMaster = pygame.image.load(image) self.imageMaster = self.imageMaster.convert() def setDX(self, dx): """ changes dx value and updates vector """ self.dx = dx self.updateVector() def addDX(self, amt): """ adds amt to dx, updates vector """ self.dx += amt self.updateVector() def setDY(self, dy): """ changes dy value and updates vector """ self.dy = dy self.updateVector() def addDY(self, amt): """ adds amt to dy and updates vector """ self.dy += amt self.updateVector() def setComponents(self, components): """ expects (dx, dy) for components change speed and angle according to dx, dy values """ (self.dx, self.dy) = components self.updateVector() def setBoundAction (self, action): """ sets action for boundary. Values are self.WRAP (wrap around edge - default) self.BOUNCE (bounce off screen changing direction) self.STOP (stop at edge of screen) self.HIDE (move off-stage and stop) self.CONTINUE (move on forever) Any other value allows the sprite to move on forever """ self.boundAction = action def setPosition (self, position): """ place the sprite directly at the given position expects an (x, y) tuple """ (self.x, self.y) = position def moveBy (self, vector): """ move the sprite by the (dx, dy) values in vector automatically calls checkBounds. Doesn't change speed or angle settings. """ (dx, dy) = vector self.x += dx self.y += dy self.__checkBounds() def forward(self, amt): """ move amt pixels in the current direction of travel """ #calculate dx dy based on current direction radians = self.dir * math.pi / 180 dx = amt * math.cos(radians) dy = amt * math.sin(radians) * -1 self.x += dx self.y += dy def addForce(self, amt, angle): """ apply amt of thrust in angle. change speed and dir accordingly add a force straight down to simulate gravity in rotation direction to simulate spacecraft thrust in dir direction to accelerate forward at an angle for retro-rockets, etc. """ #calculate dx dy based on angle radians = angle * math.pi / 180 dx = amt * math.cos(radians) dy = amt * math.sin(radians) * -1 self.dx += dx self.dy += dy self.updateVector() def updateVector(self): #calculate new speed and angle based on dx, dy #call this any time you change dx or dy self.speed = math.sqrt((self.dx * self.dx) + (self.dy * self.dy)) dy = self.dy * -1 dx = self.dx radians = math.atan2(dy, dx) self.dir = radians / math.pi * 180 def setSpeedLimits(self, max, min): """ determines maximum and minimum speeds you will allow through speedUp() method. You can still directly set any speed you want with setSpeed() Default values: max: 10 min: -3 """ self.maxSpeed = max self.minSpeed = min def dataTrace(self): """ utility method for debugging print major properties extend to add your own properties """ print "x: %d, y: %d, speed: %.2f, dir: %.f, dx: %.2f, dy: %.2f" % \ (self.x, self.y, self.speed, self.dir, self.dx, self.dy) def mouseDown(self): """ boolean function. Returns True if the mouse is clicked over the sprite, False otherwise """ self.pressed = False if pygame.mouse.get_pressed() == (1, 0, 0): if self.rect.collidepoint(pygame.mouse.get_pos()): self.pressed = True return self.pressed def clicked(self): """ Boolean function. Returns True only if mouse is pressed and released over sprite """ released = False if self.pressed: if pygame.mouse.get_pressed() == (0, 0, 0): if self.rect.collidepoint(pygame.mouse.get_pos()): released = True return released def collidesWith(self, target): """ boolean function. Returns True if the sprite is currently colliding with the target sprite, False otherwise """ collision = False if self.rect.colliderect(target.rect): collision = True return collision def collidesGroup(self, target): """ wrapper for pygame.sprite.spritecollideany() function simplifies checking sprite - group collisions returns result of collision check (sprite from group that was hit or None) """ collision = pygame.sprite.spritecollideany(self, target) return collision def distanceTo(self, point): """ returns distance to any point in pixels can be used in circular collision detection """ (pointx, pointy) = point dx = self.x - pointx dy = self.y - pointy dist = math.sqrt((dx * dx) + (dy * dy)) return dist def dirTo(self, point): """ returns direction (in degrees) to a point """ (pointx, pointy) = point dx = self.x - pointx dy = self.y - pointy dy *= -1 radians = math.atan2(dy, dx) dir = radians * 180 / math.pi dir += 180 return dir def drawTrace(self, color=(0x00, 0x00, 0x00)): """ traces a line between previous position and current position of object """ pygame.draw.line(self.scene.background, color, self.oldCenter, self.rect.center, 3) self.screen.blit(self.scene.background, (0, 0)) class Scene(object): """ encapsulates the IDEA / ALTER framework properties: sprites - a list of sprite objects that forms the primary sprite group background - the background surface screen - the display screen it's generally best to add all sprites as attributes, so they can have access to each other if needed """ def __init__(self): """ initialize the game engine set up a sample sprite for testing """ pygame.init() self.screen = pygame.display.set_mode((640, 480)) self.background = pygame.Surface(self.screen.get_size()) self.background.fill((0, 0, 0)) self.sampleSprite = SuperSprite(self) self.sampleSprite.setSpeed(3) self.sampleSprite.setAngle(0) self.sampleSprite.boundAction = self.sampleSprite.WRAP self.sprites = [self.sampleSprite] self.groups = [] def start(self): """ sets up the sprite groups begins the main loop """ self.mainSprites = pygame.sprite.OrderedUpdates(self.sprites) self.groups.append(self.mainSprites) self.screen.blit(self.background, (0, 0)) self.clock = pygame.time.Clock() self.keepGoing = True while self.keepGoing: self.__mainLoop() def stop(self): """stops the loop""" self.keepGoing = False def __mainLoop(self): """ manage all the main events automatically called by start """ self.clock.tick(30) for event in pygame.event.get(): if event.type == pygame.QUIT: self.keepGoing = False self.doEvents(event) self.update() for group in self.groups: group.clear(self.screen, self.background) group.update() group.draw(self.screen) pygame.display.flip() def makeSpriteGroup(self, sprites): """ create a group called groupName containing all the sprites in the sprites list. This group will be added after the sprites group, and will automatically clear, update, and draw """ tempGroup = pygame.sprite.OrderedUpdates(sprites) return tempGroup def addGroup(self, group): """ adds a sprite group to the groups list for automatic processing """ self.groups.append(group) def doEvents(self, event): """ overwrite this method to add your own events. Works like normal event handling, passes event object """ pass def update(self): """ happens once per frame, after event parsing. Overwrite to add your own code, esp event handling that doesn't require event obj. (pygame.key.get_pressed, pygame.mouse.get_pos, etc) Also a great place for collision detection """ pass def setCaption(self, title): """ set's the scene's title text """ pygame.display.set_caption(title) class Label(pygame.sprite.Sprite): """ a basic label properties: font: font to use text: text to display fgColor: foreground color bgColor: background color center: position of label's center size: (width, height) of label """ def __init__(self, fontName = "freesansbold.ttf"): pygame.sprite.Sprite.__init__(self) self.font = pygame.font.Font(fontName, 20) self.text = "" self.fgColor = ((0x00, 0x00, 0x00)) self.bgColor = ((0xFF, 0xFF, 0xFF)) self.center = (100, 100) self.size = (150, 30) def update(self): self.image = pygame.Surface(self.size) self.image.fill(self.bgColor) fontSurface = self.font.render(self.text, True, self.fgColor, self.bgColor) #center the text xPos = (self.image.get_width() - fontSurface.get_width())/2 self.image.blit(fontSurface, (xPos, 0)) self.rect = self.image.get_rect() self.rect.center = self.center class Button(Label): """ a button based on the label same properties as label + active: True if user is clicking on sprite False if user is not currently clicking clicked: True when user releases mouse over a currently active button """ def __init__(self): Label.__init__(self) self.active = False self.clicked = False self.bgColor = (0xCC, 0xCC, 0xCC) def update(self): Label.update(self) self.clicked = False #check for mouse input if pygame.mouse.get_pressed() == (1, 0, 0): if self.rect.collidepoint(pygame.mouse.get_pos()): self.active = True #check for mouse release if self.active == True: if pygame.mouse.get_pressed() == (0, 0, 0): self.active = False if self.rect.collidepoint(pygame.mouse.get_pos()): self.clicked = True class Scroller(Button): """ like a button, but has a numeric value that can be decremented by clicking on left half and incremented by clicking on right half. new atributes: value: the scroller's numeric value minValue: minimum value maxValue: maximum value increment: How much is added or subtracted format: format of string interpolation """ def __init__(self): Button.__init__(self) self.minValue = 0 self.maxValue = 10 self.increment = 1 self.value = 5 self.format = "<< %.2f >>" def update(self): Button.update(self) if self.active: (mousex, mousey) = pygame.mouse.get_pos() if mousex < self.rect.centerx: self.value -= self.increment if self.value < self.minValue: self.value = self.minValue else: self.value += self.increment if self.value > self.maxValue: self.value = self.maxValue self.text = self.format % self.value class MultiLabel(pygame.sprite.Sprite): """ accepts a list of strings, creates a multi-line label to display text same properties as label except textLines is a list of strings. There is no text property. Set the size manually. Vertical size should be at least 30 pixels per line (with the default font) """ def __init__(self): pygame.sprite.Sprite.__init__(self) self.textLines = ["This", "is", "sample", "text"] self.font = pygame.font.Font("freesansbold.ttf", 20) self.fgColor = ((0x00, 0x00, 0x00)) self.bgColor = ((0xFF, 0xFF, 0xFF)) self.center = (100, 100) self.size = (150, 100) def update(self): self.image = pygame.Surface(self.size) self.image.fill(self.bgColor) numLines = len(self.textLines) vSize = self.image.get_height() / numLines for lineNum in range(numLines): currentLine = self.textLines[lineNum] fontSurface = self.font.render(currentLine, True, self.fgColor, self.bgColor) #center the text xPos = (self.image.get_width() - fontSurface.get_width())/2 yPos = lineNum * vSize self.image.blit(fontSurface, (xPos, yPos)) self.rect = self.image.get_rect() self.rect.center = self.center if __name__ == "__main__": # change this code to test various features of the engine # This code will not run when gameEngine is run as a module # (as it usually will be game = Scene() thing = SuperSprite(game) thing.setSpeed(5) thing.setBoundAction(thing.BOUNCE) thing.setAngle(230) game.sprites = [thing] game.start()[/code][/spoiler] Please also note, I did not program the Game Engine. I am using a sample Game Engine from the book I am currently teaching myself from. I know this is a lot to go through, and I appreciate any help I can receive! This is my first foray into programming with the assistance of an Engine, and I know that this knowledge will be pivotal in taking my understanding of programming to the next level.
  11. I got it to work! I'll detail what I did here so if any other clueless beginner stumbles upon these same errors and does a google search, they might be able to compile their game without any issue: Firstly, to fix the _view problem, I was forced to put the following line of code into my main program (not the setup.py program) in order to call the _view.pyd so that py2exe actually finds it: [code]import pygame._view[/code] That line of code has absolutely no effect on the program itself. Afterwards, I kept getting font errors despite making sure to include the font in the list of files. A brief search of the internet helped me to narrow down exactly which part of pygame's py2exe script was responsible for fixing the issue with the font, as well as the sound which was a problem I ran into afterwards. Simply copy/pasting the code from the script did not work, and instead thanks to some advice from the following blog: [url="http://thadeusb.com/weblog/2009/4/15/pygame_font_and_py2exe"]http://thadeusb.com/...font_and_py2exe[/url] I edited my setup.py script appropriately. (Please remember to import os in your setup.py script!) Here is the final setup.py program I wound up with: [code]from distutils.core import setup import py2exe, os origIsSystemDLL = py2exe.build_exe.isSystemDLL def isSystemDLL(pathname): if os.path.basename(pathname).lower() in ("sdl_ttf.dll", "libogg-0.dll"): return 0 return origIsSystemDLL(pathname) py2exe.build_exe.isSystemDLL = isSystemDLL setup(console = ["footBallHell.py"], author="XXXX", author_email="XXXX", data_files=[('.', ["attack.ogg", "enemy.gif", "Field.gif", "football.gif", "player.gif", "save.ogg", "tackle.ogg", "freesansbold.ttf"] )] )[/code]
  12. I'm a fellow new programmer, so keep in mind my advice is coming from another person navigating the same sea of choices and challenges you are but... Two years ago I thought I'd go full force and teach myself C++ to break into game programming despite all the nay-sayers. After about 3 months, my greatest accomplishment was a text based version of Blackjack and I hit a wall, giving up soon afterwards. Being the stubborn person I was, I picked up programming again about a month or so ago, but this time I decided to try something easier with Python. I learned everything I had learned from C++ in Python in about 3 days, and after 2 weeks of diving into Python I had created my first game, a simple top down shooter. This is also learning the language between a job and taking care of my daughter, so it's not like I had tons of time to devote to it. While Python does have a few limitations I took for granted while learning C++, I'm proud of my choice. What I would suggest for you is to take a moment, step back, and look at your progress. If you're still making progress, no matter how slow, keep at it. C++ is a very useful language to know no matter how frustrating it is to learn. If you ever find yourself hitting a wall, don't give up. Learn C# if that's what interests you. Learn another language. Learn, learn, learn, and you will be surprised at what you are able to do and the skills you have acquired. I do one day plan to go back to C++, but not until I can competently and reliably program in Python.
  13. Thank you both for your replies! I looked at pygame's py2exe script before, but truth be told, I'm a fledgling in the world of programming, and admittedly know very little about the world of windows and how it actually runs programs. Looking over the script, while I understood some of it, other parts looked completely foreign even with comments. I feel uncomfortable using code that I don't at least understand what each part is supposed to be doing, and a lot of that code contains things that either look like they would be superfluous to my needs, or references stuff that I have no clue whether it's an example or is something that is actually needed. (Such as wildcards. Never heard of them before.) I tried to find some more in depth documentation of that script, but I was unable to find any such thing. Knackebrod, I took a brief look at cx_freeze, and it seems that it's benefits include cross platform support. Your example setup.py was good, but I am still confused about some of the finer details of the script. At this point in time I'm not too worried about surface level changes such as including an icon or installer (Though I did appreciate it in the example so I now know how to do such things when I do put more effort into making a presentable program. I will be checking out NSIS in the future.) Right now I'm looking for a nitty gritty bare bones .exe that I can zip up, send to my friends, and have them delete the file after they're done playing around with it. One thing that I would like to add that I found in my search for an answer was that someone with a similar problem was told that they can explicitly specify modules to include on the py2exe command line. Unfortunately, all the experience I've ever had with the command line I've learned since installing py2exe a few nights ago and the breadth of my experience with it is getting py2exe to run. I'm very nervous about tinkering around in command line as I don't want to accidentally blow my computer up, but would any one know a way to include the _view.pyd file on that same command line so it (hopefully) compiles into the .exe correctly?
  14. My problem seems like a pretty simple issue, but I don't have any idea how to go about fixing this. I'll show the problem and list the steps I've taken so far in order to fix it. After creating a game using python 2.7, I tested the game and it worked flawlessly without any bugs. Deciding that I wanted to redistribute it to a few of my friends I looked up some info on what I would have to do and eventually found py2exe. After carefully following all of the directions and creating my .exe, it failed to run. Running it through command line I got the following errors: [spoiler]footBallHell.exe:1: RuntimeWarning: import display: No module named _view (ImportError: No module named _view) footBallHell.exe:1: RuntimeWarning: import draw: No module named _view (ImportError: No module named _view) footBallHell.exe:1: RuntimeWarning: import image: No module named _view (ImportError: No module named _view) footBallHell.exe:1: RuntimeWarning: import pixelcopy: No module named _view (ImportError: No module named _view) footBallHell.exe:1: RuntimeWarning: import transform: No module named _view (ImportError: No module named _view) Traceback (most recent call last): File "footBallHell.py", line 218, in <module> File "pygame\__init__.pyc", line 70, in __getattr__ NotImplementedError: display module not available (ImportError: No module named _view)[/spoiler] (Although I'm sure it's obvious, the name of my program is footBallHell.) So, clueless as to what to do next I searched up google and found this similar problem on the python forums: [url="http://www.python-forum.org/pythonforum/viewtopic.php?f=15&t=26719"]http://www.python-fo...hp?f=15&t=26719[/url] After reading that I dug around through the Python folder and went to: C:\Python27\Lib\site-packages\pygame and found a file listed as "_view.pyd" I believed that this was the file in question that was missing so I copied it into the dist folder hoping it would solve the problem. Unfortunately, it didn't. So, afterwards I went and added it into the directory with the rest of the relevant files as well as the setup.py program I used to create the executable so the program read as follows: [code]from distutils.core import setup import py2exe setup(console = ["footBallHell.py"], author="XXXX", author_email="XXXX", data_files=[('.', ["attack.ogg", "enemy.gif", "Field.gif", "football.gif", "player.gif", "save.ogg", "tackle.ogg", "freesansbold.ttf", "_view.pyd"] )] )[/code] After running the setup.py program, it did include the _view.pyd file in the dist folder, but still would not run. So, I believe I either have the wrong file or there is something else I need to do in order to get the program to run. What I am asking is if there is any one out there that might know how to fix this issue, or, at worst, inform me of another way I can create an executable for Windows out of my python programs that I can distribute to my friends.
  15. Ugh... I knew it was going to be something that simple. For what ever reason when I was doing the program last night, I figured just running the function would be fine and never thought that I would have to actually declare 'direction' as it would automatically be imported from the function. Now I see that it only returns the value and that value needs to be assigned. Also, that any time start() is called, whether by itself or listed in an assignment, it will be run, which explains why sometimes when tinkering with this I would run into an infinite start() loop. Thank you very much! Now that I understand how functions work I can continue on with some more complex stuff.