rotate point around center of sprite in food scene

This commit is contained in:
wgroeneveld 2018-12-14 13:11:13 +01:00
parent 8f2bb74449
commit 598c62976b
7 changed files with 67 additions and 93 deletions

View File

@ -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-----

View File

@ -6,49 +6,42 @@
#include <libgba-sprite-engine/gba/tonc_bios.h>
#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);
}
sprite->moveTo(x, y);
}

View File

@ -13,14 +13,14 @@ class Bullet {
private:
std::unique_ptr<Sprite> sprite;
VECTOR dest;
VECTOR vel;
VECTOR direction;
VECTOR diff;
VECTOR directionToCover;
public:
Bullet(std::unique_ptr<Sprite> 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(); }
};

View File

@ -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};
}

View File

@ -23,6 +23,9 @@ private:
std::unique_ptr<Bullet> createBullet();
void removeBulletsOffScreen();
VECTOR rotateAround(VECTOR center, VECTOR point);
VECTOR defaultBulletTarget;
public:
explicit FoodScene(const std::shared_ptr<GBAEngine> &engine);
FoodScene(FoodScene& other) = delete;

View File

@ -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; }

View File

@ -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;