pygame 笔记-10 摩擦力与屏幕环绕
多年前写过一篇 Flash/Flex学习笔记(25):摩擦力与屏幕环绕,可惜的当时上传的flash,服务器后来无人维护,现在flash链接都失效了。本篇用pygame重新实现了一个:
原理是类似,但要注意的是:pygame中旋转的角度采用逆时针系统 ,即:逆时针方向旋转,角度为正,反之为负。所以在外理角度时,y轴方向的速度要取反。
素材图(2张):
飞船熄火
飞船点火
需求:按向上键点火,飞船启动,一直加速;无按键时,飞船熄火,速度慢慢降下来(设置摩擦系数);左右键控制转向;飞出屏幕时,从另一侧切回来。
代码:
import os
import pygame
import sys
import math pygame.init() clock = pygame.time.Clock() SIZE = WIDTH, HEIGHT = 400, 400
GRAY = (200, 200, 200)
RED = (255, 0, 0)
screen = pygame.display.set_mode(SIZE)
pygame.display.set_caption("ship")
img_base_path = os.getcwd() + '/img/' class Ship(object):
def __init__(self, img_base_path, screen):
self.vx = 0
self.vy = 0
# 旋转角速度
self.vr = 0
# 推进力
self.thrust = 0
self.angle = 0
self.show_flame = False
self.scale = 1.0
# 是否显示辅助边框
self.show_rect = False self.img_src = pygame.image.load(img_base_path + 'ship.png')
self.img_flame_src = pygame.image.load(img_base_path + 'ship_flame.png') self.img = self.img_src
self.rect = self.img_src.get_rect() self.img_new = self.img
self.rect_new = self.img_new.get_rect() self.rect = self.rect.move((WIDTH - self.rect.width) * 0.5, (HEIGHT - self.rect.height) * 0.5) def draw(self, screen):
screen.blit(self.img_new, self.rect_new)
if self.show_rect:
pygame.draw.rect(screen, GRAY, ship.rect, 1)
pygame.draw.rect(screen, RED, ship.rect_new, 1) def move(self):
self.rect = self.rect.move(self.vx, self.vy)
self.rect_new = self.rect_new.move(self.vx, self.vy)
# 向左飞出边界
if self.rect_new.right < 0 and ship.vx < 0:
self.rect_new.left = WIDTH
self.rect.left = WIDTH
# 向右飞出边界
if self.rect_new.left > WIDTH and ship.vx > 0:
self.rect_new.right = 0
self.rect.right = 0
# 向下飞出边界
if self.rect_new.top > HEIGHT and ship.vy > 0:
self.rect_new.bottom = 0
self.rect.bottom = 0
# 向上飞出边界
if self.rect_new.bottom < 0 and ship.vy < 0:
self.rect_new.top = HEIGHT
self.rect.top = HEIGHT def rotate_zoom(self):
# rotozoom=旋转+缩放
self.img_new = pygame.transform.rotozoom(self.img, self.angle, self.scale)
self.rect_new = self.img_new.get_rect(center=self.rect.center)
if math.fabs(self.angle) == 360:
self.angle = 0 def set_flame(self, show_flame=False):
self.show_flame = show_flame
if self.show_flame:
self.img = self.img_flame_src
else:
self.img = self.img_src def get_speed(speed):
if speed > 0:
return math.ceil(speed)
if speed < 0:
return math.floor(speed)
return speed ship = Ship(img_base_path, screen)
ship.scale = 0.5
ship.show_rect = True
# 摩擦系数
friction = 0.995
while True:
clock.tick(60) for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYUP:
# KEYUP时,熄火,动力归0
ship.vr = 0
ship.thrust = 0
ship.set_flame(False)
elif event.type == pygame.KEYDOWN:
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
ship.vr = 5
elif keys[pygame.K_RIGHT]:
ship.vr = -5
if keys[pygame.K_UP]:
# 按向上键时,点火,动力为0.3
ship.set_flame(True)
ship.thrust = 0.3
else:
ship.set_flame(False) # 将每一帧的底色先填充成白色
screen.fill((255, 255, 255)) pygame.draw.line(screen, GRAY, (0, HEIGHT / 2), (WIDTH, HEIGHT / 2), 1)
pygame.draw.line(screen, GRAY, (WIDTH / 2, 0), (WIDTH / 2, HEIGHT), 1) ship.angle += ship.vr
ax = math.cos(ship.angle * math.pi / 180) * ship.thrust
# 注:pygame中,角度是逆时针转的,所以垂直加速度要取反
ay = -1 * math.sin(ship.angle * math.pi / 180) * ship.thrust
ship.vx += ax
ship.vy += ay # 摩擦系数
if math.fabs(ship.vx) > 0.001:
ship.vx = ship.vx * friction
if math.fabs(ship.vy) > 0.001:
ship.vy = ship.vy * friction print("vx:", ship.vx) ship.rotate_zoom()
ship.move()
ship.draw(screen) # 更新画布
pygame.display.update()
如果把背景变成黑色,辅助边框去掉,看上去更有漆黑宇宙的感觉:)
源代码地址: https://github.com/yjmyzz/pygame_tutorial/blob/master/move_02.py
pygame 笔记-10 摩擦力与屏幕环绕的更多相关文章
- JavaScript:学习笔记(10)——XMLHttpRequest对象
JavaScript:学习笔记(10)——XMLHttpRequest对象 XHR对象 使用XMLHttpRequest (XHR)对象可以与服务器交互.您可以从URL获取数据,而无需让整个的页面刷新 ...
- Spring 源码学习笔记10——Spring AOP
Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...
- 操作系统概念学习笔记 10 CPU调度
操作系统概念学习笔记 10 CPU调度 多道程序操作系统的基础.通过在进程之间切换CPU.操作系统能够提高计算机的吞吐率. 对于单处理器系统.每次仅仅同意一个进程执行:不论什么其它进程必须等待,直到C ...
- thinkphp学习笔记10—看不懂的路由规则
原文:thinkphp学习笔记10-看不懂的路由规则 路由这部分貌似在实际工作中没有怎么设计过,只是在用默认的设置,在手册里面看到部分,艰涩难懂. 1.路由定义 要使用路由功能需要支持PATH_INF ...
- 《C++ Primer Plus》学习笔记10
<C++ Primer Plus>学习笔记10 <<<<<<<<<<<<<<<<<&l ...
- SQL反模式学习笔记10 取整错误
目标:使用小数取代整数 反模式:使用Float类型 根据IEEE754标识,float类型使用二进制格式编码实数数据. 缺点:(1)舍入的必要性: 并不是所有的十进制中描述的信息都能使用二进制存储,处 ...
- 安装好ubuntu 18.10之后,屏幕一直在自动旋转,怎么办?
sudo apt-get install okular dia gimp Gparted sudo add-apt-repository universesudo apt install gnome- ...
- JAVA自学笔记10
JAVA自学笔记10 1.形式参数与返回值 1)类名作为形式参数(基本类型.引用类型) 作形参必须是类的对象 2)抽象类名作形参 需要该抽象类的子类对象,通过多态实现 3)接口名为形参 需要的是该接口 ...
- golang学习笔记10 beego api 用jwt验证auth2 token 获取解码信息
golang学习笔记10 beego api 用jwt验证auth2 token 获取解码信息 Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放 ...
随机推荐
- Codeforces 935E Fafa and Ancient Mathematics dp
Fafa and Ancient Mathematics 转换成树上问题dp一下. #include<bits/stdc++.h> #define LL long long #define ...
- 伪分布式hbase从0.94.11版本升级stable的1.4.9版本
Hbase从0.94.11升级到stable的1.4.9版本: 升级思路: hadoop1.1.2 hbase 0.94.11 ↓ had ...
- 解决 js setTimeout 传递带参数的函数无效果
最近 js 用到 setTimeout 递归调用 刷新进度 setTimeout ("getProgress(name,type)", 3000) ; 发现getProgres ...
- HDU2853 Assignment KM
原文链接http://www.cnblogs.com/zhouzhendong/p/8284105.html 题目传送门 - HDU2853 题意概括 (来自谷歌翻译) 题解 这是一道好题. 我们首先 ...
- BigInteger的使用
[构造方法] BigInteger(String val) :将 BigInteger 的十进制字符串表示形式转换为 BigInteger. [常用方法] 1)add(BigInteger val): ...
- SpringBoot统一错误处理
1.处理错误请求页面 import org.springframework.stereotype.Controller; import org.springframework.web.bind.ann ...
- JAVA首次课堂测试总结
暑期生活已经结束,新的学期也已经开始,而暑期放假之前约定的JAVA首次课堂测试也如期的到来,本次测试真的可以学到和多东西,也有很多感想. 首先体会最深的就是系主任所说的软件工程不是那么好学的,真的需要 ...
- 6486: An Ordinary Game(规律)
题目描述 There is a string s of length 3 or greater. No two neighboring characters in s are equal.Takaha ...
- Shell学习之环境变量配置文件(三)
Shell学习之环境变量配置文件 目录 环境变量配置文件简介 环境变量配置文件作用 其他配置文件和登录信息 环境变量配置文件简介 环境变量配置文件简介 环境变量配置文件中主要是定义对系统操作环境生效的 ...
- Misunderstood-Missing-逆向DP
Misunderstood … Missing 记忆深刻......打铁没做出来的题 题意 : 打怪,有 A 的攻击力,有 D 的成长,初始均为 0,有 n 轮. 同时有三个数组 a[1:n],b[1 ...