After searching a large amount of sites, including this one, every solution i have came across seems to not work, or only work on the first object in the list.
The Problem
Slick2Ds Rectangle class offers many different methods for collision, one being the intersects(Rectangle box); method that correctly detects collisions when using this class in conjunction with javas built in ArrayList class,to an extent. The problem I'm having is that only the first object in the list is being detected and correctly collided upon.
The following code handles collisions:
public void move(float x, float y) {
if (blocks.size() > 0) {
for (int i = 0; i < blocks.size(); i++) {
Rectangle r = blocks.get(i);
Rectangle p = new Rectangle(xx + x, yy + y, 32, 32);
if (!r.intersects(p)) {
xp = xx;
yp = yy;
xx += x;
yy += y;
break;
} else {
xx = xp;
yy = yp;
xx += 0;
yy += 0;
System.out.println("Collide" + new Date());
break;
}
}
}else{
xp = xx;
yp = yy;
xx += x;
yy += y;
}
}
Key: xx = Player x; yy = Player y; xp = Players Last x Position; yp = Players Last y Position; r = Current Rectangle in the iteration list; p = Pre-calculated next position of the player
This basic codes job is to add movement by simulating a rectangle that will be in the next position the player is. if it does not collide then the player wont collide and we can move, but if it does collide then we don't move the player as the next location is not open.
But the code has a flaw as at some point during the iteration only the first box works, the others do detect collides but does not stop the box.
Correct Collision; logged in the console to confirm
Incorrect Collision; not logged in the console, even though its another instance of the same object
What happens if you use :
public void move(float x, float y) {
boolean intersectedBlock = false;
for (int i = 0; i < blocks.size(); i++) {
Rectangle r = blocks.get(i);
Rectangle p = new Rectangle(xx + x, yy + y, 32, 32);
if (r.intersects(p)) {
intersectedBlock = true;
break;
}
}
if (intersectedBlock) {
xx = xp;
yy = yp;
xx += 0;
yy += 0;
System.out.println("Collide" + new Date());
} else {
xp = xx;
yp = yy;
xx += x;
yy += y;
}
}
try to remove all the breaks.
because if it find the intersects or not, it will break out of the loop.
Related
I'm trying to make a plugin that can spawn mobs above specific block with a command. The problem is that I dont really know where to start... I am basicly looking for a function or way to cycle through all of the blocks in an area and return something when it finds 1 or more of the block type.
if (sender instanceof Player) {
Player p = (Player) sender;
if (p.hasPermission(command.getPermission())) {
Location playerLoc = p.getLocation();
org.bukkit.World world = p.getWorld();
double startX = playerLoc.getX();
double startY = playerLoc.getY() - 1;
double startZ = playerLoc.getZ() - 1;
for (int x = 0; x < Integer.valueOf(args[0]); x++) {
for (int z = 0; z < Integer.valueOf(args[1]); z++) {
for (int y = 0; y <= Integer.valueOf(args[2]); y++) {
Location loc = new Location(world, startX + x, startY + y, startZ + z);
if (loc.getBlock().equals(Material.yourmaterial)){
//do what you want
}
}
}
}
} else {
sender.sendMessage(ChatColor.DARK_RED+"Specify the size");
}
}
return true;
}
Hope that helps!
I am trying to make Space Invaders in Processing. I am currently working on getting the enemy to move correctly. I have got them to be drawn in the right spot but I haven't gotten them to be moved correctly. Here is my code:
PImage mainPlayer;
PImage enemyPlayer;
float Xspeed = 60;
float Yspeed = 60;
float X;
float Y;
Enemy EnemyPlayer = new Enemy("EnemyPlayerSpaceInvaders.png", 10, 10, 6);
void setup() {
size(1400, 800);
//enemyPlayer = loadImage("EnemyPlayerSpaceInvaders.png");
mainPlayer = loadImage("MainPlayerSpaceInvaders.png");
}
void draw() {
background(0);
Enemy[] enemyPlayer = new Enemy[60];
for (int i = 0; i < 5; i += 1) {
for (int j = 0; j < 11; j += 1) {
enemyPlayer[j *i] = new Enemy("EnemyPlayerSpaceInvaders.png", 50 + j * 100, 5 + 75 * i, 6);
}
}
for (int i = 0; i < 5; i += 1) {
for (int j = 0; j < 11; j += 1) {
if(enemyPlayer[j * i].alive){
enemyPlayer[j * i].Draw();
}
enemyPlayer[j *i].moveAndDraw(6);
}
}
}
class Enemy {
boolean alive = true;
float x;
float y;
float speed;
String playerTexFile;
PImage playerTex;
Enemy(String PlayerTexFile, float X, float Y, float Speed){
x = X;
y = Y;
speed = Speed;
playerTexFile = PlayerTexFile;
}
void Draw(){
playerTex = loadImage(playerTexFile);
image(playerTex, x, y);
}
void moveAndDraw(float Speed){
playerTex = loadImage(playerTexFile);
if(alive){
x += Speed;
if (x >= 1300) {
x = 100;
y += 50;
}
}
}
}
Here is my result:
The Draw function works but what you're seeing that is messing it up is the moveAndDraw() function.
And the enemy drawings aren't moving. I have made this before with c++ SFML but in that there is a very basic getPosition function. The reason I want to get position is that right now I'm having to use inaccurate numbers as the X and Y position and for the enemy to move correctly I need to know exactly what it's position is. I have checked multiple pages on processing.org but none of them helped. I haven't found any getPosition void and all the ones I've seen other people using a void to do this I just haven't been able to get it to work. If there is some code that could get me this to work or just some function I've looked over and even a website page I could look at I'd be open to it. Please tell me anything I can do to get this working.
The issue is that you recreate the enemies in every frame at it's initial position:
void draw() {
background(0);
Enemy[] enemyPlayer = new Enemy[60];
for (int i = 0; i < 5; i += 1) {
for (int j = 0; j < 11; j += 1) {
enemyPlayer[j *i] = new Enemy("EnemyPlayerSpaceInvaders.png", 50 + j * 100, 5 + 75 * i, 6);
}
}
// [...]
}
You've to:
Create a global array of enemies Enemy[] enemyPlayer (and delete PImage enemyPlayer).
Create and initialize the enemies in setup.
Use and move the existing enemies in draw:
Further note, that your loops doesn't do what you expect it to do. Create the enemies in 2 nested loops. If i runs from o to 6 and j from 0 to 10, the the index of an enemy is i*10 + j.
The enemies can be moved in a single loop from 0 to enemyPlayer.length.
//PImage enemyPlayer; <--- DELETE
// global array of enemies
Enemy[] enemyPlayer = new Enemy[60];
// [...]
void setup() {
size(1400, 800);
mainPlayer = loadImage("MainPlayerSpaceInvaders.png");
// create enemies
for (int i = 0; i < 6; i += 1) {
for (int j = 0; j < 10; j += 1) {
enemyPlayer[i*10 + j] = new Enemy("rocket64.png", 50 + j * 100, 5 + 75 * i, 6);
}
}
}
void draw() {
background(0);
// move enemies
for(int i = 0; i < enemyPlayer.length; ++i ) {
if(enemyPlayer[i].alive){
enemyPlayer[i].Draw();
}
enemyPlayer[i].moveAndDraw(6);
}
}
I have this array
Ball[] balls = new Ball[7]; // 7 just being an example
In my Ball class, I have getters and setters for x and y values.
I'm trying to compare the x and y values to make sure that they don't intersect.
My first thought was to make a loop looking like
for(Ball b1 : balls) {
for(Ball b2 : balls) {
if(b1.intersects(b1, b2)) {. . .} // I made intersects, not my issue
}
}
But this is no good, as it compares:
balls 0 to balls 0
balls 1 to balls 1
etc.
for(int i = 0; i < balls.length; i++) {
System.out.println(f.getContentPane().getWidth() + "\n" + f.getContentPane().getHeight());
int radius = 10 + rand.nextInt(20);
balls[i] = new Ball(360, radius,
rand.nextInt(f.getContentPane().getWidth() - 4 * radius - 5) + radius + 5,
rand.nextInt(f.getContentPane().getHeight() - 4 * radius - 5) + radius + 5
);
}
for(Ball b1 : balls) {
for (Ball b2 : balls) {
while (b1.intersects(b1, b2)) {
System.out.println("Ball started out inside of another, replacing now.");
b1.setX(rand.nextInt(f.getContentPane().getWidth() - 2 * b1.getRadius() - 5) + b1.getRadius() + 5);
b1.setY(rand.nextInt(f.getContentPane().getHeight() - 2 * b1.getRadius() - 5) + b1.getRadius() + 5);
}
}
}
////////////// class change //////////////////
class Ball {
private int direction;
private int radius;
private int x,y;
Ball(int direction, int radius, int x, int y) {
this.direction = direction;
this.radius = radius;
this.x = x;
this.y = y;
}
// Getters + Setters here
boolean intersects(Ball b1, Ball b2) {
double x = Math.pow((b2.getX() - b1.getX()), 2); // Distance formula
double y = Math.pow((b2.getY() - b1.getY()), 2); // Distance formula
double r = b1.getRadius() + b2.getRadius();
//System.out.println(x + " + " + y + " <= " + r );
return x + y <= r;
}
}
(Ignore that I didn't put my first hunk of code in a method and class, I've done that in my actual code.)
I, for whatever reason, can't think of a way to do this without a whole lot of if statements
(So I'm asking for the best way to do this)
One way to compare every distinct (i.e., no ball with itself) pair of Balls, without comparing any pair more than once would be:
for (int i = 0; i < balls.length; ++i) {
Ball b1 = balls[i];
for (int j = i+1; j < balls.length; ++j) {
Ball b2 = balls[j];
if (b1.intersects(b1, b2)) {
// ...
}
}
}
Detecting new collisions introduced in the process of resolving previous ones just means making multiple passes over balls until you no longer have any collisions. A simple, perhaps naive, way of doing this would be something like this:
boolean foundCollision;
int numTries = 0;
int maxTries = 1000000;
do {
foundCollision = false;
for (int i = 0; i < balls.length; ++i) {
Ball b1 = balls[i];
for (int j = i+1; j < balls.length; ++j) {
Ball b2 = balls[j];
if (b1.intersects(b1, b2)) {
foundCollision = true;
// resolve collision...
}
}
++numTries;
} while (foundCollision && numTries < maxTries);
if (numTries >= maxTries)
System.err.println("Couldn't sort out balls after " + maxTries + "tries: what now?");
I need a method to get the points of the circle, I have one that I found online but unfortunately I'd like to add a boolean filled to it:
public static Location[] getCylinderAt(Location loc, int r, int height) {
ArrayList<Location> list = new ArrayList<>();
int cx = loc.getBlockX();
int cy = loc.getBlockY();
int cz = loc.getBlockZ();
World w = loc.getWorld();
int rSquared = r * r;
for (int x = cx - r; x <= cx + r; x++) {
for (int y = cy - height; y <= cy + height; y++) {
for (int z = cz - r; z <= cz + r; z++) {
if ((cx - x) * (cx - x) + (cz - z) * (cz - z) <= rSquared) {
list.add(new Location(w, x, y, z));
}
}
}
}
return list.toArray(new Location[list.size()]);
}
I can't really get my head around the maths involved in this and have been searching through non minecraft sources to create my own but to no avail.
Ideally I'd like to be able to change the method to this:
public static Location[] getCylinderAt(Location loc, boolean filled, int r, int height)
Thanks guys! If you like I can remove all of the minecraft references, but I didn't think it'd be necessary as a Location is basically a Vector with a few added minecraft only variables!
Thanks for reading :)
Are you looking for a way to compute pixels on the rim of a circle, as opposed to those inside, for the case where filled is false? If so, have a look at the midpoint circle algorithm. It describes how a circle can be drawn in a raster image.
I am making and auto clicker using java.awt.Robot. One of the concerns i have however is the movements aren't very humanlike. Can anyone suggest some changes to my code to make it more human like? Right now it just moves in a straight line.
/**
*
* #param robot The java.awt.Robot being utilized
* #param sx The start x position of the mouse
* #param sy The start y potition of the mouse
* #param ex The end x position of the mouse
* #param ey The end y position of the mouse
* #param speed The speed at which to travel
*/
public void moveMouse(Robot robot, int sx, int sy, int ex, int ey, int speed){
for (int i=0; i<100; i++){
int mov_x = ((ex * i)/100) + (sx*(100-i)/100);
int mov_y = ((ey * i)/100) + (sy*(100-i)/100);
robot.mouseMove(mov_x,mov_y);
robot.delay(speed);
}
}
Update:
I decided to go with an algorithm that makes use of Bézier Curves. It's been a very long time since I implemented the change, but I wanted to post it here just in case people would find it useful in the future. Here is what I ended up with:
public class MouseEvent{
public int getMouseX(){
return MouseInfo.getPointerInfo().getLocation().x;
}
public int getMouseY(){
return MouseInfo.getPointerInfo().getLocation().y;
}
public void moveMouse(int speed, int destX, int destY, int ranX, int ranY){
Mouse.moveMouse(new Robot(), new Point(getMouseX(),getMouseY()), new Point(destX, destY), speed, ranX, ranY);
}
}
public class Mouse {
public static void moveMouse(Robot robot, Point s, Point e, int speed, int ranX, int ranY){
if(Math.abs(e.x-s.x) <= ranX && Math.abs(e.y-s.y) <= ranY)
return;
Point[] cooardList;
double t; //the time interval
double k = .025;
cooardList = new Point[4];
//set the beginning and end points
cooardList[0] = s;
cooardList[3] = new Point(e.x+random(-ranX,ranX),e.y+(random(-ranY,ranY)));
int xout = (int)(Math.abs(e.x - s.x) /10);
int yout = (int)(Math.abs(e.y - s.y) /10);
int x=0,y=0;
x = s.x < e.x
? s.x + ((xout > 0) ? random(1,xout) : 1)
: s.x - ((xout > 0) ? random(1,xout) : 1);
y = s.y < e.y
? s.y + ((yout > 0) ? random(1,yout) : 1)
: s.y - ((yout > 0) ? random(1,yout) : 1);
cooardList[1] = new Point(x,y);
x = e.x < s.x
? e.x + ((xout > 0) ? random(1,xout) : 1)
: e.x - ((xout > 0) ? random(1,xout) : 1);
y = e.y < s.y
? e.y + ((yout > 0) ? random(1,yout) : 1)
: e.y - ((yout > 0) ? random(1,yout) : 1);
cooardList[2] = new Point(x,y);
double px = 0,py = 0;
for(t=k;t<=1+k;t+=k){
//use Berstein polynomials
px=(cooardList[0].x+t*(-cooardList[0].x*3+t*(3*cooardList[0].x-
cooardList[0].x*t)))+t*(3*cooardList[1].x+t*(-6*cooardList[1].x+
cooardList[1].x*3*t))+t*t*(cooardList[2].x*3-cooardList[2].x*3*t)+
cooardList[3].x*t*t*t;
py=(cooardList[0].y+t*(-cooardList[0].y*3+t*(3*cooardList[0].y-
cooardList[0].y*t)))+t*(3*cooardList[1].y+t*(-6*cooardList[1].y+
cooardList[1].y*3*t))+t*t*(cooardList[2].y*3-cooardList[2].y*3*t)+
cooardList[3].y*t*t*t;
robot.mouseMove((int)px, (int)py);
robot.delay(random(speed,speed*2));
}
}
}
public void moveMouse(int sx, int sy, int ex, int ey, int speed) throws AWTException {
Robot robot = new Robot();
int a = 10;
boolean flag = true;
for (int i = 0; i < 100; i++) {
int mov_x = ((ex * i) / 100) + (sx * (100 - i) / 100);
int mov_y = ((ey * i) / 100) + (sy * (100 - i) / 100);
if (flag == true) {
robot.mouseMove(mov_x + a, mov_y); // adds 10 to X-axis
flag = false;
} else {
robot.mouseMove(mov_x - 2 * a, mov_y); // subtracts 20 to X-axis
flag = true;
}
robot.delay(speed);
}
}
Just manipulated your code. This moves the mouse in straight path in X-direction. You can achieve what you want from here. Just get the ideas. You can move any way you want if you can manipulate mov_x and mov_y .
You could use Catmull-Rom method. Generate random controlpoints somewhere around the endpoints and maybe where the straight line would be, asking for coordinates on every step moving from start to end (parameter t, from zero to one).
See demo applets and source: http://www.cse.unsw.edu.au/~lambert/splines/