27.09.2018, 13:40
|
Аспирант
|
|
Регистрация: 13.08.2018
Сообщений: 79
|
|
Как сделать одноразовое нажатие клавиш.
Здравствуйте!
(Это работа с канвасом.)
Есть скрипт для одновременного нажатия клавиш, всё работает, но мне нужно сделать чтобы при нажатии, например, стрелки в верх и влево, эти клавиши срабатывали лишь раз (аналогично и с одной клавишей), т.е. нужно прервать выполнение функции после того как условие выполнится, но такое ощущения, что то условие которое я написал вообще не проверяется - это я думаю, что так надо сделать - надеюсь меня наставят на путь истинный и помогут решить эту головоломку. Другими словами, мне нужно, чтобы "player" перемещался на "speed" или по оси "х", или по "у", или по оси "х - у" одновременно (по диагонали) - нажал клавишу и держи сколько хочешь, но "player" сдвинется только на "speed", нажмёшь ещё раз - сдвинется ещё раз.
Вот скрипты:
Для обработки клавишь:
var keys = {
'W': 87,
'S': 83,
'A': 65,
'D': 68,
'LEFT': 37,
'RIGHT': 39,
'UP': 38,
'DOWN': 40,
'PAUSE': 32
};
var keyDown = {};
var setKey = function (keyCode) {
keyDown[keyCode] = true;
// console.log(keyCode);
};
var clearKey = function (keyCode) {
keyDown[keyCode] = false;
};
var isKeyDown = function (keyName) {
return keyDown[keys[keyName]] == true;
};
var isAnyKeyDown = function () {
for (var k in keyDown) {
if (keyDown[k])
return true;
}
};
window.onkeydown = function (e) {
setKey(e.keyCode);
};
window.onkeyup = function (e) {
clearKey(e.keyCode);
};
То, что должно двигаться по нажатию:
var player = {
level: 1,
hp: 3,
width: 50,
height: 50,
x: 320,
y: 240,
speed: 2,
dx: 0,
dy: 0,
score: 0,
color: randomColor(),
draw: function () {
drawRect(this.x, this.y, this.width, this.height, this.color);
},
// попытка сделать то что задумал:
move: function () {
if (this.x != this.x + this.width ||
this.y != this.y + this.height ||
this.x != this.x - this.width ||
this.y != this.y - this.height) {
if (isKeyDown('LEFT')) {
this.x -= this.speed;
this.dx = -1;
} else if (isKeyDown('RIGHT')) {
this.x += this.speed;
this.dx = 1;
} else {
this.dx = 0
}
if (isKeyDown('DOWN')) {
this.y += this.speed;
this.dy = 1;
} else if (isKeyDown('UP')) {
this.y -= this.speed;
this.dy = -1;
} else {
this.dy = 0;
}
} else {
return;
}
},
init: function (x, y) {
this.x = x;
this.y = y;
}
};
|
|
27.09.2018, 14:23
|
|
Профессор
|
|
Регистрация: 08.11.2017
Сообщений: 641
|
|
<html>
<head>
<style>
#hero {
position: fixed;
top: 100px;
left: 100px;
width: 100px;
height: 100px;
background-color: burlywood;
border: 1px dashed #cccccc;
}
</style>
</head>
<body>
<textarea id="keys"></textarea>
<div id="hero"></div>
<script>
const keys = [37, 39, 38, 40]
const speed = 5
const keyPressed = {}
const currentPosition = {
x: 100,
y: 100
}
const hero = document.getElementById('hero')
document.addEventListener('keydown', function (e) {
if (keys.includes(e.keyCode)) {
keyPressed[e.keyCode] = true
}
})
document.addEventListener('keyup', function (e) {
if (keys.includes(e.keyCode)) {
delete keyPressed[e.keyCode]
}
})
setInterval(() => {
document.getElementById('keys').value = JSON.stringify(keyPressed)
update()
}, 100)
update = () => {
if (38 in keyPressed) currentPosition.y -= speed
if (40 in keyPressed) currentPosition.y += speed
if (37 in keyPressed) currentPosition.x -= speed
if (39 in keyPressed) currentPosition.x += speed
hero.style.top = `${currentPosition.y}px`
hero.style.left = `${currentPosition.x}px`
}
</script>
</body>
</html>
у меня как-то так получилось )
|
|
27.09.2018, 14:39
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,121
|
|
canvas одноразовое нажатие клавиш
drakulawz,
вариант Rise, добавлено
Сообщение от drakulawz
|
чтобы "player" перемещался на "speed" или по оси "х", или по "у", или по оси "х - у" одновременно (по диагонали) - нажал клавишу и держи сколько хочешь, но "player" сдвинется только на "speed", нажмёшь ещё раз - сдвинется ещё раз.
|
<!DOCTYPE html>
<html>
<head>
<title>Untitled</title>
<meta charset="utf-8">
<script>
try {
'code' in KeyboardEvent.prototype || Object.defineProperty(KeyboardEvent.prototype, 'code', {
get: function () { return { 37: 'ArrowLeft', 38: 'ArrowUp', 39: 'ArrowRight', 40: 'ArrowDown' }[this.keyCode] }
})
} catch (e) {}
</script>
</head>
<body>
<canvas width="200" height="100" id="myCanvas" style="border: 1px solid red"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var rec = {};
rec.x = 10;
rec.y = 10;
rec.width = 50;
rec.height = 25;
rec.step = 5;
rec.color = 'red';
rec.moveup = function () {
this.y = Math.max(this.y - this.step, 0);
};
rec.movedown = function () {
this.y = Math.min(this.y + this.step, canvas.height - this.height);
};
rec.moveleft = function () {
this.x = Math.max(this.x - this.step, 0);
};
rec.moveright = function () {
this.x = Math.min(this.x + this.step, canvas.width - this.width);
};
rec.draw = function () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
};
rec.draw();
var move = {};
document.onkeydown = function (e) {
e.preventDefault();//только для примера тут
if(move[e.code]) return;
if (e.code == 'ArrowUp') {rec.moveup();move.ArrowUp = true }
else if (e.code == 'ArrowDown') {rec.movedown();move.ArrowDown = true }
else if (e.code == 'ArrowLeft') {rec.moveleft();move.ArrowLeft = true}
else if (e.code == 'ArrowRight') {rec.moveright();move.ArrowRight = true}
else return;
rec.draw();
};
document.onkeyup = function (e) {
if (e.code == 'ArrowUp') move.ArrowUp = false;
else if (e.code == 'ArrowDown') move.ArrowDown = false;
else if (e.code == 'ArrowLeft') move.ArrowLeft = false;
else if (e.code == 'ArrowRight') move.ArrowRight = false;
};
</script>
</body>
</html>
Последний раз редактировалось рони, 27.09.2018 в 14:42.
|
|
27.09.2018, 14:43
|
Аспирант
|
|
Регистрация: 13.08.2018
Сообщений: 79
|
|
Сообщение от SuperZen
|
у меня как-то так получилось )
|
Перефразирую:
мне нужно, что бы после того как нажалась стрелка (любая или две для диагонали), ивент прекращался и плеер был перемещён на спид - всё, он не должен больше двигаться сколько бы клавиша не держалась. Нажал ещё раз - тот же эффект, ещё раз - аналогично. Вот такое решение мне нужно. Плеер не должен перемещаться когда держишь клавишу нажатой! Только один шаг - одно нажатие!
|
|
27.09.2018, 14:46
|
Аспирант
|
|
Регистрация: 13.08.2018
Сообщений: 79
|
|
рони,
Круто! Благодарю!
#offtop Кстати, кто-нибудь может сталкивался, не работают всплывающие окна в браузере (UC Browser) - ничего не менял (не помню по крайней мере), вот когда плюсик возле "Карма" жму ничего не выпадает - как и с остальными диалогами на сайте (и на всех остальных). Может какая-то комбинация клавиш такое делает? Если кто не в курсе - это тот же гугл хром (на его основе спиляно).
Последний раз редактировалось drakulawz, 27.09.2018 в 14:51.
|
|
27.09.2018, 15:09
|
|
Профессор
|
|
Регистрация: 08.11.2017
Сообщений: 641
|
|
<html>
<head>
<style>
#hero {
position: fixed;
top: 100px;
left: 100px;
width: 100px;
height: 100px;
background-color: burlywood;
border: 1px dashed #cccccc;
}
</style>
</head>
<body>
<textarea id="keys"></textarea>
<textarea id="previous_keys"></textarea>
<div id="hero"></div>
<script>
const keys = [37, 39, 38, 40]
const speed = 5
const keyPressed = {}
let previousKeyPressed = {}
const currentPosition = {
x: 100,
y: 100
}
const hero = document.getElementById('hero')
document.addEventListener('keydown', function (e) {
e.preventDefault()
if (keys.includes(e.keyCode)) {
keyPressed[e.keyCode] = true
}
})
document.addEventListener('keyup', function (e) {
e.preventDefault()
if (keys.includes(e.keyCode)) {
delete keyPressed[e.keyCode]
}
})
setInterval(() => {
document.getElementById('keys').value = JSON.stringify(keyPressed)
document.getElementById('previous_keys').value = JSON.stringify(previousKeyPressed)
update()
}, 100)
update = () => {
if (38 in keyPressed && !(38 in previousKeyPressed)) currentPosition.y -= speed
if (40 in keyPressed && !(40 in previousKeyPressed)) currentPosition.y += speed
if (37 in keyPressed && !(37 in previousKeyPressed)) currentPosition.x -= speed
if (39 in keyPressed && !(39 in previousKeyPressed)) currentPosition.x += speed
hero.style.top = `${currentPosition.y}px`
hero.style.left = `${currentPosition.x}px`
previousKeyPressed = { ...keyPressed }
}
</script>
</body>
</html>
|
|
27.09.2018, 15:20
|
Аспирант
|
|
Регистрация: 13.08.2018
Сообщений: 79
|
|
рони, а почему нужно использовать именно Math.max и Math.min?
Разве не правильней будет Math.ceil ?
|
|
27.09.2018, 15:26
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,121
|
|
Сообщение от drakulawz
|
а почему нужно использовать именно Math.max и Math.min?
|
так проще всего получить ограничение диапазона, без всяких if.
Сообщение от drakulawz
|
Math.ceil
|
не знаю каким образом это применить.
|
|
27.09.2018, 15:27
|
Аспирант
|
|
Регистрация: 13.08.2018
Сообщений: 79
|
|
SuperZen, не работает ведь. И я не понимаю, по большей части 50% вашего кода. Вариант рони, мне подходит.
|
|
27.09.2018, 15:28
|
Аспирант
|
|
Регистрация: 13.08.2018
Сообщений: 79
|
|
Сообщение от рони
|
не знаю каким образом это применить.
|
Так если у меня координаты дробными получаются, разве не лучше применить Math.ceil ? Или в канвасе лучше так не делать?
А, не так выразился. Имею в виду, если взять вот так:
в функции движения сделать так:
this.x = this.x + this.step
а уже в инициализации отрисовки:
Math.ceil(canvas.width - player.width)
Последний раз редактировалось drakulawz, 27.09.2018 в 15:37.
|
|
|
|