java - Breakout ball collision in libgdx -
i'm trying make breakout clone using java , libgdx. i'm experiencing trouble getting ball bounce off of blocks @ appropriate angle. in short problem i'm having ball moves 12 pixels every frame , doesn't line edge of brick. if has suggestions on better way move ball or different way check collision appreciated!
main game class
package com.kyleparker.breakout; import com.badlogic.gdx.applicationlistener; import com.badlogic.gdx.gdx; import com.badlogic.gdx.audio.music; import com.badlogic.gdx.audio.sound; import com.badlogic.gdx.graphics.gl10; import com.badlogic.gdx.graphics.orthographiccamera; import com.badlogic.gdx.graphics.texture; import com.badlogic.gdx.graphics.g2d.spritebatch; import com.badlogic.gdx.math.rectangle; import com.badlogic.gdx.utils.array; public class breakoutgamescreen implements applicationlistener { texture dropimage; sound dropsound; music rainmusic; spritebatch batch; orthographiccamera camera; rectangle bucket; paddle paddle; //brick bricks[]; array<brick> bricks; ball ball; @override public void create() { // load images droplet, 64x64 pixels dropimage = new texture(gdx.files.internal("droplet.png")); // load drop sound effect , rain background "music" dropsound = gdx.audio.newsound(gdx.files.internal("drop.wav")); rainmusic = gdx.audio.newmusic(gdx.files.internal("rain.mp3")); // start playback of background music rainmusic.setlooping(true); rainmusic.play(); // create camera , spritebatch camera = new orthographiccamera(); camera.settoortho(false, 1280, 720); batch = new spritebatch(); paddle = new paddle(new texture(gdx.files.internal("bucket.png"))); bricks = new array<brick>(); populatebricks(); ball = new ball(new texture(gdx.files.internal("bucket.png")), paddle, bricks); } private void populatebricks() { bricks.add(new brick(200,100)); (int = 0; < 5; i++) { (int j = 0; j <= 7; j++) { bricks.add(new brick (j * 144 + 76, * 80 + 300)); //offsets each new brick } } } @override public void render() { // clear screen dark blue color. // arguments glclearcolor red, green // blue , alpha component in range [0,1] // of color used clear screen. gdx.gl.glclearcolor(0, 0, 0.2f, 1); gdx.gl.glclear(gl10.gl_color_buffer_bit); // tell camera update matrices. camera.update(); // tell spritebatch render in // coordinate system specified camera. batch.setprojectionmatrix(camera.combined); // begin new batch , draw bucket , // drops batch.begin(); paddle.render(batch, camera); ball.move(); ball.render(batch, camera); (int x = bricks.size - 1; x > 0; x--) { bricks.get(x).render(batch,camera); } batch.end(); } @override public void dispose() { // dispose of native resources dropimage.dispose(); dropsound.dispose(); rainmusic.dispose(); batch.dispose(); paddle.dispose(); } @override public void resize(int width, int height) { } @override public void pause() { } @override public void resume() { } }
ball class
package com.kyleparker.breakout; import com.badlogic.gdx.graphics.orthographiccamera; import com.badlogic.gdx.graphics.texture; import com.badlogic.gdx.graphics.g2d.spritebatch; import com.badlogic.gdx.math.rectangle; import com.badlogic.gdx.utils.array; public class ball{ texture ballimage; rectangle ball; private int xdir; private int ydir; paddle paddle; array<brick> bricks; final int ball_speed = 12; public ball(texture ballimage, paddle paddle, array<brick> bricks) { // load ball image this.ballimage = ballimage; xdir = 1; ydir = -1; // create rectangle balls collision ball = new rectangle(); ball.x = 1280 / 2 - 64 / 2; // center ball ball.y = 100; // put ball 200px away bottom of screen ball.width = 64; ball.height = 64; this.paddle = paddle; this.bricks = bricks; } public void render(spritebatch batch, orthographiccamera camera) { // draw paddle onto batch of level batch.draw(ballimage, ball.x, ball.y); } public void move() { ball.x += xdir * ball_speed; ball.y += ydir * ball_speed; if (ball.x <= 0) { setxdir(1); } if (ball.x >= 1280 - 64) { setxdir(-1); } if (ball.y <= 0) { setydir(1); } if (ball.y >= 720 - 64) { setydir(-1); } if (ball.overlaps(paddle.getrect())) { setydir(1); } (int = 0; < bricks.size; i++) { if (ball.overlaps(bricks.get(i).getrect())) { if ((ball.x == (bricks.get(i).getrect().x + 128))) { setxdir(1); bricks.get(i).setdestroyed(true); system.out.println("collision right"); } if (((ball.x + 64) == bricks.get(i).getrect().x)) { setxdir(-1); bricks.get(i).setdestroyed(true); system.out.println("collision left"); } if ((ball.y == (bricks.get(i).getrect().y + 64))) { setydir(1); bricks.get(i).setdestroyed(true); system.out.println("collision top"); } if (((ball.y + 64) == bricks.get(i).getrect().y)) { setydir(-1); bricks.get(i).setdestroyed(true); system.out.println("collision bottom"); } } }// end of } public void setxdir(int x) { xdir = x; } public void setydir(int y) { ydir = y; } public int getydir() { return ydir; } public int getxdir() { return xdir; } public rectangle getrect() { // return collision rectangle checking overlaps return ball; } public void dispose() { // dispose of native resources ballimage.dispose(); } }// end of class
brick code in case
package com.kyleparker.breakout; import com.badlogic.gdx.gdx; import com.badlogic.gdx.graphics.orthographiccamera; import com.badlogic.gdx.graphics.texture; import com.badlogic.gdx.graphics.g2d.spritebatch; import com.badlogic.gdx.math.rectangle; public class brick{ texture brickimage; rectangle brick; boolean destroyed; public brick(int x, int y) { brickimage = new texture(gdx.files.internal("brick.png")); // create rectangle bricks collision brick = new rectangle(); brick.x = x; brick.y = y; brick.width = 128; brick.height = 64; destroyed = false; } public void render(spritebatch batch, orthographiccamera camera) { // draw brick onto batch of level batch.draw(brickimage, brick.x, brick.y); } public boolean isdestroyed() { // return collision rectangle checking overlaps return destroyed; } public void setdestroyed(boolean destroyed) { this.destroyed = destroyed; if (this.destroyed == true) { dispose(); brick.x = -1000; brick.y = -1000; } } public rectangle getrect() { return brick; } public void dispose() { // dispose of native resources brickimage.dispose(); } }
don't worry fact ball doesn't line object collision needs handled -- that's not relevant. can (and should) handle collisions less 'precisely.' is, ball's path fixed, can calculate position @ future point. check position, calculate position in next frame (which have draw anyway), , add code handle collision going happen, rather trying detect , handle collision has happened. can slow down ball if want clean reflection, or can speed framerate, or can let ball partially 'absorbed' object before reflects:
public class ball { . . . public void move() { . . . if (collisionobject.overlaps(new rectangle(ball.x + xdir, ball.y + ydir, ball.width, ball.height))) { //a collision have occurred in next frame //handle collision please } } }
i note ball_speed
field inaccurately named. presently coded, ball moves @ 45° angle, speed of 17 pixels per frame (in direction). you've coded x- , y-offset 12 pixels, if (when?) change ball's direction, you'll find speed fluctuates wildly depending on values placed in xdir
, ydir
fields. example, if (somewhat) randomize these, keep rest of code as-is, might find xdir = 2
, ydir = 4
on 1 instance, , xdir = 6
, ydir = 12
on another. note these describe same direction, second version move 3 times fast.
to handle ball's direction , speed, assign angle, , calculate xdir
, ydir
values through appropriate trigonometric functions (xdir = ball_speed * math.cos(ballangle)
, ydir = ball_speed * math.sin(ballangle)
).
Comments
Post a Comment