Ответ на Rise:
Вложений: 1
Я извиняюсь, Я неправильно написал. :) Я думаю по этой картинке всё должно быть понятно.
|
Вложений: 1
Sasha05082002, исправил, и система координат теперь более адекватная, нарисовал, так удобнее размышлять об углах :)
|
Благодарности Risе'у
Сппппппппппааааасссиииббо оо огромное Rise!!!!:thanks: Я думаю что тема закрыта, осталось тока подробнее разобрать ваш код, и вопрос как тему закрыть то? :)
|
Sasha05082002, никак, вот решил еще что-то написать но вовремя остановился :D получилось весьма интересно, особая гордость XBOT patrol - поворот по кратчайшему пути, движение по определенному маршруту (не)определенное число раз :)
<!DOCTYPE html> <html> <head><meta charset="utf-8"><title>TANK</title></head> <body> <style> canvas { outline: 1px solid gray; } canvas:hover { outline-color: red; } pre { width: 600px; font: 12px/12px monospace; outline: 1px solid gray; margin: 0; } </style> Control: Mouse + AWDS (click to focus) <pre></pre> <canvas width="600" height="300" tabindex="1"></canvas> <script> /* Class Tank */ // constructor function Tank(config) { for (var prop in config) { this[prop] = config[prop]; } } // public members Tank.prototype = { constructor: Tank, // default properties name: 'TANK', crew: 'empty', status: 1, pivotX: 100, pivotY: 100, headWidth: 50, headHeight: 40, headArrow: 10, headColor: '#aaaaaa', headAngle: 0, bodyWidth: 100, bodyHeight: 60, bodyArrow: 10, bodyColor: '#cccccc', bodyAngle: 0, stepAngle: Math.PI / 180, stepFactor: 1, // move methods bodyForward: function () { this.pivotX += Math.cos(this.bodyAngle) * this.stepFactor; this.pivotY += Math.sin(this.bodyAngle) * this.stepFactor; return this; }, bodyBackward: function () { this.pivotX -= Math.cos(this.bodyAngle) * this.stepFactor; this.pivotY -= Math.sin(this.bodyAngle) * this.stepFactor; return this; }, bodyLeft: function () { var angle = this.bodyAngle - this.stepAngle; this.bodyAngle = (angle < 0) ? angle + 2 * Math.PI : angle; return this; }, bodyRight: function () { var angle = this.bodyAngle + this.stepAngle; this.bodyAngle = (angle < 2 * Math.PI) ? angle : angle - 2 * Math.PI; return this; }, headLeft: function () { var angle = this.headAngle - this.stepAngle; this.headAngle = (angle < 0) ? angle + 2 * Math.PI : angle; return this; }, headRight: function () { var angle = this.headAngle + this.stepAngle; this.headAngle = (angle < 2 * Math.PI) ? angle : angle - 2 * Math.PI; return this; }, // frame methods update: function () { Tank.crew[this.crew].call(this); return this; }, render: function () { var x1, y1, x2, y2; // body Context.save(); Context.translate(this.pivotX, this.pivotY); Context.rotate(this.bodyAngle); Context.translate(-this.pivotX, -this.pivotY); x1 = this.pivotX - this.bodyWidth / 2; y1 = this.pivotY - this.bodyHeight / 2; x2 = x1 + this.bodyWidth; y2 = y1 + this.bodyHeight; // body polygon Context.beginPath(); Context.moveTo(x1, y1); Context.lineTo(x2, y1); Context.lineTo(x2 + this.bodyArrow, this.pivotY); Context.lineTo(x2, y2); Context.lineTo(x1, y2); Context.fillStyle = this.bodyColor; Context.fill(); Context.restore(); // head Context.save(); Context.translate(this.pivotX, this.pivotY); Context.rotate(this.headAngle); Context.translate(-this.pivotX, -this.pivotY); x1 = this.pivotX - this.headWidth / 2; y1 = this.pivotY - this.headHeight / 2; x2 = x1 + this.headWidth; y2 = y1 + this.headHeight; // head polygon Context.beginPath(); Context.moveTo(x1, y1); Context.lineTo(x2, y1); Context.lineTo(x2 + this.headArrow, this.pivotY); Context.lineTo(x2, y2); Context.lineTo(x1, y2); Context.fillStyle = this.headColor; Context.fill(); Context.restore(); // status text if (this.status) { Context.fillText(this.name + '(' + this.crew + ')', this.pivotX, this.pivotY); } return this; }, inform: function (x, y, Context) { Context.fillText(this.name + ':' + ' X ' + this.pivotX.toFixed(2) + ' Y ' + this.pivotX.toFixed(2) + ' bA ' + this.bodyAngle.toFixed(5) + ' hA ' + this.headAngle.toFixed(5) + ' sA ' + this.stepAngle.toFixed(5) + ' sF ' + this.stepFactor.toFixed(5), x, y); return this; } }; // static members // array of instances Tank.base = []; // crew methods Tank.crew = { empty: function () { //console.log(this.name, this.crew); }, player: function () { // input control if (Input.keys.left) { this.bodyLeft(); } if (Input.keys.forward) { this.bodyForward(); } if (Input.keys.right) { this.bodyRight(); } if (Input.keys.backward) { this.bodyBackward(); } // mouse control if (Mouse.follow) { Mouse.angle = Tank.math.hypotAngle(Mouse.x - this.pivotX, Mouse.y - this.pivotY); var angle = Tank.math.deltaAngle(Mouse.angle, this.headAngle); if (angle < 0) { this.headLeft(); } else { this.headRight(); } if (Math.abs(angle) - this.stepAngle < 0) { Mouse.follow = 0; } } }, patrol: function () { // states: stop 0, init 1, turn 2, move 3 if (this.routeState == 0) { //console.log('state', 0); if (this.routeIndex < this.routeArray.length) { this.routeState = 1; } else if (this.routeRound) { if (this.routeRound > 0) { this.routeRound--; } this.routeIndex = 0; } } else if (this.routeState == 1) { //console.log('state', 1); this.routePoint = this.routeArray[this.routeIndex++]; var deltaX = this.routePoint[0] - this.pivotX; var deltaY = this.routePoint[1] - this.pivotY; this.routeHypot = Tank.math.hypot(deltaX, deltaY); this.routeAngle = Tank.math.hypotAngle(deltaX, deltaY); this.routeState = 2; } else if (this.routeState == 2) { //console.log('state', 2); var angle = Tank.math.deltaAngle(this.routeAngle, this.bodyAngle); if (angle < 0) { this.bodyLeft().headLeft(); } else { this.bodyRight().headRight(); } if (Math.abs(angle) - this.stepAngle < 0) { this.routeState = 3; } } else if (this.routeState == 3) { //console.log('state', 3); this.bodyForward(); this.routeHypot -= this.stepFactor; if (this.routeHypot < 0) { this.routeState = 0; } } else { this.routeIndex = 0; this.routeState = 0; } } }; // math methods Tank.math = { hypot: function (deltaX, deltaY) { return Math.sqrt(deltaX * deltaX + deltaY * deltaY); }, hypotAngle: function (deltaX, deltaY) { // delta = point - pivot var angle = Math.atan2(deltaY, deltaX); if (angle < 0) { angle += 2 * Math.PI; } return angle; }, deltaAngle: function (hypotAngle, pivotAngle) { var angle; if (hypotAngle < pivotAngle) { angle = pivotAngle - hypotAngle; if (angle < Math.PI) { angle = -angle; } } else { angle = hypotAngle - pivotAngle; if (angle > Math.PI) { angle = -angle; } } // -angle - left, +angle - right, |angle| - delta return angle; } }; /* Input & Mouse & Output */ var Input = { // awds codes: { 65: 'left', 87: 'forward', 68: 'right', 83: 'backward' }, // arrows //codes: { 37: 'left', 38: 'forward', 39: 'right', 40: 'backward' }, keys: { left: 0, forward: 0, right: 0, backward: 0 }, inform: function (x, y, Context) { Context.fillText('INPUT:' + ' L ' + this.keys.left + ' F ' + this.keys.forward + ' R ' + this.keys.right + ' B ' + this.keys.backward, x, y); } }; var Mouse = { x: 0, y: 0, angle: 0, follow: 0, inform: function (x, y, Context) { Context.fillText('MOUSE:' + ' X ' + this.x.toFixed(2) + ' Y ' + this.y.toFixed(2) + ' A ' + this.angle.toFixed(5) + ' F ' + this.follow, x, y); } }; var Output = { setContext: function (context, pre) { if (pre) { this.context = this; this.nodes = pre.childNodes; var count = 25; while (count--) { pre.appendChild(document.createTextNode('')); } } else { this.context = context; } }, fillText: function (text, x, y) { this.nodes[y / 12].nodeValue = ' ' + text + '\n'; } }; /* Canvas & Context */ var Canvas = document.querySelector('canvas'); var Context = Canvas.getContext('2d'); Context.font = '12px monospace'; Context.fillText('Touch Me', Canvas.width / 2, Canvas.height / 2); Output.setContext(Context, document.querySelector('pre')); Canvas.addEventListener('mouseenter', onMouseenter); Canvas.addEventListener('mouseleave', onMouseleave); Canvas.addEventListener('mousemove', onMousemove); Canvas.addEventListener('keydown', onKeydown); Canvas.addEventListener('keyup', onKeyup); /* Event Handlers */ function onMouseenter(e) { Canvas.focus(); onAnimationFrame.id = requestAnimationFrame(onAnimationFrame); } function onMouseleave(e) { cancelAnimationFrame(onAnimationFrame.id); } function onMousemove(e) { Mouse.follow = 1; Mouse.x = e.offsetX; Mouse.y = e.offsetY; } function onKeydown(e) { var code = Input.codes[e.keyCode]; if (code) { Input.keys[code] = 1; } } function onKeyup(e) { var code = Input.codes[e.keyCode]; if (code) { Input.keys[code] = 0; } } function onAnimationFrame() { Context.clearRect(0, 0, Canvas.width, Canvas.height); var tank, tanks = Tank.base, index = tanks.length; while (index--) { tank = tanks[index]; tank.update().render(); tank.inform(5, 36 + 12 * index, Output.context); } Input.inform(5, 12, Output.context); Mouse.inform(5, 24, Output.context); onAnimationFrame.id = requestAnimationFrame(onAnimationFrame); } /* Tank Base Init */ Tank.base.push( new Tank({ name: 'RISE', crew: 'player', pivotX: 250, pivotY: 150, headColor: '#666633', headAngle: 5 / 3 * Math.PI, bodyColor: '#999966', bodyAngle: 5 / 3 * Math.PI }), new Tank({ name: 'XBOT', crew: 'patrol', pivotX: 400, pivotY: 200, headColor: '#663300', headAngle: 5 / 6 * Math.PI, bodyColor: '#996633', bodyAngle: 5 / 6 * Math.PI, // extra routeArray: [[500, 70], [100, 200], [520, 230]], routeRound: 1 }), new Tank() ); </script> </body> </html> |
Rise,
:victory: |
Очень круто! :) Тока бот врезался в стенку и остановился.
|
рони, :thanks:
Sasha05082002, он не врезался, у него закончился маршрут и он остановился :) |
Еще может возникнуть вопрос, почему круг (round) установлено 1, а проехал вроде как 2, на самом деле круг там один:
Первый проезд: произвольная точка -> начальная точка -> промежуточные точки -> конечная точка Второй проезд: конечная точка -> начальная точка -> промежуточные точки -> конечная точка (round) И еще, бесконечному числу кругов соответствует отрицательное значение. |
Часовой пояс GMT +3, время: 00:02. |