diff --git a/Release.key b/Release.key deleted file mode 100644 index 35e2a86..0000000 --- a/Release.key +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v2.0.15 (GNU/Linux) - -mQENBFdEgZoBCAD06orQfic7gtx/akz9QG5I9p0hjLDurZUdqL5QcV11IkvXar99 -tWforuy4tr74oUwQVn9E6GtVejwjGZfJ60qQSOs8Jye/qdtDiVg9ORFa+hDji9+X -NW22ZjVYlwfwGejXwsk8KiLYmd5nT2UftXHadInBaWj8SGtX/fDiGJmt6rBTPVs/ -JSvNF3NNi95Pnwsji9LVLGAJzHO/2h1qvK8tmGaMEAgXYuYEhZ+K2ld4c609aV1Q -WZkZakz+l9AGd1K6wy4TFgQSBoRgGZJNdDGAmorL5y/mrH/rG/9YG5BNHbhklHp+ -Obn5iWBPfoHVke2XbrjSOtYetIrPE+UUFDQLABEBAAG0OmhvbWU6UGl2YWw4MSBP -QlMgUHJvamVjdCA8aG9tZTpQaXZhbDgxQGJ1aWxkLm9wZW5zdXNlLm9yZz6JAT4E -EwECACgFAldEgZoCGwMFCQQesAAGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJ -EF0O8jNk4jAxoUgH/3YwxTPIAXCwcetRQbf3lp5N/MaV5sMf8fiV5Uy1HBKn2HMi -Gm75axQlMJTC39FTbq0CT/3nfeUhvsk1ipk41KpkukcrDpGvppZYEkzj8zxEXfiq -Ow78lWD66jpY184rTpsLLt4IcqqH1QMC7fQV9b8mzR5WmBRUhnO+l6oIT3fccZ9D -faNfXl/+CuAX+S6i7kJRyHIN07T0tKaZMyIGSiw7bhQ8L/0NZ9vn57J+KC6f5SEG -kmEs/j1AltsRI8R6Z9alT0XSjnwW6o281mbpir/12A2O/9mxVhFrcgHdB2yl3JCN -OgSX8LnHTDnjmMCmCWVz73QQDVrZJmJ0ltwVBO+IRgQTEQIABgUCV0SBmgAKCRA7 -MBG3a51lI1fSAKCA+sfj77Uv1D4g+sK7lbE0AyJKagCfdFQQ9lCfmEQ1wfZyOCvs -GSV0JlA= -=1rpz ------END PGP PUBLIC KEY BLOCK----- diff --git a/demos/demo3-foodthrowing/src/bullet.cpp b/demos/demo3-foodthrowing/src/bullet.cpp index 55d4206..a3415aa 100644 --- a/demos/demo3-foodthrowing/src/bullet.cpp +++ b/demos/demo3-foodthrowing/src/bullet.cpp @@ -6,49 +6,42 @@ #include #include "bullet.h" -// in 1/256 pixels -#define SPEED 50 +#define FIXED_POINT_BASE 1000 +#define SPEED_DELTA 1 -u32 length(VECTOR a) { - return Sqrt(a.x * a.x + a.y * a.y); +void Bullet::setDestination(VECTOR destination) { + auto currentPos = sprite->getPos(); + this->dest = destination; + + diff.x = (destination.x - currentPos.x); + diff.y = (destination.y - currentPos.y); + directionToCover.x = diff.x * FIXED_POINT_BASE; + directionToCover.y = diff.y * FIXED_POINT_BASE; + + TextStream::instance().setText(std::string("covering: ") + std::to_string(directionToCover.x) + std::string(",") + std::to_string(directionToCover.y), 15, 1); } -u32 distance(VECTOR a, VECTOR b) { - return length({a.x - b.x, a.y - b.y}); -} - -VECTOR normalize(VECTOR a) { - u32 l = length(a); - return { a.x / l, a.y / l }; -} - -void Bullet::setDestination(VECTOR vec) { - this->dest = vec; -} - -// TODO https://gamedev.stackexchange.com/questions/23447/moving-from-ax-y-to-bx1-y1-with-constant-speed void Bullet::tick() { - auto pos = sprite->getPos(); - int xdiff = 1, ydiff = 1; + auto x = sprite->getX(), y = sprite->getY(); - if(abs(pos.x - dest.x) > abs(pos.y - dest.y)) { - xdiff += 1; - } else { - ydiff += 1; + if(directionToCover.x != 0) { + if(directionToCover.x > 0) { + directionToCover.x -= FIXED_POINT_BASE; + x += SPEED_DELTA; + } else { + directionToCover.x += FIXED_POINT_BASE; + x -= SPEED_DELTA; + } + } + if(directionToCover.y != 0) { + if(directionToCover.y > 0) { + directionToCover.y -= FIXED_POINT_BASE; + y += SPEED_DELTA; + } else { + directionToCover.y += FIXED_POINT_BASE; + y -= SPEED_DELTA; + } } - if(pos.x > dest.x) { - vel.x -= 1 * xdiff; - } else if(pos.x < dest.x) { - vel.x = 1 * xdiff; - } - if(pos.y > dest.y) { - vel.y -= 1 * ydiff; - } else if(pos.y < dest.y) { - vel.y = 1 * ydiff; - } - - TextStream::instance().setText(std::string("pos/dest: (") + std::to_string(pos.x) + std::string(",") + std::to_string(pos.y) + std::string(") (") + std::to_string(dest.x) + std::string(",") + std::to_string(dest.y) + std::string(")"), 16, 1); - - sprite->setVelocity(vel.x, vel.y); -} \ No newline at end of file + sprite->moveTo(x, y); +} diff --git a/demos/demo3-foodthrowing/src/bullet.h b/demos/demo3-foodthrowing/src/bullet.h index 45a8be3..eeadaed 100644 --- a/demos/demo3-foodthrowing/src/bullet.h +++ b/demos/demo3-foodthrowing/src/bullet.h @@ -13,14 +13,14 @@ class Bullet { private: std::unique_ptr sprite; VECTOR dest; - VECTOR vel; - VECTOR direction; + VECTOR diff; + VECTOR directionToCover; public: Bullet(std::unique_ptr sprite) : sprite(std::move(sprite)), dest(VECTOR()) {} void tick(); - void setDestination(VECTOR vec); + void setDestination(VECTOR destination); bool isOffScreen() { return sprite->isOffScreen(); } Sprite* getSprite() { return sprite.get(); } }; diff --git a/demos/demo3-foodthrowing/src/food_scene.cpp b/demos/demo3-foodthrowing/src/food_scene.cpp index 421254c..ccbb86b 100644 --- a/demos/demo3-foodthrowing/src/food_scene.cpp +++ b/demos/demo3-foodthrowing/src/food_scene.cpp @@ -12,7 +12,7 @@ #include "bullet.h" #include "bullet_data.h" -#define AVATAR_ROTATION_DIFF (128 * 2) +#define AVATAR_ROTATION_DIFF (128 * 6) #define MAX_AMOUNT_OF_BULLETS 40 #define BULLET_COOLDOWN_START 20 @@ -41,25 +41,20 @@ void FoodScene::removeBulletsOffScreen() { bullets.end()); } -std::string hex(int val) { - std::stringstream sstream; - sstream << std::hex << val; - std::string result = sstream.str(); - return result; -} +VECTOR FoodScene::rotateAround(VECTOR center, VECTOR point) { + s32 centerx = center.x, centery = center.y; + s32 defaultx = point.x, defaulty = point.y; -u32 hex_int(u32 decimalValue) { - return (((decimalValue) & 0xF) + (((decimalValue) >> 4) * 10)); -} + s32 cos = lu_cos(avatarRotation) >> 4; + s32 sin = lu_sin(avatarRotation) >> 4; -VECTOR randomDestinations[6] = { - {GBA_SCREEN_WIDTH, GBA_SCREEN_HEIGHT}, - {0, 0}, - {GBA_SCREEN_WIDTH / 2, GBA_SCREEN_HEIGHT}, - {GBA_SCREEN_WIDTH, GBA_SCREEN_HEIGHT / 2}, - {GBA_SCREEN_WIDTH, 0}, - {0, GBA_SCREEN_HEIGHT} -}; + // affine matriches are 8.8 fixed point numbers, so shift all input 8 spaces up and forth + // possibilities: instead of between [-1.0, 1.0] it's between [-256, +256] + // 90° rotation in inversed y-axis needs to flip sin sign + return { + ( cos * (defaultx - centerx) + sin * (defaulty - centery) + (centerx << 8)) >> 8, + (-sin * (defaultx - centerx) + cos * (defaulty - centery) + (centery << 8)) >> 8}; +} void FoodScene::tick(u16 keys) { avatar->animateToFrame(0); @@ -74,17 +69,10 @@ void FoodScene::tick(u16 keys) { removeBulletsOffScreen(); TextStream::instance().setText(std::string("bullets: ") + std::to_string(bullets.size()), 1, 1); TextStream::instance().setText(std::string("cooldown: ") + std::to_string(bulletCooldown), 2, 1); - TextStream::instance().setText(std::string("angle pa/pb: ") + hex(avatar->getMatrix()->pa) + std::string("/") + hex(avatar->getMatrix()->pb), 3, 1); - TextStream::instance().setText(std::string("angle pc/pd: ") + hex(avatar->getMatrix()->pc) + std::string("/") + hex(avatar->getMatrix()->pd), 4, 1); - /* - int defaultx = hex_int(GBA_SCREEN_WIDTH / 2 - 20), defaulty = hex_int(GBA_SCREEN_HEIGHT - 20); + TextStream::instance().setText(std::string("angle pa/pb: ") + std::to_string(avatar->getMatrix()->pa) + std::string("/") + std::to_string(avatar->getMatrix()->pb), 3, 1); + TextStream::instance().setText(std::string("angle pc/pd: ") + std::to_string(avatar->getMatrix()->pc) + std::string("/") + std::to_string(avatar->getMatrix()->pd), 4, 1); - auto newx = toDecimal((avatar->getMatrix()->pa * defaultx + avatar->getMatrix()->pb * defaulty) >> 8); - auto newy = toDecimal((avatar->getMatrix()->pc * defaultx + avatar->getMatrix()->pd * defaulty) >> 8); - - TextStream::instance().setText(std::string("translated x/y: ") + std::to_string(newx) + std::string(",") + std::to_string(newy), 16, 1); -*/ if(keys & KEY_LEFT) { avatarRotation -= AVATAR_ROTATION_DIFF; } else if(keys & KEY_RIGHT) { @@ -98,7 +86,9 @@ void FoodScene::tick(u16 keys) { bullets.push_back(createBullet()); auto &b = bullets.at(bullets.size() - 1); - b->setDestination(randomDestinations[rand() % 6]); + auto destination = rotateAround(avatar->getCenter(), defaultBulletTarget); + TextStream::instance().setText(std::string("shooting dest: ") + std::to_string(destination.x) + std::string(",") + std::to_string(destination.y), 16, 1); + b->setDestination(destination); } } @@ -136,4 +126,7 @@ void FoodScene::load() { .withLocation(GBA_SCREEN_WIDTH + 20, GBA_SCREEN_HEIGHT + 20) .buildPtr(); bulletCooldown = BULLET_COOLDOWN_START; + + // rotation of a point on a circle within the resolution means our radius should be big enough + defaultBulletTarget = { GBA_SCREEN_WIDTH / 2, GBA_SCREEN_HEIGHT + (GBA_SCREEN_WIDTH / 2) - avatar->getCenter().y}; } \ No newline at end of file diff --git a/demos/demo3-foodthrowing/src/food_scene.h b/demos/demo3-foodthrowing/src/food_scene.h index 4860511..1cc5879 100644 --- a/demos/demo3-foodthrowing/src/food_scene.h +++ b/demos/demo3-foodthrowing/src/food_scene.h @@ -23,6 +23,9 @@ private: std::unique_ptr createBullet(); void removeBulletsOffScreen(); + VECTOR rotateAround(VECTOR center, VECTOR point); + VECTOR defaultBulletTarget; + public: explicit FoodScene(const std::shared_ptr &engine); FoodScene(FoodScene& other) = delete; diff --git a/engine/include/libgba-sprite-engine/sprites/sprite.h b/engine/include/libgba-sprite-engine/sprites/sprite.h index c2f6dfe..f454685 100644 --- a/engine/include/libgba-sprite-engine/sprites/sprite.h +++ b/engine/include/libgba-sprite-engine/sprites/sprite.h @@ -84,14 +84,16 @@ public: void update(); void moveTo(int x, int y); + void moveTo(VECTOR location); bool collidesWith(Sprite &s2); void flipVertically(bool flip); void flipHorizontally(bool flip); u32 getTileIndex() { return tileIndex; } - VECTOR getPos() { return VECTOR {x, y}; } - VECTOR getVelocity() { return VECTOR { dx, dy}; } + VECTOR getPos() { return {x, y}; } + VECTOR getCenter() { return { x + w / 2, y + h / 2 }; } + VECTOR getVelocity() { return { dx, dy}; } u32 getDx() { return dx; } u32 getDy() { return dy; } u32 getX() { return x; } diff --git a/engine/src/sprites/sprite.cpp b/engine/src/sprites/sprite.cpp index 4662d51..64edc89 100644 --- a/engine/src/sprites/sprite.cpp +++ b/engine/src/sprites/sprite.cpp @@ -18,6 +18,10 @@ Sprite::Sprite(const void *imageData, int imageSize, int x, int y, SpriteSize si setAttributesBasedOnSize(size); } +void Sprite::moveTo(VECTOR location) { + moveTo(location.x, location.y); +} + void Sprite::moveTo(int x, int y) { this->x = x; this->y = y;