Apply Speed to Unbeatable AI Paddle for Simple Pong Game - java

I have created a simple rendition of the classic Pong game on Android Studio for a college course. At this point, almost everything is ready to go, except for the fact that I created an unbeatable AI for the enemy paddle. I created the paddles and the ball with the default RectF class and change my AI paddle's position based on the ball's current position (I subtract/add by 65 because my paddles' lengths are 130 pixels and it centers the paddle compared to the ball). This essentially allows the enemy paddle to move at an infinite speed because it is matching the ball's speed/position (the ball speed increases with each new level). Here is that method:
public void AI(Paddle paddle) {
RectF paddleRect = paddle.getRect();
RectF ballRect = ball.getRect();
if (ballRect.left >= 65 && ballRect.right <= screenX - 65) {
paddleRect.left = (ballRect.left - 65);
paddleRect.right = (ballRect.right + 65);
}
if (ballRect.left < 65) {
paddleRect.left = 0;
paddleRect.right = 130;
}
if (ballRect.right > screenX - 65) {
paddleRect.left = screenX - 130;
paddleRect.right = screenX;
}
}
For reference, here are the relevant parts of my Paddle class:
public Paddle(float screenX, float screenY, float xPos, float yPos, int defaultSpeed){
length = 130;
height = 30;
paddleSpeed = defaultSpeed;
// Start paddle in the center of the screen
x = (screenX / 2) - 65;
xBound = screenX;
// Create the rectangle
rect = new RectF(x, yPos, x + length, yPos + height);
}
// Set the movement of the paddle if it is going left, right or nowhere
public void setMovementState(int state) {
paddleMoving = state;
}
// Updates paddles' position
public void update(long fps){
if(x > 0 && paddleMoving == LEFT){
x = x - (paddleSpeed / fps);
}
if(x < (xBound - 130) && paddleMoving == RIGHT){
x = x + (paddleSpeed / fps);
}
rect.left = x;
rect.right = x + length;
}
The fps in the update(long fps) method above is passed through from the run() method in my View class:
public void run() {
while (playing) {
// Capture the current time in milliseconds
startTime = System.currentTimeMillis();
// Update & draw the frame
if (!paused) {
onUpdate();
}
draw();
// Calculate the fps this frame
thisTime = System.currentTimeMillis() - startTime;
if (thisTime >= 1) {
fps = 1000 / thisTime;
}
}
}
My paddles and ball constantly update in my onUpdate() method in the View class.
public void onUpdate() {
// Update objects' positions
paddle1.update(fps);
ball.update(fps);
AI(paddle2);
}
How can I attach a speed limit to my AI paddle using the paddle speed I already define for each new paddle? I've already tried modifying the AI(Paddle paddle) method to incorporate +/- (paddleSpeed / fps) and it didn't affect the paddle seemingly at all. Maybe I just implemented it wrong, but any help would be fantastic!

To make the AI move the paddle at a steady rate rather than jumping to the correct spot, just try to make the middle of the paddle line up with the middle of the ball:
public void AI(Paddle paddle) {
RectF paddleRect = paddle.getRect();
RectF ballRect = ball.getRect();
float ballCenter = (ballRect.left + ballRect.right) / 2;
float paddleCenter = (paddleRect.left + paddleRect.right) / 2;
if (ballCenter < paddleCenter) {
setMovementState(LEFT);
}
else {
setMovementState(RIGHT);
}
}
and then after you call AI(paddle2) inside of onUpdate, call paddle2.update(fps). This way you aren't repeating yourself with the drawing code. You will notice that the AI paddle may not do perfectly if the ball is much faster than the paddle. In this case you can use math to anticipate where the ball will end up and work on getting there.

Related

What should I do in my code in order to make a collision detection between a PNG sprite and a drawn circle occur in Processing 3 (Java)?

I have been coding a significantly simple game for my academic work in which the PNG bee sprite is meant to run away from the orange ball. If the bee collides with the orange ball, she dies. Apart from this, I intend to include a timer that keeps going onwards as the bee succeeds in running away from the ball. The ball moves automatically throughout the screen, whereas the bee bounces throughout the screen with the arrow keys and gravity.
I have come across some explanations towards collision detection upon the Processing forum, however I still don't understand how this event can occur in the cases of circles x circles collisions, rectangles x circles collisions, etc.
Please, excuse my messy code. Also, excuse my poor description of what I want to know.
This is what I see on the screen:
My code:
//background
PImage background;
// keys | keyboard
boolean upPressed = false;
boolean downPressed = false;
boolean leftPressed = false;
boolean rightPressed = false;
// bee player character
PImage charImage;
float charSpeed = 5.5;
float charX = 0;
float charY = 450;
float gravity = 1.5;
float vy = 0;
float bounce = -0.8;
// platforms
PImage bee;// bee
float beeX = 300;
float beeY = 490;
PImage hi; // hi
float hiX = 400;
float hiY = 300;
PImage ve; // ve
float veX = 420;
float veY = 440;
// more beehives
PImage beehive4;// beehive4
float bee4X = 120;
float bee4Y = 90;
PImage beehive5; // beehive5
float bee5X = 200;
float bee5Y = 300;
PImage beehive6; // beehive6
float bee6X = 30;
float bee6Y = 400;
PImage beehive7; // beehive7
float bee7X = 496;
float bee7Y = 90;
// enemy ball
float ballX = 100;
float ballY = 100;
float xspeed = 100;
float yspeed = 100;
//////
public void setup() {
size(600, 800);
noStroke();
smooth();
noFill(); // to adjust the image in the screen properly in fullscreen
//load beehives
bee = loadImage("beehive 1.png");
bee.resize(100, 100);
hi = loadImage("beehive 2.png");
hi.resize(100,100);
ve = loadImage("beehive 3.png");
ve.resize(100, 100);
// load more beehives
beehive4 = loadImage("beehive 4.png");
beehive4.resize(100, 100);
beehive5 = loadImage("beehive 5.png");
beehive5.resize(100, 100);
beehive6 = loadImage("beehive 6.png");
beehive6.resize(100, 100);
beehive7 = loadImage("beehive 7.png");
beehive7.resize(100, 100);
}
/*********** drawing section !***********/
public void draw() {
background(244, 240, 219);
noStroke();
// render beehives
image(bee, beeX, beeY);
image(hi, hiX, hiY);
image(ve, veX, veY);
// render more beehives
image(beehive4, bee4X, bee4Y);
image(beehive5, bee5X, bee5Y);
image(beehive6, bee6X, bee6Y);
image(beehive7, bee7X, bee7Y);
// render bee
charImage = loadImage("bee walk 3.png");
charImage.resize(200, 200);
vy += gravity; // it applies gravity to the bee sprite
charY += vy;
if(charY > height - 150 )
vy *= bounce; // bouncing bee
// Add the current speed to the location.
ballX = ballX + xspeed;
ballY = ballY + yspeed;
// Check for bouncing
if ((ballX > width) || (ballX < 0)) {
xspeed = xspeed * -1;
}
if ((ballY > height) || (ballY < 0)) {
yspeed = yspeed * -1;
}
// Display at x,y location
stroke(0);
fill(179, 98, 0);
ellipse(ballX, ballY,80,80);
// update keys
if (upPressed) {
charY--;
}
if (downPressed) {
charY++;
}
if (leftPressed) {
charX--;
}
if (rightPressed) {
charX++;
}
if(keyPressed){
if(keyCode == UP && charY > 0){
charY -= 30;
}
if(keyCode == DOWN && charY < height){
charY += 10;
}
if(keyCode == LEFT && charX > 0){
charX -= 30;
}
if(keyCode == RIGHT && charX < width){
charX += 10;
}
}
// render beecharacter on screen
image(charImage, charX, charY);
}
There mulitple ways to tackle the problem.
Collision detection can be coarse: less accurate but faster (and simpler) or detailed (e.g. pixel level precision) but slower (and more complex).
In terms of simple collision detection two options could rectangle or circle intersections.
Rectangle intersection can be implemented manually or using Rectangle's intersects() method.
Circle intersection is trivial: if the distance(dist()) between the 1st circle's center and 2nd circle's center is smaller than the two radii then they must intersect.
here's a basic example illustrating circle intersection:
// check collision: circle
if (dist(ballX, ballY, charX, charY) < charImage.width) {
// tint red to display collision: placeholder for subtracting bee health
tint(192, 0, 0);
}else{
noTint();
}
this condition can be added before this section in draw():
// render beecharacter on screen
image(charImage, charX, charY);
The collision detection is quite rough: not pixel perfect, but hopefully a good starting point. It should tint everything red if there's a collision.
I have two other small suggestions:
reducing xspeed, yspeed to 10 or smaller values will make the game more playable. 100px/frame is too fast for people and the bee will likely collide instantly before the users even has a chance to react.
intead of a boolean beeIsAlive sort of variable that immediately, with one ball hit switches to true also might be too harsh as a game rule. Consider something like int beeHealth = 100; and gradually reducing the health with each collision will make the game more playable.

How to make the bouncing ball collide with the array of rectangles on Processing?

im trying to make the bouncing ball bounce on the arrays of rectangles. I've looked at various other codes but cant seem to find a solution. Would appreciate any help!!!
Basically, i want the bouncing ball to recognise that theres the rectangles there and for it to be able to jump onto the rectangles.
PVector location; // Location of shape
PVector velocity; // Velocity of shape
PVector gravity; // Gravity acts at the shape's acceleration
PVector upwardForce;
PImage bg;
int radius = 10, directionX = 1, directionY = 0;
float x=20, y=20, speed=0.5;
int xarray[] = new int[20];
int yarray[] = new int[20];
// =========================================================
void setup() {
size(380,750);
location = new PVector(100,50);
velocity = new PVector(0.0,2.1);
upwardForce = new PVector(0.0,-10.0);
gravity = new PVector(0,0.4);
bg = loadImage("bg.png");
bg.resize(1600,1600);
background(0);
for(int i =0; i< 20;i++){
xarray[i]= i*100;
yarray[i] = 750-int(random(10))*50;
}
}
int xd =0, yd=0;
void draw() {
background(0);
noStroke();
xd--;
yd++;
// display image twice:
image(bg, y, 0);
image(bg, y+bg.height, 0);
// pos
y--;
if (y<-bg.height)
y=0;
for (int i = 0;i< 20;i++){
if (xarray[i] <100 && xarray[i]+100 >100){
fill(255,0,0);
}
else {
fill(255);
}
rect(xarray[i],yarray[i],100,1200);
fill(255);
xarray[i]=xarray[i]-4;
//yarray[i]=yarray[i]+1;
if (xarray[i] + 100 < 0){
xarray[i]+=2000;
// yarray[i]-=850;
}
}
// changing Position
x=x+speed*directionX;
y=y+speed*directionY;
// check boundaries
if ((x>width-radius) || (x<radius))
{
directionX=-directionX;
}
if ((y>height-radius) || (y<radius))
{
directionY=-directionY;
}
// draw
// if(direction==1)
// Add velocity to the location.
location.add(velocity);
// Add gravity to velocity
velocity.add(gravity);
// Bounce off edges
if ((location.x > width) || (location.x < 0)) {
velocity.x = velocity.x * -1;
}
if ((location.y > height) || (location.y < 0)){
// We're reducing velocity ever so slightly
// when it hits the bottom of the window
velocity.y = velocity.y * -0.95;
location.y = height;
}
// Display circle at location vector
stroke(255);
strokeWeight(0);
fill(255);
ellipse(location.x,location.y,30,30);
}
void keyPressed()
{
velocity.add(upwardForce);
}
The best advice we can give you is to break your problem down into smaller steps and to take those steps on one at a time.
For example, can you create a simple sketch that just shows a single hard-coded circle and a single hard-coded rectangle? Now add some code that prints a message to the console if they're colliding. You're going to have to do some research into collision detection, but here's a hint: a common technique is to treat the ball as a rectangle, so you can do rectangle-rectangle collision detection.
Get that working perfectly by itself, and then work your way forward in small steps. Can you add a second rectangle to your sketch? How about a third?
Then if you get stuck, you can post a MCVE (not your whole project, just a small example) along with a more specific question. Good luck.
Here's a few suggestions:
You're best off using a Rectangle class. That way, you don't have to store the locations in an array, and the collide function can be a method of the class. It's easier to just call the positions of the rectangles "x" and "y", but this would obviously conflict with the x and y global variables which you declared at the top of the code. Assuming that you would want to make the ball bounce if it collided, you would need to have a "ballLastx" and a "ballLasty" in order to keep track of which direction the ball came from. You would also need to store the Rectangles in an array or arrayList. It would be something like this:
PVector lastLocation;
Rectangle[] rects;
As for the rectangle class, here's how it would probably look like this:
class Rectangle {
float x, y;
Rectangle(float x_, float y_) {
x = x_;
y = y_;
}
void show() {
//Displays rectangle
if (x < 100 && x+100 > 100) fill(255,0,0);
else fill(255);
rect(x,y,100,1200);
fill(255);
x=x-4;
if (x + 100 < 0) x+=2000;
}
private boolean insideX(PVector pos) {
return (pos.x + 15 >= x && pos.x - 15 <= x+100);
}
private boolean insideY(PVector pos) {
return (pos.y + 15 >= y && pos.y - 15 <= x + 1200);
}
boolean collidedX() {
//Detects if the ball has collided along the x-axis
return ((insideX(location) && !insideX(lastLocation)) && insideY(location))
}
boolean collidedY() {
//Detects if the ball has collided along the y-axis
return ((insideY(location) && !insideY(lastLocation)) && insideX(location))
}
}
And then, in your setup function, you could declare the Rectangle classes in a for-loop:
//declare the rects array
rects = new Rectangle[20];
//declare each item of the rects array to be a Rectangle
for(int i = 0; i < rects.length; i++) {
rects[i] = new Rectangle(i*100, 750-int(random(0,10))*50;
}
In order to detect the collision and to bounce the ball, you would need to loop through all of the Rectangles and see if the ball should bounce off any of them:
boolean bouncex = false;
boolean bouncey = false;
//see if any of the rects are colliding with the ball
for(Rectangle r : rects) {
if(r.collidedX()) bouncex = true;
if(r.collidedY()) bouncey = true;
}
//if any are colliding, bounce the ball
if(bouncex) velocity.x = -velocity.x;
if(bouncey) velocity.y = -velocity.y;
Finally, don't forget to set the lastLocation PVector to the current location, just before moving the current location:
lastLocation = location.copy();
//move the ball...
Hope this was helpful!

Character Moves Too Fast

I am developing a game where I have a speed variable and a player x and player y.
Here is the up directional movement for my player:
I use an if statement in my up method in order to check if the player is breaking the boundaries of my frame.
public void createCharacter(Player player) {
Character.player = player;
speed = 1;
character.setIcon(CharacterSheet.downRightLeg);
Game.game.add(character);
px = 200;
py = 200;
character.setBounds(px, py, 56, 63);
}
public static void up() {
if (py - 2 > 0) {
player.setPlayerDirection(1);
py -= speed;
renderUpwardWalking();
character.setLocation(px, py);
Game.user.setLocation(px, py - 50);
} else if (py - 2 < 0) {
}
}
I call createCharacter at the beginning of the game when a player logs in.
Can I set int speed to a double and give it a value like .5? I tried it and it didn't work. My character moves too fast for the game I'm making and I don't know how to slow him down.

Java game - handling linear movement

So, I'm trying to make a game in LWJGL and it seems to work fine for me. Although, I ran into some issues in moving my entities around on the screen. I want to make it go from one point to another, at the same speed. Also, I'm animating my sprite according to the direction the entity is moving.
But! I have some issues:
1# It flickers because the movement is defined a modifier: delta (to make smooth movement defined by the FPS). Actually, it never really reaches it's point (because it recalculates and never hits the position). How can I solve this?
2# When 2 players join the same server, my character on the fastest computer runs faster. I think it's because of the FPS, how can that be solved?
private String name;
private float positionx,positiony; // Current
private int targetx,targety; // Target
private int dx, dy; // Direction
private int pointx, pointy; // Direction
private float speed;
private Sprite sprite;
public Entity(String name, int positionx, int positiony, Sprite sprite){
this.name = name;
this.speed = 0.1f;
this.positionx = 720;
this.positiony = 450;
this.targetx = 1000; // fix this
this.targety = 10; // this for testing.
this.sprite = sprite;
this.dx = 0;
this.dy = 0;
}
//double distance = Math.sqrt((vx * vx) + (vy * vy));
public void move(long delta){
if(positionx < targetx){
dx = 1;
pointx = 1;
}else if(positionx > targetx){
dx = -1;
pointx = -1;
}else{
dx = 0;
}
if(positiony < targety){
dy = 1;
pointy = 1;
}else if(positiony > targety){
dy = -1;
pointy = -1;
}else{
dy = 0;
}
//Set animations:
if(positionx==targetx && positiony==targety){
if(pointx<0){
sprite.setAnimation(5, 2, 100); // Standing left
}else if(pointx>0){
sprite.setAnimation(6, 2, 100); // Standing right
}else if(pointy<0){
sprite.setAnimation(7, 2, 100); // Standing up
}else if(pointy>0){
sprite.setAnimation(4, 2, 100); // Standing down
}
}else{
if(pointx<0){
sprite.setAnimation(1, 2, 100); // Walking left
}else if(pointx>0){
sprite.setAnimation(2, 2, 100); // Walking right
}else if(pointy<0){
sprite.setAnimation(3, 2, 100); // Walking up
}else if(pointy>0){
sprite.setAnimation(0, 2, 100); // Walking down
}
}
//movement here.
positionx += dx*delta*speed;
positiony += dy*delta*speed;
System.out.println(dx*delta*speed);
sprite.setPosition((int)positionx, (int)positiony);
}
1# It flickers because the movement is defined a modifier: delta (to make smooth movement defined by the FPS). Actually, it never really reaches it's point (because it recalculates and never hits the position). How can I solve this?
If you store point A and point B between which it moves, you can set a time interval. Each time interval a set distance will be travelled and if at one iteration the object goes too far you can set its coordinates for point B. This can be easily done with a Timer. That way, after a certain amount of time, it will be on your specified position.
2# When 2 players join the same server, my character on the fastest computer runs faster. I think it's because of the FPS, how can that be solved?
Same answer as question #1, if you use a Timer. Each player will move at the same speed (because the elapsed time is the same for each gamer).
Bottom line:
fps is variable, while elapsed time is the same for everyone.

bouncing balls never stay calm on the ground

I try to create a very simple physics engine for my study (processing used for a interactive installation).
The target is to have a ground covered with balls that you can throw around with gestures (based on Kinect information).
Therefor I need to do some basic physic simulation like bouncing and thats what I started with. So there are just balls falling down and bouncing. I simulated the air resistance with a simple 0.995f multiplication on the speed if the ball moves up. Works nice and looks realistic. The main problem is, that the balls never stay calm on the ground. Instead they start to tremble on the ground. That means there is a movement of 1 or 2 pixels up and down.
How can I prevent that without implementing some "borders" on which I set the position directly to the bottom and the speed to zero?
My applet:
public class BubblePhysicApplet extends PApplet {
public static int width = 640;
public static int height = 480;
long lastTime = -1;
Bubble[] mBubbles = new Bubble[10];
Random mRandom = new Random();
public void setup() {
// size(width, height, OPENGL);
size(width, height, P2D);
for (int i = 0; i < mBubbles.length; i++) {
mBubbles[i] = new Bubble(mRandom.nextInt(width), mRandom.nextInt(height), 50);
}
lastTime = System.currentTimeMillis();
}
public void draw() {
background(0);
long tmp = System.currentTimeMillis();
long elapsed = tmp - lastTime;
for (Bubble bubble : mBubbles) {
bubble.animate(elapsed);
bubble.draw(this);
}
lastTime = System.currentTimeMillis();
}
}
The ball/bubble:
public class Bubble {
float mX;
float mY;
float mSize;
float mSpeedX = 0;
float mSpeedY = 0;
public Bubble(int x, int y, int size) {
mX = x;
mY = y;
mSize = size;
}
public void draw(PApplet applet) {
applet.stroke(255);
applet.noFill();
applet.ellipseMode(PApplet.CENTER);
applet.ellipse(mX, mY, mSize, mSize);
}
public void animate(long elapsed) {
updateSpeedY(elapsed);
if (mSpeedX != 0 || mSpeedY != 0) {
checkBorders();
}
}
private void checkBorders() {
if (mY > BubblePhysicApplet.height - mSize / 2) {
mY = 2 * BubblePhysicApplet.height - (mY + mSize);
mSpeedY = -mSpeedY;
}
if (mX > BubblePhysicApplet.width) {
mX = BubblePhysicApplet.width - (mX - BubblePhysicApplet.width);
mSpeedX = -mSpeedX;
}
}
private void updateSpeedX() {
}
private void updateSpeedY(long elapsed) {
mSpeedY += (elapsed / 1000f) * 9.81f;
if (mSpeedY < 0) {
mSpeedY *= 0.95f;
}
mY += mSpeedY;
}
}
It's not only air resistance that slows the ball down, but the fact that it's not perfectly elastic as this line suggests: mSpeedY = -mSpeedY;
The ball absorbs energy when it squishes against the floor before it bounces back, so it doesn't bounce as high. Try a real super ball. I seem to remember it only bounces 80% as high or so. You might try:
mSpeedY = - (0.8 * mSpeedY);
you have to fix your check borders method, read this answer I just gave a complete formulas needed for realistic physical simulation. and it's also more realistic if you move objects using hist method (p = v*dt + 1/2*adtdt)
The problem is that in updateSpeedY we have mSpeedY += (elapsed / 1000f) * 9.81f; even when there is a collision. That said collision is detected later in checkBorders where the speed is flipped mSpeedY = -mSpeedY;. The problem is that if the ball is hitting the floor with a speed near 0, it bounces with a speed of 0 + (elapsed / 1000f) * 9.81f;!!
You have to rethink your code.
in the same fashion you used a friction factor for the air, you can also include a friction factor for the contact with the ground, and which even higher values, so at each contact, it starts to lose eneger rapidly and finally stops

Categories

Resources