多年前写过一篇 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 摩擦力与屏幕环绕的更多相关文章

  1. JavaScript:学习笔记(10)——XMLHttpRequest对象

    JavaScript:学习笔记(10)——XMLHttpRequest对象 XHR对象 使用XMLHttpRequest (XHR)对象可以与服务器交互.您可以从URL获取数据,而无需让整个的页面刷新 ...

  2. Spring 源码学习笔记10——Spring AOP

    Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...

  3. 操作系统概念学习笔记 10 CPU调度

    操作系统概念学习笔记 10 CPU调度 多道程序操作系统的基础.通过在进程之间切换CPU.操作系统能够提高计算机的吞吐率. 对于单处理器系统.每次仅仅同意一个进程执行:不论什么其它进程必须等待,直到C ...

  4. thinkphp学习笔记10—看不懂的路由规则

    原文:thinkphp学习笔记10-看不懂的路由规则 路由这部分貌似在实际工作中没有怎么设计过,只是在用默认的设置,在手册里面看到部分,艰涩难懂. 1.路由定义 要使用路由功能需要支持PATH_INF ...

  5. 《C++ Primer Plus》学习笔记10

    <C++ Primer Plus>学习笔记10 <<<<<<<<<<<<<<<<<&l ...

  6. SQL反模式学习笔记10 取整错误

    目标:使用小数取代整数 反模式:使用Float类型 根据IEEE754标识,float类型使用二进制格式编码实数数据. 缺点:(1)舍入的必要性: 并不是所有的十进制中描述的信息都能使用二进制存储,处 ...

  7. 安装好ubuntu 18.10之后,屏幕一直在自动旋转,怎么办?

    sudo apt-get install okular dia gimp Gparted sudo add-apt-repository universesudo apt install gnome- ...

  8. JAVA自学笔记10

    JAVA自学笔记10 1.形式参数与返回值 1)类名作为形式参数(基本类型.引用类型) 作形参必须是类的对象 2)抽象类名作形参 需要该抽象类的子类对象,通过多态实现 3)接口名为形参 需要的是该接口 ...

  9. golang学习笔记10 beego api 用jwt验证auth2 token 获取解码信息

    golang学习笔记10 beego api 用jwt验证auth2 token 获取解码信息 Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放 ...

随机推荐

  1. [SDOI2018]荣誉称号

    题解: 并不需要什么算法 首先我们随便画一画就会发现 能画出一颗满二叉树 然后要满足每个点从上往下的路径和都相同(%m意义下) 一个点上可能对应了多个点 然后这样我们可以暴力dp $2^k*m^2+n ...

  2. net core体系-web应用程序-4asp.net core2.0 项目实战(1)-9项目各种全局帮助类

    本文目录 1.  前沿2.CacheHelper基于Microsoft.Extensions.Caching.Memory封装3.XmlHelper快速操作xml文档4.SerializationHe ...

  3. Codeforces 781E Andryusha and Nervous Barriers 线段树 单调栈

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF781E.html 题目传送门 - CF781E 题意 有一个矩形,宽为 w ,高为 h .一开始会有 w 个 ...

  4. java生成二维码并融合模板工具类

    二维码融合模板 二维码融合图片 import java.awt.AlphaComposite; import java.awt.Graphics2D; import java.awt.Image; i ...

  5. PAT (Basic Level) Practise - 继续(3n+1)猜想

    题目链接:https://www.patest.cn/submissions/4414905 1005. 继续(3n+1)猜想 (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限 ...

  6. vue文字跑马灯效果

    https://cdn.bootcss.com/jQuery.Marquee/1.5.0/jquery.marquee.js 兼容vue $("#demo4").marquee({ ...

  7. 博客第一篇 osi七层网络传输模型

  8. Vuejs学习笔记(一)

    1)    vue.js 的 主要功能 1.模板渲染 2.模块化 3.扩展功能:路由,Ajax 2)    vue.js 模板渲染之双向绑定示例 message 绑定到了 input 对象,所有在in ...

  9. DRF 权限 频率

    DRF的权限 权限是什么 大家之前都应该听过权限~那么我们权限到底是做什么用的呢~~ 大家都有博客~或者去一些论坛~一定知道管理员这个角色~ 比如我们申请博客的时候~一定要向管理员申请~也就是说管理员 ...

  10. [python] 查询mysql返回datetime类型数据的处理

    Python 查询Mysql,如果是datetime类型,在json序列化的时候会出现问题. 在网上查了一下,解决方案基本都是遍历dict数据,如果是datetime则转化为字符串. from dat ...