just trying to make a simple pong game in p5.js. I have very recently gotten into JavaScript and can't manage to figure out collision detection between the ball and the bat. I have tried a few ways of doing it but it mostly just stopped my code from running.. etc.. would love any help!
Here is my source code:
function setup() {
createCanvas(750, 750);
}
var x = 50;
var y = 50;
var direction = 5;
var arrow = 0;
var ball;
var bat;
function draw() {
background(220);
fill ('white');
ball = ellipse (x, y, 50, 50);
x = x + direction;
if (x > width - 25){
direction = -5;
}
if (x < 25) {
direction = 5;
}
x++;
y++;
if (keyIsDown(RIGHT_ARROW)){
arrow += 7;
}
if (keyIsDown(LEFT_ARROW)){
arrow += -7;
}
fill ('black');
bat = rect(arrow, 600, 150, 15);
}
Your question is pretty broad, but basically what you want to do is imagine a "bounding rectangle" around the ball, and then use rectangle-rectangle collision to check whether the ball is colliding with a paddle. If it is, "bounce" the ball by multiplying its horizontal speed by -1.
I wrote a tutorial on collision detection available here, but the basic if statement looks like this:
if(rectOneRight > rectTwoLeft && rectOneLeft < rectTwoRight && rectOneBottom > rectTwoTop && rectOneTop < rectTwoBottom){
You also might want to read the Collision Detection with Moving Objects section of that tutorial. It's written for Processing, but everything applies to P5.js as well.
If you're having trouble getting it working, then please start over with a more basic sketch that just shows two hard-coded rectangles. Make them turn red when they're not colliding. Then work your way up from there. It's hard to answer general "how do I do this" type questions, so you'll have much better luck if you post a specific "I tried X, expected Y, but got Z instead" type question. Good luck.
Related
i am making a javascript shooter game.i want the the player to rotate towards the mouse.it is working, but the rotation was not correct.
I tried this with an image, and it works, but with the sprite itself(player1), is not.
i have asked this once before but received no answer
I am a beginner in javascript, so help would be appreciated.
I am using the p5.js libraries
Here is my code snippet:
//variables
var player1;
var gun1;
var gun2;
function preload(){
img = loadImage('rect1.png');
}
function setup(){
//creating sprites
player1 = createSprite(200,200,30,30)
gun = createSprite(player1.x,player1.y-20,5,30)
gun.shapeColor = "black"
player1.addImage("player",img)
player1.scale = 0.2
}
function draw(){
canvas = createCanvas(displayWidth-20, displayHeight-120);
background("#32CD32");
push()
gun.x = player1.x;
gun.y = player1.y-15;
// functions to move
//up
if(keyDown("up")){
player1.y = player1.y - 5;
}
//down
if(keyDown("down")){
player1.y = player1.y + 5;
}
//right
if(keyDown("right")){
player1.x = player1.x + 5;
}
//left
if(keyDown("left")){
player1.x = player1.x - 5;
}
angleMode(DEGREES)
imageMode(CENTER)
let a = atan2(mouseY - height / 2, mouseX - width / 2);
translate(width/2, height/2);
//rotate(a)
player1.rotation = a
//image(img,0,0,40,40)
pop()
drawSprites();
}
I think I'm using a dated version of p5.play, so there's not much in your code that works for me, but here's what I think is going on based on what you're saying.
If you want to understand what the deal is with atan2(), you first have to understand atan(). Basically, you have the ordinary trig functions sin, cos, and tan. Then you have the inverse trig functions arcsin, arccos, and arctan (abbreviated asin, acos, and atan). The arctan function is useful because you can input a slope and it will give you the angle of that slope. There's a catch, though; atan will only give values between -pi/2 and pi/2. This covers all non-vertical lines, but what if you wanted to use it for a vector or something that has direction? atan2() solves that problem. Instead of taking one input (a ratio: rise/run), it takes two inputs, a rise and a run. This prevents dividing by zero (for vertical lines) and signs of rise and run cancelling. The first input is the rise, and the second is the run. The output is the angle between the vector with those coordinates and the x-axis. So atan2() will give you some angle between -pi and pi.
Now let's look at what you have put into the atan2() function:
atan2(mouseY - height / 2, mouseX - width / 2);
So the vector you're considering is the vector from the middle of the canvas to the mouse. If this is what you want, great. If it's not, maybe consider
atan2(mouseY - player1.y, mouseX - player1.y);
which yields the "heading" (not really the heading) of the vector from the player's position to the mouse.
There are a couple of other potential problems (I can't figure out which one it is because p5.play isn't behaving, or I'm doing something else wrong):
radians/degrees: sometimes this stuff goes wrong. Try printing a and seeing if it's what you're looking for. If it's in degrees, consider saying player1.rotation = radians(a) instead. I know that p5.Vector.fromAngle() doesn't care about angleMode, maybe sprite.rotation doesn't either?
I don't know how drawSprites works, but you might consider putting it inside of the push()/pop() section. When drawing other shapes, this is how you get a rotation about the point (x, y):
let x = 100;
let y = 200;
let a = atan2(mouseY - y, mouseX - x);
push();
translate(x, y);
rotate(a);
square(-10, -10, 20);
pop();
The square is centered at (x,y), and is rotated about (x,y) toward the cursor. It's necessary that you do it in this order: push, translate, rotate, shape, pop. If you mix up that order, it doesn't do it right. But what you have is push, translate, pop, shape. I don't know how sprite.rotate works, so maybe it's supposed to do what you want. But here is another way to do a rotation. (If you're going to do it this way, I think you'd have to draw player1 "at (0,0)" after the translation and rotation, before pop)
I hope this helped!
I'm viewing this code for two days now and it really doesn't seem to me like anything is wrong at all. Tried changing the code in many ways but had little to no success with the lag issue of the ball. something clearly is wrong because the ball has this weird lag (sometimes it behaves normally but most of the times it has this odd lag that is causing changes in speed of the ball.)
This are two of the main functions that make the ball move and both seem OK to me.
function ball(){ //gets called 1000 times per second
if(lifeCount==0){
ctx.clearRect(0,0,900,600);
ctx.drawImage(youLose,0,0,900,600);
return;
}
else{
ctx.beginPath();
ctx.clearRect(xBall-(r+1),yBall-(r+1),2*r+2,2*r+2);
ballCollision(); //function
ctx.arc(xBall,yBall,r,0,2*Math.PI, true);
ctx.fillStyle = "#c82124";
ctx.fill();
ctx.stroke();
bricksHit(); //function (no lag)
bricksDraw(); //function (no lag)
ballPowerUp(); //function (no lag)
}
}
function ballCollision(){
if(startDirection === 1) //random start, ball begins moving "left"
xBall += -xSpeed;
if(startDirection === 2) //random start, ball begins moving "right"
xBall += xSpeed;
if(xBall>=canvas.width-r) //right wall collision
xSpeed = -xSpeed
if(xBall<=0+r) //left wall collision
xSpeed = -xSpeed
if(yBall<=0+r)//top wall collision
ySpeed = -ySpeed;
if(xBall>=x-(paddleW/2) && xBall<=x+(paddleW/2) && (yBall <= canvas.height-paddleH-r && yBall >= canvas.height-paddleH-r-4)) //bottom paddle collision
ySpeed = -ySpeed;
yBall += ySpeed;
if(yBall>=canvas.height-r){
lifeCount--;
if(lifeCount>0)
initBall(); //another chance if you still have lives left
}
}
canvas.onmousemove = function() {
if(lifeCount==0){
return;
}
else{
padd();
}
}
There is probably some rookie mistake made in the code somewhere that I just can't seem to find or I don't know what else may be causing this. If any of you has any suggestions please let me know.
also if anyone would like to see how the game actually "lags" here's a link of html file: https://drive.google.com/open?id=1A1H1MiKpIutj9Z4kdrDunHZHHYeWNfl3
Thanks in advance!
I am trying to make a little animation with p5.js in Javascript.
However, I have some issues with the rotateX() function. I have the following code:
http://codepen.io/anon/pen/JbZdRN?editors=1010
var w, h, scl, rows, cols;
function setup() {
w = 500;
h = 500;
scl = 20;
cols = w / scl;
rows = h / scl;
createCanvas(500, 500);
}
function draw() {
background(0);
noFill();
stroke(255);
translate(width/2, height/2);
rotateX(radians(15));
for(var y = 0; y < cols; y++) {
beginShape(TRIANGLE_STRIP);
for(var x = 0; x < rows; x++){
vertex(x*scl, y*scl, 0);
vertex(x*scl, (y+1)*scl, 0);
}
endShape();
}
}
The problem is that I cannot rotate the triangle strip on the x-axis.
The thing is, if I use rotate() it works (but it's the wrong axis). If I use rotate(PI, X) or rotate(PI, Y), it doesn't work either.
So I really can't rotate the whole thing on the X-axis. How can I do this?
Questions like these are best answered by the JavaScript console. Press F12 in most browsers, or look for "developer options" in your settings menu. Any errors you get go here, and that will help you understand what's happening when things don't work.
In your case, you get an error: Uncaught not supported in p2d. Please use webgl mode
And that error tells you everything. You're using the default renderer, which only renders in 2D. Rotating around the X axis requires rendering in 3D. So to fix this error, you need to use the WEBGL renderer by passing it into the createCanvas() renderer. More info can be found in the reference.
After you fix that error you have other problems that seem to be related to this issue, but hopefully this gets you going in the right direction. Moral of the story: check the JavaScript console.
All I need is to have this object travel left and right across the top of the canvas. Currently it spawns and travels right absolutely fine, then stops once it reaches the right edge of the canvas.
//mainEnemy Variables
var mainEnemy_x = 10;
var mainEnemy_y = 10;
var mainEnemyHeight = 50;
var mainEnemyWidth = 25;
var mainEnemyRight = true;
var mainEnemyLeft = false;
var mainEnemy_dx = 2;
//Drawing the Main Enemy
function drawMainEnemy()
{
ctx.beginPath();
ctx.rect(mainEnemy_x, mainEnemy_y, mainEnemyHeight, mainEnemyWidth);
ctx.fillStyle = "green";
ctx.fill();
ctx.closePath();
}
//Movement speed of mainEnemy
if(mainEnemyRight && mainEnemy_x < canvas.width-mainEnemyWidth)
{
mainEnemy_x += 5;
}
else if(mainEnemyLeft && mainEnemy_x > 0)
{
mainEnemy_x -= 5;
}
//mainEnemy moves across the top of the canvas
if(mainEnemy_x + mainEnemy_dx - mainEnemyWidth > canvas.width)
{
mainEnemy_dx = -mainEnemy_dx;
}
ball_x += dx;
ball_y += dy;
mainEnemy_x += mainEnemy_dx;
}
This is all the code relevant to the object I need help with. I've tried just reversing it's x movement, with the mainEnemy_dx = -mainEnemy_dx; line, but this isn't working. I can see this code is an absolute mess at the moment, I just need to get it working then time for some serious cleanup.
Any and all help would be greatly appreciated!
First of all, you have two movement systems. One with the left and right flags and constants added or subtracted from x and the other with dx. You should just use one or the other, the latter being simpler.
For the jitter, you have to either also check that the current dx is positive when going over the right by border (and negative on left) and then switch the sign, or move the object left when a collision with right border is found.
At the moment you are moving the object 7 units right every time, then when border is found only dx is used (2 or -2) but since your object can be over the border it might vibrate between 2 and -2 always. But at least the right branch will always try to move 5 units right even when dx is negative.
Using a debugger to step through the code and inspecting the variables and branches taken while vibrating on the right edge will show exactly how it behaves.
I'm trying implement A* Start path finding in my games(which are written with JavaScript, HTML5 Canvas). Library for A* Start found this - http://46dogs.blogspot.com/2009/10/star-pathroute-finding-javascript-code.html and now I'm using this library for path finding.
And with this library, I'm trying write a simple test, but stuck with one problem.
I'm now done when in HTML5 canvas screen click with mouse show path until my mouse.x and mouse.y. Here is a screenshot:
(Pink square: Player, Orange squares: path until my mouse.x/mouse.y)
Code how I'm drawing the orange squares until my mouse.x/mouse.y is:
for(var i = 0; i < path.length; i++) {
context.fillStyle = 'orange';
context.fillRect(path[i].x * 16, path[i].y * 16, 16, 16);
}
My problem is I do not understand how to move my player until path goal.
I've tried:
for(var i = 0; i < path.length; i++) {
player.x += path[i].x;
player.y += path[i].y;
}
But with this code my player is not beung drawn.(When I run the code, player.x and player.y are equals to 0 and when I click with the mouse I get the path player blink and disappear)
Maybe anyone know how to solve this problem?
And I'm very very very sorry for my bad English language. :)
My Working Fiddle
This is what I currently use which is based off of my a*. The concept should be the same though. The a* function should return the path as an array, then you just need to iterate through the path on each player update and move them.
// data holds the array of points returned by the a* alg, step is the current point you're on.
function movePlayer(data, step){
step++;
if(step >= data.length){
return false;
}
// set the player to the next point in the data array
playerObj.x = data[step].x;
playerObj.y = data[step].y;
// fill the rect that the player is on
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect(playerObj.x*tileSize, playerObj.y*tileSize, tileSize, tileSize);
// do it again
setTimeout(function(){movePlayer(data,step)},10);
}