• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Gra w canvas , tablica

VPS Starter Arubacloud
0 głosów
574 wizyt
pytanie zadane 16 listopada 2018 w JavaScript przez ptaku19 Użytkownik (800 p.)

Witam ponownie... Mam tablice, w której przechowuje elementy, które są dodawane przyciskem na ekranie. Elementy te są obiektami w grze(ludzikami), które zwiększają swoje współrzedne na osi X poprzez ich Speed. Próbuje zrobic, aby każdy element(ludzik) zawsze miał odstęp od  innego o pewną wartość X, np. 50. Dodam, że elementy mają funkcję walki i aktualnie walczący element tablicy ma Speed = 0 i chciałbym, aby ludziki czekające na walkę ustawiały się w kolejkę, która właśnie dzieli każdy element odstępem jak już wspominałem.

Kod jest dość długi, ale usunęłem wszystkie zbędne elementy. Gra robiona w canvas.

Próbwałem wklejać kod na różne strony typu CodePen, ale gra mi nie działała.

Jeżeli mam coś skrócic, lub wkleić kod w inne miejsce to prosze o komentarz.

Oto kod:

https://4programmers.net/Pastebin/9959

 

komentarz 17 listopada 2018 przez rafal.budzis Szeryf (85,380 p.)
Hej nie za bardzo rozumiem co chcesz zrobić. W kodzie masz dwie klasy Wojowników oraz Wrogów. Natomiast w pytaniu używasz sformułowania ludziki.

Być może fajnie wygląda by okrąg ? ;) wówczas pozycja to:
x = odstęp * cos(deg) + obecna pozycja x środka koła
y = odstęp * sin(deg)+ obecna pozycja y środka koła
deg to losowa liczba z zakresu od 0 do 6.28 (kąt w radianach)

PS. Klasy piszemy wielką literą a stworzenie obiekty (ich instancje) małą. U ciebie w kodzie jest odwrotnie. W niczym to nie przeszkadza lecz jeśli ktoś się przyzwyczaił do innego zapisu ma przez chwile problem w zrozumieniu twojego kodu ;)
komentarz 17 listopada 2018 przez ptaku19 Użytkownik (800 p.)
Gra ma być w stylu Age of War. Pierwsza postać się biję, a pozostałe czekają w kolejce.

I właśnie chcę zrobić tę kolejkę, ale nie potrafię zrobić odstępów na osi X od każdego elementu tablicy (wojowników i wrogów). Po prostu postacie na ekranie wchodzą na siebie.
komentarz 17 listopada 2018 przez sefir Dyskutant (8,560 p.)
edycja 17 listopada 2018 przez sefir
Chcesz aby tylko 1 wojownik walczył i 1 wróg, a reszta stała z równymi odstępami między sobą, dobrze to rozumiem?

Jak tak to musisz sprawdzić czy odstęp jednostki od jednostki obok w kolejce jest na tyle duży, że możesz wykonać przesunięcie.
komentarz 17 listopada 2018 przez ptaku19 Użytkownik (800 p.)
Dokladnie o to mi chodzi. Czy aby sprawdzić te odstępy trzeba użyć jakiejś wbudowanej metody tablicy? Czy zwykla ifka starczy?
1
komentarz 17 listopada 2018 przez sefir Dyskutant (8,560 p.)
Tak zwykły if wystarczy. :)
komentarz 17 listopada 2018 przez ptaku19 Użytkownik (800 p.)
Mógłbyś mnie jeszcze bardziej naprowadzić? Kompletnie nie mam pomysłu jak się za to zabrać i nie wiem jak odwołać się do każdego elementu z tablicy. Nie chodzi mi o forEach
1
komentarz 17 listopada 2018 przez sefir Dyskutant (8,560 p.)
Możesz to zrobić tak, że podczas tworzenia nowej jednostki przekazywać referencję do ostatniej jednostki z tablicy. I podczas ruchu porównywać tylko z tą jednostką pozycje. Dodaj po prostu pole sąsiad, oczywiście pierwsza jednostka nie będzie posiadać sąsiada, będziesz musiał wstawiać tam null przy każdym usunięciu jednostki.
komentarz 17 listopada 2018 przez ptaku19 Użytkownik (800 p.)
Jestem zielony w temacie referencji, trochę czytałem o tym na internecie, próbowałem coś wykombinować, ale nic nie wychodzi bo do końca nie rozumiem co właściwie robię. Mógłbyś to zademonstrować na jakimś łatwiejszym przykładzie? PS: Tak wiem, że trochę dupe truje :P
1
komentarz 17 listopada 2018 przez sefir Dyskutant (8,560 p.)
edycja 17 listopada 2018 przez sefir

Fajnie, że trujesz, niektórzy chcą tylko gotowe rozwiązania :D

Zaraz coś Ci tam napiszę ;)

 

function enemy (){
  this.x=cw-100
  this.y=ch-170
  this.w=40
  this.h=70
  this.healthBar = 40
  this.strength = 2;
  this.speed= -2
  this.life = 500;
  this.sasiad = (function(){
    if(Warriors.length!==0)
      return Wariors[Wariors.length-1];
    else
      return null;
  })();
  this.move = function(){
    //tutaj sprawdz czy odleglosc this.x od this.sasiad.x jest wystarczajaca by przesunac pole, oczywiscie musisz sprawdzić czy sasiad nie jest null
    this.x+=this.speed
  }
}

 

komentarz 17 listopada 2018 przez ptaku19 Użytkownik (800 p.)
Dzieki bardzo :)
1
komentarz 17 listopada 2018 przez sefir Dyskutant (8,560 p.)
Spoko jak coś to pytaj, ciekawy projekt :)
komentarz 17 listopada 2018 przez ptaku19 Użytkownik (800 p.)

Kolejka już udało mi się zrobić, ale nie rozumiem do końca działania tego kodu. Rozumiem ,że jeżeli this.sasiad !== null to this.sasiad zamienia się w Warriora, tylko którego?

A dwa to, nie umiem za bardzo wykonywać operacji na tym kodzie i gdy Warrior ustanie, ponieważ przekroczył pewien odstęp ma speed=0. Jak zrobić by z powrotem zaczął iść gdy Warrior przed nim zniknie lub ruszy się do przodu? Normalnie zrobiłbym flagowanie, ale tutaj nie potrafie. Oto kod:

function warrior(){
  this.x=220;
  this.y=ch-100-50;
  this.w=30;
  this.h= 50;
  this.speed = 1;
  this.strength = 1;
  this.max = 5;
  this.life = 250;
  this.odstep = 100;
  this.healthBar = 30;
  this.sasiad = (function(){
   if(Warriors.length!==0)
     return Warriors[Warriors.length-1];
   else
     return null;
   })()

  this.move = function (){
      this.x +=this.speed
if(this.sasiad!==null && this.x > this.sasiad.x - this.odstep){
  this.speed = 0;
}
    }

}

 

komentarz 17 listopada 2018 przez ptaku19 Użytkownik (800 p.)
Dodam, że właśnie pracuję nad 'super mocą' , po której użyciu zaczyna lecieć deszcz kwadratów. Oczywiście za kwadrat itp. wklejam własne obrazki.
1
komentarz 17 listopada 2018 przez sefir Dyskutant (8,560 p.)
Podeślesz cały aktualny kod? Będzie mi łatwiej :)
komentarz 17 listopada 2018 przez ptaku19 Użytkownik (800 p.)

Jeżeli chodzi o ten, tylko zaaktualizowany to:

https://4programmers.net/Pastebin/9961

Jeżeli chodzi o mój cały to nie bardzo, ponieważ są tam obrazki i nie mógłbyś tego odpalić.

A druga sprawa to, że jest tam duży syf i chaos przez pracę nad supermocą, który chyba tylko ja ogarnę ( naprawde).

 

komentarz 17 listopada 2018 przez ptaku19 Użytkownik (800 p.)
Zapomniałem dopisać this.odstep =100. To jeżeli możesz proszę dodaj.
1
komentarz 17 listopada 2018 przez sefir Dyskutant (8,560 p.)
Ok, właśnie tego mi brakowało :D
komentarz 18 listopada 2018 przez ptaku19 Użytkownik (800 p.)

Pomożesz z kodem? Zrobiłem, że gdy warior przed nim umiera to ten, który miał speed 0 zaczyna iść do przodu, ale występuje bug.Warrior zaczyna iść, ale szybko przyśpiesza do przeciwnika, chciałbym aby to był powolny ruch.

https://4programmers.net/Pastebin/9964

W jaki sposób mogę zrobić, żeby Warrior cały czas zachowywał odstęp równy 40. W moim kodzie, gdy Warrior ustanie to już ciągle stoi.

komentarz 18 listopada 2018 przez sefir Dyskutant (8,560 p.)

Tu trzymaj drobną poprawkę.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Tower defense</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            display: flex;
            align-items: center;
            height: 100vh;
            background-color: yellow;

        }


        canvas {

            background-color: black;
            border: 10px solid #fff
        }
    </style>

<body>
    <script>
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        document.body.appendChild(canvas);
        canvas.width = window.innerWidth;
        canvas.height = 700;

        const cw = canvas.width;
        const ch = canvas.height;


        var Warriors = []
        var Enemys = []

        for (var i = 0; i < warrior.max; i++) {
            Warriors[i] = new warrior()
        }

        for (var i = 0; i < Enemys.length; i++) {
            Enemys[i] = new Enemy();
        }

        function draw() {
            czyszczenie()
            buttons()
            //Wojownicy
            for (var i = 0; i < Warriors.length; i++) {
                Warriors[i].draw()
                fight()
            }
            //Wrogowie
            for (var i = 0; i < Enemys.length; i++) {
                Enemys[i].draw()
            }
        };

        function czyszczenie() {
            ctx.fillStyle = 'lightblue'
            ctx.fillRect(0, 0, cw, ch)
        }
        //flagowanie przycisku
        var disabled = false;

        function disabling() {
            disabled = false;
        }

        function chooseButt(e) {
            var mouseX = e.clientX - 10;
            var mouseY = e.clientY - 120
            //warriors butt
            if (mouseX > 50 && mouseX < 100 && mouseY > 100 && mouseY < 100 + 50 && money >= 50 && Warriors.length < 5 && disabled == false) {
                disabled = true;
                setTimeout(disabling, 2000)

                Warrior = new warrior()
                Warriors.push(Warrior)
                //nie konieczny warnuek
                if (Warriors.length <= Warrior.max) {
                    money -= 50;
                }
            }
        }

        window.addEventListener('click', chooseButt)

        function buttons() {
            //wojownicy button
            ctx.lineWidth = '5'
            ctx.strokeStyle = 'black'
            ctx.strokeRect(50, 100, 50, 50)

            ctx.fillStyle = 'yellow'
            ctx.fillRect(50, 100, 50, 50)

            ctx.font = '16px Arial'
            ctx.fillStyle = 'red'
            ctx.fillText('W', 67, 130)

        }

        var money = 500;

        function Money() {
            //money
            ctx.font = '16px Arial'
            ctx.fillStyle = 'red'
            ctx.fillText('Money: ' + money, 50, 50)
        }


        function RespawningEnemys() {
            setTimeout(RespawningEnemys, 8000)
            Enemy = new enemy()
            Enemys.push(Enemy)
        };
        RespawningEnemys()


        function fight() {
            if (Enemys.length > 0) {
                if (Warriors[i].x + Warriors[i].w > Enemys[i].x && Warriors[i].x < Enemys[i].x + Enemys[i].w) {

                    Warriors[i].speed = 0;
                    Enemys[i].speed = 0;
                    Warriors[i].life -= Enemys[i].strength;
                    Enemys[i].life -= Warriors[i].strength;

                    // 30 z 250 - 12% //  ile to 12% z 2 - 0.24
                    //Zmniejszanie się paska HP
                    Warriors[i].healthBar -= 0.12 * Enemys[i].strength
                    Enemys[i].healthBar -= 0.08 * Warriors[i].strength


                    if (Warriors[i].life <= 0) {
                        Enemys[i].speed -= 2;
                        Warriors.shift()
                        if(Warriors.length>0){
                            Warriors[0].sasiad = null;
                            Warriors[i].canGo = true;
                        }
                    } else if (Enemys[i].life <= 0) {
                        Warriors[i].speed += 1;
                        Enemys.shift()
                        money += 50;
                    }
                }
            };
        }


        function warrior() {
            this.x = 220;
            this.y = ch - 100 - 50;
            this.w = 30;
            this.h = 50;
            this.speed = 1;
            this.strength = 1;
            this.max = 5;
            this.isFighting = false;
            this.life = 250;
            this.healthBar = 30;
            this.canGo = false;
            this.odstep = 100;
            this.sasiad = (function() {
                if (Warriors.length !== 0)
                    return Warriors[Warriors.length - 1];
                else
                    return null;
            })()

            this.move = function() {
                this.x += this.speed
                if (this.sasiad !== null){
                    if(this.x +this.w+this.odstep> this.sasiad.x){
                        this.x = this.sasiad.x-this.odstep-this.w;
                    }
                }
                if (this.canGo == true) {
                    this.speed += 1;
                }
            }
        };



        warrior.prototype.draw = function() {
            ctx.lineWidth = '5'
            ctx.strokeStyle = 'black'
            ctx.strokeRect(this.x, this.y, this.w, this.h)
            //pasek zycia
            ctx.fillStyle = 'red'
            ctx.fillRect(this.x, this.y - 40, this.healthBar, 10)

            ctx.fillStyle = 'blue'
            ctx.fillRect(this.x, this.y, this.w, this.h)
            this.move();
        }



        function enemy() {
            this.x = cw - 100
            this.y = ch - 170
            this.w = 40
            this.h = 70
            this.healthBar = 40
            this.strength = 2;
            this.speed = -2
            this.life = 500;
            this.move = function() {
                this.x += this.speed
            }
        }
        enemy.prototype.draw = function() {
            ctx.lineWidth = '5'
            ctx.strokeStyle = 'black'
            ctx.strokeRect(this.x, this.y, this.w, this.h)

            //pasek zycia
            ctx.fillStyle = 'red'
            ctx.fillRect(this.x, this.y - 40, this.healthBar, 10)

            ctx.fillStyle = 'red'
            ctx.fillRect(this.x, this.y, this.w, this.h)
            this.move()
        }


        var lastTime = 0;
        var fps = 60;
        animation = function(time) {
            requestAnimationFrame(animation);

            if (time - lastTime >= 1000 / fps) {
                lastTime = time;
                draw();
            }
        }
        animation();
    </script>
</body>

</html>

Musisz ustalić jakąś prędkość podstawową i po zabiciu wroga resetować ją u wojownika walczącego, bo prędkość Ci się kumuluje i dlatego jak z procy startuje wojownik :D

komentarz 18 listopada 2018 przez ptaku19 Użytkownik (800 p.)
Dzięki, nie dawno udało mi się to zrobić samemu. A propo nie wiem czy sprawdzałeś kod, który podałeś, ale trochę się buguje :D Ale i tak dzięki za pomoc:)
komentarz 18 listopada 2018 przez sefir Dyskutant (8,560 p.)
Cyrki się dzieją już nawet ja zmieniam rozmiar okna. Na większym trochę lepiej to działa :P
komentarz 18 listopada 2018 przez ptaku19 Użytkownik (800 p.)
Pewnie byłoby lepiej, żebym przyciski zrobil w CSS, albo zrobił skalowanie rozmiaru okna bo nie da się kliknąć czasem ;p
komentarz 18 listopada 2018 przez sefir Dyskutant (8,560 p.)
Problem z pozycją tego przycisku. A nie myślałeś by spróbować robić gierkę w jakiejś bibliotece? Przeważnie posiadają obsługiwanie zdarzeń typu kliknięcie w coś lub kolizja.
komentarz 18 listopada 2018 przez ptaku19 Użytkownik (800 p.)
Oczywiście myślałem, ale stwierdziłem, że chyba lepiej się poduczyć na czystym JS, a dopiero potem biblioteki. Gdybym tak od razu wskoczył to nie wiedziałbym co jest czystym JS a co biblioteką, a dwa to różni ludzie rożne biblioteki polecają i nie wiedziałbym co wybrac:D
komentarz 18 listopada 2018 przez sefir Dyskutant (8,560 p.)
W sumie racja. Ogólnie polecam Ci pobawić się klasami w js, czytelniejszy kod Ci się zrobi jak sobie popakujesz wszystko w klasy np gra, plansza, wojownik, wróg :)
komentarz 18 listopada 2018 przez ptaku19 Użytkownik (800 p.)
Nie wiem czy dobrze rozumiem, ale chodzi o metode class {} ? Z tego co wiem zawarta jest w ES6. Popraw mnie jeżeli źle myśle. Dodam że miałem zamiar dodać do tej gry magów itp. Stworzyć tablice Team = [] i przypisywać tu tablice z wojownikami itp.
komentarz 18 listopada 2018 przez sefir Dyskutant (8,560 p.)
Tak ES6, większość przeglądarek to już wspiera to nie ma co się męczyć ze starymi metodami  tworzenia klas, lepiej w nowych standardów się uczyć, zawsze jest się na bieżąco z technologią ;)

No to dobrą sprawą dobrze by było zrobić klasę Team i w niej pola jako tablice wojowników, magów itp
komentarz 18 listopada 2018 przez ptaku19 Użytkownik (800 p.)
Dzięki za rady, może za jakiś czas przerzucę się na ES6. Nie jesteś pierwszą osobą, która mi to radzi :D
komentarz 18 listopada 2018 przez sefir Dyskutant (8,560 p.)
Ja się przysiadłem do js'a właśnie kiedy już było w miarę spoko wsparcie do klas. Stara struktura kodu sprawia, że oczy mi krwawią xD
komentarz 18 listopada 2018 przez ptaku19 Użytkownik (800 p.)
A jeszcze takie pytanie z innej beczki ;P Nie wiem czy jesteś w stanie odpowiedzieć bez kodu

Gdy używam 'supermocy' spada 30 kwadratów, które blablabla... [...] i znikają po uderzeniu we wroga. I raz na jakiś czas, wyskakuje mi że jeden z kwadratów jest undefined. Czasem nie wyskakuje. Używam .splice(i,1). Czy możliwe jest, że komputer po prostu nie wyrabia gdy dwa uderzą w tym samym momencie?

1 odpowiedź

0 głosów
odpowiedź 18 listopada 2018 przez sefir Dyskutant (8,560 p.)

Jeżeli masz tablicę

a = ['a','b','c','d','e','f','g','h'];

i zrobisz np 

a.splice(2,1)

to

a = ["a", "b", "d", "e", "f", "g", "h"];

Mam nadzieję, że dostrzegasz w czym problem stosując 

.splice(i,1)

:)

komentarz 18 listopada 2018 przez ptaku19 Użytkownik (800 p.)
Dokładnie o to mi chodzi i tak się dzieje,kwadraty mi znikają,ale z nie wyjaśnionych przyczyn na 30 kwadratów czasem wyskoczy, że któryś jest undefined, a czasem nie. Chociaż i tak znikają wszystkie jak należy. Ale w konsoli mi się nie podoba ten błąd.Może komp nie wyrabia?
komentarz 18 listopada 2018 przez sefir Dyskutant (8,560 p.)
A jak zrobisz splice(1,1) zamiast splice(i,1) działa poprawnie?
komentarz 18 listopada 2018 przez ptaku19 Użytkownik (800 p.)
Potem zorientowałem się, że może źle kolizje wyznaczyłem, ale jak wpisałem splice(1,1) to usuwe prawie wszystkie meteoryty(kwadraty) (z 30) co jest dziwne bo spodziewalem się ze zniknie jeden.
komentarz 18 listopada 2018 przez sefir Dyskutant (8,560 p.)
Pewnie używasz tego w pętli, to może usunąć Ci wszystkie.
komentarz 18 listopada 2018 przez ptaku19 Użytkownik (800 p.)
Tak używam w pętli. Prawdopodobnie musze poprawić efekt kolizji

Podobne pytania

+2 głosów
3 odpowiedzi 644 wizyt
pytanie zadane 17 sierpnia 2020 w JavaScript przez Bakkit Dyskutant (7,600 p.)
+1 głos
2 odpowiedzi 520 wizyt
pytanie zadane 4 lipca 2020 w JavaScript przez Bakkit Dyskutant (7,600 p.)
0 głosów
0 odpowiedzi 115 wizyt

93,079 zapytań

142,042 odpowiedzi

321,449 komentarzy

62,424 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Wprowadzenie do ITsec, tom 2

Można już zamawiać tom 2 książki "Wprowadzenie do bezpieczeństwa IT" - będzie to około 650 stron wiedzy o ITsec (17 rozdziałów, 14 autorów, kolorowy druk).

Planowana premiera: 30.09.2024, zaś planowana wysyłka nastąpi w drugim tygodniu października 2024.

Warto preorderować, tym bardziej, iż mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy dodatkowe 15% zniżki! Dziękujemy zaprzyjaźnionej ekipie Sekuraka za kod dla naszej Społeczności!

...