I have balls class extends ImageView
and on this i have Circle Ball going from left side to right side and in any time speed of Moving increased <
private void render() {
while (true) {
Thread.sleep(30);
if(x > getwidth()){
Step++ && x = 0;
}
x += step
}
}
private void update() {
while (true) {
Thread.sleep(60);
Postinvalidate();
}
}
any thing is Good but when step equals 20 and more < the ball do not movie Rightly and we see it jumping <
I testing the Step = 5 and Thread.sleep(value--) < but did not work Rightly
how can I Move the ball faster and render of onDraw was Rightly
TNX ALL < #};-
Related
I want to delegate animations to a different class/entity so that render method is not bloated with code needed for animations. If the animation going on render method should execute that and move to its normal processing when the animation is done. Animation should except required sprites that involved in the animation. render method should render other sprites in normal way. (I am talking about animations of several sprites not sprite animations off of sprite sheet)
Is there a object oriented way to achieve this?
#Override
public void render ()
{
long ctime = System.currentTimeMillis();
Gdx.gl.glClearColor(backColor.r, backColor.g, backColor.b, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
float deltaTime = Gdx.graphics.getDeltaTime();
if(!startGame)
return;
if(camera != null)
batch.setProjectionMatrix(camera.combined);
batch.begin();
for (int i = 0; i < clusterList.size(); i++) {
clusterList.get(i).render(batch);
batch.end();
if(!isFinished)
scoreBar.setDeltaTime(deltaTime);
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setProjectionMatrix(batch.getProjectionMatrix());
shapeRenderer.setColor(Color.GRAY.r,Color.GRAY.g, Color.GRAY.b, 0.6f);
shapeRenderer.rect(0, camH - barHeight, camW, barHeight);
shapeRenderer.end();
Gdx.gl.glDisable(GL20.GL_BLEND);
batch.begin();
scoreBar.render(batch);
if (animateSpread) {
timeLoopSpread += deltaTime;
if (timeLoopSpread > duration) {
timeLoopSpread = 0;
animateSpread = false;
} else
animateCluster();
}
}
private void animateCluster() {
float factor = Interpolation.pow5Out.apply(timeLoopSpread /duration);
for (int index =0; index < clusterList.size(); index++) {
Cluster tempC = clusterList.get(index);
currentPos.set(tempC.endPos);
currentPos.sub(tempC.startPos);
currentPos.scl(factor);
currentPos.add(tempC.startPos);
tempC.setCenterPosition(currentPos);
}
}
Object oriented way to do this is to make the clusters animate themselves.
Instead of calling AnimateClusters() you would enable/disable them animating. Wherever you enable animateSpread you would call something like
for (int i = 0; i < clusterList.size(); i++) {
clusterList.get(i).spreadStart();
}
Then update each cluster in render(), each cluster would keep its own animation time.
for (int i = 0; i < clusterList.size(); i++) {
// update animation in there
clusterList.get(i).update(delta);
}
You could also stop the animation in the same way as it was started.
I am currently writing some simple snake game in java. The snake objects has an array full of bodyparts. these bodyparts all contain a rectangle.
the snake's update method is like that:
public void update() {
if(isMoving) {
if(System.currentTimeMillis() - moveTimer > moveSpeed) {
if(parts.get(0).getX()+dx*size >= 0+GameView.GRID_PADDING_LEFT && parts.get(0).getY()+dy*size >= 0+GameView.GRID_PADDING_TOP && parts.get(0).getX()+dx*size <= ((GameView.GRID_WIDTH-1)*size)+GameView.GRID_PADDING_LEFT && parts.get(0).getY()+dy*size <= ((GameView.GRID_HEIGHT-1)*size)+GameView.GRID_PADDING_TOP) {
for(int i = parts.size()-1; i > 0; i--) {
parts.get(i).setLocation((int)(parts.get(i-1).getX()), (int)(parts.get(i-1).getY()));
}
parts.get(0).setLocation(parts.get(0).getRect().left+dx*size, parts.get(0).getRect().top+dy*size);
moveTimer = System.currentTimeMillis();
}else {
die();
}
}
}
}
All in one, the snake moves it's head into dx direction times one cellspace (size) --> dx*size and dy*size.
Then the rest of the body moves, the part behind the head gets the coordinates of the head, the part behind that part gets the coodrinates from the part in front of him etc.
Now I am trying to achieve some collision with the snake itself. I've tried several methods, e.g.:
if(parts.size() > 2) {
for(int i = 3; i < parts.size(); i++) {
if(parts.get(0).getRect().intersect(parts.get(i).getRect())) {
die();
}
}
}
But as soon as the bodypart array reaches the limit of 2 parts, the die() method gets called. I don't know why, because the 2nd part should sit two bodyparts behind the head, which makes it impossible to intersect with the head-rectangle.
Where's my problem?
Oh, that was a really big fail i made here.
When adding a new part, the new part gets the coordinates of the head. Of course will intersect with the head when it gets it's coordinates on create!!
Nevertheless, thanks for the replies!
new addPart method, corrected the parts.get(0) --> parts.get(parts.size()-1)
public void addPart(int amount) {
for(int i = 0; i < amount; i++) {
parts.add(new BodyPart(parts.get(parts.size()-1).getX(), parts.get(parts.size()-1).getY(), parts.get(parts.size()-1).getHue()-5));
}
}
How can i improve the quality of line drawn using openGL. I dont know if im doing this the best way . Im using ShareRenderer and line. But as you can see in the image round corners dont render very well.
Im getting points in touch down and drag, i thought this would be easy to draw a line but i guess this needs to done differently in openGL. I want to trace over letters with a finger for learning to write. I can use openGL-es 1 or 2 , doesn't matter. The device used here for the image was Samsung S3.
#Override
public void render(float delta) {
super.render(delta);
if(mPoints.size() < maxPoints) return;
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
for(int i=0; i < maxPoints-1; i++) {
Vector3 pnt = mPoints.get(i);
if(pnt.x == 0 && pnt.y == 0) continue;
Vector3 pnt2 = mPoints.get(i+1);
if(pnt2.x == 0 && pnt2.y == 0) continue;
shapeRenderer.line(pnt.x, pnt.y, pnt2.x, pnt2.y);
}
shapeRenderer.end();
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
shapeRenderer.setProjectionMatrix(getCamera().combined);
Gdx.gl20.glLineWidth(200);
Gdx.gl.glEnable(GL20.GL_BLEND);
}
#Override
public boolean touchDown(int x, int y, int pointer, int button) {
currentFinger = pointer;
if (++numStrokes >= 2) { //number of strokes for a letter
numStrokes = 0;
clearAllPoints();
currentPointIndex = 0;
}
setPoint(0, 0);
return false;
}
#Override
public boolean touchDragged(int x, int y, int pointer) {
if(currentFinger!=pointer) return false;
Vector3 pnt = mPoints.get(currentPointIndex);
tempVector.set(x, y, 0);
getCamera().unproject(tempVector);
float dx = Math.abs(tempVector.x - pnt.x);
float dy = Math.abs(tempVector.y - pnt.y);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
setPoint(x, y);
}
return false;
}
UPDATED render method below to draw filled rectangles and circles, filled circles works much better.
public void render(float delta) {
super.render(delta);
if(mPoints.size() < maxPoints) return;
shapeRenderer.begin(ShapeRenderer.ShapeType.FilledRectangle);
for(int i=0; i < maxPoints-1; i++) {
Vector3 pnt = mPoints.get(i);
if(pnt.x == 0 && pnt.y == 0) continue;
Vector3 pnt2 = mPoints.get(i+1);
if(pnt2.x == 0 && pnt2.y == 0) continue;
//This creates a rectangle from the set of points see : http://stackoverflow.com/questions/7854043/drawing-rectangle-between-two-points-with-arbitrary-width
dist.set(pnt2.x - pnt.x, pnt2.y - pnt.y, 0);
pVector.set(dist.y, -dist.x, 0); //Find perpendicular (right angle) to points , basically swap x and y , make one negative
float length = (float) Math.sqrt(pVector.x * pVector.x + pVector.y * pVector.y); //Thats length of perpendicular
normVector.set(pVector.x - length, pVector.y-length, 0);
//shapeRenderer.filledCircle(pnt.x, pnt.y, lineWidth);
shapeRenderer.filledRect(pnt.x - pVector.x * rectWidth/2 , pnt.y - pVector.y * rectWidth /2, rectWidth, rectWidth);
}
shapeRenderer.end();
}
OpenGL line width other than 1.0 is not well supported in OpenGL ES, so you should avoid it on Android (See Libgdx gl10.glLineWidth()).
To get a smoother, more rounded looking "fat lines", draw each touch point as a circle, and connect points that are more than a couple pixels apart with a rectangle.
See:
libgdx- pixmap: can I somehow change the width of the line?
Drawing rectangle between two points with arbitrary width
TO smoother any line or shape you can use feature of Multisample_anti-aliasing
to do this what you have to do is:
replace the parameters in Gdx.gl.glClear();
use this:
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT | (Gdx.graphics.getBufferFormat().coverageSampling?GL20.GL_COVERAGE_BUFFER_BIT_NV:0));
and in addition to this go to default packages like android html desktop etc and add this line
for android:
config.numSamples =2;
for ios:
config.multisample = GLKViewDrawableMultisample.valueOf("2");
for desktop:
config.samples = 3;
I am new to libGDX so i found this the easiest way to do it with any shape..
I have an isometric map which I draw to the canvas. When I try and move the map around, these black lines flicker in between some of the tiles making the whole thing look rather shoddy.
Here is the relevant code from my updating thread
public void run() {
Canvas c;
while (isRunning){
c = null;
try {
c = cellMap.getHolder().lockCanvas(null);
synchronized (cellMap.getHolder()) {
cellMap.onDraw(c);
}
} finally {
if( c != null){
cellMap.getHolder().unlockCanvasAndPost(c);
}
}
}
}
and from my CellMap class (which extends SurfaceView):
public void onDraw(Canvas canvas){
canvas.drawColor(Color.BLACK);
int x = 0;
int y = 0;
for(int i = 0; i < mapSize; i++){
for(int j = 0; j < mapSize; j++){
x = (i-j) * 30 + xOffset;
y = (i+j) * 15 + yOffset;
mapCells[i][j].draw(canvas, paint, x, y);
}
}
mapCells[][] is an array of objects which contain the Bitmap image that needs to be drawn. The draw() function is only 1 line canvas.drawBitmap(bitmapImage, x, y, null)
I have discovered that removing the line Canvas.draw(Color.black) gets rid of the flicker. However, when I move the map the canvas is not cleared so I still see the image from the previous frames. I'd imagine it is because it is taking too long to draw the bitmaps? but the map is only very small at the moment.
I found the problem. When moving the map, the offset values were being changed. This lead to sections of the map being drawn temporarily with different offset values - creating the tearing. duh!
I solved this by copying the xOffset and yOffset values at the start of the onDraw() method, and using those values for the update.
Can anyone help please.
Im writing a small Android game where the player is able to select a "barrier" and drag it accross the screen with their finger. I have the barriers drawn on the screen and I am able to drag it accross the screen.
My problem however is when I add more than 1 barrier, eg 3 barriers, and drag a barrier accross the screen, they all drag and they all drag to the same position. That is to say they all lie on top of each other, making it look as though there is only 1 barrier.
Here is my code, can anyone please tell me where I am going wrong/explain where I am going wrong.
public class MainGamePanel extends SurfaceView implements SurfaceHolder.Callback, SensorEventListener {
// Initialising the Barrier
private Barrier barrier[] = new Barrier[3];
// The Main Game Panel
public MainGamePanel(Context context) {
super(context);
// Adding a call-back (this) to the surfaceHolder to intercept events
getHolder().addCallback(this);
// Creating the Game items
// The starting coordinates of the Barrier
int x = 30;
int y = 270;
barrier[0] = new Barrier(BitmapFactory.decodeResource(getResources(), R.drawable.blue_barrier), x, y);
barrier[1] = new Barrier(BitmapFactory.decodeResource(getResources(), R.drawable.green_barrier), x + 15, y);
barrier[2] = new Barrier(BitmapFactory.decodeResource(getResources(), R.drawable.pink_barrier), x + 30, y);
// Create the Game Loop Thread
thread = new MainThread(getHolder(), this);
// Make the GamePanel focusable so it can handle events
setFocusable(true);
}
// Handles the touch events
public boolean onTouchEvent(MotionEvent event)
{
int eventAction = event.getAction();
int x = (int)event.getX();
int y = (int)event.getY();
switch (eventAction)
{
// Touch down so check if finger is on Barrier
case MotionEvent.ACTION_DOWN:
if (x > barrier[0].getX() && x < barrier[0].getX() + 8
&& y > barrier[0].getX() && y < barrier[0].getY() + 8)
{
barrier[0].isTouched();
}
else if (x > barrier[1].getX() && x < barrier[1].getX() + 8
&& y > barrier[1].getX() && y < barrier[1].getY() + 8)
{
barrier[1].isTouched();
}
else if (x > barrier[2].getX() && x < barrier[2].getX() + 8
&& y > barrier[2].getX() && y < barrier[2].getY() + 8)
{
barrier[2].isTouched();
}
break;
// Touch-drag with the Barrier
case MotionEvent.ACTION_MOVE:
// Move the Barrier the same as the finger
for (int i = 0; i < barrier.length; i++)
{
if (barrier[i] == barrier[0])
{
barrier[0].setX(x);
barrier[0].setY(y);
} // end if
else if (barrier[i] == barrier[1])
{
barrier[1].setX(x);
barrier[1].setY(y);
}
else if (barrier[i] == barrier[2])
{
barrier[2].setX(x);
barrier[2].setY(y);
} // end else if
} // end for
break;
case MotionEvent.ACTION_UP:
// Finger no longer on Barrier - Do Nothing
break;
}
return true;
}
// Render - Draws the Game Item Bitmaps to the screen
public void render(Canvas canvas)
{
// Set the background to white
canvas.drawColor(Color.WHITE);
barrier[0].draw(canvas);
barrier[1].draw(canvas);
barrier[2].draw(canvas);
}
// Update
// This is the Game's update method
// It iterates through all the Objects and calls their update() methods (if they have one)
public void update()
{
} // end update
In your barrier move code, you aren't checking a particular barrier is touched, so you're moving all of them to the same coordinates. The following loop does exactly the same thing as your current code:
// Move the Barrier the same as the finger
for (int i = 0; i < barrier.length; i++)
{
barrier[i].setX(x);
barrier[i].setY(y);
} //end for
To fix this, you need to check if the current barrier in the loop is the one that was touched, and can change that whole loop to something like:
// Move the Barrier the same as the finger
for (int i = 0; i < barrier.length; i++)
{
if (barrier[i].isTouched())
{
barrier[i].setX(x);
barrier[i].setY(y);
} // end if
} // end for
You would then need to make sure that you un-set the touched property in the ACTION_UP section. If you post your Barrier class definition I can probably help more.
I'm pretty sure your problem could be solved by making the barriers three separate objects instead of in an array.
As already pointed out, your code in handling the move is wrong because it moves all the Barriers to the same X,Y when it should only move the one that is touched.
Also, you are never resetting the isTouched on the objects in the Action up. When the user lifts their finger you should set them all to isTouched == false. If you don't do that then once you touch one it will always move to the X,Y.