pygame 笔记-10 摩擦力与屏幕环绕
多年前写过一篇 Flash/Flex学习笔记(25):摩擦力与屏幕环绕,可惜的当时上传的flash,服务器后来无人维护,现在flash链接都失效了。本篇用pygame重新实现了一个:
原理是类似,但要注意的是:pygame中旋转的角度采用逆时针系统 ,即:逆时针方向旋转,角度为正,反之为负。所以在外理角度时,y轴方向的速度要取反。
素材图(2张):
飞船熄火
飞船点火
需求:按向上键点火,飞船启动,一直加速;无按键时,飞船熄火,速度慢慢降下来(设置摩擦系数);左右键控制转向;飞出屏幕时,从另一侧切回来。
代码:
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()
如果把背景变成黑色,辅助边框去掉,看上去更有漆黑宇宙的感觉:)
源代码地址: https://github.com/yjmyzz/pygame_tutorial/blob/master/move_02.py
作者:菩提树下的杨过
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。