在pygame中使用滚动相机

时间:2015-06-25 04:54:55

标签: python pygame

我试图在我用pygame制作的2d游戏中实现相机功能,但我唯一获得的是我在窗口中间设置的玩家。我看到它的x和y如何变化,但玩家不会移动。我知道我必须使用相机的apply方法到地图但我不知道该怎么做,因为这是我第一次接触pygame。这是我的代码:

import pygame, sys
from pygame.locals import *
import random

"""
dirt  0
grass 1
water 2
coal  3
"""

DIRT = 0
GRASS = 1
WATER = 2
COAL = 3
DIAMOND = 4
CLOUD = 5

cloudx = -200
cloudy = 0

WHITE = (255, 255, 255)
BLACK = (0,   0,   0  )
BROWN = (153, 76,  0  )
GREEN = (0,   255, 0  )
BLUE  = (0,   0,   255)

TILESIZE  = 40
MAPWIDTH  = 140
MAPHEIGHT = 120

WIN_WIDTH = 800
WIN_HEIGHT = 600

HALF_WIDTH = int(WIN_WIDTH / 2)
HALF_HEIGHT = int(WIN_HEIGHT / 2)

fpsClock = pygame.time.Clock()

colours = {
            DIRT: BROWN,
            GRASS: GREEN,
            WATER: BLUE,
            COAL: BLACK
          }

"""tilemap = [
            [GRASS, COAL,  DIRT ],
            [WATER, WATER, GRASS],
            [COAL,  WATER, GRASS],
            [DIRT,  WATER, COAL ],
            [GRASS, WATER, DIRT]
          ]"""

resources = [WATER, GRASS, COAL, DIRT, DIAMOND]
tilemap = [[random.choice(resources) for w in range(MAPWIDTH)] for h in range(MAPHEIGHT)]



textures = {
            DIRT: pygame.image.load("dirt.gif"),
            GRASS: pygame.image.load("grass.gif"),
            COAL: pygame.image.load("coal.gif"),
            WATER: pygame.image.load("water.gif"),
            DIAMOND: pygame.image.load("diamond.gif"),
            CLOUD: pygame.image.load("nube.gif")
           }

inventory = {
                DIRT    :0,
                WATER   :0,
                GRASS   :0,
                COAL    :0,
                DIAMOND :0

            }

playerPos = [50,50]
move = 0
vel_x = 0
vel_y = 0
speed = 1

class Camera(object):
    def __init__(self, camera_func, width, height):
        self.camera_func = camera_func
        self.state = pygame.Rect(0, 0, width, height)

    def apply(self, rect):
        return rect.move(self.state.topleft)

    def update(self, target_rect):
        self.state = self.camera_func(self.state, target_rect)

def simple_camera(camera, target_rect):
    l, t, _, _ = target_rect
    _, _, w, h = camera

    return pygame.Rect(-l+HALF_WIDTH, -t+HALF_HEIGHT, w, h)

def complex_camera(camera, target_rect):
    l, t, _, _ = target_rect
    _, _, w, h = camera
    l, t, _, _ = -l+HALF_WIDTH, -t+HALF_HEIGHT, w, h

    l = min(0, l)                           # stop scrolling at the left edge
    l = max(-(camera.width-SCREEN_WIDTH), l)   # stop scrolling at the right edge
    t = max(-(camera.height-SCREEN_HEIGHT), t) # stop scrolling at the bottom
    t = min(0, t)                           # stop scrolling at the top
    return pygame.Rect(l, t, w, h)

global cameraX, cameraY
total_level_width = len(tilemap[0]) * TILESIZE
total_level_height = len(tilemap)*TILESIZE
camera = Camera(simple_camera ,total_level_width, total_level_height)

pygame.init()
DISPLAYSURF = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT))
pygame.display.set_caption("My first game :)")
pygame.display.set_icon(pygame.image.load("player.gif"))

PLAYER = pygame.image.load("player.gif")
playerrect = PLAYER.get_rect()


for rw in range(MAPHEIGHT):
    for cl in range(MAPWIDTH):
        randomNumber = random.randint(0,50)

        if randomNumber <= 10:
            tile = COAL
        elif randomNumber > 11 and randomNumber <= 20:
            tile = WATER
        elif randomNumber > 21 and randomNumber <= 45:
            tile = GRASS
        elif randomNumber > 46 and randomNumber <= 49:
            tile = DIRT
        else:
            tile = DIAMOND

        tilemap[rw][cl] = tile

INVFONT = pygame.font.Font("freeSansBold.ttf", 18)

while True:
    for event in pygame.event.get():
        if event.type == QUIT or event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            pygame.quit()
            sys.exit()
        elif event.type == KEYDOWN:
            #movement
            if event.key == K_RIGHT and playerPos[0] < MAPWIDTH - 1:
                playerPos[0] += move
            elif event.key == K_LEFT and playerPos[0] > 1/TILESIZE:
                playerPos[0] -= move
            elif event.key == K_DOWN and playerPos[1] < MAPHEIGHT - 1:
                playerPos[1] += move
            elif event.key == K_UP and playerPos[1] > 1/TILESIZE:
                playerPos[1] -= move

            #pick up resource
            elif event.key == K_SPACE:
                currentTile = tilemap[playerPos[1]][playerPos[0]]
                inventory[currentTile] += 1
                tilemap[playerPos[1]][playerPos[0]] = DIRT

            #place resources
            elif event.key == K_1:
                currentTile = tilemap[playerPos[1]][playerPos[0]]
                if inventory[WATER] > 0:
                    inventory[WATER] -= 1
                    tilemap[playerPos[1]][playerPos[0]] = WATER
                    inventory[currentTile] += 1
            elif event.key == K_2:
                currentTile = tilemap[playerPos[1]][playerPos[0]]
                if inventory[GRASS] > 0:
                    inventory[GRASS] -= 1
                    tilemap[playerPos[1]][playerPos[0]] = GRASS
                    inventory[currentTile] += 1
            elif event.key == K_3:
                currentTile = tilemap[playerPos[1]][playerPos[0]]
                if inventory[COAL] > 0:
                    inventory[COAL] -= 1
                    tilemap[playerPos[1]][playerPos[0]] = COAL
                    inventory[currentTile] += 1
            elif event.key == K_4:
                currentTile = tilemap[playerPos[1]][playerPos[0]]
                if inventory[DIRT] > 0:
                    inventory[DIRT] -= 1
                    tilemap[playerPos[1]][playerPos[0]] = DIRT
                    inventory[currentTile] += 1
            elif event.key == K_5:
                currentTile = tilemap[playerPos[1]][playerPos[0]]
                if inventory[DIAMOND] > 0:
                    inventory[DIAMOND] -= 1
                    tilemap[playerPos[1]][playerPos[0]] = DIAMOND
                    inventory[currentTile] += 1
    keys = pygame.key.get_pressed()
    if keys[K_LEFT] and playerPos[0] > 1/TILESIZE:
        playerPos[0] -= speed
    if keys[K_RIGHT] and playerPos[0] < MAPWIDTH - 1:
        playerPos[0] += speed
    if keys[K_UP] and playerPos[1] > 1/TILESIZE:
        playerPos[1] -= speed
    if keys[K_DOWN] and playerPos[1] < MAPHEIGHT - 1:
        playerPos[1] += speed

    for row in range(MAPHEIGHT):
        for column in range(MAPWIDTH):
            DISPLAYSURF.blit(textures[tilemap[row][column]], (column*TILESIZE, row*TILESIZE))
            #DISPLAYSURF.blit(PLAYER, (playerPos[0]*TILESIZE, playerPos[1]*TILESIZE))


    DISPLAYSURF.blit(PLAYER, camera.apply(pygame.Rect(playerPos[0],playerPos[1],42,42)))
    camera.update(PLAYER.get_rect().move((playerPos[0],playerPos[1])))

    pygame.display.update()
    fpsClock.tick(10)
    print playerPos

1 个答案:

答案 0 :(得分:1)

首先,删除这段代码:

        if event.key == K_RIGHT and playerPos[0] < MAPWIDTH - 1:
            playerPos[0] += move
        elif event.key == K_LEFT and playerPos[0] > 1/TILESIZE:
            playerPos[0] -= move
        elif event.key == K_DOWN and playerPos[1] < MAPHEIGHT - 1:
            playerPos[1] += move
        elif event.key == K_UP and playerPos[1] > 1/TILESIZE:
            playerPos[1] -= move

您已使用pygame.key.get_pressed()进行移动,因此无需检查按键操作(不要忘记将以下elif更改为if )。

  

我知道我必须将相机的应用方法用于地图

是的,你正走在正确的轨道上。

您已经创建了一个变量playerrect,因此我们可以使用它来存储播放器的位置。另外,让我们创建一个Rect来存储地图的大小。这很快就会派上用场:

playerrect = PLAYER.get_rect(top=50, left=50)
mapsize = pygame.rect.Rect(0, 0, MAPWIDTH*TILESIZE, MAPHEIGHT*TILESIZE)

现在,当按住键移动播放器时,我们可以简单地使用

keys = pygame.key.get_pressed()

if keys[K_LEFT]:  playerrect.move_ip(-speed, 0)
if keys[K_RIGHT]: playerrect.move_ip(speed, 0)
if keys[K_UP]:    playerrect.move_ip(0, -speed)
if keys[K_DOWN]:  playerrect.move_ip(0, speed)

playerrect.clamp_ip(mapsize)

更改播放器的位置,playerrect.clamp_ip(mapsize)确保玩家永远不会离开地图。

对于绘图,您应该首先清除屏幕。要绘制切片,您必须为每个切片创建一个Rect(稍后您可以创建一次并存储/重复使用它们)。

DISPLAYSURF.fill(pygame.color.Color('Black'))
for row in range(MAPHEIGHT):
    for column in range(MAPWIDTH):
        DISPLAYSURF.blit(textures[tilemap[row][column]], camera.apply(pygame.rect.Rect((column*TILESIZE, row*TILESIZE), (TILESIZE, TILESIZE))))

DISPLAYSURF.blit(PLAYER, camera.apply(playerrect))
camera.update(playerrect)