Got this BOID application going in Processing with some steering algorithms.
The boids are stored
in two separate ArrayLists for each colour.
The red boid (predator) has a
pursue function:
class Creature {
int prey = 1;
PVector pursue(ArrayList boids) {
PVector steer = new PVector();
if (prey < boids.size()) {
Creature boid = (Creature) boids.get(prey);
steer = PVector.sub(boid.location, location);
steer.mult(maxpursue);
}
return steer;
}
This function gets the red boids to stand on top of the targeted white boid.
The problem is getting this white boid to disappear when all the red boids are on top of it. (Like shown in the image above)
I can add a new boid or predator with the following, but i cannot remove?:
void mousePressed() {
if (mouseButton == LEFT){
Creature predator = new Creature(mouseX, mouseY, 2);
planet.boids.add(predator);
} else if (mouseButton == RIGHT) {
Creature boid = new Creature(mouseX, mouseY, 1);
planet.boids.add(boid);
planet.boids.remove(boid); // This line does not work?
}
}
The code you posted doesn't make a ton of sense. You want to remove an existing Boid, so why on earth are you creating a new one and then immediately removing it?
You haven't posted an MCVE, so I can only answer in a general sense, but here's what you need to do:
Step 1: Refactor your code so that it makes more sense. Comment every single line if you have to, just to be sure you know exactly what the code is doing. But you shouldn't be doing things like adding a new Boid and then removing it in the very next line. Break your problem down into smaller steps, and make sure each step works perfectly by itself before trying to mix it with other funtionality.
Step 2: Create a function that takes a single white Boid and the List of red Boids, and returns true if that white Boid should be removed. Test this function by itself using hard-coded values in a standalone example sketch.
Step 3: Iterate over your white Boids and call the function you created in step 2 for each one. If the function returns true, then remove that white Boid. You might want to use an Iterator for this step.
If you get stuck on one of those steps, then post an MCVE along with a specific question, and we'll go from there. It's hard to answer general "how do I do this" type questions, but it's much easier to answer specific "I tried X, expected Y, but got Z instead" type questions- especially if we have an MCVE we can actually run on our own machines instead of some disconnected snippets.
Related
I'm trying to make a simple bit of code that will detect whether a model was clicked on. So far the best method I've seen is to create some sort of rectangle around the mesh and detect with Gdx.input.justTouched() to get the x,y coordinates, and then check if the rectangle contains the coordinates returned by justTouched().
I have no idea if there's a better way to do this, some kind of mesh onClick listener or something that LibGDX has in place that I'm unaware of (I've been scouring Google and the javadocs but I can't seem to find anything). I don't really need to deal with the z-axis coordinate, at least I don't think so. I only have the one PerspectiveCamera and it's not going to be moving around that much (not sure if this matters?)
Anyways, in my render() method I have:
if (Gdx.input.justTouched()) {
//this returns the correct values relative to the screen size
Vector2 pos = new Vector2(Gdx.input.getX(), Gdx.input.getY());
//I'm not sure how to get the correct rectangle to see what the
//width and height are for the model relative to the screen?
Rectangle modelBounds = new Rectangle(<<not sure what to put here>>);
if (modelBounds.contains(pos.x, pos.y) {
System.out.println("Model is being touched at: " + pos.x + ", " + pos.y);
}
}
I'm really not sure if this is the correct way to do this. I can get the position of the model with:
modelInstance.getNode("Node1").globalTransform.getTranslation(new Vector3());
but I'm not sure how to get the width and height as a rectangle relative to the screen size, if it's even possible.
I'm also unsure if this would cause massive lag, as I'm going to have about 7 nodes total that I need to detect if they're clicked on or not.
Is there a better way to do this? If not, is there a way to get the model width & height relative to the screensize (or camera, maybe)?
EDIT: Read about using Bounding Boxes, seems like what I need. Not quite sure how to implement it properly, however. I've changed my code to such:
public ModelInstance modelInstance;
public BoundingBox modelBounds;
#Override
public void create() {
...
//omitted irrelevant bits of code
modelInstance = new ModelInstance(heatExchangerModel);
modelBounds = modelInstance.calculateBoundingBox(new BoundingBox());
}
#Override
public void render() {
...
if (Gdx.input.justTouched()) {
Vector3 pos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
System.out.println(pos);
if (modelBounds.contains(pos)) {
System.out.println("Touching the model");
}
}
}
I'm not really sure what the output of BoundingBox is supposed to be, or how the numbers it gives me correlates to the position in a 2d space. Hmm..
EDIT2: Think I'm getting closer.. Read about Rays and the .getPickRay method for my PerspectiveCamera. .getPickRay seems to return completely unusable numbers though, like really tiny numbers. I think I need to do something like:
if (Gdx.input.justTouched()) {
Vector3 intersection = new Vector3();
Ray pickRay = perspectiveCamera.getPickRay(Gdx.input.getX(), Gdx.input.getY());
Intersector.intersectRayBounds(pickRay, modelBounds, intersection);
}
and then intersection should give me the point where they overlap. It appears to be not working, however, giving me really small numbers like (4.8066642E-5, 2.9180354E-5, 1.0) .. hmmm..
Solved.
I had a question before but it was very badly posted so here it goes again, according to better rules.
I want to create some style of a graph such as this image:
.
It's based on a physics law, Snell's Law. As of now I've managed to paint the graph it self with a basic Line2D.Double which you can see here (Line.java). Then all I need to do is, in the interface class, add the lines to the array in that class as so:
LinesArray.addLine(150 , 25 , 150 , 275);
And every time it adds a new one, it repaints as you can see in the code sample.
But the problem is that I have no idea how to make this interactive. I wanted to make it interactive, as in that you could actually move those lines and at the same time you move the first line, the second would move accordingly to the Snell's Law formula, which is:
n1 * sin( a1 ) = n2 * sin ( a2 )
Considering that a1 is the first (left) angle, and a2 the second (right) angle in the first image posted.
A perfect example of what I'd hope to achieve is this one.
And if interactive movement is too hard (I'm on a 2 days schedule), this example is also a possibility.
Correct me if I'm wrong but for the second one, all that I'd need to do is calculate the mouse's coordinates and draw and calculate everything from there.
Here (menu_ui.java) is my interface class, in which the method I'm currently working with the lines is "menuSnell()" and here (Snell.java is my Snell class which contains the logic. Apologies for portuguese comments but it's fairly simple code which you don't really need comments to understand, plus I've separated it into readable methods.
So basically, my question is how do I make those lines interactive in the way I've described above.
Thanks!
I am not a graphic expert, but I had similar work a long time ago. I had an object that I need to repaint. I created my own JPanel, which holds my objects that should be paint. Whenever something changed, I call repaint method on JPanel. It looked like this
http://sourceforge.net/p/scribbler-cvut/code/132/tree/Tuzka/src/cz/cvut/scribbler/panel/RewritableGlassPane.java.
private LinkedList<ColoredArea> background = new LinkedList<ColoredArea>();
/**
* Vykreslí všechny položky v senamu vykreslených obrazců
* #param g2d grafika k vykreslení
*/
public void paintShape(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (ColoredArea area : background) {
area.fill(g2d);
}
if (mouse != null && !block) {
g2d.setColor(mouse_color);
g2d.draw(mouse);
}
if (point!=null){
SetPointsDialog.paintPoints(point, maxPoint, parent.getChildsSize(), g2d);
}
}
#Override
public void paint(Graphics g) {
paintShape((Graphics2D) g);
}
#Override
protected void paintComponent(Graphics g) {
paintShape((Graphics2D) g);
}
Everything I need to paint was stored in background variable. When something I LinkedList changed, I invoke repaint () method on the window.
I have a full source code store here: http://sourceforge.net/projects/scribbler-cvut/ but it was my long term project, so it is a little bit big.
I am trying to make a onTouchEvent to create a missile that will launch from my character sprite and forward.
I have this working using
if (missdraw = true){
canvas.drawBitmap(missile,missilex,missileY,null);
missilex = missilex + 14;
missdraw = false;
}
in my onDraw method, but the problem is it will only create one at a time.
I tried to create a class to deal with this, but this just causes an error and crashes when i try to fire.
here is what i use for the class: (this is in the ondraw in my gameview)
for (Batcher missile : missiles ){
missile.onDraw(canvas);
}
this is in the class
public Batcher(List<Batcher> temps, ScreenActivity newView, float x,
float y, Bitmap missile){
this.x = 1;
this.y = 2;
this.missile = missile;
}
public void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
canvas.drawBitmap(missile, x,y, null);
}
I would appreciate any help, but also if you could explain how it would work, instead of just code, as im quite new to programming, and really need to understand what im doing and why im doing it, rather than just copying peoples code because it works.
Cheers Phil.
Your concepts are pretty good, actually. There are a few things I don't quite understand about the code samples you posted up, I'll try to translate into what I'd do and you can tell me if I'm doing it wrong :)
in your game class you need (and it looks like you have) a list of Missiles:
LinkedList<Batcher> missiles;
In your onTouch(), however a missile is created -
missiles.add(new Batcher(missilex, missiley, missile));
you now have a collection of missiles. Note that I didn't include the list in the constructor of your batcher, because an object should never need to know that it's a part of a collection. All it needs to know is how to draw itself and where. Since I assume that all of your missiles will be added to or removed from the screen frequently, while only having a few on screen at a time, I've used a LinkedList, which is fast for adding and removing, but slow for accessing a specific missile. If you needed to access specific items in the collection and the collection didn't change very much, you would use an ArrayList instead. on to onDraw - as you have it the missile draws itself, which is fine, but I prefer to let the View do the drawing, with the missile telling it where it should be drawn -
for (Batcher missile : missiles ){
missile.setX(missile.getX() + 14); // to make it move
if (missile.getX() > canvas.gedWidth()) { //check if it's left the screen
missiles.remove(missile); // Remove it
}
else { //perform drawing
canvas.drawBitmap(missile.getBitmap(), missile.getX(), missile.getY(), null);
}
}
Hopefully that'll do it for you, but feel free to let me know if there's anything you'd like me to explain more!
I'm pretty new at java and I've been trying to write a method that draws a gradient from one configurable color to another. However, it appears that if statements inside of the for loop are being ignored.
How can I fix this? or is there something else I'm missing?
and usage of the method is:
Gradient.dVertical(Graphics,Top left corner X,Top left corner Y,Size X,Size Y,tarting Red Value,Starting Green Value,Starting Blue Value,Ending Red Value,Ending Green Value,Ending Blue Value);
EDIT: I figured out what the real problem was and I fixed it. When it should have been incremental down it was going up. So I added a couple more if statements and that cleared it up. Using random integers when calling the method did reveal another problem though. With certain values it will not finish drawing and it will just cut off in the middle. FIXED
Here's the fixed part of the code if anyone is interested
if (rrepeat == true)
{
//prevents division by zero
if(rrate!=0)
{
//for a rate that must repeat checks
//whether or not it is time to increment
check = k%rrate;
if (check==0)
{
if(ered<sred)
{
rr--;
}
if(sred<ered)
{
rr++;
}
}
else
{
rr = rr;
}
}
}
You need to be overriding the paint method.
Here's an example: Introduction to applets
I'm working on to do my assignment. It is a chess design(AI, GUI not required), I have piece class. The piece class has two variables: color and name. So far I have a "move method" like this in this class.
`
public void move(Piece piece,int x,int y)
{
int a=0;
int b=0;
for(int i=0;i<Board.grid.length;i++) {
for(int r=0;r<Board.grid[i].length;r++) {
if(Board.grid[i][r]==piece)
a=i;
b=r;
if(Board.getisnull(x, y)){
Board.grid[a][b]=null;
Board.grid[x][y]=piece;
}
}
}
Board.grid[u][t]=null;
}
`
In this code, I want to find an index which is the old index of the piece I want to move, then moving it then setting its old index to null but this is not working. I can see the name on screen but not the color. Also, old index is not set to null. How to do it? I started to think using an object(piece) array but how?
Just a small hint:
//finds the piece equal to name and color of our piece.so
if(Board.grid[i][y].equals(name) || Piece.color.equals(color))
This doesn't fit together, since the check is "equal to name OR equal color". I think you want to change it to: if(Board.grid[i][y].equals(name) && Piece.color.equals(color))
Piece.setColor(color);//set this piece's color
Huh? What are you doing that for? Shouln't Piece keep its color all the time?
if(Board.getisnull(x, y)==true)
You're redefining y in your loop so y is not the parameter you passed in to the method.
Basically, I'd redefine the method (to keep is as close to the OP as possible, note that OOP wise there could be even better design, subclassing Piece etc.):
//Board.grid[][] should be a 'Piece[8][8]';
//edit: rename parameters for clarity
public void move( Piece piece,int targetX,int targetY)
{
if( Board.getisnull(targetX, targetY) )//method in other class checks the indexes if null
{
//remove the piece from the field/index
Board.grid[piece.x][piece.y]=null;
//add the piece to the target field and update its position
piece.x = targetX;
piece.y = targetY;
Board.grid[targetX][targetY]=piece;
}
else
{
//handle that case, e.g. by throwing an exeption
}
}
Now you'd get the piece you want to move (which knows its index), calculate the target position and call move(piece, targetX, targetY);