2013-07-16 100 views
1

我試圖複製一些電網視口(如3ds Max中的正高視圖)
或地圖觀衆喜歡(的GoogleMaps),我們有地圖或網格的行爲,這是比屏幕大很多的
,我們通過點擊視口中的某處並拖動進行導航。pygame的:視口中單擊並拖動

到目前爲止,我設法創建了一個非常大的網格,繪製它並使視口僅顯示它應該顯示的圖塊。

這是到目前爲止我的代碼:

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

FPS = 30 
WINDOWWIDTH = 640 
WINDOWHEIGHT = 480 
GRIDWIDTH = 256 
GRIDHEIGHT = 256 
GRIDSIZE = 256 
TILESIZE = 40 
BGCOLOR = (128, 128, 128) 
FGCOLOR = (64, 64, 64) 

GRID = [] 

FPSCLOCK = pygame.time.Clock() 

indexX = None 
indexY = None 

minVPcoordX = 0 
minVPcoordY = 0 
maxVPcoordX = (TILESIZE*GRIDSIZE)-WINDOWWIDTH 
maxVPcoordY = (TILESIZE*GRIDSIZE)-WINDOWHEIGHT 
viewportOffset = (0, 0) 
vpStartXTile = 0 
vpStartYTile = 0 
viewportCoord = (0, 0) 

coordX = 0 
coordY = 0 

movedDistanceX = 0 
movedDistanceY = 0 

speed = 4 

def main(): 
    global FPSCLOCK, DISPLAYSURF 
    global coordX, coordY 
    global offsetX, offsetY, negativeOffsetX, negativeOffsetY 
    global movedDistanceX, movedDistanceY 

    DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT)) 

    mouseX = 0 
    mouseY = 0 

    generateGrid(GRIDSIZE, GRIDSIZE) 

    LeftButton = False 
    mousePos = (0, 0) 
    dragStart = (0,0) 
    dragEnd = (0,0) 

    pygame.font.init() 
    arialFnt = pygame.font.SysFont('Arial', 16) 
    while True: 
     DISPLAYSURF.fill(BGCOLOR) 

     for event in pygame.event.get(): 
      if event.type == QUIT: 
       pygame.quit() 
       sys.exit() 

     #X 
     if coordX < maxVPcoordX: 
      coordX += speed 
     elif coordX < minVPcoordX: 
      coordX = 0 
     else: 
      coordX = maxVPcoordX 
     #Y 
     if coordY < maxVPcoordY: 
      coordY += speed 
     elif coordY < minVPcoordY: 
      coordY = 0 
     else: 
      coordY = maxVPcoordY 
     #------------- 

     viewportCoord = (coordX, coordY) 
     print(coordX, coordY) 

     vpStartXTile = math.floor(float(viewportCoord[0]/TILESIZE)) 
     vpStartYTile = math.floor(float(viewportCoord[1]/TILESIZE)) 
     GRIDstartTile = GRID[vpStartXTile][vpStartYTile] 

     negativeOffsetX = viewportCoord[0] - GRID[vpStartXTile][vpStartYTile][0] 
     negativeOffsetY = viewportCoord[1] - GRID[vpStartXTile][vpStartYTile][1] 

     offsetX = TILESIZE - negativeOffsetX 
     offsetY = TILESIZE - negativeOffsetY 

     repeatX = math.floor(WINDOWWIDTH/TILESIZE) 
     repeatY = math.floor(WINDOWHEIGHT/TILESIZE) 

     drawGrid(repeatX, repeatY) 

     outputLabel = arialFnt.render('(Top-Left)Coordinates: x%s - y%s' % (coordX, coordY), 1, (255,255,255)) 
     DISPLAYSURF.blit(outputLabel, (10, 10)) 

     # frame draw 
     pygame.display.set_caption("Memory Game - FPS: %.0f" % FPSCLOCK.get_fps()) 
     pygame.display.flip() 
     pygame.display.update() 
     FPSCLOCK.tick(FPS) 



def generateGrid(xTiles=None, yTiles=None): 
    global GRID 

    GRID = [] 

    for i in range(xTiles): 
     GRID.append([None] * yTiles) 

    ix = 0 
    iy = 0 

    posX = -40 

    for x in range(len(GRID[ix])): 
     posX += TILESIZE 
     posY = -40 
     iy = 0 
     for y in range(xTiles): 
      posY += TILESIZE 
      position = (posX, posY) 
      GRID[ix][iy] = position 
      iy += 1 
     if ix < xTiles: 
      ix += 1 
     else: 
      return 

def drawGrid(x=None, y=None): 
    lineWidth = 1 

    xPos = 0 
    yPos = 0 

    for i in range(x): 
     xStart = (xPos + offsetX, 0) 
     xEnd = (xPos + offsetX, WINDOWHEIGHT + negativeOffsetY) 
     pygame.draw.line(DISPLAYSURF, FGCOLOR, xStart, xEnd, lineWidth) 
     xPos += TILESIZE 

    for i in range(y): 
     yStart = (0, yPos + offsetY) 
     yEnd = (WINDOWWIDTH + negativeOffsetX, yPos + offsetY) 
     pygame.draw.line(DISPLAYSURF, FGCOLOR, yStart, yEnd, lineWidth) 
     yPos += TILESIZE 

def moveGrid():  
    pass 

def zoomIn(): 
    pass 

def zoomOut(): 
    pass 

main()  

正如你所看到的,它按預期工作(我還沒有實現任何形式的點擊&阻力
這個樣本中 的)。

似乎pygame的沒有這個事件,所以它必須是
MOUSEBUTTONDOWNMOUSEMOTION的組合。

我試着用get_pos()存儲前一幀的位置,並減去當前幀的位置,但我無法弄清楚下一個。 它加速的方式太快..
我也試過這與get_rel()鼠標的方法,沒有成功。
(雖然我敢肯定,我是不應該++鼠標位置在屏幕上的位置)

我研究了四周,看看是否有人這樣做,但我只發現瞭如何拖動東西
在一個固定的屏幕上。我需要相反的 - 在固定的網格上拖動屏幕。所以,如果任何人有任何想法或建議如何使這個機制,或任何我可以研究它的鏈接,我將不勝感激!

PS:我發現類似的東西,但它寫在JS和它的翻譯)

+1

看看這個演示。您可以使用鼠標滾動網格。 http://code.google.com/p/ninmonkey/source/browse/#hg%2Fexamples%2Fmaptiles_numpy%253Fstate%253Dclosed – ninMonkey

+0

謝謝,這對我幫助很大!我將發佈固定代碼。 –

回答

1

我得到它的工作有疼痛感!

它對zoomIn/zoomOut的添加仍然存在一些問題,但拖動網格的
的主要問題是固定的。

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

FPS = 30 
WINDOWWIDTH = 640 
WINDOWHEIGHT = 480 
GRIDSIZE = 256 
TILESIZE = 40 
BGCOLOR = (128, 128, 128) 
FGCOLOR = (64, 64, 64) 

GRID = [] 

FPSCLOCK = pygame.time.Clock() 

indexX = None 
indexY = None 

minVPcoordX = 0 
minVPcoordY = 0 
maxVPcoordX = (TILESIZE*GRIDSIZE)-WINDOWWIDTH 
maxVPcoordY = (TILESIZE*GRIDSIZE)-WINDOWHEIGHT 
viewportOffset = (0, 0) 
vpStartXTile = 0 
vpStartYTile = 0 
viewportCoord = (0, 0) 

coordX = 0 
coordY = 0 

def main(): 
    global FPSCLOCK, DISPLAYSURF 
    global coordX, coordY 
    global offsetX, offsetY, negativeOffsetX, negativeOffsetY 
    global movedDistanceX, movedDistanceY 
    global isDragging 

    DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT)) 

    mouseX = 0 
    mouseY = 0 

    generateGrid(GRIDSIZE, GRIDSIZE) 

    isDragging = False 
    mousePos = (0, 0) 
    dragStart = (0,0) 
    dragEnd = (0,0) 

    pygame.font.init() 
    arialFnt = pygame.font.SysFont('Arial', 16) 
    while True: 
     DISPLAYSURF.fill(BGCOLOR) 

     for event in pygame.event.get(): 
      if event.type == QUIT: 
       pygame.quit() 
       sys.exit() 
      if event.type == MOUSEBUTTONDOWN: 
       if event.button == 2: 
        isDragging = True 
       elif event.button == 4: 
        zoomIn() 
       elif event.button == 5: 
        zoomOut() 
      elif event.type == MOUSEMOTION: 
       mouseRel = pygame.mouse.get_rel() 
       moveGrid(mouseRel) 
      elif event.type == MOUSEBUTTONUP: 
       isDragging = False 

     viewportCoord = (coordX, coordY) 

     vpStartXTile = math.floor(float(viewportCoord[0]/TILESIZE)) 
     vpStartYTile = math.floor(float(viewportCoord[1]/TILESIZE)) 
     GRIDstartTile = GRID[vpStartXTile][vpStartYTile] 

     negativeOffsetX = viewportCoord[0] - GRID[vpStartXTile][vpStartYTile][0] 
     negativeOffsetY = viewportCoord[1] - GRID[vpStartXTile][vpStartYTile][1] 

     offsetX = TILESIZE - negativeOffsetX 
     offsetY = TILESIZE - negativeOffsetY 

     repeatX = math.floor(WINDOWWIDTH/TILESIZE) 
     repeatY = math.floor(WINDOWHEIGHT/TILESIZE) 

     drawGrid(repeatX, repeatY) 

     outputLabel = arialFnt.render('(Top-Left)Coordinates: x%s - y%s' % (coordX, coordY), 1, (255,255,255)) 
     DISPLAYSURF.blit(outputLabel, (10, 10)) 

     # frame draw 
     pygame.display.set_caption("Memory Game - FPS: %.0f" % FPSCLOCK.get_fps()) 
     pygame.display.flip() 
     pygame.display.update() 
     FPSCLOCK.tick(FPS) 



def generateGrid(xTiles=None, yTiles=None): 
    global GRID 

    GRID = [] 

    for i in range(xTiles): 
     GRID.append([None] * yTiles) 

    ix = 0 
    iy = 0 

    posX = -40 

    for x in range(len(GRID[ix])): 
     posX += TILESIZE 
     posY = -40 
     iy = 0 
     for y in range(xTiles): 
      posY += TILESIZE 
      position = (posX, posY) 
      GRID[ix][iy] = position 
      iy += 1 
     if ix < xTiles: 
      ix += 1 
     else: 
      return 

def drawGrid(x=None, y=None): 
    lineWidth = 1 

    xPos = 0 
    yPos = 0 

    for i in range(x): 
     xStart = (xPos + offsetX, 0) 
     xEnd = (xPos + offsetX, WINDOWHEIGHT + negativeOffsetY) 
     pygame.draw.line(DISPLAYSURF, FGCOLOR, xStart, xEnd, lineWidth) 
     xPos += TILESIZE 

    for i in range(y): 
     yStart = (0, yPos + offsetY) 
     yEnd = (WINDOWWIDTH + negativeOffsetX, yPos + offsetY) 
     pygame.draw.line(DISPLAYSURF, FGCOLOR, yStart, yEnd, lineWidth) 
     yPos += TILESIZE 

def moveGrid(rel): 
    global coordX, coordY, isDragging 


    if isDragging == True: 
     #X 
     if coordX <= maxVPcoordX and coordX >= minVPcoordX: 
      coordX = coordX - rel[0] 
      if coordX > maxVPcoordX: 
       coordX = maxVPcoordX 
      if coordX < minVPcoordX: 
       coordX = 0 
     #Y 
     if coordY <= maxVPcoordY and coordY >= minVPcoordY: 
      coordY = coordY - rel[1] 
      if coordY > maxVPcoordY: 
       coordY = maxVPcoordY 
      elif coordY < minVPcoordY: 
       coordY = 0 
    #------------- 



def zoomIn(): 
    global TILESIZE, maxVPcoordX, maxVPcoordY 

    TILESIZE += 4 

    print("Tile size: ", TILESIZE) 

    generateGrid(GRIDSIZE, GRIDSIZE) 

    maxVPcoordX = (TILESIZE*GRIDSIZE)-WINDOWWIDTH 
    maxVPcoordY = (TILESIZE*GRIDSIZE)-WINDOWHEIGHT 


def zoomOut(): 
    global TILESIZE, maxVPcoordX, maxVPcoordY 

    TILESIZE -= 4 
    if TILESIZE <= 0: 
     TILESIZE = 4 

    print("Tile size: ", TILESIZE) 

    generateGrid(GRIDSIZE, GRIDSIZE) 

    maxVPcoordX = (TILESIZE*GRIDSIZE)-WINDOWWIDTH 
    maxVPcoordY = (TILESIZE*GRIDSIZE)-WINDOWHEIGHT 

main()  
+0

請記住,你可以接受你自己的答案,以便將來看到這個問題的同一個問題的人會看到問題是如何解決的。 – Haz

+0

對於未來的訪問者,以下是代碼之間的差異(因爲該帖子實際上沒有提及更改內容和解決方案):https://www.diffchecker.com/QzypNclW – Luc