I am interested in simple game programming with AndEngine. And I would like to do some basic round based strategy stuff. So I would like to have a top down view to some grid. Every square in this chess like grid should be clickable (touchable on android of course). But I can´t imagine drawing lines and squares is the best solution to do so. I would like to have some kind of abstract object list, which I can extend to different behaviours (one click triggers menu to open, on other field a click triggers an explosion, whatever...).
I have been searching for this in several engines over the years now. It is a hobby, but I would like to find a solution for it. Can anyone give me a hint about how this could be done in an elegant way? Double buffering, rendering and stuff isn´t that important. The important thing is, every square should be an object that gets painted.
Anyone? ;)
Regards.
Simplet solution would be something like that (lets say that your screen is 800x480 in portrait mode, and I assume that you have GLES2-AC andEngine branch).
in your onCreateScene() method:
Rectangle rect1 = new Rectangle(80, 133, 160, 266, engine.getVertexBufferObjectManager()){
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY){
if(pSceneTouchEvent.getAction() == TouchEvent.ACTION_DOWN){
//here put what you want to be done after your button was pressed
}
}
Rectangle rect2 = new Rectangle(240, 133, 160, 266, engine.getVertexBufferObjectManager()){
#Override
public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY){
if(pSceneTouchEvent.getAction() == TouchEvent.ACTION_DOWN){
//here put what you want to be done after your button was pressed
}
}
and you continue 7 more times with changing first two numbers in new Rectangle(x, y....) which are coordinates of the center of rectangle(second pair of numbers is the height and wisth of the rectangle). (so bottomrow has coordinates: (80, 133), (240, 133) and (400, 133). Middle row: (80, 399), (240, 399) and (400, 399). Third row you can figure out. Of course it does not give you completely covered screen. This you can achieve by dividing your WIDTH and HEIGHT of the screen by certain numers und use it as a coordinates for rectangles. remember to attach all rectangles to your scene and add
this.setOnSceneTouchListener(getOnSceneTouchListener());
this.setOnSceneTouchListenerBindingOnActionDownEnabled(true);
and register touch area for all rectangles.
More difficult way would be to create class for example MyButton.class that extends rectangle or sprite class that has a methods that will be used when "button" is pressed. It depends on what you really need.
Related
Disclaimer: I am using Java and Javafx 11. Just putting it out there :)
I am in the process of trying to create an Interpreter for Logo, but have run into a roadblock. You see, I defaulted to using a canvas to display all the things I needed as that is fitting for what I am doing. However, I did not account for the fact that my Turtle needed to move.
private void drawTurtle()
{
vertices[0] = new Vector2(position.x, position.y + 15); // The three points that make the triangle that is the turtle
vertices[1] = new Vector2(position.x - 15, position.y);
vertices[2] = new Vector2(position.x + 15, position.y);
vertices[1] = Renderer.rotatePoint(vertices[1], position, rotation); // applying rotation to vertices
vertices[2] = Renderer.rotatePoint(vertices[2], position, rotation);
vertices[0] = Renderer.rotatePoint(vertices[0], position, rotation);
Renderer.drawLine(vertices[2], vertices[1], currentPen); // drawing the vertices
Renderer.drawLine(vertices[2], vertices[0], currentPen);
Renderer.drawLine(vertices[1], vertices[0], currentPen);
}
Trails left due to rotating the turtle in realtime.
In order to achieve this without leaving "trails", I tried to erase the existing turtle by drawing with a white pen over it. That gave me... weird results.
This is after rotating the turtle 360 degrees.
Then I came across a post here on SO talking about how I should use a Line object on a Pane if I wanted to move stuff. And well, I tried combining it with a canvas to make a CanvasPane:
public class CanvasPane extends Pane
{
public final Canvas canvas;
public CanvasPane(double width, double height)
{
setWidth(width);
setHeight(height);
canvas = new Canvas(width, height);
getChildren().add(canvas);
canvas.widthProperty().bind(this.widthProperty()); // Change this so this canvas does not scale with the pane, and its size is constant.
canvas.heightProperty().bind(this.heightProperty());
}
}
And added line objects to this so I can then edit their start and end values to make the turtle move, but I got nothing out of it, no line to show, and I am quite confused and don't know what to do. Nothing on the great internet helped my either, so I am now asking this question to see if anyone has ideas on how I can move my turtle flawlessly. And no, I can't use clearRect()
TLDR: My turtle leaves trails when moving on a canvas, and using Line and Pane doesn't work, and I can't use clearRect() on my canvas. Help!
Use one Pane to hold both the Canvas Node and your "turtle" Node.
Canvas canvas = new Canvas(640, 480);
Shape turtle = new Polygon(); // fill in the points
Pane p = new Pane(canvas, turtle);
Now you can control the position of the turtle node by either setting the layout coordinates or applying a translation. As it was added last, it will be drawn over the Canvas. (You could also use a StackPane to make that layering more explicit.)
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..
My little project involves a diagram editing tool, in which different sized boxes can be linked together. The drawing requirement for this is complex to say the least. You see the idea is that one can zoom in/out as far as they like and create ever smaller/larger boxes. This is sort of like a Mandelbrot, but as a diagram tool. This is shown in the image below.
These boxes have text in them and my overall aim was for this text to be centered in the absolute center of the box. The only simple way I know for text to both center and wrap is by using JLabels. But when I tried this I came across a strange bug. The labels with multiple lines were prone to "disalign" vertically every other time they were repainted. (Sometimes this happened, other times it didn't. It has some consistency in that it keeps its behaviour when I replicate the same movement and positioning). This bug is shown in the image below.
Depending on the position, it would effectively alternate between the two images above. I have isolated the drawing of each box and ensured there was no escaping graphics transformations, and it seems this problem is down to the label painting.
I am aware that the practices I've used may not be preferable (e.g. painting JLabel directly), however I struggle to find any decent alternatives. If you guys can come up with a good alternative to using JLabels for centering and word wrap I'm happy to try it. Any ideas are welcome really.
Below is the drawing code for a Box. The colors are temporary.
public void draw(Graphics2D g, Map map, int fillAlpha, int lineAlpha, double zoom)
{
if(this == map.selectedBox)
{
if(this == map.highlightedBox)
g.setColor(new Color(200,235,235,fillAlpha));
else
g.setColor(new Color(200,225,225,fillAlpha));
}
else
{
if(this == map.highlightedBox)
g.setColor(new Color(235,235,200,fillAlpha));
else
g.setColor(new Color(225,225,200,fillAlpha));
}
g.fill(rect);
if(this == map.selectedBox)
g.setColor(new Color(0,0,255,lineAlpha));
else
g.setColor(new Color(0,0,0,lineAlpha));
g.draw(rect);
g.translate(rect.x, rect.y);
label.setForeground(g.getColor());
label.paint(g);
g.translate(-rect.x, -rect.y);
}
Below is the drawing code for the whole diagram.
public void draw(Graphics2D g, int layer, Color aboveColor)
{
for(Link link : linksObj(layer))
{
g.setColor(Color.black);
link.draw(g, this, aboveColor);
}
AffineTransform at = g.getTransform();
g.scale(getZoom(layer), getZoom(layer));
double ratio = getRatio(layer);
int fill = getAnimAlpha(255, 0, ratio);
int line = getAnimAlpha(255, 32, ratio);
for(Box box : boxesObj(layer))
box.draw(g, this, fill, line, getZoom(layer));
g.setTransform(at);
}
The label uses the following to center the text.
public String convertForLabel(String in)
{
return "<html><div style=\"text-align: center;\">"+in.replaceAll("\n", "<br>")+"</html>";
}
Edit: I have created a test project for you to see the problem yourself. It is only one class so I just uploaded that. You can find it here: JLabel Bug Class
Suppose I have a StateListDrawable. I want to add 2 drawables inside it: the first if it is clicked, second for any other state.
I tried it as following (pseudo-code):
Drawable clickdDrawable = getResourses.getDrawable(R.drawable.presseddrawable);
clickDrawable.setBounds(-100, -100, 100, 100);
Drawable otherStateDrawable = getResources().getDrawable(R.drawable.somedrawable);
otherStateDrawable.setBounds(-50,-50, 50, 50);
StateListDrawable sld = new StateListDrawable();
sld.addState(new int[]{andriod.R.attr.state_pressed, android.R.attr.state_focussed}, clickDrawable);
sld.addState(StateSet.WILDCARD, otherStateDrawable);
sld.setBounds(-50, -50, 50, 50);
now if I'm in state pressed I will get the presseddrawable, but it sticks to the bounds of StateListDrawable. So my question is: How to store Drawables with different bounds inside a StateListDrawable? Is this possible?
You will have to create "custom" Drawables, but before you go that way, let me invite you (and whoever is involved, often a designer) to re-think a bit what you are doing, some years ago I did a heavy work on programmatically drawn extends Drawables (yet it was awesome) just to trash it few months later in favor of simplicity and practicality, I don't see why you can't achieve something like this with a well made 9-patch (a.k.a. n-patch) rather than hardcode dimensions, anyways before you call me grandpa here is a quick answer that could work for ya:
In example say you are using color drawables:
public class FixedBoundsColorDrawable extends ColorDrawable {
private boolean mFixedBoundsSet = false; // default
public FixedBoundsColorDrawable(int color) {
super(color);
}
#Override
public void setBounds(int left, int top, int right, int bottom) {
if (!mFixedBoundsSet) {
mFixedBoundsSet = true;
super.setBounds(left, top, right, bottom);
}
}
}
With red as pressed and blue as wildcard and your values you get on a Nexus 4:
You could also create a wrapper to wrap any drawable and call its methods but I would go that way as there are some final methods that you certainly will need.
Basically, I'm trying to move a JButton (or even a JLabel) inside a frame using the arrow keys.
I've successfully figured out the part to detect the arrow key presses. Now all i want to do is to change the position of the button (or label) depending on the key pressed.
E.G. when I press the "UP" key, the button/label should move up by say 5 pixels. I couldn't find the property to change the position of the button.
Do I need to put button/label inside the panel or something like that?
Please help, its not a homework, just curious :)
How I would do it is to use the Graphics instead of a Panel. So the bit of code that draws it could be:
public class panel extends JPanel{
public int X = 50; //Starting x
public int Y = 50; //Starting y
public panel(){
}
public void paintComponent(Graphics g){
super.paintComponent(g);
this.setBackground(Color.WHITE);
g.drawString("Hello this will be moved", X, Y);//<--- This draws the text
}
}
This bit of code will draw the text and repeatedly draw it. All you have to do is in the Key Listener or what ever was used, do;
X++;
or:
Y++;
That will add 1 everytime. So when you press the key it is moved one x pixel or y pixel or back or forth, depending on the ++ or --. Then add this to the JFrame and it will draw it on screen.
use of a raw image is much better in the application i'm doing but here is something that i accidently found while doing it ;)
This infact can be done by absolute positioning of label(dont know about button) ie. without use of any Layout Manager.
all we have to do is the follwing:
setLayout(null);
Jlabel testLabel = new JLabel("Test Moving label");
now with that done. we have to set
testLabel.setBounds(XCoord+ insets().left, yCoord+ insets().top, 150, 25);
here xCoord and yCoord are the coordinates of the top left pixel of the label. the above line can be added to the actionListener. in my case its the action for pressing UP, RIGHT and LEFT arrow keys.
we can increment and decrement the xCoord and yCoord accordingly.