My title probably does not make much sense which is why I am having a bit of an issue googling my problem.
I am trying to move a shape on the screen from one set of X/Y coordinates to another in a direct line.
So for example,
This is the class method for setting the new target direction.
void setTargetPosition(int targetX, int targetY) {
xTar = targetX;
yTar = targetY;
if (xPos > xTar)
xDir = -1;
else
xDir = 1;
if (yPos > yTar)
yDir = -1;
else
xDir = 1;
}
This would set the Direction of the X/Y variables and the following code would move the player on the screen.
void drawPlayer() {
fill(circleColour);
circle(xPos,yPos,35);
//stops player from moving once target destination has been reached
if (xPos == xTar)
xDir = 0;
if (yPos == yTar)
yDir = 0;
xPos += xDir;
yPos += yDir;
}
The above code does work mostly as intended but I need to find a way to proportionally change the X/Y coordinate so that it's more of a 'direct line' to the destination.
Sorry if this does not make sense. I don't know the right terms to use.
You have to use floating point values for the computation of the movement rather than integral values:
float xTar;
float yTar;
float xPos;
float yPos;
setTargetPosition just set xTar and yTar:
void setTargetPosition(float targetX, float targetY) {
xTar = targetX;
yTar = targetY;
}
In drawPlayer you have to compute the direction vector (PVector) from the objects position to the target:
PVector dir = new PVector(xTar - xPos, yTar - yPos);
if the length of the vector (mag()) is greater than 0, the you have to move the object:
if (dir.mag() > 0.0) {
// [...]
}
If you have to move the object, then compute the Unit vector by normalize(). Note, the length of a unit vector is 1. Multiply the vector by a certain speed by mult(). This scales the vector to a certain length. Ensure that the length of the vector is not greater than the distance to the object (min(speed, dir.mag())). Finally add the components of the vector to the position of the object:
dir.normalize();
dir.mult(min(speed, dir.mag()));
xPos += dir.x;
yPos += dir.y;
See the example:
class Player {
float xTar;
float yTar;
float xPos;
float yPos;
color circleColour = color(255, 0, 0);
Player(float x, float y)
{
xTar = xPos = x;
yTar = yPos = y;
}
void setTargetPosition(float targetX, float targetY) {
xTar = targetX;
yTar = targetY;
}
void drawPlayer() {
fill(circleColour);
circle(xPos,yPos,35);
float speed = 2.0;
PVector dir = new PVector(xTar - xPos, yTar - yPos);
if (dir.mag() > 0.0) {
dir.normalize();
dir.mult(min(speed, dir.mag()));
xPos += dir.x;
yPos += dir.y;
}
}
}
Player player;
void setup() {
size(500, 500);
player = new Player(width/2, height/2);
}
void draw() {
background(255);
player.drawPlayer();
}
void mousePressed() {
player.setTargetPosition(mouseX, mouseY);
}
Currently I'm working on a simple 2d platformer, and I decided to work on physics before working on the general concept of the game. I actually haven't learned physics in school or anything, so I'm just using google/youtube tutorials as my main resources. I've currently gotten jumping working pretty nicely, but moving side to side isn't what I would like it to be. I want it to use acceleration/deceleration vs. just incrementing/decrementing the x position by a constant speed. Now I've tried using this website for x motion but that seems to be what I'm using for jumping. Here is my current player class:
import game.Game;
import game.input.PlayerController;
public class Player {
private float dt = 0.18F, gravity = 9.81F;
public float x, y, dx, dy;
private PlayerController controller;
private boolean jumping, onGround;
public float speed = 7.5F;
public float jh = 60F;
public float vy = 120F;
public Player() {
controller = new PlayerController();
}
public void update() {
controller.update(this);
dy += gravity * dt * (jumping ? -1F : 1F);
if(!jumping && !onGround && dy > vy) dy = vy;
y += dy * dt + 0.5F * gravity * dt * dt;
x += dx;
if (y > Game.height - 32) {
dy = 0;
y = Game.height - 32;
onGround = true;
} else
onGround = false;
if(dy < jh) { jumping = false;}
dx = 0;
}
public void render(Graphics g) {
g.setColor(Color.red);
g.fillRect(x, y, 32, 32);
}
public void moveLeft() {
dx -= speed;
}
public void moveRight() {
dx += speed;
}
public void jump() {
if (onGround) {
jumping = true;
dy -=jh;
}
}
}
In the PlayerController class I'm just calling player.moveLeft() and player.moveRight() when the left and right keys are pressed.
If anybody has a good idea on how to make smoother movement, that would be very helpful. Thanks!
I have a bullet class and an algorithm that will move my bullet to where I pressed, but how would I have the bullet continuing on past the mouse_x and mouse_y when it was clicked?
In My Update method:
float xSpeed = (MoveToX - x) / 9;
float ySpeed = (MoveToY - y) / 9;
this.x += xSpeed;
this.y += ySpeed;
And this is when I first create the bullet:
Bullet(int Mx, int My){
c = Color.red;
MoveToX = Mx;
MoveToY = My;
MoveToX += Board.cam.camX;
MoveToY += Board.cam.camY;
Mx is the mouses x when it was clicked. Same with the y.
Edit:
This is my final product: everything works as it should
Bullet(int Mx, int My){
c = Color.red;
MoveToX = Mx + Board.cam.camX;
MoveToY = My + Board.cam.camY;
int speed = 5;
float distance = (float) Math.sqrt(Math.pow(MoveToX - x, 2) + Math.pow(MoveToY - y, 2));
amountToMoveX = (((MoveToX - x) / distance) * speed);
amountToMoveY = (((MoveToY - y) / distance) * speed);
}
public void update(){
x += amountToMoveX;
y += amountToMoveY;
}
The instance variables of your bullet shouldn't be moveTo_, but velocity and direction.
Calculate the direction (i.e. the angle) in the constructor, from the bullet position and the target position. velocity may also be a static constant, depending on your use case.
If it is an option, I would strongly recommend to use a physics- or game-engine. Those kind of problems were already solved a hundred times in those engines. They relieve you from those basic tasks and help you concentrate on your actual problem.
I am making a 2d rpg game in java and I have run into a problem. I can make the player move around the stage and I have rocks, trees, walls, etc. on the stage as well. I don't know how to detect the collision and make it to where the player can't move through the object. The code that reads map file and draws image on the canvas is as follows:
public void loadLevel(BufferedImage levelImage){
tiles = new int[levelImage.getWidth()][levelImage.getHeight()];
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
Color c = new Color(levelImage.getRGB(x, y));
String h = String.format("%02x%02x%02x", c.getRed(),c.getGreen(),c.getBlue());
switch(h){
case "00ff00"://GRASS Tile - 1
tiles[x][y] = 1;
break;
case "808080"://Stone -2
tiles[x][y] = 2;
break;
case "894627"://Dirt -3
tiles[x][y] = 3;
break;
case "404040"://Rock on Grass -4
tiles[x][y] = 4;
break;
case "00b700"://Tree -5
tiles[x][y] = 5;
break;
case"000000"://Wall -6
tiles[x][y] = 6;
break;
case "cccccc"://Rock on stone -7
tiles[x][y] = 7;
break;
default:
tiles[x][y] = 1;
System.out.println(h);
break;
}
}
}
}
And the player class is as follows:
public class Player {
private int x,y;
public int locx,locy;
private Rectangle playerR;
private ImageManager im;
public boolean up =false,dn = false,lt=false,rt=false,moving = false,canMove = true;
private final int SPEED =2;
public Player(int x, int y, ImageManager im){
this.x = x;
this.y = y;
this.im = im;
locx = x;
locy = y;
playerR = new Rectangle(x,y,16,16);
}
public void tick(){
if (up) {
if(canMove){
y -= SPEED;
locx = x;
locy = y;
playerR.setLocation(locx, locy);
moving = true;
}
else{
y += 1;
canMove=true;
}
}
if (dn) {
y +=SPEED;
locx = x;
locy = y;
moving = true;
}
}
if (lt) {
x -= SPEED;
locx = x;
locy = y;
moving = true;
}
if (rt) {
x+=SPEED;
locx = x;
locy = y;
moving = true;
}
}
if(moving){
System.out.println("PLAYER\tX:"+locx+" Y:"+locy);
moving = false;
}
}
public void render(Graphics g){
g.drawImage(im.player, x, y, Game.TILESIZE*Game.SCALE, Game.TILESIZE*Game.SCALE, null);
}
}
I don't really know how to do collision, but i googled it and people said to make a rectangle for the player and all the objects that the player should collide with, and every time the player moves, move the player's rectangle. Is this the right way to do this?
EDIT EDIT EDIT EDIT
code for when collision is true:
if (rt) {
x+=SPEED;
locx = x;
locy = y;
playerR.setLocation(locx, locy);
for(int i = 0;i<Level.collisions.size();i++){
if(intersects(playerR,Level.collisions.get(i))==true){
x-=SPEED;
locx = x;
playerR.setLocation(locx, locy);
}
}
moving = true;
}
And the intersects method is as follows:
private boolean intersects(Rectangle r1, Rectangle r2){
return r1.intersects(r2);
}
I'm going to focus on your tick method since that is where most of this logic is going. There are a couple changes here. Most notably, we only move the rectangle before checking for collisions. Then loop through all the collideable objects in your level. Once one is found, we reset our x and y and break out of the loop (no sense in looking at any of the other objects since we already found the one we collided with). Then we update our player position. By doing it this way, I centralized the code so it is not being repeated. If you ever see yourself repeating code, there is a pretty good chance that it can be pulled out to a common place, or to a method.
public void tick() {
if (up) {
y -= SPEED;
} else if (dn) {
y += SPEED;
} else if (lt) {
x -= SPEED;
} else if (rt) {
x += SPEED;
}
playerR.setLocation(x, y);
for (Rectangle collideable : Level.collisions) {
if (intersects(playerR, collideable)) {
x = locx;
y = locy;
playerR.setLocation(x, y);
break;
}
}
locx = x;
locy = y;
}
There are different ways to do that. As you talk about a "rpg" i think your view is Isometric (45° top down).
I would do the collision detection in pure 90° top down, as it is easier and, imho, more realistic.
We have 2 possibilities:
Move your Player to the next position. If there is a collision, reset his position.
Calculate the next position, if there would be a collision don't move.
If you want to have a "gliding" collision response, you have to check in which axis the collision will happen, and stop / reset movement for this axis only.
To have a more efficient collision detection only check near objects, which will possibly collide.
Do this by comparing a squared "dangerRadius" with the squared distance between your player and the object:
if ((player.x - object.x)² + (player.y - object.y)² <= dangerRadius²)
// Check for intersection
This will sort out most of the objects by using a simple calculation of:
2 subtractions
1 addition
3 multiplications (the ²)
1 compare (<=)
In your game you should sepparate the logic and the view. So basicly you don't detect, if the two images overlapp, but you check, if the objects in your logic overlap. Then you draw the images on the right position.
Hope this helps.
EDIT: Important: If you update your character, depending on the time between the last and this frame (1/FPS) you have to limit the max timestep. Why? Because if for some reason (maybe slow device?) the FPS are really low, it is possible, that the character moves verry far between 2 frames and for that he could go through an object in 1 frame.
Also if you simply reset the movement on collision or just don't move the distance between you and the object could be big for low FPS. For normal FPS and not to high movementspeed this won't happen/ be noticeable.
I personally am fairly new to Java, though I have worked with C# in the past. I am making a similar game, and for collision detection I just check the locations of the player and objects:
if (z.gettileX() == p.gettileX()){
if (z.gettileY() == p.gettileY()){
System.out.println("Collision!");
}
}
If the player (p) has equal X coordinates and Y coordinates to z(the bad guy), it will send this message and confirm that the two have, in fact, collided. If you can make it inherent in the actual class behind z to check if the coordinates a equal, you can create an unlimited number of in-game objects that detect collision and react in the same way, i.e. walls.
This is probably what your looking for. I've made this class spicificly for collision of multiple objects and for individual side collisions.
abstract class Entity {
private Line2D topLine;
private Line2D bottomLine;
private Line2D leftLine;
private Line2D rightLine;
private Rectangle rectangle;
private Entity entity;
protected boolean top;
protected boolean bottom;
protected boolean left;
protected boolean right;
protected int x;
protected int y;
protected int width;
protected int height;
public Entity(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
updateLinesAndRects();
}
public void updateLinesAndRects() {
topLine = new Line(x + 1, y, width - 2, 0);
bottomLine = new Line(x + 1, y + height, width - 2, height);
leftLine = new Line(x, y + 1, 0, height - 2);
rightLine = new Line(x + width, y + 1, 0, height - 2);
rectangle = new Rectangle(x, y, width, height)
}
public void setCollision(Entity entity) {
this.entity = entity;
top = isColliding(new Line2D[]{topLine, bottomLine, leftLine, rightLine});
bottom = isColliding(new Line2D[]{bottomLine, topLine, leftLine, rightLine});
left = isColliding(new Line2D[]{leftLine, topLine, bottomLine, rightLine});
right = isColliding(new Line2D[]{rightLine, topLine, bottomLine, leftLine});
}
public void updateBounds() {
if(top) y = entity.y + entity.height;
if(bottom) y = entity.y - height;
if(left) x = entity.x + entity.width;
if(right) x = entity.x - width;
}
public boolean isColliding() {
return rectangle.intersects(entity.rect);
}
private boolean isLinesColliding(Line2D[] lines) {
Rectangle rect = entity.getRectangle();
return lines[0].intersects(rect) && !lines[1].intersects(rect) && !lines[2].intersects(rect) && !lines[3].intersects(rect);
}
private Line2D line(float x, float y, float width, float height) {
return new Line2D(new Point2D.Float(x, y), new Point2D.Float(x + width, x + height));
}
public Rectangle getRectangle() {
return rectangle;
}
}
Example:
class Player extends Entity{
Entity[] entities;
public Player(int x, int y, int width, int height) {
super(x, y, width, height);
}
public void update() {
updateLinesAndRects();
for(Entity entity : entities) {
setCollision(entity);
if(top) system.out.println("player is colliding from the top!");
if(isColliding()) system.out.println("player is colliding!");
updateBounds(); // updates the collision bounds for the player from the entities when colliding.
}
}
public void setEntities(Entity[] entities) {
this.entities = entities;
}
}
I have this class, I m sending this class via RMI and via kryonet and kryo, I m getting the array of 10 objects with both incase of rmi, as return of remote method call and in case of kryonet echoing from server to client with kryonet and kryo, I have total of one object 55*10 which 555 but with RMI 1196bytes ,
Are these results are reasonable?, can some body shed some light,
*why these results are like that?
why there is that much difference.?
which overheads or other factors are involved behind the scene,
which are making that much total in RMI and too much difference and point me.
And is it 55 bytes total for single object is ok?*.
i just need some confirmation and experts eyes as i have to present these results,
I will be really thankful.
This is class which I m using with both:
public class TBall {
private float x, y; // Ball's center (x, y)
private float speedX, speedY; // Ball's speed per step in x and y
private float radius; // Ball's radius
private Color color; // Ball's color
public boolean collisionDetected = false;
public static boolean run = false;
private String name;
private float nextX, nextY;
private float nextSpeedX, nextSpeedY;
public TBall() {
super();
}
public TBall(String name1, float x, float y, float radius, float speed,
float angleInDegree, Color color) {
this.x = x;
this.y = y;
// Convert velocity from polar to rectangular x and y.
this.speedX = speed * (float) Math.cos(Math.toRadians(angleInDegree));
this.speedY = speed * (float) Math.sin(Math.toRadians(angleInDegree));
this.radius = radius;
this.color = color;
this.name = name1;
}
public String getName() {
return this.name;
}
public float getSpeed() {
return (float) Math.sqrt(speedX * speedX + speedY * speedY);
}
public float getMoveAngle() {
return (float) Math.toDegrees(Math.atan2(speedY, speedX));
}
public float getRadius() {
return radius;
}
public Color getColor() {
return this.color;
}
public void setColor(Color col) {
this.color = col;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public void setX(float f) {
x = (int) f;
}
public void setY(float f) {
y = (int) f;
}
public void move() {
if (collisionDetected) {
// Collision detected, use the values computed.
x = nextX;
y = nextY;
speedX = nextSpeedX;
speedY = nextSpeedY;
} else {
// No collision, move one step and no change in speed.
x += speedX;
y += speedY;
}
collisionDetected = false; // Clear the flag for the next step
System.out.println("In serializedBall in move.");
}
public void collideWith() {
float minX = 0 + radius;
float minY = 0 + radius;
float maxX = 0 + 640 - 1 - radius;
float maxY = 0 + 480 - 1 - radius;
double gravAmount = 0.9811111f;
double gravDir = (90 / 57.2960285258);
// Try moving one full step
nextX = x + speedX;
nextY = y + speedY;
System.out.println("In serializedBall in collision.");
// If collision detected. Reflect on the x or/and y axis
// and place the ball at the point of impact.
if (speedX != 0) {
if (nextX > maxX) { // Check maximum-X bound
collisionDetected = true;
nextSpeedX = -speedX; // Reflect
nextSpeedY = speedY; // Same
nextX = maxX;
nextY = (maxX - x) * speedY / speedX + y; // speedX non-zero
} else if (nextX < minX) { // Check minimum-X bound
collisionDetected = true;
nextSpeedX = -speedX; // Reflect
nextSpeedY = speedY; // Same
nextX = minX;
nextY = (minX - x) * speedY / speedX + y; // speedX non-zero
}
}
// In case the ball runs over both the borders.
if (speedY != 0) {
if (nextY > maxY) { // Check maximum-Y bound
collisionDetected = true;
nextSpeedX = speedX; // Same
nextSpeedY = -speedY; // Reflect
nextY = maxY;
nextX = (maxY - y) * speedX / speedY + x; // speedY non-zero
} else if (nextY < minY) { // Check minimum-Y bound
collisionDetected = true;
nextSpeedX = speedX; // Same
nextSpeedY = -speedY; // Reflect
nextY = minY;
nextX = (minY - y) * speedX / speedY + x; // speedY non-zero
}
}
System.out.println("In serializedBall collision.");
// speedX += Math.cos(gravDir) * gravAmount;
// speedY += Math.sin(gravDir) * gravAmount;
System.out.println("In serializedBall in collision.");
}
}
Thanks.
Where did you get '55' from? You have:
9 floats, = 9x4 bytes, total 36 bytes
1 boolean, serialized as a byte, total 1 byte
1 String, could be any length
1 Color, which in turn contains:
1 int, serialized as 4 bytes
1 float, serialized as 4 bytes
2 float[] of length 3 each, serialized as 24 bytes
1 Colorspace, which in turn contains:
2 ints, serialized as 8 bytes
The total of this is at least 77 bytes plus whatever is required to transmit the String.
Serialization also sends class information, versioning information, and a tag in front of every item; RMI also sends method information. All that could easily account for the difference. I don't know what those other packages do.