Reputation: 101
I'm attempting to make it so that you can zoom in and zoom out in my pygame project. It is working fine except when I zoom in, the screen seems to be zooming towards the top left and then readjusting itself after (making it so that the player is on the center of the screen). When I zoom out, it simply does the same with the opposite corner, can someone explain me why is it doing so? Here is my code:
import pygame
import random
import sys
from pygame.locals import *
WINDOW_SIZE = (600, 400)
FPS = 60
# Initialize pygame and create window
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode(WINDOW_SIZE)
zoom = 2
display = pygame.Surface((int(WINDOW_SIZE[0] / zoom), int(WINDOW_SIZE[1] / zoom)))
pygame.display.set_caption('Game')
clock = pygame.time.Clock()
player_img = pygame.image.load('player.png').convert()
player_img.set_colorkey((255, 255, 255))
player_rect = pygame.Rect(0, 0, 5, 16)
grass_img = pygame.image.load('grass.png').convert()
dirt_img = pygame.image.load('dirt.png').convert()
# 0 = Air
# 1 = Grass
# 2 = Dirt
game_map =[['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['0','0','0','0','0','0','1','1','1','1','1','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['1','1','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1','1','0','0','0','0','0','0','0','0','0'],
['2','2','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','2','2','0','0','0','1','1','1','1','1','0'],
['2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','2','0','0','0','2','2','2','2','2','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2','2','2','0','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2','2','0','0','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','2','0','0','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'],
['0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0']]
def collision_test(rect,tiles):
collisions = []
for tile in tiles:
if rect.colliderect(tile):
collisions.append(tile)
return collisions
def move(rect, movement, tiles):
collision_direction = {'up': False, 'down': False, 'right': False, 'left' : False}
rect.x += movement[0]
collisions = collision_test(rect, tiles)
for tile in collisions:
if movement[0] > 0:
rect.right = tile.left
collision_direction['right'] = True
if movement[0] < 0:
rect.left = tile.right
collision_direction['left'] = True
rect.y += round(movement[1])
collisions = collision_test(rect, tiles)
for tile in collisions:
if movement[1] > 0:
rect.bottom = tile.top
collision_direction['down'] = True
if movement[1] < 0:
rect.top = tile.bottom
collision_direction['up'] = True
return rect, collision_direction
mouvement_speed = 2
moving_right = False
moving_left = False
moving_up = False
moving_down = False
ctrl_pressed = False
equals_pressed = False
minus_pressed = False
zero_pressed = False
player_y_momentum = 0
air_timer = 0
scroll = [0, 0]
running = True
# Game loop
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
if event.type == KEYDOWN:
if event.key == K_RIGHT or event.key == K_d:
moving_right = True
if event.key == K_LEFT or event.key == K_a:
moving_left = True
if event.key == K_UP or event.key == K_w:
if air_timer < 3:
player_y_momentum = -4
if event.key == K_DOWN or event.key == K_s:
moving_down = True
if event.key == K_RCTRL or event.key == K_LCTRL:
ctrl_pressed = True
if event.key == K_EQUALS:
equals_pressed = True
if event.key == K_MINUS:
minus_pressed = True
if event.key == K_0:
zero_pressed = True
if event.type == KEYUP:
if event.key == K_RIGHT or event.key == K_d:
moving_right = False
if event.key == K_LEFT or event.key == K_a:
moving_left = False
if event.key == K_UP or event.key == K_w:
moving_up = False
if event.key == K_DOWN or event.key == K_s:
moving_down = False
if event.key == K_EQUALS:
equals_pressed = False
if event.key == K_MINUS:
minus_pressed = False
if event.key == K_0:
zero_pressed = False
if event.key == K_RCTRL or event.key == K_LCTRL:
ctrl_pressed = False
if equals_pressed and ctrl_pressed:
zoom += 0.2
print('ZOOMING IN')
if minus_pressed and ctrl_pressed:
zoom -= 0.2
print('ZOOMING OUT')
if zero_pressed and ctrl_pressed:
zoom = 2
print('RESET')
try:
display = pygame.Surface((int(WINDOW_SIZE[0] / zoom), int(WINDOW_SIZE[1] / zoom)))
except:
zoom = 0.4
display.fill((5, 195, 225))
tile_rect = []
y = 0
for layer in game_map:
x = 0
for tile in layer:
if tile == '1':
display.blit(grass_img, (x * 16 - scroll[0], y * 16 - scroll[1]))
if tile == '2':
display.blit(dirt_img, (x * 16 - scroll[0], y * 16 - scroll[1]))
if tile != '0':
tile_rect.append(pygame.Rect(x * 16, y * 16, 16, 16))
x += 1
y += 1
scroll[0] += ((player_rect.x - int(WINDOW_SIZE[0]/ (zoom * 2)) + 2) - scroll[0]) / 12
scroll[1] += ((player_rect.y - int(WINDOW_SIZE[1]/ (zoom * 2)) + 5) - scroll[1]) / 12
player_mouvement = [0, 0]
if moving_right:
player_mouvement[0] += mouvement_speed
if moving_left:
player_mouvement[0] -= mouvement_speed
if moving_down:
player_mouvement[1] += 5
player_y_momentum += 0.2
if player_y_momentum > 5:
player_y_momentum = 5
player_mouvement[1] += player_y_momentum
player_rect, collision_direction = move(player_rect, player_mouvement, tile_rect)
if collision_direction['down']:
air_timer = 0
player_y_momentum = 0
else:
air_timer += 1
if collision_direction['up']:
player_y_momentum = 0
display.blit(player_img, (player_rect.x - scroll[0], player_rect.y - scroll[1]))
#pygame.draw.rect(display,(255, 255, 255),player_rect)
#print(air_timer)
screen.blit(pygame.transform.scale(display,WINDOW_SIZE),(0,0))
pygame.display.update()
clock.tick(FPS)
pygame.quit()
sys.exit()
Upvotes: 3
Views: 12148
Reputation: 2779
Your scroll
calculation is a bit confusing and I am not quite sure what the calculation is exactly doing (and there are no comments to explain it). Clearly the intent is to scroll it to track the player and so adjust where the game_map
gets drawn onto the display
and where the player gets drawn onto it. You then scale()
that to the screen
to get your zoom effect
Though I cannot comment on exactly what the issue is with the scroll I could suggest a different and I believe simpler way to go about this. Draw your display
without doing the scroll stuff. Then use subsurface()
to grab a section of display
centered on your player with the desired size to achieve the zoom effect you want. Then scale that subsurface and blit()
it onto screen
.
Although above I just said centered on your player for simplicity, you would have to adjust that if the player was too close to the edges of display
at the desired zoom level.
This should simplify all the creation of the display
and the only effort is in deciding where and how big the subsurface is within display
to get the location and zoom factor that you want.
Upvotes: 1
Reputation: 101
All that you need to do is lock the scroll towards the player by using
scroll[0] = player_rect.x - int(WINDOW_SIZE[0]/ (zoom * 2)) + 2
scroll[1] = player_rect.y - int(WINDOW_SIZE[1]/ (zoom * 2)) + 5
Upvotes: 1