Skocz do zawartości

Kuzyn

Użytkownicy
  • Postów

    9
  • Dołączył

  • Ostatnia wizyta

  • Wygrane w rankingu

    3

Ostatnia wygrana Kuzyn w dniu 20 Czerwca 2023

Użytkownicy przyznają Kuzyn punkty reputacji!

Informacje

  • Użytkownik GameMaker Studio 2
    Tak
  • Użytkownik GameMaker Studio
    Tak
  • Użytkownik GameMaker 8
    Nie
  • Użytkownik GameMaker 7 i wcześniejszych wersji
    Nie
  • Użytkownik Unity
    Nie
  • Użytkownik Godot
    Nie
  • Steam
    kuzynn

O mnie

Ostatnie wizyty

519 wyświetleń profilu

Osiągnięcia Kuzyn

Chicken

Chicken (1/13)

8

Reputacja

  1. Uprzedziłeś mnie z odpowiedzią Dzięki za pomoc i dodam jeszcze, czemu objCitizen nie mógł znaleźć ścieżki. Ano dlatego, że źle ustawione maski budynków zajmowały zbyt dużo komórek w gridzie i cel wskazany dla objCitizen był w niedostępnej komórce. Także uczulam na sprawdzanie tego również!
  2. Cześć, przychodzę z nieco bardziej skomplikowanym problemem, ale już nie mam w głowie żadnych innych pomysłów jak go rozwiązać. Postaram się jak najdokładniej opisać co jest nie tak. Co jest nie tak? Moje obiekty objCitizen nie przechodzą ścieżki od punktu A do punktu B w drugiej fazie swojej pracy, co powoduje, że kod z warunkiem (path_position == 1) wykonuje się natychmiastowo. A jak powinno być? Obiekt objBuilding na początku szuka wolnego objCitizen, który mógłby dla niego pracować. Jeśli go znajdzie, przydziela go do siebie. Następnie tenże objBuilding sprawdza czy ma wolne miejsce na składzie, jeśli tak to z puli przypisanych pracowników (na ten moment maks. 1) wybiera sobie pierwszego wolnego, wynajduje mu pracę i wytycza mu ścieżkę do tej pracy. objCitizen w tym momencie rusza do miejsca pracy i wykonuje swoją pracę, po czym zgłasza, że ją wykonał. Wtedy objBuilding woła go z powrotem do siebie, żeby wrócił z tym wynikiem pracy. (to nie działa) objCitizen wraca, oddaje na skład wynik swojej pracy i jest gotowy na podjęcie nowej, wyznaczonej przez objBuilding. Czy wcześniej to działało? Tak i nawet dzieliłem się tym na discordzie GMClanu https://streamable.com/qx78pz Natomiast w momencie gdy dodałem drugi rodzaj budynku i nieco pozmieniałem kod, całość się wysypała. Opierając się na przykładzie z wideo, objCitizen zamiast odnosić drewno do składu, zbiera po prostu jedno po drugim, oddając je na odległość do składu i staje w miejscu. Co do tej pory sprawdziłem i co mogę jeszcze zrobić? Opcją ostateczną zostaje dla mnie cofnięcie się do poprzedniej wersji projektu z githuba, chciałbym rozwiązać ten problem, a nie cofać wszystko. Sprawdzałem czy objCitizen ma poprawnie wyznaczony cel, próbowałem podmieniać różne warunki, sprawdzałem czy parametry ścieżki w postaci celu są poprawne i tak, wszystko się zgadzało. Zanim wkleję kod, pokrótce rozpiszę zmienne, które mają kontrolować zachowanie objCitizen i objBuilding i jak po kolei powinny się zmieniać. objBuilding w Step Evencie ma switcha, który zmienia mu stany. Stan odpowiedzialny za wyznaczanie pracy ma taki kod: function buildingStateWork(){ if (building.buildingTaskAssigned == false) { switch (building.buildingType) { case "Utility": #region UTILITY switch (building.buildingUtilityType) { #region WAREHOUSE // Check if building is Warehouse. case "Warehouse": //Check if the building got any space left. if (building.buildingStorageFull == false) { //If building is full, do not perform this code for performance. for (var i = 0; i + 1 < array_length(building.buildingStorage); i += 2) { if (building.buildingStorage[@ i][1] < building.buildingStorage[@ i + 1][1]) { //There is space for something. For this example, simplify it to wood only. //Look for somebody to bring items. for (var i = 0; i < array_length(building.buildingWorkerList); i++) { //Check if the workers are already occupied doing something or not. if (building.buildingWorkerList[i].citizen.citizenOccupied == false and building.buildingWorkerList[i].citizen.citizenBackFromTask == false) { //Check for items to be picked up in range. var AvailableItems = ds_list_create(); //Store there items that will be found in range. var CurrentWorker = building.buildingWorkerList[i]; //Store id of the worker. collision_circle_list(x, y, building.buildingWorkRange, objectItem, false, true, AvailableItems, true); //Find items. for (var i = 0; i < ds_list_size(AvailableItems); i++) { if (AvailableItems[| i].item.itemName == "Wood log") { CurrentWorker.citizen.citizenOccupied = true ; CurrentWorker.citizen.citizenGoToTask = true ; CurrentWorker.citizen.citizenTarget = AvailableItems[| i].id; CurrentWorker.citizen.citizenTargetX = AvailableItems[| i].x ; CurrentWorker.citizen.citizenTargetY = AvailableItems[| i].y ; CurrentWorker.pathStarted = false ; with (CurrentWorker) { citizenPath = path_add(); } CurrentWorker.citizen.citizenState = CITIZEN_STATES.MOVE ; building.buildingTaskAssigned = true ; break; } else { break; } } } } } else { //There is no space, so there is no need to look out for resources to be picked up/send worker. building.buildingStorageFull = true; //This needs to be set to false once somebody picks up something from there. break; } } } break; //WAREHOUSE #endregion } #endregion break; case "Production": #region PRODUCTION //Check if the building got any space left. if (building.buildingOutputAmount < building.buildingOutputAmountMax) { //Look for somebody to cut the tree. for (var i = 0; i < array_length(building.buildingWorkerList); i++) { //Check if the workers are already occupied doing something or not. if (building.buildingWorkerList[i].citizen.citizenOccupied == false and building.buildingWorkerList[i].citizen.citizenBackFromTask == false) { //Check for trees to be cut down. var AvailableResources = ds_list_create(); //Store there trees that will be found in range. var CurrentWorker = building.buildingWorkerList[i]; //Store id of the worker. collision_circle_list(x, y, building.buildingWorkRange, building.buildingProductionTarget, false, true, AvailableResources, true); //Find trees. for (var i = 0; i < ds_list_size(AvailableResources); i++) { if (AvailableResources[| i].tree.treeGrowthStage == 2) { CurrentWorker.citizen.citizenVocation = "Woodcutter" ; CurrentWorker.citizen.citizenOccupied = true ; CurrentWorker.citizen.citizenGoToTask = true ; CurrentWorker.citizen.citizenTarget = AvailableResources[| i].id ; CurrentWorker.citizen.citizenTargetX = AvailableResources[| i].x ; CurrentWorker.citizen.citizenTargetY = AvailableResources[| i].y + AvailableResources[| i].tree.treeYOffset ; CurrentWorker.pathStarted = false ; with (CurrentWorker) { citizenPath = path_add(); } CurrentWorker.citizen.citizenState = CITIZEN_STATES.MOVE ; building.buildingTaskAssigned = true ; break; } } } } } else { //There is no space, so there is no need to look out for resources to be picked up/send worker. building.buildingState = BUILDING_STATES.HOLD; //This needs to be set to false once somebody picks up something from there. } #endregion break; } } else { switch (building.buildingType) { case "Utility": #region UTILITY switch (building.buildingUtilityType) { #region WAREHOUSE // Check if building is Warehouse. case "Warehouse": for (var i = 0; i < array_length(building.buildingWorkerList); i++) { var CurrentWorker = building.buildingWorkerList[i]; if (CurrentWorker.citizen.citizenOccupied == false and CurrentWorker.citizen.citizenBackFromTask == true) { CurrentWorker.citizen.citizenOccupied = true ; CurrentWorker.citizen.citizenTarget = id ; CurrentWorker.citizen.citizenTargetX = x ; CurrentWorker.citizen.citizenTargetY = y+building.buildingYOffset ; CurrentWorker.pathStarted = false ; with (CurrentWorker) { citizenPath = path_add(); } CurrentWorker.citizen.citizenState = CITIZEN_STATES.MOVE ; break; } } break; #endregion } #endregion break; case "Production": #region PRODUCTION for (var i = 0; i < array_length(building.buildingWorkerList); i++) { var CurrentWorker = building.buildingWorkerList[i]; if (CurrentWorker.citizen.citizenOccupied == false and CurrentWorker.citizen.citizenBackFromTask == true) { CurrentWorker.citizen.citizenOccupied = true ; CurrentWorker.citizen.citizenTarget = id ; CurrentWorker.citizen.citizenTargetX = x ; CurrentWorker.citizen.citizenTargetY = y+building.buildingYOffset ; CurrentWorker.pathStarted = false ; with (CurrentWorker) { citizenPath = path_add(); } CurrentWorker.citizen.citizenState = CITIZEN_STATES.MOVE ; break; } } #endregion break; } //Switch } //Else } //Function objCitizen działa na podobnej zasadzie, w Step Evencie jest switch. Kod odpowiedzialny za pracę poniżej: function citizenStateWork(){ switch (citizen.citizenVocation) { case "Mover": //Citizen is moving to the resource. if (citizen.citizenGoToTask == true) { if collision_circle(x, y, citizen.citizenPickupRange, citizen.citizenTarget, false, true) { citizen.citizenGoToTask = false ; citizen.citizenBackFromTask = true ; citizen.citizenOccupied = false ; citizen.citizenCarrying = true ; citizen.citizenCargo = citizen.citizenTarget.item; instance_destroy(citizen.citizenTarget); } //Add else if someone picks resource before Citizen, reset back to go to the building. } if (citizen.citizenCarrying == true and citizen.citizenBackFromTask == false) { citizen.citizenOccupied = false; citizen.citizenCarrying = false; var CarriedItem = citizen.citizenCargo.itemName; citizen.citizenCargo = 0; //Find carried item in a storage and add to the pool. for (var i = 0; i < array_length(citizen.citizenAssigned.building.buildingStorage); i++) { if (CarriedItem == citizen.citizenAssigned.building.buildingStorage[i][0]) { citizen.citizenAssigned.building.buildingStorage[i][1] += 1; } } //Let building find another task. citizen.citizenAssigned.building.buildingTaskAssigned = false; } break; case "Woodcutter": //Citizen is moving to the building back with the resource. if (citizen.citizenGoToTask == true) { if collision_circle(x, y, citizen.citizenPickupRange, citizen.citizenTarget, false, true) { //Cut the tree here.f if (workTimerOn == false and citizen.citizenTarget.tree.treeHealth > 0) { workTimerOn = true; citizen.citizenTarget.tree.treeHealth = citizen.citizenTarget.tree.treeHealth - 1; time_source_start(workTimer); } //Remove the tree and add resource to worker. if (citizen.citizenTarget.tree.treeHealth <= 0) { citizen.citizenOccupied = false ; citizen.citizenGoToTask = false ; citizen.citizenBackFromTask = true ; citizen.citizenCarrying = true ; var outputToPick = instance_create_layer(citizen.citizenTargetX, citizen.citizenTargetY, "instanceSystem", objectItem); with (outputToPick) { item = new WoodLog() ; image_speed = 0 ; sprite_index = item.itemSprite ; image_index = item.itemSpriteI ; } instance_destroy(citizen.citizenTarget); citizen.citizenCargo = outputToPick.item; instance_destroy(outputToPick); } } //Add else if someone picks tree before Citizen, reset back to go to the building. } if (citizen.citizenCarrying == true and citizen.citizenBackFromTask == false) { citizen.citizenOccupied = false; citizen.citizenCarrying = false; var CarriedItem = citizen.citizenCargo.itemName; citizen.citizenCargo = 0; //Add carried item to the pool, check before if right item is coming in. if (CarriedItem == citizen.citizenAssigned.building.buildingOutput) { citizen.citizenAssigned.building.buildingOutputAmount += 1; } //Let building find another task. citizen.citizenAssigned.building.buildingTaskAssigned = false; } break; } } A na końcu kod odpowiedzialny za przemieszczenia objCitizen: function citizenStateMove(){ if (pathStarted == false) { if mp_grid_path( systemPathfinding.pathfindingCitizenGrid, citizenPath, x, y, citizen.citizenTargetX, citizen.citizenTargetY, 1) { path_start(citizenPath, citizen.citizenSpeed, path_action_stop, true); pathStarted = true; } } if (path_position == 1) { if (citizen.citizenOccupied == true and citizen.citizenBackFromTask == true) { citizen.citizenBackFromTask = false; } path_delete(citizenPath); pathStarted = false ; citizen.citizenState = CITIZEN_STATES.WORK ; } }
  3. Kuzyn

    Męczymy AI z ChatGPT

    Ja to z nim zawsze rozmawiam na zasadzie: 🤣 I tak, sugestia go nakierowuje na jakieś rozwiązania. Trzeba mu jak najwięcej mówić o tym co nie działa, jak ma działać a jaki na dany moment jest rezultat. Wtedy może wyciągać jakieś wnioski. Ale trzeba być precyzyjnym, bo może np. początkowe założenia zmienić.
  4. Kuzyn

    Męczymy AI z ChatGPT

    Osobiście przy GM użyłem go raz do systemu kolizji (prosiłem go o przerobienie istniejącego kodu z dodatkowymi warunkami) i udało mu się, a danych wejściowych miał dosyć mało. Później wprowadzili move_and_collide i wszystko poszło na marne 🤣 Natomiast bardzo często używałem go w pracy do tworzenia skryptów w google sheets (apps script), które później można użyć do obrabiania danych czy jakichś tam spraw organizacyjnych. Jak ktoś ma zamiar używać tego częściej to moje spostrzeżenia są takie: Bot będzie starał się stworzyć kod dosłownie tak, jak mu to napisaliście. Jeśli zastosowaliście jakieś skróty myślowe, to będzie się to rozjeżdżać z rzeczywistością. Najlepiej rozpisać mu wszystko w krokach z jak największą ilością danych, żeby rezultat był zbliżony do tego co chcecie osiągnąć. Nie raz widziałem na Twitterze czy wręcz artykuły na stronach krzyczące, że głupi bot nie robi tego co sobie ktoś wymyślił, więc się z nim schowajcie bo żaden z niego pożytek. No tak, tylko nikomu nie przyszło do głowy, że on nie jest od interpretacji myśli, tylko tego co mu człowiek literkami napisał na wejściu. Często pomaga pisanie do niego wymieniając konkretne działania od myślników albo pisanie 1 by 1. Najpierw prosimy go o coś ogólnego/pierwszego. Jak się uda wygenerować dobry kod i działa to lecimy dalej. Nie zawsze radzi sobie ze zrobieniem wszystkiego na raz, ale to raczej kwestia tego o czym pisałem powyżej. On interpretuje tylko tekst, nie nasze zamiary. Najprawdopodobniej bot będzie używał najprostszych metod na osiągnięcie celu, co w przypadku takiego apps script odbija się na wydajności. Można prosić go o optymalizowanie danego rozwiązania, ale nie zawsze się to sprawdza bo on będzie próbował optymalizować to co już ma, a nie stosować alternatywne rozwiązania. Przykładowo: mamy 1000 wierszy po kilka kolumn z danymi i chcemy je przerobić. Jeśli napiszemy tak wprost do bota, to będzie budował kod tak, żeby operować na wierszach i kolumnach i powtarzać dane akcje na arkuszu. Nie przyjdzie mu do głowy, że arraye będą szybsze i lepiej jest dane zapisać do arraya, obrobić je tam i później wypluć rezultat. Pomijając, że samo działanie na arkuszach jest wolne, to po 400 wierszach drastycznie spada prędkość pracy skryptów. Bot tego nie wie, więc warto sugerować mu korzystanie z arraya w takich sytuacjach.
  5. Moja opinia o ciemnym motywie na PC. 1. Kolor tekstu w nawigacji zmieniłbym na biały. Strasznie się to zlewa z takim tłem, wygląda jak coś nieaktywnego/nieklikalnego. 2. Albo jaśniejszy czerwony, albo jakieś inne tło/kolor tekstu dla tego guziczka. 3. Główne nazwy zmieniłbym na białe a oznaczenia dat ewentualnie na te niebieskie, ciężko się czyta niebieski tekst, jeszcze na ciemnym tle. 4. Tutaj bym dał na datę taki sam kolor jaki mógłby być w punkcie 3. 5. Tutaj podobnie, niech oznaczenia czasowe mają ten sam kolor. 6. Tekst zdecydowanie na biało, nicki może białym boldem tak jak jest u góry przy discordzie, a czas na niebiesko.
  6. Spotkałem się z zabawą w familiadę na weselach. Może wzrost zainteresowania stąd wynika, że osoby planujące wzięcie ślubu, nie chcą płacić za "wodzirejów z profesjonalnym sprzętem" do zabawy w familiadę i chcą sobie to zorganizować na własną rękę 😄
  7. Tak jak mówili poprzednicy, super że widać efekt końcowy na samym początku, bez owijania w bawełnę. Jako osoba początkująca, zawsze mam z tym problem, że muszę przebrnąć przez dużą część poradnika, żeby później się rozczarować, że to nie o to mi chodziło. Albo szukać w ciemno pierwszego efektu. Co do samego filmu, mów głośniej i pewniej. Wtedy wszystko będzie wyraźniej słychać, a zawsze przy obróbce możesz siebie nieco przyciszyć. W drugą stronę to nie da rady. No i nieco ciszej muzykę mimo wszystko A i całkiem fajna wstawka z tym rwaniem papierowych spritów!
  8. Świetnie to wygląda! To będzie jakieś płatne/darmowe narzędzie? Super gdyby była opcja eksportu modeli jako spritesheetów z animacją ruchu pod ustalonym kątem.
  9. Dzięki za podpowiedzi z tym losowaniem. Pewnie wpisanie tego w create załatwi cały problem. Co do różnych wartości, to tak, wiem o tym. Gdy wszędzie wpisywałem to samo to i tak nie było równo z racji tego, że te sprity, obiekty i teksty są różnych rozmiarów i nawet jak pierwsza linia się ułoży to reszta już nie przed inne odstępów Ale popróbuję jeszcze to wyrównać Dziękuję za pomoc.
  10. Dzięki za odpowiedź, zmotywowała mnie ona do tego, żeby jednak przejrzeć jeszcze raz kod i udało mi się wyeliminować część błędów i chyba zostanę przy pętli. Potrzebuję jednak dalszej pomocy Problem polega na tym, że nie mogę dojść do tego, żeby wszystko było w jednej linii (walczyłem już dziesiątkami różnych kombinacji i ciągle jest nie tak), a druga to taka, że te liczby (3 cyfrowe i po przecinku) zmieniają się kilkukrotnie w ułamku sekundy. Nie chcą wygenerować się raz i przestać. Kod draw_gui: switch (switch_view) //w zaleznosci od otwartego okna, zmienia sie zawartosc { case "resource": //okno resource draw_set_font(fnt_italianate2); draw_set_colour(c_black); draw_text(128, 320, "Energy: " + string(energy)); draw_text(128, 520, "Water: " + string(water)); break; case "local": //okno local market draw_set_font(fnt_italianate2); draw_set_colour(c_black); for (i = 0; i < 5; i += 1) //tworzenie ofert { instance_create(1848, (i+1)*275+50, obj_sell10); instance_create(2048, (i+1)*275+50, obj_sell100); draw_sprite_ext(spr_pl, 0, 128, ((i+1)*0.75)*350+50, 1, 1, 0, c_white, 1); obj_game.retail_price = item_price + random_range(0.5,0.75); obj_game.retail_amount = item_amount + irandom_range(-150, 150); draw_text(308, ((i+1)*0.75)*325+50, string(obj_game.retail_amount)); draw_text(508, ((i+1)*0.75)*325+50, string(obj_game.retail_price)); } break; case "false": break; } P.S. Twoja sygnatura do discorda nie działa, link źle napisany.
  11. Witam! Jest to mój pierwszy post tutaj, nawet nie wiedziałem, że mamy polskojęzyczne forum o GM! Generalnie jestem "noobem" w kwestii programowania i tak dalej, ale postanowiłem coś stworzyć i powalczyć z tym. Doszedłem do momentu, w którym potrzebuję stworzyć "miejsce" gdzie mam zebrane zmienne, mniej więcej taka tabelka 5x10. Jak mogę najefektywniej to uczynić, aby zapisywanie jak i odczytywanie zmiennych było w miarę proste? Czytałem o ds_map, ds_list, ds_grid. Jakoś nie uśmiecha mi się wypisywać 50 linijek kodu, żeby te wszystkie struktury uzupełnić... A innego sposobu nie znam, słyszałem, że można też coś robić z plikami csv/ini ale jak ściągnąłem jakiś dodatek czytający dane z csv i zobaczyłem ten kod to... eh. To czego potrzebuję wygląda mniej więcej tak: Te dane chciałbym później odczytać by móc tworzyć obiekty i teksty na zasadzie takiej listy. Bawiłem się z "for", który jakby miał sam po części tworzyć te dane, ale wyszły takie jaja, że chciałem zrobić to inaczej.
×
×
  • Dodaj nową pozycję...