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的开放 ...
随机推荐
- Python hasattr,getattr,setattr,delattr
#!/usr/bin/env python # -*- coding:utf-8 -*- # 作者:Presley # 邮箱:1209989516@qq.com # 时间:2018-11-04 # 反 ...
- k8s 相关命令
kompose convert -f docker-compose-pro.yml k8s数据卷挂载: https://blog.csdn.net/wlhdo71920145/article/deta ...
- Cookies 和 Session的区别
1.cookie 是一种发送到客户浏览器的文本串句柄,并保存在客户机硬盘上,可以用来在某个WEB站点会话间持久的保持数据. 2.session其实指的就是访问者从到达某个特定主页到离开为止的那段时间. ...
- js拷贝
现在有一个对象 var obj = { name: '隔壁老王', age: 60, sex: 'male' } 我们现在想把obj里的每一个属性拷贝到一个空对象var obj1 = {}中,那么需要 ...
- BZOJ2527 [Poi2011]Meteors 整体二分 树状数组
原文链接http://www.cnblogs.com/zhouzhendong/p/8686460.html 题目传送门 - BZOJ2527 题意 有$n$个国家. 太空里有$m$个太空站排成一个圆 ...
- Shell工具| 流程控制
1. 流程控制 if 判断 ()[ 条件判断式 ],中括号和条件判断式之间必须有空格 ()if后要有空格 [kris@hadoop datas]$ vim if.sh #!/bin/bash -eq ...
- 20165235 Java第一周学习总结
(# 20165235 Java第一周学习总结 Ubuntu下git的安装与使用 首先Ubuntu下git的安装,使用sudo apt-get install git下载Ubuntu,下载完成后可以用 ...
- Team Queue POJ - 2259 (队列)
Queues and Priority Queues are data structures which are known to most computer scientists. The Team ...
- hdu 2181 哈密顿绕行世界问题【DFS】
题目链接 题目大意: Problem Description 一个规则的实心十二面体,它的 20个顶点标出世界著名的20个城市,你从一个城市出发经过每个城市刚好一次后回到出发的城市. Input ...
- Stm32基础
Stm32基础 目录 常用功能函数 跑马灯实验 蜂鸣器实验 按键实验 端口复用与重映射 常用功能函数 初始化gpio函数 作用:初始化一个或者多个io口(同一组)的工作方式和速度该函数主要是操作GPI ...