I am trying to check collisions between two arrays, one of moving rectangles and the other of stationery boundaries (trying to get the rectangles to bounce off the walls).
The problem is that I wrote a nested for loop that seems to work for 2 out of 4 boundaries. Is my loop not reaching all possible combinations?
Here is my loop:
for(int n=0;n<_f;n++){
for(int m=0;m<_b;m++){
if(farr[n].inter(barr[m]))
farr[n].setD();
}
}
_f counts the moving rectangles (starts at 0 and increases after each one is added) and _b counts the boundaries. The inter() is a method I am using to detect collisions and it has worked in all other parts of my program.
Any help would be greatly appreciated,
Thanks in advace!!!
public boolean inter(Rect rect){
if(Rect.intersects(rect, rec))
return true;
else
return false;
}
The setD() method:
public void setD(){
if(_d==0)
_d=2;
if(_d==1)
_d=3;
if(_d==2)
_d=0;
if(_d==3)
_d=1;
}
The move method where _d is used:
public void moveF(){
if(_d==0){_l+=_s;_r+=_s;}
if(_d==1){_t+=_s;_b+=_s;}
if(_d==2){_l-=_s;_r-=_s;}
if(_d==3){_t-=_s;_b-=_s;}
}
_l is left side, _t is top, _r is right, and _b is bottom, and _s is how many pixels it moves per iteration(set to 1 in all cases)
Assuming _f, _b, farr, and barr do not change during the execution of the loop, your loop checks all combinations exactly once. So how is it that you "check some collisions twice"? Does setD() do something sneaky? Do you mean that once a rectangle collides there is no need to check more boundaries? If so, that can be fixed with a simple break statement. Otherwise, there likely is a problem with your inter() method, independent as to whether or not it appears to work elsewhere. Can you post your inter implementation?
There is a possibility of another problem, that of assuming continuous properties in a discrete space. As my amazing ascii art (titled: ball and wall) skills demonstrate...
Frame 1:
o__|_
Frame 2:
_o_|_
Frame 3:
__o|_
Frame 4:
___|o
Notice that the ball passed through the wall! In no frame did the ball intersect the wall. This happens if your distance moved per frame can be roughly the same or larger than the characteristic size of your moving object. This is difficult to check for with a simple intersection check. You actually need to check the path that the ball occupied between frames.
If your rectangles and barriers are oriented without rotation, this is still a fairly easy check. Use the bounding rectangle of the moving rectangle between the two frames and intersect that with the barriers.
Other ideas:
You are double colliding, switching the direction twice.
Your rectangles are in two different coordinate spaces.
Some other thread is screwing with your rects.
But basically, your code looks good. How many rectangles do you have? Can you make them distinct colors? Then, in your loop, when you collide, call setD and output the color of the rectangle that collided, and where it was. Then, when you notice a problem, kill the code and look at the output. If you see two collisions in a row (causing the rect to switch directions twice), you'll have caught your bug. Outputting the coordinates might also help, on the off chance that you are in two different coordinate spaces.
If it's a threading issue, then it's time to brush up on critical sections.
Found your mistake:
public void setD(){
if(_d==0)
_d=2;
if(_d==1)
_d=3;
if(_d==2)
_d=0;
if(_d==3)
_d=1;
}
Each of these needs to be else if, otherwise you update 0 to become 2 and then 2 to become 0 in the same call.
Related
I'm simply trying to drag a sprite around using my finger. I'm doing this by detecting the distance the finger that is touching the screen has moved by and then moving the sprite by the same amount.
This is an openGL ES 2.0 app, so my rendering and logic updating takes place on my GL Rendering thread, and obviously touch events are captured on the UI thread.
So, my setup is something like this:
UI Thread
case MotionEvent.ACTION_MOVE: {
movedByX = event.getX()-oldXPosition;
movedByY = event.getY()-oldYPosition;
oldXPosition = event.getX();
oldYPosition = event.getY();
break;
}
GL Rendering thread
Rendering
#Override
public void render() {
drawSprite(testSprite); //Draws using the sprites' internal x and y coordinates
}
logic update
#Override
public void updateLogic() {
testSprite.x+=movedByX; //Update the sprite's X position
testSprite.y+=movedByY; //Update the sprite's Y position
}
The issue
If one drags the sprite around the screen for a while, and then stops. The resting point of the finger relative to the sprite is not the same as it was when the finger initially went down. Take for a example a circlar sprite like so. The blue circle is the sprite and the red dot represents the finger/pointer.
So as you can see, it doesn't quite work as expected and I'm not sure why.
I had a similar question in previously in which I 'worked around' the problem by initially grabbing the X and Y in ACTION_MOVE (onTouchEvent/UI Thread) as I am above, but then in my updateLogic method, I make a copy of it and work out the 'moveByY' amount there before applying it to my sprite's position.
Doing this effectively solved the problem of the finger 'wandering' - but - it makes the movement of the sprite very choppy, therefore I can't use this solution.
I think this choppiness may be because the rendering thread sometimes runs twice without the UI thread running, therefore, even though the finger has moved, the logic is still using the version it has because onTouch hasn't been able to capture to actual most up to date finger position. But I'm not 100% sure.
If I simply update my sprite's positionin my UI thread, (again, in ACTION_MOVE) - again, I get very choppy movement but the pointer position does remain correct).
So, I need to keep the smooth movement that I get from the method outlined at the top of the question, but I need to know why the moveBy amount is causing the sprite to wander from the finger.
Other Notes
I need to move the sprite using a the difference between the finger's old and current positions, and not simply draw the sprite at the finger's current position because this will eventually become part of a 'scrollable' menu system.
All of my variables are declared as 'private float volatile' and my onTouchEvent and updateLogic methods are synchronised.
i dont know if its a typo
#Override
public void updateLogic() {
testSprite.x+=movedByX; //Update the sprite's X position
testSprite.x+=movedByY; //Update the sprite's Y position
}
but you set testsprite.x both times
I am using CCTMXTiledMap on cocos2dx-2.2, I created and added the tiled map like this:
// TileMap
CCTMXTiledMap *m_pTileMap = CCTMXTiledMap::create("tilesets/my-isometric-small.tmx");
float fPosX = m_pTileMap->getPositionX();
float fPosY = m_pTileMap->getPositionY();
CCLOG( "TileMapPos: %f, %f", fPosX, fPosY );
this->addChild(m_pTileMap);
The tiled map are created and rendered successfully, but out of position. I use CCTMXTiledMap::getPosition, CCTMXLayer::positionAt, and also examine the CCSprite that I get from CCTMXLayer::tileAt... all of them are returning the correct value based on cocos2d screen coordinate { (0, 0) from bottom left and increasing upward and rightward } However, when viewed on the screen, there is always a slight offset and I can't get where it come from. All the m_obOffsetPosition are confirmed to be zero...
By correct value, I mean the tiles are positioned in the pink area (I getPosition from each of the tile, create CCSprite for each, setPosition of each tile and add it to the screen... They show up in the pink area)
Image supposed to be positioned at shady pink boxes, but instead positioned in the blue area (the entire blue sea is the whole map)
Any ideas are highly appreciated... Thanks!!
After wasting days trying to dissect tilemap_parallax_nodes in cocos2d-x, finally I figured out the culprit... it is the Layer Property cc_vertexz that cause it to be rendered off position. I haven't got the time to figure out how and why it works that way and since I'm not going to use it anyway (I just need flat, single layer, thus no need z order etc), so I just remove that property from all of my Layers and the problem is gone..
Hope it helps someone... Thanks!
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
I am making a learning game for teaching numbers to kindergarten kids. It requires some animation like this but I am failing in achieving this animation smoothly in canvas.
I want exactly the same animation appearing using this dotted line.
Please guide me to perform exactly this type of animation.
What you need is:
a loop
path definition
The loop should update current image position and rotation. Then draw the updated animation on a screen. You can just override dispatchDraw method and call invalidate at the very end of it. You can update position right before drawing. Your case is similar to game programming, so you can look for articles about game loops.
Path definition should allow you to calculate position depending on time. Fo example you can use Bezier curves. Bezier curve equation is parametric and the parameter is 'time'. Using the animation time gives you smooth movement along the path.
Example of a generic game loop: http://www.gameprogblog.com/generic-game-loop/
Bezier curve: http://en.wikipedia.org/wiki/B%C3%A9zier_curve
long time = System.currentTimeMillis();
protected void dispatchDraw(Canvas canvas) {
PointF pos = getBezierPos(System.currentTimeMillis() - time);
drawImage(pos);
invalidate();
}
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.