Професионална програма
Loading...
Smeshan avatar Smeshan 89 Точки

Elevator rush [Custom game]

Здравейте,

предаставям ви играта, върху която работя. Кръстил съм я Elevator rush. Крайният вариант трябва да представлява нещо подобно на: Mini metro и Mini motorways само че с асансьори :)
Вчера след като чух изискванията се зарадвах, защото някои от нещата вече ги бях направил, така че се боря за най-високия резултат в краткото оставащо време, за което и пиша тук, тъй като имам доста въпроси и проблеми за решаване.

Линк с код-а: https://github.com/Smeshan/Elevator-rush (мисля, че се справих)

Идеята на играта:
Всяко ниво има сграда, на която в random момент се появяват хората (сини кръгчета за сега), които искат да се качат или слязат от някой етаж. Има шахти за асансьори, при които ще се поставят с мишката асансьори, които ще се движат автоматично (според зависи дали хората отиват някъде или офисите имат нужда от хора, още не съм решил кой ще управлява).
Ще има таймер горе, който отмерва едно денонощие (30-60 сек) и на следващия ден се появява на екрана избор за играча, измежду нов асансьор, нова шахта, по-голям аснасьор, стъпала дори, и всякакви такива, които той събира и разполага по картата. Ще избира само едно от две. И тези различни асансьори ще се разполагат по картата или ще се пазят, изобразени някъде по екрана.
В същото време с всеки ден се забързва появяването на хората и офисите, до момента в който губиш играта, ако някой човек(или офис) е чакал прекалено много време и не е бил взет от асансьор. Всеки човек е една точка и се бориш за high score.

Какво съм направил до сега:
Има главно меню с динамичен бекраунд и гейм меню, което зарежда ниво. Там съм разположил офиси (квадратите с числа 1-2..) и един асаньор и един човек (кръгчето). Както и tile map на асаньора, която ще ползвам за поставяне на асаньори според стратегията на играча. Хората имат число над себе си и това етажа на който искат да отидат (ще отпадне по нататък). Офисите пък също има индикатор, който показва колко хора са нужни да се закарат там. За проба съм нагласил бутони + и -, както и 1 и 2.

Проблемите:
1. Кода поддържа звуци и музика, НО има някакво забавяне в изпълнението. Първо ако мините с мишка през главното меню хвърля грешка от Mix_GetError() -> Mix_PlayChannel() failed. Error: Surface doesn't have a colorkey. Която е супер странна и не разбирам как да я оправя. Рових в нета - нищо свързано с миксера от тази грешка. Но може би от там идва това забавяне след като се сложи мишката върху бутон от менюто и не произлиза веднага звук.
2. В MenuButton.cpp функцията, която оцветява текста, по някакви причини не работи с WHITE и GREY, отново никаква идея защо е това странно поведение.
3. В text.cpp в void Text::destroy() , която се обсъждаше добавянето unLoadText при мен се чупи в момента, в който го добавя.

Архитектурни питанки:
1. След като стартираш играта от менюто, обектите и анимацията от main menu си остават на заден план, но просто не се рисуват нали? Какво трябва да ги направя, да ги деинициализирам в която фунцкия всеки обект ще се дестройва? Или?
2. Създал съм LevelPos, който за по-лесно преизчислява кординатите по етажи и шахти(колони), но ми се струва, че не съм го направил много добре. Но то и самия grid map е различен за чакащите хора, асансьорите и офисите, като се предполага, че като добавяш нови шахти, офисите и хората ще мърдат сътоветно настрани.
3. В даден момент, когато съм готов ще трябва да направя PersonGenerator и OfficeGenerator, които да генерира съотвените обекти на нивото. Само че просто random не би било яко. Как да го персонализирам, така че да може едно ниво да бъде горе-долу еднакво или като цяло да мога да го контролирам. Скоростта на създаване е ясна на теория, но примерно в началото на деня да пуска повече хора долу (отиващи хора да работят в офис), на обяд друго, вечерта трето. Просто този генератор как да го контролирам и все пак да е рандом, за да не е напълно еднакво нивото.
4. Придвижването на хора. Вижте в Elevator.cpp съм докарал process() фунцкията, която да гледа ако аснасьора е спрял и ако не е пълен, да вземе хора от етажа. Само че хората са в Level обекта. Бях написал прокси, което взема и прехвърля човек. Това ли е начина? Или да сложа още един флаг в Level, който в процесс да пита isThereElevator и ако има, да маха от себе си хора и да казва на асансьора да ги пълни? Поне това ми хрумна вчера. И същото с офисите, ако има асансьор и ако има пътници да слизат, да намали request-ите на офиса и да махне хора от асансьора. :?

Todo:
1. Да добавя повече цветове или форми на Person и Office обектите, за да махна текста, показващ къде искат да отидат.
2. Да добавя поне още 4-5 нива до края на срока.
3. Да направя заключени нива и само определен score отключва следващото.
4. Background и background анимация за всяко ниво (имам идея какви)
5. Още звуци
6. И други.. (приемам идеи)

Ще се радвам за мнение. Да ме поправите ако съм написал нещо тъпо. И за всякакъв вид друга помощ. За пръв път пиша нещо такова, така че доста се вълнувам и отдлено се уча в движение (ако забележите странни неща в кода).

Мисля да редактирам, този въпрос директно при следващите промени/въпроси, за да може първото, което излиза да е това и да се вижда какво направено и какво не. Така че може да няма нови постове отдолу, но ще редактирам този текст тук. Като запазвам старите неща, за да са свързани коментарите.

Поздрави,
Илиян

П.С. Повечето неща си ги рисувам аз :D

Тагове:
1
C++ Applications Development 14/11/2021 00:38:22
Smeshan avatar Smeshan 89 Точки

Здравейте, играта ми от време на време крашва, без да казва от какво? Пуснах gdb, но не казва при коя фунцкия се е случил segmentation fault-a. :?

Дали сте виждалите нещо подобно:

Thread 1 "elevator_rush" received signal SIGSEGV, Segmentation fault.
0x00007ffff658d545 in ?? ()
(gdb) bt
#0  0x00007ffff658d545 in ?? ()
#1  0x3f8000003f800000 in ?? ()
#2  0x0000000000000018 in ?? ()
#3  0x00007fffffffaa7c in ?? ()
#4  0x0000000000000002 in ?? ()
#5  0x00007fffffffaa40 in ?? ()
#6  0x0000000000000002 in ?? ()
#7  0x00007fffffffaa40 in ?? ()
#8  0x00007fffffffa9c0 in ?? ()
#9  0x0000555555954390 in ?? ()
#10 0x00007fffea0ca5c7 in ?? ()
#11 0x0000555500000001 in ?? ()
---Type <return> to continue, or q <return> to quit---

Поздрави,
Илиян

1
JohnDoe256 avatar JohnDoe256 6 Точки

Щом е segmentation fault най-вероятно имаш pointer,който сочи към uninitialized memory и като играта го access-не става memory leak/undefined behavior.За да го оправиш опитай да изолираш по някакъв начин грешката,един вид да може да я предизвикваш всеки път.Ако успееш това,почваш да коментираш функции да видиш без коя крашва,.Ако крашва без нея значи проблема не е  в нея.

1
j.petrov_90 avatar j.petrov_90 372 Точки

Не виждаш никаква информация, защото нямаш дебъг символи.

Билдни си проекта за дебъг чрез CMake и повтори операцията с gdb.

Това ти е най-добрия ориентир, защото с gdb ще видиш точно кое ти гърми и ще можеш да разгледаш стойността на останалите променливи по време на crash-a.

 

Valgrind също може да ти помогне.

valgrind --leak-check=full --track-origins=yes ./myAppName

1
30/11/2021 08:38:18
Smeshan avatar Smeshan 89 Точки
Thread 1 "elevator_rush" received signal SIGSEGV, Segmentation fault.
malloc_consolidate (av=av@entry=0x7ffff68e4c40 <main_arena>) at malloc.c:4469
4469    malloc.c: No such file or directory.
(gdb) bt
#0  malloc_consolidate (av=av@entry=0x7ffff68e4c40 <main_arena>) at malloc.c:4469
#1  0x00007ffff658d968 in _int_malloc (av=av@entry=0x7ffff68e4c40 <main_arena>, bytes=bytes@entry=3772) at malloc.c:3713
#2  0x00007ffff65903cd in __GI___libc_malloc (bytes=3772) at malloc.c:3075
#3  0x00007ffff7b07a83 in ?? () from /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0
#4  0x00007ffff7b3b251 in ?? () from /usr/lib/x86_64-linux-gnu/libSDL2-2.0.so.0
#5  0x00007ffff744e31f in TTF_RenderUTF8_Blended () from /usr/lib/x86_64-linux-gnu/libSDL2_ttf-2.0.so.0
#6  0x00007ffff744e6fa in TTF_RenderText_Blended () from /usr/lib/x86_64-linux-gnu/libSDL2_ttf-2.0.so.0
#7  0x00005555555914f3 in Texture::createTextureFromText (text=0x5555561468d0 "3", color=..., font=0x55555607d200, outTexture=@0x555556137f20: 0x0, outTextWidth=@0x555556146890: 23, 
    outTextHeight=@0x555556146894: 41) at /home/smeshan/workspace/elevator rush/sdl_utils/src/Texture.cpp:66
#8  0x000055555558b582 in TextContainer::reloadText (this=0x555555951348, text=0x5555561468d0 "3", color=..., fontId=2, textId=10, outTextWidth=@0x555556146890: 23, 
    outTextHeight=@0x555556146894: 41) at /home/smeshan/workspace/elevator rush/sdl_utils/src/containers/TextContainer.cpp:72
#9  0x0000555555584f8a in Text::setColor (this=0x555556146878, color=...) at /home/smeshan/workspace/elevator rush/manager_utils/src/drawing/Text.cpp:91
---Type <return> to continue, or q <return> to quit---

Готово, но #5 нагоре нищо не ми говори :?

0
MartinBG avatar MartinBG 3981 Точки

Всичко тръгва от Text::setColor. Този метод приема само един параметър - референция към Color, която е трудно да бъде невалидна, но все пак прегледай дали в извикването на метода ползваш само предефинираните цветове. Виж също дали я трансформираш (до SDL_Color) и предаваш правилно към TTF_RenderText_Blended.

Друга вероятната причина за проблема е, този метод да е извикан върху неинициализиран обект, но от текста в грешката не изглежда да е така:

- става дума за текст "3", което най-вероятно е някой от бутоните в MenuButton

- TextContainer::reloadText е извикан от инициализиран обект: (this=0x555555951348, text=0x5555561468d0 "3", color=..., fontId=2, textId=10, outTextWidth=@0x555556146890: 23, outTextHeight=@0x555556146894: 41)

- Texture::createTextureFromText също изглежда да е получила валидни параметри: (text=0x5555561468d0 "3", color=..., font=0x55555607d200, outTexture=@0x555556137f20: 0x0, outTextWidth=@0x555556146890: 23, outTextHeight=@0x555556146894: 41)

Евентуален проблем може да има, ако паметта за textId=10 (т.е. outTexture=@0x555556137f20: 0x0) вече не принадлежи на приложението, т.е. била е освободена и този адрес вече е чужд.

 

Забелязвам, че в MenuButton::handleEvent викаш директно Text::setColor(Colors::WHITE); или Text::setColor(Colors::GRAY);

Това работи, но е доста странно като запис, особено като се има предвид, че този метод е няколко нива надолу в йерархията на наследяването на MenuButton. По-четимо ще е използването на this->setColor(...)

0
30/11/2021 17:11:06