Pages

Se afișează postările cu eticheta python packages. Afișați toate postările
Se afișează postările cu eticheta python packages. Afișați toate postările

luni, 10 august 2026

PyGame : Fixing Android Screen Rotation Crashes in Pygame and Pydroid 3.

When developing mobile 2D games using Python, Pygame, and Pydroid 3 on Android, rotating the device frequently causes application crashes or frozen rendering loops. This core instability stems from how the Android operating system handles application lifecycles and SDL video contexts. When an orientation shift occurs, the system destroys the underlying hardware surface. Standard Pygame implementations try to catch this through resize events or re-initialize the surface using display mode settings. On Android architectures, this dynamic re-allocation often triggers memory faults or direct binary crashes. Furthermore, fixed pixel logic locks game entities into rigid coordinate boundaries, causing objects to render off-screen when the display aspect ratio changes
To solve these performance bottlenecks, this script implements a robust mobile rendering pattern that combines three key engineering strategies.
Non-Destructive Context Polling: Instead of intercepting risky window resize events that break SDL bindings, this script queries hardware display properties dynamically per frame using system info calls. This approach preserves the active video memory context, preventing system-level crashes.
Delta Time Frame-Independent Physics: Traditional loop iterations rely on rigid frame counts, which fluctuate wildly during background tasks or screen rotations. This script measures precise time deltas, ensuring that entity velocity calculations remain strictly constant in pixels per second regardless of processor load or refresh rates.
Proportional Relative Mapping: To preserve entity placement during aspect ratio flips, this script tracks horizontal coordinates as normalized fractions. When viewport dimensions swap, entities instantly project to their accurate proportional coordinates without scaling distortion.
Let's see the source code:
import pygame
import random

pygame.init()

info = pygame.display.Info()
WIDTH, HEIGHT = info.current_w, info.current_h

screen = pygame.display.set_mode((WIDTH, HEIGHT), pygame.FULLSCREEN)
clock = pygame.time.Clock()

class FallingBox:
    def __init__(self, rel_x):
        self.rel_x = rel_x                      # Horizontal percentage (kept during rotation)
        self.y_pixels = random.uniform(0, 100)  # Current vertical pixel position
        self.size = 50                          # Box size in pixels

        # Maximum falling distance (recalculated dynamically)
        self.max_dist_pixels = random.randint(150, 400)

        # Constant speed in pixels per second
        self.speed_pps = random.uniform(150.0, 300.0)

        self.color = (
            random.randint(100, 255),
            random.randint(100, 255),
            random.randint(100, 255)
        )

    def update(self, dt, current_h):
        # Time‑based movement (dt in seconds)
        self.y_pixels += self.speed_pps * dt

        # Reset if reaching limit or bottom of screen
        if self.y_pixels >= self.max_dist_pixels or self.y_pixels >= current_h - self.size:
            self.y_pixels = 0.0
            self.max_dist_pixels = random.randint(150, int(current_h * 0.6))
            self.speed_pps = random.uniform(150.0, 300.0)

    def draw(self, surface, current_w):
        # X position scales with screen width
        pos_x = int(self.rel_x * current_w) - (self.size // 2)
        pos_y = int(self.y_pixels)

        # Guide line
        limit_y = int(self.max_dist_pixels)
        pygame.draw.line(surface, (70, 70, 90), (pos_x, limit_y), (pos_x + self.size, limit_y), 2)

        # Draw the box
        pygame.draw.rect(surface, self.color, (pos_x, pos_y, self.size, self.size))


# Create 4 falling boxes
boxes = [FallingBox(i / 5.0) for i in range(1, 5)]

running = True
while running:
    dt = clock.tick(60) / 1000.0  # Frame time in seconds

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # Update screen size dynamically (rotation, resizing)
    info = pygame.display.Info()
    current_w, current_h = info.current_w, info.current_h

    # Update boxes
    for box in boxes:
        box.update(dt, current_h)

    # Render
    screen.fill((20, 20, 30))

    for box in boxes:
        box.draw(screen, current_w)

    pygame.display.flip()

pygame.quit()

luni, 20 aprilie 2026

Python-CE : simulation continuous collision with PyQtGraph python module.

This test runs a pygame‑ce simulation inside a separate thread while a PyQt6 window displays a real‑time performance chart. The pygame engine creates multiple moving sprites, updates their positions every frame, and performs continuous collision detection between all sprites. During each frame, the engine measures the current FPS (frames per second) and counts how many sprite‑to‑sprite collisions occurred.
The PyQt6 interface collects these values and plots them live using PyQtGraph. The yellow curve represents the FPS over time, showing how well the pygame‑ce engine performs under load, while the red curve shows the number of collisions detected each frame. Together, the two curves let you visually evaluate both rendering performance and collision‑handling complexity as the simulation runs.
The source code is created with copilot artificial intelligence, tested and works very well.
import sys
import time
import threading
import pygame
from pygame.sprite import Sprite, Group

from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout
from PyQt6.QtCore import QTimer
import pyqtgraph as pg

# -------------------------------
# SPRITE PYGAME
# -------------------------------
class TestSprite(Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.Surface((30, 30))
        self.image.fill((255, 255, 0))
        self.rect = self.image.get_rect(topleft=(x, y))
        self.vx = 3
        self.vy = 3

    def update(self):
        self.rect.x += self.vx
        self.rect.y += self.vy

        if self.rect.left < 0 or self.rect.right > 800:
            self.vx *= -1
        if self.rect.top < 0 or self.rect.bottom > 600:
            self.vy *= -1


# -------------------------------
# THREAD PYGAME
# -------------------------------
class PygameThread(threading.Thread):
    def __init__(self):
        super().__init__()
        self.running = True
        self.fps_value = 0
        self.collision_count = 0

    def run(self):
        pygame.init()
        screen = pygame.display.set_mode((800, 600))
        clock = pygame.time.Clock()

        sprites = Group()
        for i in range(50):
            sprites.add(TestSprite(i * 15, i * 10))

        while self.running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.running = False

            sprites.update()

            # collision detection
            collisions = pygame.sprite.groupcollide(sprites, sprites, False, False)
            self.collision_count = sum(len(v) for v in collisions.values())

            screen.fill((0, 0, 0))
            sprites.draw(screen)
            pygame.display.flip()

            self.fps_value = clock.get_fps()
            clock.tick(0)

        pygame.quit()


# -------------------------------
# PYQT6 UI + CHART
# -------------------------------
class FPSWindow(QWidget):
    def __init__(self, pg_thread):
        super().__init__()
        self.pg_thread = pg_thread

        self.setWindowTitle("PyQt6 + pygame-ce FPS Chart + Collision Test")
        layout = QVBoxLayout(self)

        self.plot = pg.PlotWidget()
        self.plot.setYRange(0, 200)
        self.plot.showGrid(x=True, y=True)
        layout.addWidget(self.plot)

        self.data_fps = []
        self.data_collisions = []
        self.curve_fps = self.plot.plot(pen='y')
        self.curve_col = self.plot.plot(pen='r')

        self.timer = QTimer()
        self.timer.timeout.connect(self.update_chart)
        self.timer.start(50)

    def update_chart(self):
        self.data_fps.append(self.pg_thread.fps_value)
        self.data_collisions.append(self.pg_thread.collision_count)

        if len(self.data_fps) > 300:
            self.data_fps.pop(0)
            self.data_collisions.pop(0)

        self.curve_fps.setData(self.data_fps)
        self.curve_col.setData(self.data_collisions)


# -------------------------------
# MAIN
# -------------------------------
if __name__ == "__main__":
    pg_thread = PygameThread()
    pg_thread.start()

    app = QApplication(sys.argv)
    win = FPSWindow(pg_thread)
    win.resize(900, 500)
    win.show()

    app.exec()

    pg_thread.running = False
    pg_thread.join()

sâmbătă, 19 octombrie 2024

PyGame : 5by5 linux game project - part 001.

The game is about your brain skills to hack the code based on minimal information versus total information.
The code has 5 distinct letters.
  • click on the letters on the keypad
  • the number of guessed letters is displayed in the form: centered - guessed letters on positions and moved guessed letters but on other positions
I used agentpy python module and pygame python module
The game can be found on my fedora pagure account.

sâmbătă, 21 septembrie 2024

PyGame : 8in8 linux game project - part 001.

I started a game project with the python packages pygame and agentpy in the Fedora Linux distribution.
You can find it on my fedora pagure repo