2012-12-12 10 views
6

Wiem, że zostało to zadane kilka razy wcześniej, ale nie było odpowiedzi, która faktycznie działa, co mogę znaleźć. Jest podobny, ale prędkość zmienia się w zależności od przebytej odległości.Przesuwanie obiektu wzdłuż linii prostej ze stałą prędkością od punktu A do B

Mój problem polega na tym, że próbuję uzyskać obiekt (w tym przypadku odtwarzacz), aby poruszać się wzdłuż linii prostej od punktu A do punktu B ze stałą prędkością. Odbywa się to poprzez kliknięcie na odtwarzaczu i przeciągnięcie do miejsca, do którego chcę iść, aby mógł być w dowolnym kierunku i na dowolną odległość.

Mam kod, który prawie działa, ale odtwarzacz zawsze kończy się nieco poza kursem, tym bardziej im dłuższy dystans, który pokonuje. Oto kod:

window.addEventListener('mouseup', function(e) { 
    selectedPlayer.moveX = e.pageX; 
    selectedPlayer.moveY = e.pageY; 
    movePlayer(selectedPlayer); 
}); 

function movePlayer(player) { 

    var xDistance = player.moveX - player.x; 
    var yDistance = player.moveY - player.y; 
    var travelDistance = Math.sqrt((xDistance * xDistance) + (yDistance * yDistance)); 
    var timeToTravel = travelDistance; //This may seem pointless, but I will add a speed variable later 
    var playerAngle = Math.atan2(yDistance, xDistance) * (180/Math.PI); 
    var xRatio = Math.atan2(xDistance, travelDistance); 
    var yRatio = Math.atan2(yDistance, travelDistance); 

    //This function is called in another part of code that repeats it 60 times a second 
    walkPlayer = function() { 

     setTimeout(function(){ 
      player.x = player.moveX; 
      player.y = player.moveY; 
      selectedPlayer = undefined; 
      walkPlayer = undefined; 
     }, timeToTravel * 20) 

     player.angle = playerAngle; 
     player.x += xRatio; 
     player.y += yRatio; 
    }; 
} 

Mam nadzieję, że to ma sens, musiałem uwzględnić tylko tę część kodu, która jest istotna. Myślę, że mój problem prawdopodobnie dotyczy części xRatio i yRatio, ale nie mogę tego rozgryźć; Jestem kompletnie zakłopotany.

EDYCJA: Chciałbym dodać, że PlayerAngle sprawia, że ​​gracz twarzą w kierunku przeciągania, a ta część działa dobrze.

+0

Czy X i Y Int? Ponieważ ruch będzie prawdopodobnie wymagał stabilnego pływaka. (Nie jestem super javascript, więc może var jest właściwy?) – ninMonkey

+0

Co to ma zrobić 'setTimeout'? Zwłaszcza jeśli jest wywoływany 60 razy na sekundę? – Bergi

+0

@Bergi to (zła) próba zatrzymania gracza we właściwym miejscu. Działa, ale jest dość błędny i nieefektywny. Nie miałem jednak czasu, aby przejrzeć tę część, ponieważ starałem się rozwiązać główny problem. –

Odpowiedz

8

Live Demo

Poniżej są podstawy potrzebne, aby dostać to, czego potrzebujesz pracy,

var tx = targetX - x, 
    ty = targetY - y, 
    dist = Math.sqrt(tx*tx+ty*ty), 
    rad = Math.atan2(ty,tx), 
    angle = rad/Math.PI * 180;; 

    velX = (tx/dist)*thrust; 
    velY = (ty/dist)*thrust; 

player.x += velX 
player.y += velY 

To demo Zrobiłem jakiś czas temu, który brzmi jak co szukasz, dodałem możliwość kliknięcia w celu zmiany celu na podstawie twojego problemu.

window.addEventListener('mouseup', function(e) { 
    targetX = e.pageX; 
    targetY = e.pageY; 
}); 

var ctx = document.getElementById("canvas").getContext("2d"), 
    x = 300, 
    y = 0, 
    targetX = Math.random()*300, 
    targetY = Math.random()*300, 
    velX = 0, 
    velY = 0, 
    thrust = 5; 


function draw(){ 
    var tx = targetX - x, 
     ty = targetY - y, 
     dist = Math.sqrt(tx*tx+ty*ty), 
     rad = Math.atan2(ty,tx), 
     angle = rad/Math.PI * 180;; 

    velX = (tx/dist)*thrust; 
    velY = (ty/dist)*thrust; 

    // stop the box if its too close so it doesn't just rotate and bounce 
    if(dist > 1){ 
     x += velX; 
     y += velY; 
    } 

    ctx.fillStyle = "#fff"; 
    ctx.clearRect(0,0,400,400); 
    ctx.beginPath(); 
    ctx.rect(x, y, 10, 10); 
    ctx.closePath(); 
    ctx.fill(); 

    ctx.fillStyle = "#ff0"; 
    ctx.beginPath(); 
    ctx.rect(targetX, targetY, 10, 10); 
    ctx.closePath(); 
    ctx.fill(); 

    setTimeout(function(){draw()}, 30); 
} 

draw(); 
+0

To bardzo przypomina to, czego szukam, dziękuję! Spróbuję trochę go zaadaptować do mojego kodu i sprawdzić, czy to działa i do ciebie wrócić. –

+0

@JamieRushworth tak, trochę pośpiesznie opublikowałem to, napisałem nieco wyjaśnienia powyżej i zmodyfikowałem przykład mojego kodu, aby oprzeć cel poza miejscem, w którym użytkownik kliknie. – Loktar

+0

Działa to znacznie lepiej, dzięki! Dzięki za aktualizację za pomocą myszy, chociaż w twoim demo zdaje się odbijać wokół celu, co wydaje się nieco dziwne. Myślę, że to dlatego, że właściwie nic nie zatrzymuje zatrzymania funkcji, gdy dotrze ona do miejsca przeznaczenia? –

1

Twój problem wydaje się, że xRatio i yRatio są kąty, koordynuje nie wektorowych. Powinno to zadziałać:

document.addEventListener('mouseup', function(e) { 
    movePlayer(selectedPlayer, {x:e.pageX, y:e.pageY}); 
}); 

function movePlayer(player, target) { 
    var start = { 
      x: player.x, 
      y: player.y, 
      t: Date.now() 
     }, 
     distance = Math.sqrt(distance.x*distance.x + distance.y*distance.y), 
     time = distance; //This may seem pointless, but I will add a speed variable later 
     difference = { 
      x: target.x - player.x, 
      y: target.y - player.y, 
      t: time 
     }; 

    player.angle = Math.atan2(distance.y, distance.x) * (180/Math.PI); 

    //This function is called in another part of code that repeats it 60 times a second 
    walkPlayer = function(curTime) { // we need timing information here: Date.now() 
     var elapsed = curTime - start.t, 
      ratio = elapsed/difference.t; 
     player.x = start.x + difference.x * ratio; 
     player.y = start.y + difference.y * ratio; 
     if (ratio >= 1) { 
      player.x = target.x; 
      player.y = target.y; 
      // end calling of walkPlayer 
     } 
    }; 
} 
+0

Bardzo dziękuję, wykorzystałem twoją część czasu i działa świetnie. Nie mogę przegłosować twojego postu, dopóki nie zdobędę 15 punktów reputacji, ale zrobię to, kiedy będę mógł! –

Powiązane problemy