Let's visualize this mechanic below. The player is represented by red dot, the rectangle with a blue border represents a game display just the user can see and there is a map generated with brown and green rectangles. When the player was moving up, actually, the map moving down. As you see can:
If the player moves down, the map will be moved up in fact:
This situation is valid when the player moved through the right and left:
Everything make sense, I mean we have to calculate positions of every object in the game according to target which is also player.Let's start with typing Camera Class:
import pygame
from pygame.math import Vector2
class Camera:
def __init__(self, target, width, height):
self.width = width
self.height = height
self.camera = Vector2(target.pos.x, target.pos.y)
self.target = target
self.offset = Vector2(0,0)
We are going to use a vector for the camera, also we need to screen's width and height. We will use width and height values for centering the target and camera on the screen. A vector in math has a length and direction. We created a camera vector that will contain the position of our camera and assigned position of target object, initially. The target variable contains our player what we want to focus on with the camera. The offset vector will be used for setting the position of each object in the game.We are adding a method called scroll for calculating offset value and the tilemap:
def scroll(self):
self.pointTarget = self.target.pos - self.camera
self.camera += self.pointTarget
self.offset = -self.camera + Vector2(self.width/2, self.height/2)
We calculated pointTarget vector that will be point to the target vector. Because when the player moved, the camera's position must be updated according to the target. So, we will calculate the distance between the camera and the target and this distance that is pointTarget will be added to camera for to the getting position of player. Finally, we calculate the offset value according to the camera vector. If you realize, Vector2(self.width/2, self.height/2)
is added to the offset in addition, to do centering to the player on the screen. Lets use it in main.py:
import pygame
import random
from player import Player
from tilemap import *
from camera import Camera
...
player = Player(sprites_group, (0,0), (25,25), (0,0,255))
map_data = generate_map(1024, 1024)
camera = Camera(player, 640, 480)
e = Entity(sprites_group, (32,32), (32,32), (255,0,255))
def main():
...
while running:
...
camera.scroll()
# draw
screen.fill((255,255,255))
draw_map(screen, map_data, camera)
for sprite in sprites_group:
screen.blit(sprite.image, (sprite.rect.topleft + camera.offset))
...
camera
the object is created and passed player object. In the game loop, we are calculating offset with camera.scroll()
and we will update positions of all sprites in the game according to camera vector with for loop and render them at the same time. But this scrolling hasn't affected the tilemap yet. As a solution, we have to change to draw_map function a little bit, and actually, we do the same thing that we do for the sprites. Every tile's position has to be updated with offset value as in the code below:
def draw_map(screen, map_data, camera = None):
...
if camera:
for row in range(MAP_HEIGHT):
for col in range(MAP_WIDTH):
screen.blit(textures[map_data[row][col]],
(col*TILE_SIZE + camera.offset.x, row*TILE_SIZE + camera.offset.y))
...
So we did it, we can around everywhere on the map.Well, maybe I should fill the background with black color. 👀
You are able to reach full of source code on the Github repo.
No comments:
Post a Comment