├── pyxel
├── pyxelrogue
│ ├── src
│ │ ├── components
│ │ │ ├── __init__.py
│ │ │ ├── base_component.py
│ │ │ ├── inventory.py
│ │ │ └── equippable.py
│ │ ├── requirements.txt
│ │ ├── menu_background.png
│ │ ├── equipment_types.py
│ │ ├── render_order.py
│ │ ├── exceptions.py
│ │ ├── render_functions.py
│ │ ├── color.py
│ │ └── tile_types.py
│ ├── part10
│ │ ├── components
│ │ │ ├── __init__.py
│ │ │ ├── base_component.py
│ │ │ ├── inventory.py
│ │ │ └── fighter.py
│ │ ├── menu_background.png
│ │ ├── render_order.py
│ │ ├── exceptions.py
│ │ ├── render_functions.py
│ │ ├── color.py
│ │ ├── tile_types.py
│ │ ├── entity_factories.py
│ │ └── engine.py
│ ├── part11
│ │ ├── components
│ │ │ ├── __init__.py
│ │ │ ├── base_component.py
│ │ │ ├── inventory.py
│ │ │ └── fighter.py
│ │ ├── menu_background.png
│ │ ├── render_order.py
│ │ ├── exceptions.py
│ │ ├── entity_factories.py
│ │ ├── render_functions.py
│ │ ├── color.py
│ │ └── tile_types.py
│ ├── part12
│ │ ├── components
│ │ │ ├── __init__.py
│ │ │ ├── base_component.py
│ │ │ ├── inventory.py
│ │ │ └── fighter.py
│ │ ├── menu_background.png
│ │ ├── render_order.py
│ │ ├── exceptions.py
│ │ ├── entity_factories.py
│ │ ├── render_functions.py
│ │ ├── color.py
│ │ └── tile_types.py
│ ├── part13
│ │ ├── components
│ │ │ ├── __init__.py
│ │ │ ├── base_component.py
│ │ │ ├── inventory.py
│ │ │ └── equippable.py
│ │ ├── menu_background.png
│ │ ├── equipment_types.py
│ │ ├── render_order.py
│ │ ├── exceptions.py
│ │ ├── render_functions.py
│ │ ├── color.py
│ │ └── tile_types.py
│ ├── part6
│ │ ├── components
│ │ │ ├── __init__.py
│ │ │ ├── base_component.py
│ │ │ └── fighter.py
│ │ ├── render_order.py
│ │ ├── entity_factories.py
│ │ ├── main.py
│ │ ├── tile_types.py
│ │ └── engine.py
│ ├── part7
│ │ ├── components
│ │ │ ├── __init__.py
│ │ │ ├── base_component.py
│ │ │ └── fighter.py
│ │ ├── render_order.py
│ │ ├── color.py
│ │ ├── entity_factories.py
│ │ ├── tile_types.py
│ │ ├── render_functions.py
│ │ ├── main.py
│ │ └── engine.py
│ ├── part8
│ │ ├── components
│ │ │ ├── __init__.py
│ │ │ ├── base_component.py
│ │ │ ├── inventory.py
│ │ │ ├── consumable.py
│ │ │ └── fighter.py
│ │ ├── exceptions.py
│ │ ├── render_order.py
│ │ ├── color.py
│ │ ├── entity_factories.py
│ │ ├── render_functions.py
│ │ ├── tile_types.py
│ │ ├── engine.py
│ │ └── main.py
│ ├── part9
│ │ ├── components
│ │ │ ├── __init__.py
│ │ │ ├── base_component.py
│ │ │ ├── inventory.py
│ │ │ └── fighter.py
│ │ ├── exceptions.py
│ │ ├── render_order.py
│ │ ├── color.py
│ │ ├── render_functions.py
│ │ ├── tile_types.py
│ │ ├── entity_factories.py
│ │ ├── engine.py
│ │ └── main.py
│ ├── screenshots
│ │ ├── pyxelrogue01.gif
│ │ ├── pyxelrogue02.gif
│ │ ├── pyxelrogue03.gif
│ │ ├── pyxelrogue04.gif
│ │ ├── pyxelrogue05.gif
│ │ ├── pyxelrogue06.gif
│ │ ├── pyxelrogue07.gif
│ │ ├── pyxelrogue08.gif
│ │ ├── pyxelrogue09.gif
│ │ ├── pyxelrogue10.gif
│ │ ├── pyxelrogue11.gif
│ │ ├── pyxelrogue12.gif
│ │ └── pyxelrogue13.gif
│ ├── part1
│ │ ├── actions.py
│ │ ├── input_handlers.py
│ │ └── main.py
│ ├── part2
│ │ ├── actions.py
│ │ ├── entity.py
│ │ ├── game_map.py
│ │ ├── input_handlers.py
│ │ ├── main.py
│ │ ├── engine.py
│ │ └── tile_types.py
│ ├── part3
│ │ ├── actions.py
│ │ ├── entity.py
│ │ ├── game_map.py
│ │ ├── input_handlers.py
│ │ ├── engine.py
│ │ ├── tile_types.py
│ │ └── main.py
│ ├── part5
│ │ ├── entity_factories.py
│ │ ├── input_handlers.py
│ │ ├── entity.py
│ │ ├── main.py
│ │ ├── tile_types.py
│ │ ├── engine.py
│ │ └── game_map.py
│ └── part4
│ │ ├── entity.py
│ │ ├── input_handlers.py
│ │ ├── actions.py
│ │ ├── main.py
│ │ ├── game_map.py
│ │ ├── tile_types.py
│ │ └── engine.py
├── aclm
│ ├── aclm.pyxapp
│ ├── screenshots
│ │ ├── aclm01.gif
│ │ ├── aclm02.gif
│ │ └── aclm03.gif
│ └── README.md
├── nixie
│ ├── Nixie.pyxapp
│ ├── Nixie.pyxres
│ ├── screenshots
│ │ └── Nixie01.gif
│ ├── README.md
│ └── Nixie.py
├── outrun
│ ├── outrun.pyxapp
│ ├── screenshots
│ │ ├── outrun01.gif
│ │ └── outrun02.gif
│ └── README.md
├── frogger
│ ├── frogger.pyxapp
│ ├── screenshots
│ │ ├── frogger01.gif
│ │ └── frogger02.gif
│ └── README.md
├── mahjong
│ ├── mahjong.pyxapp
│ ├── mahjong.pyxres
│ ├── screenshots
│ │ └── mahjong01.png
│ ├── README.md
│ └── mahjong.py
├── pinball
│ ├── Pinball.pyxapp
│ ├── Pinball.pyxres
│ ├── screenshots
│ │ ├── Pinball01.gif
│ │ ├── Pinball02.gif
│ │ ├── Pinball03.gif
│ │ └── Pinball04.gif
│ └── README.md
├── galaxian
│ ├── galaxian.pyxapp
│ ├── galaxian.pyxres
│ ├── screenshots
│ │ └── galaxian01.gif
│ ├── README.md
│ └── galaxian.py
├── hanafuda
│ ├── hanafuda.pyxapp
│ ├── hanafuda.pyxres
│ ├── screenshots
│ │ └── hanafuda01.png
│ ├── README.md
│ └── hanafuda.py
├── sombrero
│ ├── sombrero.pyxapp
│ ├── screenshots
│ │ ├── sombrero01.png
│ │ ├── sombrero02.png
│ │ └── sombrero03.png
│ ├── README.md
│ └── sombrero.py
├── sheep
│ ├── screenshots
│ │ └── sheep01.gif
│ ├── Grass.py
│ ├── README.md
│ ├── Sheep.py
│ └── SheepAndGrass.py
├── tennis
│ ├── screenshots
│ │ └── tennis01.gif
│ ├── README.md
│ ├── Ball.py
│ └── App.py
├── autorace
│ ├── screenshots
│ │ └── autorace01.gif
│ ├── README.md
│ ├── basic.py
│ └── autorace.py
├── asteroids
│ ├── screenshots
│ │ └── asteroids01.gif
│ ├── README.md
│ ├── Bullet.py
│ ├── Ship.py
│ ├── Vec.py
│ └── Rock.py
├── pyxel2d
│ └── README.md
├── pyxelchip8
│ └── README.md
└── doc
│ ├── 230409_PyxelNote.md
│ └── 220217_PyxelNote.md
├── hsp
├── ball
│ ├── ball.hsp
│ └── screenshots
│ │ └── hsp01.png
├── mandel
│ ├── mandel.hsp
│ ├── mandel2.hsp
│ └── screenshots
│ │ ├── hsp02.png
│ │ └── hsp03.png
└── doc
│ └── 200724_HspNote.md
├── haskell
└── asteroids
│ ├── Asteroids.hs
│ ├── screenshots
│ ├── asteroids00.png
│ ├── asteroids01.png
│ └── asteroids02.png
│ ├── README.md
│ └── LICENSE
└── research
├── 99_00_NoteOnGames.md
├── 02_00_VideoGameHistory.md
├── 99_01_NoteOnGames2017.md
├── 02_07_HistoryOfAthena.md
├── 99_03_NoteOnGames2019.md
├── 01_03_AsteroidsNote.md
├── 03_00_VideoGameCollecting.md
└── 01_02_PinballNote.md
/pyxel/pyxelrogue/src/components/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part10/components/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part11/components/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part12/components/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part13/components/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part6/components/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part7/components/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part8/components/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part9/components/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/hsp/ball/ball.hsp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/hsp/ball/ball.hsp
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/src/requirements.txt:
--------------------------------------------------------------------------------
1 | tcod>=11.13
2 | numpy>=1.18
3 | pyxel>=1.9.18
4 |
--------------------------------------------------------------------------------
/hsp/mandel/mandel.hsp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/hsp/mandel/mandel.hsp
--------------------------------------------------------------------------------
/hsp/mandel/mandel2.hsp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/hsp/mandel/mandel2.hsp
--------------------------------------------------------------------------------
/pyxel/aclm/aclm.pyxapp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/aclm/aclm.pyxapp
--------------------------------------------------------------------------------
/pyxel/nixie/Nixie.pyxapp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/nixie/Nixie.pyxapp
--------------------------------------------------------------------------------
/pyxel/nixie/Nixie.pyxres:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/nixie/Nixie.pyxres
--------------------------------------------------------------------------------
/pyxel/outrun/outrun.pyxapp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/outrun/outrun.pyxapp
--------------------------------------------------------------------------------
/pyxel/frogger/frogger.pyxapp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/frogger/frogger.pyxapp
--------------------------------------------------------------------------------
/pyxel/mahjong/mahjong.pyxapp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/mahjong/mahjong.pyxapp
--------------------------------------------------------------------------------
/pyxel/mahjong/mahjong.pyxres:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/mahjong/mahjong.pyxres
--------------------------------------------------------------------------------
/pyxel/pinball/Pinball.pyxapp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pinball/Pinball.pyxapp
--------------------------------------------------------------------------------
/pyxel/pinball/Pinball.pyxres:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pinball/Pinball.pyxres
--------------------------------------------------------------------------------
/haskell/asteroids/Asteroids.hs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/haskell/asteroids/Asteroids.hs
--------------------------------------------------------------------------------
/hsp/ball/screenshots/hsp01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/hsp/ball/screenshots/hsp01.png
--------------------------------------------------------------------------------
/hsp/mandel/screenshots/hsp02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/hsp/mandel/screenshots/hsp02.png
--------------------------------------------------------------------------------
/hsp/mandel/screenshots/hsp03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/hsp/mandel/screenshots/hsp03.png
--------------------------------------------------------------------------------
/pyxel/galaxian/galaxian.pyxapp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/galaxian/galaxian.pyxapp
--------------------------------------------------------------------------------
/pyxel/galaxian/galaxian.pyxres:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/galaxian/galaxian.pyxres
--------------------------------------------------------------------------------
/pyxel/hanafuda/hanafuda.pyxapp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/hanafuda/hanafuda.pyxapp
--------------------------------------------------------------------------------
/pyxel/hanafuda/hanafuda.pyxres:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/hanafuda/hanafuda.pyxres
--------------------------------------------------------------------------------
/pyxel/sombrero/sombrero.pyxapp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/sombrero/sombrero.pyxapp
--------------------------------------------------------------------------------
/pyxel/aclm/screenshots/aclm01.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/aclm/screenshots/aclm01.gif
--------------------------------------------------------------------------------
/pyxel/aclm/screenshots/aclm02.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/aclm/screenshots/aclm02.gif
--------------------------------------------------------------------------------
/pyxel/aclm/screenshots/aclm03.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/aclm/screenshots/aclm03.gif
--------------------------------------------------------------------------------
/pyxel/nixie/screenshots/Nixie01.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/nixie/screenshots/Nixie01.gif
--------------------------------------------------------------------------------
/pyxel/outrun/screenshots/outrun01.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/outrun/screenshots/outrun01.gif
--------------------------------------------------------------------------------
/pyxel/outrun/screenshots/outrun02.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/outrun/screenshots/outrun02.gif
--------------------------------------------------------------------------------
/pyxel/sheep/screenshots/sheep01.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/sheep/screenshots/sheep01.gif
--------------------------------------------------------------------------------
/pyxel/tennis/screenshots/tennis01.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/tennis/screenshots/tennis01.gif
--------------------------------------------------------------------------------
/pyxel/frogger/screenshots/frogger01.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/frogger/screenshots/frogger01.gif
--------------------------------------------------------------------------------
/pyxel/frogger/screenshots/frogger02.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/frogger/screenshots/frogger02.gif
--------------------------------------------------------------------------------
/pyxel/mahjong/screenshots/mahjong01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/mahjong/screenshots/mahjong01.png
--------------------------------------------------------------------------------
/pyxel/pinball/screenshots/Pinball01.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pinball/screenshots/Pinball01.gif
--------------------------------------------------------------------------------
/pyxel/pinball/screenshots/Pinball02.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pinball/screenshots/Pinball02.gif
--------------------------------------------------------------------------------
/pyxel/pinball/screenshots/Pinball03.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pinball/screenshots/Pinball03.gif
--------------------------------------------------------------------------------
/pyxel/pinball/screenshots/Pinball04.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pinball/screenshots/Pinball04.gif
--------------------------------------------------------------------------------
/pyxel/autorace/screenshots/autorace01.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/autorace/screenshots/autorace01.gif
--------------------------------------------------------------------------------
/pyxel/galaxian/screenshots/galaxian01.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/galaxian/screenshots/galaxian01.gif
--------------------------------------------------------------------------------
/pyxel/hanafuda/screenshots/hanafuda01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/hanafuda/screenshots/hanafuda01.png
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/src/menu_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/src/menu_background.png
--------------------------------------------------------------------------------
/pyxel/sombrero/screenshots/sombrero01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/sombrero/screenshots/sombrero01.png
--------------------------------------------------------------------------------
/pyxel/sombrero/screenshots/sombrero02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/sombrero/screenshots/sombrero02.png
--------------------------------------------------------------------------------
/pyxel/sombrero/screenshots/sombrero03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/sombrero/screenshots/sombrero03.png
--------------------------------------------------------------------------------
/pyxel/asteroids/screenshots/asteroids01.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/asteroids/screenshots/asteroids01.gif
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part10/menu_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/part10/menu_background.png
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part11/menu_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/part11/menu_background.png
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part12/menu_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/part12/menu_background.png
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part13/menu_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/part13/menu_background.png
--------------------------------------------------------------------------------
/haskell/asteroids/screenshots/asteroids00.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/haskell/asteroids/screenshots/asteroids00.png
--------------------------------------------------------------------------------
/haskell/asteroids/screenshots/asteroids01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/haskell/asteroids/screenshots/asteroids01.png
--------------------------------------------------------------------------------
/haskell/asteroids/screenshots/asteroids02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/haskell/asteroids/screenshots/asteroids02.png
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/screenshots/pyxelrogue01.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/screenshots/pyxelrogue01.gif
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/screenshots/pyxelrogue02.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/screenshots/pyxelrogue02.gif
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/screenshots/pyxelrogue03.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/screenshots/pyxelrogue03.gif
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/screenshots/pyxelrogue04.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/screenshots/pyxelrogue04.gif
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/screenshots/pyxelrogue05.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/screenshots/pyxelrogue05.gif
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/screenshots/pyxelrogue06.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/screenshots/pyxelrogue06.gif
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/screenshots/pyxelrogue07.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/screenshots/pyxelrogue07.gif
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/screenshots/pyxelrogue08.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/screenshots/pyxelrogue08.gif
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/screenshots/pyxelrogue09.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/screenshots/pyxelrogue09.gif
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/screenshots/pyxelrogue10.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/screenshots/pyxelrogue10.gif
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/screenshots/pyxelrogue11.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/screenshots/pyxelrogue11.gif
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/screenshots/pyxelrogue12.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/screenshots/pyxelrogue12.gif
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/screenshots/pyxelrogue13.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jay-kumogata/RetroGames/HEAD/pyxel/pyxelrogue/screenshots/pyxelrogue13.gif
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part6/render_order.py:
--------------------------------------------------------------------------------
1 | from enum import auto, Enum
2 |
3 |
4 | class RenderOrder(Enum):
5 | CORPSE = auto()
6 | ITEM = auto()
7 | ACTOR = auto()
8 |
--------------------------------------------------------------------------------
/pyxel/pyxel2d/README.md:
--------------------------------------------------------------------------------
1 | # Pyxel2D
2 |
3 | ## Introduction
4 |
5 | Pyxel2D is a physics engine that runs on Pyxel/Python.
6 | Moved to [a new repository](https://github.com/jay-kumogata/Pyxel2D).
7 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/src/equipment_types.py:
--------------------------------------------------------------------------------
1 | from enum import auto, Enum
2 |
3 |
4 | class EquipmentType(Enum):
5 | WEAPON = auto()
6 | ARMOR = auto()
7 |
8 | # end of equipment_types.py
9 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part13/equipment_types.py:
--------------------------------------------------------------------------------
1 | from enum import auto, Enum
2 |
3 |
4 | class EquipmentType(Enum):
5 | WEAPON = auto()
6 | ARMOR = auto()
7 |
8 | # end of equipment_types.py
9 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part8/exceptions.py:
--------------------------------------------------------------------------------
1 | class Impossible(Exception):
2 | """Exception raised when an action is impossible to be performed.
3 |
4 | The reason is given as the exception message.
5 | """
6 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part9/exceptions.py:
--------------------------------------------------------------------------------
1 | class Impossible(Exception):
2 | """Exception raised when an action is impossible to be performed.
3 |
4 | The reason is given as the exception message.
5 | """
6 |
--------------------------------------------------------------------------------
/pyxel/pyxelchip8/README.md:
--------------------------------------------------------------------------------
1 | # PyxelChip8
2 |
3 | ## Introduction
4 |
5 | PyxelChip8 is a CHIP-8/SUPER-CHIP emulator that runs on Pyxel/Python library.
6 | Moved to [a new repository](https://github.com/jay-kumogata/PyxelChip8).
7 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/src/render_order.py:
--------------------------------------------------------------------------------
1 | from enum import auto, Enum
2 |
3 |
4 | class RenderOrder(Enum):
5 | CORPSE = auto()
6 | ITEM = auto()
7 | ACTOR = auto()
8 |
9 | # end of render_order.py
10 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part10/render_order.py:
--------------------------------------------------------------------------------
1 | from enum import auto, Enum
2 |
3 |
4 | class RenderOrder(Enum):
5 | CORPSE = auto()
6 | ITEM = auto()
7 | ACTOR = auto()
8 |
9 | # end of render_order.py
10 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part11/render_order.py:
--------------------------------------------------------------------------------
1 | from enum import auto, Enum
2 |
3 |
4 | class RenderOrder(Enum):
5 | CORPSE = auto()
6 | ITEM = auto()
7 | ACTOR = auto()
8 |
9 | # end of render_order.py
10 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part12/render_order.py:
--------------------------------------------------------------------------------
1 | from enum import auto, Enum
2 |
3 |
4 | class RenderOrder(Enum):
5 | CORPSE = auto()
6 | ITEM = auto()
7 | ACTOR = auto()
8 |
9 | # end of render_order.py
10 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part13/render_order.py:
--------------------------------------------------------------------------------
1 | from enum import auto, Enum
2 |
3 |
4 | class RenderOrder(Enum):
5 | CORPSE = auto()
6 | ITEM = auto()
7 | ACTOR = auto()
8 |
9 | # end of render_order.py
10 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part7/render_order.py:
--------------------------------------------------------------------------------
1 | from enum import auto, Enum
2 |
3 |
4 | class RenderOrder(Enum):
5 | CORPSE = auto()
6 | ITEM = auto()
7 | ACTOR = auto()
8 |
9 | # end of render_order.py
10 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part8/render_order.py:
--------------------------------------------------------------------------------
1 | from enum import auto, Enum
2 |
3 |
4 | class RenderOrder(Enum):
5 | CORPSE = auto()
6 | ITEM = auto()
7 | ACTOR = auto()
8 |
9 | # end of render_order.py
10 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part9/render_order.py:
--------------------------------------------------------------------------------
1 | from enum import auto, Enum
2 |
3 |
4 | class RenderOrder(Enum):
5 | CORPSE = auto()
6 | ITEM = auto()
7 | ACTOR = auto()
8 |
9 | # end of render_order.py
10 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part1/actions.py:
--------------------------------------------------------------------------------
1 | class Action:
2 | pass
3 |
4 |
5 | class EscapeAction(Action):
6 | pass
7 |
8 |
9 | class MovementAction(Action):
10 | def __init__(self, dx: int, dy: int):
11 | super().__init__()
12 |
13 | self.dx = dx
14 | self.dy = dy
15 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part10/exceptions.py:
--------------------------------------------------------------------------------
1 | class Impossible(Exception):
2 | """Exception raised when an action is impossible to be performed.
3 |
4 | The reason is given as the exception message.
5 | """
6 |
7 | class QuitWithoutSaving(SystemExit):
8 | """Can be raised to exit the game without automatically saving."""
9 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part11/exceptions.py:
--------------------------------------------------------------------------------
1 | class Impossible(Exception):
2 | """Exception raised when an action is impossible to be performed.
3 |
4 | The reason is given as the exception message.
5 | """
6 |
7 | class QuitWithoutSaving(SystemExit):
8 | """Can be raised to exit the game without automatically saving."""
9 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part12/exceptions.py:
--------------------------------------------------------------------------------
1 | class Impossible(Exception):
2 | """Exception raised when an action is impossible to be performed.
3 |
4 | The reason is given as the exception message.
5 | """
6 |
7 | class QuitWithoutSaving(SystemExit):
8 | """Can be raised to exit the game without automatically saving."""
9 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part13/exceptions.py:
--------------------------------------------------------------------------------
1 | class Impossible(Exception):
2 | """Exception raised when an action is impossible to be performed.
3 |
4 | The reason is given as the exception message.
5 | """
6 |
7 | class QuitWithoutSaving(SystemExit):
8 | """Can be raised to exit the game without automatically saving."""
9 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/src/exceptions.py:
--------------------------------------------------------------------------------
1 | class Impossible(Exception):
2 | """Exception raised when an action is impossible to be performed.
3 |
4 | The reason is given as the exception message.
5 | """
6 |
7 | class QuitWithoutSaving(SystemExit):
8 | """Can be raised to exit the game without automatically saving."""
9 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part2/actions.py:
--------------------------------------------------------------------------------
1 | class Action:
2 | pass
3 |
4 |
5 | class EscapeAction(Action):
6 | pass
7 |
8 |
9 | class MovementAction(Action):
10 | def __init__(self, dx: int, dy: int):
11 | super().__init__()
12 |
13 | self.dx = dx
14 | self.dy = dy
15 |
16 | # end of actions.py
17 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part3/actions.py:
--------------------------------------------------------------------------------
1 | class Action:
2 | pass
3 |
4 |
5 | class EscapeAction(Action):
6 | pass
7 |
8 |
9 | class MovementAction(Action):
10 | def __init__(self, dx: int, dy: int):
11 | super().__init__()
12 |
13 | self.dx = dx
14 | self.dy = dy
15 |
16 | # end of actions.py
17 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part5/entity_factories.py:
--------------------------------------------------------------------------------
1 | from entity import Entity
2 |
3 | player = Entity(char="@", color=7, name="Player", blocks_movement=True)
4 |
5 | orc = Entity(char="o", color=14, name="Orc", blocks_movement=True)
6 | troll = Entity(char="T", color=15, name="Troll", blocks_movement=True)
7 |
8 | # end of entity_factories.py
9 |
10 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part7/color.py:
--------------------------------------------------------------------------------
1 | white = 7
2 | black = 0
3 |
4 | player_atk = 12
5 | enemy_atk = 13
6 |
7 | player_die = 14
8 | enemy_die = 15
9 |
10 | welcome_text = 6
11 |
12 | bar_text = white
13 | bar_filled = 11
14 | bar_empty = 8
15 |
16 | # キャラクタドット数(Pyxel組込フォント)
17 | chr_x = 4
18 | chr_y = 5
19 |
20 | # end of color.py
21 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part6/components/base_component.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | if TYPE_CHECKING:
6 | from engine import Engine
7 | from entity import Entity
8 |
9 |
10 | class BaseComponent:
11 | entity: Entity # Owning entity instance.
12 |
13 | @property
14 | def engine(self) -> Engine:
15 | return self.entity.gamemap.engine
16 |
17 | # end of base_component.py
18 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part7/components/base_component.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | if TYPE_CHECKING:
6 | from engine import Engine
7 | from entity import Entity
8 |
9 |
10 | class BaseComponent:
11 | entity: Entity # Owning entity instance.
12 |
13 | @property
14 | def engine(self) -> Engine:
15 | return self.entity.gamemap.engine
16 |
17 | # end of base_component.py
18 |
--------------------------------------------------------------------------------
/pyxel/galaxian/README.md:
--------------------------------------------------------------------------------
1 | # Galaxian
2 |
3 | ## Introduction
4 |
5 | It is a demo of Galaxian.
6 |
7 | 
8 |
9 | ## How to Run
10 |
11 | Please execute the following from the Pyxel (version 2.2.10) environment.
12 | Or you can play [here](https://kitao.github.io/pyxel/wasm/launcher/?run=jay-kumogata.RetroGames.pyxel.galaxian.galaxian).
13 |
14 | > python galaxian.py
15 |
16 | ## Remarks
17 |
--------------------------------------------------------------------------------
/pyxel/hanafuda/README.md:
--------------------------------------------------------------------------------
1 | # Hanafuda Koi-Koi
2 |
3 | ## Introduction
4 |
5 | It is a demo of Hanafuda Koi-Koi (Japanese card game).
6 |
7 | 
8 |
9 | ## How to Run
10 |
11 | Please execute the following from the Pyxel (version 1.9.18) environment.
12 | Or you can play [here](https://kitao.github.io/pyxel/wasm/launcher/?run=jay-kumogata.RetroGames.pyxel.hanafuda.hanafuda).
13 |
14 | > python hanafuda.py
15 |
16 | ## Remarks
17 |
--------------------------------------------------------------------------------
/pyxel/mahjong/README.md:
--------------------------------------------------------------------------------
1 | # Mahjong
2 |
3 | ## Introduction
4 |
5 | It is a demo of Mahjong (Chinese table game).
6 |
7 |
8 |
9 | ## How to Run
10 |
11 | Please execute the following from the Pyxel (version 2.2.10) environment.
12 | Or you can play [here](https://kitao.github.io/pyxel/wasm/launcher/?run=jay-kumogata.RetroGames.pyxel.mahjong.mahjong).
13 |
14 | > python mahjong.py
15 |
16 | ## Remarks
17 |
--------------------------------------------------------------------------------
/research/99_00_NoteOnGames.md:
--------------------------------------------------------------------------------
1 | # 99_ゲーム雑記
2 |
3 | ## はじめに
4 |
5 | ゲーム(レトロゲーム含む)について,Twitter等で呟いた内容をまとめます.
6 | 時系列で未整理の内容です.
7 |
8 | - [01_ゲーム雑記2017](99_01_NoteOnGames2017.md)
9 | - [01_ゲーム雑記2018](99_02_NoteOnGames2018.md)
10 | - [01_ゲーム雑記2019](99_03_NoteOnGames2019.md)
11 | - [01_ゲーム雑記2020](99_04_NoteOnGames2020.md)
12 | - [01_ゲーム雑記2021](99_05_NoteOnGames2021.md)
13 | - [01_ゲーム雑記2022](99_06_NoteOnGames2022.md)
14 | - [01_ゲーム雑記2023](99_07_NoteOnGames2023.md)
15 | - [01_ゲーム雑記2024](99_08_NoteOnGames2024.md)
16 |
17 | 以上
18 |
--------------------------------------------------------------------------------
/pyxel/sheep/Grass.py:
--------------------------------------------------------------------------------
1 | import pyxel
2 |
3 | class Grass:
4 |
5 | def __init__(self, x, y, sz):
6 | self.x = x
7 | self.y = y
8 | self.energy = 20 # この牧草を食べたときに得られる体力
9 | self.eaten = False # まだ食べられていない状態
10 | self.sz = sz
11 |
12 | def update(self):
13 | if self.eaten:
14 | pyxel.rect(self.x, self.y, self.sz, self.sz, 4) # 茶
15 | else:
16 | pyxel.rect(self.x, self.y, self.sz, self.sz, 3) # 緑
17 |
18 | # End of Grass.py
19 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part2/entity.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | class Entity:
4 | """
5 | A generic object to represent players, enemies, items, etc.
6 | """
7 | def __init__(self, x: int, y: int, char: str, color: int):
8 | self.x = x
9 | self.y = y
10 | self.char = char
11 | self.color = color
12 |
13 | def move(self, dx: int, dy: int) -> None:
14 | # Move the entity by a given amount
15 | self.x += dx
16 | self.y += dy
17 |
18 | # end of entity.py
19 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part3/entity.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | class Entity:
4 | """
5 | A generic object to represent players, enemies, items, etc.
6 | """
7 | def __init__(self, x: int, y: int, char: str, color: int):
8 | self.x = x
9 | self.y = y
10 | self.char = char
11 | self.color = color
12 |
13 | def move(self, dx: int, dy: int) -> None:
14 | # Move the entity by a given amount
15 | self.x += dx
16 | self.y += dy
17 |
18 | # end of entity.py
19 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part4/entity.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | class Entity:
4 | """
5 | A generic object to represent players, enemies, items, etc.
6 | """
7 | def __init__(self, x: int, y: int, char: str, color: int):
8 | self.x = x
9 | self.y = y
10 | self.char = char
11 | self.color = color
12 |
13 | def move(self, dx: int, dy: int) -> None:
14 | # Move the entity by a given amount
15 | self.x += dx
16 | self.y += dy
17 |
18 | # end of entity.py
19 |
--------------------------------------------------------------------------------
/pyxel/sombrero/README.md:
--------------------------------------------------------------------------------
1 | # Mexican hat (sombrero) demo
2 |
3 | ## Introduction
4 |
5 | It is a demo of Mexican hat (sombrero) graphics.
6 |
7 |
8 |
9 | ## How to Run
10 |
11 | Please execute the following from the Pyxel (version 2.0.13) environment.
12 | Or you can play [here](https://kitao.github.io/pyxel/wasm/launcher/?run=jay-kumogata.RetroGames.pyxel.sombrero.sombrero&packages=numpy).
13 |
14 | > python sombrero.py
15 |
16 | ## Remarks
17 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part8/components/base_component.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | if TYPE_CHECKING:
6 | from engine import Engine
7 | from entity import Entity
8 | from game_map import GameMap
9 |
10 | class BaseComponent:
11 | parent: Entity # Owning entity instance.
12 |
13 | @property
14 | def gamemap(self) -> GameMap:
15 | return self.parent.gamemap
16 |
17 | @property
18 | def engine(self) -> Engine:
19 | return self.gamemap.engine
20 |
21 | # end of base_component.py
22 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part9/components/base_component.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | if TYPE_CHECKING:
6 | from engine import Engine
7 | from entity import Entity
8 | from game_map import GameMap
9 |
10 | class BaseComponent:
11 | parent: Entity # Owning entity instance.
12 |
13 | @property
14 | def gamemap(self) -> GameMap:
15 | return self.parent.gamemap
16 |
17 | @property
18 | def engine(self) -> Engine:
19 | return self.gamemap.engine
20 |
21 | # end of base_component.py
22 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/src/components/base_component.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | if TYPE_CHECKING:
6 | from engine import Engine
7 | from entity import Entity
8 | from game_map import GameMap
9 |
10 | class BaseComponent:
11 | parent: Entity # Owning entity instance.
12 |
13 | @property
14 | def gamemap(self) -> GameMap:
15 | return self.parent.gamemap
16 |
17 | @property
18 | def engine(self) -> Engine:
19 | return self.gamemap.engine
20 |
21 | # end of base_component.py
22 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part10/components/base_component.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | if TYPE_CHECKING:
6 | from engine import Engine
7 | from entity import Entity
8 | from game_map import GameMap
9 |
10 | class BaseComponent:
11 | parent: Entity # Owning entity instance.
12 |
13 | @property
14 | def gamemap(self) -> GameMap:
15 | return self.parent.gamemap
16 |
17 | @property
18 | def engine(self) -> Engine:
19 | return self.gamemap.engine
20 |
21 | # end of base_component.py
22 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part11/components/base_component.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | if TYPE_CHECKING:
6 | from engine import Engine
7 | from entity import Entity
8 | from game_map import GameMap
9 |
10 | class BaseComponent:
11 | parent: Entity # Owning entity instance.
12 |
13 | @property
14 | def gamemap(self) -> GameMap:
15 | return self.parent.gamemap
16 |
17 | @property
18 | def engine(self) -> Engine:
19 | return self.gamemap.engine
20 |
21 | # end of base_component.py
22 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part12/components/base_component.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | if TYPE_CHECKING:
6 | from engine import Engine
7 | from entity import Entity
8 | from game_map import GameMap
9 |
10 | class BaseComponent:
11 | parent: Entity # Owning entity instance.
12 |
13 | @property
14 | def gamemap(self) -> GameMap:
15 | return self.parent.gamemap
16 |
17 | @property
18 | def engine(self) -> Engine:
19 | return self.gamemap.engine
20 |
21 | # end of base_component.py
22 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part13/components/base_component.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | if TYPE_CHECKING:
6 | from engine import Engine
7 | from entity import Entity
8 | from game_map import GameMap
9 |
10 | class BaseComponent:
11 | parent: Entity # Owning entity instance.
12 |
13 | @property
14 | def gamemap(self) -> GameMap:
15 | return self.parent.gamemap
16 |
17 | @property
18 | def engine(self) -> Engine:
19 | return self.gamemap.engine
20 |
21 | # end of base_component.py
22 |
--------------------------------------------------------------------------------
/pyxel/sheep/README.md:
--------------------------------------------------------------------------------
1 | # Eating sheep program
2 |
3 | ## Introduction
4 |
5 | I ported the "Eating sheep program" introduced
6 | in a book ["Math Adventures with Python"](https://nostarch.com/mathadventures) to Pyxel.
7 | It is a simulation of sheep moving while eating grass.
8 | When there is no more grass to eat, they will be taken to heaven.
9 |
10 | 
11 |
12 | ## How to Run
13 |
14 | Please execute the following from the Pyxel (version 2.0.13) environment.
15 |
16 | > python SheepAndGrass.py
17 |
18 | ## Remarks
19 |
--------------------------------------------------------------------------------
/pyxel/outrun/README.md:
--------------------------------------------------------------------------------
1 | # Outrun for Pyxel/Python
2 |
3 | ## Introduction
4 |
5 | It is a Outrun(Sega/1986) demo.
6 |
7 |
8 |
9 | ## How to Play
10 |
11 | Please execute the following from the Pyxel (version 2.2.10) environment.
12 | Or you can play [here](https://kitao.github.io/pyxel/wasm/launcher/?run=jay-kumogata.RetroGames.pyxel.outrun.outrun).
13 |
14 | > python outrun.py
15 |
16 | ## Remarks
17 |
18 | [Simple OutRun in pseudo 3D](https://zenn.dev/sdkfz181tiger/articles/5b96fc307510a3) has been converted into Pyxel/Python using Grok4.
19 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part8/color.py:
--------------------------------------------------------------------------------
1 | import pyxel
2 |
3 | white = 7
4 | black = 0
5 |
6 | player_atk = 12
7 | enemy_atk = 13
8 |
9 | player_die = 14
10 | enemy_die = 15
11 |
12 | invalid = 9
13 | impossible = 10
14 | error = 2
15 |
16 | welcome_text = 6
17 | health_recovered = 3
18 |
19 | bar_text = white
20 | bar_filled = 11
21 | bar_empty = 8
22 |
23 | # キャラクタドット数(Pyxel組込フォント)
24 | chr_x = 4
25 | chr_y = 5
26 |
27 | # Pyxel向けヘルパー関数
28 | def rect(x: int, y: int, w: int, h: int, col: int):
29 | pyxel.rect(x*chr_x, y*chr_y, w*chr_x, h*chr_y, col)
30 |
31 | def text(x: int, y: int, s: str, col: int):
32 | pyxel.text(x*chr_x, y*chr_y, s, col)
33 |
34 | # end of color.py
35 |
--------------------------------------------------------------------------------
/pyxel/asteroids/README.md:
--------------------------------------------------------------------------------
1 | # Asteroids in Pyxel/Python
2 |
3 | ## Introduction
4 |
5 | I ported Asteroids, which was implemented in Haskell, to Pyxel/Python.
6 |
7 |
8 |
9 | ## How to run
10 |
11 | > python Asteroids.py
12 |
13 | ## How to Play
14 |
15 | You rotate your ship with [Left] and [Right] keys,
16 | and shoot a bullet with [Space] key and split the meteorite.
17 | Small meteorites are extinguished.
18 | If you hit a meteorite, the game is over.
19 | You can replay with [Enter] key.
20 | If you split the meteorite, you will get 100 points,
21 | and if you eliminate it, you will get 500 points.
22 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part6/entity_factories.py:
--------------------------------------------------------------------------------
1 | from components.ai import HostileEnemy
2 | from components.fighter import Fighter
3 | from entity import Actor
4 |
5 | player = Actor(
6 | char="@",
7 | color=7,
8 | name="Player",
9 | ai_cls=HostileEnemy,
10 | fighter=Fighter(hp=30, defense=2, power=5),
11 | )
12 |
13 | orc = Actor(
14 | char="o",
15 | color=8,
16 | name="Orc",
17 | ai_cls=HostileEnemy,
18 | fighter=Fighter(hp=10, defense=0, power=3),
19 | )
20 | troll = Actor(
21 | char="T",
22 | color=9,
23 | name="Troll",
24 | ai_cls=HostileEnemy,
25 | fighter=Fighter(hp=16, defense=1, power=4),
26 | )
27 |
28 | # end of entity_factories.py
29 |
30 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part7/entity_factories.py:
--------------------------------------------------------------------------------
1 | from components.ai import HostileEnemy
2 | from components.fighter import Fighter
3 | from entity import Actor
4 |
5 | player = Actor(
6 | char="@",
7 | color=7,
8 | name="Player",
9 | ai_cls=HostileEnemy,
10 | fighter=Fighter(hp=30, defense=2, power=5),
11 | )
12 |
13 | orc = Actor(
14 | char="o",
15 | color=8,
16 | name="Orc",
17 | ai_cls=HostileEnemy,
18 | fighter=Fighter(hp=10, defense=0, power=3),
19 | )
20 | troll = Actor(
21 | char="T",
22 | color=9,
23 | name="Troll",
24 | ai_cls=HostileEnemy,
25 | fighter=Fighter(hp=16, defense=1, power=4),
26 | )
27 |
28 | # end of entity_factories.py
29 |
30 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part3/game_map.py:
--------------------------------------------------------------------------------
1 | import numpy as np # type: ignore
2 | import pyxel
3 |
4 | import tile_types
5 |
6 | class GameMap:
7 | def __init__(self, width: int, height: int):
8 | self.width, self.height = width, height
9 | self.tiles = np.full((width, height), fill_value=tile_types.wall, order="F")
10 |
11 | def in_bounds(self, x: int, y: int) -> bool:
12 | """Return True if x and y are inside of the bounds of this map."""
13 | return 0 <= x < self.width and 0 <= y < self.height
14 |
15 | def render(self) -> None:
16 | for x in range(self.width):
17 | for y in range(self.height):
18 | pyxel.pset(x,y,self.tiles["dark"][x,y]["fg"])
19 |
20 | # end of game_map.py
21 |
--------------------------------------------------------------------------------
/pyxel/frogger/README.md:
--------------------------------------------------------------------------------
1 | # Frogger for Pyxel/Python
2 |
3 | ## Introduction
4 |
5 | It is a Frogger(Konami/1981) clone.
6 |
7 |
8 |
9 | ## How to Play
10 |
11 | Please execute the following from the Pyxel (version 2.2.10) environment.
12 | Or you can play [here](https://kitao.github.io/pyxel/wasm/launcher/?run=jay-kumogata.RetroGames.pyxel.frogger.frogger).
13 |
14 | > python frogger.py
15 |
16 | ## How to Controll
17 |
18 | Use the [up] / [down] / [left] / [right] key to move up / down / left / right.
19 |
20 | ## Remarks
21 |
22 | [Basic Frogger](https://gist.github.com/straker/82a4368849cbd441b05bd6a044f2b2d3) has been converted into Pyxel/Python using Grok3.
23 |
--------------------------------------------------------------------------------
/pyxel/pinball/README.md:
--------------------------------------------------------------------------------
1 | # Pinball
2 |
3 | ## Introduction
4 |
5 | I ported Mr. Isidor's [Pinball Pong](https://www.lexaloffle.com/bbs/?tid=28488) to Pyxel/Python.
6 | It's a pinball game, or rather, a combination of pinball and Atari's Breakout.
7 |
8 |
9 |
10 | ## How to Run
11 |
12 | Please execute the following from the Pyxel (version 1.9.18) environment.
13 | Or you can play [here](https://kitao.github.io/pyxel/wasm/launcher/?run=jay-kumogata.RetroGames.pyxel.pinball.Pinball).
14 |
15 | > python Pinball.py
16 |
17 | ## How to Control
18 |
19 | - [right-arrow]: Flip the right flippers
20 | - [left-arrow]: Flip the left flippers
21 | - [SPACE]: Start game again
22 |
--------------------------------------------------------------------------------
/pyxel/nixie/README.md:
--------------------------------------------------------------------------------
1 | # Nixie tube clock
2 |
3 | ## Introduction
4 |
5 | It is a demo of the Nixie tube clock.
6 |
7 | 
8 |
9 | ## How to Run
10 |
11 | Please execute the following from the Pyxel (version 1.7.1) environment.
12 | Or you can play [here](https://kitao.github.io/pyxel/wasm/launcher/?run=jay-kumogata.RetroGames.pyxel.nixie.Nixie).
13 |
14 | > python Nixie.py
15 |
16 | ## Remarks
17 |
18 | I started making Nixie tube clocks with Pyxel.
19 | First, I drew a dot picture of a Nixie tube, but it looks like a toy.
20 | I had an LED calculator that runs an LED check (count up) when the power is turned off and on, but I remembered that.
21 | It is delicate whether to make this continuation.
22 |
--------------------------------------------------------------------------------
/pyxel/asteroids/Bullet.py:
--------------------------------------------------------------------------------
1 | import pyxel
2 | from Vec import *
3 |
4 | class Bullet():
5 | def __init__(self, p : Vec, v : Vec, a : int):
6 | # 弾情報Bulletは,座標Vec,速度Velocity,年齢Ageから構成.
7 | self.p = p
8 | self.v = v
9 | self.a = a
10 | self.l = True # 生死フラグ
11 |
12 | def update(self, timeStep : float):
13 |
14 | # 50サイクルで消滅
15 | if self.a > 50:
16 | self.l = False
17 | # timeStep分移動
18 | else:
19 | self.p = self.p.add(self.v.mul(timeStep))
20 | self.p = self.p.restoreToScreen()
21 | self.a += timeStep
22 |
23 | def draw(self):
24 | # 弾を表示
25 | pyxel.circb(self.p.x+160, self.p.y+160, 1, 7)
26 |
27 | # End of Bullet.py
28 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part1/input_handlers.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 | import pyxel
3 | from actions import Action, EscapeAction, MovementAction
4 |
5 | class EventHandler:
6 | def dispatch(self) -> Optional[Action]:
7 | action = None
8 | if pyxel.btnp(pyxel.KEY_UP):
9 | action = MovementAction(dx=0, dy=-1)
10 | elif pyxel.btnp(pyxel.KEY_DOWN):
11 | action = MovementAction(dx=0, dy=1)
12 | elif pyxel.btnp(pyxel.KEY_LEFT):
13 | action = MovementAction(dx=-1, dy=0)
14 | elif pyxel.btnp(pyxel.KEY_RIGHT):
15 | action = MovementAction(dx=1, dy=0)
16 |
17 | elif pyxel.btnp(pyxel.KEY_ESCAPE):
18 | action = EscapeAction()
19 |
20 | # No valid key was pressed
21 | return action
22 |
--------------------------------------------------------------------------------
/pyxel/autorace/README.md:
--------------------------------------------------------------------------------
1 | # Autorace
2 |
3 | ## Introduction
4 |
5 | I ported Miss Harumi Takahasi's [Autorace(one screen software)](https://archive.org/details/Fm-7Fm-8/page/n173/mode/2up) to Pyxel/Python.
6 | The original was published in [FM-7 FM-8 Harumi's Game Library](https://archive.org/details/Fm-7Fm-8/).
7 | This is a game where you operate your car and avoid obstacles.
8 | It is extremely difficult.
9 |
10 |
11 |
12 | ## How to Run
13 |
14 | Please execute the following from the Pyxel (version 2.0.0) environment.
15 |
16 | > python autorace.py
17 |
18 | ## How to Control
19 |
20 | - [Right]: Move car to the right
21 | - [Left]: Move car to the left
22 | - [S\]: Replay the game
23 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part2/game_map.py:
--------------------------------------------------------------------------------
1 | import numpy as np # type: ignore
2 | import pyxel
3 |
4 | import tile_types
5 |
6 | class GameMap:
7 | def __init__(self, width: int, height: int):
8 | self.width, self.height = width, height
9 | self.tiles = np.full((width, height), fill_value=tile_types.floor, order="F")
10 |
11 | self.tiles[30:33, 22] = tile_types.wall
12 |
13 | def in_bounds(self, x: int, y: int) -> bool:
14 | """Return True if x and y are inside of the bounds of this map."""
15 | return 0 <= x < self.width and 0 <= y < self.height
16 |
17 | def render(self) -> None:
18 | for x in range(self.width):
19 | for y in range(self.height):
20 | pyxel.pset(x,y,self.tiles["dark"][x,y]["fg"])
21 |
22 | # end of game_map.py
23 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part2/input_handlers.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 | import pyxel
3 | from actions import Action, EscapeAction, MovementAction
4 |
5 | class EventHandler:
6 | def dispatch(self) -> Optional[Action]:
7 | action = None
8 | if pyxel.btnp(pyxel.KEY_UP):
9 | action = MovementAction(dx=0, dy=-1)
10 | elif pyxel.btnp(pyxel.KEY_DOWN):
11 | action = MovementAction(dx=0, dy=1)
12 | elif pyxel.btnp(pyxel.KEY_LEFT):
13 | action = MovementAction(dx=-1, dy=0)
14 | elif pyxel.btnp(pyxel.KEY_RIGHT):
15 | action = MovementAction(dx=1, dy=0)
16 |
17 | elif pyxel.btnp(pyxel.KEY_ESCAPE):
18 | action = EscapeAction()
19 |
20 | # No valid key was pressed
21 | return action
22 |
23 | # end of input_handlers.py
24 |
--------------------------------------------------------------------------------
/pyxel/tennis/README.md:
--------------------------------------------------------------------------------
1 | # Tennis-for-Two
2 |
3 | ## Introduction
4 |
5 | Tennis-for-Two is a sports video game that simulates a game of tennis,
6 | and was one of the first games developed in the early history of video games.
7 |
8 |
9 |
10 | ## How to Play
11 |
12 | Please execute the following from the Pyxel (version 2.2.10) environment.
13 |
14 | > python App.py
15 |
16 | ## How to Controll
17 |
18 | ### Player #1
19 |
20 | - [W] / [S]: Turn volume #1 to left / right
21 | - [D]: Hit a ball
22 |
23 | ### Player #2
24 |
25 | - [UP] / [DOWN]: Turn volume #2 to left / right
26 | - [LEFT]: Hit a ball
27 |
28 | ## Remarks
29 |
30 | I also ported the processing program, [Tennis For Two](https://openprocessing.org/sketch/9892/), into Pyxel/Python.
31 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part3/input_handlers.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 | import pyxel
3 | from actions import Action, EscapeAction, MovementAction
4 |
5 | class EventHandler:
6 | def dispatch(self) -> Optional[Action]:
7 | action = None
8 |
9 | if pyxel.btnp(pyxel.KEY_UP):
10 | action = MovementAction(dx=0, dy=-1)
11 | elif pyxel.btnp(pyxel.KEY_DOWN):
12 | action = MovementAction(dx=0, dy=1)
13 | elif pyxel.btnp(pyxel.KEY_LEFT):
14 | action = MovementAction(dx=-1, dy=0)
15 | elif pyxel.btnp(pyxel.KEY_RIGHT):
16 | action = MovementAction(dx=1, dy=0)
17 |
18 | elif pyxel.btnp(pyxel.KEY_ESCAPE):
19 | action = EscapeAction()
20 |
21 | # No valid key was pressed
22 | return action
23 |
24 | # end of input_handlers.py
25 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part10/components/inventory.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import List, TYPE_CHECKING
4 |
5 | from components.base_component import BaseComponent
6 |
7 | if TYPE_CHECKING:
8 | from entity import Actor, Item
9 |
10 |
11 | class Inventory(BaseComponent):
12 | parent: Actor
13 |
14 | def __init__(self, capacity: int):
15 | self.capacity = capacity
16 | self.items: List[Item] = []
17 |
18 | def drop(self, item: Item) -> None:
19 | """
20 | Removes an item from the inventory and restores it to the game map, at the player's current location.
21 | """
22 | self.items.remove(item)
23 | item.place(self.parent.x, self.parent.y, self.gamemap)
24 |
25 | self.engine.message_log.add_message(f"You dropped the {item.name}.")
26 |
27 | # end of inventory.py
28 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part11/components/inventory.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import List, TYPE_CHECKING
4 |
5 | from components.base_component import BaseComponent
6 |
7 | if TYPE_CHECKING:
8 | from entity import Actor, Item
9 |
10 |
11 | class Inventory(BaseComponent):
12 | parent: Actor
13 |
14 | def __init__(self, capacity: int):
15 | self.capacity = capacity
16 | self.items: List[Item] = []
17 |
18 | def drop(self, item: Item) -> None:
19 | """
20 | Removes an item from the inventory and restores it to the game map, at the player's current location.
21 | """
22 | self.items.remove(item)
23 | item.place(self.parent.x, self.parent.y, self.gamemap)
24 |
25 | self.engine.message_log.add_message(f"You dropped the {item.name}.")
26 |
27 | # end of inventory.py
28 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part12/components/inventory.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import List, TYPE_CHECKING
4 |
5 | from components.base_component import BaseComponent
6 |
7 | if TYPE_CHECKING:
8 | from entity import Actor, Item
9 |
10 |
11 | class Inventory(BaseComponent):
12 | parent: Actor
13 |
14 | def __init__(self, capacity: int):
15 | self.capacity = capacity
16 | self.items: List[Item] = []
17 |
18 | def drop(self, item: Item) -> None:
19 | """
20 | Removes an item from the inventory and restores it to the game map, at the player's current location.
21 | """
22 | self.items.remove(item)
23 | item.place(self.parent.x, self.parent.y, self.gamemap)
24 |
25 | self.engine.message_log.add_message(f"You dropped the {item.name}.")
26 |
27 | # end of inventory.py
28 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part13/components/inventory.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import List, TYPE_CHECKING
4 |
5 | from components.base_component import BaseComponent
6 |
7 | if TYPE_CHECKING:
8 | from entity import Actor, Item
9 |
10 |
11 | class Inventory(BaseComponent):
12 | parent: Actor
13 |
14 | def __init__(self, capacity: int):
15 | self.capacity = capacity
16 | self.items: List[Item] = []
17 |
18 | def drop(self, item: Item) -> None:
19 | """
20 | Removes an item from the inventory and restores it to the game map, at the player's current location.
21 | """
22 | self.items.remove(item)
23 | item.place(self.parent.x, self.parent.y, self.gamemap)
24 |
25 | self.engine.message_log.add_message(f"You dropped the {item.name}.")
26 |
27 | # end of inventory.py
28 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part8/components/inventory.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import List, TYPE_CHECKING
4 |
5 | from components.base_component import BaseComponent
6 |
7 | if TYPE_CHECKING:
8 | from entity import Actor, Item
9 |
10 |
11 | class Inventory(BaseComponent):
12 | parent: Actor
13 |
14 | def __init__(self, capacity: int):
15 | self.capacity = capacity
16 | self.items: List[Item] = []
17 |
18 | def drop(self, item: Item) -> None:
19 | """
20 | Removes an item from the inventory and restores it to the game map, at the player's current location.
21 | """
22 | self.items.remove(item)
23 | item.place(self.parent.x, self.parent.y, self.gamemap)
24 |
25 | self.engine.message_log.add_message(f"You dropped the {item.name}.")
26 |
27 | # end of inventory.py
28 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part9/components/inventory.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import List, TYPE_CHECKING
4 |
5 | from components.base_component import BaseComponent
6 |
7 | if TYPE_CHECKING:
8 | from entity import Actor, Item
9 |
10 |
11 | class Inventory(BaseComponent):
12 | parent: Actor
13 |
14 | def __init__(self, capacity: int):
15 | self.capacity = capacity
16 | self.items: List[Item] = []
17 |
18 | def drop(self, item: Item) -> None:
19 | """
20 | Removes an item from the inventory and restores it to the game map, at the player's current location.
21 | """
22 | self.items.remove(item)
23 | item.place(self.parent.x, self.parent.y, self.gamemap)
24 |
25 | self.engine.message_log.add_message(f"You dropped the {item.name}.")
26 |
27 | # end of inventory.py
28 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/src/components/inventory.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import List, TYPE_CHECKING
4 |
5 | from components.base_component import BaseComponent
6 |
7 | if TYPE_CHECKING:
8 | from entity import Actor, Item
9 |
10 |
11 | class Inventory(BaseComponent):
12 | parent: Actor
13 |
14 | def __init__(self, capacity: int):
15 | self.capacity = capacity
16 | self.items: List[Item] = []
17 |
18 | def drop(self, item: Item) -> None:
19 | """
20 | Removes an item from the inventory and restores it to the game map, at the player's current location.
21 | """
22 | self.items.remove(item)
23 | item.place(self.parent.x, self.parent.y, self.gamemap)
24 |
25 | self.engine.message_log.add_message(f"You dropped the {item.name}.")
26 |
27 | # end of inventory.py
28 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part4/input_handlers.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 | import pyxel
3 | from actions import Action, EscapeAction, MovementAction
4 |
5 | class EventHandler:
6 | def dispatch(self) -> Optional[Action]:
7 | # メモ: 何も押されていない場合はNoneを返却
8 | action = None
9 |
10 | if pyxel.btnp(pyxel.KEY_UP):
11 | action = MovementAction(dx=0, dy=-1)
12 | elif pyxel.btnp(pyxel.KEY_DOWN):
13 | action = MovementAction(dx=0, dy=1)
14 | elif pyxel.btnp(pyxel.KEY_LEFT):
15 | action = MovementAction(dx=-1, dy=0)
16 | elif pyxel.btnp(pyxel.KEY_RIGHT):
17 | action = MovementAction(dx=1, dy=0)
18 |
19 | elif pyxel.btnp(pyxel.KEY_ESCAPE):
20 | action = EscapeAction()
21 |
22 | # No valid key was pressed
23 | return action
24 |
25 | # end of input_handlers.py
26 |
--------------------------------------------------------------------------------
/research/02_00_VideoGameHistory.md:
--------------------------------------------------------------------------------
1 | # 02_ゲーム史研究
2 |
3 | ## はじめに
4 |
5 | ゲームの歴史を調べるテーマです.
6 |
7 | - サブテーマリスト
8 | - [01_進化論的アプローチ](https://github.com/jay-kumogata/RetroGames/blob/main/research/02_01_EvolutionaryApproach.md): いかにゲーム作品が進化したかを進化論(生物学)のアナロジーで研究(→比較的主流派)
9 | - [02_産業論的アプローチ](https://github.com/jay-kumogata/RetroGames/blob/main/research/02_02_IndustrialApproach.md): いかにゲーム産業が発展したかを産業論として研究
10 | - 例: スペースインベーダーが進化してギャラクシアンが開発等
11 | - [03_ゲームマシンアーカイブ](https://github.com/jay-kumogata/RetroGames/blob/main/research/02_03_GMANote.md): GM誌を年代別に調査
12 | - [04_海外ゲーム史研究](https://github.com/jay-kumogata/RetroGames/blob/main/research/02_04_WesternGames.md): 海外のゲーム史を調査
13 | - 05_野球ゲーム史研究: 野球のゲーム史を調査(→野球にスポットをあてるのは個人的な理由)
14 | - 06_影響論: ゲームをすることでどんな影響がでるか(→厳密には歴史ではない)
15 | - 例: 子供が狂暴になる等
16 | - [07_社史編纂](https://github.com/jay-kumogata/RetroGames/blob/main/research/02_07_HistoryOfAthena.md): アテナ社
17 |
18 | 以上
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part9/color.py:
--------------------------------------------------------------------------------
1 | import pyxel
2 |
3 | white = 7
4 | black = 0
5 | red = 8
6 |
7 | player_atk = 12
8 | enemy_atk = 13
9 |
10 | player_die = 14
11 | enemy_die = 15
12 | needs_target = 5
13 | status_effect_applied = 6
14 |
15 | invalid = 9
16 | impossible = 10
17 | error = 2
18 |
19 | welcome_text = 6
20 | health_recovered = 3
21 |
22 | bar_text = white
23 | bar_filled = 11
24 | bar_empty = 8
25 |
26 | # メモ: 以下、色(color)とは直接関係ないコード(Pyxel関連)
27 |
28 | # メモ: 組込フォントのドット数(4x5)
29 | chr_x = 4
30 | chr_y = 5
31 |
32 | # メモ: ヘルパー関数
33 | def rect(x: int, y: int, w: int, h: int, col: int):
34 | pyxel.rect(x*chr_x, y*chr_y, w*chr_x, h*chr_y, col)
35 |
36 | def rectb(x: int, y: int, w: int, h: int, col: int):
37 | pyxel.rectb(x*chr_x, y*chr_y, w*chr_x, h*chr_y, col)
38 |
39 | def text(x: int, y: int, s: str, col: int):
40 | pyxel.text(x*chr_x, y*chr_y, s, col)
41 |
42 | # end of color.py
43 |
--------------------------------------------------------------------------------
/pyxel/mahjong/mahjong.py:
--------------------------------------------------------------------------------
1 | #
2 | # 麻雀デモ
3 | # まぐち氏作の「mahjong! #アイロンビーズ #ドット絵 #麻雀 #mahjong」を参考にしました.
4 | # https://x.com/maguchi_tweet/status/876398803732934657
5 | #
6 | # Feb 07, 2025 ver.1 (first release)
7 | #
8 | # -*- coding: utf-8 -*-
9 | import pyxel
10 | import random
11 |
12 | class Mahjong:
13 | def __init__( self ):
14 | pyxel.init( 96, 96, title="Mahjong", fps=20)
15 | pyxel.load( "mahjong.pyxres")
16 | pyxel.run(self.update, self.draw)
17 |
18 | def update( self ):
19 | """NONE"""
20 |
21 | def draw( self ):
22 | pyxel.cls(3)
23 |
24 | for m in range(4):
25 | for n in range(9):
26 | self.draw_pi(m, n, n*9+7, m*11+26)
27 |
28 | # m: 種類(0:字牌, 1:索子, 2:筒子, 3:萬子)
29 | # n: 順番(数牌:0~8, 字牌: 0~6)
30 | def draw_pi( self, m, n, x, y):
31 | pyxel.blt( x, y, 0, n*8, m*16, 8, 10 )
32 |
33 | # Main
34 | Mahjong()
35 |
36 | # End of mahjong.py
37 |
--------------------------------------------------------------------------------
/pyxel/doc/230409_PyxelNote.md:
--------------------------------------------------------------------------------
1 | ## Pyxelによるゲーム開発記(2023年編)
2 |
3 | ### はじめに
4 |
5 | レトロゲームエンジン [Pyxel](https://github.com/kitao/pyxel) によるゲーム開発の記録です.
6 |
7 | ### 2023-04-09
8 |
9 | 数式でアートが作れるなら,数式で遊びが作れるのだろうか.と考えながら散歩しました.多分できないです.
10 | 数式でできるのは,シミュレーションまでです.それを遊びにするのは,ホモ・ルーデンスである我々ということになります.
11 |
12 | 例えば,月面着陸船の挙動を数式で表して,それを月面着陸シミュレーションにすることはできます.
13 | でも,それを訓練と思うか,遊びと思うかは,あくまで我々ということです.
14 | そもそも,数式でアートが作れるというのも,数式でシミュレーション(もしくは単なる模様)が作れるだけです.
15 | それを美しいと思うのは我々なんだなと思います.
16 | 何を芸術と思うか,何を遊びと考えるか,ということを,他の人と共有できれば,それらは芸術や遊びとして成立するのでしょう.
17 | 数式で遊びが作れるか,という問いについて,少し考えてみました.
18 |
19 | ### 2023-04-22
20 |
21 | Pyxelでゲーム🎮作れる人,尊敬します.
22 | いくらやっても,模擬器と謎のデモしかできないです.
23 | あの16色でドットが打てる人は,職人ですね.
24 |
25 | ### 2023-11-26
26 |
27 | 夏頃に花札を作ろうと思い,ドットを置きました.
28 | 完成が遠いので,とりあえず,48枚の花札を表示するデモを作ってみました.
29 | matt氏作の [Hanafuda Koi-Koi (Japanese card game)](https://www.lexaloffle.com/bbs/?tid=2421) を参考にしています.
30 |
31 | 
32 |
33 | 以上
34 |
--------------------------------------------------------------------------------
/haskell/asteroids/README.md:
--------------------------------------------------------------------------------
1 | # Asteroids in Haskell
2 |
3 | ## Introduction
4 |
5 | I came up with the mysterious question of whether a game can be made with mathematical formulas.
6 | In the past, I've researched the haskell implementation of an old game called Asteroids.
7 | The shape of the meteorite has been slightly improved and left as it is.
8 | Here, I think that this topic will be done privately.
9 | And if you get tired of it again, leave it alone.
10 |
11 |
12 |
13 | ## How to run
14 |
15 | > stack install gloss
16 | > stack ghc Asteroids.hs
17 | > ./Asteroids.exe
18 |
19 | ## How to Play
20 |
21 | Left-click to shoot a bullet and split the meteorite.
22 | Small meteorites are extinguished.
23 | If you hit a meteorite, the game is over.
24 | Right click to replay.
25 | If you split the meteorite, you will get 100 points,
26 | and if you eliminate it, you will get 500 points.
27 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part8/entity_factories.py:
--------------------------------------------------------------------------------
1 | from components.ai import HostileEnemy
2 | from components.consumable import HealingConsumable
3 | from components.fighter import Fighter
4 | from components.inventory import Inventory
5 | from entity import Actor, Item
6 |
7 | player = Actor(
8 | char="@",
9 | color=7,
10 | name="Player",
11 | ai_cls=HostileEnemy,
12 | fighter=Fighter(hp=30, defense=2, power=5),
13 | inventory=Inventory(capacity=26),
14 | )
15 |
16 | orc = Actor(
17 | char="o",
18 | color=8,
19 | name="Orc",
20 | ai_cls=HostileEnemy,
21 | fighter=Fighter(hp=10, defense=0, power=3),
22 | inventory=Inventory(capacity=0),
23 | )
24 | troll = Actor(
25 | char="T",
26 | color=9,
27 | name="Troll",
28 | ai_cls=HostileEnemy,
29 | fighter=Fighter(hp=16, defense=1, power=4),
30 | inventory=Inventory(capacity=0),
31 | )
32 |
33 | health_potion = Item(
34 | char="!",
35 | color=11,
36 | name="Health Potion",
37 | consumable=HealingConsumable(amount=4),
38 | )
39 |
40 | # end of entity_factories.py
41 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part5/input_handlers.py:
--------------------------------------------------------------------------------
1 | from typing import Optional
2 |
3 | import tcod.event
4 | import pyxel
5 |
6 | from actions import Action, BumpAction, EscapeAction
7 |
8 | class EventHandler:
9 | def dispatch(self) -> Optional[Action]:
10 | # メモ: 何も押されていない場合はNoneを返却
11 | action = None
12 |
13 | if pyxel.btnp(pyxel.KEY_UP):
14 | #action = MovementAction(dx=0, dy=-1)
15 | action = BumpAction(dx=0, dy=-1)
16 | elif pyxel.btnp(pyxel.KEY_DOWN):
17 | #action = MovementAction(dx=0, dy=1)
18 | action = BumpAction(dx=0, dy=1)
19 | elif pyxel.btnp(pyxel.KEY_LEFT):
20 | #action = MovementAction(dx=-1, dy=0)
21 | action = BumpAction(dx=-1, dy=0)
22 | elif pyxel.btnp(pyxel.KEY_RIGHT):
23 | #action = MovementAction(dx=1, dy=0)
24 | action = BumpAction(dx=1, dy=0)
25 |
26 | elif pyxel.btnp(pyxel.KEY_ESCAPE):
27 | action = EscapeAction()
28 |
29 | # No valid key was pressed
30 | return action
31 |
32 | # end of input_handlers.py
33 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part1/main.py:
--------------------------------------------------------------------------------
1 | import pyxel
2 |
3 | from actions import EscapeAction, MovementAction
4 | from input_handlers import EventHandler
5 |
6 | def main() -> None:
7 | global player_x, player_y, event_handler
8 |
9 | screen_width = 80
10 | screen_height = 50
11 |
12 | player_x = int(screen_width / 2)
13 | player_y = int(screen_height / 2)
14 |
15 | event_handler = EventHandler()
16 |
17 | pyxel.init(
18 | screen_width,
19 | screen_height,
20 | title="Yet Another Roguelike Tutorial",
21 | fps=30
22 | )
23 | pyxel.run(update, draw)
24 |
25 | def update():
26 | global player_x, player_y, event_handler
27 |
28 | action = event_handler.dispatch()
29 |
30 | if action is None:
31 | return
32 |
33 | if isinstance(action, MovementAction):
34 | player_x += action.dx
35 | player_y += action.dy
36 |
37 | elif isinstance(action, MovementAction):
38 | raise SystemExit()
39 |
40 | def draw():
41 | pyxel.cls(1)
42 | pyxel.pset(player_x,player_y,7)
43 |
44 | if __name__ == "__main__":
45 | main()
46 |
--------------------------------------------------------------------------------
/haskell/asteroids/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Niko Heikkilä
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/pyxel/hanafuda/hanafuda.py:
--------------------------------------------------------------------------------
1 | #
2 | # 花札デモ
3 | # matt氏作の「Hanafuda Koi-Koi(Japanese card game)」を参考にしました.
4 | # https://www.lexaloffle.com/bbs/?tid=2421
5 | #
6 | # Nov 26, 2023 ver.1 (first release)
7 | #
8 | # -*- coding: utf-8 -*-
9 | import pyxel
10 |
11 | class Hanafuda:
12 | def __init__( self ):
13 | # Pyxel初期化
14 | pyxel.init( 128, 128, title="Hanafuda", fps=20)
15 | pyxel.load("hanafuda.pyxres")
16 | pyxel.run(self.update,self.draw)
17 |
18 | def update( self ):
19 | """NONE"""
20 |
21 | def draw( self ):
22 | pyxel.cls(1)
23 |
24 | # 全ての花札を表示(デモ)
25 | for i in range(48):
26 | m = int( i / 4 )
27 | n = int( i % 4 )
28 | x = int( i % 8 )*15
29 | y = int( i / 8 )*19
30 | self.draw_hanafuda( m, n, x+4, y+8)
31 |
32 | # 花札表示
33 | # m: 花(0..11), n: 札(0..3)
34 | # x: x座標(0..113), y座標(0..109)
35 | def draw_hanafuda( self, m, n, x, y ):
36 | pyxel.rectb( x, y, 14, 18, 4 )
37 | pyxel.blt( x+1, y+1, 0, n*16, m*16, 12, 16 )
38 |
39 | # Main
40 | Hanafuda()
41 |
42 | # End of Hanafuda.py
43 |
--------------------------------------------------------------------------------
/pyxel/doc/220217_PyxelNote.md:
--------------------------------------------------------------------------------
1 | ## Pyxelによるゲーム開発記
2 |
3 | ### はじめに
4 |
5 | レトロゲームエンジン[Pyxel](https://github.com/kitao/pyxel)によるゲーム開発の記録です.
6 |
7 | ### 2022-02-17
8 |
9 | お夜寝から目が覚めたので,pyxel環境を整えました.
10 |
11 | - python: 3.8.9
12 | - pip: 22.0.3
13 | - pyxel: 1.6.9
14 |
15 | pyLodeRunnerを動かそうとしたら,すでに消えていました.
16 | 権利的にNGだったのかもしれません.
17 | シューティングゲームのサンプルは無事に動きました.
18 |
19 | ### 2022-02-19
20 |
21 | ブックオフから帰宅して,もろもろ掃除とかして,この前に動かしたシューティングのサンプルソースコードを読みました.
22 | pythonと2Dゲームの知識があれば,比較的すらすらと読めるかもしれません.
23 | 350行位だったので,そんなに苦労せずに理解できました.
24 | ただ普通に何か作ってもつまらないので,少し考えます.
25 |
26 | ### 2022-02-20
27 |
28 | pyxel 1.6.9だと若干構文が変わっています.
29 |
30 | % pyxel edit *.pyxres
31 | % pyxel copy_examples
32 |
33 | [Asteroids](https://github.com/timbledum/asteroids)の実装がGitにあったので,動かしてみました.
34 | ロジックをpythonで書く必要があるので,Pyxelでの開発はあまり気分が盛り上がらないです.
35 |
36 | ### 2022-04-03
37 |
38 | Pyxelを少し練習しました.pngファイルが読み込めるみたいです.なにか作ってみようかなと考えています.
39 |
40 | ### 2022-07-20
41 |
42 | Pyxelで,ニキシー管時計を作りはじめました.
43 | まず,ニキシー管のドット絵を描いてみましたが,少しおもちゃっぽい感じの仕上がりです.
44 | 電源をOFF/ONすると,LEDチェック(カウントアップ)が走るLED電卓を持っていたのですが,そのことを思い出しました.
45 | この続きを作るかは微妙です.
46 |
47 | 
48 |
49 | 以上
50 |
--------------------------------------------------------------------------------
/pyxel/aclm/README.md:
--------------------------------------------------------------------------------
1 | # ACLM
2 |
3 | ## Introduction
4 |
5 | I ported Mr. Wingman's [ACLM](https://archive.org/details/micom-basic-magazine-issue-16-october-1983/page/n92/mode/1up) to Pyxel/Python.
6 | The original was published in [Mycom Basic Magazine (October 1983 issue)](https://archive.org/details/micom-basic-magazine-issue-16-october-1983/).
7 | This is a game where you operate my aircraft (red) and defeat enemy aircraft (blue) by hitting them vertically and horizontally.
8 | Since it is extremely difficult, I have changed the rules to say that if my aircraft collides with the enemy aircraft, it will be 'a tie' instead of 'a loss.'
9 | Also, the original version seems to have a scene 2 in which they attack a city.
10 |
11 |
12 |
13 | ## How to Run
14 |
15 | Please execute the following from the Pyxel (version 1.7.0) environment.
16 | Or you can play [here](https://kitao.github.io/pyxel/wasm/launcher/?run=jay-kumogata.RetroGames.pyxel.aclm.aclm).
17 |
18 | > python aclm.py
19 |
20 | ## How to Control
21 |
22 | - [right-arrow]: Rotate my aircraft to the right
23 | - [left-arrow]: Rotate my aircraft to the left
24 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part2/main.py:
--------------------------------------------------------------------------------
1 | import pyxel
2 |
3 | from engine import Engine
4 | from entity import Entity
5 | from game_map import GameMap
6 | from input_handlers import EventHandler
7 |
8 | def main() -> None:
9 | global engine
10 |
11 | screen_width = 80
12 | screen_height = 50
13 |
14 | map_width = 80
15 | map_height = 50
16 |
17 | event_handler = EventHandler()
18 |
19 | player = Entity(int(screen_width / 2), int(screen_height / 2), "@", 7)
20 | npc = Entity(int(screen_width / 2 - 5), int(screen_height / 2), "@", 10)
21 | entities = {npc, player}
22 |
23 | game_map = GameMap(map_width, map_height)
24 |
25 | engine = Engine(entities=entities, event_handler=event_handler, game_map=game_map, player=player)
26 |
27 | pyxel.init(
28 | screen_width,
29 | screen_height,
30 | title="Yet Another Roguelike Tutorial",
31 | fps=30
32 | )
33 | pyxel.run(update, draw)
34 |
35 | def update():
36 | global engine
37 | engine.handle_events()
38 |
39 | def draw():
40 | global engine
41 | engine.render()
42 |
43 | if __name__ == "__main__":
44 | main()
45 |
46 | # end of main.py
47 |
--------------------------------------------------------------------------------
/research/99_01_NoteOnGames2017.md:
--------------------------------------------------------------------------------
1 | # 99_ゲーム雑記: 01_ゲーム雑記2017
2 |
3 | ## twitterより
4 |
5 | ### 2017-01-22
6 |
7 | あそぶ!ゲーム展にて,[「ゼビウス」製作チームメンバの対談](http://channel2.skipcity.jp/popup/?md=mus_asbgmtn2xvszdnk_960x540&mw=560&mh=315)が配信中です.「スクロールするゲームで,(コナミのスクランブルのように)上下を撃ち分けるゲームが流行る」というマーケティングの情報で開発したという逸話が面白いです.必見です.
8 |
9 | ### 2017-02-05
10 |
11 | [MAMEプロジェクト](https://www.mamedev.org/)も,20年ですか.消え行くものをエミュレーションという技術で必死に保存しようとする英雄的な活動は,後世にまで語り継がれるでしょう.そして,本当に多くの貢献者により,この活動が支えられているのだと知り,頭が上がりません.
12 |
13 |
14 |
15 | ### 2017-04-19
16 |
17 | [Lode Runner](https://tozaigames.co.jp/products/loderunner_history/),懐かしいです.
18 |
19 | 
20 |
21 | ### 2017-04-28
22 |
23 | 昔のゲーム機の復刻ブームですが,次はスーファミという噂があるみたいです.
24 | 米国では,今年発売のようです.
25 |
26 | ### 2017-04-29
27 |
28 | 古い機械についてつぶやきます.エレクトロニクス企業の繁栄と衰退に興味があります.
29 | I'll tweet about old machines. And I'm interested in prosperity and decline of electronics companies.
30 |
31 | ### 2017-12-18
32 |
33 | [ファイナルファンタジー30周年](http://www.finalfantasy.jp/30th/)です.
34 | 結局,ファミコンで,FinalFantasy1/2/3,ワンダースワンで,FinalFantasy1/2/4,プレステで,FinalFantasy7,しかやっていません.
35 |
36 | 
37 |
38 | 以上
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part2/engine.py:
--------------------------------------------------------------------------------
1 | from typing import Set, Iterable, Any
2 |
3 | import pyxel
4 |
5 | from actions import EscapeAction, MovementAction
6 | from entity import Entity
7 | from game_map import GameMap
8 | from input_handlers import EventHandler
9 |
10 | class Engine:
11 | def __init__(self, entities: Set[Entity], event_handler: EventHandler, game_map: GameMap, player: Entity):
12 | self.entities = entities
13 | self.event_handler = event_handler
14 | self.game_map = game_map
15 | self.player = player
16 |
17 | def handle_events(self) -> None:
18 | action = self.event_handler.dispatch()
19 |
20 | if action is None:
21 | return
22 |
23 | if isinstance(action, MovementAction):
24 | if self.game_map.tiles["walkable"][self.player.x + action.dx, self.player.y + action.dy]:
25 | self.player.move(dx=action.dx, dy=action.dy)
26 |
27 | elif isinstance(action, EscapeAction):
28 | raise SystemExit()
29 |
30 | def render(self) -> None:
31 | pyxel.cls(1)
32 | self.game_map.render()
33 | for entity in self.entities:
34 | pyxel.pset(entity.x, entity.y, entity.color)
35 |
36 | # end of engine.py
37 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part3/engine.py:
--------------------------------------------------------------------------------
1 | from typing import Set, Iterable, Any
2 |
3 | import pyxel
4 |
5 | from actions import EscapeAction, MovementAction
6 | from entity import Entity
7 | from game_map import GameMap
8 | from input_handlers import EventHandler
9 |
10 | class Engine:
11 | def __init__(self, entities: Set[Entity], event_handler: EventHandler, game_map: GameMap, player: Entity):
12 | self.entities = entities
13 | self.event_handler = event_handler
14 | self.game_map = game_map
15 | self.player = player
16 |
17 | def handle_events(self) -> None:
18 | action = self.event_handler.dispatch()
19 |
20 | if action is None:
21 | return
22 |
23 | if isinstance(action, MovementAction):
24 | if self.game_map.tiles["walkable"][self.player.x + action.dx, self.player.y + action.dy]:
25 | self.player.move(dx=action.dx, dy=action.dy)
26 |
27 | elif isinstance(action, EscapeAction):
28 | raise SystemExit()
29 |
30 | def render(self) -> None:
31 | pyxel.cls(1)
32 | self.game_map.render()
33 | for entity in self.entities:
34 | pyxel.pset(entity.x, entity.y, entity.color)
35 |
36 | # end of engine.py
37 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part5/entity.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import copy
4 | from typing import Tuple, TypeVar, TYPE_CHECKING
5 |
6 | if TYPE_CHECKING:
7 | from game_map import GameMap
8 |
9 | T = TypeVar("T", bound="Entity")
10 |
11 | class Entity:
12 | """
13 | A generic object to represent players, enemies, items, etc.
14 | """
15 | def __init__(
16 | self,
17 | x: int = 0,
18 | y: int = 0,
19 | char: str = "?",
20 | color: int = 7, # 白
21 | name: str = "",
22 | blocks_movement: bool = False,
23 | ):
24 | self.x = x
25 | self.y = y
26 | self.char = char
27 | self.color = color
28 | self.name = name
29 | self.blocks_movement = blocks_movement
30 |
31 | def spawn(self: T, gamemap: GameMap, x: int, y: int) -> T:
32 | """Spawn a copy of this instance at the given location."""
33 | clone = copy.deepcopy(self)
34 | clone.x = x
35 | clone.y = y
36 | gamemap.entities.add(clone)
37 | return clone
38 |
39 | def move(self, dx: int, dy: int) -> None:
40 | # Move the entity by a given amount
41 | self.x += dx
42 | self.y += dy
43 |
44 | # end of entity.py
45 |
--------------------------------------------------------------------------------
/pyxel/asteroids/Ship.py:
--------------------------------------------------------------------------------
1 | import pyxel
2 | from Vec import *
3 |
4 | class Ship():
5 | # 船情報Shipは,座標Vec,速度Velocityから構成.
6 | def __init__(self, p : Vec, v : Vec):
7 | self.p = p
8 | self.v = v
9 | self.s = [[0, -4], [-2, 4], [2, 4], [0, -4]]
10 | self.r = math.pi / 2
11 |
12 | def update(self, timeStep : float):
13 | # 弾を発射したら反動で動く
14 | self.p = self.p.add(self.v.mul(timeStep))
15 | self.p = self.p.restoreToScreen()
16 |
17 | # 回転
18 | if pyxel.btn(pyxel.KEY_LEFT):
19 | self.r -= math.pi / 8
20 | elif pyxel.btn(pyxel.KEY_RIGHT):
21 | self.r += math.pi / 8
22 |
23 | if self.r < 0:
24 | self.r += 2 * math.pi
25 | elif self.r > 2 * math.pi:
26 | self.r -= 2 * math.pi
27 |
28 | def draw(self):
29 | a = []
30 | for b in self.s:
31 | a.append(Vec(b[0],b[1]).rotateV(self.r))
32 |
33 | for n in range(len(self.s)-1):
34 | pyxel.line( self.p.x+a[n].x+160,
35 | self.p.y+a[n].y+160,
36 | self.p.x+a[n+1].x+160,
37 | self.p.y+a[n+1].y+160,
38 | 7 )
39 |
40 | # End of Ship.py
41 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part3/tile_types.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import numpy as np # type: ignore
4 |
5 | # Tile graphics structured type
6 | graphic_dt = np.dtype(
7 | [
8 | ("ch", np.int32), # Unicode codepoint.(未使用: キャラクタコード)
9 | ("fg", np.int32), # 文字色(Pyxelでの色情報)
10 | ("bg", np.int32), # 背景色(Pyxelでの色情報)
11 | ]
12 | )
13 |
14 | # Tile struct used for statically defined tile data.
15 | tile_dt = np.dtype(
16 | [
17 | ("walkable", np.bool_), # True if this tile can be walked over.
18 | ("transparent", np.bool_), # True if this tile doesn't block FOV.
19 | ("dark", graphic_dt), # Graphics for when this tile is not in FOV.
20 | ]
21 | )
22 |
23 |
24 | def new_tile(
25 | *, # Enforce the use of keywords, so that parameter order doesn't matter.
26 | walkable: int,
27 | transparent: int,
28 | dark: Tuple[int, int, int]
29 | ) -> np.ndarray:
30 | """Helper function for defining individual tile types """
31 | return np.array((walkable, transparent, dark), dtype=tile_dt)
32 |
33 | floor = new_tile(
34 | walkable=True, transparent=True, dark=(ord(" "), 5, 1),
35 | )
36 | wall = new_tile(
37 | walkable=False, transparent=False, dark=(ord(" "), 1, 2),
38 | )
39 |
40 | # end of tile_types.py
41 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part2/tile_types.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import numpy as np # type: ignore
4 |
5 | # Tile graphics structured type compatible with Console.tiles_rgb.
6 | graphic_dt = np.dtype(
7 | [
8 | ("ch", np.int32), # Unicode codepoint.
9 | ("fg", np.int32), # 3 unsigned bytes, for RGB colors.
10 | ("bg", np.int32),
11 | ]
12 | )
13 |
14 | # Tile struct used for statically defined tile data.
15 | tile_dt = np.dtype(
16 | [
17 | ("walkable", np.bool_), # True if this tile can be walked over.
18 | ("transparent", np.bool_), # True if this tile doesn't block FOV.
19 | ("dark", graphic_dt), # Graphics for when this tile is not in FOV.
20 | ]
21 | )
22 |
23 |
24 | def new_tile(
25 | *, # Enforce the use of keywords, so that parameter order doesn't matter.
26 | walkable: int,
27 | transparent: int,
28 | dark: Tuple[int, int, int]
29 | ) -> np.ndarray:
30 | """Helper function for defining individual tile types """
31 | return np.array((walkable, transparent, dark), dtype=tile_dt)
32 |
33 | floor = new_tile(
34 | walkable=True, transparent=True, dark=(ord(" "), 5, 1),
35 | )
36 | wall = new_tile(
37 | walkable=False, transparent=False, dark=(ord(" "), 1, 2),
38 | )
39 |
40 | # end of tile_types.py
41 |
--------------------------------------------------------------------------------
/pyxel/tennis/Ball.py:
--------------------------------------------------------------------------------
1 | # generated by Grok3
2 |
3 | import pyxel
4 |
5 | class Ball:
6 | def __init__(self, p_pos_x, p_pos_y):
7 | self.pos_x = self.prev_pos_x = p_pos_x
8 | self.pos_y = self.prev_pos_y = p_pos_y
9 | self.vel_x = 0
10 | self.vel_y = 0
11 |
12 | def update(self, p_gravity):
13 | self.prev_pos_x = self.pos_x
14 | self.prev_pos_y = self.pos_y
15 | self.vel_y += p_gravity
16 | self.pos_x += self.vel_x
17 | self.pos_y += self.vel_y
18 |
19 | def draw(self):
20 | # 線を描画
21 | pyxel.line(self.prev_pos_x, self.prev_pos_y, self.pos_x, self.pos_y, 14)
22 | # 点を描画
23 | pyxel.pset(self.pos_x, self.pos_y, 14)
24 |
25 | def bounce_floor(self, p_bounce):
26 | self.vel_y = -self.vel_y * p_bounce
27 |
28 | def bounce_fence(self, p_bounce):
29 | self.vel_x = -self.vel_x * p_bounce
30 |
31 | def set_speed(self, p_vel_x, p_vel_y):
32 | self.vel_x = p_vel_x
33 | self.vel_y = p_vel_y
34 |
35 | def set_position(self, p_pos_x, p_pos_y):
36 | self.pos_x = p_pos_x
37 | self.pos_y = p_pos_y
38 |
39 | def set_prev_position(self, p_pos_x, p_pos_y):
40 | self.prev_pos_x = p_pos_x
41 | self.prev_pos_y = p_pos_y
42 |
43 | # End of Ball.py
44 |
--------------------------------------------------------------------------------
/pyxel/autorace/basic.py:
--------------------------------------------------------------------------------
1 | #
2 | # 「昔のBASICゲームをPythonに移植するためのライブラリ」
3 | #
4 | # Jun 14, 2024 ver.1 (autorace.py対応)
5 | #
6 | # -*- coding: utf-8 -*-
7 | import numpy as np
8 |
9 | # 仮想画面
10 | class screen:
11 | def __init__(
12 | self, width: int, height: int
13 | ):
14 | # 初期化(仮想画面)
15 | self.width, self.height = width, height
16 | self.ch = np.full((width, height), ord(' '))
17 | self.fg = np.full((width, height), 7)
18 |
19 | # 画面表示(X座標,Y座標,キャラクタ,色属性)
20 | def poke(self, x: int, y: int, c: int, a: int):
21 | self.ch[x,y] = c
22 | self.fg[x,y] = a
23 |
24 | # 画面情報(X座標,Y座標,キャラクタ/色属性)
25 | def peek(self, x: int, y: int, f: bool):
26 | if f:
27 | return self.ch[x,y]
28 | else:
29 | return self.fg[x,y]
30 |
31 | # 画面スクロール
32 | def scroll(self):
33 | for w in range(self.width):
34 | for h in range(self.height-1):
35 | self.ch[w,h] = self.ch[w,h+1]
36 | self.fg[w,h] = self.fg[w,h+1]
37 |
38 | # 文字列を画面に表示(X座標,Y座標,文字列,色属性)
39 | def print(self, x:int, y:int, s: str, a:int):
40 | l = list(s)
41 | for n in range(len(l)):
42 | self.poke(x,y,ord(l[n]),a)
43 | x+=1
44 |
45 | # end of basic.py
46 |
--------------------------------------------------------------------------------
/research/02_07_HistoryOfAthena.md:
--------------------------------------------------------------------------------
1 | # 02_ゲーム史研究: 07_社史編纂: アテナ(Athena)
2 |
3 | |属性|属性値|
4 | |---|--|
5 | |社名|株式会社アテナ|
6 | |本社所在地|〒162-0067 東京都新宿区富久町8-26(2013年12月11日時点)|
7 | |設立|1987年7月|
8 | |代表者|中村栄氏(2013年12月11日時点)|
9 | |売上高|2億82百万円(2005年3月期)|
10 |
11 | ## 沿革
12 |
13 | |日付|出来事|
14 | |---|------|
15 | |1987年7月|会社設立(代表:中村栄氏)|
16 | |2013年12月11日|東京地方裁判所にて,破産手続きの開始決定(破産管財人:古田茂弁護士)|
17 |
18 | ## タイトル一覧
19 |
20 | ### 極シリーズ
21 |
22 | |発売日|ハード|ジャンル|タイトル名|
23 | |-----|-----|-------|---------|
24 | |1993年6月11日|SFC|テーブル|プロ麻雀 極|
25 | |1994年7月20日|SFC|テーブル|プロ麻雀 極II|
26 | |1994年12月22日|GB|テーブル|プロ麻雀 極GB|
27 | |1995年6月30日|SFC|テーブル|プロ麻雀 極III|
28 | |1996年1月12日|SS|テーブル|プロ麻雀 極S|
29 | |1996年8月30日|PS1|テーブル|プロ麻雀 極PLUS|
30 | |1997年11月10日|Win|テーブル|プロ麻雀 極 for Windows|
31 | |1997年11月21日|N64|テーブル|プロ麻雀 極64|
32 | |1998年12月10日|PS|テーブル|プロ麻雀 極PLUSII|
33 | |1999年3月19日|GBC|テーブル|プロ麻雀 極GBII|
34 | |1999年10月7日|WS|テーブル|プロ麻雀 極 for WonderSwan|
35 | |1999年10月28日|PS|テーブル|プロ麻雀 極 天元戦編|
36 | |1999年12月2日|PS|テーブル|井出洋介の麻雀教室 〜プロ麻雀 極シリーズ 初級編〜|
37 | |2000年3月30日|DC|テーブル|プロ麻雀 極D|
38 | |2000年8月31日|PS2|テーブル|プロ麻雀 極NEXT|
39 | |2001年8月10日|GBA|テーブル|極 麻雀デラックス 未来戦士21|
40 | |2001年10月26日|Win|テーブル|プロ麻雀 極 天元戦編 for Windows|
41 | |2002年8月9日|GC|テーブル|極 麻雀DXII -The 4th MONDO21Cup Competition-|
42 | |2003年12月18日|PS2|テーブル|極 麻雀DX2 -The 4th MONDO21Cup Competition-|
43 | |2007年8月3日|Win|テーブル|プロ麻雀 極 NEXT for Windows Vista対応|
44 |
45 | 以上
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part13/components/equippable.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | from components.base_component import BaseComponent
6 | from equipment_types import EquipmentType
7 |
8 | if TYPE_CHECKING:
9 | from entity import Item
10 |
11 |
12 | class Equippable(BaseComponent):
13 | parent: Item
14 |
15 | def __init__(
16 | self,
17 | equipment_type: EquipmentType,
18 | power_bonus: int = 0,
19 | defense_bonus: int = 0,
20 | ):
21 | self.equipment_type = equipment_type
22 |
23 | self.power_bonus = power_bonus
24 | self.defense_bonus = defense_bonus
25 |
26 |
27 | class Dagger(Equippable):
28 | def __init__(self) -> None:
29 | super().__init__(equipment_type=EquipmentType.WEAPON, power_bonus=2)
30 |
31 |
32 | class Sword(Equippable):
33 | def __init__(self) -> None:
34 | super().__init__(equipment_type=EquipmentType.WEAPON, power_bonus=4)
35 |
36 |
37 | class LeatherArmor(Equippable):
38 | def __init__(self) -> None:
39 | super().__init__(equipment_type=EquipmentType.ARMOR, defense_bonus=1)
40 |
41 |
42 | class ChainMail(Equippable):
43 | def __init__(self) -> None:
44 | super().__init__(equipment_type=EquipmentType.ARMOR, defense_bonus=3)
45 |
46 | # end of equippable.py
47 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/src/components/equippable.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | from components.base_component import BaseComponent
6 | from equipment_types import EquipmentType
7 |
8 | if TYPE_CHECKING:
9 | from entity import Item
10 |
11 |
12 | class Equippable(BaseComponent):
13 | parent: Item
14 |
15 | def __init__(
16 | self,
17 | equipment_type: EquipmentType,
18 | power_bonus: int = 0,
19 | defense_bonus: int = 0,
20 | ):
21 | self.equipment_type = equipment_type
22 |
23 | self.power_bonus = power_bonus
24 | self.defense_bonus = defense_bonus
25 |
26 |
27 | class Dagger(Equippable):
28 | def __init__(self) -> None:
29 | super().__init__(equipment_type=EquipmentType.WEAPON, power_bonus=2)
30 |
31 |
32 | class Sword(Equippable):
33 | def __init__(self) -> None:
34 | super().__init__(equipment_type=EquipmentType.WEAPON, power_bonus=4)
35 |
36 |
37 | class LeatherArmor(Equippable):
38 | def __init__(self) -> None:
39 | super().__init__(equipment_type=EquipmentType.ARMOR, defense_bonus=1)
40 |
41 |
42 | class ChainMail(Equippable):
43 | def __init__(self) -> None:
44 | super().__init__(equipment_type=EquipmentType.ARMOR, defense_bonus=3)
45 |
46 | # end of equippable.py
47 |
--------------------------------------------------------------------------------
/pyxel/asteroids/Vec.py:
--------------------------------------------------------------------------------
1 | import math
2 |
3 | # 2D座標を扱う関数ライブラリ
4 | class Vec():
5 | def __init__(self, x : float, y: float):
6 | self.x = x
7 | self.y = y
8 |
9 | # ベクトル加減算
10 | def sub(self, p):
11 | return Vec(self.x - p.x, self.y - p.y)
12 | def add(self, p):
13 | return Vec(self.x + p.x, self.y + p.y)
14 |
15 | # ベクトル乗算
16 | def mul(self, s):
17 | return Vec(s * self.x, s * self.y)
18 |
19 | # ベクトル正規化
20 | def norm(self):
21 | m = self.magV()
22 | return Vec(self.x/m, self.y/m)
23 |
24 | # ベクトル長
25 | def magV(self):
26 | return math.sqrt(self.x ** 2 + self.y ** 2)
27 |
28 | # ベクトル長(制限あり)
29 | def limitMag(self, n):
30 | if self.magV() > n: return (self.norm()).mul(n)
31 | else: return self
32 |
33 | # ベクトル回転
34 | def rotateV(self, r):
35 | return Vec(
36 | self.x * math.cos(r) - self.y * math.sin(r),
37 | self.x * math.sin(r) + self.y * math.cos(r)
38 | )
39 |
40 | # 画面外に出たら反対から出現(トーラス化)
41 | def restoreToScreen(self):
42 | return Vec(
43 | self.cycleCoordinates(self.x),
44 | self.cycleCoordinates(self.y),
45 | )
46 |
47 | # 同上
48 | def cycleCoordinates(self, x):
49 | if x < -160: return 320+x
50 | elif x > 160: return x-320
51 | else: return x
52 |
53 | # End of Vec.py
54 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part4/actions.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | if TYPE_CHECKING:
6 | from engine import Engine
7 | from entity import Entity
8 |
9 |
10 | class Action:
11 | def perform(self, engine: Engine, entity: Entity) -> None:
12 | """Perform this action with the objects needed to determine its scope.
13 |
14 | `engine` is the scope this action is being performed in.
15 |
16 | `entity` is the object performing the action.
17 |
18 | This method must be overridden by Action subclasses.
19 | """
20 | raise NotImplementedError()
21 |
22 |
23 | class EscapeAction(Action):
24 | def perform(self, engine: Engine, entity: Entity) -> None:
25 | raise SystemExit()
26 |
27 |
28 | class MovementAction(Action):
29 | def __init__(self, dx: int, dy: int):
30 | super().__init__()
31 |
32 | self.dx = dx
33 | self.dy = dy
34 |
35 | def perform(self, engine: Engine, entity: Entity) -> None:
36 | dest_x = entity.x + self.dx
37 | dest_y = entity.y + self.dy
38 |
39 | if not engine.game_map.in_bounds(dest_x, dest_y):
40 | return # Destination is out of bounds.
41 | if not engine.game_map.tiles["walkable"][dest_x, dest_y]:
42 | return # Destination is blocked by a tile.
43 |
44 | entity.move(self.dx, self.dy)
45 |
46 | # end of actions.py
47 |
--------------------------------------------------------------------------------
/pyxel/nixie/Nixie.py:
--------------------------------------------------------------------------------
1 | # Nixie Tube Clock v0.1: Nixie Tube Clock in Pyxel/Python
2 | # Copyright (c) 2022 Kumogata Computing Laboratory.
3 | # All Rights Reserved.
4 |
5 | import pyxel
6 |
7 | class Nixie:
8 |
9 | # Variables
10 | f1 = 0
11 | f2 = 1
12 | f3 = 2
13 | f4 = 3
14 |
15 | # Constructor
16 | def __init__( self ):
17 | pyxel.init( 128, 64, title="Nixie Tube Clock v0.1", fps=20)
18 | pyxel.load("Nixie.pyxres")
19 | pyxel.run(self.update,self.draw)
20 |
21 | def update( self ):
22 | # do nothing
23 | """NONE"""
24 | self.f1 = pyxel.frame_count % 10000 // 1000
25 | self.f2 = pyxel.frame_count % 1000 // 100
26 | self.f3 = pyxel.frame_count % 100 // 10
27 | self.f4 = pyxel.frame_count % 10
28 |
29 | def draw( self ):
30 | pyxel.cls(0)
31 | pyxel.blt(32, 16, 0, 0, 0, 16, 32) # tube #1
32 | pyxel.blt(48, 16, 0, 0, 0, 16, 32) # tube #2
33 | pyxel.blt(64, 16, 0, 0, 0, 16, 32) # tube #3
34 | pyxel.blt(80, 16, 0, 0, 0, 16, 32) # tube #4
35 |
36 | pyxel.blt(32, 24, 0, self.f1*16, 48, 16, 16) # figure #1
37 | pyxel.blt(48, 24, 0, self.f2*16, 48, 16, 16) # figure #2
38 | pyxel.blt(64, 24, 0, self.f3*16, 48, 16, 16) # figure #3
39 | pyxel.blt(80, 24, 0, self.f4*16, 48, 16, 16) # figure #4
40 |
41 | # Main
42 | Nixie()
43 |
44 | # End of Nixie.py
45 |
46 |
47 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part10/render_functions.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | import color
6 | import pyxel
7 |
8 | if TYPE_CHECKING:
9 | from tcod import Console
10 | from engine import Engine
11 | from game_map import GameMap
12 |
13 |
14 | def get_names_at_location(x: int, y: int, game_map: GameMap) -> str:
15 | if not game_map.in_bounds(x, y) or not game_map.visible[x, y]:
16 | return ""
17 |
18 | names = ", ".join(
19 | entity.name for entity in game_map.entities if entity.x == x and entity.y == y
20 | )
21 |
22 | return names.capitalize()
23 |
24 | def render_bar(
25 | current_value: int, maximum_value: int, total_width: int
26 | ) -> None:
27 | bar_width = int(float(current_value) / maximum_value * total_width)
28 |
29 | color.rect(0, 45, total_width, 1, color.bar_empty)
30 |
31 | if bar_width > 0:
32 | color.rect( 0, 45, bar_width, 1, color.bar_filled)
33 |
34 | color.text(1, 45, f"HP: {current_value}/{maximum_value}", color.bar_text)
35 |
36 | def render_names_at_mouse_location(
37 | x: int, y: int, engine: Engine
38 | ) -> None:
39 | mouse_x, mouse_y = engine.mouse_location
40 |
41 | names_at_mouse_location = get_names_at_location(
42 | x=mouse_x, y=mouse_y, game_map=engine.game_map
43 | )
44 |
45 | color.text(x, y, names_at_mouse_location, 7)
46 |
47 | # end of render_functions.py
48 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part8/render_functions.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | import color
6 | import pyxel
7 |
8 | if TYPE_CHECKING:
9 | from tcod import Console
10 | from engine import Engine
11 | from game_map import GameMap
12 |
13 |
14 | def get_names_at_location(x: int, y: int, game_map: GameMap) -> str:
15 | if not game_map.in_bounds(x, y) or not game_map.visible[x, y]:
16 | return ""
17 |
18 | names = ", ".join(
19 | entity.name for entity in game_map.entities if entity.x == x and entity.y == y
20 | )
21 |
22 | return names.capitalize()
23 |
24 | def render_bar(
25 | current_value: int, maximum_value: int, total_width: int
26 | ) -> None:
27 | bar_width = int(float(current_value) / maximum_value * total_width)
28 |
29 | color.rect(0, 45, total_width, 1, color.bar_empty)
30 |
31 | if bar_width > 0:
32 | color.rect( 0, 45, bar_width, 1, color.bar_filled)
33 |
34 | color.text(1, 45, f"HP: {current_value}/{maximum_value}", color.bar_text)
35 |
36 | def render_names_at_mouse_location(
37 | x: int, y: int, engine: Engine
38 | ) -> None:
39 | mouse_x, mouse_y = engine.mouse_location
40 |
41 | names_at_mouse_location = get_names_at_location(
42 | x=mouse_x, y=mouse_y, game_map=engine.game_map
43 | )
44 |
45 | color.text(x, y, names_at_mouse_location, 7)
46 |
47 | # end of render_functions.py
48 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part9/render_functions.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | import color
6 | import pyxel
7 |
8 | if TYPE_CHECKING:
9 | from tcod import Console
10 | from engine import Engine
11 | from game_map import GameMap
12 |
13 |
14 | def get_names_at_location(x: int, y: int, game_map: GameMap) -> str:
15 | if not game_map.in_bounds(x, y) or not game_map.visible[x, y]:
16 | return ""
17 |
18 | names = ", ".join(
19 | entity.name for entity in game_map.entities if entity.x == x and entity.y == y
20 | )
21 |
22 | return names.capitalize()
23 |
24 | def render_bar(
25 | current_value: int, maximum_value: int, total_width: int
26 | ) -> None:
27 | bar_width = int(float(current_value) / maximum_value * total_width)
28 |
29 | color.rect(0, 45, total_width, 1, color.bar_empty)
30 |
31 | if bar_width > 0:
32 | color.rect( 0, 45, bar_width, 1, color.bar_filled)
33 |
34 | color.text(1, 45, f"HP: {current_value}/{maximum_value}", color.bar_text)
35 |
36 | def render_names_at_mouse_location(
37 | x: int, y: int, engine: Engine
38 | ) -> None:
39 | mouse_x, mouse_y = engine.mouse_location
40 |
41 | names_at_mouse_location = get_names_at_location(
42 | x=mouse_x, y=mouse_y, game_map=engine.game_map
43 | )
44 |
45 | color.text(x, y, names_at_mouse_location, 7)
46 |
47 | # end of render_functions.py
48 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part6/main.py:
--------------------------------------------------------------------------------
1 | import copy
2 |
3 | import pyxel
4 |
5 | from engine import Engine
6 | import entity_factories
7 | from procgen import generate_dungeon
8 |
9 | def main() -> None:
10 | global engine
11 |
12 | screen_width = 80
13 | screen_height = 50
14 |
15 | map_width = 80
16 | map_height = 45
17 |
18 | room_max_size = 10
19 | room_min_size = 6
20 | max_rooms = 30
21 | max_monsters_per_room = 2
22 |
23 | player = copy.deepcopy(entity_factories.player)
24 | engine = Engine(player=player)
25 |
26 | engine.game_map = generate_dungeon(
27 | max_rooms=max_rooms,
28 | room_min_size=room_min_size,
29 | room_max_size=room_max_size,
30 | map_width=map_width,
31 | map_height=map_height,
32 | max_monsters_per_room=max_monsters_per_room,
33 | engine=engine,
34 | )
35 | engine.update_fov()
36 |
37 |
38 | # Pyxel初期化
39 | pyxel.init(
40 | screen_width,
41 | screen_height,
42 | title="Yet Another Roguelike Tutorial",
43 | fps=30
44 | )
45 | pyxel.run(update, draw)
46 |
47 | def update():
48 | # メモ: イベントハンドラを呼ぶ
49 | global engine
50 | engine.event_handler.handle_events()
51 |
52 | def draw():
53 | # メモ: 画面描画ルーチンを呼ぶ
54 | global engine
55 | engine.render()
56 |
57 | if __name__ == "__main__":
58 | main()
59 |
60 | # end of main.py
61 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part10/color.py:
--------------------------------------------------------------------------------
1 | import pyxel
2 |
3 | # メモ: パレット(pyxel既定)
4 |
5 | black = 0
6 | dark_blue = 1
7 | purple = 2
8 | green = 3
9 | brown = 4
10 | blue = 5
11 | light_purple = 6
12 | white = 7
13 | red = 8
14 | amber = 9
15 | yellow = 10
16 | light_green = 11
17 | light_blue = 12
18 | gray = 13
19 | pink = 14
20 | beige = 15
21 |
22 | player_atk = light_blue
23 | enemy_atk = gray
24 |
25 | player_die = pink
26 | enemy_die = beige
27 | needs_target = blue
28 | status_effect_applied = light_purple
29 |
30 | invalid = amber
31 | impossible = yellow
32 | error = purple
33 |
34 | welcome_text = light_purple
35 | health_recovered = green
36 |
37 | bar_text = white
38 | bar_filled = light_green
39 | bar_empty = red
40 |
41 | menu_title = yellow
42 | menu_text = white
43 |
44 | # メモ: 以下、色(color)とは直接関係ないコード(Pyxel関連)
45 |
46 | # メモ: コンソールサイズ(80x50)
47 | width = 80
48 | height = 50
49 |
50 | # メモ: 組込フォントのドット数(4x5)
51 | chr_x = 4
52 | chr_y = 5
53 |
54 | # メモ: ヘルパー関数
55 | def rect(x: int, y: int, w: int, h: int, col: int):
56 | pyxel.rect(x*chr_x, y*chr_y, w*chr_x, h*chr_y, col)
57 |
58 | def rectb(x: int, y: int, w: int, h: int, col: int):
59 | pyxel.rectb(x*chr_x, y*chr_y, w*chr_x, h*chr_y, col)
60 |
61 | def text(x: int, y: int, s: str, col: int):
62 | pyxel.text(x*chr_x, y*chr_y, s, col)
63 |
64 | # テキストを中央に表示
65 | def textc(x: int, y: int, s: str, col: int):
66 | pyxel.text((x - len(s) // 2)*chr_x, y*chr_y, s, col)
67 |
68 | # end of color.py
69 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part3/main.py:
--------------------------------------------------------------------------------
1 | import pyxel
2 |
3 | from engine import Engine
4 | from entity import Entity
5 | from input_handlers import EventHandler
6 | from procgen import generate_dungeon
7 |
8 | def main() -> None:
9 | global engine
10 |
11 | screen_width = 80
12 | screen_height = 50
13 |
14 | map_width = 80
15 | map_height = 45
16 |
17 | room_max_size = 10
18 | room_min_size = 6
19 | max_rooms = 30
20 |
21 | event_handler = EventHandler()
22 |
23 | player = Entity(int(screen_width / 2), int(screen_height / 2), "@", 7)
24 | npc = Entity(int(screen_width / 2 - 5), int(screen_height / 2), "@", 10)
25 | entities = {npc, player}
26 |
27 | game_map = generate_dungeon(
28 | max_rooms=max_rooms,
29 | room_min_size=room_min_size,
30 | room_max_size=room_max_size,
31 | map_width=map_width,
32 | map_height=map_height,
33 | player=player
34 | )
35 |
36 | engine = Engine(entities=entities, event_handler=event_handler, game_map=game_map, player=player)
37 |
38 | pyxel.init(
39 | screen_width,
40 | screen_height,
41 | title="Yet Another Roguelike Tutorial",
42 | fps=30
43 | )
44 | pyxel.run(update, draw)
45 |
46 | def update():
47 | global engine
48 | engine.handle_events()
49 |
50 | def draw():
51 | global engine
52 | engine.render()
53 |
54 | if __name__ == "__main__":
55 | main()
56 |
57 | # end of main.py
58 |
--------------------------------------------------------------------------------
/pyxel/sheep/Sheep.py:
--------------------------------------------------------------------------------
1 | import random
2 | import pyxel
3 |
4 | class Sheep:
5 | def __init__(self, x, y):
6 | self.p = None # 参照元
7 | self.x = x # x座標
8 | self.y = y # y座標
9 | self.sz = 2 # 大きさ
10 | self.energy = 20 # 体力
11 | self.col = random.randint( 6, 15 ) # 色
12 |
13 | def update(self):
14 | # 羊がランダムに動き回るようにする
15 | move = 1 # 任意の方向に移動するときの最大距離
16 | self.energy -= 1
17 | if self.energy <= 0:
18 | self.p.sheepList.remove(self)
19 | self.x += random.randint( -move, move )
20 | self.y += random.randint( -move, move )
21 |
22 | # Asteroids式の「丸め」
23 | if self.x >= self.p.width:
24 | self.x %= self.p.width
25 | if self.y >= self.p.height:
26 | self.y %= self.p.height
27 | if self.x < 0:
28 | self.x += self.p.width
29 | if self.y < 0:
30 | self.y += self.p.height
31 |
32 | # grassListの中から牧草区画を見つける
33 | xscl = int(self.x / self.p.patchSize)
34 | yscl = int(self.y / self.p.patchSize)
35 |
36 | grass = self.p.grassList[xscl * self.p.rows_of_grass + yscl]
37 | if not grass.eaten:
38 | self.energy += grass.energy
39 | grass.eaten = True
40 |
41 | pyxel.circ(self.x,self.y,self.sz,self.col)
42 |
43 | # End of Sheep.py
44 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part6/components/fighter.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | from components.base_component import BaseComponent
6 | from input_handlers import GameOverEventHandler
7 | from render_order import RenderOrder
8 |
9 | if TYPE_CHECKING:
10 | from entity import Actor
11 |
12 | class Fighter(BaseComponent):
13 | entity: Actor
14 |
15 | def __init__(self, hp: int, defense: int, power: int):
16 | self.max_hp = hp
17 | self._hp = hp
18 | self.defense = defense
19 | self.power = power
20 |
21 | @property
22 | def hp(self) -> int:
23 | return self._hp
24 |
25 | @hp.setter
26 | def hp(self, value: int) -> None:
27 | self._hp = max(0, min(value, self.max_hp))
28 | if self._hp == 0 and self.entity.ai:
29 | self.die()
30 |
31 | def die(self) -> None:
32 | if self.engine.player is self.entity:
33 | death_message = "You died!"
34 | self.engine.event_handler = GameOverEventHandler(self.engine)
35 | else:
36 | death_message = f"{self.entity.name} is dead!"
37 |
38 | self.entity.char = "%"
39 | self.entity.color = 2
40 | self.entity.blocks_movement = False
41 | self.entity.ai = None
42 | self.entity.name = f"remains of {self.entity.name}"
43 | self.entity.render_order = RenderOrder.CORPSE
44 |
45 | print(death_message)
46 |
47 | # end of fighter.py
48 |
--------------------------------------------------------------------------------
/pyxel/asteroids/Rock.py:
--------------------------------------------------------------------------------
1 | import pyxel
2 | from Vec import *
3 |
4 | class Rock():
5 | def __init__(self, p : Vec, s : float, v : Vec):
6 | # 岩情報Rockは,座標Vec,サイズSize,速度Velocityから構成.
7 | self.p = p
8 | self.s = s
9 | self.v = v
10 | self.l = True
11 |
12 | # 岩形状
13 | self.r = [[+0.7, +0.5],
14 | [-0.1, +0.8],
15 | [-0.7, +0.6],
16 | [-0.9, -0.1],
17 | [-0.7, -0.9],
18 | [+0.0, -0.7],
19 | [+0.6, -0.8],
20 | [+0.9, -0.2],
21 | [+0.5, +0.1],
22 | [+0.7, +0.5]]
23 |
24 | # 座標pが,岩Rockに衝突したか否かを返却.
25 | # 岩座標rpから岩サイズsだけ離れた領域(円)に,座標pが含まれるか否かを返却.
26 | def collidesWith(self, p : Vec):
27 | rp = self.p
28 | rp = rp.sub(p)
29 | rp = rp.magV()
30 | return rp < self.s
31 |
32 | # 時間timeStep分だけ位置を更新.
33 | # 岩に弾が当たって,岩のサイズが7の場合は,ここに含まれる.
34 | def update(self, timeStep : float):
35 | self.p = self.p.add(self.v.mul(timeStep))
36 | self.p = self.p.restoreToScreen()
37 |
38 | # 岩を描画
39 | def draw(self):
40 | for n in range(len(self.r)-1):
41 | pyxel.line( self.p.x+self.r[n][0]*self.s+160,
42 | self.p.y+self.r[n][1]*self.s+160,
43 | self.p.x+self.r[n+1][0]*self.s+160,
44 | self.p.y+self.r[n+1][1]*self.s+160,
45 | 7 )
46 |
47 | # End of Rock.py
48 |
--------------------------------------------------------------------------------
/hsp/doc/200724_HspNote.md:
--------------------------------------------------------------------------------
1 | ## HSPによる開発記
2 |
3 | ### 2020-07-25
4 |
5 | 昨日くらいから,hot soup proccessorという言語処理系に手を出しています.昔遊んだBASICのゲームを移植してみました.基本は仮想画面を作って,画面表示と当たり判定を同時にやることにしました.画面のちらつきも昔っぽいです.命令も大体分かったので,もう少し書いてみようかなと思います.
6 |
7 | ### 2020-10-18
8 |
9 | 雑誌 I/O 1976年11月号(創刊号)のp.28に掲載されていた「パーソナル・コンピュータで立体の等高線を得る」という記事を発見しました.BASICで球体を描くプログラムがあったので,HSPに移植してみました.ちなみに,記事を書かれたのは,ASCII創業者の西和彦氏です.最初は,I/Oで記事を書かれていたという歴史があるのですね.
10 |
11 | 
12 |
13 | ### 2020-10-23
14 |
15 | あるホームページに掲載されていた「 マンデルブロート集合」という記事[1]を発見しました.マンデルブロート集合を描くプログラムがあったので,HSPに移植してみました.
16 |
17 | 
18 |
19 | 記事を書かれたのは,井村誠司氏です.高校の数学教師をされていた方のようです.
20 | - [1] http://imura.la.coocan.jp/40FractalCG/Mandel/mandel.html
21 |
22 | ### 2020-10-24
23 |
24 | 青色と黄色のグラデーションで表示すると,森田和郎氏の名作アルフォスっぽい仕上がりになりました.
25 |
26 | 
27 |
28 | ### 2021-01-08
29 |
30 | 非常にどうでもいいお知らせですが,昨年書いたHSPスクリプトをGitHubに上げました.リポジトリ名は,Gamesですが,ゲームではありません.2021年は,巣籠りで作業できるかもしれません.#HSP3
31 |
32 | ### 2021-01-09
33 |
34 | GitHub(*2)上にHSPスクリプトを公開しました.HSPスクリプトエディタに読み込んでいただければ,動作するはずです.version 3.5.1を利用しています.健康のために,プライベートではコードを極力書かないよう心がけています.が,2021年は少し書くかもしれません.#HSP3
35 | - (*2) https://github.com/jay-kumogata/RetroGames
36 |
37 | ### 2021-05-20
38 |
39 | 日本語を少し直しました.ですます調に統一しました.
40 |
41 | ___
42 | Copyright (c) 2020-2021 Kumogata Jay. All Rights Reserved.
43 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part5/main.py:
--------------------------------------------------------------------------------
1 | import copy
2 |
3 | import pyxel
4 |
5 | from engine import Engine
6 | import entity_factories
7 | from input_handlers import EventHandler
8 | from procgen import generate_dungeon
9 |
10 | def main() -> None:
11 | global engine
12 |
13 | screen_width = 80
14 | screen_height = 50
15 |
16 | map_width = 80
17 | map_height = 45
18 |
19 | room_max_size = 10
20 | room_min_size = 6
21 | max_rooms = 30
22 | max_monsters_per_room = 2
23 |
24 | event_handler = EventHandler()
25 |
26 | player = copy.deepcopy(entity_factories.player)
27 |
28 | game_map = generate_dungeon(
29 | max_rooms=max_rooms,
30 | room_min_size=room_min_size,
31 | room_max_size=room_max_size,
32 | map_width=map_width,
33 | map_height=map_height,
34 | max_monsters_per_room=max_monsters_per_room,
35 | player=player
36 | )
37 |
38 | engine = Engine(event_handler=event_handler, game_map=game_map, player=player)
39 |
40 | # メモ: Pyxel初期化
41 | pyxel.init(
42 | screen_width,
43 | screen_height,
44 | title="Yet Another Roguelike Tutorial",
45 | fps=30
46 | )
47 | pyxel.run(update, draw)
48 |
49 | def update():
50 | # メモ: イベントハンドラ(キー操作)を呼ぶ
51 | global engine
52 | engine.handle_events()
53 |
54 | def draw():
55 | # メモ: 画面描画ルーチンを呼ぶ
56 | global engine
57 | engine.render()
58 |
59 | if __name__ == "__main__":
60 | main()
61 |
62 | # end of main.py
63 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part5/tile_types.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import numpy as np # type: ignore
4 |
5 | # Tile graphics structured type
6 | graphic_dt = np.dtype(
7 | [
8 | ("ch", np.int32), # Unicode codepoint.(未使用: キャラクタコード)
9 | ("fg", np.int32), # 文字色(Pyxelでの色情報)
10 | ("bg", np.int32), # 背景色(Pyxelでの色情報)
11 | ]
12 | )
13 |
14 | # Tile struct used for statically defined tile data.
15 | tile_dt = np.dtype(
16 | [
17 | ("walkable", np.bool_), # True if this tile can be walked over.
18 | ("transparent", np.bool_), # True if this tile doesn't block FOV.
19 | ("dark", graphic_dt), # Graphics for when this tile is not in FOV.
20 | ("light", graphic_dt), # Graphics for when the tile is in FOV.
21 | ]
22 | )
23 |
24 |
25 | def new_tile(
26 | *, # Enforce the use of keywords, so that parameter order doesn't matter.
27 | walkable: int,
28 | transparent: int,
29 | dark: Tuple[int, int, int],
30 | light: Tuple[int, int, int]
31 | ) -> np.ndarray:
32 | """Helper function for defining individual tile types """
33 | return np.array((walkable, transparent, dark, light), dtype=tile_dt)
34 |
35 | # SHROUD represents unexplored, unseen tiles
36 | SHROUD = np.array((ord(" "), 0, 7), dtype=graphic_dt)
37 |
38 | floor = new_tile(
39 | walkable=True, transparent=True, dark=(ord(" "), 12, 1), light=(ord(" "), 10, 11),
40 | )
41 | wall = new_tile(
42 | walkable=False, transparent=False, dark=(ord(" "), 1, 2), light=(ord(" "), 9, 13),
43 | )
44 |
45 | # end of tile_types.py
46 |
--------------------------------------------------------------------------------
/pyxel/sombrero/sombrero.py:
--------------------------------------------------------------------------------
1 | #
2 | # 「ソンブレロ(メキシカンハット)デモ」
3 | # 「瞬時に拡散!古いパソコンでメキシカンハットが蘇った日」を参考にしました
4 | # cf. https://togetter.com/li/2390318
5 | #
6 | # Jun 25, 2024 ver.1 (Pyxelによる実装)
7 | # Jun 26, 2024 ver.2 (SuperChip8模擬)
8 | #
9 | # -*- coding: utf-8 -*-
10 | import math
11 | import pyxel
12 | import random
13 | import numpy as np
14 |
15 | def init():
16 | global d,dr
17 |
18 | d=np.full((160), 100)
19 | dr = math.pi / 180
20 |
21 | def update():
22 | global d,dr
23 | """ NONE """
24 | return
25 |
26 | # 画面描画
27 | def draw():
28 | global d,dr
29 |
30 | for y in range(-180,180,6):
31 | for x in range(-180,180,4):
32 | r=dr*math.sqrt(x*x+y*y)
33 | z=100*math.cos(r)-30*math.cos(3*r)
34 | sx=int(80+x/3-y/6)
35 | sy=int(40-y/6-z/4)
36 | if sx<0 or sx>=160: continue
37 | if d[sx]<=sy: continue
38 | zz=int((z+100)*0.035)+1
39 | c=0
40 | if zz==1 or zz==3 or zz==5 or zz==7: c += 2
41 | if zz==2 or zz==3 or zz>=6: c += 4
42 | if zz>=4: c += 8
43 | pyxel.pset(sx*2,sy*2,c)
44 | #pyxel.pset(sx,sy,c)
45 | #if c>0: pyxel.pset(sx*128/160,sy*64/100,7)
46 | d[sx]=sy
47 |
48 | # 初期化
49 | init()
50 | pyxel.init( 320, 200, title="sombrero", fps=20 )
51 | #pyxel.init( 160, 100, title="sombrero", fps=20 )
52 | #pyxel.init( 128, 64, title="sombrero", fps=20 )
53 | pyxel.cls(0)
54 | pyxel.run(update, draw)
55 |
56 | # end of sombrero.py
57 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part4/main.py:
--------------------------------------------------------------------------------
1 | import pyxel
2 |
3 | from engine import Engine
4 | from entity import Entity
5 | from input_handlers import EventHandler
6 | from procgen import generate_dungeon
7 |
8 | def main() -> None:
9 | global engine
10 |
11 | screen_width = 80
12 | screen_height = 50
13 |
14 | map_width = 80
15 | map_height = 45
16 |
17 | room_max_size = 10
18 | room_min_size = 6
19 | max_rooms = 30
20 |
21 | event_handler = EventHandler()
22 |
23 | player = Entity(int(screen_width / 2), int(screen_height / 2), "@", 7)
24 | npc = Entity(int(screen_width / 2 - 5), int(screen_height / 2), "@", 10)
25 | entities = {npc, player}
26 |
27 | game_map = generate_dungeon(
28 | max_rooms=max_rooms,
29 | room_min_size=room_min_size,
30 | room_max_size=room_max_size,
31 | map_width=map_width,
32 | map_height=map_height,
33 | player=player
34 | )
35 |
36 | engine = Engine(entities=entities, event_handler=event_handler, game_map=game_map, player=player)
37 |
38 | pyxel.init(
39 | screen_width,
40 | screen_height,
41 | title="Yet Another Roguelike Tutorial",
42 | fps=30
43 | )
44 | pyxel.run(update, draw)
45 |
46 | def update():
47 | # メモ: イベントハンドラ(キー操作)を呼ぶ
48 | global engine
49 | engine.handle_events()
50 |
51 | def draw():
52 | # メモ: 画面描画ルーチンを呼ぶ
53 | global engine
54 | engine.render()
55 |
56 | if __name__ == "__main__":
57 | main()
58 |
59 | # end of main.py
60 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part4/game_map.py:
--------------------------------------------------------------------------------
1 | import numpy as np # type: ignore
2 | import pyxel
3 |
4 | import tile_types
5 |
6 | class GameMap:
7 | def __init__(self, width: int, height: int):
8 | self.width, self.height = width, height
9 | self.tiles = np.full((width, height), fill_value=tile_types.wall, order="F")
10 |
11 | self.visible = np.full((width, height), fill_value=False, order="F") # Tiles the player can currently see
12 | self.explored = np.full((width, height), fill_value=False, order="F") # Tiles the player has seen before
13 |
14 | def in_bounds(self, x: int, y: int) -> bool:
15 | """Return True if x and y are inside of the bounds of this map."""
16 | return 0 <= x < self.width and 0 <= y < self.height
17 |
18 | def render(self) -> None:
19 | """
20 | Renders the map.
21 |
22 | If a tile is in the "visible" array, then draw it with the "light" colors.
23 | If it isn't, but it's in the "explored" array, then draw it with the "dark" colors.
24 | Otherwise, the default is "SHROUD".
25 | """
26 |
27 | # メモ: pyxel対応のため、愚直に表示(現時点では点描)
28 | for x in range(self.width):
29 | for y in range(self.height):
30 | if self.visible[x][y]:
31 | pyxel.pset(x,y,self.tiles["light"][x,y]["fg"])
32 | elif self.explored[x][y]:
33 | pyxel.pset(x,y,self.tiles["dark"][x,y]["fg"])
34 | else:
35 | pyxel.pset(x,y,tile_types.SHROUD["fg"])
36 |
37 | # end of game_map.py
38 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part4/tile_types.py:
--------------------------------------------------------------------------------
1 | # 2024/04/25
2 |
3 | from typing import Tuple
4 |
5 | import numpy as np # type: ignore
6 |
7 | # Tile graphics structured type
8 | graphic_dt = np.dtype(
9 | [
10 | ("ch", np.int32), # Unicode codepoint.(未使用: キャラクタコード)
11 | ("fg", np.int32), # 文字色(Pyxelでの色情報)
12 | ("bg", np.int32), # 背景色(Pyxelでの色情報)
13 | ]
14 | )
15 |
16 | # Tile struct used for statically defined tile data.
17 | tile_dt = np.dtype(
18 | [
19 | ("walkable", np.bool_), # True if this tile can be walked over.
20 | ("transparent", np.bool_), # True if this tile doesn't block FOV.
21 | ("dark", graphic_dt), # Graphics for when this tile is not in FOV.
22 | ("light", graphic_dt), # Graphics for when the tile is in FOV.
23 | ]
24 | )
25 |
26 |
27 | def new_tile(
28 | *, # Enforce the use of keywords, so that parameter order doesn't matter.
29 | walkable: int,
30 | transparent: int,
31 | dark: Tuple[int, int, int],
32 | light: Tuple[int, int, int]
33 | ) -> np.ndarray:
34 | """Helper function for defining individual tile types """
35 | return np.array((walkable, transparent, dark, light), dtype=tile_dt)
36 |
37 | # SHROUD represents unexplored, unseen tiles
38 | SHROUD = np.array((ord(" "), 0, 7), dtype=graphic_dt)
39 |
40 | floor = new_tile(
41 | walkable=True, transparent=True, dark=(ord(" "), 12, 1), light=(ord(" "), 10, 11),
42 | )
43 | wall = new_tile(
44 | walkable=False, transparent=False, dark=(ord(" "), 1, 2), light=(ord(" "), 9, 13),
45 | )
46 |
47 | # end of tile_types.py
48 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part7/tile_types.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import numpy as np # type: ignore
4 |
5 | # Tile graphics structured type
6 | graphic_dt = np.dtype(
7 | [
8 | ("ch", np.int32), # Unicode codepoint.(未使用: キャラクタコード)
9 | ("fg", np.int32), # 文字色(Pyxelでの色情報)
10 | ("bg", np.int32), # 背景色(Pyxelでの色情報)
11 | ]
12 | )
13 |
14 | # Tile struct used for statically defined tile data.
15 | tile_dt = np.dtype(
16 | [
17 | ("walkable", np.bool_), # True if this tile can be walked over.
18 | ("transparent", np.bool_), # True if this tile doesn't block FOV.
19 | ("dark", graphic_dt), # Graphics for when this tile is not in FOV.
20 | ("light", graphic_dt), # Graphics for when the tile is in FOV.
21 | ]
22 | )
23 |
24 |
25 | def new_tile(
26 | *, # Enforce the use of keywords, so that parameter order doesn't matter.
27 | walkable: int,
28 | transparent: int,
29 | dark: Tuple[int, int, int],
30 | light: Tuple[int, int, int]
31 | ) -> np.ndarray:
32 | """Helper function for defining individual tile types """
33 | return np.array((walkable, transparent, dark, light), dtype=tile_dt)
34 |
35 | # SHROUD represents unexplored, unseen tiles
36 | SHROUD = np.array((ord(" "), 0, 7), dtype=graphic_dt)
37 |
38 | # メモ: 床と壁において,光が当たっていない場合(dark)と当たっている場合(light)の情報
39 | floor = new_tile(
40 | walkable=True, transparent=True, dark=(ord(" "), 12, 1), light=(ord(" "), 10, 11),
41 | )
42 | wall = new_tile(
43 | walkable=False, transparent=False, dark=(ord(" "), 1, 2), light=(ord(" "), 9, 13),
44 | )
45 |
46 | # end of tile_types.py
47 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part8/tile_types.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import numpy as np # type: ignore
4 |
5 | # Tile graphics structured type
6 | graphic_dt = np.dtype(
7 | [
8 | ("ch", np.int32), # Unicode codepoint.(未使用: キャラクタコード)
9 | ("fg", np.int32), # 文字色(Pyxelでの色情報)
10 | ("bg", np.int32), # 背景色(Pyxelでの色情報)
11 | ]
12 | )
13 |
14 | # Tile struct used for statically defined tile data.
15 | tile_dt = np.dtype(
16 | [
17 | ("walkable", np.bool_), # True if this tile can be walked over.
18 | ("transparent", np.bool_), # True if this tile doesn't block FOV.
19 | ("dark", graphic_dt), # Graphics for when this tile is not in FOV.
20 | ("light", graphic_dt), # Graphics for when the tile is in FOV.
21 | ]
22 | )
23 |
24 |
25 | def new_tile(
26 | *, # Enforce the use of keywords, so that parameter order doesn't matter.
27 | walkable: int,
28 | transparent: int,
29 | dark: Tuple[int, int, int],
30 | light: Tuple[int, int, int]
31 | ) -> np.ndarray:
32 | """Helper function for defining individual tile types """
33 | return np.array((walkable, transparent, dark, light), dtype=tile_dt)
34 |
35 | # SHROUD represents unexplored, unseen tiles
36 | SHROUD = np.array((ord(" "), 0, 7), dtype=graphic_dt)
37 |
38 | # メモ: 床と壁において,光が当たっていない場合(dark)と当たっている場合(light)の情報
39 | floor = new_tile(
40 | walkable=True, transparent=True, dark=(ord(" "), 12, 1), light=(ord(" "), 10, 11),
41 | )
42 | wall = new_tile(
43 | walkable=False, transparent=False, dark=(ord(" "), 1, 2), light=(ord(" "), 9, 13),
44 | )
45 |
46 | # end of tile_types.py
47 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part9/tile_types.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import numpy as np # type: ignore
4 |
5 | # Tile graphics structured type
6 | graphic_dt = np.dtype(
7 | [
8 | ("ch", np.int32), # Unicode codepoint.(未使用: キャラクタコード)
9 | ("fg", np.int32), # 文字色(Pyxelでの色情報)
10 | ("bg", np.int32), # 背景色(Pyxelでの色情報)
11 | ]
12 | )
13 |
14 | # Tile struct used for statically defined tile data.
15 | tile_dt = np.dtype(
16 | [
17 | ("walkable", np.bool_), # True if this tile can be walked over.
18 | ("transparent", np.bool_), # True if this tile doesn't block FOV.
19 | ("dark", graphic_dt), # Graphics for when this tile is not in FOV.
20 | ("light", graphic_dt), # Graphics for when the tile is in FOV.
21 | ]
22 | )
23 |
24 |
25 | def new_tile(
26 | *, # Enforce the use of keywords, so that parameter order doesn't matter.
27 | walkable: int,
28 | transparent: int,
29 | dark: Tuple[int, int, int],
30 | light: Tuple[int, int, int]
31 | ) -> np.ndarray:
32 | """Helper function for defining individual tile types """
33 | return np.array((walkable, transparent, dark, light), dtype=tile_dt)
34 |
35 | # SHROUD represents unexplored, unseen tiles
36 | SHROUD = np.array((ord(" "), 0, 7), dtype=graphic_dt)
37 |
38 | # メモ: 床と壁において,光が当たっていない場合(dark)と当たっている場合(light)の情報
39 | floor = new_tile(
40 | walkable=True, transparent=True, dark=(ord(" "), 12, 1), light=(ord(" "), 10, 11),
41 | )
42 | wall = new_tile(
43 | walkable=False, transparent=False, dark=(ord(" "), 1, 2), light=(ord(" "), 9, 13),
44 | )
45 |
46 | # end of tile_types.py
47 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part10/tile_types.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import numpy as np # type: ignore
4 |
5 | # Tile graphics structured type
6 | graphic_dt = np.dtype(
7 | [
8 | ("ch", np.int32), # Unicode codepoint.(未使用: キャラクタコード)
9 | ("fg", np.int32), # 文字色(Pyxelでの色情報)
10 | ("bg", np.int32), # 背景色(Pyxelでの色情報)
11 | ]
12 | )
13 |
14 | # Tile struct used for statically defined tile data.
15 | tile_dt = np.dtype(
16 | [
17 | ("walkable", np.bool_), # True if this tile can be walked over.
18 | ("transparent", np.bool_), # True if this tile doesn't block FOV.
19 | ("dark", graphic_dt), # Graphics for when this tile is not in FOV.
20 | ("light", graphic_dt), # Graphics for when the tile is in FOV.
21 | ]
22 | )
23 |
24 |
25 | def new_tile(
26 | *, # Enforce the use of keywords, so that parameter order doesn't matter.
27 | walkable: int,
28 | transparent: int,
29 | dark: Tuple[int, int, int],
30 | light: Tuple[int, int, int]
31 | ) -> np.ndarray:
32 | """Helper function for defining individual tile types """
33 | return np.array((walkable, transparent, dark, light), dtype=tile_dt)
34 |
35 | # SHROUD represents unexplored, unseen tiles
36 | SHROUD = np.array((ord(" "), 0, 7), dtype=graphic_dt)
37 |
38 | # メモ: 床と壁において,光が当たっていない場合(dark)と当たっている場合(light)の情報
39 | floor = new_tile(
40 | walkable=True, transparent=True, dark=(ord(" "), 12, 1), light=(ord(" "), 10, 11),
41 | )
42 | wall = new_tile(
43 | walkable=False, transparent=False, dark=(ord(" "), 1, 2), light=(ord(" "), 9, 13),
44 | )
45 |
46 | # end of tile_types.py
47 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part6/tile_types.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import numpy as np # type: ignore
4 |
5 | # Tile graphics structured type
6 | graphic_dt = np.dtype(
7 | [
8 | ("ch", np.int32), # Unicode codepoint.(未使用: キャラクタコード)
9 | ("fg", np.int32), # 文字色(Pyxelでの色情報)
10 | ("bg", np.int32), # 背景色(Pyxelでの色情報)
11 | ]
12 | )
13 |
14 | # Tile struct used for statically defined tile data.
15 | tile_dt = np.dtype(
16 | [
17 | ("walkable", np.bool_), # True if this tile can be walked over.
18 | ("transparent", np.bool_), # True if this tile doesn't block FOV.
19 | ("dark", graphic_dt), # Graphics for when this tile is not in FOV.
20 | ("light", graphic_dt), # Graphics for when the tile is in FOV.
21 | ]
22 | )
23 |
24 |
25 | def new_tile(
26 | *, # Enforce the use of keywords, so that parameter order doesn't matter.
27 | walkable: int,
28 | transparent: int,
29 | dark: Tuple[int, int, int],
30 | light: Tuple[int, int, int]
31 | ) -> np.ndarray:
32 | """Helper function for defining individual tile types """
33 | return np.array((walkable, transparent, dark, light), dtype=tile_dt)
34 |
35 | # SHROUD represents unexplored, unseen tiles
36 | SHROUD = np.array((ord(" "), 0, 7), dtype=graphic_dt)
37 |
38 | # メモ: 床と壁において, 光が当たっていない場合(dark)と当たっている場合(light)の情報
39 | floor = new_tile(
40 | walkable=True, transparent=True, dark=(ord(" "), 12, 1), light=(ord(" "), 10, 11),
41 | )
42 | wall = new_tile(
43 | walkable=False, transparent=False, dark=(ord(" "), 1, 2), light=(ord(" "), 9, 13),
44 | )
45 |
46 | # end of tile_types.py
47 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part7/render_functions.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | import color
6 | import pyxel
7 |
8 | if TYPE_CHECKING:
9 | from tcod import Console
10 | from engine import Engine
11 | from game_map import GameMap
12 |
13 |
14 | def get_names_at_location(x: int, y: int, game_map: GameMap) -> str:
15 | if not game_map.in_bounds(x, y) or not game_map.visible[x, y]:
16 | return ""
17 |
18 | names = ", ".join(
19 | entity.name for entity in game_map.entities if entity.x == x and entity.y == y
20 | )
21 |
22 | return names.capitalize()
23 |
24 | def render_bar(
25 | current_value: int, maximum_value: int, total_width: int
26 | ) -> None:
27 | bar_width = int(float(current_value) / maximum_value * total_width)
28 |
29 | pyxel.rect(0*color.chr_x, 45*color.chr_y, total_width*color.chr_x, 1*color.chr_y, color.bar_empty)
30 |
31 | if bar_width > 0:
32 | pyxel.rect(
33 | 0*color.chr_x, 45*color.chr_y, bar_width*color.chr_x, 1*color.chr_y, color.bar_filled
34 | )
35 |
36 | pyxel.text(1*color.chr_x, 45*color.chr_y, f"HP: {current_value}/{maximum_value}", color.bar_text)
37 |
38 | def render_names_at_mouse_location(
39 | x: int, y: int, engine: Engine
40 | ) -> None:
41 | mouse_x, mouse_y = engine.mouse_location
42 |
43 | names_at_mouse_location = get_names_at_location(
44 | x=mouse_x, y=mouse_y, game_map=engine.game_map
45 | )
46 |
47 | pyxel.text(x*color.chr_x, y*color.chr_y, names_at_mouse_location, 7)
48 |
49 | # end of render_functions.py
50 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part10/entity_factories.py:
--------------------------------------------------------------------------------
1 | from components.ai import HostileEnemy
2 | from components import consumable
3 | from components.fighter import Fighter
4 | from components.inventory import Inventory
5 | from entity import Actor, Item
6 |
7 | player = Actor(
8 | char="@",
9 | color=7,
10 | name="Player",
11 | ai_cls=HostileEnemy,
12 | fighter=Fighter(hp=30, defense=2, power=5),
13 | inventory=Inventory(capacity=26),
14 | )
15 |
16 | orc = Actor(
17 | char="o",
18 | color=8,
19 | name="Orc",
20 | ai_cls=HostileEnemy,
21 | fighter=Fighter(hp=10, defense=0, power=3),
22 | inventory=Inventory(capacity=0),
23 | )
24 | troll = Actor(
25 | char="T",
26 | color=9,
27 | name="Troll",
28 | ai_cls=HostileEnemy,
29 | fighter=Fighter(hp=16, defense=1, power=4),
30 | inventory=Inventory(capacity=0),
31 | )
32 |
33 | confusion_scroll = Item(
34 | char="~",
35 | color=13,
36 | name="Confusion Scroll",
37 | consumable=consumable.ConfusionConsumable(number_of_turns=10),
38 | )
39 | health_potion = Item(
40 | char="!",
41 | color=11,
42 | name="Health Potion",
43 | consumable=consumable.HealingConsumable(amount=4),
44 | )
45 | lightning_scroll = Item(
46 | char="~",
47 | color=12,
48 | name="Lightning Scroll",
49 | consumable=consumable.LightningDamageConsumable(damage=20, maximum_range=5),
50 | )
51 | fireball_scroll = Item(
52 | char="~",
53 | color=8,
54 | name="Fireball Scroll",
55 | consumable=consumable.FireballDamageConsumable(damage=12, radius=3),
56 | )
57 |
58 | # end of entity_factories.py
59 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part9/entity_factories.py:
--------------------------------------------------------------------------------
1 | from components.ai import HostileEnemy
2 | from components import consumable
3 | from components.fighter import Fighter
4 | from components.inventory import Inventory
5 | from entity import Actor, Item
6 |
7 | player = Actor(
8 | char="@",
9 | color=7,
10 | name="Player",
11 | ai_cls=HostileEnemy,
12 | fighter=Fighter(hp=30, defense=2, power=5),
13 | inventory=Inventory(capacity=26),
14 | )
15 |
16 | orc = Actor(
17 | char="o",
18 | color=8,
19 | name="Orc",
20 | ai_cls=HostileEnemy,
21 | fighter=Fighter(hp=10, defense=0, power=3),
22 | inventory=Inventory(capacity=0),
23 | )
24 | troll = Actor(
25 | char="T",
26 | color=9,
27 | name="Troll",
28 | ai_cls=HostileEnemy,
29 | fighter=Fighter(hp=16, defense=1, power=4),
30 | inventory=Inventory(capacity=0),
31 | )
32 |
33 | confusion_scroll = Item(
34 | char="~",
35 | color=13,
36 | name="Confusion Scroll",
37 | consumable=consumable.ConfusionConsumable(number_of_turns=10),
38 | )
39 | health_potion = Item(
40 | char="!",
41 | color=11,
42 | name="Health Potion",
43 | consumable=consumable.HealingConsumable(amount=4),
44 | )
45 | lightning_scroll = Item(
46 | char="~",
47 | color=12,
48 | name="Lightning Scroll",
49 | consumable=consumable.LightningDamageConsumable(damage=20, maximum_range=5),
50 | )
51 | fireball_scroll = Item(
52 | char="~",
53 | color=8,
54 | name="Fireball Scroll",
55 | consumable=consumable.FireballDamageConsumable(damage=12, radius=3),
56 | )
57 |
58 | # end of entity_factories.py
59 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part6/engine.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | import pyxel
6 |
7 | from tcod.context import Context
8 | from tcod.console import Console
9 | from tcod.map import compute_fov
10 |
11 | from input_handlers import MainGameEventHandler
12 |
13 | if TYPE_CHECKING:
14 | from entity import Entity
15 | from game_map import GameMap
16 | from input_handlers import EventHandler
17 |
18 | class Engine:
19 | game_map: GameMap
20 |
21 | def __init__(self, player: Entity):
22 | self.event_handler: EventHandler = MainGameEventHandler(self)
23 | self.player = player
24 |
25 | def handle_enemy_turns(self) -> None:
26 | for entity in set(self.game_map.actors) - {self.player}:
27 | if entity.ai:
28 | entity.ai.perform()
29 |
30 | def update_fov(self) -> None:
31 | """Recompute the visible area based on the players point of view."""
32 | self.game_map.visible[:] = compute_fov(
33 | self.game_map.tiles["transparent"],
34 | (self.player.x, self.player.y),
35 | radius=8,
36 | )
37 | # If a tile is "visible" it should be added to "explored".
38 | self.game_map.explored |= self.game_map.visible
39 |
40 | def render(self) -> None:
41 | pyxel.cls(0)
42 | self.game_map.render()
43 |
44 | #console.print(
45 | # x=1,
46 | # y=47,
47 | # string=f"HP: {self.player.fighter.hp}/{self.player.fighter.max_hp}",
48 | #)
49 | pyxel.line(1,47,6,47,7) # TODO: HitPoint表示(キャラ表示に変更時に)
50 |
51 | # end of engine.py
52 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part7/main.py:
--------------------------------------------------------------------------------
1 | import copy
2 |
3 | import pyxel
4 |
5 | import color
6 | from engine import Engine
7 | import entity_factories
8 | from procgen import generate_dungeon
9 |
10 | def main() -> None:
11 | global engine
12 |
13 | screen_width = 80
14 | screen_height = 50
15 |
16 | map_width = 80
17 | map_height = 43
18 |
19 | room_max_size = 10
20 | room_min_size = 6
21 | max_rooms = 30
22 | max_monsters_per_room = 2
23 |
24 | player = copy.deepcopy(entity_factories.player)
25 | engine = Engine(player=player)
26 |
27 | engine.game_map = generate_dungeon(
28 | max_rooms=max_rooms,
29 | room_min_size=room_min_size,
30 | room_max_size=room_max_size,
31 | map_width=map_width,
32 | map_height=map_height,
33 | max_monsters_per_room=max_monsters_per_room,
34 | engine=engine,
35 | )
36 | engine.update_fov()
37 |
38 | engine.message_log.add_message(
39 | "Hello and welcome, adventurer, to yet another dungeon!", color.welcome_text
40 | )
41 |
42 | # Pyxel初期化
43 | pyxel.init(
44 | screen_width * color.chr_x,
45 | screen_height * color.chr_y,
46 | title="Yet Another Roguelike Tutorial",
47 | fps=30
48 | )
49 | pyxel.mouse(True) # メモ: マウスを表示
50 | pyxel.run(update, draw)
51 |
52 | def draw():
53 | # メモ: 画面描画ルーチンを呼ぶ
54 | global engine
55 | pyxel.cls(0)
56 | engine.event_handler.on_render()
57 |
58 | def update():
59 | # メモ: イベントハンドラを呼ぶ
60 | global engine
61 | engine.event_handler.handle_events()
62 |
63 | if __name__ == "__main__":
64 | main()
65 |
66 | # end of main.py
67 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part7/components/fighter.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | import color
6 | from components.base_component import BaseComponent
7 | from input_handlers import GameOverEventHandler
8 | from render_order import RenderOrder
9 |
10 | if TYPE_CHECKING:
11 | from entity import Actor
12 |
13 | class Fighter(BaseComponent):
14 | entity: Actor
15 |
16 | def __init__(self, hp: int, defense: int, power: int):
17 | self.max_hp = hp
18 | self._hp = hp
19 | self.defense = defense
20 | self.power = power
21 |
22 | @property
23 | def hp(self) -> int:
24 | return self._hp
25 |
26 | @hp.setter
27 | def hp(self, value: int) -> None:
28 | self._hp = max(0, min(value, self.max_hp))
29 | if self._hp == 0 and self.entity.ai:
30 | self.die()
31 |
32 | def die(self) -> None:
33 | if self.engine.player is self.entity:
34 | death_message = "You died!"
35 | death_message_color = color.player_die
36 | self.engine.event_handler = GameOverEventHandler(self.engine)
37 | else:
38 | death_message = f"{self.entity.name} is dead!"
39 | death_message_color = color.enemy_die
40 |
41 | self.entity.char = "%"
42 | self.entity.color = 2
43 | self.entity.blocks_movement = False
44 | self.entity.ai = None
45 | self.entity.name = f"remains of {self.entity.name}"
46 | self.entity.render_order = RenderOrder.CORPSE
47 |
48 | self.engine.message_log.add_message(death_message, death_message_color)
49 |
50 | # end of fighter.py
51 |
--------------------------------------------------------------------------------
/pyxel/sheep/SheepAndGrass.py:
--------------------------------------------------------------------------------
1 | #
2 | # Pyxelを使った「食事をする羊のプログラム」
3 | # 書籍「Pythonではじめる数学の冒険―プログラミングで図解する代数、幾何学、三角関数」を参考にしました.
4 | # https://www.oreilly.co.jp/books/9784873119304/
5 | #
6 | # Apr 19, 2024 ver.1 (Pyxelへ移植)
7 | #
8 | # -*- coding: utf-8 -*-
9 | import random
10 | import pyxel
11 | from Sheep import *
12 | from Grass import *
13 |
14 | class SheepAndGrass:
15 |
16 | def __init__( self ):
17 |
18 | # ウィンドウサイズ
19 | self.width = 128
20 | self.height = 128
21 |
22 | self.sheepList = [] # 羊用のリスト
23 | self.grassList = [] # 牧草用のリスト
24 | self.patchSize = 4 # 牧草の1区画の大きさ
25 | self.rows_of_grass = int( self.height / self.patchSize)
26 |
27 | # 羊を作る
28 | for n in range(20):
29 | sheep = Sheep(random.randint(0, self.width),random.randint(0, self.height))
30 | sheep.p = self
31 | self.sheepList.append(sheep)
32 |
33 | # 牧草を作る
34 | for x in range(0, self.width, self.patchSize):
35 | for y in range(0, self.height, self.patchSize):
36 | self.grassList.append(Grass(x, y, self.patchSize))
37 |
38 | # Pyxel初期化
39 | pyxel.init( self.width, self.height, title="SheepAndGrass", fps=10)
40 | pyxel.run(self.update, self.draw)
41 |
42 | def update(self):
43 | """NONE"""
44 | def draw(self):
45 | pyxel.cls(1)
46 |
47 | # 先に牧草を更新
48 | for grass in self.grassList:
49 | grass.update()
50 |
51 | # 続いて羊を更新
52 | for sheep in self.sheepList:
53 | sheep.update()
54 |
55 | # Main
56 | SheepAndGrass()
57 |
58 | # End of SheepAndGrass.py
59 |
60 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part5/engine.py:
--------------------------------------------------------------------------------
1 | from typing import Iterable, Any
2 |
3 | import pyxel
4 | from tcod.map import compute_fov
5 |
6 | from actions import EscapeAction, MovementAction
7 | from entity import Entity
8 | from game_map import GameMap
9 | from input_handlers import EventHandler
10 |
11 | class Engine:
12 | def __init__(self, event_handler: EventHandler, game_map: GameMap, player: Entity):
13 | self.event_handler = event_handler
14 | self.game_map = game_map
15 | self.player = player
16 | self.update_fov()
17 |
18 | def handle_enemy_turns(self) -> None:
19 | for entity in self.game_map.entities - {self.player}:
20 | print(f'The {entity.name} wonders when it will get to take a real turn.')
21 |
22 | def handle_events(self) -> None:
23 | # メモ: pyxel対応として、直接キーバッファを監視するように変更
24 | action = self.event_handler.dispatch()
25 |
26 | if action is None:
27 | return
28 |
29 | action.perform(self, self.player)
30 | self.handle_enemy_turns()
31 | self.update_fov() # Update the FOV before the players next action.
32 |
33 | def update_fov(self) -> None:
34 | """Recompute the visible area based on the players point of view."""
35 | self.game_map.visible[:] = compute_fov(
36 | self.game_map.tiles["transparent"],
37 | (self.player.x, self.player.y),
38 | radius=8,
39 | )
40 | # If a tile is "visible" it should be added to "explored".
41 | self.game_map.explored |= self.game_map.visible
42 |
43 |
44 | def render(self) -> None:
45 | pyxel.cls(0)
46 | self.game_map.render()
47 |
48 | # end of engine.py
49 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part4/engine.py:
--------------------------------------------------------------------------------
1 | from typing import Set, Iterable, Any
2 |
3 | import pyxel
4 | from tcod.map import compute_fov
5 |
6 | from actions import EscapeAction, MovementAction
7 | from entity import Entity
8 | from game_map import GameMap
9 | from input_handlers import EventHandler
10 |
11 | class Engine:
12 | def __init__(self, entities: Set[Entity], event_handler: EventHandler, game_map: GameMap, player: Entity):
13 | self.entities = entities
14 | self.event_handler = event_handler
15 | self.game_map = game_map
16 | self.player = player
17 | self.update_fov()
18 |
19 | def handle_events(self) -> None:
20 | # メモ: pyxel対応として、直接キーバッファを監視するように変更
21 | action = self.event_handler.dispatch()
22 |
23 | if action is None:
24 | return
25 |
26 | action.perform(self, self.player)
27 |
28 | self.update_fov() # Update the FOV before the players next action.
29 |
30 | def update_fov(self) -> None:
31 | """Recompute the visible area based on the players point of view."""
32 | self.game_map.visible[:] = compute_fov(
33 | self.game_map.tiles["transparent"],
34 | (self.player.x, self.player.y),
35 | radius=8,
36 | )
37 | # If a tile is "visible" it should be added to "explored".
38 | self.game_map.explored |= self.game_map.visible
39 |
40 |
41 | def render(self) -> None:
42 | pyxel.cls(0)
43 | self.game_map.render()
44 | for entity in self.entities:
45 | # Only print entities that are in the FOV
46 | if self.game_map.visible[entity.x, entity.y]:
47 | pyxel.pset(entity.x, entity.y, entity.color)
48 |
49 | # end of engine.py
50 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part11/entity_factories.py:
--------------------------------------------------------------------------------
1 | from components.ai import HostileEnemy
2 | from components import consumable
3 | from components.fighter import Fighter
4 | from components.inventory import Inventory
5 | from components.level import Level
6 | from entity import Actor, Item
7 |
8 | player = Actor(
9 | char="@",
10 | color=7,
11 | name="Player",
12 | ai_cls=HostileEnemy,
13 | fighter=Fighter(hp=30, defense=2, power=5),
14 | inventory=Inventory(capacity=26),
15 | level=Level(level_up_base=200),
16 | )
17 |
18 | orc = Actor(
19 | char="o",
20 | color=8,
21 | name="Orc",
22 | ai_cls=HostileEnemy,
23 | fighter=Fighter(hp=10, defense=0, power=3),
24 | inventory=Inventory(capacity=0),
25 | level=Level(xp_given=35),
26 | )
27 | troll = Actor(
28 | char="T",
29 | color=9,
30 | name="Troll",
31 | ai_cls=HostileEnemy,
32 | fighter=Fighter(hp=16, defense=1, power=4),
33 | inventory=Inventory(capacity=0),
34 | level=Level(xp_given=100),
35 | )
36 |
37 | confusion_scroll = Item(
38 | char="~",
39 | color=13,
40 | name="Confusion Scroll",
41 | consumable=consumable.ConfusionConsumable(number_of_turns=10),
42 | )
43 | health_potion = Item(
44 | char="!",
45 | color=11,
46 | name="Health Potion",
47 | consumable=consumable.HealingConsumable(amount=4),
48 | )
49 | lightning_scroll = Item(
50 | char="~",
51 | color=12,
52 | name="Lightning Scroll",
53 | consumable=consumable.LightningDamageConsumable(damage=20, maximum_range=5),
54 | )
55 | fireball_scroll = Item(
56 | char="~",
57 | color=8,
58 | name="Fireball Scroll",
59 | consumable=consumable.FireballDamageConsumable(damage=12, radius=3),
60 | )
61 |
62 | # end of entity_factories.py
63 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part12/entity_factories.py:
--------------------------------------------------------------------------------
1 | from components.ai import HostileEnemy
2 | from components import consumable
3 | from components.fighter import Fighter
4 | from components.inventory import Inventory
5 | from components.level import Level
6 | from entity import Actor, Item
7 |
8 | player = Actor(
9 | char="@",
10 | color=7,
11 | name="Player",
12 | ai_cls=HostileEnemy,
13 | fighter=Fighter(hp=30, defense=2, power=5),
14 | inventory=Inventory(capacity=26),
15 | level=Level(level_up_base=200),
16 | )
17 |
18 | orc = Actor(
19 | char="o",
20 | color=8,
21 | name="Orc",
22 | ai_cls=HostileEnemy,
23 | fighter=Fighter(hp=10, defense=0, power=3),
24 | inventory=Inventory(capacity=0),
25 | level=Level(xp_given=35),
26 | )
27 | troll = Actor(
28 | char="T",
29 | color=9,
30 | name="Troll",
31 | ai_cls=HostileEnemy,
32 | fighter=Fighter(hp=16, defense=1, power=4),
33 | inventory=Inventory(capacity=0),
34 | level=Level(xp_given=100),
35 | )
36 |
37 | confusion_scroll = Item(
38 | char="~",
39 | color=13,
40 | name="Confusion Scroll",
41 | consumable=consumable.ConfusionConsumable(number_of_turns=10),
42 | )
43 | health_potion = Item(
44 | char="!",
45 | color=11,
46 | name="Health Potion",
47 | consumable=consumable.HealingConsumable(amount=4),
48 | )
49 | lightning_scroll = Item(
50 | char="~",
51 | color=12,
52 | name="Lightning Scroll",
53 | consumable=consumable.LightningDamageConsumable(damage=20, maximum_range=5),
54 | )
55 | fireball_scroll = Item(
56 | char="~",
57 | color=8,
58 | name="Fireball Scroll",
59 | consumable=consumable.FireballDamageConsumable(damage=12, radius=3),
60 | )
61 |
62 | # end of entity_factories.py
63 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part11/render_functions.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import Tuple, TYPE_CHECKING
4 |
5 | import color
6 | import pyxel
7 |
8 | if TYPE_CHECKING:
9 | from tcod import Console
10 | from engine import Engine
11 | from game_map import GameMap
12 |
13 |
14 | def get_names_at_location(x: int, y: int, game_map: GameMap) -> str:
15 | if not game_map.in_bounds(x, y) or not game_map.visible[x, y]:
16 | return ""
17 |
18 | names = ", ".join(
19 | entity.name for entity in game_map.entities if entity.x == x and entity.y == y
20 | )
21 |
22 | return names.capitalize()
23 |
24 | def render_bar(
25 | current_value: int, maximum_value: int, total_width: int
26 | ) -> None:
27 | bar_width = int(float(current_value) / maximum_value * total_width)
28 |
29 | color.rect(0, 45, total_width, 1, color.bar_empty)
30 |
31 | if bar_width > 0:
32 | color.rect( 0, 45, bar_width, 1, color.bar_filled)
33 |
34 | color.text(1, 45, f"HP: {current_value}/{maximum_value}", color.bar_text)
35 |
36 | def render_dungeon_level(
37 | dungeon_level: int, location: Tuple[int, int]
38 | ) -> None:
39 | """
40 | Render the level the player is currently on, at the given location.
41 | """
42 | x, y = location
43 |
44 | color.text(x, y, f"Dungeon level: {dungeon_level}", color.white)
45 |
46 | def render_names_at_mouse_location(
47 | x: int, y: int, engine: Engine
48 | ) -> None:
49 | mouse_x, mouse_y = engine.mouse_location
50 |
51 | names_at_mouse_location = get_names_at_location(
52 | x=mouse_x, y=mouse_y, game_map=engine.game_map
53 | )
54 |
55 | color.text(x, y, names_at_mouse_location, color.white)
56 |
57 | # end of render_functions.py
58 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part12/render_functions.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import Tuple, TYPE_CHECKING
4 |
5 | import color
6 | import pyxel
7 |
8 | if TYPE_CHECKING:
9 | from tcod import Console
10 | from engine import Engine
11 | from game_map import GameMap
12 |
13 |
14 | def get_names_at_location(x: int, y: int, game_map: GameMap) -> str:
15 | if not game_map.in_bounds(x, y) or not game_map.visible[x, y]:
16 | return ""
17 |
18 | names = ", ".join(
19 | entity.name for entity in game_map.entities if entity.x == x and entity.y == y
20 | )
21 |
22 | return names.capitalize()
23 |
24 | def render_bar(
25 | current_value: int, maximum_value: int, total_width: int
26 | ) -> None:
27 | bar_width = int(float(current_value) / maximum_value * total_width)
28 |
29 | color.rect(0, 45, total_width, 1, color.bar_empty)
30 |
31 | if bar_width > 0:
32 | color.rect( 0, 45, bar_width, 1, color.bar_filled)
33 |
34 | color.text(1, 45, f"HP: {current_value}/{maximum_value}", color.bar_text)
35 |
36 | def render_dungeon_level(
37 | dungeon_level: int, location: Tuple[int, int]
38 | ) -> None:
39 | """
40 | Render the level the player is currently on, at the given location.
41 | """
42 | x, y = location
43 |
44 | color.text(x, y, f"Dungeon level: {dungeon_level}", color.white)
45 |
46 | def render_names_at_mouse_location(
47 | x: int, y: int, engine: Engine
48 | ) -> None:
49 | mouse_x, mouse_y = engine.mouse_location
50 |
51 | names_at_mouse_location = get_names_at_location(
52 | x=mouse_x, y=mouse_y, game_map=engine.game_map
53 | )
54 |
55 | color.text(x, y, names_at_mouse_location, color.white)
56 |
57 | # end of render_functions.py
58 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part13/render_functions.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import Tuple, TYPE_CHECKING
4 |
5 | import color
6 | import pyxel
7 |
8 | if TYPE_CHECKING:
9 | from tcod import Console
10 | from engine import Engine
11 | from game_map import GameMap
12 |
13 |
14 | def get_names_at_location(x: int, y: int, game_map: GameMap) -> str:
15 | if not game_map.in_bounds(x, y) or not game_map.visible[x, y]:
16 | return ""
17 |
18 | names = ", ".join(
19 | entity.name for entity in game_map.entities if entity.x == x and entity.y == y
20 | )
21 |
22 | return names.capitalize()
23 |
24 | def render_bar(
25 | current_value: int, maximum_value: int, total_width: int
26 | ) -> None:
27 | bar_width = int(float(current_value) / maximum_value * total_width)
28 |
29 | color.rect(0, 45, total_width, 1, color.bar_empty)
30 |
31 | if bar_width > 0:
32 | color.rect( 0, 45, bar_width, 1, color.bar_filled)
33 |
34 | color.text(1, 45, f"HP: {current_value}/{maximum_value}", color.bar_text)
35 |
36 | def render_dungeon_level(
37 | dungeon_level: int, location: Tuple[int, int]
38 | ) -> None:
39 | """
40 | Render the level the player is currently on, at the given location.
41 | """
42 | x, y = location
43 |
44 | color.text(x, y, f"Dungeon level: {dungeon_level}", color.white)
45 |
46 | def render_names_at_mouse_location(
47 | x: int, y: int, engine: Engine
48 | ) -> None:
49 | mouse_x, mouse_y = engine.mouse_location
50 |
51 | names_at_mouse_location = get_names_at_location(
52 | x=mouse_x, y=mouse_y, game_map=engine.game_map
53 | )
54 |
55 | color.text(x, y, names_at_mouse_location, color.white)
56 |
57 | # end of render_functions.py
58 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/src/render_functions.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import Tuple, TYPE_CHECKING
4 |
5 | import color
6 | import pyxel
7 |
8 | if TYPE_CHECKING:
9 | from tcod import Console
10 | from engine import Engine
11 | from game_map import GameMap
12 |
13 |
14 | def get_names_at_location(x: int, y: int, game_map: GameMap) -> str:
15 | if not game_map.in_bounds(x, y) or not game_map.visible[x, y]:
16 | return ""
17 |
18 | names = ", ".join(
19 | entity.name for entity in game_map.entities if entity.x == x and entity.y == y
20 | )
21 |
22 | return names.capitalize()
23 |
24 | def render_bar(
25 | current_value: int, maximum_value: int, total_width: int
26 | ) -> None:
27 | bar_width = int(float(current_value) / maximum_value * total_width)
28 |
29 | color.rect(0, 45, total_width, 1, color.bar_empty)
30 |
31 | if bar_width > 0:
32 | color.rect( 0, 45, bar_width, 1, color.bar_filled)
33 |
34 | color.text(1, 45, f"HP: {current_value}/{maximum_value}", color.bar_text)
35 |
36 | def render_dungeon_level(
37 | dungeon_level: int, location: Tuple[int, int]
38 | ) -> None:
39 | """
40 | Render the level the player is currently on, at the given location.
41 | """
42 | x, y = location
43 |
44 | color.text(x, y, f"Dungeon level: {dungeon_level}", color.white)
45 |
46 | def render_names_at_mouse_location(
47 | x: int, y: int, engine: Engine
48 | ) -> None:
49 | mouse_x, mouse_y = engine.mouse_location
50 |
51 | names_at_mouse_location = get_names_at_location(
52 | x=mouse_x, y=mouse_y, game_map=engine.game_map
53 | )
54 |
55 | color.text(x, y, names_at_mouse_location, color.white)
56 |
57 | # end of render_functions.py
58 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/src/color.py:
--------------------------------------------------------------------------------
1 | import pyxel
2 |
3 | # メモ: パレット(pyxel既定)
4 |
5 | black = 0
6 | dark_blue = 1
7 | purple = 2
8 | green = 3
9 | brown = 4
10 | blue = 5
11 | light_purple = 6
12 | white = 7
13 | red = 8
14 | amber = 9
15 | yellow = 10
16 | light_green = 11
17 | light_blue = 12
18 | gray = 13
19 | pink = 14
20 | beige = 15
21 |
22 | player_atk = light_blue
23 | enemy_atk = gray
24 |
25 | player_die = pink
26 | enemy_die = beige
27 | needs_target = blue
28 | status_effect_applied = light_purple
29 | descend = light_purple
30 |
31 | invalid = amber
32 | impossible = yellow
33 | error = purple
34 |
35 | welcome_text = light_purple
36 | health_recovered = green
37 |
38 | bar_text = white
39 | bar_filled = light_green
40 | bar_empty = red
41 |
42 | menu_title = yellow
43 | menu_text = white
44 |
45 | # メモ: 以下、色(color)とは直接関係ないコード(Pyxel関連)
46 |
47 | # メモ: コンソールサイズ(80x50)
48 | width = 80
49 | height = 50
50 |
51 | # メモ: 組込フォントのドット数(4x5)
52 | chr_x = 4
53 | chr_y = 5
54 |
55 | # メモ: ヘルパー関数
56 | def rect(x: int, y: int, w: int, h: int, col: int):
57 | pyxel.rect(x*chr_x, y*chr_y, w*chr_x, h*chr_y, col)
58 |
59 | def rectb(x: int, y: int, w: int, h: int, col: int):
60 | pyxel.rectb(x*chr_x, y*chr_y, w*chr_x, h*chr_y, col)
61 |
62 | def text(x: int, y: int, s: str, col: int):
63 | pyxel.text(x*chr_x, y*chr_y, s, col)
64 |
65 | # テキストを中央に表示
66 | def textc(x: int, y: int, s: str, col: int):
67 | pyxel.text((x - len(s) // 2)*chr_x, y*chr_y, s, col)
68 |
69 | # 背景色を指定してテキストを表示
70 | def textbg(x: int, y: int, s: str, fg: int, bg: int):
71 | rect(x, y, len(s), 1, bg)
72 | text(x ,y, s, fg)
73 |
74 | # 背景色を指定してテキストを中央に表示
75 | def textcbg(x: int, y: int, s: str, fg: int, bg: int):
76 | rect(x - len(s) // 2, y, len(s), 1, bg)
77 | textc(x ,y, s, fg)
78 |
79 | # end of color.py
80 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part11/color.py:
--------------------------------------------------------------------------------
1 | import pyxel
2 |
3 | # メモ: パレット(pyxel既定)
4 |
5 | black = 0
6 | dark_blue = 1
7 | purple = 2
8 | green = 3
9 | brown = 4
10 | blue = 5
11 | light_purple = 6
12 | white = 7
13 | red = 8
14 | amber = 9
15 | yellow = 10
16 | light_green = 11
17 | light_blue = 12
18 | gray = 13
19 | pink = 14
20 | beige = 15
21 |
22 | player_atk = light_blue
23 | enemy_atk = gray
24 |
25 | player_die = pink
26 | enemy_die = beige
27 | needs_target = blue
28 | status_effect_applied = light_purple
29 | descend = light_purple
30 |
31 | invalid = amber
32 | impossible = yellow
33 | error = purple
34 |
35 | welcome_text = light_purple
36 | health_recovered = green
37 |
38 | bar_text = white
39 | bar_filled = light_green
40 | bar_empty = red
41 |
42 | menu_title = yellow
43 | menu_text = white
44 |
45 | # メモ: 以下、色(color)とは直接関係ないコード(Pyxel関連)
46 |
47 | # メモ: コンソールサイズ(80x50)
48 | width = 80
49 | height = 50
50 |
51 | # メモ: 組込フォントのドット数(4x5)
52 | chr_x = 4
53 | chr_y = 5
54 |
55 | # メモ: ヘルパー関数
56 | def rect(x: int, y: int, w: int, h: int, col: int):
57 | pyxel.rect(x*chr_x, y*chr_y, w*chr_x, h*chr_y, col)
58 |
59 | def rectb(x: int, y: int, w: int, h: int, col: int):
60 | pyxel.rectb(x*chr_x, y*chr_y, w*chr_x, h*chr_y, col)
61 |
62 | def text(x: int, y: int, s: str, col: int):
63 | pyxel.text(x*chr_x, y*chr_y, s, col)
64 |
65 | # テキストを中央に表示
66 | def textc(x: int, y: int, s: str, col: int):
67 | pyxel.text((x - len(s) // 2)*chr_x, y*chr_y, s, col)
68 |
69 | # 背景色を指定してテキストを表示
70 | def textbg(x: int, y: int, s: str, fg: int, bg: int):
71 | rect(x, y, len(s), 1, bg)
72 | text(x ,y, s, fg)
73 |
74 | # 背景色を指定してテキストを中央に表示
75 | def textcbg(x: int, y: int, s: str, fg: int, bg: int):
76 | rect(x - len(s) // 2, y, len(s), 1, bg)
77 | textc(x ,y, s, fg)
78 |
79 | # end of color.py
80 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part12/color.py:
--------------------------------------------------------------------------------
1 | import pyxel
2 |
3 | # メモ: パレット(pyxel既定)
4 |
5 | black = 0
6 | dark_blue = 1
7 | purple = 2
8 | green = 3
9 | brown = 4
10 | blue = 5
11 | light_purple = 6
12 | white = 7
13 | red = 8
14 | amber = 9
15 | yellow = 10
16 | light_green = 11
17 | light_blue = 12
18 | gray = 13
19 | pink = 14
20 | beige = 15
21 |
22 | player_atk = light_blue
23 | enemy_atk = gray
24 |
25 | player_die = pink
26 | enemy_die = beige
27 | needs_target = blue
28 | status_effect_applied = light_purple
29 | descend = light_purple
30 |
31 | invalid = amber
32 | impossible = yellow
33 | error = purple
34 |
35 | welcome_text = light_purple
36 | health_recovered = green
37 |
38 | bar_text = white
39 | bar_filled = light_green
40 | bar_empty = red
41 |
42 | menu_title = yellow
43 | menu_text = white
44 |
45 | # メモ: 以下、色(color)とは直接関係ないコード(Pyxel関連)
46 |
47 | # メモ: コンソールサイズ(80x50)
48 | width = 80
49 | height = 50
50 |
51 | # メモ: 組込フォントのドット数(4x5)
52 | chr_x = 4
53 | chr_y = 5
54 |
55 | # メモ: ヘルパー関数
56 | def rect(x: int, y: int, w: int, h: int, col: int):
57 | pyxel.rect(x*chr_x, y*chr_y, w*chr_x, h*chr_y, col)
58 |
59 | def rectb(x: int, y: int, w: int, h: int, col: int):
60 | pyxel.rectb(x*chr_x, y*chr_y, w*chr_x, h*chr_y, col)
61 |
62 | def text(x: int, y: int, s: str, col: int):
63 | pyxel.text(x*chr_x, y*chr_y, s, col)
64 |
65 | # テキストを中央に表示
66 | def textc(x: int, y: int, s: str, col: int):
67 | pyxel.text((x - len(s) // 2)*chr_x, y*chr_y, s, col)
68 |
69 | # 背景色を指定してテキストを表示
70 | def textbg(x: int, y: int, s: str, fg: int, bg: int):
71 | rect(x, y, len(s), 1, bg)
72 | text(x ,y, s, fg)
73 |
74 | # 背景色を指定してテキストを中央に表示
75 | def textcbg(x: int, y: int, s: str, fg: int, bg: int):
76 | rect(x - len(s) // 2, y, len(s), 1, bg)
77 | textc(x ,y, s, fg)
78 |
79 | # end of color.py
80 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part13/color.py:
--------------------------------------------------------------------------------
1 | import pyxel
2 |
3 | # メモ: パレット(pyxel既定)
4 |
5 | black = 0
6 | dark_blue = 1
7 | purple = 2
8 | green = 3
9 | brown = 4
10 | blue = 5
11 | light_purple = 6
12 | white = 7
13 | red = 8
14 | amber = 9
15 | yellow = 10
16 | light_green = 11
17 | light_blue = 12
18 | gray = 13
19 | pink = 14
20 | beige = 15
21 |
22 | player_atk = light_blue
23 | enemy_atk = gray
24 |
25 | player_die = pink
26 | enemy_die = beige
27 | needs_target = blue
28 | status_effect_applied = light_purple
29 | descend = light_purple
30 |
31 | invalid = amber
32 | impossible = yellow
33 | error = purple
34 |
35 | welcome_text = light_purple
36 | health_recovered = green
37 |
38 | bar_text = white
39 | bar_filled = light_green
40 | bar_empty = red
41 |
42 | menu_title = yellow
43 | menu_text = white
44 |
45 | # メモ: 以下、色(color)とは直接関係ないコード(Pyxel関連)
46 |
47 | # メモ: コンソールサイズ(80x50)
48 | width = 80
49 | height = 50
50 |
51 | # メモ: 組込フォントのドット数(4x5)
52 | chr_x = 4
53 | chr_y = 5
54 |
55 | # メモ: ヘルパー関数
56 | def rect(x: int, y: int, w: int, h: int, col: int):
57 | pyxel.rect(x*chr_x, y*chr_y, w*chr_x, h*chr_y, col)
58 |
59 | def rectb(x: int, y: int, w: int, h: int, col: int):
60 | pyxel.rectb(x*chr_x, y*chr_y, w*chr_x, h*chr_y, col)
61 |
62 | def text(x: int, y: int, s: str, col: int):
63 | pyxel.text(x*chr_x, y*chr_y, s, col)
64 |
65 | # テキストを中央に表示
66 | def textc(x: int, y: int, s: str, col: int):
67 | pyxel.text((x - len(s) // 2)*chr_x, y*chr_y, s, col)
68 |
69 | # 背景色を指定してテキストを表示
70 | def textbg(x: int, y: int, s: str, fg: int, bg: int):
71 | rect(x, y, len(s), 1, bg)
72 | text(x ,y, s, fg)
73 |
74 | # 背景色を指定してテキストを中央に表示
75 | def textcbg(x: int, y: int, s: str, fg: int, bg: int):
76 | rect(x - len(s) // 2, y, len(s), 1, bg)
77 | textc(x ,y, s, fg)
78 |
79 | # end of color.py
80 |
--------------------------------------------------------------------------------
/research/99_03_NoteOnGames2019.md:
--------------------------------------------------------------------------------
1 | # 99_ゲーム雑記: 03_ゲーム雑記2019
2 |
3 | ## twitterより
4 |
5 | ### 2019-09-15
6 |
7 | NHK連続テレビ小説「なつぞら」を見て思ったのですが,20年後ぐらいには,セガの小玉理恵子さんを主役にしたシリーズが作られるかもしれません.そして,ラストシーンは,GDCでのPioneer Award授賞式です.
8 |
9 | ### 2019-10-19
10 |
11 | Z80です.
12 |
13 | ### 2019-10-20
14 |
15 | アレクセイパジトノフ氏.すっかりアメリカ人になりました.ゲームボーイを首からかけています.
16 | テトリスといえば,ゲームボーイです.
17 |
18 | ### 2019-10-22
19 |
20 | Nintendo Switchの出来損ないみたいなゲーム機です.君の名はという感じです.
21 | Atariがゲーム機出すとか言ってたから,それでしょうか.今日分かったのですが,現行の天皇制は,エミュレーションです.
22 |
23 | ダビスタというゲームが大好きで,最近またDSでプレイしています.
24 | 牝馬は,引退直前までレースに出走させられるのですが,引退後は,繁殖牝馬として,優秀な仔馬を生むことをもとめられます.
25 | その様子は,キャリアウーマンとしてバリバリ仕事をしていたのに,次の日から優秀な子供を産み育てることをもとめられ,運命に翻弄される若い母親の姿に重なって見えます.
26 | (こんなツイートを本日するのには,本当に大意はありません.ただ,ふと想起されただけです.)
27 |
28 | MZ80Kも,Mac SEとPETに並んで立派です.最初に,確か秋葉原だったと思うけど,MZ80Kでゲームが動いているのを見て,なんとも言えない興奮を覚えた記憶があります.エミュレータを作っていて,最初に画面が再現された時の興奮に似ています.
29 |
30 | ### 2019-10-23
31 |
32 | Evercadeというのは,英国のレトロゲームを作る企業みたいです.Atariとか,Namcoとか,InterPlayとか,DataEastとかのレトロゲームを専用ゲーム機で出している企業とのことです.InterPlayというのは,海外でPCゲームを出していた企業みたいです.知りませんでした.
33 |
34 | ### 2019-10-30
35 |
36 | 宮本茂氏が,文化功労者になりました.当然と言えば当然です.これからゲーム分野の受賞者が増えそうです.
37 | 世間的にもそろそろということで,機が熟したのでしょうか.セガ関係者としては,鈴木裕氏,中裕司氏は,次の候補かもしれません.
38 |
39 | _(2023-10-29) その後,ゲーム部門としては,作曲家のすぎやまこういち氏が,受賞されています._
40 |
41 | 去年の11/3に,『紫綬褒章は,「学術芸術上の発明改良創作に関し事績著明なる者」に授与されるのに,ゲームクリエータに受賞者はいませんでした.ゲームは芸術の域には至っていないということでしょうか.宮本茂さんは,フランスの勲章を受けています.「寺尾聡さんに紫綬褒章あげるのであれば,宮本茂さんにあげないといけません.」と言っていたら,ある方に「政治家にでもなったらどうですか.」と言われました.でも,公約が「宮本茂さんに勲章をあげる」というのも,ちょっと志が低い気がしたので諦めました.』と呟いていました.
42 |
43 | ロードランナーと言えば,これだと個人的には思います.
44 |
45 | ### 2019-12-09
46 |
47 | どうしても,「東亜プラン」というと,究極タイガーなのですね.個人的には,飛翔鮫が大好きです.
48 | 川崎の九龍城がなくなり,できなくなりました.タイガーヘリと究極タイガーは,PS1版を持ってるから,いつでもできます.
49 | 東亜プランシューティングバトル1です.
50 |
51 | 以前はワンダースワンを持っていました.壊れたから,2台目を買いました.2台目も壊れたので,あきらめました.
52 | 最近は,中古でも売ってるのをあまり見かけなくなりました.
53 |
54 | 以上
55 |
--------------------------------------------------------------------------------
/research/01_03_AsteroidsNote.md:
--------------------------------------------------------------------------------
1 | # 01_ゲーム製作: 03_アステロイド開発記
2 |
3 | つぶやきながら,アステロイドを開発する記録です.
4 |
5 | ## アステロイド開発記(2024年編)
6 |
7 | ### 2024-07-12
8 |
9 | 過去に開発した
10 | [Asteroids in Haskell](https://github.com/jay-kumogata/RetroGames/tree/main/haskell/asteroids)
11 | を,Pyxel/Pythonに移植してみることにしました.
12 |
13 |
14 |
15 | ### 2024-07-13
16 |
17 | Asteroids開発の続報です.本日の進捗は,以下の通りです.
18 |
19 | - Vecクラス(旧PointInSpaceクラス)を実装
20 | - Rockクラスを実装
21 |
22 | ### 2024-07-14
23 |
24 | Asteroids開発の続報です.本日の進捗は,以下の通りです.
25 |
26 | - Shipクラスを実装
27 | - Bulletクラスを実装
28 | - Asteroidsクラスを実装(未完了)
29 |
30 | ### 2024-07-20
31 |
32 | Asteroids開発の続報です.本日の進捗は,以下の通りです.
33 |
34 | - Asteroidsクラスを実装(未完了)
35 | - 弾発射処理
36 | - 岩分裂処理
37 |
38 | ### 2024-07-21
39 |
40 | Asteroids開発の続報です.本日の進捗は,以下の通りです.
41 |
42 | - Asteroidsクラスを実装(未完了)
43 | - 自機当り判定処理
44 | - ゲームオーバー処理
45 |
46 | ### 2024-07-25
47 |
48 | Haskellみたいな関数型は,関数適用が多く,コードが横長になり,Pythonみたいな逐次型は,コードが縦長になる傾向があります.
49 |
50 | ### 2024-07-27
51 |
52 | Asteroids開発の続報です.本日の進捗は,以下の通りです.
53 |
54 | - Asteroidsクラスを実装
55 | - 点数表示処理
56 |
57 | ### 2024-09-02
58 |
59 | Asteroids開発の続報です.本日の進捗は,以下の通りです.
60 |
61 | - コメントを修正
62 | - Asteroidsクラスを修正
63 | - 弾を撃ったら,自機も動くように変更(作用反作用の法則)
64 |
65 | ### 2024-09-23
66 |
67 | Asteroids開発の続報です.ビデオゲームとしては,一旦完成です.
68 |
69 |
70 |
71 | ### 2024-12-25
72 |
73 | 秋頃に,Haskellで書いたAsteroidsを,Pyxel/Pythonに移植しました.
74 | Githubの方には,[ソースコード](https://github.com/jay-kumogata/RetroGames/tree/main/pyxel/asteroids)を公開しましたが,Xには投稿していませんでした.
75 | Haskellでは関数適用を繰り返す処理も,Pythonだと逐次的な処理になり,楽しい移植作業でした.
76 |
77 |
78 |
79 | 以上
80 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part8/components/consumable.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import Optional, TYPE_CHECKING
4 |
5 | import actions
6 | import color
7 | import components.inventory
8 | from components.base_component import BaseComponent
9 | from exceptions import Impossible
10 |
11 | if TYPE_CHECKING:
12 | from entity import Actor, Item
13 |
14 |
15 | class Consumable(BaseComponent):
16 | parent: Item
17 |
18 | def get_action(self, consumer: Actor) -> Optional[actions.Action]:
19 | """Try to return the action for this item."""
20 | return actions.ItemAction(consumer, self.parent)
21 |
22 | def activate(self, action: actions.ItemAction) -> None:
23 | """Invoke this items ability.
24 |
25 | `action` is the context for this activation.
26 | """
27 | raise NotImplementedError()
28 |
29 | def consume(self) -> None:
30 | """Remove the consumed item from its containing inventory."""
31 | entity = self.parent
32 | inventory = entity.parent
33 | if isinstance(inventory, components.inventory.Inventory):
34 | inventory.items.remove(entity)
35 |
36 |
37 | class HealingConsumable(Consumable):
38 | def __init__(self, amount: int):
39 | self.amount = amount
40 |
41 | def activate(self, action: actions.ItemAction) -> None:
42 | consumer = action.entity
43 | amount_recovered = consumer.fighter.heal(self.amount)
44 |
45 | if amount_recovered > 0:
46 | self.engine.message_log.add_message(
47 | f"You consume the {self.parent.name}, and recover {amount_recovered} HP!",
48 | color.health_recovered,
49 | )
50 | self.consume()
51 | else:
52 | raise Impossible(f"Your health is already full.")
53 |
54 | # end of consumable.py
55 |
--------------------------------------------------------------------------------
/pyxel/tennis/App.py:
--------------------------------------------------------------------------------
1 | # generated by Grok3
2 |
3 | import pyxel
4 | from TennisEngine import *
5 |
6 | class App:
7 | W = 0
8 | S = 1
9 | D = 2
10 | Up = 3
11 | Down = 4
12 | Left = 5
13 |
14 | def __init__(self):
15 | # 画面サイズをサイズ (256, 256) に合わせる
16 | pyxel.init(256,256)
17 | # TennisEngine を初期化(バッファサイズとして 256x256 を指定)
18 | self.my_engine = TennisEngine(256, 256)
19 | self.keys = [False] * 6 # W, S, D, Up, Down, Left
20 | # 画像の読み込み(frame.png と overlay.png が必要)
21 | #pyxel.images[0].load(0, 0, "frame.png") # イメージバンク 0 に frame.png
22 | #pyxel.images[1].load(0, 0, "overlay.png") # イメージバンク 1 に overlay.png
23 | # キーイベントを登録
24 | pyxel.run(self.update, self.draw)
25 |
26 | def update(self):
27 | # キー入力の処理
28 | self.keys[self.W] = pyxel.btn(pyxel.KEY_W)
29 | self.keys[self.S] = pyxel.btn(pyxel.KEY_S)
30 | self.keys[self.D] = pyxel.btn(pyxel.KEY_D)
31 | self.keys[self.Up] = pyxel.btn(pyxel.KEY_UP)
32 | self.keys[self.Down] = pyxel.btn(pyxel.KEY_DOWN)
33 | self.keys[self.Left] = pyxel.btn(pyxel.KEY_LEFT)
34 |
35 | # スペースキーでヒット
36 | if pyxel.btnp(pyxel.KEY_SPACE):
37 | self.my_engine.hit()
38 |
39 | # 'i' キーでスクリーンショット保存
40 | if pyxel.btnp(pyxel.KEY_I):
41 | pyxel.save("pic{:03d}.png".format(pyxel.frame_count))
42 |
43 | # ゲームエンジンの更新
44 | self.my_engine.update(self.keys)
45 |
46 | def draw(self):
47 | # 背景をクリア(黒)
48 | pyxel.cls(0)
49 | # ゲームエンジンの描画
50 | self.my_engine.draw()
51 | # バッファを画面に描画(0, 0 のオフセットで 256x256 の領域)
52 | pyxel.blt(0, 0, 0, 0, 0, 256, 256, colkey=0)
53 | # フレーム画像の描画
54 | pyxel.blt(0, 0, 0, 0, 0, 256, 256, colkey=0)
55 | # オーバーレイ画像の描画(ADD ブレンドを模倣)
56 | pyxel.blt(0, 0, 1, 0, 0, 256, 256, colkey=0)
57 |
58 | App()
59 |
60 | # App.py
61 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part7/engine.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | import pyxel
6 |
7 | from tcod.context import Context
8 | from tcod.console import Console
9 | from tcod.map import compute_fov
10 |
11 | from input_handlers import MainGameEventHandler
12 | from message_log import MessageLog
13 | from render_functions import render_bar, render_names_at_mouse_location
14 |
15 | if TYPE_CHECKING:
16 | from entity import Entity
17 | from game_map import GameMap
18 | from input_handlers import EventHandler
19 |
20 | class Engine:
21 | game_map: GameMap
22 |
23 | def __init__(self, player: Entity):
24 | self.event_handler: EventHandler = MainGameEventHandler(self)
25 | self.message_log = MessageLog()
26 | self.mouse_location = (0, 0)
27 | self.player = player
28 |
29 | def handle_enemy_turns(self) -> None:
30 | for entity in set(self.game_map.actors) - {self.player}:
31 | if entity.ai:
32 | entity.ai.perform()
33 |
34 | def update_fov(self) -> None:
35 | """Recompute the visible area based on the players point of view."""
36 | self.game_map.visible[:] = compute_fov(
37 | self.game_map.tiles["transparent"],
38 | (self.player.x, self.player.y),
39 | radius=8,
40 | )
41 | # If a tile is "visible" it should be added to "explored".
42 | self.game_map.explored |= self.game_map.visible
43 |
44 | def render(self) -> None:
45 | self.game_map.render()
46 | self.message_log.render(x=21, y=45, width=40, height=5)
47 |
48 | render_bar(
49 | current_value=self.player.fighter.hp,
50 | maximum_value=self.player.fighter.max_hp,
51 | total_width=20,
52 | )
53 |
54 | render_names_at_mouse_location(x=21, y=44, engine=self)
55 |
56 | # end of engine.py
57 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/src/tile_types.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import numpy as np # type: ignore
4 | import color
5 |
6 | # Tile graphics structured type
7 | graphic_dt = np.dtype(
8 | [
9 | ("ch", np.int32), # Unicode codepoint.(未使用: キャラクタコード)
10 | ("fg", np.int32), # 文字色(Pyxelでの色情報)
11 | ("bg", np.int32), # 背景色(Pyxelでの色情報)
12 | ]
13 | )
14 |
15 | # Tile struct used for statically defined tile data.
16 | tile_dt = np.dtype(
17 | [
18 | ("walkable", np.bool_), # True if this tile can be walked over.
19 | ("transparent", np.bool_), # True if this tile doesn't block FOV.
20 | ("dark", graphic_dt), # Graphics for when this tile is not in FOV.
21 | ("light", graphic_dt), # Graphics for when the tile is in FOV.
22 | ]
23 | )
24 |
25 |
26 | def new_tile(
27 | *, # Enforce the use of keywords, so that parameter order doesn't matter.
28 | walkable: int,
29 | transparent: int,
30 | dark: Tuple[int, int, int],
31 | light: Tuple[int, int, int]
32 | ) -> np.ndarray:
33 | """Helper function for defining individual tile types """
34 | return np.array((walkable, transparent, dark, light), dtype=tile_dt)
35 |
36 | # SHROUD represents unexplored, unseen tiles
37 | SHROUD = np.array((ord(" "), color.white, color.black), dtype=graphic_dt)
38 |
39 | # メモ: 床と壁において,光が当たっていない場合(dark)と当たっている場合(light)の情報
40 | floor = new_tile(
41 | walkable=True,
42 | transparent=True,
43 | dark=(ord(" "), color.white, color.light_blue),
44 | light=(ord(" "), color.white, color.yellow),
45 | )
46 | wall = new_tile(
47 | walkable=False,
48 | transparent=False,
49 | dark=(ord(" "), color.white, color.dark_blue),
50 | light=(ord(" "), color.white, color.amber),
51 | )
52 | down_stairs = new_tile(
53 | walkable=True,
54 | transparent=True,
55 | dark=(ord(">"), color.dark_blue, color.blue),
56 | light=(ord(">"), color.white, color.yellow),
57 | )
58 |
59 | # end of tile_types.py
60 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part11/tile_types.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import numpy as np # type: ignore
4 | import color
5 |
6 | # Tile graphics structured type
7 | graphic_dt = np.dtype(
8 | [
9 | ("ch", np.int32), # Unicode codepoint.(未使用: キャラクタコード)
10 | ("fg", np.int32), # 文字色(Pyxelでの色情報)
11 | ("bg", np.int32), # 背景色(Pyxelでの色情報)
12 | ]
13 | )
14 |
15 | # Tile struct used for statically defined tile data.
16 | tile_dt = np.dtype(
17 | [
18 | ("walkable", np.bool_), # True if this tile can be walked over.
19 | ("transparent", np.bool_), # True if this tile doesn't block FOV.
20 | ("dark", graphic_dt), # Graphics for when this tile is not in FOV.
21 | ("light", graphic_dt), # Graphics for when the tile is in FOV.
22 | ]
23 | )
24 |
25 |
26 | def new_tile(
27 | *, # Enforce the use of keywords, so that parameter order doesn't matter.
28 | walkable: int,
29 | transparent: int,
30 | dark: Tuple[int, int, int],
31 | light: Tuple[int, int, int]
32 | ) -> np.ndarray:
33 | """Helper function for defining individual tile types """
34 | return np.array((walkable, transparent, dark, light), dtype=tile_dt)
35 |
36 | # SHROUD represents unexplored, unseen tiles
37 | SHROUD = np.array((ord(" "), color.white, color.black), dtype=graphic_dt)
38 |
39 | # メモ: 床と壁において,光が当たっていない場合(dark)と当たっている場合(light)の情報
40 | floor = new_tile(
41 | walkable=True,
42 | transparent=True,
43 | dark=(ord(" "), color.white, color.light_blue),
44 | light=(ord(" "), color.white, color.yellow),
45 | )
46 | wall = new_tile(
47 | walkable=False,
48 | transparent=False,
49 | dark=(ord(" "), color.white, color.dark_blue),
50 | light=(ord(" "), color.white, color.amber),
51 | )
52 | down_stairs = new_tile(
53 | walkable=True,
54 | transparent=True,
55 | dark=(ord(">"), color.dark_blue, color.blue),
56 | light=(ord(">"), color.white, color.yellow),
57 | )
58 |
59 | # end of tile_types.py
60 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part12/tile_types.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import numpy as np # type: ignore
4 | import color
5 |
6 | # Tile graphics structured type
7 | graphic_dt = np.dtype(
8 | [
9 | ("ch", np.int32), # Unicode codepoint.(未使用: キャラクタコード)
10 | ("fg", np.int32), # 文字色(Pyxelでの色情報)
11 | ("bg", np.int32), # 背景色(Pyxelでの色情報)
12 | ]
13 | )
14 |
15 | # Tile struct used for statically defined tile data.
16 | tile_dt = np.dtype(
17 | [
18 | ("walkable", np.bool_), # True if this tile can be walked over.
19 | ("transparent", np.bool_), # True if this tile doesn't block FOV.
20 | ("dark", graphic_dt), # Graphics for when this tile is not in FOV.
21 | ("light", graphic_dt), # Graphics for when the tile is in FOV.
22 | ]
23 | )
24 |
25 |
26 | def new_tile(
27 | *, # Enforce the use of keywords, so that parameter order doesn't matter.
28 | walkable: int,
29 | transparent: int,
30 | dark: Tuple[int, int, int],
31 | light: Tuple[int, int, int]
32 | ) -> np.ndarray:
33 | """Helper function for defining individual tile types """
34 | return np.array((walkable, transparent, dark, light), dtype=tile_dt)
35 |
36 | # SHROUD represents unexplored, unseen tiles
37 | SHROUD = np.array((ord(" "), color.white, color.black), dtype=graphic_dt)
38 |
39 | # メモ: 床と壁において,光が当たっていない場合(dark)と当たっている場合(light)の情報
40 | floor = new_tile(
41 | walkable=True,
42 | transparent=True,
43 | dark=(ord(" "), color.white, color.light_blue),
44 | light=(ord(" "), color.white, color.yellow),
45 | )
46 | wall = new_tile(
47 | walkable=False,
48 | transparent=False,
49 | dark=(ord(" "), color.white, color.dark_blue),
50 | light=(ord(" "), color.white, color.amber),
51 | )
52 | down_stairs = new_tile(
53 | walkable=True,
54 | transparent=True,
55 | dark=(ord(">"), color.dark_blue, color.blue),
56 | light=(ord(">"), color.white, color.yellow),
57 | )
58 |
59 | # end of tile_types.py
60 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part13/tile_types.py:
--------------------------------------------------------------------------------
1 | from typing import Tuple
2 |
3 | import numpy as np # type: ignore
4 | import color
5 |
6 | # Tile graphics structured type
7 | graphic_dt = np.dtype(
8 | [
9 | ("ch", np.int32), # Unicode codepoint.(未使用: キャラクタコード)
10 | ("fg", np.int32), # 文字色(Pyxelでの色情報)
11 | ("bg", np.int32), # 背景色(Pyxelでの色情報)
12 | ]
13 | )
14 |
15 | # Tile struct used for statically defined tile data.
16 | tile_dt = np.dtype(
17 | [
18 | ("walkable", np.bool_), # True if this tile can be walked over.
19 | ("transparent", np.bool_), # True if this tile doesn't block FOV.
20 | ("dark", graphic_dt), # Graphics for when this tile is not in FOV.
21 | ("light", graphic_dt), # Graphics for when the tile is in FOV.
22 | ]
23 | )
24 |
25 |
26 | def new_tile(
27 | *, # Enforce the use of keywords, so that parameter order doesn't matter.
28 | walkable: int,
29 | transparent: int,
30 | dark: Tuple[int, int, int],
31 | light: Tuple[int, int, int]
32 | ) -> np.ndarray:
33 | """Helper function for defining individual tile types """
34 | return np.array((walkable, transparent, dark, light), dtype=tile_dt)
35 |
36 | # SHROUD represents unexplored, unseen tiles
37 | SHROUD = np.array((ord(" "), color.white, color.black), dtype=graphic_dt)
38 |
39 | # メモ: 床と壁において,光が当たっていない場合(dark)と当たっている場合(light)の情報
40 | floor = new_tile(
41 | walkable=True,
42 | transparent=True,
43 | dark=(ord(" "), color.white, color.light_blue),
44 | light=(ord(" "), color.white, color.yellow),
45 | )
46 | wall = new_tile(
47 | walkable=False,
48 | transparent=False,
49 | dark=(ord(" "), color.white, color.dark_blue),
50 | light=(ord(" "), color.white, color.amber),
51 | )
52 | down_stairs = new_tile(
53 | walkable=True,
54 | transparent=True,
55 | dark=(ord(">"), color.dark_blue, color.blue),
56 | light=(ord(">"), color.white, color.yellow),
57 | )
58 |
59 | # end of tile_types.py
60 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part8/engine.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | import pyxel
6 |
7 | from tcod.map import compute_fov
8 |
9 | import exceptions
10 | from input_handlers import MainGameEventHandler
11 | from message_log import MessageLog
12 | from render_functions import render_bar, render_names_at_mouse_location
13 |
14 | if TYPE_CHECKING:
15 | from entity import Entity
16 | from game_map import GameMap
17 | from input_handlers import EventHandler
18 |
19 | class Engine:
20 | game_map: GameMap
21 |
22 | def __init__(self, player: Entity):
23 | self.event_handler: EventHandler = MainGameEventHandler(self)
24 | self.message_log = MessageLog()
25 | self.mouse_location = (0, 0)
26 | self.player = player
27 |
28 | def handle_enemy_turns(self) -> None:
29 | for entity in set(self.game_map.actors) - {self.player}:
30 | if entity.ai:
31 | try:
32 | entity.ai.perform()
33 | except exceptions.Impossible:
34 | pass # Ignore impossible action exceptions from AI.
35 |
36 | def update_fov(self) -> None:
37 | """Recompute the visible area based on the players point of view."""
38 | self.game_map.visible[:] = compute_fov(
39 | self.game_map.tiles["transparent"],
40 | (self.player.x, self.player.y),
41 | radius=8,
42 | )
43 | # If a tile is "visible" it should be added to "explored".
44 | self.game_map.explored |= self.game_map.visible
45 |
46 | def render(self) -> None:
47 | self.game_map.render()
48 | self.message_log.render(x=21, y=45, width=40, height=5)
49 |
50 | render_bar(
51 | current_value=self.player.fighter.hp,
52 | maximum_value=self.player.fighter.max_hp,
53 | total_width=20,
54 | )
55 |
56 | render_names_at_mouse_location(x=21, y=44, engine=self)
57 |
58 | # end of engine.py
59 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part9/engine.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | import pyxel
6 |
7 | from tcod.map import compute_fov
8 |
9 | import exceptions
10 | from input_handlers import MainGameEventHandler
11 | from message_log import MessageLog
12 | from render_functions import render_bar, render_names_at_mouse_location
13 |
14 | if TYPE_CHECKING:
15 | from entity import Entity
16 | from game_map import GameMap
17 | from input_handlers import EventHandler
18 |
19 | class Engine:
20 | game_map: GameMap
21 |
22 | def __init__(self, player: Entity):
23 | self.event_handler: EventHandler = MainGameEventHandler(self)
24 | self.message_log = MessageLog()
25 | self.mouse_location = (0, 0)
26 | self.player = player
27 |
28 | def handle_enemy_turns(self) -> None:
29 | for entity in set(self.game_map.actors) - {self.player}:
30 | if entity.ai:
31 | try:
32 | entity.ai.perform()
33 | except exceptions.Impossible:
34 | pass # Ignore impossible action exceptions from AI.
35 |
36 | def update_fov(self) -> None:
37 | """Recompute the visible area based on the players point of view."""
38 | self.game_map.visible[:] = compute_fov(
39 | self.game_map.tiles["transparent"],
40 | (self.player.x, self.player.y),
41 | radius=8,
42 | )
43 | # If a tile is "visible" it should be added to "explored".
44 | self.game_map.explored |= self.game_map.visible
45 |
46 | def render(self) -> None:
47 | self.game_map.render()
48 | self.message_log.render(x=21, y=45, width=40, height=5)
49 |
50 | render_bar(
51 | current_value=self.player.fighter.hp,
52 | maximum_value=self.player.fighter.max_hp,
53 | total_width=20,
54 | )
55 |
56 | render_names_at_mouse_location(x=21, y=44, engine=self)
57 |
58 | # end of engine.py
59 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part8/main.py:
--------------------------------------------------------------------------------
1 | import copy
2 | import traceback
3 |
4 | import pyxel
5 |
6 | import color
7 | from engine import Engine
8 | import entity_factories
9 | from procgen import generate_dungeon
10 |
11 | def main() -> None:
12 | global engine
13 |
14 | screen_width = 80
15 | screen_height = 50
16 |
17 | map_width = 80
18 | map_height = 43
19 |
20 | room_max_size = 10
21 | room_min_size = 6
22 | max_rooms = 30
23 | max_monsters_per_room = 2
24 | max_items_per_room = 2
25 |
26 | player = copy.deepcopy(entity_factories.player)
27 | engine = Engine(player=player)
28 |
29 | engine.game_map = generate_dungeon(
30 | max_rooms=max_rooms,
31 | room_min_size=room_min_size,
32 | room_max_size=room_max_size,
33 | map_width=map_width,
34 | map_height=map_height,
35 | max_monsters_per_room=max_monsters_per_room,
36 | max_items_per_room=max_items_per_room,
37 | engine=engine,
38 | )
39 | engine.update_fov()
40 |
41 | engine.message_log.add_message(
42 | "Hello and welcome, adventurer, to yet another dungeon!", color.welcome_text
43 | )
44 |
45 | # Pyxel初期化
46 | pyxel.init(
47 | screen_width * color.chr_x,
48 | screen_height * color.chr_y,
49 | title="Yet Another Roguelike Tutorial",
50 | fps=30
51 | )
52 | pyxel.mouse(True) # メモ: マウスを表示
53 | pyxel.run(update, draw)
54 |
55 | def draw():
56 | # メモ: 画面描画ルーチンを呼ぶ
57 | global engine
58 | pyxel.cls(0)
59 | engine.event_handler.on_render()
60 |
61 | def update():
62 | # メモ: イベントハンドラを呼ぶ
63 | global engine
64 |
65 | try:
66 | engine.event_handler.handle_events()
67 | except Exception: # Handle exceptions in game.
68 | traceback.print_exc() # Print error to stderr.
69 | # Then print the error to the message log.
70 | engine.message_log.add_message(traceback.format_exc(), color.error)
71 |
72 | if __name__ == "__main__":
73 | main()
74 |
75 | # end of main.py
76 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part9/main.py:
--------------------------------------------------------------------------------
1 | import copy
2 | import traceback
3 |
4 | import pyxel
5 |
6 | import color
7 | from engine import Engine
8 | import entity_factories
9 | from procgen import generate_dungeon
10 |
11 | def main() -> None:
12 | global engine
13 |
14 | screen_width = 80
15 | screen_height = 50
16 |
17 | map_width = 80
18 | map_height = 43
19 |
20 | room_max_size = 10
21 | room_min_size = 6
22 | max_rooms = 30
23 | max_monsters_per_room = 2
24 | max_items_per_room = 2
25 |
26 | player = copy.deepcopy(entity_factories.player)
27 | engine = Engine(player=player)
28 |
29 | engine.game_map = generate_dungeon(
30 | max_rooms=max_rooms,
31 | room_min_size=room_min_size,
32 | room_max_size=room_max_size,
33 | map_width=map_width,
34 | map_height=map_height,
35 | max_monsters_per_room=max_monsters_per_room,
36 | max_items_per_room=max_items_per_room,
37 | engine=engine,
38 | )
39 | engine.update_fov()
40 |
41 | engine.message_log.add_message(
42 | "Hello and welcome, adventurer, to yet another dungeon!", color.welcome_text
43 | )
44 |
45 | # Pyxel初期化
46 | pyxel.init(
47 | screen_width * color.chr_x,
48 | screen_height * color.chr_y,
49 | title="Yet Another Roguelike Tutorial",
50 | fps=30
51 | )
52 | pyxel.mouse(True) # メモ: マウスを表示
53 | pyxel.run(update, draw)
54 |
55 | def draw():
56 | # メモ: 画面描画ルーチンを呼ぶ
57 | global engine
58 | pyxel.cls(0)
59 | engine.event_handler.on_render()
60 |
61 | def update():
62 | # メモ: イベントハンドラを呼ぶ
63 | global engine
64 |
65 | try:
66 | engine.event_handler.handle_events()
67 | except Exception: # Handle exceptions in game.
68 | traceback.print_exc() # Print error to stderr.
69 | # Then print the error to the message log.
70 | engine.message_log.add_message(traceback.format_exc(), color.error)
71 |
72 | if __name__ == "__main__":
73 | main()
74 |
75 | # end of main.py
76 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part10/components/fighter.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | import color
6 | from components.base_component import BaseComponent
7 | from render_order import RenderOrder
8 |
9 | if TYPE_CHECKING:
10 | from entity import Actor
11 |
12 | class Fighter(BaseComponent):
13 | parent: Actor
14 |
15 | def __init__(self, hp: int, defense: int, power: int):
16 | self.max_hp = hp
17 | self._hp = hp
18 | self.defense = defense
19 | self.power = power
20 |
21 | @property
22 | def hp(self) -> int:
23 | return self._hp
24 |
25 | @hp.setter
26 | def hp(self, value: int) -> None:
27 | self._hp = max(0, min(value, self.max_hp))
28 | if self._hp == 0 and self.parent.ai:
29 | self.die()
30 |
31 | def die(self) -> None:
32 | if self.engine.player is self.parent:
33 | death_message = "You died!"
34 | death_message_color = color.player_die
35 | else:
36 | death_message = f"{self.parent.name} is dead!"
37 | death_message_color = color.enemy_die
38 |
39 | self.parent.char = "%"
40 | self.parent.color = 2
41 | self.parent.blocks_movement = False
42 | self.parent.ai = None
43 | self.parent.name = f"remains of {self.parent.name}"
44 | self.parent.render_order = RenderOrder.CORPSE
45 |
46 | self.engine.message_log.add_message(death_message, death_message_color)
47 |
48 | def heal(self, amount: int) -> int:
49 | if self.hp == self.max_hp:
50 | return 0
51 |
52 | new_hp_value = self.hp + amount
53 |
54 | if new_hp_value > self.max_hp:
55 | new_hp_value = self.max_hp
56 |
57 | amount_recovered = new_hp_value - self.hp
58 |
59 | self.hp = new_hp_value
60 |
61 | return amount_recovered
62 |
63 | def take_damage(self, amount: int) -> None:
64 | self.hp -= amount
65 |
66 | # end of fighter.py
67 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part10/engine.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import lzma
4 | import pickle
5 | from typing import TYPE_CHECKING
6 |
7 | import pyxel
8 | from tcod.map import compute_fov
9 |
10 | import exceptions
11 | from message_log import MessageLog
12 | from render_functions import render_bar, render_names_at_mouse_location
13 |
14 | if TYPE_CHECKING:
15 | from entity import Entity
16 | from game_map import GameMap
17 |
18 | class Engine:
19 | game_map: GameMap
20 |
21 | def __init__(self, player: Entity):
22 | self.message_log = MessageLog()
23 | self.mouse_location = (0, 0)
24 | self.player = player
25 |
26 | def handle_enemy_turns(self) -> None:
27 | for entity in set(self.game_map.actors) - {self.player}:
28 | if entity.ai:
29 | try:
30 | entity.ai.perform()
31 | except exceptions.Impossible:
32 | pass # Ignore impossible action exceptions from AI.
33 |
34 | def update_fov(self) -> None:
35 | """Recompute the visible area based on the players point of view."""
36 | self.game_map.visible[:] = compute_fov(
37 | self.game_map.tiles["transparent"],
38 | (self.player.x, self.player.y),
39 | radius=8,
40 | )
41 | # If a tile is "visible" it should be added to "explored".
42 | self.game_map.explored |= self.game_map.visible
43 |
44 | def render(self) -> None:
45 | self.game_map.render()
46 | self.message_log.render(x=21, y=45, width=40, height=5)
47 |
48 | render_bar(
49 | current_value=self.player.fighter.hp,
50 | maximum_value=self.player.fighter.max_hp,
51 | total_width=20,
52 | )
53 |
54 | render_names_at_mouse_location(x=21, y=44, engine=self)
55 |
56 | def save_as(self, filename: str) -> None:
57 | """Save this Engine instance as a compressed file."""
58 | save_data = lzma.compress(pickle.dumps(self))
59 | with open(filename, "wb") as f:
60 | f.write(save_data)
61 |
62 | # end of engine.py
63 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part11/components/fighter.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | import color
6 | from components.base_component import BaseComponent
7 | from render_order import RenderOrder
8 |
9 | if TYPE_CHECKING:
10 | from entity import Actor
11 |
12 | class Fighter(BaseComponent):
13 | parent: Actor
14 |
15 | def __init__(self, hp: int, defense: int, power: int):
16 | self.max_hp = hp
17 | self._hp = hp
18 | self.defense = defense
19 | self.power = power
20 |
21 | @property
22 | def hp(self) -> int:
23 | return self._hp
24 |
25 | @hp.setter
26 | def hp(self, value: int) -> None:
27 | self._hp = max(0, min(value, self.max_hp))
28 | if self._hp == 0 and self.parent.ai:
29 | self.die()
30 |
31 | def die(self) -> None:
32 | if self.engine.player is self.parent:
33 | death_message = "You died!"
34 | death_message_color = color.player_die
35 | else:
36 | death_message = f"{self.parent.name} is dead!"
37 | death_message_color = color.enemy_die
38 |
39 | self.parent.char = "%"
40 | self.parent.color = 2
41 | self.parent.blocks_movement = False
42 | self.parent.ai = None
43 | self.parent.name = f"remains of {self.parent.name}"
44 | self.parent.render_order = RenderOrder.CORPSE
45 |
46 | self.engine.message_log.add_message(death_message, death_message_color)
47 |
48 | self.engine.player.level.add_xp(self.parent.level.xp_given)
49 |
50 | def heal(self, amount: int) -> int:
51 | if self.hp == self.max_hp:
52 | return 0
53 |
54 | new_hp_value = self.hp + amount
55 |
56 | if new_hp_value > self.max_hp:
57 | new_hp_value = self.max_hp
58 |
59 | amount_recovered = new_hp_value - self.hp
60 |
61 | self.hp = new_hp_value
62 |
63 | return amount_recovered
64 |
65 | def take_damage(self, amount: int) -> None:
66 | self.hp -= amount
67 |
68 | # end of fighter.py
69 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part12/components/fighter.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | import color
6 | from components.base_component import BaseComponent
7 | from render_order import RenderOrder
8 |
9 | if TYPE_CHECKING:
10 | from entity import Actor
11 |
12 | class Fighter(BaseComponent):
13 | parent: Actor
14 |
15 | def __init__(self, hp: int, defense: int, power: int):
16 | self.max_hp = hp
17 | self._hp = hp
18 | self.defense = defense
19 | self.power = power
20 |
21 | @property
22 | def hp(self) -> int:
23 | return self._hp
24 |
25 | @hp.setter
26 | def hp(self, value: int) -> None:
27 | self._hp = max(0, min(value, self.max_hp))
28 | if self._hp == 0 and self.parent.ai:
29 | self.die()
30 |
31 | def die(self) -> None:
32 | if self.engine.player is self.parent:
33 | death_message = "You died!"
34 | death_message_color = color.player_die
35 | else:
36 | death_message = f"{self.parent.name} is dead!"
37 | death_message_color = color.enemy_die
38 |
39 | self.parent.char = "%"
40 | self.parent.color = 2
41 | self.parent.blocks_movement = False
42 | self.parent.ai = None
43 | self.parent.name = f"remains of {self.parent.name}"
44 | self.parent.render_order = RenderOrder.CORPSE
45 |
46 | self.engine.message_log.add_message(death_message, death_message_color)
47 |
48 | self.engine.player.level.add_xp(self.parent.level.xp_given)
49 |
50 | def heal(self, amount: int) -> int:
51 | if self.hp == self.max_hp:
52 | return 0
53 |
54 | new_hp_value = self.hp + amount
55 |
56 | if new_hp_value > self.max_hp:
57 | new_hp_value = self.max_hp
58 |
59 | amount_recovered = new_hp_value - self.hp
60 |
61 | self.hp = new_hp_value
62 |
63 | return amount_recovered
64 |
65 | def take_damage(self, amount: int) -> None:
66 | self.hp -= amount
67 |
68 | # end of fighter.py
69 |
--------------------------------------------------------------------------------
/research/03_00_VideoGameCollecting.md:
--------------------------------------------------------------------------------
1 | # 03_ビデオゲーム収集記
2 |
3 | ## はじめに
4 |
5 | ビデオゲームを収集する記録です.
6 |
7 | - サブテーマリスト
8 | - [01_収集リスト](03_01_CollectionList.md): 収集したビデオゲームをリスト化
9 | - [02_メガドラミニ研究](03_02_MegadriveMini.md): ビデオゲーム復刻事例として研究
10 | - [03_Final Fantasy研究](03_03_FinalFantasy.md): 代表的なJRPGとして研究
11 | - [04_PlayStation5研究](03_04_PlayStation5.md): PlayStation5を購入するまでの記録
12 | - [05_NintendoSwitch2研究](03_05_NintendoSwitchNote.md): NintendoSwitch2を購入するまでの記録
13 | - [06_パルワールド研究記](03_06_PalWorldNote.md): ビデオゲームの模倣事例として研究
14 |
15 | ### 2021-12-12
16 |
17 | ここ3年位,長年の夢だったビデオゲーム収集をしました.
18 | 他の人に比べたら,全然収集できなかったと思います.
19 | 収集という概念は広いが,僕は文化財の保護だと考えていました.
20 | 2000年以降は,国立国会図書館に納本されることを考えると,それ以前を中心に収集しようと考えていました.
21 | ただ,単に収集するのは,誰でもできるかなと思うようになりました.
22 | 僕は,プログラミングの能力を使って,過去のゲームを復刻していくのがよいのではないでしょうか.
23 |
24 | ### 2022-05-06
25 |
26 | コンプリート達成者リストを作成しました.
27 |
28 | |対象|範囲|総数|達成者|達成日|備考|
29 | |---|---|---|----|-----|---|
30 | |ファミコン|ROM/箱説有|1053|SOMARI氏(@smr_an_fami)|2021/03/11|https://twitter.com/smr_an_fami/status/1381250946735300610|
31 | |ファミコン|ROM/箱説有|1053|コーナー氏(@corner_mask)|2021/07/18|https://twitter.com/corner_mask/status/1416650529850085377|
32 | |PlayStation|-|3289|灼栗(しゃっくり)氏(@heat_maroon)|2021/10/12|https://twitter.com/heat_maroon/status/1447808515846721537|
33 | |PlayStation VITA|通常版/ベスト版|955|マルヒゲヤ氏(@maruhigeya61)|2022/05/02|https://twitter.com/maruhigeya61/status/1521809952750604290|
34 |
35 | ### 2022-05-25
36 |
37 | 先日NHKで九州国立博物館(九博)の舞台裏というTV番組を視聴しました.
38 | 美術品の修復について紹介していました.
39 | 虫食いされた古文書は,和紙で修復まではするのですが,新たに文字は書き込みません.
40 | 新たに文字を書き込むと別作品になってしまうのが理由です.
41 | また,100年後には和紙の張替が必要になるので,その作業を繰り返すそうです.
42 |
43 | レトロゲームの修復でも参考になります.今後は心がけたいです.
44 |
45 | - 説明書が折れていた場合,極力しわを伸ばして保管
46 | - 説明書が破れていた場合,セロテープで補修しない(時間を経た時にどうなるかわからない)
47 | - ケースが割れていた場合,安易に新しいケースに交換しない
48 | - 同じ作品を2個購入して,綺麗な状態の1個を作らない(「ニコイチ化」しない)
49 |
50 | ### 2024-07-07
51 |
52 | ビデオゲームの文化財としての保存においても,希少でも人気がある(高価な)タイトルは,今後も保存される可能性が高いです.
53 | そのため,私個人の活動としては,希少で人気がない(安価な)タイトルこそ,購入するように心がけています.
54 |
55 | ### 2025-05-11
56 |
57 | たまたま立ち寄ったbookoffで,ナムコミュージアムvol.5があったので,クーポンを使って購入しました.
58 | vol.1からvol.4は,新品を買ったので,vol.1からvol.5までは揃いました.
59 | 当時,vol.5も買おうと思っていたのですが,色々忙しくて,買いそびれたのです.
60 | 30年の時を越えて,一歩前進しました.
61 |
62 | 以上
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part8/components/fighter.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | import color
6 | from components.base_component import BaseComponent
7 | from input_handlers import GameOverEventHandler
8 | from render_order import RenderOrder
9 |
10 | if TYPE_CHECKING:
11 | from entity import Actor
12 |
13 | class Fighter(BaseComponent):
14 | parent: Actor
15 |
16 | def __init__(self, hp: int, defense: int, power: int):
17 | self.max_hp = hp
18 | self._hp = hp
19 | self.defense = defense
20 | self.power = power
21 |
22 | @property
23 | def hp(self) -> int:
24 | return self._hp
25 |
26 | @hp.setter
27 | def hp(self, value: int) -> None:
28 | self._hp = max(0, min(value, self.max_hp))
29 | if self._hp == 0 and self.parent.ai:
30 | self.die()
31 |
32 | def die(self) -> None:
33 | if self.engine.player is self.parent:
34 | death_message = "You died!"
35 | death_message_color = color.player_die
36 | self.engine.event_handler = GameOverEventHandler(self.engine)
37 | else:
38 | death_message = f"{self.parent.name} is dead!"
39 | death_message_color = color.enemy_die
40 |
41 | self.parent.char = "%"
42 | self.parent.color = 2
43 | self.parent.blocks_movement = False
44 | self.parent.ai = None
45 | self.parent.name = f"remains of {self.parent.name}"
46 | self.parent.render_order = RenderOrder.CORPSE
47 |
48 | self.engine.message_log.add_message(death_message, death_message_color)
49 |
50 | def heal(self, amount: int) -> int:
51 | if self.hp == self.max_hp:
52 | return 0
53 |
54 | new_hp_value = self.hp + amount
55 |
56 | if new_hp_value > self.max_hp:
57 | new_hp_value = self.max_hp
58 |
59 | amount_recovered = new_hp_value - self.hp
60 |
61 | self.hp = new_hp_value
62 |
63 | return amount_recovered
64 |
65 | def take_damage(self, amount: int) -> None:
66 | self.hp -= amount
67 |
68 | # end of fighter.py
69 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part9/components/fighter.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | import color
6 | from components.base_component import BaseComponent
7 | from input_handlers import GameOverEventHandler
8 | from render_order import RenderOrder
9 |
10 | if TYPE_CHECKING:
11 | from entity import Actor
12 |
13 | class Fighter(BaseComponent):
14 | parent: Actor
15 |
16 | def __init__(self, hp: int, defense: int, power: int):
17 | self.max_hp = hp
18 | self._hp = hp
19 | self.defense = defense
20 | self.power = power
21 |
22 | @property
23 | def hp(self) -> int:
24 | return self._hp
25 |
26 | @hp.setter
27 | def hp(self, value: int) -> None:
28 | self._hp = max(0, min(value, self.max_hp))
29 | if self._hp == 0 and self.parent.ai:
30 | self.die()
31 |
32 | def die(self) -> None:
33 | if self.engine.player is self.parent:
34 | death_message = "You died!"
35 | death_message_color = color.player_die
36 | self.engine.event_handler = GameOverEventHandler(self.engine)
37 | else:
38 | death_message = f"{self.parent.name} is dead!"
39 | death_message_color = color.enemy_die
40 |
41 | self.parent.char = "%"
42 | self.parent.color = 2
43 | self.parent.blocks_movement = False
44 | self.parent.ai = None
45 | self.parent.name = f"remains of {self.parent.name}"
46 | self.parent.render_order = RenderOrder.CORPSE
47 |
48 | self.engine.message_log.add_message(death_message, death_message_color)
49 |
50 | def heal(self, amount: int) -> int:
51 | if self.hp == self.max_hp:
52 | return 0
53 |
54 | new_hp_value = self.hp + amount
55 |
56 | if new_hp_value > self.max_hp:
57 | new_hp_value = self.max_hp
58 |
59 | amount_recovered = new_hp_value - self.hp
60 |
61 | self.hp = new_hp_value
62 |
63 | return amount_recovered
64 |
65 | def take_damage(self, amount: int) -> None:
66 | self.hp -= amount
67 |
68 | # end of fighter.py
69 |
--------------------------------------------------------------------------------
/pyxel/galaxian/galaxian.py:
--------------------------------------------------------------------------------
1 | # ランダムな大きさの3種類の敵が回転しながら落ちてくるプログラム
2 |
3 | import pyxel
4 |
5 | # 敵を表現するクラス
6 | class Enemy:
7 | def __init__(self, x, y, size, type, rotate_speed, fall_speed, scale):
8 | self.x = x
9 | self.y = y
10 | self.size = size
11 | self.type = type
12 | self.rotate_speed = rotate_speed
13 | self.fall_speed = fall_speed
14 | self.scale = scale
15 | self.rotate = 0
16 |
17 | # 敵を動かす
18 | def update(self):
19 | self.rotate += self.rotate_speed
20 | self.y += self.fall_speed
21 | if self.y > 256: # 画面外に出たら上に戻る
22 | self.x = pyxel.rndi(-self.size//8, 256//8) * 8
23 | #self.y = pyxel.rndi(-256//8, 0) * 8
24 | self.y = -self.size
25 |
26 | # 敵を描画
27 | def draw(self):
28 | pyxel.blt(
29 | self.x, self.y,
30 | # 対応するイメージバンクの番号、x座標、y座標、横サイズ、縦サイズ、透明色
31 | 0, self.type * (self.size+4), 0, self.size, self.size, 0,
32 | # 回転角度(ラジアンでなく度:Degree)、拡大率(1より小さいときは縮小)
33 | self.rotate, self.scale)
34 |
35 | class App:
36 | def __init__(self):
37 | pyxel.init(256, 256, title="Galaxian", capture_scale=1)
38 | self.enemy_size = 12
39 |
40 | # イメージバンク0の座標 (0, 0)に画像ファイルを読み込む
41 | pyxel.load("galaxian.pyxres")
42 |
43 | # 複数の敵を初期化
44 | self.enemyflakes = [
45 | Enemy(
46 | x = pyxel.rndi(-self.enemy_size//4, 256//4) * 4,
47 | y = pyxel.rndi(-256//8, 0) * 8,
48 | size = self.enemy_size,
49 | type = pyxel.rndi(0, 2), # 3種類ある敵のどれか
50 | fall_speed = pyxel.rndf(0.6, 1.0),
51 | rotate_speed = pyxel.rndf(-3, 3),
52 | scale = pyxel.rndf(1.5, 2.4) # 画像の表示倍率
53 | )
54 | for _ in range(24)
55 | ]
56 |
57 | pyxel.run(self.update, self.draw)
58 |
59 | def update(self):
60 | # 全ての敵を更新
61 | for flake in self.enemyflakes:
62 | flake.update()
63 |
64 | def draw(self):
65 | pyxel.cls(1)
66 | # 全ての敵を描画
67 | for flake in self.enemyflakes:
68 | flake.draw()
69 |
70 | App()
71 |
--------------------------------------------------------------------------------
/pyxel/autorace/autorace.py:
--------------------------------------------------------------------------------
1 | #
2 | # 「オートレース(1画面ソフト) 」
3 | # 高橋はるみ氏作の「オートレース(1画面ソフト) 」を参考にしました.
4 | # cf. 高橋はるみ:「FM-7 FM-8 はるみのゲーム・ライブラリー」, 株式会社ナツメ社, 1983年.
5 | #
6 | # Jun 14, 2024 ver.1 (Pyxelによる実装)
7 | #
8 | # -*- coding: utf-8 -*-
9 | import pyxel
10 | import random
11 | import basic
12 |
13 | width = 40
14 | height = 20
15 | chr_x = 4
16 | chr_y = 5
17 |
18 | def init():
19 | global st,s, x, i
20 |
21 | # 0:遊戯中 1:終了
22 | st = 0
23 |
24 | # 画面初期化(10行目),画面クリア(12行目)
25 | s = basic.screen(width, height)
26 | # 車位置初期化(12行目)
27 | x = 2
28 | # カウンタ初期化,Beep音初期化(14行目)
29 | i = 0
30 |
31 | # メインループ
32 | def update():
33 | global st, s, x, i
34 |
35 | # 遊戯中
36 | if st == 0:
37 | # 車消去,Beep音(16行目)
38 | s.print(x,4," ",7)
39 | pyxel.play(0,0)
40 | # キー入力チェック,左移動(17行目)
41 | if pyxel.btnp(pyxel.KEY_LEFT) and x > 1: x -= 1
42 | # キー入力チェック,左移動(18行目)
43 | if pyxel.btnp(pyxel.KEY_RIGHT) and x < 4: x += 1
44 | # 車衝突チェック(19行目)
45 | if s.peek(x,5,True) > ord(' '):
46 | # 終了
47 | st = 1
48 | return
49 | # 道路表示(20行目)
50 | s.print(0,19,"| |",1)
51 | # 最下段に文字が表示されると自動的に縦スクロール(BASIC仕様)
52 | s.scroll()
53 | # 車表示(21行目)
54 | s.print(x,4,"U",2)
55 | # 障害物表示(22行目)
56 | s.print(random.randint(1,4),18,"+",3)
57 | # ゴール表示(23行目)
58 | if i == 186:
59 | s.print(0,18,"-GOAL-",4)
60 | # カウントアップ(24行目)
61 | i += 1
62 |
63 | # 終了
64 | elif st == 1:
65 | # ゲームオーバ,スコア表示(30行目)
66 | s.print(9,9,"**** GAME OVER ****",8)
67 | s.print(13,11,f"[:SCORE {i}]",9)
68 |
69 | # キー入力チェック,再ゲーム(31行目)
70 | if pyxel.btnp(pyxel.KEY_S):
71 | # 再ゲーム
72 | init()
73 |
74 | # 画面描画
75 | def draw():
76 | global st, s, x, i
77 |
78 | pyxel.cls(0)
79 | for w in range(s.width):
80 | for h in range(s.height):
81 | pyxel.text(w*4,h*5,chr(s.peek(w,h,True)), s.peek(w,h,False))
82 |
83 | # 初期化
84 | init()
85 | pyxel.init( width*chr_x, height*chr_y, title="autorace", fps=5 )
86 | pyxel.sounds[0].set("a2","p","6","n",2)
87 | pyxel.run(update, draw)
88 |
89 | # end of autorace.py
90 |
--------------------------------------------------------------------------------
/pyxel/pyxelrogue/part5/game_map.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import Iterable, Optional, TYPE_CHECKING
4 |
5 | import numpy as np # type: ignore
6 | from tcod.console import Console
7 | import pyxel
8 |
9 | import tile_types
10 |
11 | if TYPE_CHECKING:
12 | from entity import Entity
13 |
14 | class GameMap:
15 | def __init__(self, width: int, height: int, entities: Iterable[Entity] = ()):
16 | self.width, self.height = width, height
17 | self.entities = set(entities)
18 | self.tiles = np.full((width, height), fill_value=tile_types.wall, order="F")
19 |
20 | self.visible = np.full((width, height), fill_value=False, order="F") # Tiles the player can currently see
21 | self.explored = np.full((width, height), fill_value=False, order="F") # Tiles the player has seen before
22 |
23 | def get_blocking_entity_at_location(self, location_x: int, location_y: int) -> Optional[Entity]:
24 | for entity in self.entities:
25 | if entity.blocks_movement and entity.x == location_x and entity.y == location_y:
26 | return entity
27 |
28 | return None
29 |
30 | def in_bounds(self, x: int, y: int) -> bool:
31 | """Return True if x and y are inside of the bounds of this map."""
32 | return 0 <= x < self.width and 0 <= y < self.height
33 |
34 | def render(self) -> None:
35 | """
36 | Renders the map.
37 |
38 | If a tile is in the "visible" array, then draw it with the "light" colors.
39 | If it isn't, but it's in the "explored" array, then draw it with the "dark" colors.
40 | Otherwise, the default is "SHROUD".
41 | """
42 |
43 | # メモ: pyxel対応のため、愚直に表示(現時点では点描)
44 | for x in range(self.width):
45 | for y in range(self.height):
46 | if self.visible[x][y]:
47 | pyxel.pset(x,y,self.tiles["light"][x,y]["fg"])
48 | elif self.explored[x][y]:
49 | pyxel.pset(x,y,self.tiles["dark"][x,y]["fg"])
50 | else:
51 | pyxel.pset(x,y,tile_types.SHROUD["fg"])
52 |
53 | for entity in self.entities:
54 | # Only print entities that are in the FOV
55 | if self.visible[entity.x, entity.y]:
56 | pyxel.pset(entity.x, entity.y, entity.color)
57 |
58 | # end of game_map.py
59 |
--------------------------------------------------------------------------------
/research/01_02_PinballNote.md:
--------------------------------------------------------------------------------
1 | # 01_ゲーム製作: 02_ピンボール開発記
2 |
3 | つぶやきながら,ピンボールを開発する日記です.
4 |
5 | ## ピンボール開発記
6 |
7 | ### 2022-08-07
8 |
9 | 最近,ピンボールを作りたくなっているけど,いまさらなので,やめようかなと考えています.
10 | ただ,「車輪の再発見」という言葉あるけど,「再発見」しないと本当には理解できないと思います.
11 | モノ作りってそういうものです.これは,ビジネススクールでは教えてくれないことです.
12 |
13 | ### 2023-04-28
14 |
15 | 年初から,ピンボールを作りたいと思い,数日前から作りはじめました.
16 | PICO-8実装を写経するという手法です.
17 | Isidor氏の [Pinball Pong](https://www.lexaloffle.com/bbs/?tid=28488) を写経しました.
18 | ピンボールというか,ピンボールとブロック崩しが融合したゲームです.
19 | オリジナルはランダム要素が強かったので,シミュレーション要素を強めに変更しています.
20 |
21 | 
22 |
23 | ### 2023-04-30
24 |
25 | 画面上部の障害物,画面左右のバー(5点),ゲームオーバー処理を追加しました.
26 | キャラクタも立体感が出るように描き直しました.
27 | [コード](https://github.com/jay-kumogata/RetroGames/blob/main/pyxel/pinball) は,多少リファクタリングしました.
28 | 小学生の時に,PC-8001mkIIで作ったブロック崩しを思い出します.
29 | あれから40年位経過したけど,やっていることに進歩がないですね.
30 |
31 | 
32 |
33 | ### 2023-07-16
34 |
35 | 昔は,ピンボールとブロック崩しが合体したゲームが結構あったらしいです.
36 | ナムコのボムビーとか,キューティーキューとかです.
37 | 結構作ってみると,フリッパーの処理が難しくて,パドルだと簡単に作れることがわかります.
38 |
39 | ### 2023-07-17
40 |
41 | Isidor氏の [Pinball Pong](https://www.lexaloffle.com/bbs/?tid=28488)をPyxel に移植してみました.
42 | ピンボールとポンを組み合わせたようなゲームです.
43 | 春頃に作って公開するのを忘れていました.
44 | 任天堂ピンボールのツイートを見て,思い出しました.
45 | #Pyxel #Pinball
46 |
47 | ### 2023-07-18
48 |
49 | Pyxelで動作するPinball Pong🕹️の [ソースリスト](https://github.com/jay-kumogata/RetroGames/tree/main/pyxel/pinball) 📁を公開しました.
50 | #Pyxel #Pinball
51 |
52 | ### 2023-10-23
53 |
54 | 週末に,春頃に作ってたPinball Pongを少し直しました.
55 | Pongということで,パドルでボールを跳ね返すゲームだったのを,Pinballらしく,フリッパーを付けました.
56 | しかも,デザインの都合で,ダブルフリッパーです.
57 | 各アイテムの位置決めが結構大変で,いい感じにするのに時間がかかりました.
58 |
59 | 
60 |
61 | ### 2023-11-09
62 |
63 | Pyxelで動作するPinball🕹️の [ソースリスト](https://github.com/jay-kumogata/RetroGames/tree/main/pyxel/pinball) 📁を公開しました.
64 | #Pyxel #Pinball
65 |
66 | ### 2023-11-17
67 |
68 | Pinballの続きです.フリッパーを追加したのはよかったのですが,ボールの動きが不自然なままでした.
69 | そこで,重力加速度を大きめにして,フリッパーの速度に応じて,ボールが上がるように修正しました.
70 | 物理シミュレーションっぽい感じにはなりましたが,ビデオゲームとして面白いかは不明です.
71 |
72 | 
73 |
74 | ### 2023-11-18
75 |
76 | 小学生の頃に,コリントゲームをヒントに木製のピンボールを作ったことがあります.
77 | その時は,全然完成しませんでした.
78 | 約45年の時を超えて,ようやくピンボールが完成しました.
79 |
80 | 以上
81 |
--------------------------------------------------------------------------------