Skip to content

Commit

Permalink
Merge pull request #6 from polldo/python-animation
Browse files Browse the repository at this point in the history
Python animation
  • Loading branch information
polldo authored Mar 29, 2022
2 parents 48b65fa + dc87d73 commit d60c60f
Show file tree
Hide file tree
Showing 13 changed files with 325 additions and 15 deletions.
15 changes: 15 additions & 0 deletions examples/micropython/animation/animation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import dolp

explosion1 = bytearray(b'\x10\x10\x00\x00\x00\x00\x90\x40\x40\x20\x40\x40\x84\x00\x10\x00\x00\x00\x00\x00\x04\x00\x00\x05\x01\x02\x01\x21\x00\x04\x00\x00\x00\x00')
explosion2 = bytearray(b'\x10\x10\x00\x00\x00\x00\x88\x60\x24\x10\x20\x60\x80\x00\x12\x00\x00\x00\x00\x40\x02\x00\x00\x03\x02\x24\x02\x03\x00\x00\x00\x44\x00\x00')
explosion3 = bytearray(b'\x10\x10\x00\x00\x60\x44\x84\x40\xa6\x14\x10\x20\x42\x82\x00\x08\x40\x00\x00\x08\x00\x08\x01\x22\x04\x4b\x48\x05\x02\x01\x00\x60\x06\x00')
explosion4 = bytearray(b'\x10\x10\x00\x00\x00\x18\xa8\xc8\xf0\xf0\xf0\xe0\xe8\xb8\x08\x00\x00\x00\x00\x00\x00\x30\x39\x17\x17\x1f\x0f\x17\x13\x21\x78\x20\x00\x00')
explosion = dolp.Animation([explosion1, explosion2, explosion3, explosion4], [150, 200, 200, 300])

dolp.begin()
o = dolp.new_entity()
o.set_animation(explosion)
o.configure(30,30,8,8)

while True:
dolp.loop()
80 changes: 80 additions & 0 deletions micropython/animation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include "pentity.h"
extern "C"
{
#include <dolpmodule.h>
#include "py/obj.h"
#include "py/runtime.h"
}

mp_obj_t animation_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args)
{
mp_arg_check_num(n_args, n_kw, 2, 3, false);
dolp_animation_obj_t *p = m_new_obj(dolp_animation_obj_t);

if (!mp_obj_is_type(args[0], &mp_type_list))
{
mp_raise_TypeError("first parameter should be a list of bytearray");
}
if (!mp_obj_is_type(args[1], &mp_type_list))
{
mp_raise_TypeError("second parameter should be a list of int");
}
if (n_args > 2 && !mp_obj_is_type(args[2], &mp_type_list))
{
mp_raise_TypeError("third parameter should be a list of bytearray");
}

mp_obj_list_t *images = (mp_obj_list_t *)MP_OBJ_TO_PTR(args[0]);
mp_obj_list_t *times = (mp_obj_list_t *)MP_OBJ_TO_PTR(args[1]);
if (images->len != times->len)
{
mp_raise_TypeError("length of bytearray list should equal the length of int list");
}
mp_obj_list_t *masks = NULL;
if (n_args > 2)
{
masks = (mp_obj_list_t *)MP_OBJ_TO_PTR(args[2]);
if (masks->len != images->len)
{
mp_raise_TypeError("length of first bytearray list should equal the length of second bytearray list");
}
}

if (images->len < 1)
{
mp_raise_TypeError("give me at least a frame!");
}

for (size_t i = 0; i < images->len; i++)
{
mp_buffer_info_t imgbuf;
if (!mp_get_buffer(images->items[i], &imgbuf, 1))
{
mp_raise_TypeError("first parameter should be a list of bytearray");
}
}

for (size_t i = 0; i < times->len; i++)
{
if (!mp_obj_is_int(times->items[i]))
{
mp_raise_TypeError("second parameter should be a list of int");
}
}

if (masks)
{
for (size_t i = 0; i < masks->len; i++)
{
mp_buffer_info_t imgbuf;
if (!mp_get_buffer(masks->items[i], &imgbuf, 1))
{
mp_raise_TypeError("third parameter should be a list of bytearray");
}
}
}

p->base.type = &dolp_animation_type;
p->animation = Animation(images, times, masks);
return MP_OBJ_FROM_PTR(p);
}
13 changes: 13 additions & 0 deletions micropython/dolpmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dolp_pentity_get_x_obj, dolp_pentity_obj_get_x)
STATIC MP_DEFINE_CONST_FUN_OBJ_1(dolp_pentity_get_y_obj, dolp_pentity_obj_get_y);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(dolp_pentity_delete_obj, dolp_pentity_obj_delete);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dolp_pentity_set_image_obj, 2, 3, dolp_pentity_obj_set_image);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(dolp_pentity_set_animation_obj, dolp_pentity_obj_set_animation);
STATIC const mp_rom_map_elem_t dolp_pentity_locals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR_get_id), MP_ROM_PTR(&dolp_pentity_get_id_obj)},
{MP_ROM_QSTR(MP_QSTR_set_type), MP_ROM_PTR(&dolp_pentity_set_type_obj)},
Expand All @@ -31,6 +32,7 @@ STATIC const mp_rom_map_elem_t dolp_pentity_locals_dict_table[] = {
{MP_ROM_QSTR(MP_QSTR_set_state), MP_ROM_PTR(&dolp_pentity_set_state_obj)},
{MP_ROM_QSTR(MP_QSTR_get_state), MP_ROM_PTR(&dolp_pentity_get_state_obj)},
{MP_ROM_QSTR(MP_QSTR_set_image), MP_ROM_PTR(&dolp_pentity_set_image_obj)},
{MP_ROM_QSTR(MP_QSTR_set_animation), MP_ROM_PTR(&dolp_pentity_set_animation_obj)},
{MP_ROM_QSTR(MP_QSTR_new_timeout), MP_ROM_PTR(&dolp_pentity_new_timeout_obj)},
{MP_ROM_QSTR(MP_QSTR_delete_timeout), MP_ROM_PTR(&dolp_pentity_delete_timeout_obj)},
{MP_ROM_QSTR(MP_QSTR_get_timeout), MP_ROM_PTR(&dolp_pentity_get_timeout_obj)},
Expand All @@ -48,6 +50,16 @@ const mp_obj_type_t dolp_pentity_type = {
.locals_dict = (mp_obj_t)&dolp_pentity_locals_dict,
};

STATIC const mp_rom_map_elem_t dolp_animation_locals_dict_table[] = {};

STATIC MP_DEFINE_CONST_DICT(dolp_animation_locals_dict, dolp_animation_locals_dict_table);
const mp_obj_type_t dolp_animation_type = {
{&mp_type_type},
.name = MP_QSTR_Animation,
.make_new = animation_make_new,
.locals_dict = (mp_obj_t)&dolp_animation_locals_dict,
};

STATIC MP_DEFINE_CONST_FUN_OBJ_0(dolp_begin_obj, dolp_begin);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dolp_loop_obj, 0, 1, dolp_loop);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(dolp_loop_begin_obj, dolp_loop_begin);
Expand Down Expand Up @@ -86,6 +98,7 @@ STATIC const mp_rom_map_elem_t dolp_module_globals_table[] = {
{MP_ROM_QSTR(MP_QSTR_BUTTON_D), MP_ROM_INT(3)},

{MP_OBJ_NEW_QSTR(MP_QSTR_PEntity), (mp_obj_t)&dolp_pentity_type},
{MP_OBJ_NEW_QSTR(MP_QSTR_Animation), (mp_obj_t)&dolp_animation_type},
};
STATIC MP_DEFINE_CONST_DICT(dolp_module_globals, dolp_module_globals_table);

Expand Down
4 changes: 4 additions & 0 deletions micropython/dolpmodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ extern mp_obj_t dolp_pentity_obj_collided(mp_obj_t self_in, mp_obj_t other_in);
extern mp_obj_t dolp_pentity_obj_set_state(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);
extern mp_obj_t dolp_pentity_obj_get_state(mp_obj_t self_in, mp_obj_t index);
extern mp_obj_t dolp_pentity_obj_set_image(size_t n_args, const mp_obj_t *args);
extern mp_obj_t dolp_pentity_obj_set_animation(mp_obj_t self_in, mp_obj_t animation_in);
extern mp_obj_t dolp_pentity_obj_new_timeout(mp_obj_t self_in, mp_obj_t index);
extern mp_obj_t dolp_pentity_obj_delete_timeout(mp_obj_t self_in, mp_obj_t index);
extern mp_obj_t dolp_pentity_obj_get_timeout(mp_obj_t self_in, mp_obj_t index);
Expand All @@ -36,3 +37,6 @@ extern mp_obj_t dolp_pentity_obj_get_y(mp_obj_t self_in);
extern mp_obj_t dolp_pentity_obj_delete(mp_obj_t self_in);
extern mp_obj_t pentity_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
extern void pentity_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);

extern const mp_obj_type_t dolp_animation_type;
extern mp_obj_t animation_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
1 change: 1 addition & 0 deletions micropython/micropython.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ target_sources(usermod_dolp INTERFACE
${CMAKE_CURRENT_LIST_DIR}/dolp.cpp
${CMAKE_CURRENT_LIST_DIR}/dolpmodule.c
${CMAKE_CURRENT_LIST_DIR}/pentity.cpp
${CMAKE_CURRENT_LIST_DIR}/animation.cpp

${CMAKE_CURRENT_LIST_DIR}/../src/dolp.cpp

Expand Down
12 changes: 12 additions & 0 deletions micropython/pentity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,18 @@ mp_obj_t dolp_pentity_obj_set_image(size_t n_args, const mp_obj_t *args)
return mp_const_none;
}

mp_obj_t dolp_pentity_obj_set_animation(mp_obj_t self_in, mp_obj_t animation_in)
{
if (!mp_obj_is_type(animation_in, &dolp_animation_type))
{
mp_raise_TypeError("you should pass an animation here");
}
dolp_pentity_obj_t *self = (dolp_pentity_obj_t *)MP_OBJ_TO_PTR(self_in);
dolp_animation_obj_t *animation = (dolp_animation_obj_t *)MP_OBJ_TO_PTR(animation_in);
self->pentity.setAnimation(animation->animation);
return mp_const_none;
}

mp_obj_t dolp_pentity_obj_new_timeout(mp_obj_t self_in, mp_obj_t index)
{
dolp_pentity_obj_t *self = (dolp_pentity_obj_t *)MP_OBJ_TO_PTR(self_in);
Expand Down
6 changes: 6 additions & 0 deletions micropython/pentity.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@ typedef struct _dolp_pentity_obj_t
PEntity pentity;
} dolp_pentity_obj_t;

typedef struct _dolp_animation_obj_t
{
mp_obj_base_t base;
Animation animation;
} dolp_animation_obj_t;

#endif
54 changes: 39 additions & 15 deletions src/engine/components/RenderComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,7 @@ void RenderComponent::render()
{
if (timer.checkTimeout(_animationTimeout))
{
timer.setTimeout(_animationTimeout, _animation->times[_animationCounter], false);
if (_animation->imagesMonochrome && _animation->imagesMonochromeMasks)
{
_imageMonochrome = _animation->imagesMonochrome[_animationCounter];
_imageMonochromeMask = _animation->imagesMonochromeMasks[_animationCounter];
}
else if (_animation->imagesMonochrome)
{
_imageMonochrome = _animation->imagesMonochrome[_animationCounter];
}
else if (_animation->imagesColor)
{
_imageColor = _animation->imagesColor[_animationCounter];
}
_animationCounter = (_animationCounter + 1) % _animation->length;
updateAnimation();
}
}

Expand All @@ -88,6 +74,35 @@ void RenderComponent::render()
}
}

void RenderComponent::updateAnimation()
{
#if defined(MICROPYTHON)
timer.setTimeout(_animationTimeout, _animation->time(_animationCounter), false);
_imageMonochrome = _animation->image(_animationCounter);
if (_animation->masks)
{
_imageMonochromeMask = _animation->mask(_animationCounter);
}
_animationCounter = _animation->upCount(_animationCounter);
#else
timer.setTimeout(_animationTimeout, _animation->times[_animationCounter], false);
if (_animation->imagesMonochrome && _animation->imagesMonochromeMasks)
{
_imageMonochrome = _animation->imagesMonochrome[_animationCounter];
_imageMonochromeMask = _animation->imagesMonochromeMasks[_animationCounter];
}
else if (_animation->imagesMonochrome)
{
_imageMonochrome = _animation->imagesMonochrome[_animationCounter];
}
else if (_animation->imagesColor)
{
_imageColor = _animation->imagesColor[_animationCounter];
}
_animationCounter = (_animationCounter + 1) % _animation->length;
#endif
}

void RenderComponent::setImage(const uint8_t *image)
{
removeAnimation();
Expand All @@ -114,6 +129,14 @@ void RenderComponent::setImage(const uint16_t *image)

void RenderComponent::setAnimation(const Animation &animation)
{
#if defined(MICROPYTHON)
_animation = &animation;
_animationTimeout = timer.newTimeout();
_imageMonochrome = NULL;
_imageMonochromeMask = NULL;
_imageColor = NULL;
updateAnimation();
#else
_animation = &animation;
_animationCounter = 1;
_animationTimeout = timer.newTimeout();
Expand All @@ -137,6 +160,7 @@ void RenderComponent::setAnimation(const Animation &animation)
_imageMonochrome = NULL;
_imageMonochromeMask = NULL;
}
#endif
}

void RenderComponent::removeAnimation()
Expand Down
43 changes: 43 additions & 0 deletions src/engine/components/RenderComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
#include "BodyComponent.h"
#include "drivers/Timer.h"

#if defined(MICROPYTHON)
extern "C"
{
#include "py/runtime.h"
#include "py/obj.h"
}
#endif

class Entity;

// typedef uint16_t* ImageColor;
Expand All @@ -30,6 +38,39 @@ class Entity;
struct Animation
{
// const AnimationFrame* frames;

#if defined(MICROPYTHON)
const mp_obj_list_t *images;
const mp_obj_list_t *masks;
const mp_obj_list_t *times;

Animation() : images(NULL), masks(NULL), times(NULL) {}
Animation(const mp_obj_list_t *img, const mp_obj_list_t *tms, const mp_obj_list_t *msk) : images(img), masks(msk), times(tms) {}

int upCount(const int count) const
{
return (count + 1) % images->len;
}

const uint8_t *image(const int count) const
{
mp_obj_t img = images->items[count];
mp_buffer_info_t imgbuf;
mp_get_buffer_raise(img, &imgbuf, 1);
return (const uint8_t *)imgbuf.buf;
}
const int time(const int count) const
{
return mp_obj_get_int(times->items[count]);
}
const uint8_t *mask(const int count) const
{
mp_obj_t msk = masks->items[count];
mp_buffer_info_t mskbuf;
mp_get_buffer_raise(msk, &mskbuf, 1);
return (const uint8_t *)mskbuf.buf;
}
#else
const uint8_t **imagesMonochrome;
const uint8_t **imagesMonochromeMasks;
const uint16_t **imagesColor;
Expand All @@ -40,6 +81,7 @@ struct Animation
Animation(const uint8_t **img, const uint32_t *tms, uint8_t len) : imagesMonochrome(img), imagesMonochromeMasks(NULL), imagesColor(NULL), times(tms), length(len) {}
Animation(const uint8_t **img, const uint8_t **msk, const uint32_t *tms, uint8_t len) : imagesMonochrome(img), imagesMonochromeMasks(msk), imagesColor(NULL), times(tms), length(len) {}
Animation(const uint16_t **img, const uint32_t *tms, uint8_t len) : imagesMonochrome(NULL), imagesMonochromeMasks(NULL), imagesColor(img), times(tms), length(len) {}
#endif
};

class RenderComponent : public Poolable
Expand All @@ -50,6 +92,7 @@ class RenderComponent : public Poolable

void render();
// void update();
void updateAnimation();

void setImage(const uint8_t *image);
void setImage(const uint8_t *image, const uint8_t *mask);
Expand Down
47 changes: 47 additions & 0 deletions tools/monochrome/cmd/main/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package main

import (
"flag"
"fmt"
"image"

_ "golang.org/x/image/bmp"

_ "image/jpeg"
_ "image/png"

"os"

"github.com/polldo/dolp/tools/monochrome"
)

func main() {
var filepath string
flag.StringVar(&filepath, "i", "", "path of image to convert")
flag.Parse()
if filepath == "" {
fmt.Println("please provide a filepath")
os.Exit(1)
}

img, err := openImage(filepath)
if err != nil {
fmt.Printf("cannot open file %s: %s\n", filepath, err)
os.Exit(1)
}

b := monochrome.Convert(img)
fmt.Printf("Image for c++: \n%s\n", b.ToCpp())
fmt.Println()
fmt.Printf("Image for python: \n%s\n", b.ToPy())
}

func openImage(filepath string) (image.Image, error) {
f, err := os.Open(filepath)
if err != nil {
return nil, fmt.Errorf("opening file %s: %w", filepath, err)
}
defer f.Close()
img, _, err := image.Decode(f)
return img, err
}
5 changes: 5 additions & 0 deletions tools/monochrome/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/polldo/dolp/tools/monochrome

go 1.17

require golang.org/x/image v0.0.0-20220321031419-a8550c1d254a
Loading

0 comments on commit d60c60f

Please sign in to comment.