Re: [pygame] how to bind surface rects without subsurface (need help with bug)
Makes so much more sense now...and that worked great. Thanks :) /me does a little happy python dance On Tue, Mar 10, 2009 at 12:34 PM, Patrick Mullen wrote: > Yep, changing the layer order is just a quick fix, not a real > solution. You can keep the layer order you had before, and add a > move_layers function to the map. Give the player a reference to the > map instead of the two layers, and call move_layers in the spots you > are setting the background.move and foreground.move. Map.move_layers > would look something like this: > > def move_layers(self, amount): >for layer in [self.background, self.foreground]: >layer.dirty = 1 >layer.rect.move_ip(amount) > > Actually, it might be even better to just make move a function instead > of an attribute on TileLayer. You will have to change less code (but > will still have the ugly bg/fg references in player). > > class TileLayer(pygame.sprite.DirtySprite): >def __init__(self, screen, layer, w, numx, h, numy): >self.screen = screen >pygame.sprite.DirtySprite.__init__(self) >if layer == 'fg': >self.image = pygame.Surface((w*numx,h*numy), > SRCALPHA, 32).convert_alpha() >else: >self.image = > pygame.Surface((w*numx,h*numy)).convert() >self.rect = self.image.get_rect() > >def move(self): >self.dirty = 1 >self.rect.move_ip(self.move) > > Then in player you would say: > self.background.move([self.movement, 0]) > self.foreground.move([self.movement, 0]) > > etc. Instead of assigning to those values. > > The real problem is that you are delaying an action until the update > functions when it is really (in this case) an in-place action. >
Re: [pygame] how to bind surface rects without subsurface (need help with bug)
Yep, changing the layer order is just a quick fix, not a real solution. You can keep the layer order you had before, and add a move_layers function to the map. Give the player a reference to the map instead of the two layers, and call move_layers in the spots you are setting the background.move and foreground.move. Map.move_layers would look something like this: def move_layers(self, amount): for layer in [self.background, self.foreground]: layer.dirty = 1 layer.rect.move_ip(amount) Actually, it might be even better to just make move a function instead of an attribute on TileLayer. You will have to change less code (but will still have the ugly bg/fg references in player). class TileLayer(pygame.sprite.DirtySprite): def __init__(self, screen, layer, w, numx, h, numy): self.screen = screen pygame.sprite.DirtySprite.__init__(self) if layer == 'fg': self.image = pygame.Surface((w*numx,h*numy), SRCALPHA, 32).convert_alpha() else: self.image = pygame.Surface((w*numx,h*numy)).convert() self.rect = self.image.get_rect() def move(self): self.dirty = 1 self.rect.move_ip(self.move) Then in player you would say: self.background.move([self.movement, 0]) self.foreground.move([self.movement, 0]) etc. Instead of assigning to those values. The real problem is that you are delaying an action until the update functions when it is really (in this case) an in-place action.
Re: [pygame] how to bind surface rects without subsurface (need help with bug)
Thanks Patrick, your feedback is greatly appreciated. I'm surprised you took the time to _really_ get to know my code. I know it's a big mess right now. I cleaned it up a lot the last few weeks, and I even had functionality to find the player offscreen and pre-scroll before the map loads, but I took that and a few other buggy pieces out as I am trying to iron out as much as I can at this point before moving forward. I didn't really know what I was doing when I started tis project, and just sort of ran with it ever since. By the way, I have worked on this project everyday since 01.08. Over a year, and I can't believe how much I learned. With that said, after reading your explanations and suggestions, I have a much better idea of how my game works, and how it could work so much better with half of that unneeded code. About your solution; the reason I have 3 layers, is so that they will draw in the order bg, player, fg. If you think about it, the foreground shouldnt have anything in front of it...except maybe another foreground with translucent scrolling clouds or something similar. Your solution did fix the problem, and it was what I asked for, but the player can walk through the huge tree trunks...nothing obscures him. I know you offered a solution of using a single pointer instead of 2 surfaces, which would even be more efficient, but I'd like to clean the code up as is right now, so another guy can dive in and help easier. Thanks for the criticism, Mike Sure. I love looking at other peoples code for problems. (Honestly, > it's a lot more fun than trying to find problems in code I wrote) > > This was hard, because while your code is not bad per say, there is a > lot of indirection, and much overengineering going on. There are too > many strong connections between classes (like the player having to > know about the background and the foreground), and this coupling makes > it very inflexible. > > In this case, the problem is simply a matter of ordering. The > background is updated, then the player, then the foreground. When you > start scrolling the screen (from the player update), the background > has already run it's update for that frame, while the foreground gets > to run its update with the move command. So it is a frame ahead of > the background. > > In scene.py, if you change the order that objects are updated: > >self.render.add(self.map.background) >self.render.add(self.map.foreground) >self.render.add(self.player) > > Then the player will set up the scrolling for the next frame, which > fixes the problem. A better way to do cameras, instead of having it > happening in the player movement function, is to have a separate > camera update that scrolls the right direction at a maximum speed > until whatever it is focused on is within some region of the screen. > That way if you start the player offscreen, the camera will still be > able to find him. Also, for cutscenes, you can have the camera focus > on a different character than the player fairly easily. > > Another thing that bugged me: It seems weird that you have limited > yourself to only two layers in the code, when any number of layers > would actually be easier. A map.move() function, which moves all of > its layers by a set amount, means one less line all of the places you > have to write "background.move... foreground.move", and would also > solve the above problem (because the movement happens instantly > instead of waiting for some update). And in the map, instead of > having background, and foreground, you could simply have layers[]. In > the future, when you want to add a paralax treeshadow layer to display > on top of the player and npc's, you will be hitting yourself at all of > the places you will have to add the new layer. > > Good luck with the game, the sprites/tiles look really nice, and the > code isn't all bad :) >
Re: [pygame] how to bind surface rects without subsurface (need help with bug)
On Mon, Mar 9, 2009 at 10:31 PM, Michael Fiano wrote: > I realize my code isn't the best code there is, but it's also my first > programming project and I've been teaching myself all sorts of things > as I go. But, could someone please take a look at code and > tell me why the foreground isn't aligned when scrolling? To reproduce, > you'll have to move the player toward the right side of the screen > until it scrolls the map, and while it does pay attention to the huge > trees and other foreground objects such as the tall grass. Sure. I love looking at other peoples code for problems. (Honestly, it's a lot more fun than trying to find problems in code I wrote) This was hard, because while your code is not bad per say, there is a lot of indirection, and much overengineering going on. There are too many strong connections between classes (like the player having to know about the background and the foreground), and this coupling makes it very inflexible. In this case, the problem is simply a matter of ordering. The background is updated, then the player, then the foreground. When you start scrolling the screen (from the player update), the background has already run it's update for that frame, while the foreground gets to run its update with the move command. So it is a frame ahead of the background. In scene.py, if you change the order that objects are updated: self.render.add(self.map.background) self.render.add(self.map.foreground) self.render.add(self.player) Then the player will set up the scrolling for the next frame, which fixes the problem. A better way to do cameras, instead of having it happening in the player movement function, is to have a separate camera update that scrolls the right direction at a maximum speed until whatever it is focused on is within some region of the screen. That way if you start the player offscreen, the camera will still be able to find him. Also, for cutscenes, you can have the camera focus on a different character than the player fairly easily. Another thing that bugged me: It seems weird that you have limited yourself to only two layers in the code, when any number of layers would actually be easier. A map.move() function, which moves all of its layers by a set amount, means one less line all of the places you have to write "background.move... foreground.move", and would also solve the above problem (because the movement happens instantly instead of waiting for some update). And in the map, instead of having background, and foreground, you could simply have layers[]. In the future, when you want to add a paralax treeshadow layer to display on top of the player and npc's, you will be hitting yourself at all of the places you will have to add the new layer. Good luck with the game, the sprites/tiles look really nice, and the code isn't all bad :)
[pygame] how to bind surface rects without subsurface (need help with bug)
I have been working on a game for a while, and ran into a problem. I am drawing layers with a background, player, and foreground layer. The forground is transparent and redraws treetops and stuff the user should always be in front of. That works great, however I cannot find any logic in my code as to why The foreground layer is slightly offset by 3 or 4 pixels when the map is scrolling (the map scrolls when the player is within range of the screen's edge). I realize my code isn't the best code there is, but it's also my first programming project and I've been teaching myself all sorts of things as I go. But, could someone please take a look at code and tell me why the foreground isn't aligned when scrolling? To reproduce, you'll have to move the player toward the right side of the screen until it scrolls the map, and while it does pay attention to the huge trees and other foreground objects such as the tall grass. You can grab the source at http://bloodcurse.axedcode.net/files/bloodcurse-0.1-week61.tar.gz Thanks for all the help, Michael Fiano