I have two questions.
I'm working in a rogue-like and I've manage to implement a camera on the player, the camera shows just the players surroundings and is fixed in the side of the windows.
The problem is, when the player is close to the sides of the map there's a black space in the surface. Like so:
1) How do I make the camera 'snap' to the side and don't go any further?
To draw the map
- I took the Camera Rect positions [topleft and bottomright];
- Converted it to World Position;
- Iterate over it, with a enumerator too;
- Did any lit/visited FOG calcunations with X and Y;
- And Blited in the screen using the enumerators 'i' and 'j'.
Here's the code:
topleft = Map.toWorld(camera.rect.topleft) bottomright = Map.toWorld(camera.rect.bottomright) for i, x in enumerate(xrange(topleft, bottomright)): for j, y in enumerate(xrange(topleft, bottomright)): tile = mymap.tileAt(x, y) object = [obj for obj in Object.OBJECTS if obj.pos == (x,y)] if tile: lit = field_of_view.lit(x, y) visited = field_of_view.visited(x, y) graphic = tile.graphic if lit: color = tile.color elif visited: color = GRAY else: color = BLACK renderedgraphic = myfont.render(ch, 1, graphic) screen.blit(renderedgraphic, Map.toScreen((i + 1, j))) if object: Draw.drawObject(object, Map.toScreen((i + 1, j)))
I saw HERE a exemple of this but I couldn't adapt the code to my game because it uses sprites.
I also tried a different approach using just a camera.center position:
class Object(): def update(self): self.relX = self.x - camera.x self.relY = self.y - camera.y class Camera(Object): def update(self): self.x = self.relX = PLAYER.x self.y = self.relY = PLAYER.y def MapDraw() for x in xrange(mymap.width): for y in xrange(mymap.height): ... # do fov stuff tile = Tile.At(x, y) # get tile instance if tile: tile.update() # update it's relative position screen.blit(renderedgraphic, (tile.relX * TILESIZE, tile.relX * TILESIZE)) # blit the postion to it's relative position
This is what happens:
which leads to the next question:
2) Is there a better way to create a camera than using this 'hack' of enumerating?
So after some struggles I tried the old, print whatever I had and found out that I could use the camera.x and camera.y for this.
first I check the distace between camera.x and the optional position in the sides, It was 3 for up and down, 7 to sides.
Then a couple of if-statements fixed this. But since int's aren't very consitent depending on mapsize, cameraview, I found that the camera.rect width and height divided by 2 in world position was the same as (7,3) I was looking for.
Anyway, here's the code for the camera.
def update(self): self.x, self.y = PLAYER.pos # center camera on player self.size = Map.toWorld((camera.rect.width, camera.rect.height)) ## get the ScreenSize of the rect and convert to World Position self.size /= 2 # divided each one by two, because the player is in the center. self.size /= 2 if self.x < self.size: # right self.x = self.size if self.y < self.size: # up self.y = self.size if self.x + self.size > mymap.width: # left self.x = mymap.width- self.size if self.y + self.size > mymap.height: # down self.y = mymap.height-self.size self.rect = pygame.Rect((self.x * TILESIZE) - CAMERA_WIDTH / 2, (self.y * TILESIZE) - CAMERA_HEIGHT / 2, CAMERA_WIDTH, CAMERA_HEIGHT) # updated the rect
Thanks Tyyppi_77, even tho you provided a small answer, the way you phrased it was just right for me to get it.