Tay*_*orS 4 javascript canvas game-physics html5-canvas
如何使用只有几个变量的画布对象来模拟重力。
我创建了基础画布、游戏、时间、得分、一切,甚至游戏状态,但我被困在“将速度和重力因子添加到玩家 Y 变量中”的部分。
我尝试将重力系数乘以指定值,然后将其添加到 yVel,然后将其添加到实际 Y 值,但我无法正确转换定位。
我想如果我弄清楚如何“创造重力”来创造跳跃、向右移动和向左移动就不会太困难了。
这是我用来寻找平台的主要代码:
map.plates 表示一个充满数组的数组,每个数组包含一个车牌(平台车牌)的 4 个值,e 是 map.plates.Arrays。playY 基本上就是玩家的 Y 高度,全部渲染到 fillRect() 中;
function detectGravity() {
map.plates.forEach(e => {
if (playY > e[1] && playX <= e[0] && playX >= e[0] + e[2]) {
} else {
playY += 0; // Gravity Calculations here
}
});
}
Run Code Online (Sandbox Code Playgroud)
我真的不知道是否应该在此处包含其他内容,但如果您想要整个项目,请参阅下面的代码片段。
如果问题有什么问题请告诉我,我已经快半年没有来过这里了。
完整代码以防 codepen 死亡(在评论中建议):
"esversion: 6";
const can = document.querySelector(".block"),
ctx = can.getContext("2d"),
mScore = 100,
map = {
plates: [
[25, 25, 25, 2],
[75, 25, 25, 2],
[125, 25, 25, 2],
[175, 25, 25, 2],
[225, 25, 25, 2],
[25, 75, 25, 2],
[75, 62, 25, 2],
[125, 50, 25, 2],
[175, 38, 25, 2],
[25, 87, 25, 2],
[75, 100, 25, 2]
],
moneys: [
[25, 25],
[125, 25],
[225, 25],
[75, 62],
[75, 100]
],
player: [25, 25, 2, 2],
badSpt: []
};
let score = 0,
time = 60,
gameOn = 0;
let playX,
playY,
velX,
velY,
grav = 1.05;
can.addEventListener("click", startGame);
function startGame() {
if (gameOn != 1) {
gameOn = 1;
init();
gameTime = setInterval(() => {
if (time != 0) {
time -= 1;
}
}, 1000);
}
}
function init() {
can.width = 300;
can.height = 300;
drawEnviron();
drawLevel();
drawPlayer();
drawGame();
drawPixels();
if (time == 0) {
clearInterval(gameTime);
time = 60;
gameOn = 2;
}
window.requestAnimationFrame(init);
}
function drawEnviron() {
with (ctx) {
fillStyle = "#000000";
fillRect(0, 0, can.width, can.height);
fillStyle = "rgba(255, 255, 255, 0.5)";
fillRect(0, 0, can.width, can.height);
fillStyle = "#000000";
fillRect(0, 0, can.width, can.height / 15);
fillStyle = "#ffffff";
font = can.height / 15 + "px Verdana";
fillText("Score: " + score + "/" + mScore, 1, can.height / 19);
fillText("Time: " + time, can.width / 1.5 + 6, can.height / 19);
}
}
function drawLevel() {
map.plates.forEach(e => {
ctx.fillStyle = "#ffffff";
ctx.fillRect(e[0], can.height / 15 + e[1], e[2], e[3]);
});
map.moneys.forEach(e => {
ctx.beginPath();
ctx.fillStyle = "#fcba03";
ctx.arc(e[0] + 12.5, e[1] + 12.5, 4, 0, 2 * Math.PI);
ctx.fill();
});
}
function detectGravity() {
map.plates.forEach(e => {
if (playY > e[1] && playX <= e[0] && playX >= e[0] + e[2]) {
} else {
playY += 0;
}
});
}
function drawPlayer() {
const a = map.player;
if (gameOn == 0 || gameOn == 2) {
playX = a[0];
playY = a[1];
velX = 0;
velY = 0;
}
ctx.beginPath();
ctx.fillStyle = "#ff0000";
ctx.arc(playX + 12.5, playY + 12.5, 4, 0, 2 * Math.PI);
ctx.fill();
}
function drawGame() {
if (gameOn == 0) {
can.style.animation = "none";
with (ctx) {
fillStyle = "rgba(0, 0, 0, 0.5)";
fillRect(0, 0, can.width, can.height);
strokeStyle = "#000000";
lineWidth = 5;
fillStyle = "#ffffff";
textAlign = "center";
strokeText("Click to Start", 150, can.height / 4);
fillText("Click to Start", 150, can.height / 4);
}
} else if (gameOn == 2) {
can.style.animation = "0.2s flash infinite";
with (ctx) {
fillStyle = "rgba(0, 0, 0, 0.5)";
fillRect(0, 0, can.width, can.height);
strokeStyle = "#000000";
lineWidth = 5;
fillStyle = "#ff0000";
textAlign = "center";
strokeText("-- Game Over --", 150, can.height / 4);
fillText("-- Game Over --", 150, can.height / 4);
}
} else {
can.style.animation = "none";
}
}
function drawPixels() {
var fw = (can.width / 2) | 0,
fh = (can.height / 2) | 0;
ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = ctx.msImageSmoothingEnabled = ctx.webkitImageSmoothingEnabled = false;
ctx.drawImage(can, 0, 0, fw, fh);
ctx.drawImage(can, 0, 0, fw, fh, 0, 0, can.width, can.height);
}
init();Run Code Online (Sandbox Code Playgroud)
* {
box-sizing: border-box;
overflow: hidden;
}
.block {
border: 2px solid black;
}
@keyframes flash {
0%, 100% {
border: 2px solid black;
}
50% {
border: 2px solid red;
}
}Run Code Online (Sandbox Code Playgroud)
<canvas class="block"></canvas>Run Code Online (Sandbox Code Playgroud)
重力表现为速度随时间的变化(加速度)。它有方向和大小(矢量)
我们定义沿着画布向下的重力矢量
const gravity = {x: 0, y: 1};
Run Code Online (Sandbox Code Playgroud)
通常我们在以秒为单位的时间内施加重力。这不是一个方便的动画单元。在这种情况下,我们可以将其定义为每帧的像素。一帧是 1/60 秒。因此,上面定义的重力大小为每平方刻度 1 像素。因此,在一秒钟内,物体将以每刻 60 像素或每秒 3600 像素的速度移动。
对于大多数动画来说这有点太快了,所以我们可以稍微放慢速度
const gravity = {x: 0, y: 0.1};
Run Code Online (Sandbox Code Playgroud)
物体具有位置(坐标)和速度(矢量),速度(矢量)具有方向和大小。
const object = {
pos: {x: 0, y: 0}, // position
vel: {x, 0, y: 0}, // velocity
}
Run Code Online (Sandbox Code Playgroud)
为了模拟该对象上的重力,我们可以添加函数形式的行为。在这种情况下我们可以调用它update。在函数中,我们通过将向量添加到速度向量 ( ) 来update加速对象。然后我们通过将速度向量添加到位置坐标来更新位置gravityobject.velobject.velobject.pos
const gravity = {x: 0, y: 0.1};
const object = {
pos: {x: 0, y: 0}, // position
vel: {x, 0, y: 0}, // velocity
update() {
this.vel.x += gravity.x;
this.vel.y += gravity.y;
this.pos.x += this.vel.x;
this.pos.y += this.vel.y;
}
}
Run Code Online (Sandbox Code Playgroud)
这个物体本身将会永远坠落,所以我们需要让它与世界互动。我们可以定义一条地线。最基本的是画布上任意位置的一条线。
const ground = ctx.canvas.height; // ground at bottom of canvas.
Run Code Online (Sandbox Code Playgroud)
为了进行交互,我们需要添加到对象update函数中。在此我们检查物体相对于地面的位置。如果该位置低于地面,我们将该位置向上移动到远离地面的距离,与移动到地面的距离相同,并反转速度(弹跳)。
我们可以将地面的弹性定义为速度的一部分。
我们还需要给对象一个大小。
这样我们就得到了。
const gravity = {x: 0, y: 0.1};
const ground = ctx.canvas.height; // ground at bottom of canvas.
const bounce = 0.5;
const object = {
pos: {x: 0, y: 0}, // position
vel: {x, 0, y: 0}, // velocity
size: {w: 10, h: 10},
update() {
this.vel.x += gravity.x;
this.vel.y += gravity.y;
this.pos.x += this.vel.x;
this.pos.y += this.vel.y;
const g = ground - this.size.h; // adjust for size
if(this.pos.y >= g) {
this.pos.y = g - (this.pos.y - g); //
this.vel.y = -Math.abs(this.vel.y) * bounce; // change velocity to moving away.
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后所需要做的就是每帧调用 update 并将对象绘制在正确的位置。
将其付诸实践。
一个简单的盒子object从画布顶部落下并撞击地面(画布底部),弹起一点然后停止。(点击重置)
更新:我忘记检查物体是否静止。
如果我们不添加一些额外的代码,数学将使盒子振动并且永远不会真正停止移动update。
当盒子的弹跳力小于重力时,盒子现在看起来会完全停止。查看评论// check for rest.
const gravity = {x: 0, y: 1};
Run Code Online (Sandbox Code Playgroud)
const gravity = {x: 0, y: 0.1};
Run Code Online (Sandbox Code Playgroud)
const object = {
pos: {x: 0, y: 0}, // position
vel: {x, 0, y: 0}, // velocity
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3107 次 |
| 最近记录: |