mirror of
https://github.com/QuasarApp/Snake.git
synced 2025-04-26 01:34:40 +00:00
201 lines
3.9 KiB
C++
201 lines
3.9 KiB
C++
#include "snake.h"
|
|
#include "guiobject.h"
|
|
|
|
#include <QDateTime>
|
|
#include <QMap>
|
|
#include <QRectF>
|
|
#include <cmath>
|
|
|
|
Snake::Snake() {
|
|
}
|
|
|
|
const QVector<Head *> &Snake::getItems() const {
|
|
return items;
|
|
}
|
|
|
|
void Snake::render() {
|
|
|
|
auto centerX = [](const Head* head) {
|
|
return head->x()/* + (head->w() / 2)*/;
|
|
};
|
|
|
|
auto centerY = [](const Head* head) {
|
|
return head->y() /*+ (head->h() / 2)*/;
|
|
};
|
|
|
|
for (int i = items.length() - 1; i >= 0; --i) {
|
|
|
|
if (dead) {
|
|
items[i]->render();
|
|
continue;
|
|
}
|
|
|
|
if (i == 0) {
|
|
if (isClick) {
|
|
if (countClick & 1){
|
|
items[i]->setAngle(45);
|
|
} else {
|
|
items[i]->setAngle(315);
|
|
}
|
|
isClick = false;
|
|
}
|
|
} else {
|
|
|
|
double _atan2 = atan2(centerY(items[i - 1]) - centerY(items[i]),
|
|
centerX(items[i - 1]) - centerX(items[i])) * 90;
|
|
|
|
items[i]->setAngle(_atan2);
|
|
}
|
|
|
|
items[i]->render();
|
|
}
|
|
}
|
|
|
|
double Snake::checDistance(int i) {
|
|
|
|
auto result = (items[i]->rect().y() -
|
|
items[i - 1]->rect().y()) / rataticonDistance;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
double Snake::getRataticonDistance() const {
|
|
return rataticonDistance;
|
|
}
|
|
|
|
void Snake::setRataticonDistance(double value) {
|
|
rataticonDistance = value;
|
|
}
|
|
|
|
void Snake::unPause() {
|
|
for ( int i = 0; i < items.size(); ++i ) {
|
|
items[i]->unPause();
|
|
}
|
|
}
|
|
|
|
double Snake::sizeByLvl(double lvl , int count) const {
|
|
double maxSize = 9;
|
|
double minSize = 5;
|
|
|
|
double pos = (1 - (lvl / count));
|
|
|
|
QList<QPair<double, double>> snakeGradientSize {
|
|
{1, 4},
|
|
{0.99, 7},
|
|
{0.8, 5},
|
|
{0.6, 6},
|
|
{0.0, 3}
|
|
};
|
|
|
|
double local = 0;
|
|
int index = 0;
|
|
|
|
while (index + 1 < snakeGradientSize.size()
|
|
&& pos <= snakeGradientSize[index].first) {
|
|
|
|
maxSize = snakeGradientSize[index].second;
|
|
minSize = snakeGradientSize[index + 1].second;
|
|
|
|
auto range = snakeGradientSize[index].first -
|
|
snakeGradientSize[index + 1].first;
|
|
|
|
local = ( range - (snakeGradientSize[index].first - pos)) /
|
|
range;
|
|
|
|
index++;
|
|
}
|
|
|
|
return local * (maxSize - minSize) + minSize;
|
|
}
|
|
|
|
void Snake::changeCountObjects(int count) {
|
|
if (count > 0) {
|
|
double margin = 60.0 / count;
|
|
for ( int i = 0; i < count; ++i ) {
|
|
|
|
auto size = sizeByLvl(i, count);
|
|
auto obj = new Head(margin * (count - i),
|
|
50, size , size,
|
|
this->speed);
|
|
|
|
obj->setY(50 + obj->h() / 2);
|
|
|
|
items.push_back(obj);
|
|
}
|
|
|
|
} else {
|
|
for ( int i = count; i < 0; ++i ) {
|
|
auto obj = items.first();
|
|
items.removeFirst();
|
|
delete obj;
|
|
}
|
|
}
|
|
}
|
|
|
|
QMap<int, GuiObject*> Snake::init(int size, double *speed) {
|
|
|
|
QMap<int, GuiObject*> res;
|
|
|
|
if (size <= 0) {
|
|
return res;
|
|
}
|
|
|
|
this->speed = speed;
|
|
|
|
changeCountObjects(size - items.size());
|
|
|
|
for (auto i : items) {
|
|
res[i->guiId()] = i;
|
|
}
|
|
|
|
dead = false;
|
|
|
|
return res;
|
|
}
|
|
|
|
bool Snake::isInited() const {
|
|
return items.size();
|
|
}
|
|
|
|
void Snake::clearItems() {
|
|
for (auto i : items) {
|
|
delete i;
|
|
}
|
|
items.clear();
|
|
}
|
|
|
|
void Snake::resetPosotion() {
|
|
double margin = 60.0 / items.size();
|
|
|
|
for ( int i = 0; i < items.size(); ++i ) {
|
|
items[i]->setX(margin * (items.size() - i));
|
|
items[i]->setY(50 + items[i]->h() / 2);
|
|
items[i]->setAngle(0);
|
|
}
|
|
}
|
|
|
|
void Snake::kill() {
|
|
dead = true;
|
|
}
|
|
|
|
bool Snake::isDead() const {
|
|
return dead;
|
|
}
|
|
|
|
Snake::~Snake() {
|
|
clearItems();
|
|
}
|
|
|
|
void Snake::clear() {
|
|
clearItems();
|
|
}
|
|
|
|
void Snake::reverse() {
|
|
if (isClick) {
|
|
return;
|
|
}
|
|
isClick = true;
|
|
countClick++;
|
|
}
|