2013-05-14 59 views
2

我正在用pygame做一個平臺遊戲,我想給它添加重力。 現在我只有一張當我按下箭頭鍵時會移動的圖片,而我的下一步將是重力。這裏是我的代碼:pygame中的重力

import pygame, sys 
from pygame.locals import * 

pygame.init() 

FPS = 30 
fpsClock = pygame.time.Clock() 

DISPLAYSURF = pygame.display.set_mode((400, 300), 0, 32) 
pygame.display.set_caption("Jadatja") 

WHITE = (255, 255, 255) 
catImg = pygame.image.load("images/cat.png") 
catx = 10 
caty = 10 
movingRight = False 
movingDown = False 
movingLeft = False 
movingUp = False 

while True: #main game loop 

    #update 
    for event in pygame.event.get(): 
    if event.type == KEYDOWN: 
     if event.key == K_RIGHT: 
      #catx += 5 
      movingRight = True 
      movingLeft = False 
     elif event.key == K_DOWN: 
      #caty += 5 
      movingDown = True 
      movingUp = False 
     elif event.key == K_LEFT: 
      #catx -= 5 
      movingLeft = True 
      movingRight = False 
     elif event.key == K_UP: 
      #caty -= 5 
      movingUp = True 
      movingDown = False 

    if event.type == KEYUP: 
     if event.key == K_RIGHT: 
      movingRight = False 
     if event.key == K_DOWN: 
      movingDown = False 
     if event.key == K_LEFT: 
      movingLeft = False 
     if event.key == K_UP: 
      movingUp = False 


    #actually make the player move 
    if movingRight == True: 
     catx += 5 
    if movingDown == True: 
     caty += 5 
    if movingLeft == True: 
     catx -= 5 
    if movingUp == True: 
     caty -= 5 


    #exit 
    for event in pygame.event.get(): 
     if event.type == KEYUP: 
      if event.key == K_ESCAPE: 
       pygame.quit() 
       sys.exit() 

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

    #draw 
    DISPLAYSURF.fill(WHITE) 
    DISPLAYSURF.blit(catImg, (catx, caty)) 



    pygame.display.update() 
    fpsClock.tick(FPS) 

我不是100%肯定,如果我認爲是這樣的代碼是光滑的,但我希望你們能做出什麼事情。

感謝

+0

你嘗試過什麼到目前爲止實現重力?當精靈被認爲是「在空中」的時候,引力的「你好世界」就會通過應用負面的東西來工作。但我重申,到目前爲止您嘗試過什麼? – Tadgh

回答

4

a tutorial創建一個反彈球,我認爲可能對您有所幫助。

現在,添加重力到模擬,你的每一次循環簡單地增加一些額外的速度在y方向:

speed[1] += gravity 

是一種愚蠢的,但是你結了什麼,由於圖像快速下降的窗口的底部之下永遠不會再看到:)因此

下一步是夾球的位置,所以它必須留在窗口:

import os 
import sys, pygame 
pygame.init() 

size = width, height = 320, 240 
speed = [1, 1] 
black = 0, 0, 0 
gravity = 0.1 

screen = pygame.display.set_mode(size) 

image_file = os.path.expanduser("~/pybin/pygame_examples/data/ball.png") 
ball = pygame.image.load(image_file) 
ballrect = ball.get_rect() 

def clip(val, minval, maxval): 
    return min(max(val, minval), maxval) 

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

    speed[1] += gravity 

    ballrect = ballrect.move(speed) 
    if ballrect.left < 0 or ballrect.right > width: 
     speed[0] = -speed[0] 
    if ballrect.top < 0 or ballrect.bottom > height: 
     speed[1] = -speed[1] 

    # clip the position to remain in the window 

    ballrect.left = clip(ballrect.left, 0, width) 
    ballrect.right = clip(ballrect.right, 0, width)   
    ballrect.top = clip(ballrect.top, 0, height) 
    ballrect.bottom = clip(ballrect.bottom, 0, height) 

    screen.fill(black) 
    screen.blit(ball, ballrect) 
    pygame.display.flip() 

好的,現在你可以將它結合到你當前的代碼中,你將會關閉並運行。但是,有些事情可以使代碼更有組織,重複性更低。

例如,請考慮下面

for event in pygame.event.get(): 

大量if...then塊你可以把它改寫爲這樣的:

delta = { 
    pygame.K_LEFT: (-20, 0), 
    pygame.K_RIGHT: (+20, 0), 
    pygame.K_UP: (0, -20), 
    pygame.K_DOWN: (0, +20), 
    } 
for event in pygame.event.get(): 
    if event.type == pygame.KEYDOWN: 
     deltax, deltay = delta.get(event.key, (0, 0)) 
     ball.speed[0] += deltax 
     ball.speed[1] += deltay 

你也可以從投入與運動相關聯的所有邏輯受益您的圖像合併爲一類:

class Ball(pygame.sprite.Sprite): 
    def __init__(self): 
     pygame.sprite.Sprite.__init__(self) 
     self.image = pygame.image.load(image_file) 
     self.rect = self.image.get_rect() 
     self.speed = [0, 0] 
     area = pygame.display.get_surface().get_rect() 
     self.width, self.height = area.width, area.height 

    def update(self): 
     self.rect = self.rect.move(self.speed) 
     if self.rect.left < 0 or self.rect.right > self.width: 
      self.speed[0] = -self.speed[0] 
     if self.rect.top < 0 or self.rect.bottom > self.height: 
      self.speed[1] = -self.speed[1] 
     self.rect.left = clip(self.rect.left, 0, self.width) 
     self.rect.right = clip(self.rect.right, 0, self.width)   
     self.rect.top = clip(self.rect.top, 0, self.height) 
     self.rect.bottom = clip(self.rect.bottom, 0, self.height)     

注意方法與本教程提供的代碼非常相似。創建一個Ball類的好處之一是,程序的其餘部分不需要知道Ball如何移動。所有的邏輯在Ball.update。而且,它可以很容易地實例化許多球。而且你可以創建其他類型不同的類(飛機,鳥類,槳等),並將它們相對無痛地添加到你的模擬中。

所以,把他們放在一起,你最終會得到這樣的:


""" 
http://stackoverflow.com/a/15459868/190597 (unutbu) 
Based on http://www.pygame.org/docs/tut/intro/intro.html 
Draws a red ball bouncing around in the window. 
Pressing the arrow keys moves the ball 
""" 

import sys 
import pygame 
import os 


image_file = os.path.expanduser("~/pybin/pygame_examples/data/ball.png") 

delta = { 
    pygame.K_LEFT: (-20, 0), 
    pygame.K_RIGHT: (+20, 0), 
    pygame.K_UP: (0, -20), 
    pygame.K_DOWN: (0, +20), 
    } 

gravity = +1 

class Ball(pygame.sprite.Sprite): 
    def __init__(self): 
     pygame.sprite.Sprite.__init__(self) 
     self.image = pygame.image.load(image_file) 
     self.rect = self.image.get_rect() 
     self.speed = [0, 0] 
     area = pygame.display.get_surface().get_rect() 
     self.width, self.height = area.width, area.height 

    def update(self): 
     self.rect = self.rect.move(self.speed) 
     if self.rect.left < 0 or self.rect.right > self.width: 
      self.speed[0] = -self.speed[0] 
     if self.rect.top < 0 or self.rect.bottom > self.height: 
      self.speed[1] = -self.speed[1] 
     self.rect.left = clip(self.rect.left, 0, self.width) 
     self.rect.right = clip(self.rect.right, 0, self.width)   
     self.rect.top = clip(self.rect.top, 0, self.height) 
     self.rect.bottom = clip(self.rect.bottom, 0, self.height)     

def clip(val, minval, maxval): 
    return min(max(val, minval), maxval) 

class Main(object): 
    def __init__(self): 
     self.setup() 
    def setup(self): 
     pygame.init() 
     size = (self.width, self.height) = (640,360) 
     self.screen = pygame.display.set_mode(size, 0, 32) 
     self.ball = Ball() 
     self.setup_background() 
    def setup_background(self): 
     self.background = pygame.Surface(self.screen.get_size()) 
     self.background = self.background.convert() 
     self.background.fill((0, 0, 0)) 
     self.screen.blit(self.background, (0, 0)) 
     pygame.display.flip() 
    def draw(self): 
     self.screen.blit(self.background, (0, 0)) 
     self.screen.blit(self.ball.image, self.ball.rect) 
     pygame.display.flip() 
    def event_loop(self): 
     ball = self.ball 
     friction = 1 
     while True: 
      for event in pygame.event.get(): 
       if ((event.type == pygame.QUIT) or 
        (event.type == pygame.KEYDOWN and 
        event.key == pygame.K_ESCAPE)): 
        sys.exit() 
       elif event.type == pygame.KEYDOWN: 
        deltax, deltay = delta.get(event.key, (0, 0)) 
        ball.speed[0] += deltax 
        ball.speed[1] += deltay 
        friction = 1 
       elif event.type == pygame.KEYUP: 
        friction = 0.99 

      ball.speed = [friction*s for s in ball.speed] 
      ball.speed[1] += gravity 
      ball.update() 
      self.draw() 
      pygame.time.delay(10) 

if __name__ == '__main__': 
    app = Main() 
    app.event_loop()