all:
I have created a PetCanvas class to handle an ArrayList of pets that each have their own draw method. This draw method is void and accepts a GraphicsContext object that is used to specify how the pet is drawn. The GraphicsContext object comes from the PetCanvas class that has a void method sketchPet that calls draw on each of the pets in the list. I want to use the PetCanvas object to draw the Graphics to the GUI but the compiler will not allow me to add PetCanvas.sketchPet to the root because sketchPet does not return a Node object. Any suggestions? Or any more information needed to determine a solution?
Thank you in advance.
I'm beginning to think the issue lies here:
public void sketchPets() {
if (this.drawableList.size() == 0) {
throw new IllegalArgumentException("The list has no animals to draw");
}
for (Drawable current : this.drawableList) {
current.draw(this.getGraphicsContext2D());
}
}
The current.draw line does nothing with the GraphicsContext object after it is drawn. I'm not sure how to remedy this issue if it is the cause.
Related
I'm using GraphStream to show a map of an area and I've tried to inherit from the default MouseManager DefaultMouseManager and to override the mouseClicked method so that when clicking on a node the following will happened:
node's color will change.
node's label will show.
node's data will show in terminal.
I do know that the method works because the node's data does get printed to terminal, but I think some other mouse event repaint the node and rehide the label so they doesn't change when clicking on a node.
here is my MouseManager's code:
public class CustomMouseManager2 extends DefaultMouseManager {
protected View view;
protected GraphicGraph graph;
private GraphicElement focusedNode;
#Override
public void init(GraphicGraph graph, View view) {
super.init(graph, view);
.
.
.
}
#Override
public void mouseClicked(MouseEvent e) {
GraphicElement currentNode = view.findNodeOrSpriteAt(e.getX(), e.getY());
if(currentNode != null){
OGraph graph = OGraph.getInstance();
Random r = new Random();
currentNode.setAttribute("ui.style", "fill-color: red; text-mode: normal;");
ONode oNode = graph.getNode(Long.parseLong(currentNode.getLabel()));
System.out.println(oNode.toString());
}
if(focusedNode!= null)
focusedNode.setAttribute("ui.style", "fill-color: black;size: 10px, 10px; text-mode: hidden;");
focusedNode = currentNode;
}
}
I've tried to check what methods from the base class DefaultMouseManager are called after my mouseClicked is called so I could override them too, but there was to many of them to follow.
Is there an elegant way to make sure my changes will execute after all other method from the base class?
Is there an elegant way to make sure my changes will execute after all other method from the base class?
Read the documentation and look at the code in DefaultMouseManager. I googled DefaultMouseManager, looked at the documentation, went through the inheritance of the different interfaces until I got to MouseListener, which describes the order of operations. Then I looked at mouseClicked and mouseReleased since they would be called last, mouseClicked is empty so that leaves mouseReleased and the methods that are called in it.
So, something similar to this question has happened, the mouseClicked() method was called twice.
In my code, I repaint black the previous node and hide its label after a new node is clicked. And for that reason, when the mouseClicked() method was called twice then the first call changed the node`s appearance and the second one changed it back.
In that case, an easy fix will be to check if the previous node and current node are the same. replace this if(focusedNode!= null) with this
if(focusedNode!= null && focusedNode != currentNode)
but a more straightforward solution will be to understand why the method is been called twice.
My guess is that it has something to do with the inheritance but I'm not sure.
public void move()
{
//if (this.getWorld().getObjects(Marker.class).isEmpty())
Dog bill = getOneIntersectingObject(Dog.class);
Marker bone = getOneIntersectingObject(Dog.class);
if (bone == null);
{
Marker bone= new Marker();
getWorld().addObject(marker.getX(), marker.getY());
}
super.move(1);
}
I'm trying to reference the location of my current actor subclass (dog) in order to place a marker(bone) of another subclass at the coordinates it is located at.
You can retrieve the coordinates of the actor by calling getX() and getY(), as you do it for other actors.
If you like to call methods for the "current" actor, you might like to use this, in example this.getX(). But it is only necessary, if you need to resolve some ambiguity. Commonly you can just call the method.
public void move()
{
Dog bill = getOneIntersectingObject(Dog.class);
Marker bone = getOneIntersectingObject(Marker.class);
if (bone == null)
{
Marker marker = new Marker();
getWorld().addObject(marker, getX(), getY());
}
super.move(1);
}
Changes necessary as obvious from the shown excerpt:
The parameter of the second getOneIntersectingObject() is Marker.class, because you seem to want this.
No semicolon after the parenthesis of the if. If you don't remove it: This semicolon is an empty statement, so the if will have no effect. The block between the braces following it will always be executed.
Rename the second bone as marker to show your intention. (It would "shadow" the "outer" bone, additionally, but this is no problem here.)
Call addObject() with the right parameters: the object to place (the new marker), and its coordinates (retrieved by calling getX() and getY()).
In general, my goal is to draw lines defined by the user's cursor. To accomplish this, I am figuring out the calculations for those lines in one class, and then updating the class that paints the lines with those new values. Overall I want to access a list of line segments, a list of nodes, and the current abstract "node" that the cursor is located at. (Nodes and Line Segments are my own defined classes). The class in which the lines are drawn is called GraphicsPanel.
I set up access between the classes as follows:
public class MainClass extends JFrame {
protected static ArrayList<LineSegment> lineList = new ArrayList<LineSegment>();
protected static ArrayList<Node> nodeList = new ArrayList<Node>();
protected static Node current = new Node();
// Code for calculations and user interactions
{
GraphicsPanel displayPanel = new GraphicsPanel();
// Values are updated
displayPanel.revalidate();
displayPanel.repaint();
}
}
public class GraphicsPanel extends JPanel {
private ArrayList<LineSegment> lineList = package.MainClass. lineList;
private ArrayList<Node> nodeList = package.MainClass.nodeList;
private Node current = package.MainClass.current;
public GraphicsPanel() {
}
public void paint(Graphics g) {
// Paint lines and other shapes
}
}
While the lineList and nodeList objects get correctly updated when a new LineSegment or Node is added to the list, the current Node is never updated and always shows the default of (0, 0).
As an example, within the main class, I have two mouse listeners, one for mouse clicks and one for mouse movement. They have similar functions, but the mouse click listener updates both the current Node and the lineList ArrayList of LineSegments.
displayPanel.addMouseListener(new MouseListener() {
#Override
public void mousePressed(MouseEvent e) {
Point p = e.getPoint();
current = new Node(p.getX(), p.getY());
lineList.add(new LineSegment(current, current);
// Don't worry, the line segment gets updated (correctly) with a new end node as
// the cursor moves around the window
displayPanel.revalidate();
displayPanel.repaint();
}
});
When I click on the window to create lines, the lines show up as expected but the current Node remains at (0, 0). I am completely flabbergasted by this, since it seems like only one of the variables is updating, even though both are written to update in basically the same way: I modify the instance of the class variable in the main class, which should modify the instance of the variable in the GraphicsPanel class.
I appreciate any help with this conundrum and welcome suggestions for what's wrong, as well as better ways to approach this application.
You don't modify the instance, you create a new instance, replacing the old. This means that GraphicsPanel.current will keep pointing to the original instance, but MainClass.current will point to a new distance.
If you did something like instance.setY(p.getY()), it would modify the single original instance that both classes are pointing to.
Your MouseListener adds objects to the Main class list.
Then it assigns a different new object to the panel reference current. But that doesn't change the Main class refence!
You could just not have another current reference in the panel code. Simply directly assign to the current instance that belongs to the Main class!
In my game, i want to be able to collect coins. I have an arrayList of sprites of that coin so that I can draw multiple coins spaced out individually. These coins also move with the background (to emulate a car driving) and i want it so when the coin hits the car, it disappears and is collected.
Thank you for helping.
You can use getBoundingRectangle() method of Sprite and check is there and collision with other rectangle and if yes you can remove that coin from coinList.
ArrayList<Sprite> coinList;
Sprite car;
#Override
public void create() {
coinList=new ArrayList<>();
car=new Sprite();
coinList.add(new Sprite());
}
#Override
public void render() {
//Gdx.gl....
spriteBatch.begin();
for (Sprite coin:coinList)
coin.draw(spriteBatch);
spriteBatch.end();
for(Sprite coin:coinList)
if(car.getBoundingRectangle().overlaps(coin.getBoundingRectangle())) {
coinList.remove(coin);
break;
}
}
EDIT
You can use Iterator to prevent ConcurrentModificationException
for (Iterator<Sprite> iterator = coinList.iterator(); iterator.hasNext();) {
Sprite coin = iterator.next();
if (car.getBoundingRectangle().overlaps(coin.getBoundingRectangle())) {
// Remove the current element from the iterator and the list.
iterator.remove();
}
}
You can use Array instead of ArrayList, there are bunch classes inside libGDX that are optimised to avoid garbage collection as much as possible also having many benefits.
You should always try to use libGDX classes whenever you can.
I've tried a lot of things but I still cannot figure it out. I have a List that contains "entities". I'm going trought all of these and rendering them. This works perfectly fine. The problem is that when I remove one object (entity) in this List from different thread. In this case the square (entity) won't disappear until I resize the window.
private List<Entity> entities = new ArrayList<Entity>();
public void render(Graphics g, ImageObserver obs) { //This function is called from my game loop (few hundred times per second..)
for (int i = 0; i < entities.size(); i++) {
entities.get(i).render(); //Calling the render function in the entity class
}
}
public void removeEntity(int index) { //This function is called from different thread
entities.remove(index); //Removing entity from the list
}
Your render() function is not being called. You need to call repaint() to do this. This will call render() and update the JFrame. Resizing the window repaints the window automatically, which is why it worked only after you resized it.