diff --git a/picoled b/picoled index eab338e..1c9fc51 160000 --- a/picoled +++ b/picoled @@ -1 +1 @@ -Subproject commit eab338e380c9f7f30a3699097bf925214415120b +Subproject commit 1c9fc51d01e3f5579b25f4b291b4fa01fdd83faf diff --git a/pong/src/main.cpp b/pong/src/main.cpp index 43ff088..a640c68 100644 --- a/pong/src/main.cpp +++ b/pong/src/main.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -5,9 +6,59 @@ #include +namespace +{ + +struct rect +{ + float x, y, w, h; + + void draw(picoled::oled& oled) const + { + for (int i = 0; i < w; i++) + { + for (int j = 0; j < h; j++) + { + oled(x + i, y + j) = true; + } + } + } + + float left() const { return x; } + float right() const { return x + w; } + float top() const { return y; } + float bottom() const { return y + h; } + + float middle_h() const { return x + w / 2.0f; } + float middle_v() const { return y + h / 2.0f; } + + bool overlaps(const rect& other) const + { + const bool x_overlaps = + (left() >= other.left() && left() <= other.right()) || + (right() >= other.left() && right() <= other.right()); + + const bool y_overlaps = + (top() >= other.top() && top() <= other.bottom()) || + (bottom() >= other.top() && bottom() <= other.bottom()); + + return x_overlaps && y_overlaps; + } +}; + +constexpr uint8_t LEFT_BUTTON = 2; +constexpr uint8_t MIDDLE_BUTTON = 3; +constexpr uint8_t RIGHT_BUTTON = 4; + +constexpr float PADDLE_SPEED = 20; +constexpr float INITIAL_BALL_SPEED = 32; + +} + int main() { stdio_usb_init(); + srand(time_us_64()); i2c_init(i2c0, 3 * 1000 * 1000); gpio_set_function(0, GPIO_FUNC_I2C); @@ -15,19 +66,97 @@ int main() gpio_pull_up(0); gpio_pull_up(1); + gpio_set_function(LEFT_BUTTON, GPIO_FUNC_SIO); + gpio_set_function(MIDDLE_BUTTON, GPIO_FUNC_SIO); + gpio_set_function(RIGHT_BUTTON, GPIO_FUNC_SIO); + gpio_set_dir(LEFT_BUTTON, GPIO_IN); + gpio_set_dir(MIDDLE_BUTTON, GPIO_IN); + gpio_set_dir(RIGHT_BUTTON, GPIO_IN); + gpio_pull_down(LEFT_BUTTON); + gpio_pull_down(MIDDLE_BUTTON); + gpio_pull_down(RIGHT_BUTTON); + picoled::ssd1306 oled(i2c0, 0x3C); oled.update(); + rect player = { 8.0f, oled.get_height() / 2.0f - 8.0f, 4.0f, 16.0f }; + rect ai = { oled.get_width() - 8.0f - 4.0f, oled.get_height() / 2.0f - 8.0f, 4.0f, 16.0f }; + rect ball = { 64.0f - 2.0f, 32.0f - 2.0f, 4.0f, 4.0f }; + float ball_dir = (((rand() % 1000000) / 1000000.0f) - 0.5f) * 3.1415926f * 2.0f; + float ball_dx = cosf(ball_dir); + float ball_dy = sinf(ball_dir); + float ball_speed = INITIAL_BALL_SPEED; + + int64_t us = time_us_32(); + while (true) { - for (int i = 0; i < 16; i++) - { - const int x = rand() % oled.get_width(); - const int y = rand() % oled.get_height(); + oled.clear(); - oled(x, y).invert(); + for (int i = 0; i < oled.get_width(); i++) + { + oled(i, 0) = true; + oled(i, oled.get_height() - 1) = true; } + for (int i = 0; i < oled.get_height(); i++) + { + oled(0, i) = true; + oled(oled.get_width() - 1, i) = true; + } + + int64_t current = time_us_32(); + float dt = std::abs(current - us) / 1000000.0f; + us = current; + + if (gpio_get(LEFT_BUTTON)) { player.y -= PADDLE_SPEED * dt; } + if (gpio_get(MIDDLE_BUTTON)) { player.y += PADDLE_SPEED * dt; } + + float diff = ball.middle_v() - ai.middle_v(); + ai.y += 1.35f * diff * dt; + + ball.x += ball_dx * dt * ball_speed; + ball.y += ball_dy * dt * ball_speed; + + if (ball.overlaps(player)) + { + ball_dx = -ball_dx; + ball.x = player.right(); + ball_speed += 1.0f; + } + if (ball.overlaps(ai)) + { + ball_dx = -ball_dx; + ball.x = ai.left() - ball.w; + ball_speed += 1.0f; + } + + if (ball.left() < 0) + { + ball_dx = -ball_dx; + ball.x = 0; + } + if (ball.right() >= oled.get_width()) + { + ball_dx = -ball_dx; + ball.x = oled.get_width() - ball.w; + } + + if (ball.top() < 0) + { + ball_dy = -ball_dy; + ball.y = 0; + } + if (ball.bottom() >= oled.get_height()) + { + ball_dy = -ball_dy; + ball.y = oled.get_height() - ball.h; + } + + player.draw(oled); + ai.draw(oled); + ball.draw(oled); + oled.update(); } }