rotate point around center of sprite in food scene
This commit is contained in:
parent
8f2bb74449
commit
598c62976b
21
Release.key
21
Release.key
|
@ -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-----
|
|
|
@ -6,49 +6,42 @@
|
||||||
#include <libgba-sprite-engine/gba/tonc_bios.h>
|
#include <libgba-sprite-engine/gba/tonc_bios.h>
|
||||||
#include "bullet.h"
|
#include "bullet.h"
|
||||||
|
|
||||||
// in 1/256 pixels
|
#define FIXED_POINT_BASE 1000
|
||||||
#define SPEED 50
|
#define SPEED_DELTA 1
|
||||||
|
|
||||||
u32 length(VECTOR a) {
|
void Bullet::setDestination(VECTOR destination) {
|
||||||
return Sqrt(a.x * a.x + a.y * a.y);
|
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() {
|
void Bullet::tick() {
|
||||||
auto pos = sprite->getPos();
|
auto x = sprite->getX(), y = sprite->getY();
|
||||||
int xdiff = 1, ydiff = 1;
|
|
||||||
|
|
||||||
if(abs(pos.x - dest.x) > abs(pos.y - dest.y)) {
|
if(directionToCover.x != 0) {
|
||||||
xdiff += 1;
|
if(directionToCover.x > 0) {
|
||||||
} else {
|
directionToCover.x -= FIXED_POINT_BASE;
|
||||||
ydiff += 1;
|
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) {
|
sprite->moveTo(x, y);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
|
@ -13,14 +13,14 @@ class Bullet {
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Sprite> sprite;
|
std::unique_ptr<Sprite> sprite;
|
||||||
VECTOR dest;
|
VECTOR dest;
|
||||||
VECTOR vel;
|
VECTOR diff;
|
||||||
VECTOR direction;
|
VECTOR directionToCover;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Bullet(std::unique_ptr<Sprite> sprite) : sprite(std::move(sprite)), dest(VECTOR()) {}
|
Bullet(std::unique_ptr<Sprite> sprite) : sprite(std::move(sprite)), dest(VECTOR()) {}
|
||||||
|
|
||||||
void tick();
|
void tick();
|
||||||
void setDestination(VECTOR vec);
|
void setDestination(VECTOR destination);
|
||||||
bool isOffScreen() { return sprite->isOffScreen(); }
|
bool isOffScreen() { return sprite->isOffScreen(); }
|
||||||
Sprite* getSprite() { return sprite.get(); }
|
Sprite* getSprite() { return sprite.get(); }
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "bullet.h"
|
#include "bullet.h"
|
||||||
#include "bullet_data.h"
|
#include "bullet_data.h"
|
||||||
|
|
||||||
#define AVATAR_ROTATION_DIFF (128 * 2)
|
#define AVATAR_ROTATION_DIFF (128 * 6)
|
||||||
#define MAX_AMOUNT_OF_BULLETS 40
|
#define MAX_AMOUNT_OF_BULLETS 40
|
||||||
#define BULLET_COOLDOWN_START 20
|
#define BULLET_COOLDOWN_START 20
|
||||||
|
|
||||||
|
@ -41,25 +41,20 @@ void FoodScene::removeBulletsOffScreen() {
|
||||||
bullets.end());
|
bullets.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string hex(int val) {
|
VECTOR FoodScene::rotateAround(VECTOR center, VECTOR point) {
|
||||||
std::stringstream sstream;
|
s32 centerx = center.x, centery = center.y;
|
||||||
sstream << std::hex << val;
|
s32 defaultx = point.x, defaulty = point.y;
|
||||||
std::string result = sstream.str();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 hex_int(u32 decimalValue) {
|
s32 cos = lu_cos(avatarRotation) >> 4;
|
||||||
return (((decimalValue) & 0xF) + (((decimalValue) >> 4) * 10));
|
s32 sin = lu_sin(avatarRotation) >> 4;
|
||||||
}
|
|
||||||
|
|
||||||
VECTOR randomDestinations[6] = {
|
// affine matriches are 8.8 fixed point numbers, so shift all input 8 spaces up and forth
|
||||||
{GBA_SCREEN_WIDTH, GBA_SCREEN_HEIGHT},
|
// possibilities: instead of between [-1.0, 1.0] it's between [-256, +256]
|
||||||
{0, 0},
|
// 90° rotation in inversed y-axis needs to flip sin sign
|
||||||
{GBA_SCREEN_WIDTH / 2, GBA_SCREEN_HEIGHT},
|
return {
|
||||||
{GBA_SCREEN_WIDTH, GBA_SCREEN_HEIGHT / 2},
|
( cos * (defaultx - centerx) + sin * (defaulty - centery) + (centerx << 8)) >> 8,
|
||||||
{GBA_SCREEN_WIDTH, 0},
|
(-sin * (defaultx - centerx) + cos * (defaulty - centery) + (centery << 8)) >> 8};
|
||||||
{0, GBA_SCREEN_HEIGHT}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
void FoodScene::tick(u16 keys) {
|
void FoodScene::tick(u16 keys) {
|
||||||
avatar->animateToFrame(0);
|
avatar->animateToFrame(0);
|
||||||
|
@ -74,17 +69,10 @@ void FoodScene::tick(u16 keys) {
|
||||||
removeBulletsOffScreen();
|
removeBulletsOffScreen();
|
||||||
TextStream::instance().setText(std::string("bullets: ") + std::to_string(bullets.size()), 1, 1);
|
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("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);
|
|
||||||
|
|
||||||
/*
|
TextStream::instance().setText(std::string("angle pa/pb: ") + std::to_string(avatar->getMatrix()->pa) + std::string("/") + std::to_string(avatar->getMatrix()->pb), 3, 1);
|
||||||
int defaultx = hex_int(GBA_SCREEN_WIDTH / 2 - 20), defaulty = hex_int(GBA_SCREEN_HEIGHT - 20);
|
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) {
|
if(keys & KEY_LEFT) {
|
||||||
avatarRotation -= AVATAR_ROTATION_DIFF;
|
avatarRotation -= AVATAR_ROTATION_DIFF;
|
||||||
} else if(keys & KEY_RIGHT) {
|
} else if(keys & KEY_RIGHT) {
|
||||||
|
@ -98,7 +86,9 @@ void FoodScene::tick(u16 keys) {
|
||||||
bullets.push_back(createBullet());
|
bullets.push_back(createBullet());
|
||||||
|
|
||||||
auto &b = bullets.at(bullets.size() - 1);
|
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)
|
.withLocation(GBA_SCREEN_WIDTH + 20, GBA_SCREEN_HEIGHT + 20)
|
||||||
.buildPtr();
|
.buildPtr();
|
||||||
bulletCooldown = BULLET_COOLDOWN_START;
|
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};
|
||||||
}
|
}
|
|
@ -23,6 +23,9 @@ private:
|
||||||
std::unique_ptr<Bullet> createBullet();
|
std::unique_ptr<Bullet> createBullet();
|
||||||
void removeBulletsOffScreen();
|
void removeBulletsOffScreen();
|
||||||
|
|
||||||
|
VECTOR rotateAround(VECTOR center, VECTOR point);
|
||||||
|
VECTOR defaultBulletTarget;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FoodScene(const std::shared_ptr<GBAEngine> &engine);
|
explicit FoodScene(const std::shared_ptr<GBAEngine> &engine);
|
||||||
FoodScene(FoodScene& other) = delete;
|
FoodScene(FoodScene& other) = delete;
|
||||||
|
|
|
@ -84,14 +84,16 @@ public:
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
void moveTo(int x, int y);
|
void moveTo(int x, int y);
|
||||||
|
void moveTo(VECTOR location);
|
||||||
bool collidesWith(Sprite &s2);
|
bool collidesWith(Sprite &s2);
|
||||||
|
|
||||||
void flipVertically(bool flip);
|
void flipVertically(bool flip);
|
||||||
void flipHorizontally(bool flip);
|
void flipHorizontally(bool flip);
|
||||||
|
|
||||||
u32 getTileIndex() { return tileIndex; }
|
u32 getTileIndex() { return tileIndex; }
|
||||||
VECTOR getPos() { return VECTOR {x, y}; }
|
VECTOR getPos() { return {x, y}; }
|
||||||
VECTOR getVelocity() { return VECTOR { dx, dy}; }
|
VECTOR getCenter() { return { x + w / 2, y + h / 2 }; }
|
||||||
|
VECTOR getVelocity() { return { dx, dy}; }
|
||||||
u32 getDx() { return dx; }
|
u32 getDx() { return dx; }
|
||||||
u32 getDy() { return dy; }
|
u32 getDy() { return dy; }
|
||||||
u32 getX() { return x; }
|
u32 getX() { return x; }
|
||||||
|
|
|
@ -18,6 +18,10 @@ Sprite::Sprite(const void *imageData, int imageSize, int x, int y, SpriteSize si
|
||||||
setAttributesBasedOnSize(size);
|
setAttributesBasedOnSize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sprite::moveTo(VECTOR location) {
|
||||||
|
moveTo(location.x, location.y);
|
||||||
|
}
|
||||||
|
|
||||||
void Sprite::moveTo(int x, int y) {
|
void Sprite::moveTo(int x, int y) {
|
||||||
this->x = x;
|
this->x = x;
|
||||||
this->y = y;
|
this->y = y;
|
||||||
|
|
Loading…
Reference in New Issue