# 足球小将
# 足球小将(一)
# 课程目标
通过趣味练习,来强化对于 JavaScript 的熟悉
练习如何对于问题进行抽象,应用面向对象或者各种设计模式进行问题的解决
# 创建一个足球场
需求
通过 Canvas 或者 SVG 绘制一片绿色矩形,就像是我们从高空俯视绿色草坪足球场看见的一样。
有余力的同学,可以把足球场上的各种边线画上。
设计
应用工厂模式,设计一个生成足球场的类
足球场包括长度,宽度的属性,长度宽度创建时候以模拟真实单位的“米”为参数,同时以容器宽度和高度进行对应换算。
验证 在不同像素高宽的容器中生成同样长宽米的球场,看球场是否进行了对应的自适应变换
在同样像素高宽的容器中,生成不同长宽米的球场
# 创建一个足球运动员
需求
通过 Canvas 或者 SVG 或者 DOM 创建一个足球运动员。
我们将足球运动员抽象为一个实心圆,不需要考虑他的方向问题。
- 参考 (opens new window) 创建球员的时候,需要将球员创建到某个球场中,球员圆形的大小默认为2米,按照和球场的大小进行对应像素的换算。
球员有很多关于足球运动能力的属性,比如速度,力量,技术,射门等等。我们先添加一个属性,叫做速度。
速度 VNum 为一个在1-99范围内的整数,随机生成。对应物理概念可以假设为:
速度值为 99 的,最高速度为 12米每秒
速度值为 1 的,最高速度为 3米每秒
假设速度值和最高速度是线性关系,我们推导出如下公式:
最高速度VMax = 3 + (VNum - 1) * ( 9 / 98 )
# 让球员跑起来
需求
给球员增加一个方法,奔跑,指定一个终止点(相对于球场左上角的米的坐标),球员向那个终止点跑去。
使用上一个需求中的球员速度,以及和球场实际大小进行计算,模拟一个球员奔跑中,球员圆圈移动的动画。
为了测试方便,再给球员设置一个方法,设定球员所在位置,参数为相对于球场左上角的用米为单位的坐标,需要转换为像素
注意:球员不可能一直按着最高速度进行奔跑,球员有起步,加速到全速,到终点后降速的过程
阅读
- 贝塞尔曲线的一些事情 (opens new window)
- cubic-bezier 贝塞尔曲线 CSS3 动画工具 (opens new window)
- 贝塞尔曲线与 CSS3 动画、SVG 和 canvas 的基情 (opens new window)
- JS 模拟 CSS3 动画 贝塞尔曲线 (opens new window)
- css3 动画 常用的贝塞尔曲线 (opens new window)
- CSS3 三次贝塞尔曲线(cubic-bezier) (opens new window)
设计
根据上面的阅读,实现球员的奔跑方法,球员有起步,逐渐加速,全速,到达终点后,再逐渐降速并继续向前再移动一小段距离
验证
- 生成一个速度为 100 的球员,奔跑吧
- 生成一个速度为 1 的球员,奔跑吧
- 生成好多速度随机的球员,一起跑步比赛吧
# 让球员跑得更真实
需求
我们知道,球员跑步速度不仅仅和最高速度有关系,还和体力,爆发力相关
爆发力强,则加速到最快速度会比较快,体力好,坚持在最高速度会比较久
所以给球员增加这两个属性,然后再让大家奔跑看看
设计
爆发力和体力依然用 1-99 范围内的整数来设定,假设有如下物理意义:
爆发力为 99 表示能够在 1 秒就达到最高速度
爆发力为 1 表示需要 4 秒才能达到最高速度
假设爆发力和需要多长时间达到最高速度是线性关系,请自行推导公式
- 体力为 99 表示能够在最高速度上坚持 15 秒
- 体力为 1 表示能够在最高速度上坚持 10 秒 假设体力和能够在最高速度上坚持的时间是线性关系,请自行推导公式
验证
生成不同的怪异数值球员进行比赛吧,也可以根据比赛结果适当调整各种数值的物理计算公式
# 足球小将(二)
# 课程目标
通过趣味练习,来强化对于 JavaScript 的熟悉
持续练习如何对于问题进行抽象,应用面向对象或者各种设计模式进行问题的解决
# 创建一个足球
需求
创建一个足球,用一个圆形表示,足球大小的直径假设为 0.5 米(不太真实,但为了看清),实际显示大小按照球场像素进行对应变化。
足球不妨找一个图片做贴图
足球有一个方法是移动,参数为运动方向、初速度、加速度,先假设足球只在草地平面移动。加速度为全局常量。
验证
创建足球,尝试各种参数的搭配,观察足球在运动场上的运动轨迹。
# 跑向足球
跑向静止的足球
实现运动员跑向足球并停球的行为。
随机生成足球和运动员的位置,然后运动员向足球跑去,直到运动员和足球相接后,运动员和足球停下来
跑向移动的足球
随机生成足球和运动员的位置,并让足球开始移动,接下来让运动员进行一个预判,并开始向足球可能接到的位置跑去,跑的过程中可能需要定期调整运动员奔跑的方向。
# 踢出足球
简单地踢出足球
给足球运动员增加一个踢出足球的方法,参数为期望球运动的方向,期望足球初速度。
我们先简单实现踢出足球的实现,按照给定的参数,踢出足球。
实现以下踢球:
- 球员在球场中心向球门踢出足球
- 球员从小禁区向球场中心踢出足球
- 球员从角球区向点球点踢出足球
- 球员从大禁区角附近,向球门踢出足球
- 球员从本方禁区附近向对方半场边线踢出足球
给球员增加两个属性
现在,我们稍微模拟一下真实情况,我们给球员增加两个属性:技术、力量
技术决定运动员踢球方向的准确性和力量控制的准确性,力量决定踢球的最大速度。
两个属性依然都是 1-99 的正整数。
对于力量的设定可以为:
- 力量为 1 的静止运动员踢出静止足球的最大初速度为 5米/秒
- 力量为 99 的静止运动员踢出静止足球的最大初速度为 50米/秒
- 力量和静止态踢出静止足球的最大初速度为线性关系
- 运动状态的球员可以提升或减小踢出足球的最大初速度,以球员运动方向和踢出足球方向来计算,方向完全相同,加速最大,方向完全相反,减速最大。范围为 -40% 到 40%
对于技术的设定可以为:
- 技术对于方向及力量的控制符合正态分布
- 技术值越低,实际踢出的方向越容易出现和期望方向角度偏离的情况
- 技术值越高,实际踢出的方向越不容易出现和期望方向角度偏离的情况
- 技术值越低,实际踢出的初速度越容易出现和期望初速度偏离的情况,注意实际初速度不能超过最大初速度
- 技术值越高,实际踢出的初速度越不容易出现和期望初速度偏离的情况,注意实际初速度不能超过最大初速度
- 技术值越低,正态分布的方差越大
- 技术高越低,正态分布的方差越小
- 技术值与方差大小可以为线性关系,也可以自定义
阅读
实现具体以下内容
- 在页面中增加一个球员生成器,可以设置球员的各种属性
- 在页面中可填写球员、球的位置
- 在页面中可填写球员的动作及对应参数,然后有按钮进行对应动作执行
# 再复杂一些
我们知道,运动员大部分时候是在运动过程中踢球,不同的角度,运动状态,会导致踢出足球的速度,角度都有偏差
静止地踢静止的球
这是我们上面做的情况,所有参数以运动员自身属性来决定
运动地踢静止的球
运动员的运动方向和球需要踢出的方向的夹角,对于最后实际踢出球的方向及初速度有一定影响,我们假设有以下影响,你也可以根据自己经验重新设定这些影响。当然我们更建议你在页面中实现参数的配置,来动态实现参数的调整,并实时进行预览
- 运动员的运动方向和球需要踢出的方向的夹角,会对方向控制的方差产生一定影响,我们假设夹角为 a(区间为 0° 到 360°)。
- 假设方向影响因子为 b,这个 b 会对计算概率的方差进行一个乘积的影响,即 方差 = 原方差 * b
- 夹角 a 为 0° 时候,b = 1(参考值,可自定)
- 夹角 a 为 180° 时候,b = 2(参考值,可自定)
- a 与 b 可以为线性关系
- 对力量的控制同理
静止地踢运动的球
有时候踢侧面来的球,踢出的球大概率会有一个原始方向的偏移,所以球的运动方向也会对踢出球的方向有影响,我们假设影响如下
- 球原本运动的方向和踢出足球的方向的夹角为 a(区间为 0° 到 360°),踢出方向的正态分布概率密度函数均值 μ 会因为 a 而产生向球运动的方向进行一定量的偏移 c
- 当 a 为 0° 或者 180° 时,踢出的期望方向不受球的运动方向影响,c 为 0
- 当 a 为 90° 或者 270° 时,踢出的期望方向最受球的运动方向影响,c 为偏 30°对应的偏差(参考值,可自定)
- a 与 c 可以为线性关系
- 计算出 c 后,是否真实产生偏差,还和球员技术相关,根据球员技术,根据正态分布,计算出不会出现偏差 c 的概率,最后实际出现的偏差为 c * (1 - 不会出现偏差的概率)。所以,当球员技术很好时,c 大概率为 0,或者是个极小值,对最后方向影响最小。
运动地踢运动的球
结合上面两者,进行最复杂的踢球的实现,运动的球员踢出运动的球。
实现各种参数的可视化配置,然后不断调参,找到最模拟真实的参数配置吧。
# 足球小将(三)
# 课程目标
通过趣味练习,来强化对于 JavaScript 的熟悉
持续练习如何对于问题进行抽象,应用面向对象或者各种设计模式进行问题的解决
# 课程描述
我们在前两个子任务中完成了运动员的运动,足球的运动,接下来我们来实现具体的足球运动的行为。
# 踢球行为
停球
停球,就是将运动向自己的足球控制在自己的一定范围内。
将上一任务中的踢球封装为父类,停球继承踢球。
我们定义停球的行为,是将足球踢向一个距离自己很近的位置,甚至距离为0。比如:
- 球员在原地停球时,需要将球停到自己脚下
- 球员在前插奔跑中停球,需要将球停到自己奔跑方向 2 米远的地方,便于下一步射门
- 球员在摆脱防守队员中停球,有时候需要将球停到自己当前方向反方向 1 米远的地方,便于摆脱
为了简化需求,我们将停球动作抽象为以下规则:
- 当球员静止时,球停在原地
- 当球员运动时,球停到 1 秒后球员在的位置
传球
传球就是将球传给另外一个运动员,依然是继承踢球的父类
最简单的传球,就是看目标运动员在哪里,然后传给他,但在实际比赛中,我们往往会把球传给目标运动员的运动方向,或者躲开防守队员,将球传到空档区域。
为了简化需求,我们将传球抽象为以下规则:
- 对于传球目标静止的,我们将球直接传给他
- 对于传球目标在运动中,我们需要通过计算,算好提前量,把球传到目标球员运动方向的前方,正好是目标球员跑到那个位置的时候,球也传到那个位置
带球
带球是不断地踢球的过程,每次踢一小步,让球向前滚动一小段距离,然后奔跑跟上。
我们简化需求,假设带球过程中,触球的频率是固定的,假设每秒触球一次,所以带球过程中,每次触球踢球的距离为,运动员按照当前速度 1 秒后到达的距离。
射门
射门在这其中是最好处理的,朝向球门射去即可。
为了简化射门中的参数传递,我们把射门抽象为以下几种:
- 射向球门左上角
- 射向球门左下角
- 射向球门右上角
- 射向球门右上角
- 射向球门正上方
- 射向球门正下方
验证 如前面的任务,创建一系列的参数可视化配置,及方法执行按钮,验证如上行为的实现和效果验证。
# 提交
把你的代码放在 Github 后进行提交
# 总结
依然把今天的学习用时,收获,问题进行记录
← 开一家餐厅吧 揭开迭代器神秘的面纱 →