2D3D maze game based on WebGL of HTML5

Posted by teamatomic on Tue, 22 Oct 2019 15:02:10 +0200

In order to implement a scene game based on HTML5, I used HT for Web To achieve, just 200 lines of code, I can use the "first person" to operate forward and backward up and down, and achieve collision detection.

Let's first look at the effect of the implementation:  http://hightopo.com/guide/guide/core/3d/ht-3d-guide.html#ref_collision

perhaps http://v.youku.com/v_show/id_XMzA5MzUzODc4NA==.html?spm=a2h3j.8428770.3416059.1 The problem of the frame in the video is the problem of my screen recorder. It won't exist during the real operation. It's recommended to use the above link to operate by yourself.

Play, mouse or touch screen can be, but I think the most convenient is to operate the keyboard wsad control up and down around.

My idea is to lay out the scene first. The code is as follows:

createHT([100, -20, 100], '#E74C3C');                  
createHT([-100, -20, 100], '#1ABC9C');                    
createHT([100, -20, -100], '#3498DB');                   
createHT([-100, -20, -100], '#9B59B6');   
createCurve([0, -20, 0]);
createCircle();

These are all user-defined functions. createHT is a graph depicting HT shape. There are four functions in the scene, so it is called four times. Createcycle is a yellow curve depicting the middle of the scene. Createcycle is a circle depicting the outermost layer, because it is not a full circle, so it is also a dot drawing.

HT It encapsulates a component. ht.Shape (hereinafter referred to as shape), which can describe the graph freely according to the tracing points. You can add all the points to the array through shape.setPoints(pointsArray), and set them to the shape. Then you can set the line array information through setSegments(), that is, what kind of way to connect the two points? It is described in the shape manual, and you can refer to the interested ones. HT for Web Shape Brochure . Take one of the functions that describe a point to see:

function createHT(p3, color){
    shape = new ht.Shape();                
    shape.s({
        'shape.background': null,
        'shape.border.width': 10,
        'shape.border.color': color,
        'all.color': color
    });
    shape.setTall(40);
    shape.setThickness(5);
    shape.setPoints([                    
        // draw H
        {x: 20, y: 0},
        {x: 20, y: 100},
        {x: 20, y: 50},
        {x: 80, y: 50},
        {x: 80, y: 0},
        {x: 80, y: 100},

        // draw T
        {x: 120, y: 0},
        {x: 180, y: 0},
        {x: 150, y: 0},
        {x: 150, y: 100}                    
    ]);                                
    shape.setSegments([
        // draw H
        1, // moveTo
        2, // lineTo
        1, // moveTo
        2, // lineTo
        1, // moveTo
        2, // lineTo

        // draw T
        1, // moveTo
        2, // lineTo
        1, // moveTo
        2 // lineTo
    ]);                
    shape.p3(p3);
    dataModel.add(shape); 
    return shape;
}

Because the word "HT" has many points to describe, the code looks a bit large. If you see how to describe an incomplete circle in 20 lines of code, and including the style, you will be surprised:

shape = new ht.Shape();                
shape.s({
    'shape.background': null,
    'shape.border.width': 10,
    'shape.border.color': '#D26911',
    'all.color': '#D26911'
});
shape.setTall(40);
shape.p3(0, -20, 0);
shape.setThickness(10);
                
var r = 300;
for(var i=0; i<36; i++){
    var angle = Math.PI * 2 * i / 36;
    shape.addPoint({
        x: r * Math.cos(angle),
        y: r * Math.sin(angle)
    });
}
                
dataModel.add(shape); 
return shape;

After the scene is set, the position of "I" in 3d will be displayed in 2d. First of all, I have to set "I" as "first person roaming mode", and directly set g3d.setfirstperson mode (true). The essence of first person roaming mode is to control eye and center. If the first person roaming mode is not set, the mouse or touchpad drag will rotate around the center. Detailed reference HT for Web 3D Brochure.

because HT 3D Two methods, getEye and getCenter, are encapsulated in. They are respectively to obtain the location of camera and the location of target center point. The former, according to the imagination, is like having a camera on your head, where you go to its center point, you can easily record your location. The latter is equivalent to the location you see, but it's not the same as us. , because people can see a wide range, but this center is equivalent to your eyeball and can't rotate. It is a point in front of you that is your focus position.

After understanding getEye and getCenter, we can get the current position and sight position:

g2d.addTopPainter(function(g){
    var eye = g3d.getEye(),
    center = g3d.getCenter();
                        
    g.fillStyle = 'red';
    g.strokeStyle = 'black';
    g.lineWidth = 1;
    g.beginPath();                    
    g.arc(eye[0], eye[2], 12, 0, Math.PI * 2, true); //Draw circle and get the position of "I" in 3d in real time
    g.fill();
    g.stroke();  
                    
    g.strokeStyle = 'black';
    g.lineWidth = 2;
    g.beginPath(); 
    g.moveTo(eye[0], eye[2]);
    g.lineTo(center[0], center[2]); //Draw lines, which can change the line segment between "me" and "my sight position" in real time   
    g.stroke(); 
});

But in the code, we found that this method was drawn only once. If it is not redrawn all the time, the position and movement of "I" in 2d interface will not change, so we monitored the change of attributes in 3d.

g3d.mp(function(e){//Update 2d interface in real time according to my position and line of sight on 3d
    if(e.property === 'eye' || e.property === 'center'){ //If the e property changes to get/setEye, get/setCenter, redraw the 2d interface.
        g2d.redraw();
    } 
});

In 2D, I can edit the entity, move its points, change the size of an entity, and so on. As long as the entity is changed, my collision test must be updated:

function updateBoundaries(){
    boundaries = [];
    dataModel.each(function(data){//HT curve circle              
        boundaries = boundaries.concat(ht.Default.toBoundaries(data.getPoints(), data.getSegments()));
        // ht.Default.toBoundaries convert the discontinuous curve to the parameter format required by graph3dview ා setboundaries (BS)
    }); 
    g3d.setBoundaries(boundaries);//setBoundary() to specify the collision boundary
}

What we are curious about is how to keep collision detection when dragging elements to change their size.

HT There is a monitoring event for property change in addDataPropertyChangeListener(), which can be abbreviated to md(). When we drag an element, the basic points for drawing the element will be changed, so we just need to check whether the monitoring points have been changed. How to use this event can be referred to. HT for Web Data Model Manual

dataModel.md(function(e){//data property change event    
    if(e.property === 'points'){//If the data property changes to getPoints/setPoints, update the boundary
        updateBoundaries();
    }
});

Topics: Front-end html5