Skocz do zawartości

Konrad-GM

Użytkownicy
  • Postów

    2 728
  • Dołączył

  • Ostatnia wizyta

  • Wygrane w rankingu

    44

Treść opublikowana przez Konrad-GM

  1. To super, że rozwiązałeś problem. Tak dodam jeszcze, że można sprawdzić, czy inst[ i ] nie jest ścianą (np. czy należy do grupy/teamu "walls"), jeżeli tak, to można przerwać pętlę break-em.
  2. Jaką wersję GameMakera używasz? Bodajże wersja 1.4 miała jakieś problemy z losowaniem liczb. Może ktoś bardziej obeznany wie coś więcej na ten temat. PS. Funkcję randomize(); musisz wywołać tylko raz, może w create jakiegoś obiektu?
  3. Moje skrypty są tylko przykładem kompozycji, pomysłem jak można rozwiązać problem z wielokrotnym dziedziczeniem. Nie bardzo rozumiem, dlaczego nie możesz wykonywać skryptu: if collision_line_list(x, y-hot_spot, x+sight_range, y-hot_spot, "grupa", false, true, spotted_list, true){ //seeing closest object var closest = spotted_list[|0]; spotted_point = closest.x-x; ds_list_clear(spotted_list); if (instance_exists(obj_player)) && (closest == obj_player.id) && !(status = state.attack){ // change state to attack status = state.attack; angry = 30; attack_buffer = 60; } else { // not seeing spotted_point = 0; } } W każdym obiekcie z osobna. Dodatkowo żeby sprawdzić "grupę" obiektów, to możesz zrobić coś takiego: var spotted_list = ds_list_create(); var instances = collision_line_list(x, y - hot_spot, x + sight_range, y - hot_spot, par_entities, false, true, spotted_list, true); var enemy_spotted = false; for (var i = 0; i < instances; i++) { var inst = spotted_list[| i]; // sprawdzamy przynaleznosc do teamu if (inst.team == "red" && status != state.attack) { enemy_spotted = true; spotted_point = inst.x - x; status = state.attack; angry = 30; attack_buffer = 60; break; } } if (!enemy_spotted) { spotted_point = 0; } ds_list_destroy(spotted_list); Jeżeli boisz się o optymalizację, możesz ten fragment kodu zamiast wykonywać w Step Event, np. ustawić Infinite Alarm (alarm ustawiający sam siebie) i np. uruchamiać ten skrypt co jakiś czas np. 100ms. (16ms to jedna klatka przy 60fps) Jeżeli chcesz dodać kilka team-ów, możesz zamiast zmiennej team dodawać zmienną teams jako tablicę, np. teams[0] = "red"; teams[1] = "green"; Stworzyć skrypt do sprawdzania zawartości tablicy: /// scr_array_includes(arr, value) var arr = argument0; var len = array_length_1d(arr); for (var i = 0; i < len ; i++) { if (arr[i] == argument1) { return true; } } return false; I wtedy powyższy skrypt z collision_line_list można przerobić na: var spotted_list = ds_list_create(); var instances = collision_line_list(x, y - hot_spot, x + sight_range, y - hot_spot, par_entities, false, true, spotted_list, true); var enemy_spotted = false; for (var i = 0; i < instances; i++) { var inst = spotted_list[| i]; // sprawdzamy przynaleznosc do teamu (z grupy teamow) if (scr_array_includes(inst.teams, "red") && status != state.attack) { enemy_spotted = true; spotted_point = inst.x - x; status = state.attack; angry = 30; attack_buffer = 60; break; } } if (!enemy_spotted) { spotted_point = 0; } ds_list_destroy(spotted_list);
  4. Cześć, może masz jakiś inny skrypt co powoduje znikanie obiektów - instance_destroy albo sprite ma animację która się nie loopuje i przeskakuje na pustą klatkę animacji. W debuggerze sprawdź, czy Ci znikają instancje z room-a.
  5. W zasadzie nie opisałeś problemu, a problem ze swoim rozwiązaniem, które z założenia może być niepoprawne. W GMie, tak jak w wielu innych językach programowania, paradygmat pojedynczego dziedziczenia jest dość powszechnie stosowany. Nie powinieneś myśleć w kategoriach wielodziedziczenia tak jak chociażby pozwala na to C++ tworząc logikę gry. Nawet w C++ wielodziedziczenie jest dość powszechnie uznawane jako złe podejście do rozwiązania większości problemów, częściej stosuje się po prostu kompozycje obiektów - proste i efektywne. Z tego co widzę, tworzysz jakiś obiekt "system" odpowiedzialny za obsługę innych instancji w jakiejś dziwacznej pętli - a w zasadzie nie widzę tutaj sensownego wyjaśnienia, dlaczego. A nie możesz przenieść po prostu logiki do tych obiektów? Możesz chociażby napisać skrypty scr_unit_* i komponować z nich obiekty, np.: /// scr_unit_create(team) team = argument0; some_crazy_variable = 10; /// scr_unit_step() some_crazy_variable++; /// scr_unit_draw() draw_self(); Potem w obiektach np. obj_enemy, obj_player wykonujesz odpowiednio skrypty scr_unit_create w Event Create, scr_unit_step w Event Step i scr_unit_draw w Event Draw.
  6. Faktycznie, nie przemyślałem tego, że w GML shadowing wbudowanych zmiennych może nie działać w taki sposób. A po uproszczeniu to w sumie można wyrzucić funkcję power: var t = floor(obj_gracz_widoczny.image_index) - 2; if (t*t - 4 == 0) { // kod }
  7. Można też w ten sposób: var t = floor(obj_gracz_widoczny.image_index); if (power(t - 2, 2) - 4 == 0) { // kod }
  8. Bo bez nawiasów zwraca Ci inta, ale jest to identyfikator skryptu. Czasami użyteczne jak masz skrypt i jego ID przypisujesz do zmiennej. Wtedy możesz wywoływać ten skrypt funkcją script_execute. Np. var skrypt = scr_arrow_can_hit; // nie ma tutaj nawiasów script_execute(skrypt, parametr1, parametr2);
  9. Cześć, nie wykonujesz skryptu, tylko porównujesz jego ID. Skrypty wywołujesz jak każdą inną funkcję, czyli w pierwszym if-ie daj: if(scr_arrow_can_hit() == 1) (...) Dodatkowo dodam od siebie, że zamiast używać other w skryptach, to powinieneś przesyłać dane poprzez parametry. Poprawia czytelność kodu oraz pozwala używać tego skryptu w różnych miejscach a nie tylko w Collision Event: ///scr_arrow_can_hit(array, against_id) var arr = argument0; var inst = argument1; var i, al = array_length_1d(arr); for(i=0; i<al; i++) { if(arr[i] == inst) return 0; } return 1; Potem używasz tego skryptu w ten sposób: if(scr_arrow_can_hit(other.array_objectID, id) == 1) (...)
  10. Kilka razy przyblokowałem się na krawędzi ściany, kilka razy musiałem zresetować przez to grę. Ten bug był dla mnie szczególnie uciążliwy. Poza tym to grało się całkiem przyjemnie, ale przez bugi przeszedłem do max 2 poziomu.
  11. Podejrzewam, że masz niepoprawnie skonfigurowane środowisko, spróbuj skonfigurować Android SDK jak opisano w artykule https://help.yoyogames.com/hc/en-us/articles/216753498-GameMaker-Studio-Android-SDK-and-NDK-setup- Edit: Możliwe też, że masz zainstalowany najnowszy pakiet NDK w wersji r19 - wprowadzili zmiany do toolchainów i może GMS ich już nie rozpoznawać. Jeżeli po skonfigurowaniu SDK dalej Ci nie działa, spróbuj przywrócić ndk-bundle do wersji r18b pobierając ze strony https://developer.android.com/ndk/downloads/older_releases.html i zastąp tym ndk-bundle w Android SDK.
  12. Też mam czasami problem z podłączeniem przez adb, wyłącza mi autoryzację od tak i muszę odłączyć i podłączyć, żeby mi znowu widziało urządzenie. A najgorzej to już jak próbuję przez tcpip podłączyć do sieci, żeby nie bawić się kablem (ale też bo ekran mi wariuje przez brak uziemienia w porcie usb, kek), to też co chwila mnie wywala, co drugi-trzeci build. Może to wina windowsa, bo na linuchu nie miałem takich problemów. Albo po prostu któraś aktualizacja SDK się spierdzieliła :/ Reasumując, adb raz działa, a raz leci sobie w kulki, co jest mega frustrujące i trzeba sprawdzać co chwila adb devices, czy wszystko gra.
  13. Cześć, treść błędu mówi, że próba komunikacji z urządzeniem nie powiodła się. Odpal narzędzie adb z konsoli komendą E:\SDK\platform-tools\adb.exe devices i sprawdź, czy urządzenie zostało autoryzowane i czy jest online. Jeżeli nie, to musisz wejść w ustawienia telefonu i włączyć debugowanie przez USB. Opcja ta znajduje się w ekranie opcje programistyczne. Jeżeli nie masz takiej opcji w ustawieniach, to trzeba wejść w informacje o urządzeniu i kliknąć kilka razy label numer kompilacji. Po podłączeniu USB i włączeniu ADB, na telefonie powinien pojawić się popup z autoryzacją komputera.
  14. Żeby utrzymać rozmiar backgrounda, to musiałbyś policzyć tzw. aspect ratio i bazować na nim podczas rysowania tła. Przypuśćmy, że masz backgrounda 1024x1024 i chcesz go rozciągnąć na całego viewa: // szerokosc okna jest wieksza niz jego wysokosc, liczymy aspect ratio jako: szerokosc / wysokosc if (view_wview[0] > view_hview[0]) { var aspect = view_wview[0] / view_hview[0]; var sx = ((view_wview[0] - view_hview[0]) / aspect) * 0.5; draw_background_stretched(bg_tlo, view_xview[0] - sx, view_yview[0], view_wview[0] + sx * 2.0, view_hview[0]); } // wysokosc okna jest wieksza niz jego szerokosc, liczymy aspct ratio jako: wysokosc / szerokosc else { var aspect = view_hview[0] / view_wview[0]; var sy = ((view_hview[0] - view_wview[0]) / aspect) * 0.5; draw_background_stretched(bg_tlo, view_xview[0], view_yview[0] - sy, view_wview[0], view_hview[0] + sy * 2.0); }
  15. Cześć, Draw GUI rysuje się zawsze na końcu, niezależnie od depth innych obiektów. Depth służy wtedy do sortowania innych elementów GUI. Nie widzę takiej możliwości, aby rysować GUI jako tło. https://docs.yoyogames.com/source/dadiospice/000_using gamemaker/events/draw gui event.html Twoja propozycja z dedykowanym obiektem jest jak najbardziej dobrym rozwiązaniem. Tylko, że zamiast draw_background_ext możesz użyć chociażby draw_background_stretched. Coś takiego: draw_background_stretched(bg_niebo, view_xview[0], view_yview[0], view_wview[0], view_hview[0])
  16. Dobra, rozwiązałem swój problem, ale głupotę zrobiłem, aż mi wstyd xD No ale może ktoś taki sam problem będzie miał, to dla potomnych podaję rozwiązanie: Otóż na stronie view.page, uwaga, importuję moduł rodzica session.module i dlatego router ponownie przekierowywał na list.page bo jest zdefiniowany w session.module i tak w kółko. Chciałem wcześniej importować komponenty rodzica, ale wyczytałem wcześniej już, że do tego potrzebny jest shared.module, tylko zapomniałem usunąć z view.page importu modułu session.module, kek.
  17. Cześć, ktoś się może zajmuje tutaj Angular-em? Bo prosiłbym o pomoc kogoś, kto miał jakieś doświadczenie z Router-em. Otóż Angular dziwnie się zachowuje, jak buduje routing aplikacji, chodzi dokładniej o child Routers w modułach. Podzieliłem podstrony aplikacji na moduły, które importują routing poprzez RouterModule.forChild i przekierowanie z modułu sessions.module na list.page działa, ale gdy przekierowuję na view.page z modułu sessions.module, to kompletnie się psuje routing i przekierowuje mnie znowu na list.page z dość dziwnym linkiem. Struktura aplikacji wygląda tak: src\app |- app-routing-module |- \home |- home.page |- \intro |- intro.page |- \sessions |- sessions.module |- \list |- list.page |- \view |- view.page |- \shared |- shared.module Kod głównego modułu app-routing.module: import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = [ { path: '', redirectTo: 'intro', pathMatch: 'full' }, { path: 'home', loadChildren: './home/home.module#HomePageModule' }, { path: 'intro', loadChildren: './intro/intro.module#IntroPageModule' }, { path: 'sessions', loadChildren: './sessions/sessions.module#SessionsModule' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule {} Kod modułu session.module wygląda tak: import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = [ { path: '', redirectTo: 'list', pathMatch: 'full' }, { path: 'list', loadChildren: './list/list.module#ListPageModule' }, { path: 'view', loadChildren: './view/view.module#ViewPageModule' } ]; @NgModule({ imports: [ CommonModule, RouterModule.forChild(routes), ] }) export class SessionsModule {} Przekierowuję na stronę view.page dyrektywą: [routerLink]="['/sessions', 'view']" Link przed przekierowaniem wygląda tak: http://localhost:8100/sessions/list Po kliknięciu na link, przekierowuje mnie do tej samej strony list.page, ale link wygląda już tak: http://localhost:8100/sessions/view/list Zauważyłem, że jak usunę kod odpowiedzialny za przekierowanie w module sessions.module: const routes: Routes = [ // { // path: '', // redirectTo: 'list', // pathMatch: 'full' // }, { path: 'list', loadChildren: './list/list.module#ListPageModule' }, { path: 'view', loadChildren: './view/view.module#ViewPageModule' } ]; To wtedy działa jak powinno, ale nie przekierowuje mnie na list.page jak przejdę na link /sessions (trzeba przekierowywać bezpośrednio na /sessions/list) Może ktoś ma jakiś pomysł, dlaczego w taki właśnie sposób zachowuje się Angular?
  18. Ok, poświęciłem trochę czasu i zrobiłem "brudny" przykład jak można to zrobić z Google Drive. Przykład tworzy przykładowy plik na drive. Ale nie widzę możliwości, żeby przeglądarka sama otwierała okno gry żeby wrócić :/ https://gmclan.org/up1717_16_OAuth2.html Przykład działa tak jak opisałem, otwiera url z oauth i tworzy bardzo mikro serwer "http". Potem czeka aż przyjdą dane z tym wymaganym parametrem `code`
  19. Cześć, możesz stworzyć np. zmienną globalną tj.: global.score_multiplier = 0.0; Potem np. przy zderzeniu z bonusem w Collision Event dodawać do tego mnożnika jakąś wartość i uruchamiać alarm u gracza bo bonus po usunięciu poprzez instance_destroy nie wywoła Ci alarmu, np: global.score_multiplier += 0.20; other.alarm[0] = room_speed * 60; W alarmie gracza odejmuj bądź resetuj mnożnik. Zależy też, czy chcesz obsługiwać kilka mnożników na raz, to wtedy zamiast alarmów możesz wykorzystać Step Event i ds_list/ds_grid jako timery bonusów. global.score_multiplier -= 0.20; Do dodawania punktów możesz stworzyć skrypt, który ułatwi Ci obsługę mnożnika w różnych miejscach projektu: /// scr_add_score(score) score += argument0 * (1.0 + max(0, global.score_multiplier));
  20. Tak naprawdę to interesuje Cię pierwsze logowanie OAuth2 w przeglądarce, ponieważ Twoja aplikacja wymaga odebrania odpowiedzi od serwera autoryzującego, dokładniej chodzi o parametr `code`. Potem z poziomu już aplikacji w GMie puszczasz POST (poprzez http_request) do tego serwera autoryzującego, żeby otrzymać `access_token` oraz `refresh_token`, które umożliwiają Ci dostęp do zasobów już bez konieczności dalszej ingerencji użytkownika. (https://alexbilbie.com/guide-to-oauth-2-grants/) Znalazłem coś takiego - https://developer.okta.com/blog/2018/07/16/oauth-2-command-line. Wygląda na dość legitne rozwiązanie, o ile na stronie w której tworzysz aplikację OAuth2 umożliwia Ci ona przekierowanie po localhoście (ustawienie parametru `redirect_uri` na localhost). Generalnie wygląda to tak (poza użyciem PHP ofc.) - otwierasz lokalny serwer w GMie (tworząc serwer za pomocą funkcji network_create_server_raw) i czekasz, aż odbierzesz dane z przekierowania (zwłaszcza na parametr `code`) od użytkownika gdy przekieruje go strona autoryzacji (użyj chociażby url_open żeby otworzyć przeglądarkę z endpointem autoryzacji). Pamiętaj, że serwer HTTP działa jak każdy inny serwer, po socketach, tyle, że w GMie otrzymasz cały bufor wraz z nagłówkami. Potem po odebraniu wiadomości zamykasz lokalny serwer i wysyłasz POSTa z parametrem `code` i otrzymujesz wymagane tokeny, kiedy wygaśnie `access_token`, odnawiasz go dzięki `refresh_token` ale już tylko przy użyciu POST i http_request. Sprawa inaczej wygląda, jak używasz eksportu HTML5, bo tutaj już masz serwer, wystarczy, że będziesz nasłuchiwał na kod i wymienisz go z aplikacją w GMie np. poprzez GMowe rozszerzenia javascriptowe. Pewnie byłbym w stanie jakiś przykład zrobić czy coś, ale to dość sporo zachodu a aktualnie czasu nie mam na zabawę
  21. Cześć, 1) jeżeli chodzi Ci o otworzenie przeglądarki w oknie gry, to jest to niemożliwe, bo GM nie ma wbudowanej przeglądarki www i mogę z pewnością rzec, że nie będzie miał jej w przyszłości. 2) ale jak sama się wyłączy? wątpię, żeby mogła, jak już otwierasz przeglądarkę np. poprzez execute_shell (nie wiem czy jeszcze działa w GMS), to nawet JS nie umożliwia Ci manipulowaniem okna przeglądarki. 3) przecież jest funkcja http_request, powinna działać też w eksporcie HTML5. Nie wiem, co próbujesz osiągnąć, IMO na 99% przypadków komunikacji z serwerem to http_request wystarczy.
  22. Też zdecydowanie polecam surface, bez takiego glScissor to chyba najlepsza opcja właśnie zrobić to na surface.
  23. Ok, przerobiłem swój kod żeby łamał słowa jak i linie, traktując ciąg spacji również jak słowo: /// scr_wrap_string(string,w) var text = argument0, len = argument1; var strlen = string_length(text); var i = 1, c = '', w = '', word = '', line = '', result = ''; while (i <= strlen) { c = string_char_at(text, i++); w = string_char_at(word, 1); // lamanie tekstu if (c == '#') { result += line + word + '#'; line = ''; word = ''; w = ''; continue; } // przelamujemy linie if (line != '' && string_width(line + word) > len) { result += line + '#'; line = ''; } // przelamujemy slowo if (string_width(word + c) > len) { line += word + '#'; word = ''; w = ''; } // budujemy slowo // ciag spacji traktujemy jako slowo if ((c == ' ' && (w == '' || w == ' ')) || (c != ' ' && w != ' ')) { word += c; } else { line += word; word = c; // linii nie zaczynamy spacja if (string_char_at(line, 1) == ' ') { line = ''; } } } result += line; result += word; return result; Jako, że teraz skrypt ten łamie tekst również w linii, nie potrzebujemy używać draw_text_ext a wystarczy draw_text: var text = scr_wrap_string("Lorem ipsum dolor sit amet, andverylongwordthatmustbesplitted", 100); draw_set_color(c_black); draw_rectangle(10, 10, 110, 210, false); draw_set_color(c_white); draw_text(10, 10, text);
  24. Cześć, możesz podzielić słowa które są dłuższe niż dana szerokość i rysować tekst za pomocą draw_text_ext. Skrypt do łamania słów: /// scr_wrap_words(string,w) var text = argument0, len = argument1; var strlen = string_length(text); var i = 1, c = '', word = '', result = ''; while (i < strlen + 1) { c = string_char_at(text, i++); if (string_width(word + c) > len) { word += '#'; } word += c; if (c == ' ') { result += word; word = ''; } } return result + word; W połączeniu z draw_draw_text: var text = scr_wrap_words("Lorem ipsum dolor sit amet, andverylongwordthatmustbesplitted.", 100); draw_set_color(c_black); draw_rectangle(10, 10, 110, 210, false); draw_set_color(c_white); draw_text_ext(10, 10, text, 15, 100); Rezultat powinien być wystarczający:
  25. Spróbuj użyć draw_text_ext, nie jestem pewien, czy nowa linia będzie wyśrodkowana, musisz sprawdzić. Jeżeli nie, to pozostaje podzielenie linii np. do tablicy i rysować wg. własnego algorytmu.
×
×
  • Dodaj nową pozycję...