MOUSE ACTIONS:
var held, mouseX, mouseXInitial;
window.addEventListener('mousedown',function(e){
held = true;
mouseXInitial = mouseX;
});
window.addEventListener('mouseup',function(e){
held = false;
});
window.addEventListener('mousemove',function(e){
mouseX = e.clientX;
});
mouseEvents();
环顾四周(在屏幕上拖动环顾四周):
var sharedParentObject = {
scrolledAmount: null,
scrolling: function(){
if (held){
this.scrolledAmount = mouseX - mouseXInitial;
this.x = this.xInitial + this.scrolledAmount;
}
},
inputShared: function(){
var that = this;
window.addEventListener('mousedown',function(e){
that.xInitial = that.x;
});
window.addEventListener('mousemove',function(e){
that.scrolling();
});
}
}
移动角色:
function Character(){
this.speed = 2;
this.target = null;
this.input = function(){
var that = this;
window.addEventListener('mouseup',function(e){
that.target = that.mouseXInitial;
that.target += that.scrolledAmount;
});
}
this.update = function(){
if (this.target){
//moving right
if (this.x + this.w/2 < this.target){
this.x += this.speed;
}
//moving left
if (this.x + this.w/2 > this.target){
this.x -= this.speed;
}
}
}
}
Character.prototype = Object.create(sharedParentObject);
这样可行,但问题是,一旦我开始在屏幕上拖动环顾四周,当角色已经走路时,它会变得奇怪而且紧张。我明白为什么会这样。字符的x在字符类和父类中同时被更改。有没有办法让角色能够继续向目标走去,同时在我滚动环境时仍然会被移动?有点做两件事,没有一个影响对方..
答案 0 :(得分:0)
您需要做的就是跟踪鼠标在onmousedown和onmouseup事件之间移动的距离。如果距离非常小,则用户点击了一个点,如果距离较大,则他们试图平移场景。
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
display: block;
margin-top: 20px;
margin-left: auto;
margin-right: auto;
border: solid 1px white;
border-radius: 10px;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
// ES5 Friendly class functions
// (Supports overloading & single inheritance)
var _class = (function() {
"use strict";
/*
All a class is in JS is a function that
acts as a constructor and an object (prototype)
that holds the properties shared across all
instances (static vars, constants & functions).
*/
function _class(constructor,prototype) {
prototype.base = null;
prototype.super = constructor;
constructor.prototype = prototype;
return constructor;
}
_class.extends = function(base,constructor,prototype) {
for (var property in base.prototype) {
if (!prototype[property]) {
prototype[property] = base.prototype[property];
}
}
function bundledConstructor() {
base.apply(this,arguments);
constructor.apply(this,arguments);
}
prototype.base = base;
prototype.super = bundledConstructor;
bundledConstructor.prototype = prototype;
return bundledConstructor;
}
return _class;
})();
void function() {
"use strict";
// Classes
// Encapsulate canvas element
var Viewport = _class(
function(canvasID,width,height,bgColour) {
this.canvas = document.getElementById(canvasID) || null;
this.width = width || 1.0;
this.height = height || 1.0;
this.bgColour = bgColour || "gray";
this.hWidth = this.width >> 1;
this.hHeight = this.height >> 1;
this.canvas.width = this.width;
this.canvas.height = this.height;
this.ctx = this.canvas.getContext("2d");
this.ctx.translate(this.hWidth,this.hHeight);
var bounds = this.canvas.getBoundingClientRect();
this.leftMargin = bounds.left;
this.topMargin = bounds.top;
},{
clear: function() {
var ctx = this.ctx;
ctx.fillStyle = this.bgColour;
ctx.fillRect(-this.hWidth,-this.hHeight,this.width,this.height);
}
}
);
// This is a class used to encapsulate
// the scene's panning/zooming.
var Camera = _class(
// Constructor Function
function(viewport,x,y) {
this.viewport = viewport || null;
this.x = x || 0.0;
this.y = y || 0.0;
this.scale = 1.0;
this.invScale = 1.0 / this.scale;
this.allowUserInput = false;
this.mouseDown = false;
this.mouseLastX = 0.0;
this.mouseLastY = 0.0;
viewport.canvas.addEventListener("wheel",this.onwheel.bind(this));
viewport.canvas.addEventListener("mousedown",this.onmousedown.bind(this));
viewport.canvas.addEventListener("mouseup",this.onmouseup.bind(this));
viewport.canvas.addEventListener("mousemove",this.onmousemove.bind(this));
},
// Prototype (constant values & functions go here)
{
scaleCoordinates: function(x,y) {
return [
(x - this.viewport.hWidth) * this.invScale + this.x,
(y - this.viewport.hHeight) * this.invScale + this.y
];
},
scaleDimensions: function(width,height) {
return [
width * this.invScale,
height * this.invScale
];
},
pan: function(deltaX,deltaY) {
this.x += deltaX;
this.y += deltaY;
},
zoom: function(deltaScale) {
this.scale += deltaScale;
this.scale = Math.max(0.0,this.scale);
this.invScale = 1.0 / this.scale;
},
onwheel: function(e) {
if (this.allowUserInput) {
var deltaY = -Math.sign(e.deltaY) * (e.deltaY / e.deltaY) * 0.25;
this.zoom(deltaY);
}
},
onmousedown: function(e) {
this.mouseDown = true;
[
this.mouseLastX,
this.mouseLastY
] = this.scaleCoordinates(
e.clientX - this.viewport.leftMargin,
e.clientY - this.viewport.topMargin
);
},
onmouseup: function(e) {
this.mouseDown = false;
},
onmousemove: function(e) {
if (this.allowUserInput && this.mouseDown) {
var [
mouseX,
mouseY
] = this.scaleCoordinates(
e.clientX - this.viewport.leftMargin,
e.clientY - this.viewport.topMargin
);
this.pan(
this.mouseLastX - mouseX,
this.mouseLastY - mouseY
);
}
}
}
);
// Contains basic behaviour all game objects will have
var GameObject = _class(
function(x,y,width,height,colour) {
this.x = x || 0.0;
this.y = y || 0.0;
this.width = width || 1.0;
this.height = height || 1.0;
this.colour = colour || "darkblue";
this.dx = 0.0;
this.dy = 0.0;
this._draw_x = 0.0;
this._draw_y = 0.0;
this._draw_width = 0.0;
this._draw_height = 0.0;
},{
updateDrawParameters: function(camera) {
this._draw_width = this.width * camera.scale;
this._draw_height = this.height * camera.scale;
this._draw_x = ((this.x - camera.x) * camera.scale) - this._draw_width * 0.5;
this._draw_y = ((this.y - camera.y) * camera.scale) - this._draw_height * 0.5;
},
tick: function() {
},
render: function(viewport) {
var ctx = viewport.ctx;
ctx.fillStyle = this.colour;
ctx.strokeStyle = "black";
ctx.lineWidth = 2;
ctx.beginPath();
ctx.rect(this._draw_x,this._draw_y,this._draw_width,this._draw_height);
ctx.fill();
ctx.stroke();
}
}
);
// A more specialized type of game object that
// can move to a specific location
var MoveAgent = _class.extends(GameObject,
function(x,y,width,height,colour) {
this.currentState = this.STATE_IDLE;
this.targetX = 0.0;
this.targetY = 0.0;
},{
STATE_IDLE: 1000,
STATE_MOVING_TO_TARGET: 1001,
MOVE_SPEED: 1.0,
GOAL_TOLERANCE: 5.0, // How close is 'good enough' to the target
moveTo: function(x,y) {
this.targetX = x || 0.0;
this.targetY = y || 0.0;
this.currentState = this.STATE_MOVING_TO_TARGET;
},
tick: function() {
switch(this.currentState) {
case this.STATE_IDLE:
break;
case this.STATE_MOVING_TO_TARGET:
var x = this.targetX - this.x;
var y = this.targetY - this.y;
var l = x * x + y * y;
if (l < this.GOAL_TOLERANCE * this.GOAL_TOLERANCE) {
this.currentState = this.STATE_IDLE;
} else {
l = 1.0 / Math.sqrt(l);
this.dx = x * l * this.MOVE_SPEED;
this.dy = y * l * this.MOVE_SPEED;
this.x += this.dx;
this.y += this.dy;
}
break;
}
}
}
);
var ControlledMoveAgent = _class.extends(MoveAgent,
function(x,y,width,height,colour,camera) {
this.camera = camera || null;
this.mouseDown = false;
this.mouseX = 0.0;
this.mouseY = 0.0;
viewport.canvas.addEventListener("mousedown",this.onmousedown.bind(this));
viewport.canvas.addEventListener("mouseup",this.onmouseup.bind(this));
viewport.canvas.addEventListener("mousemove",this.onmousemove.bind(this));
},{
MOVE_TOLLERANCE: 5.0,
onmousedown: function(e) {
if (e.button === 0) {
this.mouseDown = true;
this.mouseX = e.clientX;
this.mouseY = e.clientY;
}
},
onmouseup: function(e) {
if (e.button === 0 && this.mouseDown) {
this.mouseDown = false;
var x = e.clientX - this.camera.viewport.leftMargin;
var y = e.clientY - this.camera.viewport.topMargin;
[x,y] = this.camera.scaleCoordinates(x,y);
this.moveTo(x,y);
}
},
onmousemove: function(e) {
if (this.mouseDown) {
var x = this.mouseX - e.clientX;
var y = this.mouseY - e.clientY;
var l = Math.sqrt(x * x + y * y);
if (l > this.MOVE_TOLLERANCE) {
this.mouseDown = false;
}
}
}
}
);
// Vars
var camera = null;
var viewport = null;
var scenery = [];
var character = null;
// Functions
function loop() {
// Tick
for (var i = 0; i < scenery.length; ++i) {
scenery[i].updateDrawParameters(camera);
}
character.tick();
character.updateDrawParameters(camera);
// Render
viewport.clear();
for (var i = 0; i < scenery.length; ++i) {
scenery[i].render(viewport);
}
character.render(viewport);
//
requestAnimationFrame(loop);
}
// Entry Point
onload = function() {
viewport = new Viewport("canvas",180,160,"gray");
camera = new Camera(viewport,0,0);
camera.allowUserInput = true;
camera.zoom(0.25);
for (var i = 0; i < 10; ++i) {
scenery[i] = new GameObject(
180 * Math.random() - 90,
160 * Math.random() - 80,
10 + Math.random() * 10,
10 + Math.random() * 10,
"#" + ((Math.random() * 255) | 0).toString(16)
+ ((Math.random() * 255) | 0).toString(16)
+ ((Math.random() * 255) | 0).toString(16)
);
}
character = new ControlledMoveAgent(0,0,10,10,"darkred",camera);
loop();
}
}()
</script>
</body>
</html>
&#13;