I have a game of a rocket landing game, where the player is the rocket and you must land it safely at the right speed on the landing pad. This was taken from www.gametutorial.net
Its actually for educational purposes and I recently added a still meteor in the game.
When the player hits the meteor (touches) the game is over.
if(...) {
playerRocket.crashed = true;
}
My problem is there I need to replace the "..." with the actual condition that "Has the rocket crashed into the meteor?"
Plus the following variables (coordinates, height and width) for use -
[All Integers]:
X and Y coordinates: playerRocket.x, playerRocket.y, meteor.x, meteor.y
Height and Width: playerRocket.rocketImgHeight, playerRocket.rocketImgWidth, meteor.meteorImgHeight, meteor.meteorImgWidth
For collision detection in 2D games, you can use rectangles. I'd use a base class called GObject and inherit all objects in the game from it.
public class GObject
{
private Rectangle bounds;
public float x, y, hspeed, vspeed;
private Image image;
public GObject(Image img, float startx, float starty)
{
image = img;
x = startx;
y = starty;
hspeed = vspeed = 0;
bounds = new Rectangle(x, y, img.getWidth(null), img.getHeight(null));
}
public Rectangle getBounds()
{
bounds.x = x;
bounds.y = y;
return bounds;
}
}
There's also other methods like update() and render() but I'm not showing them. So to check for collision between two objects use
public boolean checkCollision(GObject obj1, GObject obj2)
{
return obj1.getBounds().intersects(obj2.getBounds());
}
Also, there's a specific site for game related questions. Go to Game Development Stack Exchange
You need to check if you hit the object, meaning, if the click coordinates are within the object's Rectangle.
if( playerRocket.x + playerRocket.width >= clickX && playerRocket.x <= clickX &&
playerRocket.y + playerRocket.height >= clickY && playerRocket.Y <= clickY ) {
playerRocket.crashed = true;
}
Related
class Bullet {
float bulletX, bulletY;
float angle;
int x;
int y;
int score; // add a score variable
static final float BULLET_SPEED = 5; // define a constant for the bullet's speed
Bullet(float x, float y, float angle) {
this.bulletX = x;
this.bulletY = y;
this.angle = angle;
}
// Updates the position of the bullet based on its angle and speed.
void update() {
bulletX += cos(angle) * BULLET_SPEED;
bulletY += sin(angle) * BULLET_SPEED;
}
// Draws the bullet image on the screen.
void show() {
drawBullet();
}
// Draws the bullet image on the screen.
void drawBullet() {
image(Bulletimg, bulletX, bulletY);
Bulletimg.resize(30, 30);
}
//Returns true if the bullet is off screen, false otherwise.
boolean offScreen() {
return bulletX < 0 || bulletX > width || bulletY < 0 || bulletY > height;
}
//Checks if the bullet hits the enemy, and updates the score and enemy position accordingly.
// check for collision
void checkCollision(Enemy e) {
float distance = dist(bulletX, bulletY, e.x, e.y);
if (distance < e.x / 2) {
// assuming enemy.size is the radius of the
}
}
}
I tried changing around the check collision(enemy e) block and I'm not sure how i would go about removing an enemy object and also updating my score. i've tried messing about with the draw(); method but i cant seem to figure it out without breaking my entire game. any help with this class would be much appreciated.
You can use/create some attribute in your Enemy object to know/check if is alive or death.
For example in your check collision you can add
if (distance < e.x / 2) {
// assuming enemy.size is the radius of the
e.alive = false
}
Edit: I dont know how your manage the Enemy object and if it can be modified directly in the check collision method if this is not possible then you need to find a way to have access inside the method or use a return and manage that return outside.
I am creating a Bouncing Ball Animation with JavaFX similar to the bouncing windows logo screen saver. The code I have now is decent but it will only bounce the ball in a clockwise manner. This is good generally but eventually the ball works itself around to a counter-clockwise rotation in which case it no longer looks realistic. I am stuck trying to find a way to calculate how the ball should bounce; in my mind it really comes down to what angel the ball comes in at. I am Using an AnimationTimer which Translates the ball a set amount each frame. When the Bounds of the ball meet a boundary the translating direction is changed it is at this meeting that I need a suggestion...
BallAnimation is an inner class.
class BallAnimation extends AnimationTimer{
private final Sphere ball;
private double movex = 0;
private double movey = 0;
private double xvariation = 0;
private double yvariation = 0;
private boolean right = true;
private boolean up = false;
private boolean changeColorRandomly = true;
private double rate = 1;
public BallAnimation(Sphere ball){
this.ball = ball;
ball.setLayoutX(200);
ball.setLayoutY(50);
}
public void handle(long now){
move(right,up);
Bounds ballBounds = ball.localToScene(ball.getBoundsInLocal());
if(ballBounds.intersects(rightWall.getBoundsInParent())){
calculateMotion(rightWall);
randomBounceAngle();
setRandomColor();
}
if(ballBounds.intersects(leftWall.getBoundsInParent())){
calculateMotion(leftWall);
randomBounceAngle();
setRandomColor();
}
if(ballBounds.intersects(ceiling.getBoundsInParent())){
calculateMotion(ceiling);
randomBounceAngle();
setRandomColor();
}
if(ballBounds.intersects(floor.getBoundsInParent())){
calculateMotion(floor);
randomBounceAngle();
setRandomColor();
}
}
private void calculateMotion(Line touchedWall){
if(touchedWall.equals(rightWall)){
right = false;
up = false;
}
if(touchedWall.equals(leftWall)){
right = true;
up = true;
}
if(touchedWall.equals(ceiling)){
right = true;
up = false;
}
if(touchedWall.equals(floor)){
right = false;
up = true;
}
}
public void move(boolean right, boolean up){
if(right && !up){
ball.setTranslateX((movex += (getRate() + xvariation)));
ball.setTranslateY((movey += (getRate() + yvariation)));
}
if(right && up){
ball.setTranslateX((movex += (getRate() + xvariation)));
ball.setTranslateY((movey -= (getRate() + yvariation)));
}
if(!right && up){
ball.setTranslateX((movex -= (getRate() + xvariation)));
ball.setTranslateY((movey -= (getRate() + yvariation)));
}
if(!right && !up){
ball.setTranslateX((movex -= (getRate() + xvariation)));
ball.setTranslateY((movey += (getRate() + yvariation)));
}
System.out.println("("+movex+", "+movey+")");
}
public double getRate(){
return rate;
}
public void setRate(double rate){
this.rate = rate;
}
public void randomBounceAngle(){
double ran = Math.random();
if(ran >= .50){
//shallow bounce angle
xvariation = 3;
yvariation = 2;
}else{
//sharp bounce angle
xvariation = 2;
yvariation = 3;
}
}
... The problem is when the ball hits the right boundary it bounces down and away, the bottom it bounces up and left, left boundary: up and right, ceiling: right and down. This is fine most of the time but sometimes it needs to bounce the other way.
Well, in a world of perfect physics, in angle is equal to out angle. If you are using an x/y axis, For reflection off the x-axis, negate the y component of the ball's velocity. For reflection off the y-axis, negate the x component of the ball's velocity.
I re-wrote pong in javascript using layers and detecting keyboard strokes for paddle control (this was in '00 or '01 with Netscape 4.7x). I cheated, and set up functions to move the ball in 8 directions. If the ball was traveling along an axis (straight left/right or up/down) a quick random number provided a different bounce coming out. Otherwise, bounce out at same angle in.
Here is a function to reflect a vector around a normal. It can be used to create a bounce, by reflecting the velocity vector of the ball around the normal of the wall (or the normal of the side of another object) that the ball is bouncing off of.
private Point2D reflect(Point2D vector, Point2D normal) {
return vector.subtract(normal.multiply(vector.dotProduct(normal) * 2));
}
It is part of an implementation for a sample breakout game I created based on the example code in this question.
The code shown for the vector-based reflection uses the formula provided in the answer to this question, which is translated directly to JavaFX classes:
How to get a reflection vector?
𝑟=𝑑−2(𝑑⋅𝑛)𝑛 where 𝑑⋅𝑛 is the dot product and 𝑛 must be normalized.
Please note that, if you search, there are many math tutorials and Stackoverflow questions that talk about functions and methods for performing reflection.
A particular case for balls bouncing off vertical or horizontal surfaces such as walls or bricks in a breakout game is that the lines which the ball is bouncing off of are parallel to the x and y axes of the coordinate system, so the bounce can be performed by negating the x or y values of the velocity vector. See the example code in this question or answers to other questions on reflection for an example of this simplification if it is something you wish to use.
if (topWall) {
dy = dy * -1;
}
if (leftWall || rightWall) {
dx = dx * -1;
}
if(bottomWall) {
dy = dy * -1;
}
I am programming a 2d platformer with libgdx, I'm trying to make a menu screen where the player can click a button and it will load that level. I use gdx.input for the click coordinates and TextureRegion.getRegionX() for the button coordinates. They don't sync together and I read that camera.unproject should fix this problem. I duly used it but the coords still don't match. camera.unproject seems to set 0,0 for x and y as the centre of the screen, while batch.draw (which is the method which draws the TextureRegion to screen) seems to be using the bottom left hand corner as x and y's 0, 0.
Here is the code, I left out what I didn't think was relevant:
public class LevelScreen implements Screen {
private TextureRegion level_bg;
private SpriteBatch batch;
private Camera camera;
private TextureAtlas textureAtlas;
private TextureRegion lockselectbg[]=new TextureRegion[10];
public LevelScreen(){
}
#Override
public void show() {
batch=new SpriteBatch();
camera = new OrthographicCamera(500,700);
LevelStatus.put();
LevelStatus.get();
textureAtlas=new TextureAtlas(Gdx.files.internal("levelatlas.pack"));
Array<AtlasRegion> atlasArrays = new Array<AtlasRegion>(textureAtlas.getRegions());
level_bg = atlasArrays.get(0);
lockselectbg[0] = atlasArrays.get(21);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(159/255.0f,220/255.0f,235/255.0f,0xff/255.0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(level_bg, -500/2,-348/2);
batch.draw(lockselectbg[0], -180,0);
batch.end();
if(Gdx.input.isTouched()){
Vector3 tmp = new Vector3(Gdx.input.getX(),Gdx.input.getY(), 0);
camera.unproject(tmp);
Rectangle textureBounds = new Rectangle(lockselectbg[0].getRegionX(), lockselectbg[0].getRegionY(), lockselectbg[0].getRegionWidth(), lockselectbg[0].getRegionHeight());
if(textureBounds.contains(tmp.x, tmp.y)) {
System.out.println("It worked");
}
}
}
#Override
public void dispose() {
textureAtlas.dispose();
batch.dispose();
}
Camera#unproject will convert touch coordinates to world coordinates. They have nothing to do with the location of the region on the texture, which is what TextureRegion is. You are practically comparing world (read: game logic) coordinates with asset coordinates. Those two are completely unrelated.
If you want to check whether your image on the screen is touched then compare the touch coordinate with the location and size of the image you used in the batch.draw call. For example:
float x = -180f;
float y = 0f;
float width = 200f;
float height = 150f;
...
batch.draw(region, x, y, width, height);
...
camera.unproject(tmp.set(Gdx.input.getX(),Gdx.input.getY(), 0));
boolean touched = tmp.x >= x && tmp.y >= y && tmp.x < (x + width) && tmp.y < (y + height);
if (touched)
System.out.println("It worked");
Btw, you might want to read this post: http://blog.xoppa.com/pixels as well, because you are coupling your logic with asset size.
I'm working on a simple game and i need these squareBumpers which simply stands idle and when got hit, collides and reflects the ball. But currently the ball just flies through my squareBumpers. I can only use java awt and swing libraries. Here's the code:
class squareBumper {
private int x = 300;
private int y = 300;
private Color color = new Color(66,139,139);
public void paint(Graphics g) {
Rectangle clipRect = g.getClipBounds();
g.setColor(color);
g.fillRect(x, y, 31, 31);
}
}
class BouncingBall {
// Overview: A BouncingBall is a mutable data type. It simulates a
// rubber ball bouncing inside a two dimensional box. It also
// provides methods that are useful for creating animations of the
// ball as it moves.
private int x = 320;
private int y = 598;
public static double vx;
public static double vy;
private int radius = 6;
private Color color = new Color(0, 0, 0);
public void move() {
// modifies: this
// effects: Move the ball according to its velocity. Reflections off
// walls cause the ball to change direction.
x += vx;
if (x <= radius) { x = radius; vx = -vx; }
if (x >= 610-radius) { x = 610-radius; vx = -vx; }
y += vy;
if (y <= radius) { y = radius; vy = -vy; }
if (y >= 605-radius) { y = 605-radius; vy = -vy; }
}
public void randomBump() {
// modifies: this
// effects: Changes the velocity of the ball by a random amount
vx += (int)((Math.random() * 10.0) - 5.0);
vx = -vx;
vy += (int)((Math.random() * 10.0) - 5.0);
vy = -vy;
}
public void paint(Graphics g) {
// modifies: the Graphics object <g>.
// effects: paints a circle on <g> reflecting the current position
// of the ball.
// the "clip rectangle" is the area of the screen that needs to be
// modified
Rectangle clipRect = g.getClipBounds();
// For this tiny program, testing whether we need to redraw is
// kind of silly. But when there are lots of objects all over the
// screen this is a very important performance optimization
if (clipRect.intersects(this.boundingBox())) {
g.setColor(color);
g.fillOval(x-radius, y-radius, radius+radius, radius+radius);
}
}
public Rectangle boundingBox() {
// effect: Returns the smallest rectangle that completely covers the
// current position of the ball.
// a Rectangle is the x,y for the upper left corner and then the
// width and height
return new Rectangle(x-radius, y-radius, radius+radius+1, radius+radius+1);
}
}
Take a look at the classes that implement the Shape interface. There are ellipses and other shapes, and they all implement a intersects(Rectangle2D) method. It might help you if you don't want to perform intersection yourself.
As for dealing with the collision, well, it depends on the level of accuracy you want. Simply deflecting the ball of edges is quite easy. Just determine whether the collided side of the rectangle is vertical or horizontal, and negate the corresponding velocity component accordingly. If you want to handle the corners, well that is a bit more complicated.
You need to detect when the ball has collided with the bumper. You have the boundingBox() method of BouncingBall, this will get you a rectangle that contains your ball. So you need to check if this rectangle intersects your square bumper (which implies a collision), and then do something with that.
So I understand that I'm not coding this the best way possible at the moment; this is a sort of test run. What I'm trying to do is wall collisions using rectangles and the intersects property (sorry if I'm not using the correct terminology). So far I have 2 rectangles on screen. 1 the player controls and the other which the play is colliding with. When they collide the player stops moving. The problem is that if the player is trying to move into the rectangle while they are already colliding then the player can't move in any direction perpendicular to the movement ie if the player is holding the right arrow key moving into the rectangle, then they cannot move up or down. The game works on the premise that if your x or y coordinates aren't valid, then you will be moved back to the last valid coordinate recorded but I'm having trouble detecting the valid x and y coordinate separately. Here is the code:
public void Collision()
{
if(x < 0)
x = 0;
if(x > 400 - width)
x = 400 - width;
if(y < 0)
y = 0;
if(y > 300 - height)
y = 300 - height;
rect1 = new Rectangle(x, y, 16, 16);
rect2 = new Rectangle(sx, sy, wid, hei);
if(!rect1.intersects(rect2))
{
validX = true;
validY = true;
}
else
{
validX = false;
validY = false;
}
if(validX)
{
lastValidX = x;
}
if(validY)
{
lastValidY = y;
}
if(!validX)
{
x = lastValidX;
}
if(!validY)
{
y = lastValidY;
}
}
The Collision() method in the Guy class is where I'm having the trouble I believe. Yes my code is pretty messy right now but this is only a test.
Thanks, David.
You can implement what you're describing by doing extra logic around here (i.e. detecting cases when one is false and the other is true):
if(!rect1.intersects(rect2))
{
validX = true;
validY = true;
}
else
{
validX = false;
validY = false;
}
However, it seems like maybe you shouldn't be allowing the rectangles to ever be in a "colliding" state in the first place. For example, you can change the Move method to do something like
public void Move()
{
int oldX = x, oldY = y;
x += dx;
y += dy;
if (Collision()) {
x = oldX;
y = oldY;
}
}