I'm currently working on my first Android game project using LibGdx. It is a 2D maze game where you use touch input to "draw" a line from one of the entrances to one of the exits. The world itself is a TiledMap, which act only as a visual backround at the moment.
The problem I have is the whole system of collision detection. There are (obliviously) walls in the maze, located on the edges of my background tiles. So when I slide my finger across a wall, the "player line" should stop at the wall. Additionally, events should be triggered when the line reaches an exit.
I could not find a way to properly implement these functionalities using the built-in libraries (I tried using Scene2D and Box2D). Stopping an actor's movement and firing an event is not that exotic, or?
All I need is some information on what I should use and maybe some first steps. :)
Thanks in advance!
Collision detection is probably the most difficult part of making a tiled game. Libgdx has a lot of useful methods to help you get the geometry but the actual collision handling after a collision is detected (called collision resolution) is a large topic. I suspect all you want is the player to stop. More advanced realistic solutions such as bouncing and friction are what Box2D specializes in.
First and foremost, getting the geometry that's going to collide.
a) The player can be represented by a rectangle. Have it extend the Sprite class and then you can use the getBoundingRectangle() function (A rectangle keeps things simple, but there are many other shapes that get used for collisions ).
b) Getting the geometry of the tiles, also a bunch of rectangles.
A function that gets the surrounding tiles.
public void getsurroundingTiles(int startX, int startY, int endX, int endY, Array<Rectangle> surroundingTiles){
TiledMapTileLayer layer = (TiledMapTileLayer) worldRef.getCurrentMap().getLayers().get("Terrain");
surroundingTiles.clear();
for (int y = startY; y <= endY; y++) {
for (int x = startX; x <= endX; x++) {
Cell cell = layer.getCell(x, y);
if (cell != null && cell.getTile().getProperties().containsKey("blocked")) {
Rectangle rect = new Rectangle();
rect.set(x, y, 1, 1);
surroundingTiles.add(rect);
}
}
}
}
}
This function gets the tiled map tile layer made in the Tiled program and fills up a Rectangle ArrayList with the rectangles only if the tile has the key "blocked".
So now you have rectangles representing your player, and representing all the
colliding blocks. You can draw them with a ShapeRenderer object.
This is what it looks like in a game I am working on.
Lastly, actually resolving the collisions is a larger topic. This is a great starting point.
http://www.metanetsoftware.com/technique/tutorialA.html
Related
I just started experimenting libgdx and understanding... I looked sample projects... My problem :
The 1 and 6 originial ball number. And other balls, the ball's(1 and 6) will go randomly other places. (speed 1). ex . If a i am torch on the any ball, its speed up to 3...
The GameObjects should be in while loop. Ball images sometimes (randomly), the balls should be retun own 360 degrees. And get picture on TectureRegion.
Is there a similar example ? or
How can I do this ?
(Sorry for bad english)
Thanks...
As much as i understood you want your ball objects to move arround until you quit the game. Also you want to speed them up on touch right? Also you want to texture them and maybe they should detect collision with the screen borders and other balls to?
Libgdx has a main loop. This loop calls render(delta) every renderloop. The delta depends on the time ellapsed since last call of render. So on fast devices this delta is smaller then on slow devices (most times). This time is given in seconds. To move your objects you can add a value to their position in every render loop. In your case you want to add 1 (hopefully not pixel, as it then would seem slower on big screens):
for(BallObject ball : ballObjects) {
ball.setPositionX(ball.getPositionX() + ball.getSpeed() * delta * direction.x);
ball.setPositionY(ball.getPositionY() + ball.getSpeed() * delta * direction.y);
}
In this case a BallObject has a positionX and positionY describing his current position, a direction.x and direction.y, describing his movement in x and y direction (for 45° it would be direction.x=0.5 and direction.y=0.5), as well as a speed describing movement per second. This speed will be set to 3 on touch.
To speed the ball up on touch, you first need to implement InputProcessor in the class, which manages the movement of all ballobjects. Next you have to set it as the InputProcessor of the game: Gdx.input.setInputProcessor(this);. The InputProcessor has a method touchDown(int x, int y) or something like that. The x and y value are giving the coordinates in pixels, on the screen.
If you are using a camera or viewport in the new Libgdx version (you should do that) you have to use camera.unproject(x,y) or the viewport version of that (idk the exact method name). This method gives you the touchposition in your world coordinate system. Then you can simply check which ball is on this touchpos and set its speed to 3.
To texture the ball you have to use SpriteBatch for drawing. Look at the different draw() methods in the API and use the one which fits best for you. Just load a Texture, which should be a ".png" with a circle texture and the rest of it should be transparent (alpha = 0). With blending enabled (default) it will then only render the ball, even if it is actually a rectangle shaped Texture.
I hope it helps
Im doing a game and I'm using SurfaceView. In the game I have 25 small dots that are moving around. The goal is to make a game where the player draw a circle around some of the dots with the same color. My problem is that while I draw this circle and after I have lift my finger from the screen, all the dots are moving very, very slow! I guess the reason for this is all the line segmets that are being drawn constantly together with all the dots.
Is it possible to have the same moving speed of the dots all the time? I tested with SystemClock.Sleep(1) but it didn't helped much.
// Method to draw objects
private void drawObjects(Canvas canvas) {
SystemClock.sleep(1);
synchronized (this) {
// Clear screen with black color
canvas.drawRGB(0, 0, 0);
// Draw line
if(startDrawLine) {
// Set properties to Paint object
paint.setColor(Color.WHITE);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
// Draw path
path.moveTo(touchDownX, touchDownY);
for(Point point: points) {
path.lineTo(point.x, point.y);
canvas.drawPath(path, paint);
}
path.reset();
}
}
// Call method draw() in CircleManager to draw all circles in list
circleManager.drawCirclesInList(canvas);
}
Slow drawing is caused by to many points in your path.
If you are handling Touch event, you can expect hundreds and thousands of touches (your points) in short period of time.
You need to interpolate your points somehow - take averages, ignore same and close points or something else.
When you animate the "dots" your ANIMATION MUST BE BASED ON TIME, and not on the actual speed of the drawing on hardware.
To base your animation on time, you should calculate time passed since previous frame and use this time in function which calculates new position of the dot.
Here is a great article on the subject:
http://www.koonsolo.com/news/dewitters-gameloop/
EDIT - Response to a comment:
Suppose that your "dot" (I will call it a ball) needs to move horizontally (by X) from left to right at a constant speed of 100 units per second.
If you are doing your calculation WITH ASSUMPTION that your game will be running at 25 FPS, you simply add 4 to X on each frame.
The problem with this approach is that getting constant FPS is very hard to achieve.
On the fast hardware you will be sacrificing smoothness by limiting FPS,
on slow hardware you will be forced to skip drawing (drop) some frames (which can be jumpy with constant FPS).
Timer in Android is not very precise and also thread sleep functions are inaccurate.
In your case, instead of trying to force the constant FPS or calculate current FPS, try to wrap your head around and rethink of your problem
in a context of time.
When you think about time, it does not matter how fast is the game
running (how many FPS) and what happened before.
You just need to ask a question "Where the ball should be in this
moment, right now?"
If you, for example, know that ball movement stared at origin position X0 at origin time T0 then at the current moment TC ball position should be X = (TC - T0) * 100
Second approach is to measure time passed TD since last ball position update. Then the ball position should be updated like this: X = X + TD * 100
Once you get used to this approach, you will see that vast majority of animations is really trivial to implement with a great level of accuracy.
i am working on isometric tiled map game.here in introduction i want to show complete game field .so i used
this.mCamera = new ZoomCamera(CAMERA_WIDTH, CAMERA_HEIGHT, CAMERA_WIDTH, CAMERA_HEIGHT) {
#Override
public void onApplySceneBackgroundMatrix(final GLState pGLState) {
final float widthRaw = this.getWidthRaw();
final float heightRaw = this.getHeightRaw();
pGLState.orthoProjectionGLMatrixf(0, widthRaw, heightRaw, 0, getZNear(), getZFar());
}
#Override
public void onUpdate(float pSecondsElapsed) {
if (timeCounter >= 1) {
mCamera.setRotation(i);
timeCounter = 0;
i=i+1;
}
timeCounter += pSecondsElapsed;
super.onUpdate(pSecondsElapsed);
}
};
but its rotating 2d view .i want to rotate in 3d perspective .how can i rotate camera in 3d perspective in andenigne GLES2.0.
please suggest me
You cannot rotate your camera in 3D. The appearance of 3D is caused by the fact that the artwork is drawn in perspective. Rotating the artwork does not cause the artwork to change the way its drawn any more than rotating a piece of paper with a drawing on it would cause a 3D transformation. To rotate in 3D you need to be using a 3D engine.
Several times I stumbled upon this tutorial in the AndEngine Forum, where it states that it is possible to rotate the Camera in a way to show distant objects further away (smaller). It is made for the AndEngine GLES1 but it should be possible to adapt it to GLES2.
AndEngine knows a z-axis. The position on that axis is set automatically based on the order in which you attach the Sprites to the Scene. However, you should set it manually. In most cases it will be sufficient to set the z-axis according to the y-position (z-axis = y-axis) every time a Sprite changes its position.
public class YourSprite extends Sprite{
...
#Override
setPosition(float x, float y){
super.setPosition(x,y);
this.setZIndex(y);
}
}
If you then manage to implement the camera rotation as described in the tutorial, together with the z-axis you should have a pretty realistic 3D effect.
However, I never tried that tutorial, because most games that use the Bird's-eye view (as the game from the youtube link you provided) don't need a real vanishing point, since the display is most likely so small, so the player wouldn't notice anyway. So I stick to changing the position on the z-axis. But I would certainly like to know more if anyone manages to rotate the camera!
I am experimenting with 2D graphics in Android during my off time, and I'm intrigued by the idea of creating a sprite based "sandbox" for playing around. I've looked around online and found some good tutorials, but I'm stuck with a fairly basic problem: My sprite moves faster than the terrain and "glides" over it. Also, he slowly outpaces the terrain scrolling and moves to the edge of the view.
I've got an animated sprite that I want to move around the world. I do so by changing his absolute coordinates(setting X and Y position in an 'update()' function and applying a scalar multiple to speed up or slow down the rate at which he's moving around.
this.setXPos(currX + (speed * dx2));
this.setYPos(currY + (speed * dy2));
Underneath that sprite, I'm drawing "terrain" from a bitmap. I want to continue to move that sprite around via the coordinate accessors above, but also move my view and scroll the terrain so that the sprite stays in the same relative screen location but moves through the "world". I have an imperfect implementation where player is my sprite and field is my terrain:
#Override
protected void onDraw(Canvas canvas)
{
player.updateLocation(GameValues.speedScale);
field.update(new Point(player.getXPos(), player.getYPos()));
field.draw(canvas);
player.draw(canvas);
//more stuff here...
}
And field.update() looks like(Warning: Hard-coded scariness):
public void update(Point pt)
{
sourceRect.left = pt.x - 240;
sourceRect.right = pt.x + 240;
sourceRect.top = pt.y - 400;
sourceRect.bottom = pt.y + 400;
}
The thinking there was that I would eventually just get screen dimensions and make it less 'hack-y', but get something together quickly. This could easily be where my issue is coming from. Of immediate interest is field.draw():
#Override
public void draw(Canvas canvas)
{
try
{
canvas.drawBitmap(fieldSheet, sourceRect, destRect, null);
}
catch(Exception e)
{
//Handle Exception...
}
}
You'll notice I'm using the overload of drawBitmap() that accepts a source and destination Rect and that the field.update() method moves that sourceRect to match the movement of the sprite. How can I keep the "camera (so to speak)" centered on the sprite and scroll the terrain appropriately? I had thought that moving just the sourceRect and maintaining a constant destRect would do so, but now I'm thinking I have to move the destRect around the "world" with the sprite, while maintaining the same dimensions.
Is there a better (read functional) way of making this work? I'm coming here somewhat shamefully, since I think this should be somewhat easier than it seems to be for me. Any and all help or suggestions are appreciated. Thanks!
*Edit:*Does it make sense to also move the destination Rect at the same speed as the sprite? I think I conflated the source and destination Rect's and left the destRect immobile. I'll update with the results after I get a chance to try it (maybe during lunch).
*Edit_2:*Changing the destination rectangle didn't get me there, but using the View.scrollBy(x, y) method gets me close to totally satisfied. The remaining question to be satisfied is how to "clip" the View scrolling to a rectangle that represents the "field". I believe that the View.getLeft() and View.getTop() functions, offset by the screen width and height, can be used to specify a Rect that can be virtually moved around within the constraints of the "world" and block further deltas from being argued to the View.scrollBy() method. The reason I look toward this approach is because the View doesn't seem to be positioned in absolute space, and a View.getLeft() call, even after a View.scrollBy(x, y) where x > 0, returns a 0.
I'm developing a Android board game and have a question regarding creating a board that is zoomable and scrollable. The board contains a static background, characters (players) and the actual "level" which is drawn using tiles.
My solutions is to have a collection of elements (tiles, figures, all game elements - all have x,y coordinates and width + height), a camera and a renderer that draws the collection according to cameraX,cameraY, cameraWidth and cameraHeight. So if a user would scroll to the right, the camera would just set the cameraX appropriately - and the surface is scrollable. And if a user would zoom in/out the renderer would just scale every element image appropriately.
Example code for the renderer with scrollable surface and zoom in/out
protected function draw(Canvas c){
Collection elements = collection.getElements(cameraX,cameraY,cameraWidth,cameraHeight);
if(elements.size() > 0) {
for(int i = 0; i < elements.size(); i++) {
elements.get(i).drawElement(c);
}
}
}
.
.
.
// element class drawElement function
protected drawElement function(Canvas c) {
if(this.image != null) {
int w = this.width;
int h = this.height;
if(this.zoomFactor < 1) {
w*=this.zoomFactor;
h*=this.zoomFactor;
}
c.drawBitmap(this.image,this.x,this.y,w,h);
}
}
Is this the best solutions?
Could it be achived somehow else?
Could scrolling be achived using a ScrollView?
I dont wanna use any engine, because this is for a school project.
Actually you can simplify this situation somewhat. If you are indeed seeking a flat texture plane that is simply distorted by perspective, the Android Camera class can help you. Do not confuse this with the hardware camera for taking photos. This camera is a helper class wrapped around a matrix to perform transformations on 2D objects. You can read more about this very complex rendering topic by googling "fast fourier transforms". Basically you will want to create a canvas and do your drawing in a completely 2D way. Then right before you draw to the screen, you should transform this canvas using the Camera class. Let me know if you need some clarification. There is a lot of cool mathematics going on behind the scenes!
Take a look at this sample from the Android API Demos
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/animation/Rotate3dAnimation.html
Android graphics.Camera documentation
http://developer.android.com/reference/android/graphics/Camera.html