[Cson original] HTML5 achieves a 3D maze

Source: Internet
Author: User

Function Description:

The left and right arrow keys control the player's direction, and the up and down arrow keys control the player's forward and backward.

Effect preview:

Implementation principle:

In the previous effect preview, we can see a 2D flat map on the right, while a 3D view in the first person on the left. The relationship between the two images is very close, essentially,The process of 3D vision is the process of converting a map into a first-person vision based on a 2D map..

In the previous articleArticle: In JavaScript 3D room, the 3D effect is only limited to the plane (meaning there is no three-dimensional effect from the side). In this limited 3D effect, we use an object as a unit to realize 3D through the visual difference between different object planes. In this effect, in order to enable an object to have a three-dimensional effect from different angles,We changed the unit from a plane to a line..

First, we create something called a visual plane, which is like a mirror, which projects the object onto a plane. First, initialize the plane size:

 
Screensize: [320,240],//Visual screen size

Then, we can use 1 pixel as the unit. As long as we know the height of each pixel of an object displayed on the visual plane, we can plot the effect of the object on the first person's vision.

Taking the first pixel line segment on the visual plane as an example, we can know according to the ratio.: 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. We can define the distance from the player to the visual plane and the actual height of the object. Therefore, as long as we know the distance from the player to the object, we can know the height of the object's pixel on the visual plane.

How can we know the actual distance from a player to an object? In this case, we need to use 2D maps closely related to 3D visual images. First, we define the maximum visual angle of a player to 60 degrees (that is, the angle of the player's visual range). Since we are dealing with the first pixel line of a plane, therefore, the pixel line angle is-30 degrees relative to the player. On the map, we can know the player's position X and Y and the player's direction, so we can know the direction of the first pixel line on the map.

On a 2D map, how does one represent a pixel line on a 3D visual plane? In fact, if you think about it, you can find that a pixel line in a 3D visual plane is equivalent to a ray emitted in a specific direction on a 2D map,The intersection of rays and objects is the pixel line in the 3D visual plane.Therefore, we can know the distance between the player and the object as long as we calculate the length of the ray (start point: Player Position end point: the intersection of the ray and the object, in this way, the height of the pixel-modified object on the visual plane is obtained.

Last as longCyclically traverse each pixel line with a 1 px width on the visual planeBased on the length of the corresponding rays on the 2D map, we can obtain the height of each pixel of the objects in all visual ranges on the visual plane to form a 3D visual effect.


CodeAnalysis:

Focus on the core code of the implementation, traverse each pixel line on the visual plane cyclically, and draw the object content on the pixel line:

VaRContext =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 );

Because this effect requires two canvases (one for displaying a map and one for displaying a 3D visual map), we first obtain the canvas on the 3D visual map and draw the ground and sky.

     //  Cngame. Context. beginpath ();  
For ( VaR Index = 0, colcount = This . Screensize [0]/This. viewcolwidth; index <colcount; index ++ ){
Screenx =- This . Screensize [0]/2 + Index * This. viewcolwidth; // The X coordinate of the vertical line on the screen
Colangle = math. atan (screenx/This. screendistant); // angle of the player's sight to the vertical line on the screen
Colangle % = 2 * Math. Pi;
VaR Angle = This . Player. Angle/180 * (math. Pi)-colangle; // angle of the ray in the map
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 coordinate of the player's midpoint
Centery = This . Player. Y + ( This . Player. Height)/2; // y coordinate in the player
While ( This . Map. getposvalue (centerx + X, centery-y) = 0 ){
Distant + = 1;
X = distant * Math. Cos (angle );
Y = distant * Math. Sin (angle );
}
// Draw a line if a ray encounters a wall on the map
/* 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 ); // Prevention of fisheye Effect

Heightinscreen = This . Screendistant/(distant) * This. wallsize [2]; // calculate the height of the wall on the visual plane based on the distance from the player to the wall
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)
}

Then, you can start to traverse each pixel line cyclically and draw the object content. When processing each pixel line, we increase the length of the ray by 1 pixel each time,When a ray encounters a non-empty space (getposvalue (x, y)> 0), it stops increasing and records the length of the ray at this time, the length is the actual distance from the player to the pixel line content.

In the above Code, the commented out part is actually used to draw the departure Ray. If you need it, you can restore this part of code to see the player's visual range.

Note that because the visual plane distinguishes the human eye (a plane rather than a sphere ),Therefore, we need to multiply the cosine of the player's visual angle to avoid the effect of the fish eye..

Finally, we can draw players (hands with guns) on 3D Visual graphs to achieve better results.

 

Complete demo download: Click to download

 

References:

Create a pseudo 3D Game (Part1) using HTML5 canvas and raycasting)

Creating pseudo do 3D games with HTML 5 canvas and raycasting

Ray-casting tutorial for game development and other purposes

Welcome to reprint, please indicate the source: http://www.cnblogs.com/Cson/archive/2012/02/26/2368955.html

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.