Tank

Destroy your least favorite website with this tank!

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name					Tank
// @namespace			http://www.thenewgroup.com/gmscripts
// @description		Destroy your least favorite website with this tank!
// @include				*
// @copyright			2010+, The New Group (http://theNewGroup.com)
// @author				Kory Paulsen
// @licence				GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
// @version				0.2.4
// ==/UserScript==

// Jarett's update checker (https://userscripts-mirror.org/scripts/review/20145)
var SUC_script_num = 66802; // Basecamp Writeboard Sorting UserScripts script id
try{function updateCheck(forced){if ((forced) || (parseInt(GM_getValue('SUC_last_update', '0')) + 86400000 <= (new Date().getTime()))){try{GM_xmlhttpRequest({method: 'GET',url: 'https://userscripts-mirror.org/scripts/source/'+SUC_script_num+'.meta.js?'+new Date().getTime(),headers: {'Cache-Control': 'no-cache'},onload: function(resp){var local_version, remote_version, rt, script_name;rt=resp.responseText;GM_setValue('SUC_last_update', new Date().getTime()+'');remote_version=parseInt(/@uso:version\s*(.*?)\s*$/m.exec(rt)[1]);local_version=parseInt(GM_getValue('SUC_current_version', '-1'));if(local_version!=-1){script_name = (/@name\s*(.*?)\s*$/m.exec(rt))[1];GM_setValue('SUC_target_script_name', script_name);if (remote_version > local_version){if(confirm('There is an update available for the Greasemonkey script "'+script_name+'."\nWould you like to go to the install page now?')){GM_openInTab('https://userscripts-mirror.org/scripts/show/'+SUC_script_num);GM_setValue('SUC_current_version', remote_version);}}else if (forced)alert('No update is available for "'+script_name+'."');}else GM_setValue('SUC_current_version', remote_version+'');}});}catch (err){if (forced)alert('An error occurred while checking for updates:\n'+err);}}}GM_registerMenuCommand(GM_getValue('SUC_target_script_name', '???') + ' - Manual Update Check', function(){updateCheck(true);});updateCheck(false);}catch(err){}

var Tank = function()
{
	var delay = 50;

	var tank = document.createElement('canvas');
	tank.degrees = 0;
	tank.speed = 8;
	tank.imgWidth = 80;
	tank.imgHeight = 80;
	tank.canvSize = Math.round(Math.sqrt(tank.imgWidth*tank.imgWidth+tank.imgHeight*tank.imgHeight)); //square canvas as wide as hypotenuse for complete rotation
	tank.height = tank.canvSize;
	tank.width = tank.canvSize;
	tank.x = Math.floor(window.innerWidth / 2);
	tank.y = Math.floor(window.innerHeight / 2);
	tank.left = tank.x-Math.floor(tank.canvSize/2);
	tank.top = tank.y-Math.floor(tank.canvSize/2);
	tank.setAttribute('style', 'position:absolute; top:'+tank.top+'px; left:'+tank.left+'px; width:'+tank.canvSize+'px; height:'+tank.canvSize+'px; z-index:998;');
	tank.className = 'GM_Tank_aTank';
	document.body.appendChild(tank);

	var tankCtx = tank.getContext('2d');
	tank.img = new Image();
	tank.img.src = 'data:image/png;base64,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';
	tank.img.addEventListener('load', drawTank, true);

	function drawTank()
	{
		tankCtx.drawImage(tank.img, (tank.canvSize-tank.imgWidth)/2, (tank.canvSize-tank.imgHeight)/2);
	}

	var turret = document.createElement('canvas');
	turret.degrees = 0;
	turret.speed = 8;
	turret.imgWidth = tank.imgWidth;
	turret.imgHeight = tank.imgHeight;
	turret.canvSize = Math.round(Math.sqrt(turret.imgWidth*turret.imgWidth+turret.imgHeight*turret.imgHeight)); //square canvas as wide as hypotenuse for complete rotation
	turret.height = turret.canvSize;
	turret.width = turret.canvSize;
	turret.x = tank.x;
	turret.y = tank.y;
	turret.left = turret.x-Math.floor(turret.canvSize/2);
	turret.top = turret.y-Math.floor(turret.canvSize/2);
	turret.setAttribute('style', 'position:absolute; top:'+turret.top+'px; left:'+turret.left+'px; width:'+turret.canvSize+'px; height:'+turret.canvSize+'px; z-index:999;');
	turret.className = 'GM_Tank_aTurret';
	document.body.appendChild(turret);

	var turretCtx = turret.getContext('2d');
	turret.img = new Image();
	turret.img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAa5JREFUeNrs3UGKglAYwPGnzS3CRYu8QB2hRSujSxR4I7tE5KpFR9ALKCgt2neB0XnfA2Fm8BXMLOZr+P9Bkp6Lxy9DjQcFxphJ3/fvRmHL5bKX16IoAo3zC4JgElg8oxVvUZZuv1ws9CJqBbSf7peJ2XmqBAyN4rIsc5vmVAO+QgACCCCAABKAAAIIIAEIIIAAEoAAAgggAQgggAASgAACCCABCCCAANJob1omcjgc3Ot+vx9dsDisF8yyzK0T3O12nIHfG/DiOO7SNDX3+91tsi/vPQL+q9SsUB3OsPV6bbbb7egxx+PRnM9nt69lxaqqM1DOss1m4x2Xsfl8rmpBvCpACxTa/JO1Y0mSTAD0NJ1Onx4TRRG3Mb+acBgC6Ot2uz095nq9AujrdDp1Nu+4jOV5zkXEV1VVoUV8BGzqulZ1EVHzJCJPGHKTLPd5TdN0q9UqnM1mbqxtW3O5XDoB/vw0AqAHUaDsNvpt0YSn6knkVePXGAABBBBAAhBAAAEkAAEEEEACEEAAASQAAQQQQAIQQAABJAABBBBAAhBAAP8hoPylAww/S+w+BBgAR3eGqc0+EFMAAAAASUVORK5CYII=';
	turret.img.addEventListener('load', drawTurret, true);

	function drawTurret()
	{
		turretCtx.drawImage(turret.img, (turret.canvSize-turret.imgWidth)/2, (turret.canvSize-turret.imgHeight)/2);
	}

	var mouseObj = turret;
	var keybdObj = tank;

	function rotate(canvas, deg){
		ctx = canvas.getContext('2d');
		rad = deg*Math.PI/180
		ctx.clearRect(0,0,canvas.canvSize,canvas.canvSize);
		ctx.save();
		ctx.translate(canvas.canvSize/2,canvas.canvSize/2);
		try{
		ctx.rotate(rad);
		}catch(e){}
		ctx.drawImage(canvas.img, -canvas.imgWidth/2, -canvas.imgHeight/2, canvas.imgWidth, canvas.imgHeight);
		ctx.restore();
	}

	function followMouse(e)
	{
		if (!myTank) {
			document.removeEventListener('mousemove', followMouse, true);
			return false;
		}
		mouseX = e.pageX;
		mouseY = e.pageY;
		offX = (mouseX-mouseObj.x);
		if (offX == 0) offX = 0.01;
		offY = -1*(mouseY-mouseObj.y);
		deg = 90 - (180/Math.PI) * Math.atan( offY/offX );
		if (offX < 0)
			deg += 180;
		mouseObj.degrees = deg;
		rotate( mouseObj, deg );
	}

	function move(forward)
	{
		maxX = document.body.clientWidth - 15;
		minX = tank.imgWidth/2;

		maxY = document.body.clientHeight - 15;
		minY = tank.imgHeight/2;

		deg = tank.degrees;

		mX = Math.round( tank.speed * Math.sin( deg*Math.PI/180 ) );
		if (!forward) mX *= -1;
		turret.x = tank.x += mX; if (tank.x > maxX) tank.x = maxX; else if (tank.x < minX) tank.x = minX;
		turret.left = tank.left = tank.x-Math.floor(tank.canvSize/2);
		turret.style.left = tank.style.left = tank.left + 'px';

		mY = Math.round( tank.speed * Math.cos( deg*Math.PI/180 ) );
		if (!forward) mY *= -1;
		turret.y = tank.y -= mY; if (tank.y > maxY) tank.y = maxY; else if (tank.y < minY) tank.y = minY;
		turret.top = tank.top = tank.y-Math.floor(tank.canvSize/2);
		turret.style.top = tank.style.top = tank.top + 'px';
	}

	function turn(mvLeft)
	{
		if ( mvLeft )
		{
			keybdObj.degrees -= keybdObj.speed; if ( keybdObj.degrees < 0 ) keybdObj.degrees += 360;
		}
		else
		{
			keybdObj.degrees += keybdObj.speed; if ( keybdObj.degrees > 360 ) keybdObj.degrees -= 360;
		}
		rotate( keybdObj, keybdObj.degrees );
	}

	function forward() { move(true); }
	function backward() { move(false); }

	function left() { turn(true); }
	function right() { turn(false); }

	function doKey(e)
	{
		if (!myTank) {
			document.removeEventListener('keydown', doKey, true);
			return false;
		}
		switch( e.which )
		{
			case 87: // 'w' up
				if(tank.go==undefined)
					tank.go = setInterval(forward, delay);
				break;
			case 83: // 's' down
				if(tank.go==undefined)
					tank.go = setInterval(backward, delay);
				break;
			case 65: // 'a' left
				if(turret.go==undefined)
					turret.go = setInterval(left, delay);
				break;
			case 68: // 'd' right
				if(turret.go==undefined)
					turret.go = setInterval(right, delay);
				break;
		}
	}

	function stop(e)
	{
		if (!myTank) {
			document.removeEventListener('keyup', stop, true);
			return false;
		}
		switch( e.which )
		{
			case 87: // 'w' up
				clearInterval(tank.go);
				tank.go=undefined;
				break;
			case 83: // 's' down
				clearInterval(tank.go);
				tank.go=undefined;
				break;
			case 65: // 'a' left
				clearInterval(turret.go);
				turret.go=undefined;
				break;
			case 68: // 'd' right
				clearInterval(turret.go);
				turret.go=undefined;
				break;
		}
	}

	var cannon = function(x, y, deg, dist)
	{
		var x = x;
		var y = y;
		var degrees = deg;
		var distance = dist;

		var speed = 16;
		this.imgWidth = 80;
		this.imgHeight = 80;
		var canvSize = Math.round(Math.sqrt(this.imgWidth*this.imgWidth+this.imgHeight*this.imgHeight)); //square canvas as wide as hypotenuse for complete rotation
		var left = x-Math.floor(this.canvSize/2);
		var top = y-Math.floor(this.canvSize/2);

		var minX = this.imgWidth/2;
		var minY = this.imgHeight/2;
		var maxX = document.body.clientWidth - 15;
		var maxY = document.body.clientHeight - 15;

		var canvas = document.createElement('canvas');
		canvas.height = canvSize;
		canvas.width = canvSize;
		canvas.setAttribute('style', 'position:absolute; top:'+top+'px; left:'+left+'px; width:'+canvSize+'px; height:'+canvSize+'px; z-index:997;');
		canvas.className = 'GM_Tank_aCannon';
		document.body.appendChild(canvas);

		var ctx = canvas.getContext('2d');
		ctx.beginPath();
		ctx.fillStyle   = '#999';
		ctx.strokeStyle = '#666';
		ctx.arc(canvSize/2,canvSize/2,2,0,Math.PI*2,true);
		ctx.fill();
		ctx.stroke();

		var flying = setInterval( fly, delay );

		function fly()
		{
			var bExp = false;
			distance -= speed;
			if ( distance < 0 )
			{
				speed += distance;
			  explode();
			}

			var mX = Math.round( speed * Math.sin( degrees*Math.PI/180 ) );
			x += mX;
			left = x-Math.floor(canvSize/2);
			canvas.style.left = left + 'px';

			var mY = Math.round( speed * Math.cos( degrees*Math.PI/180 ) );
			y -= mY;
			top = y-Math.floor(canvSize/2);
			canvas.style.top = top + 'px';

			if (x > maxX || x < minX || y > maxY || y < minY) explode();
		}
		function explode()
		{
			clearInterval(flying);
			ctx.beginPath();
			ctx.fillStyle   = '#000';
			ctx.strokeStyle = '#111';
			ctx.moveTo(Math.floor(Math.random()*11),Math.floor(Math.random()*11));		// topLeft
			ctx.lineTo(canvSize*.33+Math.floor(Math.random()*11)-5,Math.floor(Math.random()*31));		// topMid
			ctx.lineTo(canvSize*.66+Math.floor(Math.random()*11)-5,Math.floor(Math.random()*31));		// topMid
			ctx.lineTo(canvSize-Math.floor(Math.random()*11),Math.floor(Math.random()*11));		// topRight
			ctx.lineTo(canvSize-Math.floor(Math.random()*31),canvSize*.33+Math.floor(Math.random()*11)-5);		// midRight
			ctx.lineTo(canvSize-Math.floor(Math.random()*31),canvSize*.66+Math.floor(Math.random()*11)-5);		// midRight
			ctx.lineTo(canvSize-Math.floor(Math.random()*11),canvSize-Math.floor(Math.random()*11));		// bottomRight
			ctx.lineTo(canvSize*.66+Math.floor(Math.random()*11)-5,canvSize-Math.floor(Math.random()*31));		// bottomMid
			ctx.lineTo(canvSize*.33+Math.floor(Math.random()*11)-5,canvSize-Math.floor(Math.random()*31));		// bottomMid
			ctx.lineTo(Math.floor(Math.random()*11),canvSize-Math.floor(Math.random()*11));		// bottomLeft
			ctx.lineTo(Math.floor(Math.random()*31),canvSize*.66+Math.floor(Math.random()*11)-5);		// midRight
			ctx.lineTo(Math.floor(Math.random()*31),canvSize*.33+Math.floor(Math.random()*11)-5);		// midRight
			ctx.closePath();
			ctx.fill();
			ctx.stroke();
		}
	}

	function fire(e)
	{
		if (!myTank) {
			document.removeEventListener('click', fire, true);
			return false;
		}
		mouseX = e.pageX;
		mouseY = e.pageY;
		offX = (mouseX-turret.x);
		offY = -1*(mouseY-turret.y);
		distance = Math.round(Math.sqrt(offX*offX+offY*offY));
		var boom = new cannon( turret.x, turret.y, turret.degrees, distance );
	}

	document.addEventListener('mousemove', followMouse, true);
	document.addEventListener('keydown', doKey, true);
	document.addEventListener('keyup', stop, true);
	document.addEventListener('click', fire, true);
}

var TankMenu = function()
{
	var menuDiv = document.createElement('div');
	menuDiv.setAttribute('style', 'position:absolute; top:0px; right:0px; height:16px; z-index:1000; cursor:pointer; margin-top:2px;');
	var menuIcon = document.createElement('canvas');
	menuIcon.setAttribute('height', '16');
	menuIcon.setAttribute('width', '16');
	menuDiv.appendChild(menuIcon);
	document.body.appendChild(menuDiv);

	var menuIconCtx = menuIcon.getContext('2d');
	var menuIconImg = new Image();
	menuIconImg.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAjRJREFUeNp0UzmrWkEUPl535bmveUU0WgiigihYioWPV1nnF6YQtJE0VqKNWigWWogYhWvEuGvE3cw35IKPmwxc7sxZvjnfd84o6O/K5XINrVYbuFwuPweDwXun0/n9+fX1K3wjUfwWCAQMkUikyGK+nM/nSbFYjMCnkADS6fTeZDIZWQB5PJ61Wq2+9/t9HXzBYPB4v9+F2WxmWS6XxHz7Uqn0Ap9KAjCbzSe73W5kQMSCLYIg0PF45L54PG643W4EW7fbpclkcpbyBGmzWq3I6/USAvHN53PCbbCLoghQYqWTzWaj/X5PMoDNZsP/SqWS1us1VSoVejwe/NxoNGg8HpNKpeLgAJYB6HQ6UigUdL1eeQKoWK1WMhqNlM1mqdfrcUqgodfr5QAOh4Mg4HQ6JafTyZORcDqdSKPRUCgUIiYi34OqDAC8UB4C/H4/5fN5zhdfoVDg4NAAtCS6H7oA3pLSoIIz6EgCwwYfxITAMgBoAMEOhwMtFgtKJpNUr9e5D3vQwe0AMhgMcgBogOVyuajdblMmk6FoNMqTcGutVqNEIsFpPGugetYAweAai8WoWq1SOBzmVbGJJLfbTWxSucj/1ADG7XZLrVaL95tNH6eCktkoY7y5Jv/VAL3FxKFduBVUkISFJAjM3gAHRadkAD6fTwNxwJGBrYfD4Z2eFqMnMCEto9GI2MtUl8vljwDsGf9gpX9iifNms/nGArfPAEyDl1Qq9Z0NmWe32/2S7H8EGACamSyS1N8W9gAAAABJRU5ErkJggg==';
	menuIconImg.addEventListener('load', drawMenuIcon, true);
	function drawMenuIcon() { menuIconCtx.drawImage(menuIconImg, 0, 0); }

	menuIcon.addEventListener('click', newTank, true);
}

var menu = new TankMenu();

var myTank;
function newTank() {
	if (!myTank)
		myTank = new Tank();
	else
	{
		// remove holes
		var rmCannons = document.evaluate("//*[@class='GM_Tank_aCannon']",
		  document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
		for (var i = rmCannons.snapshotLength - 1; i >= 0; i--)
		{
			var elm = rmCannons.snapshotItem(i);
			document.body.removeChild( elm );
		}
		var rmTank = document.evaluate("//*[@class='GM_Tank_aTank']",
			document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue;
		document.body.removeChild( rmTank );
		var rmTurret = document.evaluate("//*[@class='GM_Tank_aTurret']",
			document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue;
		document.body.removeChild( rmTurret );
		myTank = null;
	}
}