Skip to content

Commit

Permalink
Added spritesheets, fixed animation system and added spritesheet supp…
Browse files Browse the repository at this point in the history
…ort to animation system
  • Loading branch information
dimkauzh committed Jan 26, 2024
1 parent 7cb854a commit d33b30d
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 25 deletions.
28 changes: 25 additions & 3 deletions docs/changelog/v5.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
# Version 5 Todo/Changelog

## V5
- [ ] Docs cleanup
- [ ] New color system
- [ ] Optimised font drawing
- [x] Docs cleanup
- [x] New color system
- [x] Optimised font drawing
- [x] OpenGL rendering

## V5
- [ ] New Window features
- [ ] Full Screen
- [ ] is_fullscreen
- [ ] toggle_fullscreen
- [ ] Screen Safer
- [ ] get_screensafer_allowed
- [ ] set_screensafer_allowed
- [ ] get_vsync_enabled
- [ ] get_screen_refresh_rate
- [ ] get_display_amount
- [ ] get_active

- [ ] SpriteSheet class
- [ ] __init__(Image, width, height)
- [ ] frames (variable with all your extracted frames)
- [ ] draw(speed) (gets a argument speed that specifies the speed of drawing in frames)

- Image system updates
- [ ] Added crop() function
10 changes: 5 additions & 5 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ nav:


- Changelog:
- v5: 'changelog/v5.md'
- v4: 'changelog/v4.md'
- v3: 'changelog/v3.md'
- V5: 'changelog/v5.md'
- V4: 'changelog/v4.md'
- V3: 'changelog/v3.md'

- Legacy:
- Start: 'legacy/index.md'
- v3:
- V3:
- Wiki:
- Main page: 'legacy/v3/wiki/wiki.md'
- Keys page: 'legacy/v3/wiki/keys.md'
Expand All @@ -59,7 +59,7 @@ nav:
- Setup: 'legacy/v3/tutorials/setup.md'
- Basics: 'legacy/v3/tutorials/basics.md'

- v4:
- V4:
- Wiki:
- Window with fusion: 'legacy/v4/wiki/window.md'
- Rendering with fusion: 'legacy/v4/wiki/rendering.md'
Expand Down
1 change: 1 addition & 0 deletions src/fusionengine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

# Animation
from fusionengine.engine.animation import *
from fusionengine.engine.spritesheets import *


import pygame as pg
Expand Down
31 changes: 18 additions & 13 deletions src/fusionengine/engine/animation.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
from fusionengine.engine.window import Window
from fusionengine.engine.spritesheets import SpriteSheet


class Animation:
def __init__(self, window: Window, images: tuple, speed: int) -> None:
def __init__(self, window: Window, images: tuple | SpriteSheet) -> None:
"""
The class to create a Animation.
Args:
window: Window
image: tuple of Images
image (Tuple | Spritesheets): Tuple of Images or a SpriteSheet
Speed: Int (FPS)
"""
self.frame = 0
self.anim = images
if isinstance(images, SpriteSheet):
self.frames = images.frames
elif isinstance(images, tuple):
self.frames = images
else:
ValueError("Images must be a tuple of Images or a SpriteSheet")

self.speed = speed
self.window = window

def draw(self) -> None:
def play(self, speed: float) -> None:
"""
Draw the animation you made before
"""
self.window.set_fps(self.speed)
if isinstance(self.frame, int) or (
isinstance(self.frame, float) and self.frame.is_integer()
):
if 0 <= int(self.frame) < len(self.frames):
self.frames[int(self.frame)].draw()

if self.frame >= len(self.anim):
self.frame = 0

image = self.anim[self.frame]
self.frame += speed

image.draw()

self.frame += 1
if self.frame >= len(self.frames):
self.frame = 0
35 changes: 31 additions & 4 deletions src/fusionengine/engine/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@
class Image:
def __init__(
self,
image_path: str,
image_path: str | Imager.Image,
x: int,
y: int,
width: int,
height: int,
) -> None:
"""
Opens an image. Can be later rendered with draw_image.
Opens an image. Can be later rendered with draw method.
Args:
image_path (str): The path to the image
image_path (str or Pillow Image): The path to the image | Pillow Image
x (int): X coordinate of the image
y (int): Y coordinate of the image
width (int): Width of the image (scaling allowed)
Expand All @@ -31,7 +31,13 @@ def __init__(
self.width = width
self.height = height

self.image = Imager.open(image_path)
if isinstance(image_path, str):
self.image = Imager.open(str(image_path))
elif isinstance(image_path, Imager.Image):
self.image = image_path
else:
raise ValueError("Invalid image_path type")

image_data = self.image.tobytes("raw", "RGBA", 0, -1)

self.texture = gl.GenTextures(1)
Expand All @@ -53,6 +59,27 @@ def __init__(
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)

def crop(self, left: int, right: int, top: int, bottom: int) -> "Image":
"""
Crop the image based on the specified boundaries.
Args:
left (int): The left boundary of the crop area.
right (int): The right boundary of the crop area.
top (int): The top boundary of the crop area.
bottom (int): The bottom boundary of the crop area.
Returns:
Image: A new Image object representing the cropped image.
"""
return Image(
self.image.crop((left, right, top, bottom)),
self.x,
self.y,
self.width,
self.height,
)

def draw(self) -> None:
"""
Draws your image on the screen.
Expand Down
81 changes: 81 additions & 0 deletions src/fusionengine/engine/spritesheets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from fusionengine.engine.image import Image
from PIL import Image as Imager


class SpriteSheet:
def __init__(self, image_path: str, sprite_width: int, sprite_height: int):
"""
Represents a SpriteSheet containing a grid of frames.
Args:
image_path (str): The path to the sprite sheet image file.
sprite_width (int): Width of each sprite frame.
sprite_height (int): Height of each sprite frame.
"""
self.sprite_sheet = Imager.open(image_path).convert("RGBA")
self.sprite_width = sprite_width
self.sprite_height = sprite_height
self.frames = self.get_frames()
self.width = 0
self.height = 0

def get_frames(self) -> list:
"""
Extract frames from the sprite sheet.
Returns:
list: List of Image objects representing individual frames.
"""
frames = []
columns = self.sprite_sheet.width // self.sprite_width
rows = self.sprite_sheet.height // self.sprite_height

for row in range(rows):
for col in range(columns):
frame = Image(self.extract_frame(col, row), 0, 0, 0, 0)
frames.append(frame)

return frames

def extract_frame(self, col: int, row: int) -> Imager.Image:
"""
Extract a single frame from the sprite sheet.
Args:
col (int): Column index of the sprite.
row (int): Row index of the sprite.
Returns:
Imager.Image: Image object representing the extracted frame.
"""
x = col * self.sprite_width
y = row * self.sprite_height

frame = self.sprite_sheet.crop(
(x, y, x + self.sprite_width, y + self.sprite_height)
)
return frame

def frame_size(self, width: int, height: int) -> None:
"""
Set the size of each frame in the sprite sheet.
Args:
width (int): Width to set for each frame.
height (int): Height to set for each frame.
"""
for frame in self.frames:
frame.width = width
frame.height = height

def frame_pos(self, x: int, y: int) -> None:
"""
Set the position of each frame in the sprite sheet.
Args:
x (int): X position to set for each frame.
y (int): Y position to set for each frame.
"""
for frame in self.frames:
frame.x = x
frame.y = y
17 changes: 17 additions & 0 deletions tests/spritesheet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import fusionengine as fusion

window = fusion.Window("Spritesheet test", 500, 500)
window.set_fps(30)
main_image = fusion.Image(fusion.DEBUGIMAGE, 200, 200, 50, 50)

spr = fusion.SpriteSheet(fusion.DEBUGIMAGE, 100, 100)
spr.frame_size(60, 60)
spr.frame_pos(50, 50)

anim = fusion.Animation(window, spr)


@window.loop
def loop():
anim.play(0.5)
main_image.draw()

0 comments on commit d33b30d

Please sign in to comment.