1
\$\begingroup\$

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:

game camera

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[0], bottomright[0])):
    for j, y in enumerate(xrange(topleft[1], bottomright[1])):
        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[0], 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:

in short:

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:

enter image description here

which leads to the next question:

2) Is there a better way to create a camera than using this 'hack' of enumerating?

EDIT: Answer

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[0] /= 2 # divided each one by two, because the player is in the center.
    self.size[1] /= 2

    if self.x < self.size[0]:  # right
        self.x = self.size[0]
    if self.y < self.size[1]: # up
        self.y = self.size[1]
    if self.x + self.size[0] > mymap.width: # left
        self.x = mymap.width- self.size[0]
    if self.y + self.size[1] > mymap.height: # down
        self.y = mymap.height-self.size[1]

    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.

\$\endgroup\$
1
\$\begingroup\$

1) You could make sure that the topleft of the camera would never be smaller than the topleft of the map. And then also check that the bottomright of the camera is never bigger than the bottomright of the map. That should do the trick.

2) Your way seems okay, but camera movement is often acomplished by offsetting the rendered tiles by some varying amount.

I hope this helps.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.