Разработка на коленке

"тут должна быть красивая цитата о программировании"

Перемещать объект в место последнего клика

2024-02-27 22:00

Когда я писал аркадные игрушки, например, Арканоид, то у объекта была либо своя постоянная скорость, и менялось только направление, либо же объект двигался вслед за курсором (пальцем на телефоне).

В этом сниппете я сделал перемещение к конкретной точке, которая ставится кликом мышки.



import pygame as pg


from pygame.math import Vector2
from pygame.time import Clock


class Deck:
    def __init__(self, surface, x, y, velocity=4, size=(140, 30), color=(10, 100, 10)):
        self.surface = surface
        self.position = Vector2(x, y)
        self.velocity = velocity
        self.size = size
        self.color = color

        self.center_x = x + size[0] / 2

        self.rect = pg.rect.Rect(x, y, size[0], size[1])

    def move(self, x):
        self.center_x = x + self.size[0] // 2
        self.position.x = x
        self.rect.x = x

    def render(self):
        pg.draw.rect(self.surface, self.color, self.rect, border_radius=3)


class Mark:
    def __init__(self, surface, x, y, color=(200, 200, 150)):
        self.surface = surface
        self.x = x
        self.y = y
        self.color = color

        self.inner_radius = 6
        self.outer_radius = 16
        self.dash_len = 4
        self.dash_padding = 13

    def render(self):
        pg.draw.circle(
            self.surface,
            self.color,
            (self.x, self.y),
            self.outer_radius,
            1
        )

        pg.draw.circle(
            self.surface,
            self.color,
            (self.x, self.y),
            self.inner_radius
        )

        y = 0
        while y < self.surface.get_height():
            pg.draw.line(
                self.surface, 
                self.color,
                (self.x, y),
                (self.x, y + self.dash_len)
            )
            y += (self.dash_len + self.dash_padding)

class Game:
    def __init__(self, surface):
        self.surface = surface

        self.bg_color = (0, 0, 0)

        self.clock = Clock()
        self.fps = 60

        self.mouse_down_x = None
        self.mouse_offset = 10

        y = self.surface.get_height() - 80
        self.deck = Deck(self.surface, 10, y)
        self.mark = Mark(self.surface, surface.get_width() // 2, y + self.deck.size[1] //2)

        self.working = True

    def process_events(self):
        for e in pg.event.get():
            if e.type == pg.QUIT:
                self.working = False
            elif e.type == pg.KEYDOWN and e.key == pg.K_ESCAPE:
                self.working = False

        if pg.mouse.get_pressed()[0] and self.mouse_down_x is None:
            self.mouse_down_x = pg.mouse.get_pos()[0]

        if not pg.mouse.get_pressed()[0] and self.mouse_down_x is not None:
            x = pg.mouse.get_pos()[0]
            if abs(x - self.mouse_down_x) <= self.mouse_offset:
                self.mark.x = self.mouse_down_x
                if self.mark.x >= self.deck.center_x:
                    self.deck.velocity = abs(self.deck.velocity)
                else:
                    self.deck.velocity = -abs(self.deck.velocity)
            self.mouse_down_x = None

    def update(self):
        if abs(self.deck.center_x - self.mark.x) >= abs(self.deck.velocity):
            self.deck.move(self.deck.position.x + self.deck.velocity)
        else:
            self.deck.move(self.mark.x - self.deck.size[0] // 2)

    def render(self):
        self.surface.fill(self.bg_color)

        self.deck.render()
        self.mark.render()

        pg.display.update()

    def run(self):
        while self.working:
            self.process_events()
            self.update()
            self.render()

            self.clock.tick(self.fps)


def main():
    pg.init()

    size = (1920, 1080)
    flags = pg.FULLSCREEN
    display_surface = pg.display.set_mode(size, flags)
    Game(display_surface).run()

    pg.quit()


if __name__ == "__main__":
    main()

1/move_object_to_click.py

Эксперимент. Разработка через заметки

2024-02-27 21:00

Слушал книгу Зонке Аренса "Как делать полезные заметки", и мне стал интересен подход, в котором работа идёт не сверху вниз от крупных блоков к меньшим, а от маленького к крупному.

Я хочу запустить небольшой эксперимент. Вместо того, чтобы писать программы, проектируя их целиком и переключаясь на разработку каждого отдельного компонента, я буду писать небольшие сниппеты, которые реализуют какую-то компактуню функциональность, которая сама по себе не приносит пользы. А когда наберётся достаточно большое количество таких сниппетов, попробую собрать из них что-то более крупное.

Начну со сниппетов на python+pygame, потому что эти штуки мне снова стали интересны. Но никаких ограничений в развитии в эксперимента не будет. У всех таких постов будет тег notes. Исходники будут лежать в репозитории experiment.

Выпустил Broken Spaceship

2020-05-15 18:40

Broken Spaceship preview

Зарелизил игрушку про управление кораблём со сломанным управлением. Корабль постоянно стреляет и смещается в сторону, а кликом по экрану можно изменить направление смещения.

Писал на LibGDX+Kotlin. Графику рисовал в Aseprite. Музыку взял на opengameart.

Get it on Google Play

Змейка на Phaser3

2018-12-02 19:40

Snake preview

Просто очередная змейка на Phaser3 с графикой в стиле pixelart.

По мере поедания фиолетовых яблок появляются не только новые яблоки, но и камни, столкновение с которыми убивает змейку.

Из интересного - забавный механизм смены головы и хвоста, если нажать кнопку, противоположную текущему направлению движения. Работает примерно так:

reverse() {
    const inverse = {
        up: 'down',
        down: 'up',
        left: 'right',
        right: 'left',
    };

    this.snake = this.snake.reverse();
    this.snake.forEach(s => {
        s.direction = inverse[s.direction];
    });
    this.direction = this.snake[this.snake.length - 1].direction;
}

Спрайты

Пальмы вышли странновато, а вот камень мне нравится.

Snake sprites

Игра

Snake game

Исходники

https://gitlab.com/grigoriytretyakov/phaser3-snake

Sparkling Tail, постмортем

2018-11-02 00:30

Sparkling Tail preview

История этой игры началась в далёком 2013 году. Тогда я (ещё на python+pygame) сделал игрушку, где персонажем был Sparkling Tail. Этот зверёк мне так понравился, что уже позже, в 2014, я решил сделать новую игру с его участием, но уже браузерную версию (раз, два). Однако тогда у меня так и не дошли руки закончить игрушку. И вот спустя ещё 3 года, теперь уже в конце 2018 я решил довести до конца задуманную тогда игру. И дело не в том, что идея игры мне не давала покоя (ничего особенного в ней нет), мне нравился сам герой.

Правила игры довольно просты - уклоняться от летящих на тебя штуковин. Камни просто бьют по голове и смещают в сторону, если вылетел за границы экрана - умер. Колючки убивают сразу.

Когда я снова засел за эту игру, то придумал целый набор разных каменюк, а также разные способы движения. Но уже после добавления камней и шипов с тремя типами движения понял, что игра не настолько интересна, чтобы продолжать её развивать. Бросать разработку на половине пути тоже не хотелось, поэтому я доделал игру с той механикой, что уже была запрограммирована. Так что пусть всё остаётся как есть.

Игра

Sparkling Tail game

Исходники

https://gitlab.com/grigoriytretyakov/sparklingtail-ng