P5中如何给小球添加弹跳压缩动画?
How to add a bounce compression animation to a ball in P5?
我用 P5.js 创建的简单游戏包括一个受重力影响下落并在地面上弹跳的球。我想在球接触地面时添加 "compression" 动画,使其看起来更逼真。
我怎样才能做到这一点而不让它看起来很奇怪?
代码是这样的:
function Ball() {
this.diameter = 50;
this.v_speed = 0;
this.gravity = 0.2;
this.starty = height / 2 - 100;
this.endy = height - this.diameter / 2;
this.ypos = this.starty;
this.xpos = width / 2;
this.update = function() {
this.v_speed = this.v_speed + this.gravity;
this.ypos = this.ypos + this.v_speed;
if (this.ypos >= this.endy) {
this.ypos = this.endy;
this.v_speed *= -1.0; // change direction
this.v_speed = this.v_speed * 0.9;
if (Math.abs(this.v_speed) < 0.5) {
this.ypos = this.starty;
}
}
}
this.show = function() {
ellipse(this.xpos, this.ypos, this.diameter);
fill(255);
}
}
var ball;
function setup() {
createCanvas(600, 600);
ball = new Ball();
}
function draw() {
background(0);
ball.update();
ball.show();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.js"></script>
一个非常简单的解决方案是动态增加 this.endy
,增加一个取决于速度的经验值。该值的最大值必须小于 this.diameter/2
。在示例中,我使用 this.diameter/3
作为最大数量,但您可以使用此值。如果速度为0,那么数量也必须为0:
endy = this.endy + Math.min(Math.abs(this.v_speed), this.diameter/3);
if (this.ypos >= endy) {
this.ypos = endy;
// [...]
}
这导致球稍微低于底部。用这个来“挤压”球相同的量:
this.show = function() {
h = Math.min(this.diameter, (height - this.ypos)*2)
w = 2 * this.diameter - h;
ellipse(this.xpos, this.ypos, w, h);
fill(255);
}
查看示例,其中我将建议应用于问题的代码:
function Ball() {
this.diameter = 50;
this.v_speed = 0;
this.gravity = 0.2;
this.starty = height / 2 - 100;
this.endy = height - this.diameter / 2;
this.ypos = this.starty;
this.xpos = width / 2;
this.update = function() {
this.v_speed = this.v_speed + this.gravity;
this.ypos = this.ypos + this.v_speed;
endy = this.endy + Math.min(Math.abs(this.v_speed), this.diameter/3);
if (this.ypos >= endy) {
this.ypos = endy;
this.v_speed *= -1.0; // change direction
this.v_speed = this.v_speed * 0.9;
if (Math.abs(this.v_speed) < 0.5) {
this.ypos = this.starty;
}
}
}
this.show = function() {
h = Math.min(this.diameter, (height - this.ypos)*2)
w = 2 * this.diameter - h;
ellipse(this.xpos, this.ypos, w, h);
fill(255);
}
}
var ball;
function setup() {
createCanvas(600, 600);
ball = new Ball();
}
function draw() {
background(0);
ball.update();
ball.show();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.js"></script>
我用 P5.js 创建的简单游戏包括一个受重力影响下落并在地面上弹跳的球。我想在球接触地面时添加 "compression" 动画,使其看起来更逼真。
我怎样才能做到这一点而不让它看起来很奇怪?
代码是这样的:
function Ball() {
this.diameter = 50;
this.v_speed = 0;
this.gravity = 0.2;
this.starty = height / 2 - 100;
this.endy = height - this.diameter / 2;
this.ypos = this.starty;
this.xpos = width / 2;
this.update = function() {
this.v_speed = this.v_speed + this.gravity;
this.ypos = this.ypos + this.v_speed;
if (this.ypos >= this.endy) {
this.ypos = this.endy;
this.v_speed *= -1.0; // change direction
this.v_speed = this.v_speed * 0.9;
if (Math.abs(this.v_speed) < 0.5) {
this.ypos = this.starty;
}
}
}
this.show = function() {
ellipse(this.xpos, this.ypos, this.diameter);
fill(255);
}
}
var ball;
function setup() {
createCanvas(600, 600);
ball = new Ball();
}
function draw() {
background(0);
ball.update();
ball.show();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.js"></script>
一个非常简单的解决方案是动态增加 this.endy
,增加一个取决于速度的经验值。该值的最大值必须小于 this.diameter/2
。在示例中,我使用 this.diameter/3
作为最大数量,但您可以使用此值。如果速度为0,那么数量也必须为0:
endy = this.endy + Math.min(Math.abs(this.v_speed), this.diameter/3);
if (this.ypos >= endy) {
this.ypos = endy;
// [...]
}
这导致球稍微低于底部。用这个来“挤压”球相同的量:
this.show = function() {
h = Math.min(this.diameter, (height - this.ypos)*2)
w = 2 * this.diameter - h;
ellipse(this.xpos, this.ypos, w, h);
fill(255);
}
查看示例,其中我将建议应用于问题的代码:
function Ball() {
this.diameter = 50;
this.v_speed = 0;
this.gravity = 0.2;
this.starty = height / 2 - 100;
this.endy = height - this.diameter / 2;
this.ypos = this.starty;
this.xpos = width / 2;
this.update = function() {
this.v_speed = this.v_speed + this.gravity;
this.ypos = this.ypos + this.v_speed;
endy = this.endy + Math.min(Math.abs(this.v_speed), this.diameter/3);
if (this.ypos >= endy) {
this.ypos = endy;
this.v_speed *= -1.0; // change direction
this.v_speed = this.v_speed * 0.9;
if (Math.abs(this.v_speed) < 0.5) {
this.ypos = this.starty;
}
}
}
this.show = function() {
h = Math.min(this.diameter, (height - this.ypos)*2)
w = 2 * this.diameter - h;
ellipse(this.xpos, this.ypos, w, h);
fill(255);
}
}
var ball;
function setup() {
createCanvas(600, 600);
ball = new Ball();
}
function draw() {
background(0);
ball.update();
ball.show();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.js"></script>