天天看點

pygame 筆記-10 摩擦力與螢幕環繞

pygame 筆記-10 摩擦力與螢幕環繞

多年前寫過一篇 Flash/Flex學習筆記(25):摩擦力與螢幕環繞,可惜的當時上傳的flash,伺服器後來無人維護,現在flash連結都失效了。本篇用pygame重新實作了一個:

pygame 筆記-10 摩擦力與螢幕環繞

原理是類似,但要注意的是:pygame中旋轉的角度采用逆時針系統 ,即:逆時針方向旋轉,角度為正,反之為負。是以在外理角度時,y軸方向的速度要取反。

素材圖(2張):

飛船熄火

pygame 筆記-10 摩擦力與螢幕環繞

飛船點火

pygame 筆記-10 摩擦力與螢幕環繞

需求:按向上鍵點火,飛船啟動,一直加速;無按鍵時,飛船熄火,速度慢慢降下來(設定摩擦系數);左右鍵控制轉向;飛出螢幕時,從另一側切回來。

代碼:

pygame 筆記-10 摩擦力與螢幕環繞
pygame 筆記-10 摩擦力與螢幕環繞
1 import os
  2 import pygame
  3 import sys
  4 import math
  5 
  6 pygame.init()
  7 
  8 clock = pygame.time.Clock()
  9 
 10 SIZE = WIDTH, HEIGHT = 400, 400
 11 GRAY = (200, 200, 200)
 12 RED = (255, 0, 0)
 13 screen = pygame.display.set_mode(SIZE)
 14 pygame.display.set_caption("ship")
 15 img_base_path = os.getcwd() + '/img/'
 16 
 17 
 18 class Ship(object):
 19     def __init__(self, img_base_path, screen):
 20         self.vx = 0
 21         self.vy = 0
 22         # 旋轉角速度
 23         self.vr = 0
 24         # 推進力
 25         self.thrust = 0
 26         self.angle = 0
 27         self.show_flame = False
 28         self.scale = 1.0
 29         # 是否顯示輔助邊框
 30         self.show_rect = False
 31 
 32         self.img_src = pygame.image.load(img_base_path + 'ship.png')
 33         self.img_flame_src = pygame.image.load(img_base_path + 'ship_flame.png')
 34 
 35         self.img = self.img_src
 36         self.rect = self.img_src.get_rect()
 37 
 38         self.img_new = self.img
 39         self.rect_new = self.img_new.get_rect()
 40 
 41         self.rect = self.rect.move((WIDTH - self.rect.width) * 0.5, (HEIGHT - self.rect.height) * 0.5)
 42 
 43     def draw(self, screen):
 44         screen.blit(self.img_new, self.rect_new)
 45         if self.show_rect:
 46             pygame.draw.rect(screen, GRAY, ship.rect, 1)
 47             pygame.draw.rect(screen, RED, ship.rect_new, 1)
 48 
 49     def move(self):
 50         self.rect = self.rect.move(self.vx, self.vy)
 51         self.rect_new = self.rect_new.move(self.vx, self.vy)
 52         # 向左飛出邊界
 53         if self.rect_new.right < 0 and ship.vx < 0:
 54             self.rect_new.left = WIDTH
 55             self.rect.left = WIDTH
 56         # 向右飛出邊界
 57         if self.rect_new.left > WIDTH and ship.vx > 0:
 58             self.rect_new.right = 0
 59             self.rect.right = 0
 60         # 向下飛出邊界
 61         if self.rect_new.top > HEIGHT and ship.vy > 0:
 62             self.rect_new.bottom = 0
 63             self.rect.bottom = 0
 64         # 向上飛出邊界
 65         if self.rect_new.bottom < 0 and ship.vy < 0:
 66             self.rect_new.top = HEIGHT
 67             self.rect.top = HEIGHT
 68 
 69     def rotate_zoom(self):
 70         # rotozoom=旋轉+縮放
 71         self.img_new = pygame.transform.rotozoom(self.img, self.angle, self.scale)
 72         self.rect_new = self.img_new.get_rect(center=self.rect.center)
 73         if math.fabs(self.angle) == 360:
 74             self.angle = 0
 75 
 76     def set_flame(self, show_flame=False):
 77         self.show_flame = show_flame
 78         if self.show_flame:
 79             self.img = self.img_flame_src
 80         else:
 81             self.img = self.img_src
 82 
 83 
 84 def get_speed(speed):
 85     if speed > 0:
 86         return math.ceil(speed)
 87     if speed < 0:
 88         return math.floor(speed)
 89     return speed
 90 
 91 
 92 ship = Ship(img_base_path, screen)
 93 ship.scale = 0.5
 94 ship.show_rect = True
 95 # 摩擦系數
 96 friction = 0.995
 97 while True:
 98     clock.tick(60)
 99 
100     for event in pygame.event.get():
101         if event.type == pygame.QUIT:
102             sys.exit()
103         elif event.type == pygame.KEYUP:
104             # KEYUP時,熄火,動力歸0
105             ship.vr = 0
106             ship.thrust = 0
107             ship.set_flame(False)
108         elif event.type == pygame.KEYDOWN:
109             keys = pygame.key.get_pressed()
110             if keys[pygame.K_LEFT]:
111                 ship.vr = 5
112             elif keys[pygame.K_RIGHT]:
113                 ship.vr = -5
114             if keys[pygame.K_UP]:
115                 # 按向上鍵時,點火,動力為0.3
116                 ship.set_flame(True)
117                 ship.thrust = 0.3
118             else:
119                 ship.set_flame(False)
120 
121     # 将每一幀的底色先填充成白色
122     screen.fill((255, 255, 255))
123 
124     pygame.draw.line(screen, GRAY, (0, HEIGHT / 2), (WIDTH, HEIGHT / 2), 1)
125     pygame.draw.line(screen, GRAY, (WIDTH / 2, 0), (WIDTH / 2, HEIGHT), 1)
126 
127     ship.angle += ship.vr
128     ax = math.cos(ship.angle * math.pi / 180) * ship.thrust
129     # 注:pygame中,角度是逆時針轉的,是以垂直加速度要取反
130     ay = -1 * math.sin(ship.angle * math.pi / 180) * ship.thrust
131     ship.vx += ax
132     ship.vy += ay
133 
134     # 摩擦系數
135     if math.fabs(ship.vx) > 0.001:
136         ship.vx = ship.vx * friction
137     if math.fabs(ship.vy) > 0.001:
138         ship.vy = ship.vy * friction
139 
140     print("vx:", ship.vx)
141 
142     ship.rotate_zoom()
143     ship.move()
144     ship.draw(screen)
145 
146     # 更新畫布
147     pygame.display.update()      

View Code

如果把背景變成黑色,輔助邊框去掉,看上去更有漆黑宇宙的感覺:)

源代碼位址: ​​https://github.com/yjmyzz/pygame_tutorial/blob/master/move_02.py​​

作者:​​菩提樹下的楊過​​

本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。