如何在catgdx

时间:2017-06-03 07:34:09

标签: java libgdx game-physics

我试图移动我的曲线,但它不能很好地移动,当它从左到右或从右到左改变方向时,运动非常尴尬。 我想像这个视频一样移动我的曲线 video of curve movement what i actually want。 在这个视频中,当它改变它的方向时,它是如此优雅,但在我的情况下,它改变了它的方向,曲线在新添加的点上给出了一个疯狂的形状。 专家请解决这个问题。 这是我的代码

//create paths
private Bezier<Vector2> path1; 
private CatmullRomSpline<Vector2> path2;
private ShapeRenderer sr;
int height,width;
Vector2 starting,ending,endingControl;
ArrayList<Vector2> listOfPoints;
Vector3 touchPos;
float timeDifference;
Boolean leftPos=false,rightPos=false;
Boolean isTouch=false,isTouchUp=false;
Vector2 mVector2;
private OrthographicCamera cam;
Vector2[] controlPoints;

@Override
public void create () { 

     width = Gdx.graphics.getWidth();
     height = Gdx.graphics.getHeight();
     ending=new Vector2(width/2,height/2);
     endingControl=new Vector2(ending.x,ending.y+10);
     starting=new Vector2(width/2,0);

    controlPoints = new Vector2[]{starting,starting,ending,ending};



    // set up the curves

    path2 = new CatmullRomSpline<Vector2>(controlPoints, false);
    listOfPoints=new ArrayList<Vector2>();
    // setup ShapeRenderer
    sr = new ShapeRenderer();
    sr.setAutoShapeType(true);
    sr.setColor(Color.BLACK);
    cam=new OrthographicCamera();
    cam.setToOrtho(false);
    listOfPoints.add(new Vector2(width/2,0)); //starting 
    listOfPoints.add(new Vector2(width/2,0)); //starting

}

@Override
public void resize(int width, int height) {
    // TODO Auto-generated method stub
    super.resize(width, height);


    cam.update();
}

@Override
public void render () {
    cam.update();
    Gdx.gl.glClearColor(1f, 1f, 1f, 1f);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    sr.begin();
    sr.set(ShapeType.Filled);


    if(Gdx.input.isTouched())
    {


        if(!isTouch){
            listOfPoints.add(new Vector2(ending.x+2, ending.y-4));


            int s=listOfPoints.size();
            controlPoints=new Vector2[s+2];
            listOfPoints.toArray(controlPoints);


            controlPoints[s]=ending;
            //endingControl.x=ending.y;
            controlPoints[s+1]=ending;
            path2 = new CatmullRomSpline<Vector2>(controlPoints, false);

        }

        isTouch=true;
        ending.x+=3;





    }
    else {

        if(isTouch){
            listOfPoints.add(new Vector2(ending.x-2, ending.y-4));
           int s=listOfPoints.size();
            controlPoints=new Vector2[s+2];
            listOfPoints.toArray(controlPoints);


            controlPoints[s]=ending;

            controlPoints[s+1]=ending;

            path2 = new CatmullRomSpline<Vector2>(controlPoints, false);


        }
        isTouch=false;
        ending.x-=3;

    }


    moveAndReduce();


    for(int i = 0; i < 100; ++i){
        float t = i /100f;
        Vector2 st = new Vector2();
        Vector2 end = new Vector2();
        path2.valueAt(st,t);
        path2.valueAt(end, t-0.01f);
        sr.rectLine(st.x, st.y, end.x, end.y,3);

    }

    sr.end();

}

@Override
public void dispose () {
    sr.dispose();
}

public void moveAndReduce()
{
    for(Vector2 vector2:listOfPoints)
    {
        vector2.y-=3 ;

    }
    if(listOfPoints.size()>3 && listOfPoints.get(3).y<-1)
    {

        listOfPoints.remove(0);
        listOfPoints.set(0, listOfPoints.get(1));
        int s=listOfPoints.size();
        controlPoints=new Vector2[s+2];
        listOfPoints.toArray(controlPoints);
        controlPoints[s]=ending;
        controlPoints[s+1]=ending;    
        path2 = new CatmullRomSpline<Vector2>(controlPoints, false);    
    }
}

1 个答案:

答案 0 :(得分:1)

通过视频看,曲线看起来并不受控制点的限制,只是一个简单的加速点跟踪。

您创建一个浮点数组,其长度(以像素为单位)与x方向上的线条长度相匹配。例如,如果屏幕宽度为200像素,则线条可以为100,因此阵列的长度为100。将数组中的每个浮点数设置为屏幕高度的一半的起始值。我在这个答案中调用数组line。你称它为你喜欢的。

您指定的head索引是最右侧的索引。每个框架将head索引向上移动一个。如果它在数组length-1之上,则将其设置为零(数组的开头)

渲染路径

当您绘制line时,您可以从head + 1

中绘制所有点
Path p = new Path();
for(int i = 0; i < 100; ++i){
   p.lineTo(i, line[(i + head + 1) % 100]); // add path points
}
// draw the path;

上下移动

为了让它移动,你有一个移动浮动move,该移动为0表示没有移动,或者正向和反向值向上或向下移动。

如果您想要移动,请将move金额增加固定值。

// moving down
if(move < maxMove){  // set a max move amount eg 10
    move += moveAmount;  // moveAmount 0.2 just as an example
}

同样向上移动,但减去

如果没有输入,您将move金额按固定汇率

移回零
// assume this is code run when no input
if(move != 0){
    if(Math.abs(move) < moveAmount){ // if close to zero set to zero
       move = 0;
    }else{
       move -= Math.sign(move) * moveAmount; // else move towards zero at
                                             // fixed rate
    }
}

前进

这条线不会向前移动,只是在我们每帧移动头部位置时才会这样做。

回到移动线的头部,下面向上或向下移动线头位置(但是没有完成,最后一行被修改以创建更平滑的曲线)

float pos = line[head]; // get the pos of line at head
head += 1; // move the head forward 1
head %= 100; // if past end of array move to 0
line[head] = pos + move; // set the new head position

更好的曲线

这将根据移动向上或向下移动线的头部。我们获得的曲线并不是那么好,所以为了让它变得更平滑你需要改变移动值改变头部位置的速率。

// an sCurve for any value of move the result is  from -1 to 1
// the greater or smaller move the closer to 1 or -1 the value gets
// the value -1.2 controls the rate at which the value moves to 1 or -1
// the closer to -1 the value is the slower the value moves to 1 or -1    
float res =  (2 / (1 + Math.pow(move,-1.2))) -1;

这实际上在上下移动时将线条曲线的形状改变为几乎正弦波

// so instead of
//line[head] = pos + move; // set the new head position
line[head] = pos + ( (2 / (1 + Math.pow(move,-1.2))) -1 ) * maxSpeed;
// max speed is the max speed the line head can move up or down
// per frame in pixels.

显示曲线的示例

下面是一个Javascript实现,如上所述(不作为答案代码)。使用键盘向上箭头向上和向下箭头移动线

如果您使用的是平板电脑或手机,那么您将看到下面的图片,为我添加和测试触摸示例的时间较晚

enter image description here

const doFor = (count, callback) => {var i = 0; while (i < count) { callback(i ++) } };
const keys = {
    ArrowUp : false,
    ArrowDown : false,
};
function keyEvents(e){
    if(keys[e.code] !== undefined){
        keys[e.code] = event.type === "keydown";
        e.preventDefault();
    }
}
addEventListener("keyup", keyEvents);
addEventListener("keydown", keyEvents);
focus();
var gameOver = 0;
var gameOverWait = 100;
var score = 0;
var nextWallIn = 500
var nextWallCount = nextWallIn;
var wallHole = 50;
const wallWidth = 5;
const walls = [];
function addWall(){
  var y = (Math.random() * (H - wallHole  * 2)) + wallHole *0.5;
  walls.push({
      x : W,
      top : y,
      bottom : y + wallHole,
      point : 1, // score point
  });
}
function updateWalls(){
   nextWallCount += 1;
   if(nextWallCount >= nextWallIn){
      addWall();
      nextWallCount = 0;
      nextWallIn -= 1;
      wallHole -= 1;
   }
   for(var i = 0; i < walls.length; i ++){
      var w = walls[i];
      w.x -= 1;
      if(w.x < -wallWidth){
        walls.splice(i--,1);
      }
      if(w.x >= line.length- + wallWidth && w.x < line.length){
          var pos = line[head];
          if(pos < w.top || pos > w.bottom){
              gameOver = gameOverWait;
          }
      }
      if(w.point > 0 && w.x <= line.length){
        score += w.point;
        w.point = 0;
      }
   }
}
function drawWalls(){
  for(var i = 0; i < walls.length; i ++){
      var w = walls[i];
      ctx.fillStyle = "red";
      ctx.fillRect(w.x,0,wallWidth,w.top);
      ctx.fillRect(w.x,w.bottom,wallWidth,H-w.bottom);
  }
}
const sCurve = (x,p) =>  (2 / (1 + Math.pow(p,-x))) -1;
const ctx = canvas.getContext("2d");
var W,H; // canvas width and height
const line = [];
var move = 0;
var curvePower = 1.2;
var curveSpeed = 0.2;
var maxSpeed = 10;
var headMoveMultiply = 2;
var head;
function init(){
  line.length = 0;
  doFor(W / 2,i => line[i] = H / 2);
  head = line.length - 1;
  move = 0;
  walls.length = 0;
  score = 0;
  nextWallIn = 500
  nextWallCount = nextWallIn;
  wallHole = 50;
  ctx.font = "30px arial black";
}
function stepLine(){
  var pos = line[head];
  head += 1;
  head %= line.length;
  
  line[head] = pos + sCurve(move,curvePower)*headMoveMultiply ;

}
function drawLine(){
  ctx.beginPath();
  ctx.strokeStyle = "black";
  ctx.lineWidth = 3;
  ctx.lineJoin = "round";
  ctx.lineCap = "round";
  for(var i = 0; i <line.length; i++){
    ctx.lineTo(i,line[(i + head + 1) % line.length]);
  }
  ctx.stroke();
}

function mainLoop(time){
    if(canvas.width !== innerWidth || canvas.height !== innerHeight){ 
        W = canvas.width = innerWidth;
        H = canvas.height = innerHeight;
        init();
    }
    if(gameOver === 1){
      gameOver = 0;
      init();
    }
    ctx.setTransform(1,0,0,1,0,0); 
    ctx.clearRect(0,0,W,H); 
    if(keys.ArrowUp){
        if(move > - maxSpeed){
          move -= curveSpeed;
        }
        
    }else if(keys.ArrowDown){
        if(move < maxSpeed){
           move += curveSpeed;
        }
    }else{
        move -= Math.sign(move)*curveSpeed;
        if(Math.abs(move) < curveSpeed){
            move = 0;
        }
    }
    if(gameOver === 0){
        stepLine();
        updateWalls();
    }
    drawLine();
    drawWalls();
    ctx.fillStyle = "Black";
    ctx.textAlign = "left";
    ctx.fillText("Score : " + score, 10,30);
    if(gameOver > 0){
        ctx.textAlign = "center";
        ctx.fillText("Crashed !!", W / 2,H * 0.4);
        gameOver -= 1;
    }
    requestAnimationFrame(mainLoop);
}
requestAnimationFrame(mainLoop);
canvas {
    position : absolute;
    top : 0px;
    left : 0px;
    z-index : -10;
}
<br><br><br>Up down arrow keys to move line.
<canvas id=canvas></canvas>