mirror of
https://github.com/ProgramSnail/snake_2024.git
synced 2025-12-08 07:28:43 +00:00
moving circle prototype, circle and square drawing, part of food map implementation, utils
This commit is contained in:
parent
b4a4ffc08a
commit
4570d6e593
9 changed files with 378 additions and 18 deletions
6
include/Bot.hpp
Normal file
6
include/Bot.hpp
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Bot {
|
||||||
|
public:
|
||||||
|
private:
|
||||||
|
};
|
||||||
123
include/Canvas.hpp
Normal file
123
include/Canvas.hpp
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <vector>
|
||||||
|
#
|
||||||
|
|
||||||
|
#include "Engine.h"
|
||||||
|
#include "Utils.hpp"
|
||||||
|
|
||||||
|
enum class Color : uint32_t {
|
||||||
|
BLACK = 0x000000ff,
|
||||||
|
WHITE = 0x00ff6000,
|
||||||
|
|
||||||
|
BLUE = 0x000000ff,
|
||||||
|
GREEN = 0x0000ff00,
|
||||||
|
CYAN = 0x0000ffff,
|
||||||
|
RED = 0x00ff0000,
|
||||||
|
MAGENTA = 0x00ff00ff,
|
||||||
|
YELLOW = 0x00ffff00,
|
||||||
|
GRAY = 0x001f1f1f,
|
||||||
|
ORANGE = 0x00ff6000,
|
||||||
|
};
|
||||||
|
constexpr Color CL_BG = Color::BLACK;
|
||||||
|
|
||||||
|
using Screen = uint32_t[SCREEN_HEIGHT][SCREEN_WIDTH];
|
||||||
|
|
||||||
|
class CanvasObject {
|
||||||
|
public:
|
||||||
|
struct Config {
|
||||||
|
Veci pos;
|
||||||
|
int size;
|
||||||
|
Color color = Color ::WHITE;
|
||||||
|
};
|
||||||
|
CanvasObject(Config config)
|
||||||
|
: pos_(config.pos), size_(config.size), color_(config.color),
|
||||||
|
shown_(false) {}
|
||||||
|
|
||||||
|
virtual void move_to(Veci) = 0;
|
||||||
|
virtual void show() = 0;
|
||||||
|
virtual void hide() = 0;
|
||||||
|
|
||||||
|
virtual ~CanvasObject() {
|
||||||
|
if (shown_) {
|
||||||
|
// hide(); // TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Veci pos_;
|
||||||
|
int size_;
|
||||||
|
Color color_;
|
||||||
|
bool shown_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class StatelessCanvasObject : public CanvasObject {
|
||||||
|
public:
|
||||||
|
using CanvasObject::CanvasObject;
|
||||||
|
|
||||||
|
void move_to(Veci pos) override {
|
||||||
|
if (not shown_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hide();
|
||||||
|
pos_ = pos;
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void show() override { fill(color_); }
|
||||||
|
|
||||||
|
void hide() override { fill(CL_BG); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void fill(Color color) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Square : public StatelessCanvasObject {
|
||||||
|
public:
|
||||||
|
using StatelessCanvasObject::StatelessCanvasObject;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void fill(Color color) override {
|
||||||
|
for (int x = pos_.x; x < pos_.x + size_; ++x) {
|
||||||
|
std::fill(screen_at(x, pos_.y), screen_at(x, pos_.y + size_),
|
||||||
|
static_cast<uint32_t>(color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Circle : public StatelessCanvasObject {
|
||||||
|
public:
|
||||||
|
using StatelessCanvasObject::StatelessCanvasObject;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void fill(Color color) override {
|
||||||
|
for (int x = -size_; x < size_; ++x) {
|
||||||
|
int size_y = std::sqrt(size_ * size_ - std::abs(x) * std::abs(x));
|
||||||
|
std::fill(screen_at(pos_.x + x, pos_.y - size_y),
|
||||||
|
screen_at(pos_.x + x, pos_.y + size_y),
|
||||||
|
static_cast<uint32_t>(color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Worm : public CanvasObject {
|
||||||
|
Worm(CanvasObject::Config config, size_t max_track_size)
|
||||||
|
: CanvasObject(config), max_track_size_(max_track_size) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const size_t max_track_size_;
|
||||||
|
std::vector<Circle> track_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// class Canvas {
|
||||||
|
// public:
|
||||||
|
// Canvas(Screen &screen) : screen_(screen) {}
|
||||||
|
|
||||||
|
// size_t insert(CanvasObject obj) {}
|
||||||
|
// void erase(size_t id) {}
|
||||||
|
|
||||||
|
// private:
|
||||||
|
// Screen &screen_;
|
||||||
|
// };
|
||||||
62
include/Map.hpp
Normal file
62
include/Map.hpp
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
#include "Utils.hpp"
|
||||||
|
#include "Vec.hpp"
|
||||||
|
|
||||||
|
class Map : public GameObject {
|
||||||
|
struct Food {
|
||||||
|
size_t gen;
|
||||||
|
Veci pos;
|
||||||
|
int weight;
|
||||||
|
bool eaten = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr double GEN_INTERVAL = 1.0;
|
||||||
|
static constexpr size_t FOOD_EXISTS_GENS = 10;
|
||||||
|
static constexpr size_t GEN_FOOD_COUNT = 1000;
|
||||||
|
static constexpr int SIZE_X = 20000;
|
||||||
|
static constexpr int SIZE_Y = 20000;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void act(float dt) override {
|
||||||
|
time_from_last_gen_ += dt;
|
||||||
|
if (time_from_last_gen_ > GEN_INTERVAL) {
|
||||||
|
time_from_last_gen_ -= GEN_INTERVAL;
|
||||||
|
generate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int eat(Veci pos, int dist) { // TODO: faster variant ?
|
||||||
|
size_t eaten_weight = 0;
|
||||||
|
for (auto &food : food_) {
|
||||||
|
if ((pos - food.pos).len_sq() < dist * dist and not food.eaten) {
|
||||||
|
food.eaten = true;
|
||||||
|
eaten_weight += food.weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return eaten_weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw() override {} // TODO
|
||||||
|
|
||||||
|
private:
|
||||||
|
void generate() {
|
||||||
|
++current_gen_;
|
||||||
|
while (food_.front().gen + FOOD_EXISTS_GENS < current_gen_) {
|
||||||
|
food_.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < GEN_FOOD_COUNT; ++i) {
|
||||||
|
food_.push_back({.gen = current_gen_,
|
||||||
|
.pos = {.x = rand() % SIZE_X, .y = rand() % SIZE_Y},
|
||||||
|
.weight = 1});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double time_from_last_gen_ = 0;
|
||||||
|
size_t current_gen_ = 0;
|
||||||
|
std::deque<Food> food_ = {};
|
||||||
|
};
|
||||||
6
include/Player.hpp
Normal file
6
include/Player.hpp
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Player {
|
||||||
|
public:
|
||||||
|
private:
|
||||||
|
};
|
||||||
0
include/Snake.hpp
Normal file
0
include/Snake.hpp
Normal file
41
include/Utils.hpp
Normal file
41
include/Utils.hpp
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "Engine.h"
|
||||||
|
#include "Vec.hpp"
|
||||||
|
|
||||||
|
namespace safe {
|
||||||
|
|
||||||
|
inline int lx(int x) { return std::max(0, x); }
|
||||||
|
|
||||||
|
inline int ly(int y) { return std::max(0, y); }
|
||||||
|
|
||||||
|
inline int ux(int x) { return std::min(SCREEN_HEIGHT - 1, x); }
|
||||||
|
|
||||||
|
inline int uy(int y) { return std::min(SCREEN_WIDTH - 1, y); }
|
||||||
|
|
||||||
|
inline int x(int x) { return safe::ux(safe::lx(x)); }
|
||||||
|
inline int y(int y) { return safe::uy(safe::ly(y)); }
|
||||||
|
} // namespace safe
|
||||||
|
|
||||||
|
inline uint32_t *screen_at(int x, int y) {
|
||||||
|
return &buffer[safe::x(x)][safe::y(y)];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> inline bool is_valid_pos(Vec<T> pos) {
|
||||||
|
return pos.x >= 0 and pos.x < SCREEN_HEIGHT and pos.y >= 0 and
|
||||||
|
pos.y < SCREEN_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Veci get_cursor() { return {.x = get_cursor_y(), .y = get_cursor_x()}; }
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
class GameObject {
|
||||||
|
public:
|
||||||
|
virtual void act(float dt) = 0;
|
||||||
|
virtual void draw() = 0;
|
||||||
|
|
||||||
|
virtual ~GameObject() {}
|
||||||
|
};
|
||||||
99
include/Vec.hpp
Normal file
99
include/Vec.hpp
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
template <typename T> struct Vec {
|
||||||
|
T x;
|
||||||
|
T y;
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename U> explicit operator Vec<U>() {
|
||||||
|
return Vec<U>{.x = x, .y = y};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
Vec &operator-() {
|
||||||
|
x = -x;
|
||||||
|
y = -y;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec &operator*=(const T &value) {
|
||||||
|
x *= value;
|
||||||
|
y *= value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec &operator/=(const T &value) {
|
||||||
|
x /= value;
|
||||||
|
y /= value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec operator*(const T &value) const {
|
||||||
|
auto copy = Vec{*this};
|
||||||
|
copy *= value;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec operator/(const T &value) const {
|
||||||
|
auto copy = Vec{*this};
|
||||||
|
copy /= value;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
Vec &operator+=(const Vec &other) {
|
||||||
|
x += other.x;
|
||||||
|
y += other.y;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec &operator-=(const Vec &other) {
|
||||||
|
x -= other.x;
|
||||||
|
y -= other.y;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec operator+(const Vec &other) const {
|
||||||
|
auto copy = Vec{*this};
|
||||||
|
copy += other;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec operator-(const Vec &other) const {
|
||||||
|
auto copy = Vec{*this};
|
||||||
|
copy -= other;
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
bool operator==(const Vec &other) const = default;
|
||||||
|
|
||||||
|
bool operator!=(const Vec &other) const = default;
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
int len_sq() const { return dot(*this, *this); }
|
||||||
|
|
||||||
|
double len() const { return std::sqrt(len_sq()); }
|
||||||
|
|
||||||
|
Vec<double> norm() { return Vec<double>(*this) / len(); }
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
int static dot(Vec left, Vec right) {
|
||||||
|
return left.x * right.x + left.y * right.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int static cross(Vec left, Vec right) {
|
||||||
|
return left.x * right.y - left.y * right.x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using Veci = Vec<int>;
|
||||||
|
using Vecf = Vec<double>;
|
||||||
0
src/Canvas.cpp
Normal file
0
src/Canvas.cpp
Normal file
59
src/Game.cpp
59
src/Game.cpp
|
|
@ -1,46 +1,69 @@
|
||||||
#include "Engine.h"
|
#include "Engine.h"
|
||||||
#include <stdlib.h>
|
#include <iostream>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
// #include <stdio.h>
|
||||||
|
|
||||||
|
#include "Canvas.hpp"
|
||||||
|
|
||||||
|
constexpr double MIN_CONTROL_DISTANCE = 10;
|
||||||
|
|
||||||
//
|
//
|
||||||
// You are free to modify this file
|
// You are free to modify this file
|
||||||
//
|
//
|
||||||
|
|
||||||
// is_key_pressed(int button_vk_code) - check if a key is pressed,
|
// is_key_pressed(int button_vk_code) - check if a key is pressed,
|
||||||
// use keycodes (VK_SPACE, VK_RIGHT, VK_LEFT, VK_UP, VK_DOWN, VK_RETURN)
|
// use keycodes (VK_SPACE, VK_RIGHT,
|
||||||
|
// VK_LEFT, VK_UP, VK_DOWN, VK_RETURN)
|
||||||
//
|
//
|
||||||
// get_cursor_x(), get_cursor_y() - get mouse cursor position
|
// get_cursor_x(), get_cursor_y() - get mouse cursor position
|
||||||
// is_mouse_button_pressed(int button) - check if mouse button is pressed (0 - left button, 1 - right button)
|
// is_mouse_button_pressed(int button) - check if mouse button is pressed (0 -
|
||||||
// schedule_quit_game() - quit game after act()
|
// left button, 1 - right button) schedule_quit_game() - quit game after act()
|
||||||
|
|
||||||
|
|
||||||
// initialize game data in this function
|
// initialize game data in this function
|
||||||
void initialize()
|
void initialize() {}
|
||||||
{
|
|
||||||
}
|
float game_time = 0.0f;
|
||||||
|
Vecf pos = {.x = 20, .y = 20};
|
||||||
|
Vecf direction{.x = 1.0, .y = 0.0};
|
||||||
|
Veci prev_cursor = {.x = 0, .y = 0};
|
||||||
|
|
||||||
// this function is called to update game data,
|
// this function is called to update game data,
|
||||||
// dt - time elapsed since the previous update (in seconds)
|
// dt - time elapsed since the previous update (in seconds)
|
||||||
void act(float dt)
|
void act(float dt) {
|
||||||
{
|
|
||||||
if (is_key_pressed(VK_ESCAPE))
|
if (is_key_pressed(VK_ESCAPE))
|
||||||
schedule_quit_game();
|
schedule_quit_game();
|
||||||
|
|
||||||
|
Veci cursor = get_cursor();
|
||||||
|
if (cursor != prev_cursor and is_valid_pos(cursor)) {
|
||||||
|
Vecf diff = Vecf(cursor) - pos;
|
||||||
|
|
||||||
|
if (diff.len() > MIN_CONTROL_DISTANCE) {
|
||||||
|
direction = diff.norm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int speed = 200;
|
||||||
|
pos += direction * dt * speed;
|
||||||
|
|
||||||
|
game_time += dt;
|
||||||
|
prev_cursor = cursor;
|
||||||
|
// std::cout << "pos: " << pos.x << ' ' << pos.y << std::endl;
|
||||||
|
// std::cout << "curs: " << get_cursor().x << ' ' << get_cursor().y <<
|
||||||
|
// std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill buffer in this function
|
// fill buffer in this function
|
||||||
// uint32_t buffer[SCREEN_HEIGHT][SCREEN_WIDTH] - is an array of 32-bit colors (8 bits per R, G, B)
|
// uint32_t buffer[SCREEN_HEIGHT][SCREEN_WIDTH] - is an array of 32-bit colors
|
||||||
void draw()
|
// (8 bits per R, G, B)
|
||||||
{
|
void draw() {
|
||||||
// clear backbuffer
|
// clear backbuffer
|
||||||
memset(buffer, 0, SCREEN_HEIGHT * SCREEN_WIDTH * sizeof(uint32_t));
|
memset(buffer, 0, SCREEN_HEIGHT * SCREEN_WIDTH * sizeof(uint32_t));
|
||||||
|
|
||||||
|
Circle sq({.pos = Veci(pos), .size = 20});
|
||||||
|
sq.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
// free game data in this function
|
// free game data in this function
|
||||||
void finalize()
|
void finalize() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue