battlefield-term 0.1.20__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- battlefield_term-0.1.20/PKG-INFO +17 -0
- battlefield_term-0.1.20/README.md +128 -0
- battlefield_term-0.1.20/battlefield_term.egg-info/PKG-INFO +17 -0
- battlefield_term-0.1.20/battlefield_term.egg-info/SOURCES.txt +88 -0
- battlefield_term-0.1.20/battlefield_term.egg-info/dependency_links.txt +1 -0
- battlefield_term-0.1.20/battlefield_term.egg-info/entry_points.txt +2 -0
- battlefield_term-0.1.20/battlefield_term.egg-info/requires.txt +6 -0
- battlefield_term-0.1.20/battlefield_term.egg-info/top_level.txt +1 -0
- battlefield_term-0.1.20/setup.cfg +4 -0
- battlefield_term-0.1.20/setup.py +53 -0
- battlefield_term-0.1.20/src/__init__.py +2 -0
- battlefield_term-0.1.20/src/base.py +63 -0
- battlefield_term-0.1.20/src/chassis/__init__.py +0 -0
- battlefield_term-0.1.20/src/chassis/chassis.py +20 -0
- battlefield_term-0.1.20/src/chassis/simple_chassis.py +152 -0
- battlefield_term-0.1.20/src/driver.py +56 -0
- battlefield_term-0.1.20/src/func.py +18 -0
- battlefield_term-0.1.20/src/game.py +121 -0
- battlefield_term-0.1.20/src/geometry/__init__.py +0 -0
- battlefield_term-0.1.20/src/geometry/euclid.py +69 -0
- battlefield_term-0.1.20/src/geometry/position.py +43 -0
- battlefield_term-0.1.20/src/geometry/triangle.py +53 -0
- battlefield_term-0.1.20/src/helpers.py +102 -0
- battlefield_term-0.1.20/src/historicalposition.py +37 -0
- battlefield_term-0.1.20/src/main.py +219 -0
- battlefield_term-0.1.20/src/mixins.py +8 -0
- battlefield_term-0.1.20/src/modes/__init__.py +0 -0
- battlefield_term-0.1.20/src/modes/helpers.py +52 -0
- battlefield_term-0.1.20/src/modes/none.py +7 -0
- battlefield_term-0.1.20/src/modes/roam_and_destroy.py +16 -0
- battlefield_term-0.1.20/src/modes/rotation.py +26 -0
- battlefield_term-0.1.20/src/modes/spiral.py +58 -0
- battlefield_term-0.1.20/src/modes/straight.py +29 -0
- battlefield_term-0.1.20/src/modes/to_homebase.py +8 -0
- battlefield_term-0.1.20/src/modes/to_position.py +77 -0
- battlefield_term-0.1.20/src/modes/turns.py +73 -0
- battlefield_term-0.1.20/src/modes/waypoints.py +33 -0
- battlefield_term-0.1.20/src/paths/__init__.py +0 -0
- battlefield_term-0.1.20/src/paths/area.py +82 -0
- battlefield_term-0.1.20/src/paths/path.py +28 -0
- battlefield_term-0.1.20/src/paths/point_collection.py +51 -0
- battlefield_term-0.1.20/src/paths/waypoint.py +26 -0
- battlefield_term-0.1.20/src/rovers/__init__.py +0 -0
- battlefield_term-0.1.20/src/rovers/rover.py +167 -0
- battlefield_term-0.1.20/src/rovers/tracked.py +61 -0
- battlefield_term-0.1.20/src/scene/__init__.py +0 -0
- battlefield_term-0.1.20/src/scene/objects/__init__.py +0 -0
- battlefield_term-0.1.20/src/scene/objects/borderstone.py +28 -0
- battlefield_term-0.1.20/src/scene/objects/damageable.py +34 -0
- battlefield_term-0.1.20/src/scene/objects/rectangle.py +48 -0
- battlefield_term-0.1.20/src/scene/objects/scene_object.py +37 -0
- battlefield_term-0.1.20/src/scene/objects/tree.py +26 -0
- battlefield_term-0.1.20/src/scene/objects/triangle.py +26 -0
- battlefield_term-0.1.20/src/scene/scene.py +273 -0
- battlefield_term-0.1.20/src/settings.py +26 -0
- battlefield_term-0.1.20/src/singletons.py +6 -0
- battlefield_term-0.1.20/src/snd/detonation.wav +0 -0
- battlefield_term-0.1.20/src/snd/spawned_enemy.wav +0 -0
- battlefield_term-0.1.20/src/snd/spawned_own.flac +0 -0
- battlefield_term-0.1.20/src/ux/__init__.py +0 -0
- battlefield_term-0.1.20/src/ux/cycler.py +31 -0
- battlefield_term-0.1.20/src/ux/dialogs/__init__.py +0 -0
- battlefield_term-0.1.20/src/ux/dialogs/dialog.py +25 -0
- battlefield_term-0.1.20/src/ux/dialogs/waypoints.py +22 -0
- battlefield_term-0.1.20/src/ux/functions.py +30 -0
- battlefield_term-0.1.20/src/ux/graph.py +51 -0
- battlefield_term-0.1.20/src/ux/grid.py +28 -0
- battlefield_term-0.1.20/src/ux/groups.py +92 -0
- battlefield_term-0.1.20/src/ux/helpers.py +20 -0
- battlefield_term-0.1.20/src/ux/images.py +29 -0
- battlefield_term-0.1.20/src/ux/keyboard.py +22 -0
- battlefield_term-0.1.20/src/ux/map_display.py +70 -0
- battlefield_term-0.1.20/src/ux/menu.py +137 -0
- battlefield_term-0.1.20/src/ux/screen.py +44 -0
- battlefield_term-0.1.20/src/ux/statusbar.py +63 -0
- battlefield_term-0.1.20/src/ux/submenus/__init__.py +0 -0
- battlefield_term-0.1.20/src/ux/submenus/driver.py +29 -0
- battlefield_term-0.1.20/src/ux/submenus/help.py +13 -0
- battlefield_term-0.1.20/src/ux/submenus/map.py +31 -0
- battlefield_term-0.1.20/src/ux/submenus/rover.py +21 -0
- battlefield_term-0.1.20/src/ux/submenus/scene.py +21 -0
- battlefield_term-0.1.20/src/ux/submenus/spawn.py +19 -0
- battlefield_term-0.1.20/src/ux/submenus/submenu.py +25 -0
- battlefield_term-0.1.20/src/ux/switches.py +197 -0
- battlefield_term-0.1.20/src/ux/texts.py +75 -0
- battlefield_term-0.1.20/src/ux/triggers/__init__.py +0 -0
- battlefield_term-0.1.20/src/ux/triggers/driver_mode_trigger.py +13 -0
- battlefield_term-0.1.20/src/ux/triggers/submenu_trigger.py +13 -0
- battlefield_term-0.1.20/src/ux/triggers/trigger.py +38 -0
- battlefield_term-0.1.20/src/ux/ux.py +67 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: battlefield_term
|
|
3
|
+
Version: 0.1.20
|
|
4
|
+
Summary: battlefield terminal game
|
|
5
|
+
Home-page:
|
|
6
|
+
Author: Jarmil Halamicek
|
|
7
|
+
Author-email: hi@jarmil.com
|
|
8
|
+
License: BSD 2-clause
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
11
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
12
|
+
Classifier: Topic :: Games/Entertainment :: Simulation
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Bot battlefield game
|
|
2
|
+
|
|
3
|
+
derived from tg/pilot
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Geometrie na scene
|
|
7
|
+
|
|
8
|
+
Vse se meri v metrech.
|
|
9
|
+
X je zleva doprava, Y je zdola nahoru.
|
|
10
|
+
Sever je nahore (tedy kladne hodnoty Y), vychod vpravo (kladne hodnoty X)
|
|
11
|
+
Rotace je clockwise: 0 stupnu sever, 90 vychod, 180 jih, 270 zapad
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## Tech stack
|
|
15
|
+
|
|
16
|
+
Python 3.10 (python 3.12 je nekompatibilni se starsim numpy verze < 2)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## Netridene todos a improvements
|
|
20
|
+
|
|
21
|
+
- IMP keyup - keydown logic v Keyboard
|
|
22
|
+
- IMP: Scene: zadej uvodni zvetseni
|
|
23
|
+
- IMP: ovladani WASD a Tab atd aktivni i kdyz je otevrene submenu
|
|
24
|
+
- IMP: move to wheel package (binary)
|
|
25
|
+
-
|
|
26
|
+
|
|
27
|
+
## Marketing
|
|
28
|
+
|
|
29
|
+
“Deploy and command combat drones—set their tactics, position them on the battlefield,
|
|
30
|
+
and manage the economy so your operations stay in control.”
|
|
31
|
+
|
|
32
|
+
## Summary (pro šéfa marketingu)
|
|
33
|
+
Cíl je dostat zcela nový Steam účet (0 wishlistů) do režimu růstu během 3 měsíců pomocí konzistentního outreachu a hlavně konzistentních Steam update postů/patch notes pro alpha verzi. Hra je singleplayer, 3rd person/aerial-map view a primární “hook” jsou autonomní bojové drony; diferenciátor je kombinace velení strategie dronů + hlídání ekonomiky/tempa operací. Priorita: rychle vybudovat důvěru (důkazy v běžících featurech a opravách), vyvolat návštěvy stránky a konverzi na wishlist přes jasné “co testovat teď”.
|
|
34
|
+
|
|
35
|
+
## Přehled strategie (co děláme)
|
|
36
|
+
- Steam stránka jako “alpha-grade” přesvědčivý brief: trailer (60–90 s), 6–10 screenshotů, About This Game (jasně co je funkční v alfě), “What’s Next” na 4–6 týdnů dopředu, přesné tagy.
|
|
37
|
+
- Komunita a feedback loop: Steam Community/Discussions rozdělené na typy feedbacku + konzistentní patch notes s “known issues” a “what to test next”.
|
|
38
|
+
- Outreach na míru targeting matrix:
|
|
39
|
+
1) command/tactics (3rd-person rozhodování),
|
|
40
|
+
2) autonomous units/squad AI (sledování chování AI),
|
|
41
|
+
3) economy/tempo (scaling/balance),
|
|
42
|
+
4) aerial/cinematic drone gameplay (wow deploy moments),
|
|
43
|
+
5) singleplayer systems (depth bez co-op).
|
|
44
|
+
- Outreach: ne spam; osobní DM/komentáře s jasným “why you” a konkrétním call to action (Steam page + access + checklist testů + deadline pro feedback).
|
|
45
|
+
- Update tempo: ideálně 1 update týdně (nebo 1× za 7–14 dní), ale vždy ve stejném formátu a s vazbou na feedback.
|
|
46
|
+
|
|
47
|
+
## Cíle (3 měsíce)
|
|
48
|
+
- Vybudovat první traction na Steam: wishlistů a aktivních hráčů v alfě především díky konzistenci update obsahu a důkazům.
|
|
49
|
+
- Vytvořit “důvěryhodný rytmus” (hráči očekávají patch notes a vědí, co testovat).
|
|
50
|
+
- Získat stabilní tok kvalitního feedbacku zaměřeného na autonomní drony (strategie), ekonomiku (tempo/failure states) a největší frikce (onboarding/performance/AI edge cases).
|
|
51
|
+
|
|
52
|
+
## Taktické kroky – 3 měsíce po týdnech
|
|
53
|
+
|
|
54
|
+
### Měsíc 1 (Týdny 1–4): Launch alfa signálu + první důkaz
|
|
55
|
+
**Týden 1**
|
|
56
|
+
- Zveřejnit Steam stránku v kvalitě “alpha-grade”: 1 krátký trailer, 6–10 screenshotů, jasné About This Game, “What’s Next” (4–6 týdnů), tagy odpovídající: military/realistic/tactics/vehicles dle relevance.
|
|
57
|
+
- Vytvořit Steam Community strukturu: Discussions k tématům (bugs, balance & tactics, performance, suggestions).
|
|
58
|
+
- První outreach dávka: top 15 cílených kontaktů (tactics/command + autonomous AI).
|
|
59
|
+
- Poslat: Steam page + alpha access (jak máte) + checklist “co otestovat” do 3–5 dní.
|
|
60
|
+
|
|
61
|
+
**Týden 2**
|
|
62
|
+
- První komunitní “Alpha Welcome / Dev Update”: co funguje, co je známé riziko, co testovat příští týden.
|
|
63
|
+
- Patch notes k prvním změnám: “what changed”, “known issues”, “what to test next”.
|
|
64
|
+
- Outreach follow-up jen pro ty, kdo reagovali/otevřeli DM (1 krátká zpráva).
|
|
65
|
+
|
|
66
|
+
**Týden 3**
|
|
67
|
+
- Druhý outreach vlnou segmenty 3 (economy/tempo) + 4 (aerial/cinematic).
|
|
68
|
+
- Dev post: 3 konkrétní learnings z feedbacku + 3 věci do dalšího buildu.
|
|
69
|
+
- Upřesnit Steam stránku podle aktuálních odpovědí komunity (zejména About / What’s Next).
|
|
70
|
+
|
|
71
|
+
**Týden 4**
|
|
72
|
+
- “Alpha Hot Fix + Roadmap Window” post: co jste opravili a na čem se teď soustředíte (na dalších 2–3 týdny).
|
|
73
|
+
- Spustit režim sběru feedbacku: vždy checklist + deadline pro test (zrychlí iterace a zvýší návratnost).
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
### Měsíc 2 (Týdny 5–8): Růst díky konzistenci update rytmu
|
|
78
|
+
**Týden 5**
|
|
79
|
+
- 1. pravidelný týdenní update (nebo 2týdenní podle kapacity) ve stejném formátu:
|
|
80
|
+
- What’s new (max 5)
|
|
81
|
+
- What changed based on feedback (min 2)
|
|
82
|
+
- Known issues (max 3)
|
|
83
|
+
- What to test next (konkrétní testy na drony + ekonomiku)
|
|
84
|
+
- Outreach: segment 1 a 2 (tactics/command + autonomous AI) – rozšířit na 25–40 kontaktů celkem v tomto měsíci.
|
|
85
|
+
|
|
86
|
+
**Týden 6**
|
|
87
|
+
- Zaměřený outreach na segment 2: “autonomous units behavior tests” (poslat 3 testy: priority cíle, chování pod tlakem, degradace při špatné ekonomice/tempu).
|
|
88
|
+
- Komunitní post s “Top 3 takeaways for players” (krátce, lidsky).
|
|
89
|
+
|
|
90
|
+
**Týden 7**
|
|
91
|
+
- Update zaměřený na největší frikci, která se objevuje ve feedbacku (např. AI volba, target priority, pathing/spotting, performance).
|
|
92
|
+
- Uvést v patch notes i “why” (co z feedbacku spustilo změnu).
|
|
93
|
+
|
|
94
|
+
**Týden 8**
|
|
95
|
+
- Second mid-cycle post: “Feature spotlight” (jeden systém/loop) + výslovně “tohle prosím testujte v příštím buildu”.
|
|
96
|
+
- Outreach: segment 3 (economy/tempo) + 4 (aerial/cinematic) – nabídnout konkrétní “deploy + tempo” scénáře.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
### Měsíc 3 (Týdny 9–12): Milník, jasná hodnota, event/boost důvěry
|
|
101
|
+
**Týden 9**
|
|
102
|
+
- Velký milníkový update (marketingově silný): zlepšení “core” části smyčky—autonomní drony + rozhodování strategie (taktika) + ekonomický failure/success model.
|
|
103
|
+
- Steam stránka: doplnit “Getting Started” (5 kroků) a vylepšit “What’s Next” podle aktuální reality.
|
|
104
|
+
|
|
105
|
+
**Týden 10**
|
|
106
|
+
- Outreach: re-hit pro top tvůrce/komunity, které reagovaly nejlépe (ne pro všechny).
|
|
107
|
+
- Komunitní post: “Before/After” (staré vs nové chování dronů / ekonomiky / tempo výsledků).
|
|
108
|
+
|
|
109
|
+
**Týden 11**
|
|
110
|
+
- Krátká event akce na 3–5 dní v komunitě:
|
|
111
|
+
- “Alpha Tactics Challenge” (týdenní tematický cíl: např. test 2 různých drone tactics + report kdy ekonomika začne degradovat operace)
|
|
112
|
+
- Vyžadovat krátký formát feedbacku (co se stalo / co jste změnili / screenshot/video pokud jde).
|
|
113
|
+
|
|
114
|
+
**Týden 12**
|
|
115
|
+
- Závěrečný “Alpha Cycle Review” post:
|
|
116
|
+
- co jsme získali od hráčů,
|
|
117
|
+
- co je hotovo,
|
|
118
|
+
- co je další milník (další roadmap window),
|
|
119
|
+
- přímý call: “wishlist if you want to continue shaping the next cycle” (bez PR mlhy).
|
|
120
|
+
- Připravit další fázi komunikace (navázat na to, co vyšlo v měsíci 3: jaké claimy jsou podložené reálnými reakcemi).
|
|
121
|
+
|
|
122
|
+
## Outreach: operativní pravidla (aby to fungovalo)
|
|
123
|
+
- Každému kontaktu: osobní “why you” (navázat na jejich témata), konkrétní testy (3–5 bodů), jasný access + deadline.
|
|
124
|
+
- Rytmus: 2 outreach vlny v měsíci 1, 3–4 vlny v měsíci 2, re-hit top segmenty v měsíci 3.
|
|
125
|
+
- Kanály: YouTube/Twitch (tactics/milsim/AI/vehicles), Discordy tactical/realism komunity, Reddit/threads v tématech realism/tactics, menší “indie milsim” discovery.
|
|
126
|
+
- Očekávaný výstup od testerů: mini-reports + 1–2 videa/screens (pokud možná), jinak aspoň reprodukce problému a co vedlo ke změně.
|
|
127
|
+
|
|
128
|
+
Chceš, abych dodal i 3–4 konkrétní šablony anglických DM zpráv (pro segmenty 1–3) a anglický formát patch notes postu, které pak jen doplňujete konkrétními body z buildu?
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: battlefield-term
|
|
3
|
+
Version: 0.1.20
|
|
4
|
+
Summary: battlefield terminal game
|
|
5
|
+
Home-page:
|
|
6
|
+
Author: Jarmil Halamicek
|
|
7
|
+
Author-email: hi@jarmil.com
|
|
8
|
+
License: BSD 2-clause
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
11
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
12
|
+
Classifier: Topic :: Games/Entertainment :: Simulation
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
setup.py
|
|
3
|
+
battlefield_term.egg-info/PKG-INFO
|
|
4
|
+
battlefield_term.egg-info/SOURCES.txt
|
|
5
|
+
battlefield_term.egg-info/dependency_links.txt
|
|
6
|
+
battlefield_term.egg-info/entry_points.txt
|
|
7
|
+
battlefield_term.egg-info/requires.txt
|
|
8
|
+
battlefield_term.egg-info/top_level.txt
|
|
9
|
+
src/__init__.py
|
|
10
|
+
src/base.py
|
|
11
|
+
src/driver.py
|
|
12
|
+
src/func.py
|
|
13
|
+
src/game.py
|
|
14
|
+
src/helpers.py
|
|
15
|
+
src/historicalposition.py
|
|
16
|
+
src/main.py
|
|
17
|
+
src/mixins.py
|
|
18
|
+
src/settings.py
|
|
19
|
+
src/singletons.py
|
|
20
|
+
src/chassis/__init__.py
|
|
21
|
+
src/chassis/chassis.py
|
|
22
|
+
src/chassis/simple_chassis.py
|
|
23
|
+
src/geometry/__init__.py
|
|
24
|
+
src/geometry/euclid.py
|
|
25
|
+
src/geometry/position.py
|
|
26
|
+
src/geometry/triangle.py
|
|
27
|
+
src/modes/__init__.py
|
|
28
|
+
src/modes/helpers.py
|
|
29
|
+
src/modes/none.py
|
|
30
|
+
src/modes/roam_and_destroy.py
|
|
31
|
+
src/modes/rotation.py
|
|
32
|
+
src/modes/spiral.py
|
|
33
|
+
src/modes/straight.py
|
|
34
|
+
src/modes/to_homebase.py
|
|
35
|
+
src/modes/to_position.py
|
|
36
|
+
src/modes/turns.py
|
|
37
|
+
src/modes/waypoints.py
|
|
38
|
+
src/paths/__init__.py
|
|
39
|
+
src/paths/area.py
|
|
40
|
+
src/paths/path.py
|
|
41
|
+
src/paths/point_collection.py
|
|
42
|
+
src/paths/waypoint.py
|
|
43
|
+
src/rovers/__init__.py
|
|
44
|
+
src/rovers/rover.py
|
|
45
|
+
src/rovers/tracked.py
|
|
46
|
+
src/scene/__init__.py
|
|
47
|
+
src/scene/scene.py
|
|
48
|
+
src/scene/objects/__init__.py
|
|
49
|
+
src/scene/objects/borderstone.py
|
|
50
|
+
src/scene/objects/damageable.py
|
|
51
|
+
src/scene/objects/rectangle.py
|
|
52
|
+
src/scene/objects/scene_object.py
|
|
53
|
+
src/scene/objects/tree.py
|
|
54
|
+
src/scene/objects/triangle.py
|
|
55
|
+
src/snd/detonation.wav
|
|
56
|
+
src/snd/spawned_enemy.wav
|
|
57
|
+
src/snd/spawned_own.flac
|
|
58
|
+
src/ux/__init__.py
|
|
59
|
+
src/ux/cycler.py
|
|
60
|
+
src/ux/functions.py
|
|
61
|
+
src/ux/graph.py
|
|
62
|
+
src/ux/grid.py
|
|
63
|
+
src/ux/groups.py
|
|
64
|
+
src/ux/helpers.py
|
|
65
|
+
src/ux/images.py
|
|
66
|
+
src/ux/keyboard.py
|
|
67
|
+
src/ux/map_display.py
|
|
68
|
+
src/ux/menu.py
|
|
69
|
+
src/ux/screen.py
|
|
70
|
+
src/ux/statusbar.py
|
|
71
|
+
src/ux/switches.py
|
|
72
|
+
src/ux/texts.py
|
|
73
|
+
src/ux/ux.py
|
|
74
|
+
src/ux/dialogs/__init__.py
|
|
75
|
+
src/ux/dialogs/dialog.py
|
|
76
|
+
src/ux/dialogs/waypoints.py
|
|
77
|
+
src/ux/submenus/__init__.py
|
|
78
|
+
src/ux/submenus/driver.py
|
|
79
|
+
src/ux/submenus/help.py
|
|
80
|
+
src/ux/submenus/map.py
|
|
81
|
+
src/ux/submenus/rover.py
|
|
82
|
+
src/ux/submenus/scene.py
|
|
83
|
+
src/ux/submenus/spawn.py
|
|
84
|
+
src/ux/submenus/submenu.py
|
|
85
|
+
src/ux/triggers/__init__.py
|
|
86
|
+
src/ux/triggers/driver_mode_trigger.py
|
|
87
|
+
src/ux/triggers/submenu_trigger.py
|
|
88
|
+
src/ux/triggers/trigger.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
battlefield_term
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from setuptools import setup
|
|
2
|
+
from src import version
|
|
3
|
+
|
|
4
|
+
setup(
|
|
5
|
+
name='battlefield_term',
|
|
6
|
+
version=version,
|
|
7
|
+
description='battlefield terminal game',
|
|
8
|
+
url='',
|
|
9
|
+
author='Jarmil Halamicek',
|
|
10
|
+
author_email='hi@jarmil.com',
|
|
11
|
+
license='BSD 2-clause',
|
|
12
|
+
package_dir={'battlefield_term': 'src'},
|
|
13
|
+
packages=[
|
|
14
|
+
'battlefield_term',
|
|
15
|
+
'battlefield_term.chassis',
|
|
16
|
+
'battlefield_term.geometry',
|
|
17
|
+
'battlefield_term.modes',
|
|
18
|
+
'battlefield_term.paths',
|
|
19
|
+
'battlefield_term.rovers',
|
|
20
|
+
'battlefield_term.scene',
|
|
21
|
+
'battlefield_term.scene.objects',
|
|
22
|
+
'battlefield_term.ux',
|
|
23
|
+
'battlefield_term.ux.dialogs',
|
|
24
|
+
'battlefield_term.ux.submenus',
|
|
25
|
+
'battlefield_term.ux.triggers',
|
|
26
|
+
],
|
|
27
|
+
install_requires=[
|
|
28
|
+
'pygame>=2.5.0',
|
|
29
|
+
'Pillow>=10.0.0',
|
|
30
|
+
'PyYAML>=6.0.1',
|
|
31
|
+
'arrow>=1.3.0',
|
|
32
|
+
'numpy>=1.24.3',
|
|
33
|
+
'termcolor>=2.4.0',
|
|
34
|
+
],
|
|
35
|
+
classifiers=[
|
|
36
|
+
'Development Status :: 3 - Alpha',
|
|
37
|
+
'Intended Audience :: End Users/Desktop',
|
|
38
|
+
'License :: OSI Approved :: BSD License',
|
|
39
|
+
'Topic :: Games/Entertainment :: Simulation',
|
|
40
|
+
'Operating System :: POSIX :: Linux',
|
|
41
|
+
'Programming Language :: Python :: 3.8',
|
|
42
|
+
'Programming Language :: Python :: 3.9',
|
|
43
|
+
'Programming Language :: Python :: 3.10',
|
|
44
|
+
'Programming Language :: Python :: 3.12',
|
|
45
|
+
],
|
|
46
|
+
|
|
47
|
+
package_data={'battlefield_term': ['snd/*']},
|
|
48
|
+
entry_points={
|
|
49
|
+
'console_scripts': [
|
|
50
|
+
'battlefield_term=battlefield_term.main:main',
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import random
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
from .geometry.position import Position
|
|
5
|
+
from .helpers import Angle
|
|
6
|
+
from .rovers.tracked import DronePiggy, DroneTango, DroneViper
|
|
7
|
+
from .modes.roam_and_destroy import RoamAndDestroy
|
|
8
|
+
from .scene.objects.damageable import DamageableObject
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ArmyBase(DamageableObject):
|
|
12
|
+
|
|
13
|
+
max_damage = 20000
|
|
14
|
+
enemy = None
|
|
15
|
+
seen_forever = True
|
|
16
|
+
|
|
17
|
+
def __init__(self, scene, x, y):
|
|
18
|
+
super().__init__(Position(x, y, Angle(360-scene.orientation).value))
|
|
19
|
+
self.scene = scene
|
|
20
|
+
|
|
21
|
+
def spawn_drone(self, drone_class):
|
|
22
|
+
if self.alive:
|
|
23
|
+
rover = drone_class(Position(self.position.x, self.position.y, random.randint(0, 359)), f"#{self.scene.drone_index}", self.scene, self.enemy)
|
|
24
|
+
rover.driver.set_mode(RoamAndDestroy)
|
|
25
|
+
self.scene.add_rover(rover)
|
|
26
|
+
self.scene.game.status_bar.warning = f"Drone {rover} spawned by {'enemy' if self.enemy else 'us'}"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class HomeBase(ArmyBase):
|
|
30
|
+
color = "blue"
|
|
31
|
+
name = "Home base"
|
|
32
|
+
enemy = False
|
|
33
|
+
|
|
34
|
+
def spawn_drone(self, drone_class):
|
|
35
|
+
""" Vypusti bota a strhne si za to penize """
|
|
36
|
+
if drone_class.price > self.scene.game.score:
|
|
37
|
+
# IMP: should raise exception and trigger catches and displays it
|
|
38
|
+
self.scene.game.status_bar.warning = f"Drone costs {drone_class.price}, you have only {self.scene.game.score}"
|
|
39
|
+
return
|
|
40
|
+
self.scene.game.score -= drone_class.price
|
|
41
|
+
self.scene.game.play_sound("spawned_own.flac")
|
|
42
|
+
|
|
43
|
+
return super().spawn_drone(drone_class)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class EnemyBase(ArmyBase):
|
|
47
|
+
color = "red"
|
|
48
|
+
name = "Enemy base"
|
|
49
|
+
enemy = True
|
|
50
|
+
spawn_interval = 40 # in seconds
|
|
51
|
+
|
|
52
|
+
def __init__(self, scene, x, y):
|
|
53
|
+
super().__init__(scene, x, y)
|
|
54
|
+
self.spawn_start = time.time()
|
|
55
|
+
|
|
56
|
+
def spawn_rover(self):
|
|
57
|
+
self.spawn_drone(random.choice([DroneViper, DroneViper, DronePiggy, DroneTango]))
|
|
58
|
+
self.scene.game.play_sound("spawned_enemy.wav")
|
|
59
|
+
|
|
60
|
+
def do(self):
|
|
61
|
+
if time.time() - self.spawn_start > self.spawn_interval:
|
|
62
|
+
self.spawn_rover()
|
|
63
|
+
self.spawn_start = time.time()
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from ..geometry.euclid import EuclideanObject
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Chassis(EuclideanObject):
|
|
5
|
+
""" common ancestor for all chassis """
|
|
6
|
+
|
|
7
|
+
color = [128, 240, 180]
|
|
8
|
+
|
|
9
|
+
def __init__(self, rover, position):
|
|
10
|
+
super().__init__(position)
|
|
11
|
+
self.rover = rover
|
|
12
|
+
|
|
13
|
+
@property
|
|
14
|
+
def speed(self):
|
|
15
|
+
return 0
|
|
16
|
+
|
|
17
|
+
def update(self, time_elapsed):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import pygame
|
|
3
|
+
from pygame import Vector2
|
|
4
|
+
|
|
5
|
+
from .chassis import Chassis
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SimpleChassis(Chassis):
|
|
9
|
+
""" Jednoduche chassis co umi zatacet """
|
|
10
|
+
|
|
11
|
+
max_speed = 10 # m/s
|
|
12
|
+
speed_change_step = 2.5
|
|
13
|
+
max_rotation_speed = 12 # degrees/s
|
|
14
|
+
rotation_speed_change_step = 4
|
|
15
|
+
|
|
16
|
+
def __init__(self, rover, position):
|
|
17
|
+
super().__init__(rover, position)
|
|
18
|
+
self._speed = 0
|
|
19
|
+
self._rotation_speed = 0
|
|
20
|
+
|
|
21
|
+
def __str__(self):
|
|
22
|
+
return f"Simple chassis {self.speed} m/s"
|
|
23
|
+
|
|
24
|
+
def draw_body(self, ux_object, rover_position):
|
|
25
|
+
super().draw_body(ux_object, rover_position)
|
|
26
|
+
my_rover_position = ux_object.screen.translate_position_to_screen(self.position.vector2-rover_position.vector2)
|
|
27
|
+
angle = 360 - self.position.angle # kresli se do sceny inverted
|
|
28
|
+
|
|
29
|
+
self.draw_track(ux_object.screen.pygame_screen, my_rover_position, angle)
|
|
30
|
+
|
|
31
|
+
def draw_track(self, screen, position, direction):
|
|
32
|
+
"""Draws speed indicator at given position"""
|
|
33
|
+
max_area = 50
|
|
34
|
+
width, length = 6, 30
|
|
35
|
+
real_pos = Vector2(position)
|
|
36
|
+
|
|
37
|
+
# Create transparent surface for rotating indicator
|
|
38
|
+
s = pygame.Surface((max_area, max_area))
|
|
39
|
+
s = s.convert_alpha()
|
|
40
|
+
s.fill((0, 0, 0, 0))
|
|
41
|
+
|
|
42
|
+
# Draw it to the surface
|
|
43
|
+
pygame.draw.rect(
|
|
44
|
+
s,
|
|
45
|
+
(60, 60, 60),
|
|
46
|
+
pygame.Rect(
|
|
47
|
+
(max_area - width) / 2,
|
|
48
|
+
(max_area - length) / 2,
|
|
49
|
+
width,
|
|
50
|
+
length,
|
|
51
|
+
),
|
|
52
|
+
)
|
|
53
|
+
if self.speed_percentage > 0:
|
|
54
|
+
pygame.draw.rect(
|
|
55
|
+
s,
|
|
56
|
+
"green",
|
|
57
|
+
pygame.Rect(
|
|
58
|
+
(max_area - width) / 2 ,
|
|
59
|
+
(max_area - length) / 2,
|
|
60
|
+
width,
|
|
61
|
+
self.speed_percentage * length,
|
|
62
|
+
),
|
|
63
|
+
)
|
|
64
|
+
else:
|
|
65
|
+
pygame.draw.rect(
|
|
66
|
+
s,
|
|
67
|
+
"red",
|
|
68
|
+
pygame.Rect(
|
|
69
|
+
(max_area - width) / 2,
|
|
70
|
+
(max_area - length) / 2,
|
|
71
|
+
width,
|
|
72
|
+
-self.speed_percentage * length,
|
|
73
|
+
),
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# And rotate it
|
|
77
|
+
s = pygame.transform.rotate(s, direction)
|
|
78
|
+
screen.blit(s, real_pos - Vector2(s.get_size()) / 2)
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def speed(self):
|
|
82
|
+
return self._speed if self.rover.alive else 0
|
|
83
|
+
|
|
84
|
+
@speed.setter
|
|
85
|
+
def speed(self, value):
|
|
86
|
+
if -self.max_speed <= value <= self.max_speed:
|
|
87
|
+
self._speed = value
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def rotation_speed(self):
|
|
91
|
+
""" Uhlova rychlost v stupnich za sekundu """
|
|
92
|
+
return self._rotation_speed if self.rover.alive else 0
|
|
93
|
+
|
|
94
|
+
@rotation_speed.setter
|
|
95
|
+
def rotation_speed(self, value):
|
|
96
|
+
if - self.max_rotation_speed <= value <= self.max_rotation_speed:
|
|
97
|
+
self._rotation_speed = value
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def speed_percentage(self):
|
|
101
|
+
return self.speed / self.max_speed
|
|
102
|
+
|
|
103
|
+
def update(self, time_elapsed):
|
|
104
|
+
"""Periodically called to update rover position and other attributes"""
|
|
105
|
+
distance_driven = self.speed * time_elapsed
|
|
106
|
+
angle = 360 - self.position.angle + 90
|
|
107
|
+
angle = math.radians(angle)
|
|
108
|
+
x_offset = distance_driven * math.cos(angle)
|
|
109
|
+
y_offset = -distance_driven * math.sin(angle)
|
|
110
|
+
self.position.x += x_offset
|
|
111
|
+
self.position.y -= y_offset
|
|
112
|
+
self.position.angle += self.rotation_speed * time_elapsed
|
|
113
|
+
|
|
114
|
+
def stop(self):
|
|
115
|
+
self.speed = 0
|
|
116
|
+
self.rotation_speed = 0
|
|
117
|
+
|
|
118
|
+
def at_arrow_up(self):
|
|
119
|
+
self.speed += self.speed_change_step
|
|
120
|
+
|
|
121
|
+
def at_arrow_down(self):
|
|
122
|
+
self.speed -= self.speed_change_step
|
|
123
|
+
|
|
124
|
+
def at_arrow_left(self):
|
|
125
|
+
self.steer_left()
|
|
126
|
+
|
|
127
|
+
def at_arrow_right(self):
|
|
128
|
+
self.steer_right()
|
|
129
|
+
|
|
130
|
+
def steer_left(self):
|
|
131
|
+
self.rotation_speed -= self.rotation_speed_change_step
|
|
132
|
+
|
|
133
|
+
def steer_right(self):
|
|
134
|
+
self.rotation_speed += self.rotation_speed_change_step
|
|
135
|
+
|
|
136
|
+
def set_speed_as_percentage(self, percentage):
|
|
137
|
+
self.speed = percentage * self.max_speed
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class FastSimpleChassis(SimpleChassis):
|
|
141
|
+
max_speed = 15 # m/s
|
|
142
|
+
speed_change_step = max_speed / 4
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class SuperFastSimpleChassis(SimpleChassis):
|
|
146
|
+
max_speed = 36 # m/s
|
|
147
|
+
speed_change_step = max_speed / 4
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class HeavySimpleChassis(SimpleChassis):
|
|
151
|
+
max_speed = 2 # m/s
|
|
152
|
+
speed_change_step = .5
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
""" Driver is a rover controller capable of working in some of predefined modes """
|
|
2
|
+
from .modes.none import ModeNone
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Driver:
|
|
6
|
+
|
|
7
|
+
color = "white"
|
|
8
|
+
|
|
9
|
+
def __init__(self, rover):
|
|
10
|
+
self.rover = rover
|
|
11
|
+
self.mode_object = None
|
|
12
|
+
self.set_mode(ModeNone)
|
|
13
|
+
|
|
14
|
+
# HACK: properties used by some modes. We have no mechanism to set mode "parameters"
|
|
15
|
+
self.mode_waypoints_loop = None
|
|
16
|
+
|
|
17
|
+
def set_mode(self, mode):
|
|
18
|
+
self.mode_object = mode(self)
|
|
19
|
+
self.rover.scene.game.status_bar.message = f"{self.rover} is in mode {str(self.mode_object)}"
|
|
20
|
+
|
|
21
|
+
def draw(self, ux, position):
|
|
22
|
+
try:
|
|
23
|
+
self.mode_object.draw(ux, position)
|
|
24
|
+
except AttributeError:
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
def do(self):
|
|
28
|
+
""" Work done on each loop: just calling the command if exists.
|
|
29
|
+
Due to fact that command is called multiple times (say 10x/sec), every command
|
|
30
|
+
method should check the state, make adjustments and return control.
|
|
31
|
+
"""
|
|
32
|
+
if self.rover.alive:
|
|
33
|
+
|
|
34
|
+
if self.mode_object:
|
|
35
|
+
|
|
36
|
+
# auto-detonate mod. Detekuj blizke objekty a pokud je to vyhodne, exploduj
|
|
37
|
+
# pouze kdyz bot je ovladany ridicem, aby nedetonoval rucne
|
|
38
|
+
objects = self.rover.get_nearby_damageable_objects()
|
|
39
|
+
if objects:
|
|
40
|
+
foes = [x for x in objects if x.is_foe(self.rover)]
|
|
41
|
+
friends = [x for x in objects if not x.is_foe(self.rover)] # includes neutrals
|
|
42
|
+
|
|
43
|
+
foe_damage = sum([x.get_expected_damage(self.rover, self.rover.detonation_damage) for x in foes])
|
|
44
|
+
friend_damage = sum([x.get_expected_damage(self.rover, self.rover.detonation_damage) for x in friends])
|
|
45
|
+
score = foe_damage + friend_damage - friend_damage
|
|
46
|
+
|
|
47
|
+
if score > self.rover.price:
|
|
48
|
+
self.rover.detonate()
|
|
49
|
+
|
|
50
|
+
if not self.rover.alive:
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
self.mode_object.wrapped_do()
|
|
54
|
+
if self.mode_object.finished:
|
|
55
|
+
self.set_mode(ModeNone)
|
|
56
|
+
self.rover.stop()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
from . import settings
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def load_status_file():
|
|
7
|
+
try:
|
|
8
|
+
with open(settings.STATUS_FILE, "r") as f:
|
|
9
|
+
return json.load(f)
|
|
10
|
+
except FileNotFoundError:
|
|
11
|
+
return {}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def save_status_file(data):
|
|
15
|
+
data["_info"] = "This file contains saved status of battlefield_term game"
|
|
16
|
+
with open(settings.STATUS_FILE, "w") as f:
|
|
17
|
+
f.write(json.dumps(data, indent=4))
|
|
18
|
+
|