My ball is sticking to the wall and cant move

uhm hi

im quite new but ive started to take classes of programming with processing

this is my 3rd or 4th lesson or so, so please dont mind the cringy piece of code

but i need help
because im trying to make a game where you have to navigate through spaces and stuff
sort of maze but with moving obstacles

so i have three issues:

  • i dont know why but my piece code is acting strange: if i move my ball to a wall it sticks to the wall and i cant move it in the opposite direction anymore
  • i dont know how to make moving obstacles and how to do if my thing hits the moving obstacle and then its game over
  • last but not least: i cant do this with a rect. if i replace my ball with rect it wont work. but im ok with the ellipse also

this is my code:

//variables
int PosX = 10;
int PosY = 10;

void setup() {
  size(1000,1000);
  frameRate(120);
}

void draw() {
  background(255);
  fill(0);
  rect(70,0,10,300);
  rect(0,200,50,10);
  //ball
  fill(255,0,0);
  ellipse(PosX,PosY,15,15);
  //ball controls
  if(keyPressed == true) {
    if(keyCode == LEFT || key == 'a') {
      if(get(PosX + 8,PosY) != -16777216) {
        PosX -= 1;
      }
    }
    if(keyCode == RIGHT || key == 'd') {
      if(get(PosX + 8,PosY) != -16777216) {
        PosX += 1;
      }
    }
    if(keyCode == UP || key == 'w') {
      if(get(PosX,PosY + 8) != -16777216) {
        PosY -= 1;
      }
    }
    if(keyCode == DOWN || key == 's') {
      if(get(PosX,PosY + 8) != -16777216) {
        PosY += 1;
      }
    }
  }
}

can someone help me? ok thank you much

1 Like

Please check the prev post: Some guidance for beginners

At the end, they mention some good links for collision algorithms that you should review. Good you have divided your problem in mini-problems. Work of each of them separately and, if possible, in that order.

Lastly, please edit your post and format your code. Highlight your code and press the </> button and your code will be formatted.

Kf

2 Likes

First off, here’s what I came up with:

I include a breakdown of the whole piece of code below this if it interests you, or anyone dealing with the same issue, or looking to make a similar game.

//Class Variables

//lets make an array of obstacles, so we can add more later
Obstacle[] obstacles = new Obstacle[2]; 
//make a ball object
Ball b; 

boolean collision = false; 

 void setup()
  {
   
   size(600,600); //my screen is a bit smaller :D 
   
   
   //Let's iterate through each obstacle in my obstacle array and initialize them
   for(int i = 0; i<obstacles.length; i++)
   {
    obstacles[i] = new Obstacle();   
   }
   
   //initialize a ball 
   b = new Ball(); 
    
  } //end of setup 
  
  
  
  void draw()
  {
   background(125); 
   
   //only show everything if there is NO colission
   if(!collision)
    { 
    //display the ball 
    b.display();
   
    //display all of the obstacles in the array  
   for(int i = 0; i<obstacles.length; i++)
   {
   obstacles[i].display();  
   }
     // 
   } //end of if 
    
   else
    { 
     //a simple game over 
       textAlign(CENTER);
       fill(255,0,0); 
       textSize(50); 
       text("GAME OVER", width/2, height/2); 
       println("Game Over"); 
    }
   
   
  } //end of void draw
  

 
  
  public class Obstacle
  {
    int obstacleX, obstacleY, obstacleWidth, obstacleHeight; 

    Obstacle()
    {
     obstacleX = 70;
     obstacleY = 0; 
     obstacleWidth = 10;
     obstacleHeight = 300; 
    }//end of obstacle default constructor
    
    Obstacle(int obstacle_x, int obstacle_y, int obstacle_width, int obstacle_height)
    {
     this.obstacleX = obstacle_x; 
     this.obstacleY = obstacle_y;
     this.obstacleWidth = obstacle_width;
     this.obstacleHeight = obstacle_height;
     
    }//end of the actual constructor so you can set the obstacles at initialization
    
    //so you can set each obstacle manually if you want to  
    void set_x(int x) { this.obstacleX = x; } 
    void set_y(int y) { this.obstacleY = y; } 
    void set_w(int w) { this.obstacleWidth = w; } 
    void set_h(int h) { this.obstacleHeight = h; } 
    
    
    void display()
    {
      
      //instead of checking for colors, lets make a check for collision function within the obstacle class 
      checkForCollisions(); 
     
     //i'm going to make the obstacles here: 
     
     //your first obstacle
     obstacles[0].set_x(70); 
     obstacles[0].set_y(0); 
     obstacles[0].set_w(10); 
     obstacles[0].set_h(300);
    
    
     //your second obstacle
     obstacles[1].set_x(0); 
     obstacles[1].set_y(200); 
     obstacles[1].set_w(50); 
     obstacles[1].set_h(10);  
   
     fill(255);  
     rect(obstacleX, obstacleY, obstacleWidth, obstacleHeight); 
  
   
    } //end of void display 
    
    void checkForCollisions()
    {
      //you are checking if the ball's position equals that of the obstacle
      if(     ( 
                ( (b.ballX+b.ballR/2)+1>(this.obstacleX) ) && 
                ( (b.ballX+b.ballR/2)+1<(this.obstacleX+this.obstacleWidth) ) &&
                ( (b.ballY+b.ballR/2)+1>(this.obstacleY) ) &&
                ( (b.ballY+b.ballR/2)+1<(this.obstacleY+this.obstacleHeight) )
              )              ||
              (
                ( (b.ballX-b.ballR/2)-1>(this.obstacleX) ) && 
                ( (b.ballX-b.ballR/2)-1<(this.obstacleX+this.obstacleWidth) ) &&
                ( (b.ballY-b.ballR/2)-1>(this.obstacleY) ) &&
                ( (b.ballY-b.ballR/2)-1<(this.obstacleY+this.obstacleHeight) )
          
              )    
           
        ) { collision = true;}
      
    }//end of CheckForCollissions
    
    
    
  }//end of Obstacle Class
  
  
 public class Ball 
  {
    int ballX, ballY, ballR; 
    
    Ball()
    {
     ballX = 10; 
     ballY = 10; 
     ballR = 15; 
    }//ball default constructor
    
    void display()
    {
      fill(255,0,0);
      ellipse(ballX,ballY,ballR,ballR); 
      
      moveBall(); 
      
    }//end of void display
    
    
    //now lets make a function to move the ball 
    void moveBall()
    { 
     if(keyPressed)
      {
       //if you'd like to use arrows, check if the key is coded aka UP, DOWN, LEFT, RIGHT 
       if(key==CODED)
        {  
        switch(keyCode)
        {   
         case LEFT: ballX--; break; 
         case RIGHT: ballX++; break;
         case UP: ballY--; break;
         case DOWN: ballY++; break; 
        }//end of switch statement
        }//end of checking if the key is coded 
        
        else
        {
        //if you want to use the keys 
        switch(key)
         { 
         case 'a': ballX--; break; 
         case 'w': ballX++; break;
         case 'd': ballY--; break;
         case 's': ballY++; break;
         }//end of the swtich statement       
        } //end of the else 
     
      } //end of if key pressed 
      
    }//move the ball
    
  }//end of the Ball Class

Now for some explanation:

I first off made everything into objects. Your ball as well as your obstacles. I first made an array of obstacles, and as you can see, there are only two of them for now:

Obstacle[] obstacles = new Obstacle[2];

Of course you can change that later. I also made a Ball object, shown here:

Ball b;

I also declared boolean that would be false at first, because a collision did not happen:

boolean collision = false;

In void setup() I went through and initialized everything. I made a for loop, so that I could go through every obstacle in the obstacle array, and I initialized them:

 for(int i = 0; i<obstacles.length; i++)
   {
    obstacles[i] = new Obstacle();   
   }

Then, I did the same with the ball:

b = new Ball();

After that, in void draw() , I have one major if statement. There are many ways of doing this state check, but I am choosing to use the boolean. And within that boolean I display call my ball’s display function with:

b.display();

and likewise, I go through the obstacles array again and display every every obstacle as well:

 for(int i = 0; i<obstacles.length; i++)
   {
   obstacles[i].display();  
   }

If the collision boolean is true, I then have it show the screen with the text “GAME OVER” on it. Of course you can edit and change to your liking, but that’s just what I chose to do.

Now to get on to the classes.

In the obstacle class, I just set a variable for each parameter, the x and y values, and the width and height:

int obstacleX, obstacleY, obstacleWidth, obstacleHeight;

I then made a default constructor, which honestly isn’t necessary because I’m sure for a game like this you will have to manually set each obstacle. But I added this default constructor just for the sake of it, in case if you want to have only one obstacle or something like that.

That is shown here:

   Obstacle()
    {
     obstacleX = 70;
     obstacleY = 0; 
     obstacleWidth = 10;
     obstacleHeight = 300; 
    }//end of obstacle default constructor

Then I added in a constructor that takes in the parameters of x, y, width and height. Again, doesn’t have much practical use for the way each Obstacle is being initialized, unless if you want to set every obstacle to the same value, or if you want to make every obstacle by hand without an array.

That is shown here:

 Obstacle(int obstacle_x, int obstacle_y, int obstacle_width, int obstacle_height)
    {
     this.obstacleX = obstacle_x; 
     this.obstacleY = obstacle_y;
     this.obstacleWidth = obstacle_width;
     this.obstacleHeight = obstacle_height;
     
    }//end of the actual constructor so you can set the obstacles at initialization

Then I made some setters. This will allow for you to manually set the parameters of each obstacle, or set specific parameters to specific obstacles.

That is shown here:

  //so you can set each obstacle manually if you want to  
    void set_x(int x) { this.obstacleX = x; } 
    void set_y(int y) { this.obstacleY = y; } 
    void set_w(int w) { this.obstacleWidth = w; } 
    void set_h(int h) { this.obstacleHeight = h; }

Each of these setters takes in an int, which will be the value you want to set. You will see an example of that a little later. By the way, taking one of the setters as an example:

void set_x(int x) { this.obstacleX = x; }

The this.obstacleX part means that I will get the obstacle in question. Meaning if I specify obstacle[0].set_x(50) , the x value I set will be set to obstacle[0].

Next, I have my display function for the Obstacle class. The first thing I do is call the checkForCollisions() function that I also made and will explain a little later.

//instead of checking for colors, lets make a check for 
//collision function within the obstacle class
 
 checkForCollisions();

In display, I then manually set each obstacle to have the same parameters that you had in your code, like this:

   //your first obstacle
     obstacles[0].set_x(70); 
     obstacles[0].set_y(0); 
     obstacles[0].set_w(10); 
     obstacles[0].set_h(300);
    
    
     //your second obstacle
     obstacles[1].set_x(0); 
     obstacles[1].set_y(200); 
     obstacles[1].set_w(50); 
     obstacles[1].set_h(10);

And then finally, I displayed the actual rectangle:

     fill(255);  
     rect(obstacleX, obstacleY, obstacleWidth, obstacleHeight);

Now to talk about the checkForCollisions() function. It’s quite simple (and can be modified) even if it looks a bit crazy. What I’m basically doing is taking into consideration the endpoints of the circle. Ellipses are drawn from the center, so if I want to check if the edge of the circle touches something, I’m going to add and subtract the radius to ball’s x and y values. Hopefully that makes sense.

In terms of why I have all those and’s, I want to check if the ball’s rightmost edge is within the obstacle’s area. I first check the top left corner:

(b.ballX+b.ballR/2)+1>(this.obstacleX)

Then the top right corner:

(b.ballX+b.ballR/2)+1<(this.obstacleX+this.obstacleWidth)

And so on with the bottom left and bottom right. I then add in a big OR and do the same thing, but with the leftmost edge.

IF that ends up being true? I set collision to true.

Hence this piece of code:

    void checkForCollisions()
    {
      //you are checking if the ball's position equals that of the obstacle
      if(     ( 
                ( (b.ballX+b.ballR/2)+1>(this.obstacleX) ) && 
                ( (b.ballX+b.ballR/2)+1<(this.obstacleX+this.obstacleWidth) ) &&
                ( (b.ballY+b.ballR/2)+1>(this.obstacleY) ) &&
                ( (b.ballY+b.ballR/2)+1<(this.obstacleY+this.obstacleHeight) )
              )              ||
              (
                ( (b.ballX-b.ballR/2)-1>(this.obstacleX) ) && 
                ( (b.ballX-b.ballR/2)-1<(this.obstacleX+this.obstacleWidth) ) &&
                ( (b.ballY-b.ballR/2)-1>(this.obstacleY) ) &&
                ( (b.ballY-b.ballR/2)-1<(this.obstacleY+this.obstacleHeight) )
          
              )    
           
        ) { collision = true;}
      
    }//end of CheckForCollissions

That is all with the Obstacle Class. Now for the Ball Class:

I declare some variables up top:

int ballX, ballY, ballR;

And then, I make my default constructor, with parameters that I saw in your code:

    Ball()
    {
     ballX = 10; 
     ballY = 10; 
     ballR = 15; 
    }//ball default constructor

I then have my display function for my ball, and I draw it:

 fill(255,0,0);
 ellipse(ballX,ballY,ballR,ballR);

And then I make a function that handles moving the ball:

moveBall();

Now let’s look at that moving function. I start off with checking if there is a key pressed. Then I check if the key is coded. Certain keys, like the UP and DOWN and LEFT and RIGHT keys for example, have those codes. Then I passed the keyCode through a switch() statement, and checked each case:

   if(key==CODED)
        {  
        switch(keyCode)
        {   
         case LEFT: ballX--; break; 
         case RIGHT: ballX++; break;
         case UP: ballY--; break;
         case DOWN: ballY++; break; 
        }//end of switch statement
        }//end of checking if the key is coded

If the key isn’t coded? For example, letter keys? I do the same thing, but this time pass in the key through the switch() statement:


    else
        {
        //if you want to use the keys 
        switch(key)
         { 
         case 'a': ballX--; break; 
         case 'w': ballX++; break;
         case 'd': ballY--; break;
         case 's': ballY++; break;
         }//end of the swtich statement       
        } //end of the else

And with that? You are finished! You can add more obstacles, and find ways to optimize your code to your liking. Hopefully this helps, and if there are any more questions, I would be glad to answer them!

EnhancedLoop7

1 Like