Drag and Drop a wall on the canvas, and use the arrow keys to control the movement of the polygon between top, bottom, and left. The wall cannot be moved forward. The following describes the problems to be solved and the specific implementation code, interested friends can learn about the game.
Drag and Drop the canvas to add a wall and use the arrow keys to control the movement of the polygon between top, bottom, and left. When a wall is displayed, the polygon cannot move forward.
Problems to be Solved
Click the mouse, drag the mouse, and release the event detection.
Polygon rendering
Draw walls
Collision Detection between polygon and walls (essentially determining the intersection between a circle and a line segment)
MYCode:
The Code is as follows:
MazeScript var canvas_width = 900; var canvas_height = 350; var ctx; var canvas; var everything = []; var cur_wall; var wall_width; var wall_style = "rgb (, 0, 200) "; var wballs = []; var in_motion = false; var unit = 10; function Token (sx, sy, rad, style_string, n) {this. sx = sx; this. sy = sy; this. rad = rad; this. draw = draw_token; this. n = n; this. angle = (2 * Math. PI)/n; this. move = move_token; this. fill_style = style_string;} function draw_token () // draw positive n edges {ctx. fill_style = this. fill_style; ctx. beginPath (); var I; var rad = this. rad; ctx. moveTo (this. sx + rad * Math. cos (-0.5 * this. angle), this. sy + rad * Math. sin (-0.5 * this. angle); for (I = 1; I <this. n; I ++) ctx. lineTo (this. sx + rad * Math. cos (I-0.5) * this. angle), this. sy + rad * Math. sin (I-0.5) * this. angle); ctx. fill ();} function move_token (dx, dy) {this. sx + = dx; this. sy + = dy; var I; var wall; for (I = 0; I <Wils. length; I ++) {wall = Wils [I]; if (intersect (wall. sx, wall. sy, wall. fx, wall. fy, this. sx, this. sy, this. rad) {this. sx-= dx; this. sy-= dy; break ;}} function Wall (sx, sy, fx, fy, width, styleString) {this. sx = sx; this. sy = sy; this. fx = fx; this. fy = fy; this. width = width; this. draw = draw_line; this. strokeStyle = styleString;} function draw_line () {ctx. lineWidth = this. width; ctx. strokeStye = this. strokeStyle; ctx. beginPath (); ctx. moveTo (this. sx, this. sy); ctx. lineTo (this. fx, this. fy); ctx. stroke ();} // note var mypent = new Token (100,100, 20, "rgb (250,)", 5); everything. push (mypent); function init () {canvas = document. getElementById ("canvas"); ctx = canvas. getContext ('2d '); // note canvas. addEventListener ('mousedown ', start_wall, false); canvas. addEventListener ('mousemove ', stretch_wall, false); canvas. addEventListener ('mouseup', finish_wall, false); window. addEventListener ('keylow', getkey_and_move, false); draw_all ();} function start_wall (ev) {var mx; var my; if (ev. layerX | ev. layerx = 0) {mx = ev. layerX; my = ev. layerY;} else if (ev. offsetX | ev. offsetX = 0) {mx = ev. offsetX; my = ev. offsetY;} cur_wall = new Wall (mx, my, mx + 1, my + 1, wall_width, wall_style); in_motion = true; everything. push (cur_wall); draw_all ();} function stretch_wall (ev) {if (in_motion) {var mx; var my; if (ev. layerX | ev. layerX = 0) {mx = ev. layerX; my = ev. layerY;} else if (ev. offsetX | ev. offsetX = 0) {mx = ev. offsetX; my = ev. offsetY;} cur_wall.fx = mx; cur_wall.fy = my; draw_all () ;}} function finish_wall (ev) {in_motion = false; Wils. push (cur_wall);} function draw_all () {ctx. clearRect (0, 0, canvas_width, canvas_height); var I; for (I = 0; I <everything. length; I ++) {everything [I]. draw () ;}} function getkey_and_move (event) {var keyCode; if (event = null) {keyCode = window. event. keyCode; window. event. preventDefault ();} else {keyCode = event. keyCode; event. preventDefault ();} switch (keyCode) {case 37: // left arrow mypent. move (-unit, 0); break; case 38: // up arrow mypent. move (0,-unit); break; case 39: // right arrow mypent. move (unit, 0); break; case 40: mypent. move (0, unit); break; default: // window. removeEventListener ('keylow', getkey_and_move, false);} draw_all ();} function intersect (sx, sy, fx, fy, cx, cy, rad) {var dx; var dy; var t; var rt; dx = fx-sx; dy = fy-sy; t = 0.0-(sx-cx) * dx + (sy-cy) * dy)/(dx * dx + dy * dy); if (t <0.0) {t = 0.0;} else if (t> 1.0) t = 1.0; var dx1 = (sx + t * dx)-cx; var dy1 = (sy + t * dy)-cy; var rt = dx1 * dx1 + dy1 * dy1; if (rt <rad * rad) return true; else return false;} script
Difficulties
Polygon and line segment Collision Detection Method
The intersect () function is used to detect the intersection between a polygon and a line segment.
Point p (x, y) on a line segment)
The two endpoints of a line segment are (sx, sy) and (fx, fy)
Note
Dx = fx-sx
Dy = fy-sy
X and y can be expressed as follows:
X = sx + t * dx
Y = sy + t * dy
To determine whether a line segment and a polygon are intersecting, convert it to determine whether a line segment and a polygon's outer circle are intersecting.
Therefore, we need to find the point p closest to the center o on the line segment.
If | op | <圆的半径,则可以判断线段和圆相交。
Otherwise, they do not overlap.
How can we find the closest point to the center of a line segment?
The distance from point P to point o can be expressed
Distance = sqrt (x-cx) * (x-cx) + (y-cy) * (y-cy ));
Substitution
X = sx + t * dx and y = sy + t * dy
We can see that distance is a function about t.
Evaluate this function
Find the corresponding tvalue when the function value is 0 to obtain the point closest to the center of the circle.