Function description:
The left and right direction keys control the player's direction, and the up and down direction keys control the player's forward and backward movement.
Effect preview:
Implementation principle:
In the above effect preview, you can see that the right side is a 2D flat map, while the left side is a first-person 3D view. The relationship between the two pictures is very close. In essence, The process of realizing 3D vision is the process of converting the map into first-person vision based on the 2D map.
The realization of 3D effects is only limited to planes (meaning that there is no three-dimensional effect when viewed from the side). In this limited 3D effect, we take each object as a unit and pass between the planes of different objects. The visual difference achieves 3D. In this effect, in order to make the object have a three-dimensional effect when viewed from different angles, we changed the unit from plane to line.
First, we create something called a visual plane, which is like a mirror and projects the physical object onto a plane. First initialize the size of the plane:
screenSize:[320,240],//视觉屏幕尺寸
After that, we can use 1 The unit is pixels. As long as you know the height of each pixel of the object displayed on the visual plane, you can draw the first-person visual effect of the object.
Take the first pixel line segment on the visual plane as an example. According to the ratio, we can know: the distance from the player to the visual plane/the actual distance from the player to the object = the height of the object on the visual plane/ The actual height of the object. Since we can define the distance between the player and the visual plane and the actual height of the object ourselves, as long as we know the distance between the player and the object, we can know the height of the pixel of the object in the visual plane.
How to know the actual distance between the player and the object? At this time we need to use 2D maps that are closely related to 3D visual maps. First, we define the player's maximum visual angle as 60 degrees (meaning the player's visual range angle). Since we are now dealing with the first pixel line of the plane, the angle of this pixel line relative to the player is -30 degrees. . On the map, we can know the player's X,Y position and the player's direction, so we can know the direction of the first pixel line on the map.
How to represent a pixel line on the 3D visual plane on a 2D map? In fact, if you think about it carefully, you can find that a pixel line in the 3D visual plane is equivalent to a ray emitted in a specific direction on the 2D map. The intersection of the ray and the object is the content of the pixel line in the 3D visual plane. . Therefore, as long as we calculate the length of the ray (starting point: player position end point: where the ray intersects with the object), we can know the distance between the player and the object, and thus find the height of the pixel-changed object on the visual plane .
In the end, justlooptraverse every 1px wide pixel line on the visual plane, and based on the length of the corresponding ray on the 2D map, the visual plane can be obtained The height of each pixel of all objects within the visual range forms a 3D visual effect.
Code analysis:
Mainly look at the core code of the implementation, loop through each pixel line on the visual plane, and draw the object content on the pixel line:var context=this.screenContext; context.clearRect(0,0,this.screenSize[0],this.screenSize[1]); context.fillStyle="rgb(203,242,238)"; context.fillRect(0,0,this.screenSize[0],this.screenSize[1]/2); context.fillStyle="rgb(77,88,87)"; context.fillRect(0,this.screenSize[1]/2,this.screenSize[0],this.screenSize[1]/2);
//cnGame.context.beginPath(); for(var index=0,colCount=this.screenSize[0]/this.viewColWidth;index<colCount;index++){ screenX=-this.screenSize[0]/2+index*this.viewColWidth;//该竖线在屏幕的x坐标 colAngle=Math.atan(screenX/this.screenDistant);//玩家的视线到屏幕上的竖线所成的角度 colAngle%=2*Math.PI; var angle=this.player.angle/180*(Math.PI)-colAngle;//射线在地图内所成的角度 angle%=2*Math.PI; if(angle<0){ angle+=2*Math.PI; } distant=0; x=0; y=0; centerX=this.player.x+(this.player.width)/2;//玩家中点X坐标 centerY=this.player.y+(this.player.height)/2;//玩家中Y坐标 while(this.map.getPosValue(centerX+x,centerY-y)==0){ distant+=1; x=distant*Math.cos(angle); y=distant*Math.sin(angle); } //如果射线在地图遇到墙壁,则画线 /*cnGame.context.strokeStyle="#000"; cnGame.context.moveTo(centerX,centerY); cnGame.context.lineTo(centerX+x,Math.floor(centerY-y)); cnGame.context.closePath(); */ distant*=Math.cos(colAngle);//防止鱼眼效果 heightInScreen=this.screenDistant/(distant)*this.wallSize[2];//根据玩家到墙壁的距离计算墙壁在视觉平面的高度 var img=cnGame.loader.loadedImgs[srcObj.stone2]; context.drawImage(img,0,0,2,240,this.viewColWidth*index,(this.screenSize[1]-heightInScreen)/2, this.viewColWidth,heightInScreen) }
When the ray encounters a non-empty area (getPosValue (x, y) >0), it stops growing and records The length of the ray at this time is the actual distance from the player to the content of the pixel line.
In the above code, the It should be noted that since the visual plane is different from the human eyeball (it is a plane rather than a sphere),we also need to multiply the distance by the cosine of the player's visual angle to avoid fish Eye effect.
Finally, we can also draw the player (the hand holding the gun) on the 3D visual map to achieve better results.The above is the detailed content of Detailed introduction to the code case of implementing 3D maze in HTML5. For more information, please follow other related articles on the PHP Chinese website!