moving two pong game paddles at the same time - javascript

I have been frustrated with making a pong game. I have two paddles that I can move separately and freely as required but I miss something and they can't move at the same time as I want, it's a multiplayer game, two opponents press different keyboard keys at the same time, but something's missing in my code!
function leftPaddleMoveUp() {
leftTopLenght = leftPaddle.getBoundingClientRect().top;
if (Math.floor(leftTopLenght) === 100) {
return NaN;
} else {
leftPaddle.style.top = leftPaddleTopUp + leftPaddleTopDown + "px";
leftPaddleTopUp -= 20; // Speed
}
}
function leftPaddleMoveDown() {
leftTopLenght = leftPaddle.getBoundingClientRect().top;
if (Math.floor(leftTopLenght) === 660) {
return NaN;
} else {
leftPaddle.style.top = leftPaddleTopUp + leftPaddleTopDown + "px";
leftPaddleTopDown += 20; // Speed
}
}
function rightPaddleMoveUp() {
rightTopLenght = rightPaddle.getBoundingClientRect().top;
if (Math.floor(rightTopLenght) === 100) {
return NaN;
} else {
rightPaddle.style.top = rightPaddleTopUp + rightPaddleTopDown + "px";
rightPaddleTopUp -= 20; // Speed
}
}
function rightPaddleMoveDown() {
rightTopLenght = rightPaddle.getBoundingClientRect().top;
if (Math.floor(rightTopLenght) === 660) {
return NaN;
} else {
rightPaddle.style.top = rightPaddleTopUp + rightPaddleTopDown + "px";
rightPaddleTopDown += 20; // Speed
}
}
document.addEventListener("keypress", (event) => {
// PlayerOne&LeftSide
if (event.keyCode === 83 /*azerty & qwerty*/) {
leftPaddleMoveUp();
} else if (
event.keyCode === 87 /*azerty*/ ||
event.keyCode === 90 /*qwerty*/
) {
leftPaddleMoveDown();
}
// PlayerTwo&RightSide
else if (event.keyCode === 38 /*UpperArrow*/) {
rightPaddleMoveUp();
} else if (event.keyCode === 40 /*LowerArrow*/) {
rightPaddleMoveDown();
}
});
Is there is any method or function to accomplish this task?

You should use keydown and keyup events, and store the currently pressed keys inside an array.
const currentKeysDown = []
document.addEventListener("keydown", (event) => {
if (!currentKeysDown.includes(event.keyCode)) {
currentKeysDown.push(event.keyCode)
}
console.log(currentKeysDown)
movePaddles()
})
document.addEventListener("keyup", (event) => {
currentKeysDown.splice(currentKeysDown.indexOf(event.keyCode), 1)
console.log(currentKeysDown)
movePaddles()
})
function movePaddles() {
// PlayerOne&LeftSide
if (currentKeysDown.includes(83) /*azerty & qwerty*/ ) {
leftPaddleMoveUp();
} else if (
currentKeysDown.includes(87) /*azerty*/ ||
currentKeysDown.includes(90) /*qwerty*/
) {
leftPaddleMoveDown();
}
// PlayerTwo&RightSide
if (currentKeysDown.includes(38) /*UpperArrow*/ ) {
rightPaddleMoveUp();
} else if (currentKeysDown.includes(40) /*LowerArrow*/ ) {
rightPaddleMoveDown();
}
}
function leftPaddleMoveUp() {
console.log('Player1 moves UP')
}
function leftPaddleMoveDown() {
console.log('Player1 moves DOWN')
}
function rightPaddleMoveUp() {
console.log('Player2 moves UP')
}
function rightPaddleMoveDown() {
console.log('Player2 moves DOWN')
}

Related

How to continuously send radio signals on Micro:bit without a forever loop?

I'm trying to make a remote controlled car with a camera. I need to send radio signals constantly which depending on the message sent will do certain things. I should have to hold down the buttons on the controller to execute the code. When no button is held I need to reset the steering and the camera should go down (there is a button for it to go up). How can I send continuous radio signals to update? The micro:bit is a V2 model. We're using DF-Driver and Kitronik Game Controller.
Here's my current code:
Kitronik_Game_Controller.onButtonPress(Kitronik_Game_Controller.ControllerButtonPins.Fire1, Kitronik_Game_Controller.ControllerButtonEvents.Down, function () {
radio.sendString("S")
})
Kitronik_Game_Controller.onButtonPress(Kitronik_Game_Controller.ControllerButtonPins.Fire2, Kitronik_Game_Controller.ControllerButtonEvents.Down, function () {
radio.sendString("CU")
})
Kitronik_Game_Controller.onButtonPress(Kitronik_Game_Controller.ControllerButtonPins.Down, Kitronik_Game_Controller.ControllerButtonEvents.Down, function () {
radio.sendString("B")
})
input.onButtonPressed(Button.A, function () {
radio.sendString("CL")
})
Kitronik_Game_Controller.onButtonPress(Kitronik_Game_Controller.ControllerButtonPins.Up, Kitronik_Game_Controller.ControllerButtonEvents.Down, function () {
radio.sendString("F")
})
radio.onReceivedString(function (receivedString) {
if (receivedString == "CL" && domeServoHorizontalAngle > 0) {
domeServoHorizontalAngle += -5
}
if (receivedString == "CR" && domeServoHorizontalAngle < 180) {
domeServoHorizontalAngle += 5
}
if (receivedString == "S") {
motor.motorStopAll()
}
if (receivedString == "CU" && domeServoVerticalAngle < 180) {
domeServoVerticalAngle += 5
} else {
if (domeServoVerticalAngle > 0) {
domeServoVerticalAngle += -5
}
}
if (receivedString == "F") {
motor.MotorRun(motor.Motors.M1, motor.Dir.CCW, 255)
}
if (receivedString == "B") {
motor.MotorRun(motor.Motors.M1, motor.Dir.CW, 255)
}
if (receivedString == "L") {
motor.servo(motor.Servos.S1, 135)
} else {
if (receivedString == "R") {
motor.servo(motor.Servos.S1, 45)
} else {
motor.servo(motor.Servos.S1, 90)
}
}
motor.servo(motor.Servos.S3, 180 - domeServoHorizontalAngle)
motor.servo(motor.Servos.S2, 180 - domeServoVerticalAngle)
})
input.onButtonPressed(Button.B, function () {
radio.sendString("CR")
})
Kitronik_Game_Controller.onButtonPress(Kitronik_Game_Controller.ControllerButtonPins.Right, Kitronik_Game_Controller.ControllerButtonEvents.Down, function () {
radio.sendString("R")
})
Kitronik_Game_Controller.onButtonPress(Kitronik_Game_Controller.ControllerButtonPins.Left, Kitronik_Game_Controller.ControllerButtonEvents.Down, function () {
radio.sendString("L")
})
let domeServoVerticalAngle = 0
let domeServoHorizontalAngle = 0
domeServoHorizontalAngle = 90
domeServoVerticalAngle = 90

I want to perform different operation processes alternately in order with the same key operation

For example, you can start with a specific key and stop with a click or another key,
// Alt + Shift + ↓ Auto scroll
document.addEventListener("DOMContentLoaded", (l) => {
var m;
setInterval(m);
$(window).keydown((e) => {
//pattern 1
if (e.altKey && e.shiftKey && e.keyCode == 40) {
if (!m) {
m = setInterval((s) => {
scrollBy(0, s || 1);
}, 35);
}
}
$(document).on('click', () => {
clearInterval(m);
m = undefined;
});
//pattern 2
setInterval(m);
if (e.altKey && e.shiftKey && e.keyCode == 40) {
if (!m) {
m = setInterval((s) => {
scrollBy(0, s || 1);
}, 35);
}
}
if (e.keyCode == 96) { //ten key of「0」key
clearInterval(m);
m = undefined;
}
//}, false);
});
});
like this:
Attempting to process start and stop with the same key will not work.
In the example below
Start with Alt + Shift + ↓,
Stop as well
I want to do it with Alt + Shift + ↓. How can I correct it to implement the desired function?
The operating environment uses a third-party extension of the Chrome WEB store.
if i have understood what you want, you want to use the same keys to start and stop so, to do that you have to use a sort of toggle:
var timer;
var last_state = "keyup";
var param = 10;
$(window).on("keydown keyup", (e) => {
if (e.type == "keyup" && e.which == 40) {
last_state = "keyup";
}
if (e.type == "keydown" && e.type != last_state && e.altKey && e.shiftKey && e.which == 40) {
last_state = e.type;
if (!timer) {
timer = setInterval(() => {
scrollBy(0, param || 1);
}, 35);
} else {
clearInterval(timer);
timer = undefined;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

entire program pauses when loop is broken

I have this code which makes a square move, but when i for example press the right arrow key then the left arrow key and release the right arrow key, the square pauses for a while and then just moves the left.
is there a way to get rid of this pause?
this is the code i have now:
let velocity = 10
let x = 375
let y = 225
setInterval(function(){
document.getElementById("square").style.left = x + "px";
document.getElementById("square").style.top = y + "px";
}, 1)
var direction = ""
function currentDirection(movingToDirection){
if(movingToDirection != direction){
return true
}
else {
return false
}
}
function Sup() {
if(currentDirection("Sup")){
direction = "Sup";
var Sloopup = setInterval(function(){
y -= velocity/10
}, 1)
window.Sloopup = Sloopup
}
}
function Sdown() {
if(currentDirection("Sdown")){
direction = "Sdown";
var Sloopdown = setInterval(function(){
y += velocity/10
}, 1)
window.Sloopdown = Sloopdown
}
}
function Sleft() {
if(currentDirection("Sleft")){
direction = "Sleft";
var Sloopleft = setInterval(function(){
x -= velocity/10
}, 1)
window.Sloopleft = Sloopleft
}
}
function Sright() {
if(currentDirection("Sright")){
direction = "Sright";
var Sloopright = setInterval(function(){
x += velocity/10
}, 1)
window.Sloopright = Sloopright
}
}
function Break(Function) {
direction = ""
if (Function = "Sup") {
clearInterval(window.Sloopup)
} if (Function = "Sdown") {
clearInterval(window.Sloopdown)
} if (Function = "Sleft") {
clearInterval(window.Sloopleft)
} if (Function = "Sright") {
clearInterval(window.Sloopright)
}
}
document.addEventListener("keydown", event => {
if(event.key==="ArrowUp") {Sup()}
if(event.key==="ArrowDown") {Sdown()}
if(event.key==="ArrowLeft") {Sleft()}
if(event.key==="ArrowRight") {Sright()}
})
document.addEventListener("keyup", event => {
if(event.key==="ArrowUp") {Break("Sup")}
if(event.key==="ArrowDown") {Break("Sdown")}
if(event.key==="ArrowLeft") {Break("Sleft")}
if(event.key==="ArrowRight") {Break("Sright")}
})
and I also have a online example:
Online example
Any help is very appreciated!
Try this:
var Keys = {
up: false,
down: false,
left: false,
right: false
};
let y = 10;
let x = 10;
document.addEventListener("keydown", (event) => {
if (event.key === "ArrowLeft") Keys.left = true;
else if (event.key === "ArrowUp") Keys.up = true;
else if (event.key === "ArrowRight") Keys.right = true;
else if (event.key === "ArrowDown") Keys.down = true;
});
document.addEventListener("keyup", (event) => {
if (event.key === "ArrowLeft") Keys.left = false;
else if (event.key === "ArrowUp") Keys.up = false;
else if (event.key === "ArrowRight") Keys.right = false;
else if (event.key === "ArrowDown") Keys.down = false;
});
setInterval(() => {
if (Keys.up) {
y -= 1;
} else if (Keys.down) {
y += 1;
}
if (Keys.left) {
x -= 1;
} else if (Keys.right) {
x += 1;
}
}, 1);
setInterval(() => {
document.getElementById("app").style.left = x + "px";
document.getElementById("app").style.top = y + "px";
}, 1);
There might be some delay when you clear and set a new interval. Here I set 2 interval that keep listening to keydown, which you will need to clear later when the game ends
Here's the sandbox
so below my suggestion if I understand well your problem:
document.addEventListener("keydown", event => {
// the issue occurs here, you have to disable all current keydown event
Break("Sup");Break("Sdown");Break("Sleft");Break("Sright");
if(event.key==="ArrowUp") {Sup()}
if(event.key==="ArrowDown") {Sdown()}
if(event.key==="ArrowLeft") {Sleft()}
if(event.key==="ArrowRight") {Sright()}
})
BTW i tested it & it works, i hope that it helps you.
Good luck!
as well as we separate content from style same concept applies in different layers of the engine you need to separate the logic from the engine as well. The idea is separation so you can implement/debug much easier. Example code below:
const velocity = {x:0, y:0}
const position = {x:375, y:225}
const keys = { ArrowLeft:false, ArrowRight:false, ArrowUp:false, ArrowDown:false }
function UpdatePlayerInput()
{
velocity.x = ((+keys.ArrowRight) - (+keys.ArrowLeft)) * 10;
velocity.y = ((+keys.ArrowDown) - (+keys.ArrowUp)) * 10;
}
function PyhsicsUpdate(){
position.x += velocity.x / 10;
position.y += velocity.y / 10;
}
function RenderUpdate() {
if (document.getElementById("square").style.left !== position.x + "px")
document.getElementById("square").style.left = position.x + "px";
if (document.getElementById("square").style.top !== position.y + "px")
document.getElementById("square").style.top = position.y + "px";
}
setInterval(PyhsicsUpdate, 1)
setInterval(RenderUpdate, 10)
document.addEventListener("keydown", event => {
keys[event.key] = true;
UpdatePlayerInput();
})
document.addEventListener("keyup", event => {
keys[event.key] = false;
UpdatePlayerInput();
})
Javascript is a heavily event-driven, often asynchronous language.
window.setTimeout(() => console.log(1), 0);
console.log(2);
The above will log 2, then 1, despite the timeout having been set to 0 milliseconds. setTimeout and setTimeout delay execution of the passed function until the first tick of the event loop, after the specified interval / timeout having been exceeded. It is not expected to be immediately invoked, even with a zero-value time argument.
is there a way to get rid of this pause?
Several approaches exist.
Whichever you end up choosing, the key adjustments you have to make is to (a) separate application state from input state and (b) only update input state as a direct result from event handlers, derive position and velocity on the following (regularly scheduled) view state update. Have one data structure hold the current state of the key(s) pressed and another positional arguments.
Prior to writing code, formalize the expected outcome. What is supposed to happen, if for instance both left and right are pressed? No acceleration in either direction, because inputs cancel? Bail early and save yourself the superfluous zero-sum arithmetic.
First (last) pressed takes precedence? Don't use an object with boolean values to represent pressed keys, use a Set (or array if unavailable) and add / remove (push / prune) to it, encode order by time of insertion.
// wrap the pure string representations of keys in a common data structure
const Key = {
DOWN: 'ArrowDown',
LEFT: 'ArrowLeft',
RIGHT: 'ArrowRight',
UP: 'ArrowUp'
}
// holds currently pressed keys
const inputState = new Set([])
function handleKeyDown(event) {
inputState.add(event.key)
}
function handleKeyUp(event) {
inputState.delete(event.key)
}
document.addEventListener('keydown', handleKeyDown)
document.addEventListener('keyup', handleKeyUp)
const viewState = {
velocity: {
x: 10,
y: 10
},
position: {
x: 375,
y: 225
}
}
const targetDomNode = document.getElementById('square')
function updateTargetDomNode(x, y) {
targetDomNode.style.left = `${x}px`
targetDomNode.style.top = `${y}px`
}
function renderViewState() {
updateTargetDomNode(
viewState.position.x,
viewState.position.y
)
}
// you could abstract more, obviously
function accelerate() {
viewState.velocity.x += inputState.has(Key.LEFT) ? -1 : 0
viewState.velocity.x += inputState.has(Key.RIGHT) ? 1 : 0
viewState.velocity.y += inputState.has(Key.UP) ? -1 : 0
viewState.velocity.y += inputState.has(Key.DOWN) ? 1 : 0
}
function updatePosition(timeSinceLastUpdate) {
viewState.position.x += viewState.velocity.x * timeSinceLastUpdate
viewState.position.y += viewState.velocity.y * timeSinceLastUpdate
}
const UPDATE_INTERVAL = 50
setInterval(() => {
accelerate()
// note, this will be slightly more than 50ms,
// if you care for accuracy, use a measurement,
// rather than a static value
updatePosition(UPDATE_INTERVAL)
renderViewState()
}, UPDATE_INTERVAL)

Paper.JS - Can´t resize rectangle after it reaches minimum size

I´ve created a small script based on HitTest example from paperjs.org. The idea is to have a Rectangle and be able to move and resize it. It is almost working but, when I resize it to the minimum size I´ve specified (10x10), for some reason, I´m not able to resize it anymore, even if I release drag event and try again.
var hitOptions = {
segments: true,
stroke: true,
fill: true,
tolerance: 1
};
project.currentStyle = {
fillColor: 'green',
strokeColor: 'black'
};
var rect_a = new Path.Rectangle(new Point(50, 50), 50);
var segment, path, hitType;
var clickPos = null;
var movePath = false;
var minHeight = 10;
var minWidth = 10;
function onMouseDown(event) {
segment = path = null;
var hitResult = project.hitTest(event.point, hitOptions);
if (!hitResult)
return;
hitType = hitResult.type;
if (event.modifiers.shift) {
if (hitResult.type == 'segment') {
hitResult.segment.remove();
};
return;
}
if (hitResult) {
path = hitResult.item;
if (hitResult.type == 'segment') {
segment = hitResult.segment;
}
}
movePath = hitResult.type == 'fill';
if (movePath) {
project.activeLayer.addChild(hitResult.item);
}
clickPos = checkHitPosition(event);
}
function onMouseMove(event) {
changeCursor(event);
project.activeLayer.selected = false;
if (event.item)
event.item.selected = true;
}
function onMouseDrag(event) {
if (hitType == "stroke" || hitType == "segment") {
resizeRectangle(path, event);
} else {
path.position += event.delta;
}
}
function resizeRectangle(path, event) {
switch(clickPos) {
case "SE" :
resizeBottom(path, event);
resizeRight(path, event);
break;
case "NE" :
resizeTop(path, event);
resizeRight(path, event);
break;
case "SW" :
resizeBottom(path, event);
resizeLeft(path, event);
break;
case "NW" :
resizeTop(path, event);
resizeLeft(path, event);
break;
case "S" :
resizeBottom(path, event);
break;
case "N" :
resizeTop(path, event);
break;
case "E" :
resizeRight(path, event);
break;
case "W" :
resizeLeft(path, event);
break;
}
}
function resizeTop(path, event) {
if(path.bounds.height >= minHeight) {
path.bounds.top += event.delta.y;
}
}
function resizeBottom(path, event) {
if(path.bounds.height >= minHeight) {
path.bounds.bottom += event.delta.y;
}
}
function resizeLeft(path, event) {
if(path.bounds.width >= minWidth) {
path.bounds.left += event.delta.x;
}
}
function resizeRight(path, event) {
if(path.bounds.width >= minWidth) {
path.bounds.right += event.delta.x;
}
}
function checkHitPosition(event) {
var hitResult = project.hitTest(event.point, hitOptions);
var clickPosition = null;
if (hitResult) {
if (hitResult.type == 'stroke' || hitResult.type == 'segment') {
var bounds = hitResult.item.bounds;
var point = hitResult.point;
if (bounds.top == point.y) {
clickPosition = "N";
}
if (bounds.bottom == point.y) {
clickPosition = "S";
}
if (bounds.left == point.x) {
clickPosition = "W";
}
if (bounds.right == point.x) {
clickPosition = "E";
}
if (bounds.top == point.y && bounds.left == point.x) {
clickPosition = "NW";
}
if (bounds.top == point.y && bounds.right == point.x) {
clickPosition = "NE";
}
if (bounds.bottom == point.y && bounds.left == point.x) {
clickPosition = "SW";
}
if (bounds.bottom == point.y && bounds.right == point.x) {
clickPosition = "SE";
}
} else {
clickPosition = "C";
}
}
return clickPosition;
};
function changeCursor(event) {
var hitPosition = checkHitPosition(event);
if(hitPosition == null ) {
document.body.style.cursor = "auto";
} else {
if (hitPosition == "C") {
document.body.style.cursor = "all-scroll";
} else {
document.body.style.cursor = hitPosition + "-resize";
}
}
}
The problem is that the code shrinks the rectangle below the minimum sizes (minWidth and minHeight). You can add a line
console.log(path.bounds.width, path.bounds.height)
at the bottom of resizeRectangle to see how the rectangle becomes smaller than minWidth and minHeight.
Then when each resizeXYZZY function is called the check if(path.bounds.height >= minHeight) (or width) fails and no change is made so the rectangle can't be made larger again.
To fix it, the resizeTop function needs to work differently:
var adj = min(event.delta.y, path.bounds.height-minHeight);
path.bounds.top += adj;
And the corresponding changes should be made for resizeBottom, Left, and Right.
This avoids setting the rectangle to be smaller than the minimum and also removes any check that prevents it from growing again.

Am I using keyup correctly?

This is an excerpt from a js file
$searchBox.keyup(function(event) {
if (event.keyCode === 13) { //enter
if(currentResult > -1) {
var result = $searchResults.find('tr.result a')[currentResult];
window.location = $(result).attr('href');
}
} else if(event.keyCode === 38) { //up
if(currentResult > 0) {
currentResult--;
renderCurrent();
}
} else if(event.keyCode === 40) { //down
if(lastResults.length > currentResult + 1){
currentResult++;
renderCurrent();
}
} else {
var query = $searchBox.val();
if (lastQuery !== query) {
currentResult = -1;
if (query.length > 2) {
self.search(query);
} else {
self.hideResults();
}
if(self.hasFilter(getCurrentApp())) {
self.getFilter(getCurrentApp())(query);
}
}
}
});
This means that it should only perform the action if the "Enter", "Up" or "Down" keys are pressed, right? Because the search start happening as soon as any key is pressed.
I also tried changing searchBox.keyup to searchBox.change but that messed up how something else was working.

Categories