InfiniTime.git

ref: fdc89f1a20889c0295534f58dc2e82ce8c55a18b

src/displayapp/screens/Paddle.cpp


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "displayapp/screens/Paddle.h"
#include "displayapp/DisplayApp.h"
#include "displayapp/LittleVgl.h"

#include <cstdlib> // for rand()

using namespace Pinetime::Applications::Screens;

Paddle::Paddle(Pinetime::Applications::DisplayApp* app, Pinetime::Components::LittleVgl& lvgl) : Screen(app), lvgl {lvgl} {
  background = lv_obj_create(lv_scr_act(), nullptr);
  lv_obj_set_size(background, LV_HOR_RES + 1, LV_VER_RES);
  lv_obj_set_pos(background, -1, 0);
  lv_obj_set_style_local_radius(background, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
  lv_obj_set_style_local_bg_color(background, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
  lv_obj_set_style_local_border_color(background, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
  lv_obj_set_style_local_border_width(background, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 1);

  points = lv_label_create(lv_scr_act(), nullptr);
  lv_obj_set_style_local_text_font(points, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42);
  lv_label_set_text_static(points, "0000");
  lv_obj_align(points, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 10);

  paddle = lv_obj_create(lv_scr_act(), nullptr);
  lv_obj_set_style_local_bg_color(paddle, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
  lv_obj_set_style_local_radius(paddle, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
  lv_obj_set_size(paddle, 4, 60);

  ball = lv_obj_create(lv_scr_act(), nullptr);
  lv_obj_set_style_local_bg_color(ball, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
  lv_obj_set_style_local_radius(ball, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE);
  lv_obj_set_size(ball, ballSize, ballSize);

  taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
}

Paddle::~Paddle() {
  lv_task_del(taskRefresh);
  lv_obj_clean(lv_scr_act());
}

void Paddle::Refresh() {
  ballX += dx;
  ballY += dy;

  lv_obj_set_pos(ball, ballX, ballY);

  // checks if it has touched the sides (floor and ceiling)
  if (ballY <= 1 || ballY >= LV_VER_RES - ballSize - 2) {
    dy *= -1;
  }

  // checks if it has touched the side (right side)
  if (ballX >= LV_HOR_RES - ballSize - 1) {
    dx *= -1;
    dy += rand() % 3 - 1; // add a little randomization in wall bounce direction, one of [-1, 0, 1]
    if (dy > 5) {         // limit dy to be in range [-5 to 5]
      dy = 5;
    }
    if (dy < -5) {
      dy = -5;
    }
  }

  // checks if it is in the position of the paddle
  if (dx < 0 && ballX <= 4) {
    if (ballX >= -ballSize / 4) {
      if (ballY <= (paddlePos + 30 - ballSize / 4) && ballY >= (paddlePos - 30 - ballSize + ballSize / 4)) {
        dx *= -1;
        score++;
      }
    }
    // checks if it has gone behind the paddle
    else if (ballX <= -ballSize * 2) {
      ballX = (LV_HOR_RES - ballSize) / 2;
      ballY = (LV_VER_RES - ballSize) / 2;
      score = 0;
    }
  }
  lv_label_set_text_fmt(points, "%04d", score);
}

bool Paddle::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
  return true;
}

bool Paddle::OnTouchEvent(uint16_t x, uint16_t y) {
  // sets the center paddle pos. (30px offset) with the the y_coordinate of the finger
  // but clamp it such that the paddle never clips off screen
  if (y < 31) {
    lv_obj_set_pos(paddle, 0, 1);
  } else if (y > LV_VER_RES - 31) {
    lv_obj_set_pos(paddle, 0, LV_VER_RES - 61);
  } else {
    lv_obj_set_pos(paddle, 0, y - 30);
  }
  paddlePos = y;
  return true;
}