Движение на мишката: Щракнете, спрайтът се придвижва до щракната точка

Аз съм доста нов в C# и XNA и добре програмирам (като че мога да следвам урок, но повечето от създаването сам все още е наистина много трудно). В момента обикалям наоколо, опитвайки се да разбера как да направя това „просто“ нещо.

Ето идеята, това ще бъде игра за отбранителна кула; в момента работя върху основите на голи кости. Имам моя малък спрайт, който ще се движи с въвеждане от клавиатурата, сега искам да щракна някъде на екрана и да го накарам да „ходи“ до тази точка. Само аз се изгубих от логиката. Мога да щракна и той ще скочи там

if (aMouse.LeftButton == ButtonState.Pressed)
{
  Position.X = aMouse.X;
  Position.Y = aMouse.Y;
} 

От това, което прочетох за друго въвеждане с мишката, мисля, че ще ми трябва някакъв вид цикъл (бул може би?), който ще премести спрайта в посока и ще трябва да изпълни проверка, за да види дали той е стигнал до това точка още. Но получаването на тази точка след щракването на мишката и създаването на този цикъл, стартирането на проверката... не съм наясно.


person Steph    schedule 17.02.2011    source източник
comment
Имате два проблема, с които трябва да се справите. Хората отговарят на един от тях. Другото е какво да правите, ако има препятствия по пътя ви. Вижте en.wikipedia.org/wiki/Pathfinding, след като стигнете до тази точка.   -  person Merlyn Morgan-Graham    schedule 17.02.2011


Отговори (4)


Трябва да добавите някои екземплярни променливи:

Point2D targetPos;

И някои константи:

const Point2D speed;

Когато преминете през своя цикъл Update(), актуализирайте текущата позиция, като добавите вектора на скоростта към нея (разбира се в правилната посока), докато не сте в рамките на предварително определен праг от целевата позиция (обикновено праговете се изчисляват от вектора на скоростта - ако разстоянието от текущата позиция до целевата позиция е по-малко от дължината на вектора на скоростта, тогава сте на вашата позиция). Използването на bool в този случай ще работи добре. Когато щракнете с мишката, задайте друга променлива на екземпляр (движение) на true и след като достигнете целевата си позиция, задайте движението на false.

person João Lourenço    schedule 17.02.2011
comment
Благодаря ви за отговора! Трябва да отида да науча повече за Point2D и определянето на праговете. - person Steph; 17.02.2011
comment
Няма проблем. Имах предвид логически прагове. Това е просто проверка дали текущата ви позиция е в рамките на определено разстояние (праг) от вашата целева позиция. - person João Lourenço; 17.02.2011

Хората отговарят на въпроса ви на много ниско ниво. Понякога помага да се мисли за проблема на по-високо ниво.

Това, от което се нуждаете, е тип държавно управление. Фантастичният термин в компютърните науки за това е крайна машина. Но не си правете труда да търсите това точно сега. В началото е доста сухо и объркващо :)

Вашият герой в момента има едно състояние - "стоящ наоколо". Трябва да добавите и обработите състоянието „ходене до дестинацията“.

От това, което прочетох за друго въвеждане с мишката, мисля, че ще имам нужда от някакъв вид цикъл

Имате нужда от един цикъл, наречен цикъл на играта. Ако използвате XNA, вече имате такъв. Но си на прав път.

Всеки път, когато преминавате през цикъла на играта, трябва да обработвате текущото състояние и да проверявате за така наречените Преходи на състояния. Това е, когато промените нещо във вашия свят от едно състояние в друго състояние. Например, когато щракнете с мишката, искате човекът да започне да се движи.

В цикъла на вашата игра проверявате дали току-що се е случило щракване с мишката. Ако е така, задайте някои данни (накъде да се придвижите) и му кажете да започне да ходи, като зададете състоянието му на „ходене до дестинацията“. Следващата актуализация вместо това ще обработите това състояние.

Когато вашият герой е в състояние "ходене към дестинация", трябва да актуализирате позицията му въз основа на времето, изминало от последната актуализация на играта. В XNA това се изчислява за вас. Ако не използвате XNA, тогава ще трябва да проверите сами. Може да можете да използвате нещо като класа Stopwatch и да проверите полето Elapsed.

Ако героят е на местоназначението, трябва да го превключите обратно в състояние "стоящо наоколо".

Ако получите друго щракване с мишката, зависи от вас дали искате състоянието „ходене до дестинацията“ да му обърне внимание или не. Ако обърнете внимание на това, вие настройвате същия вид данни, както когато сте преминали от състояние "стоящо наоколо".

И така, ще ви трябват тези променливи:

  • Таймер, за да разберете изминалото време от последния цикъл на играта (XNA ви го дава)
  • Текущото състояние на играча (може би enum)
  • Текущата позиция на играча (вектор)
  • Скоростта на ходене на играча (вероятно плувка), измерена в единици за секунда (или милисекунда)
  • Данни за състоянието "ходене до местоназначението" - целева позиция (друг вектор)
  • Данни, свързани с въвеждането на потребителя (събития с мишката, настъпили след последната актуализация, позицията на тези кликвания и т.н.)

Специфичните данни за персонажа ще бъдат различни за всеки герой във вашата игра, така че искате ново копие от него за всеки. Вероятно ще искате да го поставите в клас. Останалата част от него е по-глобална, така че можете да го запазите отделно или да го направите част от вашата игра, цикъл на играта, класове за въвеждане и т.н. (както и да изберете да го организирате).

Няма да разглеждам векторната математика за това как всъщност да изчисля нещата с частичното движение, тъй като други хора са разгледали това. Няма смисъл да дублирам тези отговори. Основно се свежда до създаване на вектор между текущата ви позиция и целевата позиция и умножаването/разделянето му по скоростта на ходене (за да го нарежете до разстоянието, изминато в една актуализация).

person Merlyn Morgan-Graham    schedule 17.02.2011
comment
Благодаря ви за отговора! Това наистина ми помага да мисля за това, от което се нуждая. Обмислях да направя състояние с enum, но не бях мислил да го имам за стоене или ходене, мисля, че мога лесно да добавя нещо по този начин, играл съм си с това за нещо друго. Мисля, че разбирам логиката на това, което трябва да се случи, синтаксисът е мястото, където чувствам, че наистина съм заседнал. Знаете ли за книга или онлайн урок, който работи с ходене на спрайт до щракване на мишката? Ако мога да работя с друг пример, наистина мога да го разбера и да го адаптирам към това, което искам. - person Steph; 18.02.2011
comment
@Steph: Всеки урок, който съм виждал по темата (преди няколко години), или предполагаше много неща, беше прекалено общ или прекалено сложен. Ето един, който намерих в Google току-що: create.msdn.com/en -US/education/catalog/sample/, въпреки че изглежда, че може да е трудно. Също така не става ясно от описанието дали поддържа състояние на играта от ниско ниво (на обект) или само състояние от високо ниво (като меню на играта, край на играта, пауза и т.н.). - person Merlyn Morgan-Graham; 18.02.2011

Предполагам, че имате три неща:

  1. Текущата позиция
  2. Желана позиция
  3. Скорост за преместване на всеки „отметка за игра“ // не знаете какво е отметка за игра? разбирам!

Ти гледаш да правиш това

въведете описание на изображението тук

// dx, dy are delta x and delta y. It's how far in each direction
// the player must travel
// note, I fixed a typo where they were desired - desired... should be
// desired - current, as they are now
float dx = desiredX - currentX;
float dy = desiredY - currentY;

// d uses the pythagorean theorum to find the distance between current and desired
float d = sqrt(dx*dx + dy*dy);
// fac is how far along that line between desired and current will you move
float fac = d / speed;

// mx is the component of the dx line proportional to the size of fac : d
// which means it's how far in the x direction you'll move
float mx = dx * fac;
float my = dy * fac;

// the new postition is the old position plus the move value
float newPositionX = dx + mx;
float newPositionY = dy + my;
person corsiKa    schedule 17.02.2011
comment
Благодаря ви за отговора! Имам текуща позиция и скорост, искам желаната позиция да идва от потребителския вход от мишката. Не съм сигурен как да получа това от mouse-user-input. Получавам picuter, но не разбирам вашия код и математика тук... (Наистина съм нов във всичко това) В този пример вие задавате позицията на disred и след това преминавате от текуща към желана, като вземете предвид скоростта? Защо dx е желаното x минус желаното x? и какво означава sqrt и fac? Съжалявам! Не е нужно да обяснявате всичко, ако не искате! Бих искал да разбера, но знам, че съм извън границите си. - person Steph; 17.02.2011
comment
P.S. Сама нарисувах тази картина. Да... възлагам разработката на спрайтовете си! - person corsiKa; 17.02.2011
comment
А!! Виждам. Благодаря ви много, че го обяснихте!! Наистина се радвам на вашата помощ (и напълно знам какво имате предвид за рисуването на спрайтове, моят човек в момента е нещо с квадратни блокове :p). - person Steph; 18.02.2011
comment
Няма проблем. Разработката на игри е много забавна, но има много математика. Наблюдавам етикета game-development, така че не забравяйте да го включите, ако задавате още въпроси. И ако това някога стане годно за игра, изпратете линк :} - person corsiKa; 18.02.2011
comment
хаха Ще го направя! С тази скорост може да мине МНОГО дълго време, преди да стане playbalbe. Имам още един въпрос относно тази математика, абсолютно необходимо ли е да се изчисли разстоянието? Мисля си, че или разстоянието трябва да бъде изчислено, или трябва да има bool цикъл, за да се провери дали желаното (X,Y) е достигнато... Правилно ли мисля? Не съм фен на математиката и винаги се опитвам да я избегна, но с фрумула като тази, тя ще бъде зададена веднъж и след това просто ще работи при необходимост... и мисля, че по отношение на обработката това ще бъде по-бързо след това bool цикъл? - person Steph; 18.02.2011
comment
(съжалявам, че продължавам да ви досаждам) Когато пробих всичко това в sqrt не работеше. Получавам Името „sqrt“ не съществува в текущия контекст, затова опитах Math.Sqrt и получавам Cannont implicity convert type „double to „float“. и съществува изрично преобразуване (липсва ли ви отливка?). Използвам XNA 3.0 в MS Visual C# 2008. Мога да настроя преобразуване, но мисля, че трябва да има по-прост начин... - person Steph; 18.02.2011
comment
Ще разгледам тези един по един. 1) оператор if за определяне на if(d < speed) ще определи дали играчът ще достигне точката. 2) sqrt може да приеме двойно. В такъв случай използвайте двойни стойности за вашите координати или прехвърлете резултата към float като float d = (float)sqrt((double)(dx*dx + dy*dy)); - person corsiKa; 18.02.2011
comment
Любопитен съм - можете ли да ми дадете пример за bool цикъл? :-) Имате предвид оператор if? Само за да сме на една страница - person corsiKa; 18.02.2011

Намерих този код за най-полезен... освен това добавих допълнителни няколко реда, за да предотвратя възникването на определени ситуации. Например ще има моменти, в които посоката е 0,83 и скоростта може да е била променена от фактори на играта като терен/време/т.н.... ако скоростта е под 1, спрайтът може изобщо да не се движи или дори да се движи в грешната посока!

 if (Vector2.Distance(Position, TargetPosition) > 2.0f)
 {
    velocity = Vector2.Subtract(TargetPosition, Position);
    velocity.Normalize();
    /// Now no matter which direction we are going we are always moving @ sprite.Speed
    /// at velocity or speed below 1 - problems occur where the unit may not move at all!!
    if(current_Speed < 1)
    {
       Vector2 temp = (velocity * 10) * (current_Speed * 10);
       Position += temp / 10;
    }
    else
    { 
       Vector2 temp = velocity * current_Speed;
       Position += temp;
    }
    //convert to int to render sprite to pixel perfect..
    Position = new Vector2((int)Position.X, (int)Position.Y);
 }
person Bixel    schedule 17.12.2013