Compare commits

...

3 Commits

Author SHA1 Message Date
markojozsef
2a29f318b4 csata menük, csata nyerés, game over képernyő 2026-10-07 13:02:35 +02:00
markojozsef
7ac1a8259f vissza függvény menuItemben 2026-10-07 12:14:49 +02:00
markojozsef
75fc03a88d csata formátum dokumentáció 2026-10-07 12:13:48 +02:00
9 changed files with 675 additions and 25 deletions

View File

@@ -14,3 +14,9 @@ Teljesen AI-generált szakaszokat egy `# !!! CHATGPT !!!` komment jelzi
### battle_data.py
* csata függvények
### gamestates/battle.py
* menük
## Dokumentáció
Ezen a fájlon kívül minden dokumentáció AI generálta.

444
doc/CsataFormatum.md Normal file
View File

@@ -0,0 +1,444 @@
# Csata objektum
## Szerkezet
```python
{
"enemies": [...],
"party_members": [...],
"enemy_turn_func": ...,
"mus_id": "...",
"init_ai_data": {...},
"menus": [...],
"spells": [...],
"inventory": [...]
}
```
---
## enemies
Az ellenséges egységek listája.
### Típus
```python
list[Combatant]
```
### Példa
```python
"enemies": [
Combatant("Six-Seven kid", 120, 30, 80, 20, 0, 50, False, False),
Combatant("Ice Sprite", 60, 15, 150, 10, 0, 200, False, True),
]
```
Minden elem egy `Combatant` objektum.
---
## party_members
A játékos által irányított karakterek listája.
### Típus
```python
list[Combatant]
```
### Példa
```python
"party_members": [
Combatant("Locke", 80, 45, 130, 15, 10, 10, False, False),
Combatant("Terra", 100, 35, 100, 30, 30, 30, False, False),
]
```
A lista sorrendje határozza meg:
- a karakter pozícióját a csatában,
- a menük hozzárendelését,
- a varázslatok hozzárendelését.
---
## enemy_turn_func
Az ellenséges köröket kezelő függvény.
### Típus
```python
callable
```
### Példa
```python
"enemy_turn_func": enemy_turn_test
```
A függvényt a rendszer az ellenfelek körének feldolgozására használja.
---
## mus_id
A csata alatt lejátszandó zene azonosítója.
### Típus
```python
str
```
### Példa
```python
"mus_id": "mus_fnafsux"
```
---
## init_ai_data
Az MI számára átadott inicializáló adatok.
### Típus
```python
dict
```
---
### moves
Az MI által használható képességek gyűjteménye.
#### Típus
```python
dict[str, tuple]
```
#### Formátum
```python
"azonosító": (
név,
függvény,
célpont_szükséges
)
```
#### Paraméterek
- `név` (`str`)
A képesség megjelenő neve.
- `függvény` (`callable`)
A végrehajtandó függvény.
- `célpont_szükséges`
- `True` → ellenséges célpont szükséges
- `False` → szövetséges célpont szükséges
- `None` → nincs célpont
#### Példa
```python
"attack": (
"Physical attack",
move_attack,
True
)
```
---
### Teljes példa
```python
"moves": {
"attack": ("Physical attack", move_attack, True),
"fire": ("Fira", move_fire, True),
"ice": ("Blizzara", move_ice, True),
"cure": ("Cure", move_cure, False),
"defend": ("Defend", move_defend, None)
}
```
---
## menus
Karakterenként meghatározza a harci főmenüt.
### Típus
```python
list[list]
```
A külső lista a karaktereket reprezentálja.
A sorrendnek meg kell egyeznie a `party_members` listával.
---
### Egy karakter menüje
```python
[
["Attack", "phys_att"],
["Magic", "magic"],
["Item", "items"]
]
```
---
### Menüpont formátuma
```python
[
megjelenő_szöveg,
parancs
]
```
#### Paraméterek
- `megjelenő_szöveg` (`str`)
- `parancs` (`str`)
---
### Speciális parancsok
#### Fizikai támadás
```python
["Attack", "phys_att"]
```
#### Mágia
```python
["Magic", "magic"]
```
#### Tárgyak
```python
["Item", "items"]
```
#### Nem választható hely
```python
["", "unselectable"]
```
Ez egy üres, nem kiválasztható menüpont.
---
## spells
Karakterenként meghatározza az elérhető varázslatokat.
### Típus
```python
list[list]
```
A lista sorrendje megegyezik a `party_members` sorrendjével.
---
### Varázslat formátuma
```python
[
név,
mp_költség,
(
név,
függvény,
célpont_szükséges
)
]
```
#### Paraméterek
- `név` (`str`)
A varázslat megjelenő neve.
- `mp_költség` (`int`)
A varázslat MP költsége.
- `akció` (`tuple`)
A végrehajtandó harci művelet.
---
### Példa
```python
[
"Fira",
15,
("Fira", move_fire, True)
]
```
---
### Teljes példa
```python
"spells": [
[],
[
["Fira", 0, ("Fira", move_fire, True)],
["Blizzara", 0, ("Blizzara", move_ice, True)]
],
[
["Fira", 0, ("Fira", move_fire, True)],
["Blizzara", 0, ("Blizzara", move_ice, True)]
],
[]
]
```
Ebben az esetben:
- Locke nem rendelkezik varázslatokkal,
- Terra használhatja a **Fira** és **Blizzara** varázslatokat,
- Celes használhatja a **Fira** és **Blizzara** varázslatokat,
- Cyan nem rendelkezik varázslatokkal.
---
## inventory
A csatában használható tárgyak listája.
### Típus
```python
list
```
---
### Tárgy formátuma
```python
[
név,
mennyiség,
(
név,
függvény,
célpont_szükséges
)
]
```
#### Paraméterek
- `név` (`str`)
A tárgy megjelenő neve.
- `mennyiség` (`int`)
A rendelkezésre álló darabszám.
- `akció` (`tuple`)
A tárgy használatakor meghívandó művelet.
---
### Példa
```python
[
"Phoenix Down",
67,
(
"Phoenix Down",
move_phoenix,
False
)
]
```
---
### Teljes példa
```python
"inventory": [
[
"Phoenix Down",
67,
(
"Phoenix Down",
move_phoenix,
False
)
]
]
```
---
## Indexkapcsolatok
A következő listák indexei összetartoznak:
```python
party_members[i]
menus[i]
spells[i]
```
Példa:
```python
party_members[1] # Terra
menus[1] # Terra menüje
spells[1] # Terra varázslatai
```
Ez biztosítja, hogy minden karakter saját menüvel és saját varázslistával rendelkezzen.
---
## Összefoglaló
```python
{
"enemies": list[Combatant],
"party_members": list[Combatant],
"enemy_turn_func": callable,
"mus_id": str,
"init_ai_data": {
"moves": dict[str, tuple]
},
"menus": list[list],
"spells": list[list],
"inventory": list
}
```
Egy csata teljes egészében leírható egyetlen szótárral, amely tartalmazza az összes résztvevőt, a harci lehetőségeket, az MI által használható képességeket, valamint a játékos számára elérhető menüket, varázslatokat és tárgyakat.

View File

@@ -26,7 +26,8 @@ MenuItem(
up,
down,
action,
data=None
data=None,
back_func=None
)
```
@@ -59,6 +60,9 @@ MenuItem(
- `data` (`any`, opcionális)
A kiválasztáskor az akciónak átadott adat.
- `back_func` (`callable`)
A menüpont kiválasztásakor meghívandó függvény.
---
## Attribútumok
@@ -97,6 +101,24 @@ def start_game(data):
print("Játék indul!")
```
---
### Vissza
```python
self.back
```
A visszalépés során meghívandó függvény.
Példa:
```python
def vissza(data):
open_menu()
```
---
### Adat
@@ -105,7 +127,7 @@ def start_game(data):
self.data
```
A menüelemhez kapcsolódó opcionális adat, amelyet az akciófüggvény paraméterként kap meg.
A menüelemhez kapcsolódó opcionális adat, amelyet az akció- és visszafüggvény paraméterként kap meg.
Példa:

View File

@@ -2,12 +2,14 @@ import gamestates.none
import gamestates.title
import gamestates.overworld
import gamestates.battle
import gamestates.gameover
gamestates = {
"none": gamestates.none,
"title": gamestates.title,
"overworld": gamestates.overworld,
"battle": gamestates.battle
"battle": gamestates.battle,
"gameover": gamestates.gameover,
}
gamestate = "none"

View File

@@ -1,6 +1,8 @@
import math
import copy
import random
import arcade
import gamestate
from battle import Combatant, Action, Damage, StatusChange
from menu import MenuItem
@@ -35,30 +37,157 @@ battle_id = 0
def switch(game):
global enemies, party_members, battle_music, enemy_turn, enemy_ai_data, party_menus, spells, inventory
enemies = battle_data.battles[battle_id]["enemies"]
party_members = battle_data.battles[battle_id]["party_members"]
enemy_turn = battle_data.battles[battle_id]["enemy_turn_func"]
enemy_ai_data = battle_data.battles[battle_id]["init_ai_data"]
party_menus = battle_data.battles[battle_id]["menus"]
spells = battle_data.battles[battle_id]["spells"]
inventory = battle_data.battles[battle_id]["inventory"]
print("asdfasdfasdf")
enemies = copy.deepcopy(battle_data.battles[battle_id]["enemies"])
party_members = copy.deepcopy(battle_data.battles[battle_id]["party_members"])
enemy_turn = copy.deepcopy(battle_data.battles[battle_id]["enemy_turn_func"])
enemy_ai_data = copy.deepcopy(battle_data.battles[battle_id]["init_ai_data"])
party_menus = copy.deepcopy(battle_data.battles[battle_id]["menus"])
spells = copy.deepcopy(battle_data.battles[battle_id]["spells"])
inventory = copy.deepcopy(battle_data.battles[battle_id]["inventory"])
battle_music = assets.sounds[battle_data.battles[battle_id]["mus_id"]].play(loops=True)
def open_menu(whose):
party_idx = party_members.index(whose)
for i, m in enumerate(party_menus[party_idx]):
menu.append(MenuItem(m[0], 19, 64-(i*13), None, None, None, None, menu_action, (whose, party_members, enemies, m[1])))
for i, m in enumerate(menu):
m.up = menu[(i - 1) % len(menu)]
m.down = menu[(i + 1) % len(menu)]
menu[1].select()
def close_menu():
global menu, menu_open
menu = []
menu_open = 0
menu_text.reset("")
# !!! CHATGPT !!!
def open_spell_menu(user, aparty, eparty):
global menu
party_idx = party_members.index(user)
spell_list = spells[party_idx]
menu = []
for i, spell in enumerate(spell_list):
menu.append(
MenuItem(
spell[0],
19,
64 - (i * 13),
None,
None,
None,
None,
spell_action,
(user, spell, aparty, eparty)
)
)
if len(menu) == 0:
return
for i, m in enumerate(menu):
m.up = menu[(i - 1) % len(menu)]
m.down = menu[(i + 1) % len(menu)]
menu[0].select()
def spell_action(data):
user, spell, aparty, eparty = data
name, mp_cost, action = spell
action_name, func, target_type = action
action_queue.append(func(user, [p for p in eparty if not p.ko][0]))
close_menu()
def open_item_menu(user, aparty, eparty):
global menu
menu = []
for i, item in enumerate(inventory):
if item[1] <= 0:
continue
menu.append(
MenuItem(
f"{item[0]} x{item[1]}",
19,
64 - (i * 13),
None,
None,
None,
None,
item_action,
(user, item, aparty, eparty)
)
)
if len(menu) == 0:
return
for i, m in enumerate(menu):
m.up = menu[(i - 1) % len(menu)]
m.down = menu[(i + 1) % len(menu)]
menu[0].select()
def item_action(data):
user, item, aparty, eparty = data
name, amount, action = item
action_name, func, target_type = action
action_queue.append(
func(user, user)
)
item[1] -= 1
close_menu()
# !!! CHATGPT VÉGE !!!
def menu_action(data):
user, aparty, eparty, action = data
match action:
case "unselectable":
return
case "phys_att":
action_queue.append(Action("Physical Attack", user, eparty[0], Damage(166, 0, 0, 0), StatusChange(0, 0, 0), battle_data.anim_default))
action_queue.append(
Action(
"Physical Attack",
user,
[p for p in eparty if not p.ko][0],
Damage(166, 0, 0, 0),
StatusChange(0, 0, 0),
battle_data.anim_default
)
)
close_menu()
case "magic":
open_spell_menu(user)
case "items":
open_item_menu(user)
case _:
print(f"Unknown action: {action}")
close_menu()
@@ -113,20 +242,23 @@ def update(game, dt):
menu_open = whose
menu_text.reset(f"{whose.name}'s Menu")
menu_text.type_all()
party_idx = party_members.index(whose)
for i, m in enumerate(party_menus[party_idx]):
menu.append(MenuItem(m[0], 19, 64-(i*13), None, None, None, None, menu_action, (whose, party_members, enemies, m[1])))
for i, m in enumerate(menu):
m.up = menu[(i - 1) % len(menu)]
m.down = menu[(i + 1) % len(menu)]
menu[1].select()
open_menu(whose)
for m in menu:
m.update()
if len(enemies) != 0 and all(e.ko for e in enemies):
print("\nVICTORY! all enemies were defeated.")
battle_music.stop()
gamestate.switch_gamestate(game,"overworld")
return
if len(party_members) != 0 and all(a.ko for a in party_members):
print("\nGAME OVER! the party was defeated.")
battle_music.stop()
gamestate.switch_gamestate(game,"gameover")
return
party_text.reset(partytext)
ene_text.reset(enetext)
party_text.type_all()

View File

@@ -0,0 +1,38 @@
import menu
import text
import renderers
import gamestate
text = text.TextRenderer(90, 180, 210)
panel = renderers.NineSlicesPanel(84,100,64,100)
m = []
def retry(g):
gamestate.switch_gamestate(g, "title")
def switch(game):
global m
m = [
menu.MenuItem("Ujrapróba", 98, 150, None, None, None, None, retry, game),
menu.MenuItem("Kilépés", 98, 130, None, None, None, None, quit)
]
m[0].down = m[1]
m[1].up = m[0]
m[0].select()
text.reset("Játék vége!")
text.type_all()
def update(game, dt):
for i in m:
i.update()
def draw(game):
panel.render()
text.render()
for i in m:
i.render()

View File

@@ -2,4 +2,4 @@ import gamestate
# Azért létezik ez a "none" gamestate hogy meghívja az elsö gamestate init() funkcióját
def update(game, dt):
gamestate.switch_gamestate(game, "overworld")
gamestate.switch_gamestate(game, "gameover")

View File

@@ -34,6 +34,7 @@ def update(game, dt):
if btrans_timer >= BTRANS_DURATION:
game.mos_enabled = False
btrans_active = False
btrans_sound.stop()
gamestate.switch_gamestate(game,"battle")

View File

@@ -5,12 +5,13 @@ import controls
# Választható menüelem több menüelem közt, ha nincs valamelyik irányba másik menüelem, az irányra None értéket adunk
class MenuItem:
def __init__(self, label, x, y, left, right, up, down, action, data=None):
def __init__(self, label, x, y, left, right, up, down, action, data=None, back_func=None):
self.left = left
self.right = right
self.up = up
self.down = down
self.action = action
self.back = back_func
self.data = data
self.x = x
self.y = y
@@ -30,6 +31,10 @@ class MenuItem:
self.action(self.data)
return
if controls.is_control_pressed(5) and self.back: # Vissza
self.back(self.data)
return
if controls.is_control_pressed(0) and self.up: # Fel
controls.depress(0)
self.selected = False