Android implementacja chodzenia po mapie, droga na skos źle działa

0

Mam ogromny problem z fragmentem kodu i jestem załamany. Nawet nie wiem czy jest sens wrzucać tutaj bo to za dużo chyba powiązań w kodzie i tłumaczenia żeby ktoś ogarnął na szybko. Ale jestem w kropce, piszę grę sam więc muszę tak zapytać bo chyba sam sobie z tym nie poradzę. Ale jeśli ktoś by mi z tym pomógł to z przyjemnością postawiłbym browara.

Otóż sprawa wygląda tak, że jeśli nasza postać (chibi1) idzie poziomo lub pionowo po mapie to nie ma problemu. Problem jest kiedy chcemy iść na skos. Wtedy postać przegapia określone pole i idzie o jedno pole w bok dalej.

public class GameSurface extends SurfaceView implements SurfaceHolder.Callback {

    int movingVectorX, movingVectorY;
    double stepX, stepY, stepsX, stepsY, stepsXSkos, stepsYSkos;
    List<Integer> pathX = new ArrayList<>(), pathY = new ArrayList<>(), movingVectorsX = new ArrayList<>(), movingVectorsY = new ArrayList<>();

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        
        (...)

        movementControl(canvas);
    }

(...)
    private void movementControl(Canvas canvas) {
        stepX = Math.abs(aa - chibi1.getX() - (chibi1.getWidth() / 2));
        stepY = Math.abs(bb - chibi1.getY() - (chibi1.getHeight() / 2));

        //nie zmieniają się wektory, to źle
        if (movingVectorX != 0 && movingVectorY == 0) {
            stepsX = stepX / cellWidth;
            stepX = 0;
        }
        if (movingVectorX == 0 && movingVectorY != 0)
            stepsY = stepY / cellHeight;
        if (movingVectorY != 0 && movingVectorX != 0) {

            stepsXSkos = (stepX / (cellWidth*5));
            stepsYSkos = (stepY / (cellHeight*4));
        }


        steps = (int) (stepsX + stepsY + stepsXSkos + stepsYSkos);

        if (pathX.size() > 1 && pathY.size() > 1) {
            if ((chibi1.getX() + (chibi1.getWidth() / 2) < pathX.get(steps)) && !drawerOn)
                movingVectorX = 1;
            if ((chibi1.getX() + (chibi1.getWidth() / 2) > pathX.get(steps)) && !drawerOn)
                movingVectorX = -1;
            if ((chibi1.getY() + (chibi1.getHeight() / 2) < pathY.get(steps)) && !drawerOn)
                movingVectorY = 1;
            if ((chibi1.getY() + (chibi1.getHeight() / 2) > pathY.get(steps)) && !drawerOn)
                movingVectorY = -1;
        }


        if (steps < (pathY.size() - 1)) {
            chibi1.setMovingVector(movingVectorsX.get(steps), movingVectorsY.get(steps));
        }

        if (steps >= (pathY.size() - 1)) {
            if (chibi1 != null) chibi1.setMovingVector(0, 0);
            if (selectedNode != enemyNode)
                if (chibi1 != null)
                    chibi1.setX((cellWidth * ((chibi1.getX() / cellWidth))) + (cellWidth / 2) - (chibi1.getWidth() / 2));
            if (selectedNode != enemyNode)
                if (chibi1 != null)
                    chibi1.setY(((cellHeight) * ((chibi1.getY() / cellHeight))) + (cellHeight / 2) - (chibi1.getHeight() / 2));
            movingVectorY = 0;
            movingVectorX = 0;
            steps = 0;
        }
    }
    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        setValuesOnTapUp(e);
        
        (...)
       
        return true;
    }
    void setValuesOnTapUp(MotionEvent e) {
        gs.aa = gs.chibi1.getX() + (gs.chibi1.getWidth() / 2);
        gs.bb = gs.chibi1.getY() + (gs.chibi1.getHeight() / 2);

       (...)

    }

Obstawiam, że problem jest tutaj w metodzie movementControl():

    if (movingVectorY != 0 && movingVectorX != 0) {

        stepsXSkos = (stepX / (cellWidth*5));
        stepsYSkos = (stepY / (cellHeight*4));
    }

te steps skos są źle wyliczane bo nie wiem jaki wzór użyć do ich obliczenia...

0

czemu cellWidth i cellHeight mnożysz przez różne wartości? (ostatni kawałek kodu).

0

No właśnie tu jest problem, że nie wiem przez jakie wartości mnożyć / dzielić. To właśnie tu jest problem chyba, bo te wartości biorę na próbę i czapki z głów temu kto wymyśli co tam wstawić zamiast tego.

0

Nie wiem po co to liczysz, ale jak chcesz liczyć "skos", to z twierdzenia pitagorasa. sqrt(x*x + y*y)

0

Faken nie można edytować postów, uprościłbym i wyklarował kod.

3

Nie bardzo rozumiem, co tam się dzieje.
Nie dziwię się, że i sam autor nie rozumie.
Uważam, że to podręcznikowy przykład, czemu zawsze warto pisać testy jednostkowe.

Poza tym radziłbym oddzielić kod odpowiedzialny za abstrakcyjną logikę poruszania się (tj. samo przeliczanie współrzędnych x, y) od kodu, który potem już tłumaczy te współrzędne na język graficznych konkretności (czyli moment, gdy w grę wchodzą już getWidth, getHeight itd.). Mieszanie jednego z drugim to proszenie się o bajzel.

W ogóle zresztą ten kod jest napisany mocno niechlujnie, i warto by nad tym popracować, bo ma to wpływ na czytelność.

0
V-2 napisał(a):

W ogóle zresztą ten kod jest napisany mocno niechlujnie, i warto by nad tym popracować, bo ma to wpływ na czytelność.

Refactoring robię dopiero jak coś działa.

jako, że nie można edytować postu to powiem, że zmieniłem stepXSkos i stepYskos na jedną zmienną double

stepsDiagonal = Math.sqrt((stepX*stepX) + (stepY*stepY)) / (Math.sqrt((cellWidth*cellWidth) + (cellHeight*cellHeight)));

i to zdaje się działać ale jedynie kiedy cała trasa jest na skos, a jeśli trasa składa się z odcinków poziomo/pionowo/diagonalnych, to postać zatrzymuje się przed skrętem.

2
V-2 napisał(a):

W ogóle zresztą ten kod jest napisany mocno niechlujnie, i warto by nad tym popracować, bo ma to wpływ na czytelność.

Refactoring robię dopiero jak coś działa.

Problem, do którego prowadzi takie podejście, powinien już być dla ciebie oczywisty...

1

Rzeczywiście, jest problem z prosty zrozumieniem tego, co się w twoim kodzie dzieje. Kiedy widzę private void movementControl(Canvas canvas) to spodziewam się zobaczyć coś w stylu (to akurat przykład z c++ w SFML, stąd):

if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
    character.move(1.f, 0.f);
}

Udostępniłeś nam małą część kodu, z czego większość raczej i tak się nie przyda do rozwiązania problemu. Nawet jeśli wkleisz cały kod, to bez odpalenia programu ciężko będzie coś poradzić, bo sposób, w jaki napisałeś kod, bardzo to utrudnia. Nie pisałem gry "mobilnej", ale kiedy ja uczę się porządkowania kodu w sensowny i przejrzysty sposób, to najlepszym sposobem jest skorzystanie z tutoriala, polecam te w formie video. Pewnie na pierwszym-lepszym zobaczysz, w jaki sposób najprościej poradzić sobie z poruszaniem postacią.

2

Źle zadajesz pytania i niedbale kodujesz.

Na start powinieneś zdefiniować dokładnie co chcesz zrobić. Np.

  1. Chcę po stuknięciu w ekran wykryć komórkę, na którą ma iść postać.
  2. Wykrywanie stuknięcia mam tu.
  3. Kiedy już wiem, w którą komórkę stuknął użytkownik, to biorę bieżącą komórkę gracza i wyznaczam trasę do stukniętej komórki.
  4. Wyznaczanie trasy robi taka metoda, zmienne XY zawierają całkowite pozycje na mapie, a inne zmienne zawierają pozycję w pikselach...
  5. Animację przechodzenia przez całą wyznaczoną trasę realizuje taka metoda i przechodzi krok po kroku przez każde pole. Każdy krok ma krótką przerwę, żeby ruch nie wyglądał na ciągły.

Jak patrzę na Twój kod, pojawia się zbyt wiele niewiadomych, które zniechęcają do domyślania się co miałeś na myśli.
Twój kod, przy którym prosisz o pomoc powinien być w miarę zrozumiały. Przerób sobie książkę "Czysty Kod". Nawet przykłady tam masz w Javie. ( https://helion.pl/ksiazki/czysty-kod-podrecznik-dobrego-programisty-robert-c-martin,czykov.htm ).
Nauczysz się, żeby przydługawe formułki nazywać jakoś robiąc metodę. To nie tylko ułatwi Ci programowanie, ale też innym ułatwi zrozumienie Twojego kodu.

Screenshot z gry i jakieś znaczki/napisy też by pomogły...

0

Look really confusing

1 użytkowników online, w tym zalogowanych: 0, gości: 1