├── camera.py └── graphics ├── ground.png ├── player.png └── tree.png /camera.py: -------------------------------------------------------------------------------- 1 | import pygame, sys 2 | from random import randint 3 | 4 | class Tree(pygame.sprite.Sprite): 5 | def __init__(self,pos,group): 6 | super().__init__(group) 7 | self.image = pygame.image.load('graphics/tree.png').convert_alpha() 8 | self.rect = self.image.get_rect(topleft = pos) 9 | 10 | class Player(pygame.sprite.Sprite): 11 | def __init__(self,pos,group): 12 | super().__init__(group) 13 | self.image = pygame.image.load('graphics/player.png').convert_alpha() 14 | self.rect = self.image.get_rect(center = pos) 15 | self.direction = pygame.math.Vector2() 16 | self.speed = 5 17 | 18 | def input(self): 19 | keys = pygame.key.get_pressed() 20 | 21 | if keys[pygame.K_UP]: 22 | self.direction.y = -1 23 | elif keys[pygame.K_DOWN]: 24 | self.direction.y = 1 25 | else: 26 | self.direction.y = 0 27 | 28 | if keys[pygame.K_RIGHT]: 29 | self.direction.x = 1 30 | elif keys[pygame.K_LEFT]: 31 | self.direction.x = -1 32 | else: 33 | self.direction.x = 0 34 | 35 | def update(self): 36 | self.input() 37 | self.rect.center += self.direction * self.speed 38 | 39 | class CameraGroup(pygame.sprite.Group): 40 | def __init__(self): 41 | super().__init__() 42 | self.display_surface = pygame.display.get_surface() 43 | 44 | # camera offset 45 | self.offset = pygame.math.Vector2() 46 | self.half_w = self.display_surface.get_size()[0] // 2 47 | self.half_h = self.display_surface.get_size()[1] // 2 48 | 49 | # box setup 50 | self.camera_borders = {'left': 200, 'right': 200, 'top': 100, 'bottom': 100} 51 | l = self.camera_borders['left'] 52 | t = self.camera_borders['top'] 53 | w = self.display_surface.get_size()[0] - (self.camera_borders['left'] + self.camera_borders['right']) 54 | h = self.display_surface.get_size()[1] - (self.camera_borders['top'] + self.camera_borders['bottom']) 55 | self.camera_rect = pygame.Rect(l,t,w,h) 56 | 57 | # ground 58 | self.ground_surf = pygame.image.load('graphics/ground.png').convert_alpha() 59 | self.ground_rect = self.ground_surf.get_rect(topleft = (0,0)) 60 | 61 | # camera speed 62 | self.keyboard_speed = 5 63 | self.mouse_speed = 0.2 64 | 65 | # zoom 66 | self.zoom_scale = 1 67 | self.internal_surf_size = (2500,2500) 68 | self.internal_surf = pygame.Surface(self.internal_surf_size, pygame.SRCALPHA) 69 | self.internal_rect = self.internal_surf.get_rect(center = (self.half_w,self.half_h)) 70 | self.internal_surface_size_vector = pygame.math.Vector2(self.internal_surf_size) 71 | self.internal_offset = pygame.math.Vector2() 72 | self.internal_offset.x = self.internal_surf_size[0] // 2 - self.half_w 73 | self.internal_offset.y = self.internal_surf_size[1] // 2 - self.half_h 74 | 75 | def center_target_camera(self,target): 76 | self.offset.x = target.rect.centerx - self.half_w 77 | self.offset.y = target.rect.centery - self.half_h 78 | 79 | def box_target_camera(self,target): 80 | 81 | if target.rect.left < self.camera_rect.left: 82 | self.camera_rect.left = target.rect.left 83 | if target.rect.right > self.camera_rect.right: 84 | self.camera_rect.right = target.rect.right 85 | if target.rect.top < self.camera_rect.top: 86 | self.camera_rect.top = target.rect.top 87 | if target.rect.bottom > self.camera_rect.bottom: 88 | self.camera_rect.bottom = target.rect.bottom 89 | 90 | self.offset.x = self.camera_rect.left - self.camera_borders['left'] 91 | self.offset.y = self.camera_rect.top - self.camera_borders['top'] 92 | 93 | def keyboard_control(self): 94 | keys = pygame.key.get_pressed() 95 | if keys[pygame.K_a]: self.camera_rect.x -= self.keyboard_speed 96 | if keys[pygame.K_d]: self.camera_rect.x += self.keyboard_speed 97 | if keys[pygame.K_w]: self.camera_rect.y -= self.keyboard_speed 98 | if keys[pygame.K_s]: self.camera_rect.y += self.keyboard_speed 99 | 100 | self.offset.x = self.camera_rect.left - self.camera_borders['left'] 101 | self.offset.y = self.camera_rect.top - self.camera_borders['top'] 102 | 103 | def mouse_control(self): 104 | mouse = pygame.math.Vector2(pygame.mouse.get_pos()) 105 | mouse_offset_vector = pygame.math.Vector2() 106 | 107 | left_border = self.camera_borders['left'] 108 | top_border = self.camera_borders['top'] 109 | right_border = self.display_surface.get_size()[0] - self.camera_borders['right'] 110 | bottom_border = self.display_surface.get_size()[1] - self.camera_borders['bottom'] 111 | 112 | if top_border < mouse.y < bottom_border: 113 | if mouse.x < left_border: 114 | mouse_offset_vector.x = mouse.x - left_border 115 | pygame.mouse.set_pos((left_border,mouse.y)) 116 | if mouse.x > right_border: 117 | mouse_offset_vector.x = mouse.x - right_border 118 | pygame.mouse.set_pos((right_border,mouse.y)) 119 | elif mouse.y < top_border: 120 | if mouse.x < left_border: 121 | mouse_offset_vector = mouse - pygame.math.Vector2(left_border,top_border) 122 | pygame.mouse.set_pos((left_border,top_border)) 123 | if mouse.x > right_border: 124 | mouse_offset_vector = mouse - pygame.math.Vector2(right_border,top_border) 125 | pygame.mouse.set_pos((right_border,top_border)) 126 | elif mouse.y > bottom_border: 127 | if mouse.x < left_border: 128 | mouse_offset_vector = mouse - pygame.math.Vector2(left_border,bottom_border) 129 | pygame.mouse.set_pos((left_border,bottom_border)) 130 | if mouse.x > right_border: 131 | mouse_offset_vector = mouse - pygame.math.Vector2(right_border,bottom_border) 132 | pygame.mouse.set_pos((right_border,bottom_border)) 133 | 134 | if left_border < mouse.x < right_border: 135 | if mouse.y < top_border: 136 | mouse_offset_vector.y = mouse.y - top_border 137 | pygame.mouse.set_pos((mouse.x,top_border)) 138 | if mouse.y > bottom_border: 139 | mouse_offset_vector.y = mouse.y - bottom_border 140 | pygame.mouse.set_pos((mouse.x,bottom_border)) 141 | 142 | self.offset += mouse_offset_vector * self.mouse_speed 143 | 144 | def zoom_keyboard_control(self): 145 | keys = pygame.key.get_pressed() 146 | if keys[pygame.K_q]: 147 | self.zoom_scale += 0.1 148 | if keys[pygame.K_e]: 149 | self.zoom_scale -= 0.1 150 | 151 | def custom_draw(self,player): 152 | 153 | # self.center_target_camera(player) 154 | # self.box_target_camera(player) 155 | # self.keyboard_control() 156 | self.mouse_control() 157 | self.zoom_keyboard_control() 158 | 159 | self.internal_surf.fill('#71ddee') 160 | 161 | # ground 162 | ground_offset = self.ground_rect.topleft - self.offset + self.internal_offset 163 | self.internal_surf.blit(self.ground_surf,ground_offset) 164 | 165 | # active elements 166 | for sprite in sorted(self.sprites(),key = lambda sprite: sprite.rect.centery): 167 | offset_pos = sprite.rect.topleft - self.offset + self.internal_offset 168 | self.internal_surf.blit(sprite.image,offset_pos) 169 | 170 | scaled_surf = pygame.transform.scale(self.internal_surf,self.internal_surface_size_vector * self.zoom_scale) 171 | scaled_rect = scaled_surf.get_rect(center = (self.half_w,self.half_h)) 172 | 173 | self.display_surface.blit(scaled_surf,scaled_rect) 174 | 175 | 176 | pygame.init() 177 | screen = pygame.display.set_mode((1280,720)) 178 | clock = pygame.time.Clock() 179 | pygame.event.set_grab(True) 180 | 181 | # setup 182 | camera_group = CameraGroup() 183 | player = Player((640,360),camera_group) 184 | 185 | for i in range(20): 186 | random_x = randint(1000,2000) 187 | random_y = randint(1000,2000) 188 | Tree((random_x,random_y),camera_group) 189 | 190 | while True: 191 | for event in pygame.event.get(): 192 | if event.type == pygame.QUIT: 193 | pygame.quit() 194 | sys.exit() 195 | if event.type == pygame.KEYDOWN: 196 | if event.key == pygame.K_ESCAPE: 197 | pygame.quit() 198 | sys.exit() 199 | 200 | if event.type == pygame.MOUSEWHEEL: 201 | camera_group.zoom_scale += event.y * 0.03 202 | 203 | screen.fill('#71ddee') 204 | 205 | camera_group.update() 206 | camera_group.custom_draw(player) 207 | 208 | pygame.display.update() 209 | clock.tick(60) 210 | -------------------------------------------------------------------------------- /graphics/ground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clear-code-projects/Pygame-Cameras/85c3f0b65d3c4ea68d5c56127b0012637984d679/graphics/ground.png -------------------------------------------------------------------------------- /graphics/player.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clear-code-projects/Pygame-Cameras/85c3f0b65d3c4ea68d5c56127b0012637984d679/graphics/player.png -------------------------------------------------------------------------------- /graphics/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clear-code-projects/Pygame-Cameras/85c3f0b65d3c4ea68d5c56127b0012637984d679/graphics/tree.png --------------------------------------------------------------------------------