gh-space-shooter 0.0.2__py3-none-any.whl → 0.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,5 +7,13 @@ SHIP_POSITION_Y = NUM_DAYS + 3 # Ship is positioned just below the grid
7
7
 
8
8
  SHIP_SPEED = 0.25 # Cells per frame the ship moves
9
9
  BULLET_SPEED = 0.15 # Cells per frame the bullet moves
10
+ BULLET_TRAILING_LENGTH = 3 # Number of trailing segments for bullets
10
11
  FRAME_DURATION_MS = 20 # Duration of each frame in milliseconds
11
- SHIP_SHOOT_COOLDOWN_FRAMES = 10 # Frames between ship shots
12
+ SHIP_SHOOT_COOLDOWN_FRAMES = 10 # Frames between ship shots
13
+
14
+ EXPLOSION_PARTICLE_COUNT_LARGE = 8 # Number of particles in a large explosion
15
+ EXPLOSION_PARTICLE_COUNT_SMALL = 4 # Number of particles in a small explosion
16
+ EXPLOSION_MAX_RADIUS_LARGE = 20 # Max radius for large explosions
17
+ EXPLOSION_MAX_RADIUS_SMALL = 10 # Max radius for small explosions
18
+ EXPLOSION_MAX_FRAMES_LARGE = 20 # Frames for large explosion animation
19
+ EXPLOSION_MAX_FRAMES_SMALL = 6 # Frames for small explosion animation
@@ -4,7 +4,7 @@ from typing import TYPE_CHECKING
4
4
 
5
5
  from PIL import ImageDraw
6
6
 
7
- from ...constants import BULLET_SPEED, SHIP_POSITION_Y
7
+ from ...constants import BULLET_SPEED, BULLET_TRAILING_LENGTH, SHIP_POSITION_Y
8
8
  from .drawable import Drawable
9
9
  from .explosion import Explosion
10
10
 
@@ -52,10 +52,9 @@ class Bullet(Drawable):
52
52
  def draw(self, draw: ImageDraw.ImageDraw, context: "RenderContext") -> None:
53
53
  """Draw the bullet with trailing tail effect."""
54
54
 
55
- trail_num = 3
56
- for i in range(trail_num):
55
+ for i in range(BULLET_TRAILING_LENGTH):
57
56
  trail_y = self.y + (i + 1) * BULLET_SPEED
58
- fade_factor = (i + 1) / trail_num / 2
57
+ fade_factor = (i + 1) / BULLET_TRAILING_LENGTH / 2
59
58
  self._draw_bullet(draw, context, (self.x, trail_y), fade_factor=fade_factor)
60
59
 
61
60
  self._draw_bullet(draw, context, (self.x, self.y), fade_factor=0.3, offset=.6)
@@ -6,6 +6,14 @@ from typing import TYPE_CHECKING, Literal
6
6
 
7
7
  from PIL import ImageDraw
8
8
 
9
+ from ...constants import (
10
+ EXPLOSION_MAX_FRAMES_LARGE,
11
+ EXPLOSION_MAX_FRAMES_SMALL,
12
+ EXPLOSION_MAX_RADIUS_LARGE,
13
+ EXPLOSION_MAX_RADIUS_SMALL,
14
+ EXPLOSION_PARTICLE_COUNT_LARGE,
15
+ EXPLOSION_PARTICLE_COUNT_SMALL,
16
+ )
9
17
  from .drawable import Drawable
10
18
 
11
19
  if TYPE_CHECKING:
@@ -30,10 +38,9 @@ class Explosion(Drawable):
30
38
  self.y = y
31
39
  self.game_state = game_state
32
40
  self.frame = 0
33
- self.max_frames = 6 if size == "small" else 20
34
- self.max_radius = 10 if size == "small" else 20
35
- self.particle_count = 4 if size == "small" else 8
36
- # Generate random angles for each particle
41
+ self.max_frames = EXPLOSION_MAX_FRAMES_SMALL if size == "small" else EXPLOSION_MAX_FRAMES_LARGE
42
+ self.max_radius = EXPLOSION_MAX_RADIUS_SMALL if size == "small" else EXPLOSION_MAX_RADIUS_LARGE
43
+ self.particle_count = EXPLOSION_PARTICLE_COUNT_SMALL if size == "small" else EXPLOSION_PARTICLE_COUNT_LARGE
37
44
  self.particle_angles = [random.uniform(0, 2 * math.pi) for _ in range(self.particle_count)]
38
45
 
39
46
  def animate(self) -> None:
@@ -44,21 +51,18 @@ class Explosion(Drawable):
44
51
 
45
52
  def draw(self, draw: ImageDraw.ImageDraw, context: "RenderContext") -> None:
46
53
  """Draw expanding particle explosion with fade effect."""
47
- # Calculate animation progress (0 to 1)
54
+
48
55
  progress = self.frame / self.max_frames
49
56
  fade = 1 - progress # Fade out as animation progresses
50
57
 
51
- # Get center position
52
58
  center_x, center_y = context.get_cell_position(self.x, self.y)
53
59
  center_x += context.cell_size // 2
54
60
  center_y += context.cell_size // 2
55
61
 
56
- # Draw expanding particles in random directions
57
62
  for i in range(self.particle_count):
58
63
  distance = progress * self.max_radius
59
64
  angle = self.particle_angles[i]
60
65
 
61
- # Particle position using random angle
62
66
  px = int(center_x + distance * math.cos(angle))
63
67
  py = int(center_y + distance * math.sin(angle))
64
68
 
@@ -32,7 +32,6 @@ class ContributionData(TypedDict):
32
32
  username: str
33
33
  total_contributions: int
34
34
  weeks: list[ContributionWeek]
35
- fetched_at: str
36
35
 
37
36
 
38
37
  class GitHubAPIError(Exception):
@@ -157,7 +156,6 @@ class GitHubClient:
157
156
  "username": username,
158
157
  "total_contributions": calendar["totalContributions"],
159
158
  "weeks": weeks,
160
- "fetched_at": datetime.now().isoformat(),
161
159
  }
162
160
 
163
161
  LEVEL_MAP = {
@@ -1,15 +1,17 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gh-space-shooter
3
- Version: 0.0.2
3
+ Version: 0.0.3
4
4
  Summary: A CLI tool that visualizes GitHub contribution graphs as gamified GIFs
5
5
  Author-email: zane <czl970721@gmail.com>
6
6
  License-File: LICENSE
7
7
  Requires-Python: >=3.13
8
8
  Requires-Dist: httpx>=0.27.0
9
- Requires-Dist: pillow>=10.0.0
9
+ Requires-Dist: pillow>=10.1.0
10
10
  Requires-Dist: python-dotenv>=1.0.0
11
11
  Requires-Dist: rich>=13.0.0
12
12
  Requires-Dist: typer>=0.12.0
13
+ Provides-Extra: dev
14
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
13
15
  Description-Content-Type: text/markdown
14
16
 
15
17
  # gh-space-shooter 🚀
@@ -18,19 +20,49 @@ Transform your GitHub contribution graph into an epic space shooter game!
18
20
 
19
21
  ![Example Game](example.gif)
20
22
 
21
- ## Features
23
+ ## Usage
24
+
25
+ ### GitHub Action
26
+
27
+ Automatically update your game GIF daily using GitHub Actions! Add this workflow to your repository at `.github/workflows/update-game.yml`:
28
+
29
+ ```yaml
30
+ name: Update Space Shooter Game
31
+
32
+ on:
33
+ schedule:
34
+ - cron: '0 0 * * *' # Daily at midnight UTC
35
+ workflow_dispatch: # Allow manual trigger
22
36
 
23
- - 🚀 **Galaga-style space shooter** - Classic arcade gameplay with your contribution data
24
- - 📊 **GitHub integration** - Fetches your last 52 weeks of contributions automatically
25
- - 🎮 **Smart enemy AI** - Multiple attack strategies (columns, rows, random patterns)
26
- - 💥 **Particle effects** - Explosions with randomized particles and smooth animations
27
- - 🎨 **Polished graphics** - Rounded enemies, smooth ship design, starfield background
28
- - 📈 **Contribution stats** - View your coding activity statistics
29
- - 💾 **Export options** - Save both the GIF and raw JSON data
37
+ permissions:
38
+ contents: write
39
+
40
+ jobs:
41
+ update-game:
42
+ runs-on: ubuntu-latest
43
+ steps:
44
+ - uses: actions/checkout@v4
45
+
46
+ - uses: czl9707/gh-space-shooter@v1
47
+ with:
48
+ github-token: ${{ secrets.GITHUB_TOKEN }}
49
+ output-path: 'game.gif'
50
+ strategy: 'random'
51
+ ```
52
+
53
+ Then display it in your README:
54
+ ```markdown
55
+ ![My GitHub Game](game.gif)
56
+ ```
30
57
 
31
- ## Installation
58
+ **Action Inputs:**
59
+ - `github-token` (required): GitHub token for fetching contributions
60
+ - `username` (optional): Username to generate game for (defaults to repo owner)
61
+ - `output-path` (optional): Where to save the GIF (default: `gh-space-shooter.gif`)
62
+ - `strategy` (optional): Attack pattern - `column`, `row`, or `random` (default: `random`)
63
+ - `commit-message` (optional): Commit message for the update
32
64
 
33
- ### From PyPI (Recommended)
65
+ ### From PyPI
34
66
 
35
67
  ```bash
36
68
  pip install gh-space-shooter
@@ -131,8 +163,7 @@ When saved to JSON, the data includes:
131
163
  }
132
164
  ]
133
165
  }
134
- ],
135
- "fetched_at": "2024-12-30T12:00:00"
166
+ ]
136
167
  }
137
168
  ```
138
169
 
@@ -1,8 +1,8 @@
1
1
  gh_space_shooter/__init__.py,sha256=jBFfHY3YC8-3m-eVPIo3CWoQLsy5Yvd0vcbHVbUDTWY,337
2
2
  gh_space_shooter/cli.py,sha256=AHONWh6Kv9Y8D7OWsnOH6kOjN73aSCXF8Ats9jKJwkY,5310
3
3
  gh_space_shooter/console_printer.py,sha256=opT5vITkPJ_9BCPNMDays6EtXez9m86YXY9pK5_Hdh8,2345
4
- gh_space_shooter/constants.py,sha256=HR_FYewYnjQ8V5fJwMS2UhiYSS3l0iR5Y8bmaS3thQE,498
5
- gh_space_shooter/github_client.py,sha256=Ugt4wi8RAvnYPO8fF7-MgugD5t91nxQUcEnCf-Hmc-8,4771
4
+ gh_space_shooter/constants.py,sha256=zMJn4wtCJf11X0pEJeK2q9zfawifB8O-PH1NEOpB0k0,1004
5
+ gh_space_shooter/github_client.py,sha256=PkXGWjR7TpzJvCPg37RM4kPq1phg_MlyBpHNtofaNXQ,4697
6
6
  gh_space_shooter/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  gh_space_shooter/game/__init__.py,sha256=bIc-S0hOiYqYBtdmd9_CedqYY07Il6XiV__TqcbtJNA,707
8
8
  gh_space_shooter/game/animator.py,sha256=5nCY0xfRl6tifwixUlUlVXCQfDjhsR6HbQBKHHmYHH8,2998
@@ -10,10 +10,10 @@ gh_space_shooter/game/game_state.py,sha256=pvKc-FAapVXuFNb2hCGoOhJI1P8kWXkyCf_lr
10
10
  gh_space_shooter/game/render_context.py,sha256=TPJw9RmRB0_786W-O7nfB61UoDzDT_SlEVdaSlW750c,1805
11
11
  gh_space_shooter/game/renderer.py,sha256=J13eUOWHkImtiNWGyvRqORM7ngg1Q7LBUgs4cWFl26g,1617
12
12
  gh_space_shooter/game/drawables/__init__.py,sha256=lzo3O5cxahrYTyOQVrz7rQ3Prkaj8Z_dpzlt0UdurOo,306
13
- gh_space_shooter/game/drawables/bullet.py,sha256=8DjqXI1Ab4IINi77szJuRc5Bqilb0gvofKgcQ9s0ONM,2920
13
+ gh_space_shooter/game/drawables/bullet.py,sha256=tNhdvMw8HPbxyZuE-xTJpo0UGJvb9H8Hj5rA_nZjSUk,2948
14
14
  gh_space_shooter/game/drawables/drawable.py,sha256=xIJWI5m-kZCbvCfgYF4jiqTvPFelViJ1gLilz7adJoM,738
15
15
  gh_space_shooter/game/drawables/enemy.py,sha256=RCIE4Vn2tis0iJmJO_JUIxnomSgDSsfFhrcPPWmFLhE,1921
16
- gh_space_shooter/game/drawables/explosion.py,sha256=Ek2CCjjifkLVSpaJ4Nv8ey1VhkXNK6HeKK3wB0fRI5g,2618
16
+ gh_space_shooter/game/drawables/explosion.py,sha256=XJM7NUnK-lkD-AOw8AusUD2erfojyW3rKAi-vqY8eEw,2767
17
17
  gh_space_shooter/game/drawables/ship.py,sha256=j389lXOUWvPoFZUNvVN-OEjhTtIlEkAVeEYqF7gDBIE,3216
18
18
  gh_space_shooter/game/drawables/starfield.py,sha256=ON_cQ6Qfg30ocLHQEp1dceqputHmxJ7sf61o4uNF4Ng,2530
19
19
  gh_space_shooter/game/strategies/__init__.py,sha256=a34i4FlNv-aQ-oEkT1ha7oJDBt7Cd7EFpbMWsYNHpW0,338
@@ -21,8 +21,8 @@ gh_space_shooter/game/strategies/base_strategy.py,sha256=IwPdthCWkgsFdUsMjQgifpS
21
21
  gh_space_shooter/game/strategies/column_strategy.py,sha256=AQHXVTRe5BEjc4QHRL9QLtkkelTzGUGf2531POGtkG0,1728
22
22
  gh_space_shooter/game/strategies/random_strategy.py,sha256=l0GKMkGJa_QEvNrN57R_KgWDBafGebP926fZJqpdghc,2215
23
23
  gh_space_shooter/game/strategies/row_strategy.py,sha256=8izcioSGrVYGdQ__GrdfAQxnJt1BLhwNdumeuQiDhpg,1426
24
- gh_space_shooter-0.0.2.dist-info/METADATA,sha256=Kd8sR8mbxG7X88E0abNI8ohBtZrN-NtjzDyNqFFFqTQ,3493
25
- gh_space_shooter-0.0.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
26
- gh_space_shooter-0.0.2.dist-info/entry_points.txt,sha256=SmK2ET5vz62eaMC4mhxmLJ1f_H9qSTXOvFOHNo-qwCk,62
27
- gh_space_shooter-0.0.2.dist-info/licenses/LICENSE,sha256=teCrgzzcmjYCQ-RqXkDmICcHMN1AfaabrjZsW6O3KEk,1075
28
- gh_space_shooter-0.0.2.dist-info/RECORD,,
24
+ gh_space_shooter-0.0.3.dist-info/METADATA,sha256=oSw8RS0yzv1ZX9oLO3vs_MWgpD38yn8fdeSxG3FxADQ,3999
25
+ gh_space_shooter-0.0.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
26
+ gh_space_shooter-0.0.3.dist-info/entry_points.txt,sha256=SmK2ET5vz62eaMC4mhxmLJ1f_H9qSTXOvFOHNo-qwCk,62
27
+ gh_space_shooter-0.0.3.dist-info/licenses/LICENSE,sha256=teCrgzzcmjYCQ-RqXkDmICcHMN1AfaabrjZsW6O3KEk,1075
28
+ gh_space_shooter-0.0.3.dist-info/RECORD,,