带HTML帆布的射线铸造地板
我正在编码一个小的JavaScript/ HTML-Canvas Wolfenstein样式游戏。我关注 persadi教程。
目前,我确实实现了质感的墙射线播种。我现在想做的是进行铺板播放。
据我所知,当我完成画一片墙时,我必须检查它是否到达画布的底部。 如果不是这样,那意味着在其下面有一个地板要渲染。因此,我从墙壁底部到画布底部抓住每个像素,在“现实世界”中计算其坐标,抓住它们的质地并将其绘制在屏幕上。
我正在使用这两个模式进行计算。
这是我的代码:
//we check if the wall reaches the bottom of the canvas
// this.wallToBorder = (400 - wallHeight) / 2;
if (this.wallToBorder > 0) {
// we calculate how many pixels we have from bottom of wall to border of canvas
var pixelsToBottom = Math.floor(this.wallToBorder);
//we calculate the distance between the first pixel at the bottom of the wall and the player eyes (canvas.height / 2)
var pixelRowHeight = 200 - pixelsToBottom;
// then we loop through every pixels until we reach the border of the canvas
for (let i = pixelRowHeight; i < 200; i++) {
// we calculate the straight distance between the player and the pixel
var directDistFloor = this.screenDist * (canvas.height/2) / Math.floor(i);
// we calculate it's real world distance with the angle relative to the player
var realDistance = directDistFloor / Math.cos(this.angleR);
// we calculate it's real world coordinates with the player angle
this.floorPointx = this.player.x + Math.cos(this.angle) * realDistance;
this.floorPointy = this.player.y - Math.sin(this.angle) * realDistance;
// we map the texture
var textY = Math.floor(this.floorPointx % 64);
var textX = Math.floor(this.floorPointy % 64);
var pixWidthHeight = (1 / realDistance) * this.screenDist;
if (pixWidthHeight < 1) pixWidthHeight = 1;
// we draw it on the canvas
this.ctx.drawImage(wallsSprite, textX, textY + 64, 1, 1, this.index, i + 200, pixWidthHeight, pixWidthHeight);
}
}
但是结果不是我期望:
这是我的< href =“ https://stackblitz.com/edit/js-2p5bor?file=ray.js” rel =“ nofollow noreferrer”> stackblitz中的项目。我做错了什么?
I am coding a small Javascript/ HTML-canvas
Wolfenstein style game. I am following Permadi tutorial.
For now I did suceed to implement the textured wall raycasting. What I want to do now is to do the floor raycasting.
As far as I understand, when I finish to draw a slice of wall, I have to check if it reaches the bottom of the canvas.
If not, that means there is a floor to be rendered underneath it. So I grab every pixel from the bottom of the wall to the bottom of the canvas, calculate their coordinates in "real-world", grab their texture and draw them on the screen.
I am using these two schemas for my calculations.
These is my code:
//we check if the wall reaches the bottom of the canvas
// this.wallToBorder = (400 - wallHeight) / 2;
if (this.wallToBorder > 0) {
// we calculate how many pixels we have from bottom of wall to border of canvas
var pixelsToBottom = Math.floor(this.wallToBorder);
//we calculate the distance between the first pixel at the bottom of the wall and the player eyes (canvas.height / 2)
var pixelRowHeight = 200 - pixelsToBottom;
// then we loop through every pixels until we reach the border of the canvas
for (let i = pixelRowHeight; i < 200; i++) {
// we calculate the straight distance between the player and the pixel
var directDistFloor = this.screenDist * (canvas.height/2) / Math.floor(i);
// we calculate it's real world distance with the angle relative to the player
var realDistance = directDistFloor / Math.cos(this.angleR);
// we calculate it's real world coordinates with the player angle
this.floorPointx = this.player.x + Math.cos(this.angle) * realDistance;
this.floorPointy = this.player.y - Math.sin(this.angle) * realDistance;
// we map the texture
var textY = Math.floor(this.floorPointx % 64);
var textX = Math.floor(this.floorPointy % 64);
var pixWidthHeight = (1 / realDistance) * this.screenDist;
if (pixWidthHeight < 1) pixWidthHeight = 1;
// we draw it on the canvas
this.ctx.drawImage(wallsSprite, textX, textY + 64, 1, 1, this.index, i + 200, pixWidthHeight, pixWidthHeight);
}
}
But The result is not I am expecting:
Here is my project in StackBlitz. What I am doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的代码中有两个小错误。
这应该计算玩家与地板瓷砖之间的距离。如果我们查找
this.screendist
的实际值,我们可以看到:因此,与地板瓷砖无关。
屏幕截图
应镜像地板图块的“高度” -64个像素在您的情况下 - 该map> map
class的属性maps
确定。更改上面的行:
第二个错误在这里潜伏:
您需要添加正弦在玩家的垂直位置。
作为旁注:在您的地板图算法中,您实际上是在滥用
drawimage()
方法来绘制单个像素。这是一个巨大的瓶颈。快速修复将是从纹理映射读取像素的颜色,然后使用fillRect()
。不过,仍然有改进的余地。这是您修改的代码:
There are two small mistakes in your code.
This should calculate the distance between the player and a floor tile. If we look up the actual value of
this.screenDist
we can see:So there is no relation to a floor tile.
screenDist
should mirror the 'height' of a floor tile - 64 pixels in your case - which is determined as propertymapS
of theMap
class.Change the above line to this:
The second bug is lurking here:
as you need to add the sine to the player's vertical position.
Just as a side note: In your floor drawing algorithm, you're literally abusing the
drawImage()
method to draw individual pixels. This is a huge bottleneck. A quick fix would be reading the pixel's color from your texture map and usefillRect()
instead. There's still room for improvement though.Here's your modified code: