Trying to reduce the sensitivity of panning by setting the tap square size, but even setting huge numbers just as in the example below seems to have no effect. On a high-res, small screen phone it is almost impossible to touch something without the panning mode kicking in.
What is the right way to do this? The code below doesn't seem to do anything about it.
public class CustomCameraInputController extends CameraInputController {
public CustomCameraInputController(Camera camera) {
super(camera);
this.setTapSquareSize(Gdx.graphics.getWidth() / 5);
}
}
for translation also panning, Use CameraInputController.translateUnits = float value;, note there are other two factors that you can use for scrolling and zooming as multiplier,
CameraInputController.pinchZoomFactor
CameraInputController.scrollFactor
OK, by debugging LibGdx I found out that the tapSquareSize works differently than I expected. It merely sets a flag but still calls process() on finger moves still inside the tap square.
If you want panning/rotation to kick in only when the user leaves the tap square, you need to redefine the process() method and transform the camera only when isPanning() is true.
Related
I have an overlay in my game that consists of an image of a screen, and a set of buttons that are "on" the screen.
Screenshot:
My Screen has one Stage. The Stage has a set of Group objects, which I think of as layers. The first group has the backgrounds, the groups in the middle has the game elements, and the frontmost group has the screen overlay.
The overlay layer consists of one Image, the screen itself, and four TextButton (one in each corner).
This would work great, if it weren't for the fact that I can't click on anything in the game layer as long as the image in the overlay layer is in front of it. Even if the image is transparent, it still interecepts all touch events before they reach the game layer.
So my questions is: How can I make the image in the overlay layer ignore all touch events, so that the game layer will get them and one can actually play the game?
I tried one idea myself, but I'm not sure this is the right way to do it:
I tried creating the image as a custom Actor that always had height/width set to 0, but still (by overloading the draw() method) drew the image on the entire screen. This works very well, except for the fact that the image for some reason gets drawn behind elements in lower layers.
Screenshot: https://dl.dropboxusercontent.com/u/1545094/Screen2.png
In this screenshot, I have opened a instruction messagebox, which adds itself to one of the game layers (group 6).
Note that all the buttons in the overlay layer (which is group 7) is in front of the messagebox, but the screen frame (which is a custom Actor) somehow gets drawn behind the messagebox. Why is that?
Note: If I take this exact same case, and change my custom actor into a regular Image, everything is drawn correctly, but then I can't click anything in the lower layers anymore, as described above.
This is my custom actor, if anybody can make any sense of it:
public class ClickThroughImage extends Actor {
BaseDrawable d;
public NonexistingImage(BaseDrawable d){
this.d = d;
setSize(0, 0);
}
#Override
public void draw(SpriteBatch batch, float parentAlpha) {
d.draw(batch, 0, 0, 1024, 768); //Yes, I tried swapping these two lines.
super.draw(batch, parentAlpha); //It had no effect.
}
}
In addition to the other methods note you can also call:
setTouchable(Touchable.disabled);
Which is documented as:
No touch input events will be received by the actor or any children.
Method is n the Actor class.
Use an InputMultiplexer. The InputMultiplexer class allows you to share user input among multiple input processors. Create your own class extending InputProcessor, and put that in InputMultiplexer with your Stage. That way you can respond to user input in a custom way, and still be able to use your stage.
InputMultiplexer multiplexer = new InputMultiplexer();
Array<InputProcessor> processors = new Array<InputProcessor>();
MyInputProcessor myInputProcessor = new MyInputProcessor();
processors.add(myInputProcessor);
processors.add(stage);
this.multiplex.setProcessors(processors);
//...
//and in your show method in your Screen class
Gdx.input.setInputProcessor(this.multiplex);
Also, be sure to return null from Actor.hit. This should cause the actor to not respond to any user interaction.
This is how I solved this problem in my game.
Yes, Pool is right.
Just set touchable to disabled.
It is questionable, whether it is a "good" default of the engine to make all actors touchable in a stage, because in most of my games the majority of actors is _not_ touchable, and there are only few elements the user can/shall interact with. Therefore I always create a base class of "nonTouchableActor" where I derive all my Actors from that shall not react on clicks/taps and this base class sets touchable(disabled) in the constructor. That way you no longer have to think about it.
For those of you who have played Madness Interactive, one of the most frustrating things is when the cursor leaves the game area, and you accidentally click. This causes the game to defocus and your character dies in a matter of seconds. To fix this, I'd like to make a java application that I can run in the background that will hold the cursor inside the screen until I press a key, like ESC or something.
I see two ways of implementing this, but I don't know if either of them are workable.
Make an AWT frame that matches the size of Madness Interactive's render area, and control the cursor using that.
Use some out-of-context operating system calls to keep the cursor in a given area.
Advantage of approach #1: Much easier to implement resizing of the frame so that user can see the shape and position of the enclosed area.
Potential Problems with approach #1: The AWT Frame would likely need to steal focus from the browser window the game is running in, making the whole solution pointless.
My question is, are either of these approaches viable? If not, is there a viable option?
EDIT: I am willing to use another programming language if necessary.
EDIT2: I might develop a browser plugin for this, but I've never done that kind of development before. I'll research it.
If you're still interested in working in Java, here's a possible solution for you.
First, in order to limit the cursor within an area, you could use the Java Robot class.
mouseMove(int x, int y);
Then, you could use AWT's MouseInfo to get the position of the mouse cursor.
PointerInfo mouseInfo = MouseInfo.getPointerInfo();
Point point = mouseInfo.getLocation();
int x = (int) point.getX();
int y = (int) point.getY();
Then, whenever the x and y value of the mouse cursor go beyond a certain point, move them back using the Java Robot class.
If this is for a browser-based game, consider writing a greasemonkey script, which acts as a browser extension that can be filtered to only run on the game's site.
In the simplest case, assume the clickable regions are (0,0) - (300,400), then you can add the following event handler to the page:
$(document).on('click', function(event) {
if (event.pageX > 300 || event.pageY > 400) {
return false;
}
});
You can further refine your script to do the following:
resize the browser to be the perfect size for playing the game
instead of checking the absolute x,y coords of the click, check if it is inside an element of the page that you don't want to receive the click
add custom key bindings to umm.. help you at the game
write a javascript bot that can play the game itself
Background:
I am making a 2D side-scroller.
When the player touches the screen, the player moves forward (the camera follows the player).
I cannot find an answer to this question although it seems rather straightforward.
Question:
How can I get my parallax background to scroll only when my player moves?
(example code would make things much easier for me)
I am using autoparallaxbackground but it seems that it simply just scrolls at the rates you pass in, with no regard to the camera. Moreover, I am not fully sure of the difference between autoparallaxbackground and parallaxbackground.
Any help is appreciated!
AutoParallaxBackground extends ParallaxBackground, adding one simple feature: automatically changing mParallaxValue with time. As you may imagine, if you don't need your background constantly moving, you may use ParallaxBackground as your base class, and then use setParallaxValue(final float pParallaxValue) to manually adjust the position.
I'm working on an Android application that requires 2D graphical view with a large set of objects. Here's what I basically need to display:
In my case, there could be hundreds of spatially distributed objects. This view is going to behave like a map, so the user is able to scroll in horizontally and vertically, zoom in and zoom out. It also requires click event handling, so the user is able to click any triangle and I then should display some extended information related with that particular triangle.
I'm mostly concerned about 3 things:
In case I re-draw all the objects per in my onDraw() handler, that would be really slow. Also, there I cases when I don't even need to draw all these objects since some of them are invisible depending on zoom level and scroll position. These requires using quad trees which I don't want to implement manually.
All these objects are defined as (x,y,rotation,type), so in case customer decides that we need a "show all" button, I'll have to implement a functionality to calculate bounding boxes.
I need to be able to handle click events and (probably) dragging for all these shapes.
Is there any library that can help me with these tasks? Just don't want to spend 3 days on stuff that I believe must already have been implemented.
All the methods in the Canvas class of the android.graphics package should suffice. The Canvas does clipping (meaning drawing commands get discarded if it's not visible) so if the image is static you could render it into a Picture and draw that on onDraw().
I think the drawing methods have methods to calculate bounds and return them. See Path's computeBounds(RectF bounds, boolean exact).
I'm in the process of developing a 2-D game for android which primarily i'm using as an experience to learn the in's and out's of programming for android apps, so naturally i run into a lot of puzzles to work through. Currently, my main activity instantiates a custom class which extends SurfaceView and implements SurfaceHolder.Callback. This view instantiates a thread which handles most of the logic and all the graphics processing (this includes instantiating a canvas and drawing to it., etc.
Well, being that I am a beginner I wasn't thinking when I started that designing the canvas to be much larger than the screen and to allow users to scroll around to see all parts of the canvas... but alas, that's what I need to happen.
If there is an easy way to do this, please let me know.
My best guess is putting the actual creation of the canvas in a separate class which extends ScrollView and somehow just calling all the Draw()'s to that canvas from my thread. is this possible? my click events are actually captured from the main activity (just fyi).
The best option would be to use a Camera to translate the canvas. Do something like this:
// Creates a new camera object
Camera mCam = new Camera();
float startX;
float startY;
#Override
public void onTouch(MotionEvent event)
{
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
startX = event.getX();
startY = event.getY();
}
else if(event.getAction() == MotionEvent.ACTION_MOVE)
{
float x = event.getX();
float y = event.getY();
// Lets you translate the camera by the difference
mCam.translate(x -startX, startY - y, 0.f);
startX = event.getX();
startY = event.getY();
}
}
#Override
public void onDraw(Canvas canvas)
{
// Draw here the objects you want static in the background
canvas.drawBitmap(mBackground, 0, 0, null);
canvas.save();
mCam.applyToCanvas();
// Draw here the objects you want to move
canvas.drawBitmap(mBall, 0, 0, null);
canvas.restore();
// Draw here the objects you want static on the forebround
canvas.drawBitmap(mScore, 0, 0, null);
}
Notice that you are drawing mBall at 0,0 but due to the camera translation it will move by the amount specified. I hope this helps. Have fun :)
I slept on the problem and came up with (if i don't say so myself) A brilliant, relatively simple and elegant solution. Sorry to toot my own horn but I was literally ecstatic that i was able to come up with this.
If anyone is thinking of using this method there are a couple of conditions that made this a good choice. First, all of my objects are drawables with predefined locations using the setBounds(int,int,int,int) method, all objects also store their own coordinates for the location to draw on the canvas and all objects are called in hashmaps which allows me to call and process all the objects in existence.
Now I was thinking about what kabuko said and how it's such a waste to draw a huge canvas and how id run into click event problems, that's when I came up with this.
when a screen touch event occurs near the edge of the screen, a custom method Scroll() is called which loops through every object and adjusts the stored coordinates of the object location depending on which direction the user is trying to scroll. after it increments the objects location, it (in parallel) increments a pair of variables for x and y offset. This offset is then factored into the coordinates of the touch events so that objects can still be selected by touch regardless of the position the screen is scrolled to.
then for performance's sake a simple if statement makes it so that draw is only called on an object if that objects coordinates fall in the range of the screen.
Sorry to gloat but I really surprised and impressed myself with this, haha. I've really only been coding about a month and I almost have a fully functional 2D strategy game!
Java for dummies paid off, lol.
You could give your approach a try, even though it's not really a strategy I'd ever use myself. I suspect you're going to run into some issues with that approach anyway though. If your game already uses touch for input, you're going to have conflicts. Also, if performance is at all a concern (especially if you have any animation), you don't want go with this approach.
If you're going as far as dealing with threading, performance probably matters. Drawing is expensive, and if you make a huge canvas, you'll have to be rendering the whole thing and it will cost you. You should only draw what's on the screen (more or less). Sorry, but you'll probably need a "major overhaul"...
That said, it's really not that bad to deal with scrolling. You probably have coordinates for everything you're drawing. All you need to do is keep track of your "current coordinates" and then translate your drawing x and y by your current x and y. Dealing with the performance stuff, there's a lot you can do, but that's starting to get a bit off-topic. Take a look at these videos if you want to know more:
http://www.youtube.com/watch?v=U4Bk5rmIpic
http://www.youtube.com/watch?v=7-62tRHLcHk
The simple trick with side-scrolling games is to divide your world into tiles, where each tile has a specified amount of area.
Displaying a Tile Based Map
Scrolling a Tile Based Map