Skocz do zawartości

Rudy

Użytkownicy
  • Postów

    154
  • Dołączył

  • Ostatnia wizyta

Treść opublikowana przez Rudy

  1. Moim zdaniem bez ingerencji w sprite sie nie da. Potrzebny ci tylko 1 image z całkowitą białością swego ludka. Potem w draw dodajesz linie: GML draw_set_alpha(jasnosc); draw_sprite(sprite_index, image tego obrazka, x, y); draw_set_alpha(1); Gorzej, jak koleś ma mieć białą animację... wtedy zrobiłbym to przez dodatkowy sprite, który będzie dokładnie taki sam, jak oryginał, tylko biały. Możesz też pokombinować z draw_set_blend_mode().
  2. Zgadzam się z Jakimem, jeżeli chodzi o tego typu gry kosmiczne to przetworzenie paru wzorów fizycznych jest chyba najlepszym pomysłem (nie mniej jednak jednym z trudniejszych). Ja bym to zrobił tak: - W obiekcie statku w create wpisz motion_set(0, 0); - Zrobić zwykłe sterowanie do okrętu (tzn sterowanie na strzałkach, czy myszą, jak tam masz, ale przez funkcję motion_add (dodawanie wektorów)) - Rzucił okiem na ten artykuł: Przyśpieszenie grawitacyjne - Za G wstaw co tam chcesz (chociażby 1), możesz tą wartością ustawić faktyczne przyśpieszenie grawitacyjne, potrzebne ci tylko masa planet i gwiazd (też użyj jakiejś umownej skali) - Niech każdy większy obiekt (np planeta) posiada w create wpisaną swoją masę, a w step ten wzór, który będzie przyciągał twój statek również przez funkcję motion_add(tutaj wpisz ten wzór, tutaj point_direction od statku do planety) W ten sposób masz wprowadzone do swojej gry namiastkę przyśpieszenie grawitacyjnego :) . Teraz zależy, czy chcesz, żeby to faktyczne miało tak wyglądać (obiekt sam nie wejdzie w ruch po okręgu, trzeba go ustawić w pierwszej prędkości kosmicznej do danego ciała niebieskiego, nie wiem czy widziałeś, jak np NASA to robi (obrót silników przeciwnie do lotu i full burn :) ))
  3. kod Muuuuczka w wersji klockowej: pamiętaj o zmianie nazw na własne z gry btw: pytanko do władców tego forum: nie dąłoby się dodać emotikonków z obrazkami częściej używanych klocków? Łatwiej by było pomóc ludziom, którzy nie chcą jeszcze brać się za kod :) .
  4. To ja jeszcze z mojej strony dodam, że niekoniecznie (chociaż zazwyczaj) musi podążać za graczem: Enable the use of View - włącz możliwość użycia viewów (normalnie jest tam jakiś domyślny tworzony) Lista Viewów - dostępnych masz 8 różnych Viewów Visible when room starts - jeśli chcesz, żeby View był aktywny od początku gry (roomu) zaznaczasz to (można go również uruchomić z poziomu kodu w trakcie gry) View in room - pozycja (x, y) oraz wymiary (width, height) widoku, który będzie pobierany z gry, by przenieść go na ekran (podajesz współrzędne w swojej grze ograniczające się do wielkości roomu) Port on screen - pozycja (x, y) oraz wymiary (width, height) widoku, który będzie umieszczony w oknie twojej gry (podajesz współrzędne pikseli na swoim monitorze (jeśli fullscreen), lub po lewego górnego rogu okna z grą) Jeśli w z viewu i z portu (tak samo h) nie będą się zgadzały, obraz zostanie przeskalowany. Dobre na chwilowy zoom ;) . Object Following - to co Bedziom powiedział, obiekt za którym może podążać widok H/VBor - odległość od krawędzi viewu którą - jeśli przekroczy obiekt, view ma ruszyć w jego kierunku. 0 oznacz tylko, jeśli obiekt dotknie krawędzi, minimum połowa wielkości viewu to znaczy, że obiekt będzie wycentrowany. H/VSp - prędkość podążania viewu z obiektem. -1 oznacza maksymalną prędkość.
  5. GIMP też dużo umie, chociaż nie dorównuje Photoshopowi ze wszystkim. Nie mniej jednak na obu programach, jeśli sie wyuczysz, można robić równie dobre grafiki na obu (chociaż Photoshop lepszy :) )
  6. Proponuję poszukać na YT użytkownika MyDesignStreet, nie robi co prawda tutoriali, ale wynik jest powalający, a i parę tricków da się wyciągnąć z jego filmów ;)
  7. Znaczy się elipsy łatwo zrobić, jedynie obrócone względem ekranu (np orbita przechodząca przez biegun) to trudniej. No i kwestia kolejności malowania... poza tym co mam nie znam lepszego sposobu (no jeszcze obiekt-orbita, ale to tez raczej nie... no i jeden obiekt ale nie wiem, czy nie trzeba mu było np do kolizji).
  8. Proszę: Orbity Sprawa trochę trudna do zrozumienia, ale próbuj, masz wszystko co chciałeś. Dodam tylko, że smugi w tej wersji mogą trochę mulić komputer. No ale są :)
  9. Temat chyba nie skończony... w każdym razie nie dla mnie :D Przebudowałem trochę kod, teraz działa na innej zasadzie, ale działa prawie idealnie, sprawdź: Przebudowana wersja Stara wersja niestety nie pozwalała na naprawę tych przeskoków. Może lepiej, teraz masz lepszy kod :) . Koniecznie przeczytaj komentarze, jak twoja gra wygląda inaczej.
  10. Poprawiona wersja Pozwoliłem sobie na parę większych zmian, wszystkie są opisane. Przejrzyj, zanalizuj, zrozum, działaj ;) .
  11. Nie do końca, dokładniej cos takiego: y -= lengthdir_y(dir,abs(vspeed)); znak minus, bo y się zmniejsza w górę. No i abs, bo tak do działania wejdą nam dwa minusy, a nam potrzebny tylko jeden (z sin, lub lengthdir). Co do tematu: Hmmm... najcudowniej by było dostać twój projekt. Wtedy wszystko byłoby jasno i wyraźnie pokazane. Na chwilę obecną mogę ci powiedzieć tak: - o ile te bloki nie nachodzą na siebie wszystko jest ok. - originy sprite'ów muszą być na środku i obiekt (a właściwie maska) powinien mieć kształt kwadratu. Jeśli originy nie masz na miejscu, a przestawianie to kupa roboty (np ze względu na gotową mapę) dodaj za other.x i other.y tyle pikseli (x i y) ile powinien mieć origin, wyjdzie na 0. (czyli ...x, y, other.x+16, other.y+16...) Jeśli maska nie ma kształtu kwadratu (np z powodu zaokrąglonych rogów sprite'a) trzeba ją ustawić: - jeśli ogólnie ściana ma kształt kwadratu (dokładniej, Bounding Box tworzy kwadrat), usuń ticka z Precise Collision Checking w opcjach sprite'a ściany - jeśli ściana ma kształt prostokąta: umieść tutaj wygląd tej ściany, zmieni sie wtedy kąty sprawdzania kierunku.
  12. Rudy

    Jak lepiej zapisać...

    Hmmm... tak gruntownej analizy o wyższości switch nad if'em nie robiłem, rozumuję to trochę inaczej. (bardziej łopatologicznie). Mamy takie dwa kawałki kodu: if (zmienna == 5) akcja1(); else if (zmienna == 7) akcja2(); else if (zmienna == 13) akcja3(); else if (zmienna == 19) akcja4(); else if (zmienna == 23) akcja5(); else akcja6(); switch (zmienna) { case 5: akcja1(); break; case 7: akcja2(); break; case 13: akcja3(); break; case 19: akcja4(); break; case 23: akcja5(); break; default: akcja6(); } Spróbujmy przeanalizować, na jakie odpowiedzi mielibyśmy odpowiedzieć, jeśli bylibyśmy procesorem*: Pierwszy kod: Czy zmienna jest równa 5? (tak - wykonujemy funkcję akcja1) Jeśli nie, to czy zmienna jest równa 7? (tak - wykonujemy funkcję akcja2) Jeśli nie, to czy zmienna jest równa 13? (tak - wykonujemy funkcję akcja3) Jeśli nie, to czy zmienna jest równa 19? (tak - wykonujemy funkcję akcja4) Jeśli nie, to czy zmienna jest równa 23? (tak - wykonujemy funkcję akcja5) Jeśli nie, wykonujemy funkcję akcja6. Drugi kod: Która z wartości pasuje do zmienna: 5, 7, 13, 19, 23, czy żadna z powyższych? (jeśli któraś z odpowiedzi pasuje, przenosimy się do jej "znacznika" i wykonujemy operację do końca klamry, lub napotkania break). I dochodzimy do setna rozważań: gdzie jest mniej pytań? Już na pierwszy rzut oka widać, że w drugim, jest tylko jedno pytanie w przeciwieństwie do pierwszego sposobu, gdzie pytań jest aż pięć. Jednakże, ten rodzaj pytania wymusza pewne zasady, które można również zauważyć w C++: - możemy tylko przyrównywać liczby, nie sprawdzimy zakresu liczb (nierówności), czy bardziej skomplikowanych działań. - wartość podana w case musi być stała, to oznacza, że nie możemy wpisać tam niestałej zmiennej. Przez to w niektórych przypadkach nie możemy użyć switch (można oczywiście wymienić wszystkie liczby z zakresu, o ile nie będzie on zbyt duży) i musimy posiłkować się ciągiem if ... else. * - ten sposób rozumowania nijak się ma do sposobu Willa, który podał, jak faktycznie działa procesor. Jednak na tym przyładzie można zastosować takie porównanie.
  13. Rudy

    Jak lepiej zapisać...

    Aha :D W sumie można i tak, chociaż rozmieszczenie liczb i szybkość będzie w obu przypadkach taka sama (albo za mało wiem o C++) Zrobię to w ten sposób. Skorzystam z Twojej pomocy i zamknę to do jednego indeksu. W przypadku, gdy będzie więcej wartości niż "pustych kratek" skorzystam z tablicy. A jeśli odwrotnie - funkcja ze switch. Wielkie dzięki za pomoc, już chyba któryś raz z kolei pomagasz mi w C++. :)
  14. Rudy

    Jak lepiej zapisać...

    Kartka jest stała, dane to liczby mieszczące sie w jednym bajcie, są losowe. Ciągle nie widzę tej jednowymiarowej tablicy, jak by ona miała działać. Mógłbyś mi to pokazać na przykładzie? Weźmy tą pierwszą tablicę z obrazka powyżej. N to pusta kratka. U mnie wyglądałoby to tak: array[4][4] = {{5, 8, 0xFF, 11} , {10, 4, 2, 0xFF} , {0xFF, 0, 6, 9} , {3, 7, 0xFF, 1}}; i wtedy x kratki byłoby pierwszym indeksem, y kratki drugim, a podczas wyświetlania (pytania użytkownika) 0xFF traktowałby jako pustą. Jeśli chcesz, możesz powiedzieć, że Ci się nie chce, trochę odeszliśmy od tematu, a faktyczny efekt to tylko zwiększenie mojej wiedzy (kosztem twojego czasu).
  15. Rudy

    Jak lepiej zapisać...

    Dlatego ich nie użyję, szukałem tylko sposobu, jak najprościej przedstawić mój problem :) Makro byłoby najszybsze, lecz chyba tutaj nie dałoby rady, chodzi właśnie o te dwie liczby... Spróbuję jeszcze inaczej :) . Wyobraź sobie kartkę w kratkę. Na tej kartce, w kratkach napisane są chaotycznie rozłożone liczby. Jak coś takiego odwzorowałbyś na komputerze? Parę zmiennych pomocniczych (wielkość kartki, wielkość jednej kratki, żeby odmalować samą kartkę)... no i właśnie, co z tymi liczbami. Jakbyś je namalował wiedząc, że nie możesz wymienić tylko tych liczb na kartce (załóżmy, że użytkownik może zapytać się, co znajduje się w tej kratce, a komputer ma odpowiedzieć (jeśli nie ma tam liczby) że kratka jest pusta). Odp: musisz mieć te liczby (i puste kratki) zapisane w tablicy, która pobiera do indeksów x i y. W momencie zapytania zwraca liczbę znajdującą się pod tymi indeksami, i jeśli jest to liczba nieużywana (jak np 0xFF) to pisze, że jest pusta kratka. Chyba, że masz lepszy pomysł.
  16. Rudy

    Jak lepiej zapisać...

    Właśnie chodzi o wielowymiarowe cuda, bo wartość zwracana zależy od 2 liczb i w górę. Tzn foo(0,2) != foo(0,5) (albo foo[0][2] != foo[0][5]). Co do przetwarzania - jedna seria w całym działaniu, około 30 razy. Ehh... chyba nie rozumiesz... jeszcze inaczej. if (a == 0 && b == 0) return 2; if (a == 0 && b == 1) return 5; if (a == 0 && b == 2) return 0; itd, itd. aż wykorzysta się wszystkie możliwości. Chodzi o to, że z dwóch podanych liczb funkcja/tablica zwraca id, który identyfikuje te zestawienie liczb. Id nie są po kolei, niektóre sie powtarzają, niektóre nigdy nie będą użyte. Tylko tyle. Jeszcze inaczej: a ¤ b = c, gdzie a i b należy do {0,1,2,3,4}, a c to jakaś liczba (czyli te id).
  17. Rudy

    Jak lepiej zapisać...

    Eee... znaczy się chodzi o coś takiego :D Mamy sobie takie liczby posegregowane wg x i y (N to liczby, które nigdy nie będą użyte (jeśli użytkownik będzie postępował zgodnie z podanymi instrukcjami (czyli prawie nigdy :D ) ). W jedynce to wiadomo, tablica najlepsza, ale co z dwójką? Też tablica? lepiej chyba funkcja. Ale wtedy mieszamy sposoby w jednym projekcie. Więc co lepiej? Dokładniej: Dostaję dwie liczby a mam wypisać jedną, takie jakby id tego zestawienia liczb. Niektóre nie będą nigdy wpisane.
  18. Rudy

    Jak lepiej zapisać...

    Witam. Więc tak, piszę pewien program i natrafiłem na miejsce, gdzie muszę z dwóch zmiennych (np x, y należące do naturalnych, wszystkie mające jakąś wartość) stworzyć jedną (coś w rodzaju id punktu). Jak napisałem wcześniej każdy punkt posiada jakąś znaczącą wartość i nijak nie da sie zapisać wzoru ogólnego. No i mam dylemat... załóżmy, że x i y to liczby od 0 do 4. Który kod byłby lepszy (tzn szybszy, mniej pamięcio-czaso-żerny): Kandydat 1: unsigned char foo(unsigned char x, unsigned char y) { switch (x) { case 0: switch (y) { case 0: return 2; case 1: return 5; case 2: return 0; case 3: return 10; case 4: return 3; } case 1: switch (y) { case 0: return 7; case 1: return 24; ... } } } Kandydat 2: const unsigned char foo[5][5] = {{2,5,0,10,3},{7,24, ... }}; Na pierwszy rzut oka 2 jest lepsza, no ale pomyślmy. Tablica zajmuje obecnie 25B. Póki jest mała wszystko jest ok. A co jak o zwracanej wartości będzie decydowały 3 liczby i 7/9 liczb będzie zwracała wartość 0xFF czyli "nieinteresującą" nas? Nie wiem gdzie przesiaduje informacja o definicji funkcji ale wiem że taka tablica zabierze mi 125B w pamięci RAMu. No więc co lepsze? Czy robić po prostu wielgachne tablice, czy może funkcje... a może makra z parametrem?
  19. Rudy

    Gry RTS

    Dobre strategie? Homeworld 1 (1999) i 2 (2003) :) EDIT: Tyle, że nie w stylu Age of Empires :D Za szybko :) .
  20. Co do kolizji ze ścianami (zapomniałem odświeżyć stronki :D ) Spróbuj ten kod wstawić do obiektu bohatera to zdarzenia kolizji ze ścianą: GML // zapisanie informacji o kącie zderzenia var dir; dir = point_direction(x, y, other.x, other.y); // podział na poszczególne reakcje if ((dir >= 45 && dir <= 135) || (dir >= 225 && dir <= 315)) y += abs(vspeed)*sin(degtorad(dir)); if ((dir >= 135 && dir <= 225) || (dir >= 315 || dir <= 45)) x -= abs(hspeed)*cos(degtorad(dir)); Mam nadzieję, że o to chodzi. Działa na zasadzie odbicia, ale tylko składowej prędkości i tylko o wymaganą wartość. Ale musisz mieć do tego originy w środku ścian i w miarę kwadratowe maski (obrazki do sprawdzania kolizji). Tylko wtedy działa, za to efekt jest taki jak powinien być. Co do kolizji ze ścieżką - niestety nie pomogę, nie znam się na ścieżkach.
  21. Nie usunąłeś może kiedyś przypadkiem tych plików z klockami? Tylko tyle mi się nasuwa, reinstalka powinna wtedy pomóc.
  22. Ciebie się nie chce nic robić, a nam niby ma się chcieć? A potem kto się pod tym podpisze... Ambient to jakby światło słoneczne, wszechobecne. O ile nie masz innych świateł, wystarczy przyciemnić tylko główne światło, by wszystko stało się czarne. Czyli zmniejszasz intensywność ambientu aż do 0. Proste.
  23. Jak wiadomo do programowania trzeba zkwantować naturę :) . Podziel linę na tablicę punktów. Punkty muszą być oddalone o tą samą odległość od siebie. Im mniejsza odległość między punktami tym lepsza dokładność kosztem większej ilości obliczeń. Teraz traktuj każdy punkt jak obiekt (czyli np. działa na niego siła grawitacji) a między puntami rysuj linię. Pozostaje ci tylko zrobić odpowiedni kod, który będzie przesuwał punkty o niewielkie odległości tak, by odległość między punktami zawsze była taka sama. I teraz, jeżeli chwycisz jeden z punktów (czyli m.in zniwelujesz działanie siły grawitacji) pozostałe punkty dalej będą spadać. Ale twój kod nie pozwoli im na zbyt daleki odlot i w efekcie powstanie efekt linii :) . Jedyny problem to ów kod. Poniższy kod pokazuje uogólnienie problemu. Ruchomy jest tylko pierwszy punkt. Ale może ci wystarczy: GML (Create) line_num = get_integer("Podaj liczbę punktów na linii", 10)+1; // liczba punktów line_length = get_integer("Podaj długość linii", 200)/(line_num-1); // odległość między punktami line_grav = 10; // przyśpieszenie grawitacyjne // tworzenie tablicy punktów for (i = 0; i < line_num; i += 1) { line_x = 100+line_length*i; line_y = 100; } // zmienne zaznaczenia point_act = -1; // mouse_over point_sel = -1; // mouse_select</span></span> GML (Step) // ---------- zaznaczanie ---------- // // zerowanie zaznaczenia przed aktualizacją point_act = -1; if (!mouse_check_button(mb_left)) point_sel = -1; // wyszukiwanie zaznaczenia i najechania for (i = 0; i < line_num; i += 1) if (point_distance(line_x, line_y, mouse_x, mouse_y) < 5) { if (mouse_check_button_pressed(mb_left)) point_sel = i; point_act = i; } // przesunięcie punktu do myszki (jeśli zaznaczony) if (point_sel >= 0) { line_x[point_sel] = mouse_x; line_y[point_sel] = mouse_y; } // ---------- kontrola odległości ---------- // // pętla przyjmuje, że pierwszy punkt jest nieruchomy i tylko jego można przesuwać // działanie następujące: // zaczynamy od drugiego punktu (pierwszy niezmienny) for (i = 1; i < line_num; i += 1) { // przesuwamy punkt zgodnie z grawitacją line_y += line_grav; // obliczamy, o ile trzeba przesunąć punkt do poprzedniego punktu point_dist = point_distance(line_x, line_y, line_x[i-1], line_y[i-1])-line_length; // ustalamy kąt przesunięcia point_dir = point_direction(line_x, line_y, line_x[i-1], line_y[i-1]); // przesuwamy ów punkt tam gdzie powinien być line_x += lengthdir_x(point_dist, point_dir); line_y += lengthdir_y(point_dist, point_dir); } GML (Draw) // efekt zaznaczenia if (point_sel >= 0) { draw_set_color(c_gray); draw_circle(line_x[point_sel], line_y[point_sel], 3, false); } // efekt najechania else if (point_act >= 0) { draw_set_color(c_ltgray); draw_circle(line_x[point_act], line_y[point_act], 3, false); } draw_set_color(c_black); // malowanie dwóch linii pierwszego punktu draw_line(line_x[0]-10, line_y[0], line_x[0]+10, line_y[0]); draw_line(line_x[0], line_y[0]-10, line_x[0], line_y[0]+10); // malowanie linii między punktami for (i = 1; i < line_num; i += 1) draw_line_width(line_x[i-1], line_y[i-1], line_x, line_y, 3); // malowanie punktów for (i = 0; i < line_num; i += 1) draw_circle(line_x, line_y, 3, true); A co na to fizyka? Ona rozwiązuje to w ten sposób. Jeśli odległość jest większa niż ma być, "punkty" przyciągane są z tą samą siłą do środka tego odcinka, by odległość wynosiła odpowiednio dużo. Jeśli punkt ma być nieruchomy, to można uznać, że ta siła przechodzi na drugi punkt i tylko on się rusza. Sposób dobry poza faktem, że te punkty bez przerwy są przesuwane. Jeśli jeden odcinek pasuje to po obliczeniu tego obok nie będzie pasował. Powstaje pętla nieskończona, nigdy odległość nie będzie równa dokładnie 100. Można zrobić oczywiście tylko kilka razy tą pętle i będzie jakiś przybliżony wynik, ale... przyrody całkiem nie odwzorujesz :) .
  24. Hehe, a ja już go uczę, a jedynym jego środkiem zapłaty są jego wyniki :P .
  25. Ja bym powiedział, że chodzi mu o coś innego. Żeby wróg ślizgał się po ścianie, tzn po kolizji szedł równolegle ze ścianą z odpowiednio zmienioną prędkością. Napisałem to w GM (wersja 8): O tutaj. Sprawdź, czy o to chodziło.
×
×
  • Dodaj nową pozycję...