# Pygame Scrolling Camera bug

I asked a question the other day about how to implement a scrolling camera. I got a great answer which helped me achieve that... but in doing so I have lost basically all collision detection. Strangely, There are still small, invisible "platforms" that can be collided with... Above the first platform in view upon spawning (the second platform down), there is a very small area where I can get collision detection... happens near coordinates (60, 51). Why is collision only happening in that tiny area, and not on any of the platforms throughout the entire level?

Thanks for any help, code at github: https://github.com/tear727/Netse/blob/master/game2.py

import random
import pygame
from pygame import *

display_width = 800
display_height = 640
camera = [0,0]
size = (display_width, display_height)
screen = pygame.display.set_mode(size)
black = (0,0,0)
white = (255,255,255)
background = Surface((32, 32))
background.convert()
background.fill(Color('#783131'))
level = [
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
"P                                          P",
"P                                          P",
"P                                          P",
"P                    PPPPPPPPPPP           P",
"P                                          P",
"P                                          P",
"P                                          P",
"P    PPPPPPPP                              P",
"P                                          P",
"P                          PPPPPPP         P",
"P                 PPPPPP                   P",
"P                                          P",
"P         PPPPPPP                          P",
"P                                          P",
"P                     PPPPPP               P",
"P                                          P",
"P   PPPPPPPPPPP                            P",
"P                                          P",
"P                 PPPPPPPPPPP              P",
"P                                          P",
"P                                          P",
"P                                          P",
"P                                          P",
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
]

def main():
pygame.init()
clock = pygame.time.Clock()
x = 0
y = 0
left_viewbox = display_width/2 - display_width/8
right_viewbox = display_width/2 + display_width/10
up_viewbox = display_height/2 - display_height/12
down_viewbox = display_height/2 - display_height/12

platformlst = []
players = []

player = Player(camera[0], camera[1])
map = Map(x, y)
platforms = Platform(camera[0], camera[1])
players.append(player)

pygame.display.set_caption("My game")

def buildMap(xpos, ypos):
for i in level:
for j in i:
if j == "P":
platformlst.append(platforms)
screen.blit(platforms.image, (xpos + camera[0], ypos + camera[1]))
xpos += 64
ypos += 64
xpos = 0

def follow(shift_x, shift_y):
camera[0] += shift_x
camera[1] += shift_y
for i in players:
i.rect.x += shift_x
i.rect.y += shift_y

def viewbox():
if player.x <= left_viewbox:
view_difference = left_viewbox - player.x
player.x = left_viewbox
follow(view_difference, 0)

if player.x >= right_viewbox:
view_difference = right_viewbox - player.x
player.x = right_viewbox
follow(view_difference, 0)

if player.y <= up_viewbox:
view_difference = up_viewbox - player.y
player.y = up_viewbox
follow(0, view_difference)

if player.y >= down_viewbox:
view_difference = down_viewbox - player.y
player.y = down_viewbox
follow(0, view_difference)

def collide():
if (platforms.rect.x < player.rect.x + player.rect.w and
platforms.rect.x + platforms.rect.w > player.rect.x and
platforms.rect.y < player.rect.y + player.rect.h and
platforms.rect.h + platforms.rect.y > player.rect.y):
print "collided"
player.grounded = True

game_exit = False

while not game_exit:
clock.tick(60)

for event in pygame.event.get():
if event.type == pygame.QUIT:
game_exit = True

if event.type == pygame.KEYDOWN:
print "pressed key"

if event.key == pygame.K_LEFT:
player.left()

if event.key == pygame.K_RIGHT:
print "move right"
player.right()
if event.key == pygame.K_UP:
print "move up"
player.up()

if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
player.stopx()

if event.key == pygame.K_UP or pygame.K_DOWN:
player.stopy()

if event.type == pygame.MOUSEBUTTONDOWN:
print "pressed mouse button"
player.boost()

if event.type == pygame.MOUSEBUTTONUP:
print "mouse button up"
player.stop()

print player.rect.x
print player.rect.y
map.buildBackground()
buildMap(x, y)
player.draw()
player.move()
collide()
viewbox()
pygame.display.update()

class Map:
def __init__(self, x, y):
self.x = x
self.y = y

def buildBackground(self):
for i in range(32):
for j in range(32):
screen.blit(background, (i*32, j*32))

class Player:
def __init__(self, x, y):
self.grounded = True
self.x = x
self.y = y
self.velx = 0
self.vely = 0
self.image = player_image
self.rect = player_image.get_rect()

def draw(self):
screen.blit(self.image, (self.x, self.y))

def move(self):
self.x += self.velx
self.y += self.vely
if not self.grounded:
self.y += 7
self.grounded = False

def right(self):
self.velx = 20

def left(self):
self.velx = -20

def up(self):
self.vely = -20

def stopx(self):
self.velx = 0

def stopy(self):
self.vely = 0

def boost(self):
self.velx += 20
self.vely += 20

def stop(self):
self.velx = 0
self.vely = 0

class Platform:
def __init__(self, x, y):
self.image = Surface((64, 64))
self.image.convert()
self.image.fill(Color('#000000'))
self.rect = Rect(x, y, 64, 64)

def draw(self):
screen.blit(self.image, (x, y))

if __name__ == "__main__":
main()


The trick is I think you misunderstood my original answer to your previous question. The camera's position should only be taken into account when drawing (using blit). You're offsetting all drawn objects in the screen by the camera's position.

So two specific problems with the code you have shown:

1. The blit that does use the camera position should subtract it rather than adding it
2. Every blit needs to subtract the camera's position
• thanks again. However, I have tried this with subtraction and addition, along with changing all the x,y variables of the objects to their own x, y coordinates, the local x, y coordinates, and the camera's x, y. Still nothing. Addition yields the best results because the camera works perfectly, just nothing else. – thevengefulco Aug 15 '15 at 7:56
• I can assure you, subtraction is correct. It has nothing to do with what "looks" better because likely other aspects of your game are confusing the issue. The reason for subtraction is when your camera moves to the right, everything else moves to the left. If you ADD the camera's position the opposite happens. You can also think of it like, when the camera is at some position, any object at that same position should then be drawn to the screen at (0, 0). That can only be accomplished with subtraction. Your main issue again is that all draws or blits must have the camera position subtracted. – Alex Sherman Aug 16 '15 at 15:53

This may, or may not, be the correct answer for you,

BUT

In your code, when you draw the platforms images to the screen, you add the camera's position to their x/y positions. This would not be necessary because you would then have problems with colliding, because your adding the cameras scroll to it so you wouldn't see them in their colliding positions.

If you wanted to keep that, then I would suggest adding the camera x/y to the collision section.

Hope this helps.

• Thanks for the help. That makes a lot of sense. Yet, when the values are not added, the camera no longer scrolls and the player is just stuck inside the viewbox. Maybe viewbox or some x/y coordinates are wrong altogether – thevengefulco Aug 15 '15 at 2:10
• This maybe also another thing, but it's just a suggestion, instead of drawing the camera and updating it based on the player position when it moves, you might want to draw the camera from the players x/y position (of course subtracting it based on half the screens width/height)? – PlatyPi Aug 15 '15 at 2:23