I'm a beginner to p5js and code in general. I'm working on a (hopefully) interactive website for one of my classes that uses two separate sketches that are controlled by the DOM. I think that the 3D and 2D rendering modes are fighting each other. Both of the sketches work perfectly separate from one another. I get this error message in Chrome developer "p5.js:16124 Uncaught not supported in p2d. Please use webgl mode". Here is my code:
HTML
<html>
<head>
<meta charset="UTF-8">
<script language="javascript" type="text/javascript" src="libraries/p5.js"></script>
<script language="javascript" src="libraries/p5.dom.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
<script language="javascript" type="text/javascript" src="sketch2.js"></script>
<style> body {padding: 0; margin: 0;} </style>
</head>
<body>
<div id="text" style="background: none; position: absolute; color: white; font-family: avenir,sans-serif; width: 250px; margin-left: 140px; margin-top: 50px; line-height: 15pt; font-size: 9pt; z-index:1;">
<p>
text
</p>
</div>
<div id="myContainer" style="background:none; position:absolute; z-index:-1; width:100%;height:100%;"></div>
<div id="myContainer2" style="background:none; position:absolute; z-index:-2; width:100%;height:100%;"></div>
</body>
</html>
Sketch 1
function setup(){
var myCanvas = createCanvas(windowWidth, windowHeight,WEBGL);
myCanvas.parent('myContainer2');
}
function draw(){
background(0,0,0);
rotateY(frameCount * 0.01);
for(var j = 0; j < 50; j++){
push();
for(var i = 0; i < 80; i++){
translate(sin(frameCount * 0.02 + j) * 150, sin(frameCount * 0.1 + j) * 110, i * 0.9);
rotateZ(frameCount * 0.04);
push();
sphere(10, 15, 5);
pop();
}
pop();
}
}
Sketch 2
var input, button;
function setup() {
// create canvas
var myCanvas = createCanvas(windowWidth, windowHeight);
myCanvas.parent('myContainer');
background(255,255,255,0);
input = createInput();
input.position(140, 675);
button = createButton('Share');
button.position(280, 676);
button.mousePressed(greet);
textAlign(CENTER)
textSize(15);
}
function greet() {
var name = input.value();
for (var i=0; i<1; i++) {
push();
fill(255,255,0);
translate(random(width), random(height));
text(name, 0, 0);
pop();
}
}
This operation doesn't work with 2d (GitHub). If you want to reverse x-coordinate and create object mirroring, just set translate and use -x for all x coordinates.
line(this.mirroring*0.5*grid_step, 0, this.mirroring*0.5*grid_step, 0.5*grid_step);
line(this.mirroring*2.5*grid_step, 0, this.mirroring*2.5*grid_step, 0.5*grid_step);
line(this.mirroring*0.5*grid_step, 0.25*grid_step, this.mirroring*2.5*grid_step, 0.25*grid_step);
Where this.mirroring can be -1 or 1. When this.mirroring = -1; reverse is toggled
Related
I am trying to render the key points to a canvas that I can getting from Blaze Pose, but I can't seem to get them drawing the canvas. I know the x and y for each key point and being retrieved but I can't get them showing up on the canvas. I have tried changing the styling but no luck so far. Thanks for the help.
const video = document.getElementById('webcam');
const canvas = document.getElementById('output')
const liveView = document.getElementById('liveView');
const demosSection = document.getElementById('demos');
const enableWebcamButton = document.getElementById('webcamButton');
const ctx = canvas.getContext("2d");
let poses;
function getUserMediaSupported() {
return !!(navigator.mediaDevices &&
navigator.mediaDevices.getUserMedia);
}
if (getUserMediaSupported()) {
enableWebcamButton.addEventListener('click', enableCam);
} else {
console.warn('getUserMedia() is not supported by your browser');
}
// Enable the live webcam view and start classification.
function enableCam(event) {
if (!model) {
return;
}
// Hide the button once clicked.
event.target.classList.add('removed');
// getUsermedia parameters to force video but not audio.
const constraints = {
video: true
};
document.getElementById('output').style.zIndex = "6";
// Activate the webcam stream.
navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
video.srcObject = stream;
video.addEventListener('loadeddata', predictWebcam);
});
}
async function predictWebcam() {
const videoHeight = video.videoHeight;
const videoWidth = video.videoWidth;
video.width = videoWidth;
video.height = videoHeight;
canvas.width = videoWidth;
canvas.height = videoHeight;
poses = await detector.estimatePoses(video)
//ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
if(poses && poses.length > 0){
for(const pose of poses){
if(pose.keypoints != null){
drawKeypoints(pose.keypoints);
}
}
}
window.requestAnimationFrame(predictWebcam);
}
function drawKeypoints(keypoints){
for(let i = 0; i < keypoints.length; i++){
drawKeypoint(keypoints[i]);
}
}
function drawKeypoint(keypoint){
ctx.fillStyle = 'Orange';
ctx.strokeStyle = 'Green';
ctx.lineWidth = 2;
const radius = 4;
const circle = new Path2D();
circle.arc(keypoint.x, keypoint.y, radius, 0, 2 * Math.PI)
ctx.fill(circle)
ctx.stroke(circle)
}
// Store the resulting model in the global scope of our app.
let model = undefined;
let detector = undefined;
// Before we can use BlazePose class we must wait for it to finish
async function loadModel(){
model = poseDetection.SupportedModels.BlazePose;
const detectorConfig = {
runtime: 'tfjs',
enableSmoothing: true,
modelType: 'full'
};
detector = await poseDetection.createDetector(model, detectorConfig);
demosSection.classList.remove('invisible');
}
loadModel();
<!DOCTYPE html>
<html lang="en">
<head>
<title>Measuring App</title>
<meta charset="utf-8">
<!-- Import the webpage's stylesheet -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Measuring App</h1>
<p>Wait for the model to load before clicking the button to enable the webcam - at which point it will become visible to use.</p>
<section id="demos" class="invisible">
<div id="liveView" class="camView">
<button id="webcamButton">Enable Webcam</button>
<canvas id="output"></canvas>
<video id="webcam" autoplay muted width="640" height="480"></video>
</div>
</section>
<!-- Import TensorFlow.js library -->
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs/dist/tf.min.js" type="text/javascript"></script>
<!-- Load the coco-ssd model to use to recognize things in images -->
<script src="https://cdn.jsdelivr.net/npm/#tensorflow-models/pose-detection"></script>
<!-- Import the page's JavaScript to do some stuff -->
<script src="script.js" defer></script>
</body>
</html>
body {
font-family: helvetica, arial, sans-serif;
margin: 2em;
color: #3D3D3D;
}
h1 {
font-style: italic;
color: #FF6F00;
}
video {
display: block;
}
section {
opacity: 1;
transition: opacity 500ms ease-in-out;
}
.removed {
display: none;
z-index: -10;
}
.invisible {
opacity: 0.2;
}
.camView {
position: relative;
float: left;
width: calc(100% - 20px);
margin: 10px;
cursor: pointer;
}
.camView p {
position: absolute;
padding: 5px;
background-color: rgba(255, 111, 0, 0.85);
color: #FFF;
border: 1px dashed rgba(255, 255, 255, 0.7);
z-index: 1;
font-size: 12px;
}
#output {
position: absolute;
z-index: -100;
top: 0;
bottom: 0;
left: 0;
}
I've recently stared coding a js/html canvas file and I've noticed a big problem that I cannot solve. The problem is that the LiverSever extension suddenly stopped working. What I mean by this is out of random it just stopped working. When I try to open it, it opens in the browser but keeps on loading. I have tried many fixes but none of them seem to work. The html port "link" is," http://127.0.0.1:49423/index.html" So I was wondering if I could get some help?
html code below:
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas</title>
<style>
canvas {
border: 1px solid lightyellow;
background: lightyellow;
}
body {
margin: 0;
}
.tooltip {
width: 100px;
position: absolute;
top: auto;
bottom: 800px;
right: 887px;
left: auto;
font-size: xx-large;
}
</style>
</head>
<body>
<canvas></canvas>
<script src="Main_Game.js">
</script>
<div class="tooltip">Money:
<script type="text/javascript">document.write(Moneys)</script>
</div>
</body>
</html>
js code:
var canvas = document.querySelector('canvas');
canvas.width = 1920;
canvas.height = 1080;
var middlex = canvas.width/2;
console.log(middlex + " - x");
var middley = canvas.height/2;
console.log(middley + " - y");
console.log(canvas);
var c = canvas.getContext('2d');
c.fillStyle = 'rgba(255,0,0)';
c.fillRect(25,540,940,250);
c.fillRect(25, 815, 940,250);
c.fillRect(985,540,915,250);
c.fillRect(985,815,915,250);
c.beginPath();
c.arc(200, 200, 30, 0, Math.PI*2, false);
c.strokeStyle = 'blue';
c.stroke();
var Moneys = 0;
while (true) {
Moneys += 1;
}
I do not know how to delete. I figured out that the name for the html was not the same as the js file
How do I get my canvas animation of the rain to start when the play button is clicked and vice versa (stop the rain when the pause button is clicked)?
I really would appreciate a helping hand.
So far I have the rain animation to play as soon as the window is loaded and the audio in the background is the only thing that plays when interacting with the play button.
I'm not sure how to go about getting the rain animation to start so that the audio also plays in sync with the rain and vice versa.
// Get the canvas and context and store in variables
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
// Set canvas dimensions to window height and width
canvas.width = window.innerHeight;
canvas.height = window.innerHeight;
// Generate the raindrops and apply attributes
var rainNum = 200; // max raindrops
var rainDrops = [];
let isClicked = true;
// Loop through the empty raindrops and apply attributes
for (var i = 0; i < rainNum; i++) {
rainDrops.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
})
}
// Draw raindrops onto canvas
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height);
context.lineWidth = 0.1;
context.strokeStyle = "white";
context.beginPath();
for (var i = 0; i < rainNum; i++) {
var r = rainDrops[i];
context.moveTo(r.x, r.y);
context.lineTo(r.x, r.y + 30);
rainDrops[i].y += 13;
context.stroke();
}
if (isClicked == true) {
moveRain();
} else {
return false
}
window.requestAnimationFrame(draw);
}
window.requestAnimationFrame(draw);
// Animate the raindrops
function moveRain() {
for (var i = 0; i < rainNum; i++) {
// Store current raindrops
var r = rainDrops[i];
// If the rain reaches the bottom, send a new one to the top
if (r.y > canvas.height) {
rainDrops[i] = {
x: Math.random() * canvas.width,
y: 0
};
}
}
}
// Create a reference to the audio
var audioOne = document.querySelector("#audio-1");
function playAudio() {
if (isClicked == true) {
isClicked = false
audioOne.pause();
btn.className = "play";
} else if (isClicked == false) {
isClicked = true
audioOne.play();
btn.className = "pause";
draw()
}
}
html {
height: 100%;
width: 100%;
}
body {
height: 100vh;
width: 100vw;
margin: 0;
padding: 0;
overflow: hidden;
}
canvas {
height: 100%;
width: 100%;
background-color: transparent;
position: absolute;
z-index: 10;
}
#sky-top {
height: 100%;
width: 100%;
position: absolute;
z-index: 1;
animation: lightning 20s ease-in-out infinite;
}
#keyframes lightning {
/****** This will create a lightning effect every 20 seconds ******/
0% {
background-color: rgb(46, 46, 46);
}
6.25% {
background-color: rgb(46, 46, 46);
}
8% {
background-color: rgb(255, 255, 255);
}
9% {
background-color: rgb(46, 46, 46);
}
11% {
background-color: rgb(255, 255, 255);
}
30% {
background-color: rgb(46, 46, 46);
}
100% {
background-color: rgb(46, 46, 46);
}
}
#sky-bottom {
height: 100%;
width: 100%;
position: absolute;
z-index: 2;
background: linear-gradient(rgba(255, 255, 255, 0), rgb(45, 45, 45));
}
.center-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
text-align: center;
z-index: 20;
background-color: transparent;
}
.button-center {
position: absolute;
top: 40%;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
-ms-transform: translateY(-50%);
-o-transform: translateY(-50%);
transform: translateY(-50%);
-webkit-transform: translateX(-50%);
-moz-transform: translateX(-50%);
-ms-transform: translateX(-50%);
-o-transform: translateX(-50%);
transform: translateX(-50%);
}
.center-container:after,
.button-center {
display: inline-block;
vertical-align: middle;
}
#btn {
height: 130px;
width: 130px;
border: none;
background-size: 100% 100%;
outline: none;
}
.play {
background: url('../image/play-button.png');
border-radius: 50%;
cursor: pointer;
-webkit-filter: drop-shadow(2px 2px 2px #666666);
filter: drop-shadow(2px 2px 2px #666666);
}
.pause {
background: url('../image/pause-button.png');
border-radius: 50%;
cursor: pointer;
-webkit-filter: drop-shadow(2px 2px 2px #666666);
filter: drop-shadow(2px 2px 2px #666666);
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Rain</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Relax your mind with some rain and thunder.">
<link href="css/styles.css" type="text/css" rel="stylesheet">
</head>
<body>
<div id="sky-top"></div>
<div id="sky-bottom"></div>
<canvas id="canvas"></canvas>
<div class="center-container">
<div class="button-center">
<button id="btn" class="play" class="pause" onclick="playAudio()"></button>
</div>
<audio src="audio/rain-and-thunder.mp3" id="audio-1" loop="loop" type="audio/mp3"></audio>
</div>
<script src="js/script.js"></script>
</body>
</html>
First off, the audio file won't work for me here locally (I downloaded my own mp3 - I am working on getting it to work now), so I focused on playing/pausing the canvas animation and ignored the sound functionality. Let's start with the HTML:
<html>
<head>
<link rel = "stylesheet"
type = "text/css"
href = "index.css" />
</head>
<body>
<canvas id="canvas"></canvas>
<div class="center-container">
<div class="button-center">
<button id="btn" class="play" class="pause" onclick="playAudio()"></button>
</div>
<audio loop="loop" id="audio-1" width="100%" height="auto">
<source src="audio/rain-and-thunder.mp3" type="audio/mpeg">
</audio>
</div>
</body>
<script src='index.js'></script>
</html>
You'll see I did a few things to display the canvas properly. For whatever reason, I couldn't see your button and the canvas was showing up blank. I decided to inline CSS the width and height, as well as put the script within the body.
Also, since we are ignoring the sound functionality, I renamed the function to startStopRain() to make more sense in your JS file. Let's talk about that next:
// Get the canvas and context and store in variables
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var audioOne = document.getElementById("audio-1");
// Set canvas dimensions to window height and width
canvas.width = window.innerHeight;
canvas.height = window.innerHeight;
// Generate the raindrops and apply attributes
var rainNum = 200; // max raindrops
var rainDrops = [];
let isClicked = false
// Loop through the empty raindrops and apply attributes
for(var i = 0; i < rainNum; i ++)
{
rainDrops.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
})
}
// Draw raindrops onto canvas
function draw()
{
context.clearRect(0, 0, canvas.width, canvas.height);
context.lineWidth = 0.1;
context.strokeStyle = "red";
context.beginPath();
for(var i = 0; i < rainNum; i ++)
{
var r = rainDrops[i];
context.moveTo(r.x, r.y);
context.lineTo(r.x, r.y + 30);
rainDrops[i].y += 13;
context.stroke();
}
if (isClicked == true) {
moveRain();
} else{
return false
}
document.getElementById("canvas").onclick = moveRain();
window.requestAnimationFrame(draw);
}
window.requestAnimationFrame(draw);
// Animate the raindrops
function moveRain(){
for(var i = 0; i < rainNum; i++)
{
// Store current raindrops
var r = rainDrops[i];
// If the rain reaches the bottom, send a new one to the top
if(r.y > canvas.height) {
rainDrops[i] = {x: Math.random() * canvas.width, y: 0};
}
}
}
// Create a reference to the audio
// need to figure out why the audio wont play - this is new to me :D
function playAudio(){
audioOne.play();
if (isClicked == true){
isClicked = false
audioOne.pause();
} else if (isClicked == false){
isClicked = true
audioOne.play();
draw()
}
}
Your original intent was to use two class names on the btn so you could distinguish between play/pause. While there are use cases for using multiple class names, I don't personally believe this is one of them. Instead, I used a global isClicked variable in the script so I could control the flow of the functions.
Follow the isClicked variable from top to bottom to better understand how I used it to call/stop functions. Minus initializing the variable at the top, you'll notice it shows up in only two functions: draw() and startStopRain().
EDIT: The flow control for the sound should be no different. You can use the same isClicked boolean value to determine when the sound should be played or not. If you want, I can update it to reflect that but truthfully, that would be good practice for you. Also, I changed the id of the button to audio-1 since the original code was selecting the element via that specific id
This is my code for bubble sort algorithm simulator. Algorithm works and prints output correctly. But I want to delay each step for 2 seconds and then display output. That means I want to delay each iteration of inner for loop of bubble sort. Thank you.
<!DOCTYPE html>
<html>
<head>
<style>
input[type=text], select {
width: 60px;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
input[type=button] {
width: 70px;
background-color: #4CAF50;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
border-radius: 4px;
cursor: pointer;
}
input[type=button]:hover {
background-color: #45a049;
}
div {
width:500px;
border-radius: 5px;
background-color: #f2f2f2;
padding: 20px;
margin:0 auto;
}
Canvas{
padding-left: 0;
padding-right: 0;
margin-left: auto;
margin-right: auto;
margin-top:10px;
display: block;
border-radius: 5px;
background-color: #f2f2f2;
}
#pp{
width:300px;
margin-left:3px;
}
#alltext{
height:300px;
width:500px;
}
</style>
</head>
<body>
<h3 align="center"style="text-decoration:underline">Algoritham Simulator</h3>
<div align="center">
<form >
<label >Insert Numbers </label>
<input id="pp" type="text" >
<input type="button" onClick="myMove()" value="Sort" >
</form>
</div>
<canvas id="myCanvas" height="10000" width="900">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script>
var height1 = 10;
var height2 = 50;
var count =0;
var canvas;
var ctx;
function setCanvas(){
canvas = document.getElementById('myCanvas');
ctx = canvas.getContext('2d');
ctx.canvas.height =10000;
ctx.canvas.width = 900;
}
function draw(cars,j){
height1+=85;
height2+=85;
count++;
var rectSize = 80;
var horizontalGap=1;
for(var i=0;i<cars.length;i++) {
if(i==j || i==j+1){
ctx.beginPath();
ctx.fillStyle="green";
ctx.fillRect((rectSize+horizontalGap),height1,rectSize,rectSize);
ctx.closePath();
ctx.fillStyle="white";
}else{
ctx.beginPath();
ctx.fillStyle="black";
ctx.fillRect((rectSize+horizontalGap),height1,rectSize,rectSize);
ctx.closePath();
ctx.fillStyle="white";
}
var text = cars[i];
ctx.fillText(text, (rectSize+40)+horizontalGap ,height2);
horizontalGap+=100;
}
}
function myMove() {
setCanvas();
var yourArray = [];
var inputText = document.getElementById("pp").value;
yourArray=inputText.split(",");
bubbleSort(yourArray);
}
function bubbleSort(items) {
var length = items.length;
for (var i = 0; i < length; i++) { //Number of passes
var c=0;
for (var j = 0; j < (length - i - 1); j++) { //Notice that j < (length - i)
//Compare the adjacent positions
if(items[j] > items[j+1]) {
//Swap the numbers
var tmp = items[j]; //Temporary variable to hold the current number
items[j] = items[j+1]; //Replace current number with adjacent number
items[j+1] = tmp; //Replace adjacent number with current number
}
}
draw(items,j);
}
}
</script>
</body>
</html>
You can't just pause a JS script, but you can use setTimeout() to queue up a function to be run after a given delay. Which means you can use setTimeout to build a sort of pseudo-loop with a delay for each iteration.
Following is a conversion of your original nested for loop function to work with setTimeout().
I haven't tried to hook this into your existing draw() code that uses a canvas - to keep the code in the answer short I'm just calling my own simple draw() for demo purposes when you click "Run code snippet" - but it should give you the general idea. (For demo purposes I've used a much shorter delay than you asked for, but obviously you can change that.)
function animatedBubbleSort(items, drawCallback) {
var i = 0;
var j = 0;
var length = items.length;
(function nextIteration() {
if (j >= length - i - 1) {
j = 0;
i++;
}
if (i < length) {
if (items[j] > items[j+1]) {
// swap items
var temp = items[j];
items[j] = items[j+1];
items[j+1] = temp;
drawCallback(items, j+1);
}
j++;
setTimeout(nextIteration, 100);
} else // finished
drawCallback(items);
})();
}
var values = [13, 12, 1, 19, 20, 4, 6, 2, 18, 15, 3, 7, 14, 17, 5, 9, 16, 11, 8, 10];
animatedBubbleSort(values, function draw(items, j) {
document.getElementById("output").innerHTML = items.map(function(v, i) { return i===j ? "<span>" + v + "</span>" : v; }).join(", ");
});
span { color: red; }
<div id="output"></div>
I have written a simple pong game in Javascript. But I am having two problems with it.
I don't know why the ball doesn't deflect off of the computer's paddle which is the "playerB" according to the code.
How can I create some randomness when the ball deflects from the paddles? Currently the game seems very repetitive.
How can I fix these two problems?
Link to Jsfiddle
HTML
<!DOCTYPE html>
<html>
<head>
<title>Pong game</title>
<script type="text/javascript" src="jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="js/pong.js"></script>
<link rel="stylesheet" href="css/pong.css">
</head>
<body>
<header>
<p>
Computer:<span id="scoreB"></span> Human:<span id="scoreA"></span>
</p>
</header>
<div id="playground">
<div id="ball"></div>
<div id="playerA" class="paddle right"></div>
<div id="playerB" class="paddle left"></div>
</div>
</body>
</html>
CSS
html,body{
margin: 0 atuo;
height:100%;
}
#playground{
position: relative;
width:700px;
height:400px;
border: 1px solid grey;
overflow:hidden;
}
#ball{
position: absolute;
background: #fbb;
width:20px;
height:20px;
left:200px;
top:100px;
border-radius:10px;
}
.paddle{
position: absolute;
border:1px solid grey;
width:10px;
height:80px;
}
.left.paddle{
left:0px;
background-color: green;
}
.right.paddle{
right:0px;
background-color: blue;
}
Javascript
$(document).ready(function(){
var values = {
ball:{
speed:5,
x:50,
y:50,
directionX: 1,
directionY: 1,
radius: 10
},
playground:{
width: parseInt($("#playground").width()),
height: parseInt($("#playground").height())
},
playerA:{
y:0,
top: $("#playerA").offset().top,
height: $("#playerA").height(),
width: $("#playerA").width(),
score:0
},
playerB:{
y:0,
top: $("#playerB").offset().top,
height: $("#playerB").height(),
width: $("#playerB").width(),
score:0
}
};
//collision detection
function hitsTopBottom(){
var y = values.ball.y;
return y>values.playground.height-20 || y < 0;
}
function hitsRight(){
return values.ball.x > values.playground.width-20;
}
function hitsLeft(){
return values.ball.x < 0;
}
//ball hits playerA's paddle. Works properly but open to improvement
function hitsPlayerA(){
var ballX = values.ball.x;
var ballY = values.ball.y;
var playerAY = values.playerA.y;
return ballY<=playerAY+values.playerA.height && ballY>playerAY && ballX>=700-values.playerA.width-values.ball.radius;
}
//ball hits playerB's paddle. Doesn't work at all
function hitsPlayerB(){
var ballX = values.ball.x;
var ballY = values.ball.y;
var playerBY = values.playerB.y;
return ballY<=playerBY+values.playerB.height && ballY>=playerBY && ballX<=values.playerB.width-values.ball.radius;
}
//rendering the position of the ball
function renderball(){
$("#ball").css("left",values.ball.x);
$("#ball").css("top",values.ball.y);
$("#scoreB").text(values.playerB.score);
$("#scoreA").text(values.playerA.score);
}
//moving ball
function moveball(){
if(hitsTopBottom()){
values.ball.directionY *= -1;
}
if(hitsPlayerA()){
values.ball.directionX *= -1;
}
if(hitsPlayerB()){
values.ball.directionX = 1;
}
if(hitsRight()){
values.ball.x = 200;
values.ball.y = 200;
values.playerB.score += 1;
}
if(hitsLeft()){
values.ball.x = 200;
values.ball.y = 200;
values.playerA.score += 1;
}
values.ball.x += values.ball.speed*values.ball.directionX;
values.ball.y += values.ball.speed*values.ball.directionY;
renderball();
var playerB_pos = values.ball.y - values.playerB.height/2;
$("#playerB").css("top",playerB_pos);
}
//player movements
$("#playground").mousemove(function(e){
values.playerA.y = e.pageY-values.playerA.top-parseInt($("#playerA").height()/2);
$("#playerA").css("top",values.playerA.y);
});
setInterval(moveball,1000/30);
});
The ball was not deflecting off the computer paddle because its position was not being stored. By setting values.playerB.y = playerB_pos in the loop it will correctly bounce off now. However since it is the same as the y position of the ball the computer will never lose. To correct for this and add some randomness I used jQuery's animate function to tween the computer paddle between points and fake momentum:
if(!isAnimating) {
isAnimating = true;
$("#playerB").animate({"top": playerB_pos}, {
duration: (values.ball.speed*16),
easing: "linear",
step: function( now, fx ) {
values.playerB.y = parseInt($("#playerB").offset().top - parseInt($("#playerA").height()));
},
complete: function() {
isAnimating = false;
}
});
}
You can see it in action here: http://jsfiddle.net/yb290ow9/5/
You forgot to edit the actual playerB.y value (you just changed the css):
var playerB_pos = values.ball.y - values.playerB.height/2;
values.playerB.y = playerB_pos; // Forgot this!
$("#playerB").css("top",playerB_pos);
Working JSFiddle: http://jsfiddle.net/yb290ow9/6/
About the randomness: you could make the paddle "bouncy": change the speed of the ball, not just the direction