made two circles one of radius 8(image 16x16)
and one of radius 20( image 40x40)
i am calling the circle over overlap method and the collsion is just off. It is colliding with a circle that is around the 0,0 point of where ever my image of the ball is. the bullet can go within the ball on the bottom and right sides.
public class MyGame extends ApplicationAdapter {
SpriteBatch batch;
Texture ballImage, bulletImage;
OrthographicCamera cam;
Circle ball;
Array <Circle> bullets;
long lastShot;
#Override
public void create ()
{
System.out.println("game created");
ballImage = new Texture(Gdx.files.internal("ball.png"));
bulletImage = new Texture(Gdx.files.internal("bullet.png"));
cam = new OrthographicCamera();
cam.setToOrtho(true,320,480);//true starts top right false starts top left
batch = new SpriteBatch();
ball = new Circle();
ball.radius=20;
ball.x=320/2-ball.radius; // half screen size - half image
ball.y=480/2-ball.radius;
bullets = new Array<Circle>();
spawnBullet();
/*
batch.draw(bulletImage,bullet.x,bullet.y);
bullet.x++;
bullet.y++; */
}
public void spawnBullet()
{
Circle bullet = new Circle();
bullet.radius=8;
bullet.x=0;
bullet.y=0;
bullets.add(bullet);
lastShot = TimeUtils.nanoTime();
}
#Override
public void render ()
{
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
cam.update();
batch.setProjectionMatrix(cam.combined);
batch.begin();
batch.draw(ballImage,ball.x,ball.y);
for(Circle bullet: bullets)
{
batch.draw(bulletImage, bullet.x, bullet.y);
}
batch.end();
if(Gdx.input.isTouched())
{
Vector3 pos = new Vector3();
pos.set(Gdx.input.getX(), Gdx.input.getY(),0);
cam.unproject(pos);
ball.y = pos.y - ball.radius;
ball.x = pos.x - ball.radius ;
}
//if(TimeUtils.nanoTime()-lastShot >1000000000) one second
//spawnBullet();
Iterator<Circle> i = bullets.iterator();
while(i.hasNext())
{
Circle bullet = i.next();
bullet.x++;
bullet.y++;
if(bullet.overlaps(ball))
{
System.out.println("overlap");
i.remove();
}
}
}
}
If your bullet and the ball are 2 circles, like you said you don't need an overlap method.
It is simple: 2 circles collide, if their distance is smaller then the sum of their radiuses.
To calculate the distance you need to make a squareroot. This is a pretty expensive calculation, so it would be better to use squared distance and squared sum of radiuses:
float xD = ball.x - bullet.x; // delta x
float yD = ball.y - bullet.y; // delta y
float sqDist = xD * xD + yD * yD; // square distance
boolean collision = sqDist <= (ball.radius+bullet.radius) * (ball.radius+bullet.radius);
Thats it.
Also in your cam.setToOrtho you wrote a cooment:
//true starts top right false starts top left
Thats wrong, it is top left or bottom left. By default it is bottom left, because this is the way a coordinate system works normaly. The top left is, because the monitor addresses pixels starting from top left = pixel 1.
EDIT: this should be the problem: The coordinates you give the batch.draw method are the left lower corner of the Texture by default, if you are using the "y = Down"-System it should be the top left corner (you have to try i am not sure).
The Circles position instead is its center.
To solve the problem you need to adjust the position like this (for "y = Up"-System):
batch.draw(bulletImage, bullet.x - bullet.radius, bullet.y - bullet.radius);
It is possible, that the same formula works also for the "y = Down"-System but i am not sure
Related
I am creating a top-down shooter game, and whenever I move the camera, or zoom, black likes appear like a grid
I am using Tiled to create the map, and I have the camera following my centered box2d body. I have found that making the camera position equal the position of the box2d body with an int cast results in the black lines disappearing like this:
The problem though, is that because I have the game scaled down, the player will move for a second or two and then when the player reaches the next whole number on either axis, the camera snaps to the player, which is not what I want for the game as it's jarring. The player's movement is granular, but, while rounded, the camera's is not. I do not know if this is a problem with my tile sheet or if it's something I can fix by altering some code. I have tried all different kinds of combinations of padding, and values of spacing and margins. So ultimately, how can I have the camera match the player's position smoothly and not cause the black lines? I'd greatly appreciate any help or recommendations. Thank you in advance!
Where I am type casting the player's float position to an int in game class:
public void cameraUpdate(float delta) {
//timeStep = 60 times a second, velocity iterations = 6, position iterations = 2
world.step(1/60f, 6, 2); //tells game how many times per second for Box2d to make its calculations
cam.position.x = (int)playerOne.b2body.getPosition().x;
cam.position.y = (int)playerOne.b2body.getPosition().y;
cam.update();
}
Majority of player class:
public class PlayerOne extends Sprite implements Disposable{
public World world; // world player will live in
public Body b2body; //creates body for player
private BodyDef bdef = new BodyDef();
private float speed = 1f;
private boolean running;
TextureAtlas textureAtlas;
Sprite sprite;
TextureRegion textureRegion;
private Sound runningSound;
public PlayerOne(World world) {
this.world = world;
definePlayer();
textureAtlas = new TextureAtlas(Gdx.files.internal("sprites/TDPlayer.atlas"));
textureRegion = textureAtlas.findRegion("TDPlayer");
sprite =new Sprite(new Texture("sprites/TDPlayer.png"));
sprite.setOrigin((sprite.getWidth() / 2) / DunGun.PPM, (float) ((sprite.getHeight() / 2) / DunGun.PPM - .08));
runningSound = Gdx.audio.newSound(Gdx.files.internal("sound effects/running.mp3"));
}
public void definePlayer() {
//define player body
bdef.position.set(750 / DunGun.PPM, 400 / DunGun.PPM);
bdef.type = BodyDef.BodyType.DynamicBody;
//create body in the world
b2body = world.createBody(bdef);
FixtureDef fdef = new FixtureDef();
CircleShape shape = new CircleShape();
shape.setRadius(12 / DunGun.PPM);
fdef.shape = shape;
b2body.createFixture(fdef);
}
public void renderSprite(SpriteBatch batch) {
float posX = b2body.getPosition().x;
float posY = b2body.getPosition().y;
float posX2 = (float) (posX - .14);
float posY2 = (float) (posY - .1);
sprite.setSize(32 / DunGun.PPM, 32 / DunGun.PPM);
sprite.setPosition(posX2, posY2);
float mouseX = Level1.mouse_position.x; //grabs cam.unproject x vector value
float mouseY = Level1.mouse_position.y; //grabs cam.unproject y vector value
float angle = MathUtils.atan2(mouseY - getY(), mouseX - getX()) * MathUtils.radDeg; //find the distance between mouse and player
angle = angle - 90; //makes it a full 360 degrees
if (angle < 0) {
angle += 360 ;
}
float angle2 = MathUtils.atan2(mouseY - getY(), mouseX - getX()); //get distance between mouse and player in radians
b2body.setTransform(b2body.getPosition().x, b2body.getPosition().y, angle2); //sets the position of the body to the position of the body and implements rotation
sprite.setRotation(angle); //rotates sprite
sprite.draw(batch); //draws sprite
}
public void handleInput(float delta) {
setPosition(b2body.getPosition().x - getWidth() / 2, b2body.getPosition().y - getHeight() / 2 + (5 / DunGun.PPM));
this.b2body.setLinearVelocity(0, 0);
if(Gdx.input.isKeyPressed(Input.Keys.W)){
this.b2body.setLinearVelocity(0f, speed);
}if(Gdx.input.isKeyPressed(Input.Keys.S)){
this.b2body.setLinearVelocity(0f, -speed);
}if(Gdx.input.isKeyPressed(Input.Keys.A)){
this.b2body.setLinearVelocity(-speed, 0f);
}if(Gdx.input.isKeyPressed(Input.Keys.D)){
this.b2body.setLinearVelocity(speed, 0f);
}if(Gdx.input.isKeyPressed(Input.Keys.W) && Gdx.input.isKeyPressed(Input.Keys.A)){
this.b2body.setLinearVelocity(-speed, speed);
}if(Gdx.input.isKeyPressed(Input.Keys.W) && Gdx.input.isKeyPressed(Input.Keys.D)){
this.b2body.setLinearVelocity(speed, speed);
}
if(Gdx.input.isKeyPressed(Input.Keys.S) && Gdx.input.isKeyPressed(Input.Keys.A)){
this.b2body.setLinearVelocity(-speed, -speed );
}if(Gdx.input.isKeyPressed(Input.Keys.S) && Gdx.input.isKeyPressed(Input.Keys.D)){
this.b2body.setLinearVelocity(speed, -speed);
}
Where I declare the pixels per meter scale:
public class DunGun extends Game{
public SpriteBatch batch;
//Virtual Screen size and Box2D Scale(Pixels Per Meter)
public static final int V_WIDTH = 1500;
public static final int V_HEIGHT = 800;
public static final float PPM = 100; //Pixels Per Meter
Game render and resize methods:
#Override
public void render(float delta) {
cameraUpdate(delta);
playerOne.handleInput(delta);
//clears screen
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if (Gdx.input.isButtonPressed(Input.Buttons.LEFT)) {
cam.zoom -= .01;
}
if (Gdx.input.isButtonPressed(Input.Buttons.RIGHT)) {
cam.zoom += .01;
}
mapRenderer.render();
b2dr.render(world, cam.combined); //renders the Box2d world
mapRenderer.setView(cam);
//render our game map
//mapRenderer.render(); // renders map
//mapRenderer.render(layerBackround); //renders layer in Tiled that p1 covers
game.batch.setProjectionMatrix(cam.combined); //keeps player sprite from doing weird out of sync movement
mouse_position.set(Gdx.input.getX(), Gdx.input.getY(), 0);
cam.unproject(mouse_position); //gets mouse coordinates within viewport
game.batch.begin(); //starts sprite spriteBatch
playerOne.renderSprite(game.batch);
game.batch.end(); //starts sprite spriteBatch
//mapRenderer.render(layerAfterBackground); //renders layer of Tiled that hides p1
}
#Override
public void resize(int width, int height) {
viewport.update(width, height, true); //updates the viewport camera
}
I solved it by fiddling around with the padding of the tilesets in GDX Texture Packer. I added 5 pixels of padding around the 32x32 tiles. I set the margins to 2, and spacing to 4 in Tiled. I had tried a lot of different combinations of padding/spacing/margins that didn't work which made me think it was a coding problem, but those settings worked, and I didn't have to round the floats.
so I've been looking at other people's questions and I've tried to apply the answers to my code but I do not seem to find how to do so. All I am trying to do is that when the Sprite moves is going to rotate at the same time. This is where I am calling the rotate function inside my Player class (which extends Sprite):
public void playerMovement(float dt){
if(Gdx.input.isPeripheralAvailable(Input.Peripheral.Accelerometer)) {
float roll = Gdx.input.getRoll();
float pitch = Gdx.input.getPitch();
final float MAX_SPEED = 0.4f;
velocity.x = roll;
velocity.y = pitch;
x = position.x;
y = position.y;
if (Math.abs(velocity.x) > 1) {
x = Math.max(0, Math.min(Gdx.graphics.getWidth(), x + velocity.x * MAX_SPEED));
position.x = x;
position.y = y;
rotate(90 * dt); //NOT WORKING
}
if (Math.abs(velocity.y) > 1) {
y = Math.max(0, Math.min(Gdx.graphics.getHeight(), y + velocity.y * MAX_SPEED));
position.x = x;
position.y = y;
rotate(90* dt); //NOT WORKING
}
}
}
before it used to extend Actor and use setRotate(90 * dt) and it was working fine. I decided to change to Sprite because I did not want to depend on the stage.
here's how I am rendering the player inside my GameScreen:
game.batch.begin();
game.batch.draw(atlas2.findRegion("player"), player.getPosition().x, player.getPosition().y, player.PLAYER_DIMENSION , player.PLAYER_DIMENSION);
game.batch.end();
I tried to use the player.draw(game.batch) function from the Sprite class, yet I did not work because I needed a Texture and the texture I am using is just an AtlasRegion and it did not let my type casted to a Texture
so if there are any suggestions on how to make my Sprite rotate I will appreciate!
Sprite holds the geometry, color, and texture information for drawing 2D sprite. In geometry, it carry sprite position, size, rotation and scale.
By using below method you're only passing position and size of player Sprite.
game.batch.draw(atlas2.findRegion("player"), player.getPosition().x, player.getPosition().y, player.PLAYER_DIMENSION , player.PLAYER_DIMENSION);
Use in this way :
TextureAtlas atlas2=....;
Sprite player=new Sprite(atlas2.findRegion("player"));
and draw by using draw method of Sprite
player.draw(game.batch);
EDIT
public class Player extends Sprite {
public Player(TextureRegion region){ // <- Add this constructor
super(region);
...
}
}
And create object of Player
Player player=new Player(atlas2.findRegion("player");
In my Game i want to implement Mouse Controls that control Camera and Player movment.
What i want to have is that when the Mouse moves to the bottom left corner of the window for example, the players Rotation goes towards this Vector.
Also i want the Camera to be shifted in the opposite 2d Vector so it appears that the player, when the cursor is in the bottom left moves into the top right corner.
Like This
And the more the cursor is moved away from the screens middle, the more the player should rotate.
The Camera should also be rotated around the player in order to make it appear that the playermodel is rotated towards the vector it rotates itself in.
This is the function that calculates the camera position:
private void calculateCameraPosition(float horizDistance, float verticDistance)
{
float theta = player.getRotY() + angleAroundPlayer;
float offsetX = (float)((horizDistance ) * Math.sin(Math.toRadians(theta)) );
float offsetZ = (float)(horizDistance * Math.cos(Math.toRadians(theta)));
position.y = player.getPosition().y + verticDistance + 8;
position.x = (player.getPosition().x - offsetX);
position.z = player.getPosition().z - offsetZ ;
this.yaw = 180 - (player.getRotY() + angleAroundPlayer);
}
And i get my Inputs from GFLW, a little bit modified as the Mouse positions, which i subtract from the width/2 and divide into smaller numbers.
angleChange_x = (int) (-(inputHandler.Mouse_x - (Width/2)) /20);
angleChange_y = (int) (-(inputHandler.Mouse_y - (Height/2)) /20 );
This is my first week of Java, and I'm making a game that involves rectangles bouncing off of each other. The rx and ry are the coordinates of the rectangles, and the velRX and velRY are their x and y velocity. I'm trying to make it so that the rectangles bounce off of each other (reversed y velocity) but continue with the same x velocity if they collide on the top or bottom, and vice versa for the left and right sides. However, I don't know how to detect which side the rectangles collide on. Could I have some help?
relevant code
//Checking for collision between Nemesis and Cop
public boolean checkCollisionOther() {
Rectangle r1 = rect1.getBoundsNemesis();
Rectangle r2 = rect2.getBoundsCop();
if (r1.intersects(r2)){
collision = true;
rect1.velRY = -rect1.velRY;
rect1.velRX = -rect1.velRX;
rect2.velRY = -rect2.velRY;
rect2.velRX = -rect2.velRX;
}
else
collision = false;
return collision;
}
What you want to do is create bounding rectangles for each of the edges of your two game rectangles. Since there are 4 edges to a rectangle, you have 4 bounding rectangles for a rectangle.
You have 4 bounding rectangles for the cop and 4 bounding rectangles for the nemesis. This means you have to do 16 intersects tests in a double for loop.
When one of the intersects tests returns true, you can determine which edge of your cop rectangle and which edge of your nemesis rectangle had the collision.
Here's some code to illustrate how to create bounding rectangles. You can make them wider than 3 pixels if you want.
public List<BoundingRectangle> createBoundingRectangles(Rectangle r) {
List<BoundingRectangle> list = new ArrayList<BoundingRectangle>();
int brWidth = 3;
// Create left rectangle
Rectangle left = new Rectangle(r.x, r.y, brWidth, r.height);
list.add(new BoundingRectangle(left, "left"));
// Create top rectangle
Rectangle top = new Rectangle(r.x, r.y, r.width, brWidth);
list.add(new BoundingRectangle(top, "top"));
// Create right rectangle
Rectangle right = new Rectangle(r.x + r.width - brWidth, r.y, brWidth,
r.height);
list.add(new BoundingRectangle(right, "right"));
// Create bottom rectangle
Rectangle bottom = new Rectangle(r.x, r.y + r.height - brWidth,
r.width, brWidth);
list.add(new BoundingRectangle(bottom, "bottom"));
return list;
}
public class BoundingRectangle {
private Rectangle rectangle;
private String position;
public BoundingRectangle(Rectangle rectangle, String position) {
this.rectangle = rectangle;
this.position = position;
}
public Rectangle getRectangle() {
return rectangle;
}
public String getPosition() {
return position;
}
public boolean intersects(Rectangle r) {
return rectangle.intersects(r);
}
}
I want to be able to create new particles from wherever I click on stage. I'm just stuck on adding the mouse portion and I've tried to add/pass parameters and I always get errors while I try setting the parameters. Any suggestions?
This is my current code:
float parSpeed = 1; //speed of particles
int nParticles = 1000; //# of particles
Particle[] particles;
void setup() {
size(700,700); //size of image (8.5 x 11 # 300px) is 3300,2550)
frameRate(60); //framerate of stage
background(0); //color of background
particles = new Particle[nParticles];
//start particle array
for(int i=0; i<nParticles; i++) {
particles[i] = new Particle();
}
}
void draw() {
fill(0,0,0,5); //5 is Alpha
rect(0,0,width,height); //color of rectangle on top?
translate(width/2, height/2); //starting point of particles
//start particle array
for(int i=0; i<nParticles; i++) {
particles[i].update();
particles[i].show();
}
}
//Particle Class
class Particle {
PVector pos; //position
float angle; //angle
float dRange; //diameter range
float dAngle; //beginning angle?
color c; //color
Particle() {
pos = new PVector(0,0);//new position for the particles.
angle = 1; //controls randomization of direction in position when multiplied
dRange = 0.01; // how big of a circle shold the particles rotate on
dAngle = 0.15; // -- maximum angle when starting
c = color(0,0,random(100, 255)); //set color to random blue
}
void update() {
float cor = .25*dRange*atan(angle)/PI;
float randNum = (random(2)-1)*dRange-cor; //Random number from (-dRange, dRange)
dAngle+=randNum; //We don't change the angle directly
//but its differential - source of the smoothness!
angle+=dAngle; //new angle is angle+dAngle -- change angle each frame
pos.x+=parSpeed*cos(angle);//random direction for X axis multiplied by speed
pos.y+=parSpeed*sin(angle);//rabdin durectuib for y axis multiplied by speed
}
void show() {
fill(c); //fill in the random color
noStroke(); //no stroke
ellipse(pos.x,pos.y,10,10); //make the shape
smooth(); //smooth out the animation
}
}
void keyPressed() {
print("pressed " + int(key) + " " + keyCode);
if (key == 's' || key == 'S'){
saveFrame("image-##.png");
}
}
void mouseReleased() {
print("mouse has been clicked!");
}
Overwrite the mouseReleased() method:
In there you'll need to:
capture the position of the mouse
create the new particle
update the position of the newly created particle.
add it to the array (the particle system)
This may look simple but you'll have to keep in mind an array cannot change sizes. I would advise that you create a ParticleSystem class that takes care of adding and removing particles from the system.
Edit: You might want to consider using an ArrayList instead of an Array of Particles. Have a look at this
In pseudo code this would look like this:
void mouseReleased() {
int particleX = mouseX;
int particleY = mouseY;
Particle P = new Particle();
P.setPos ( new PVector ( particleX, particleY ) ); // this needs to be implemented
ParticleSystem.add ( P ); // this needs to be implemented
}
I hope this will be a good start.
AH