kaplay-ui 0.20.1 → 1.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +171 -186
- package/ROADMAP.md +162 -0
- package/assets/kaplay-ui-logo.png +0 -0
- package/index.html +12 -0
- package/package.json +13 -4
- package/src/components/buttons/index.ts +1 -0
- package/src/components/buttons/text-button/index.ts +24 -0
- package/src/components/container/container.logic.ts +31 -0
- package/src/components/container/container.styles.ts +22 -0
- package/src/components/container/container.types.ts +45 -0
- package/src/components/container/index.ts +47 -0
- package/src/components/index.ts +1 -0
- package/src/components/texts/index.ts +1 -0
- package/src/components/texts/text-button/text-button.ts +24 -0
- package/src/index.ts +59 -0
- package/test/game.ts +9 -0
- package/tsconfig.json +21 -0
- package/vite.config.ts +14 -0
- package/assets/cb-icon.png +0 -0
- package/inputs/index.js +0 -226
- /package/{index.js → favicon.ico} +0 -0
package/README.md
CHANGED
|
@@ -1,245 +1,230 @@
|
|
|
1
|
-
|
|
2
|
-
<
|
|
3
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/kaplay-ui-logo.png" alt="kaplay-ui logo" width="400" >
|
|
3
|
+
</p>
|
|
4
4
|
|
|
5
|
-
# KAPLAY UI
|
|
5
|
+
# KAPLAY UI Plugin
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
A lightweight UI helper plugin for the https://kaplayjs.com/ game library, providing ready‑to‑use UI components such as text‑based buttons.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
This plugin simplifies the creation of UI elements using familiar KAPLAY primitives, offering sensible defaults while remaining flexible and composable.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
---
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
- [Usage](#usage)
|
|
15
|
-
- [License](#license)
|
|
13
|
+
## ✨ Features
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
- 🎛️ **Text Button** — easily create a button with centered text
|
|
16
|
+
- 🧩 Designed to feel like native KAPLAY components
|
|
17
|
+
- 🎨 Comes with built‑in sizing, positioning, and outline defaults
|
|
18
|
+
- 🔧 Fully customizable through the normal KAPLAY component system
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
---
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
npm install kaplay-ui
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Usage
|
|
22
|
+
## 📦 Installation
|
|
26
23
|
|
|
27
|
-
|
|
24
|
+
You can install the plugin using your preferred package manager:
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
```javascript
|
|
32
|
-
import {} from "kaplay-ui/inputs";
|
|
26
|
+
```sh
|
|
27
|
+
npm install kaplay-ui
|
|
33
28
|
```
|
|
34
29
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
To make a checkbox, one must use the exported <code>makeCheckbox()</code> function.
|
|
38
|
-
|
|
39
|
-
##### Example
|
|
40
|
-
|
|
41
|
-
An example usage of a checkbox.
|
|
42
|
-
|
|
43
|
-
```javascript
|
|
44
|
-
import kaplay from "kaplay";
|
|
45
|
-
import "kaplay/global";
|
|
46
|
-
|
|
47
|
-
import { makeCheckbox } from "kaplay-ui/inputs";
|
|
48
|
-
|
|
49
|
-
kaplay();
|
|
30
|
+
or:
|
|
50
31
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
add(checkBox);
|
|
32
|
+
```sh
|
|
33
|
+
pnpm add kaplay-ui
|
|
54
34
|
```
|
|
55
35
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
A cehckbox has the following state:
|
|
59
|
-
|
|
60
|
-
| state | Type | Default | State change by |
|
|
61
|
-
| --------- | --------- | ------- | ----------------- |
|
|
62
|
-
| `checked` | `boolean` | false | Click on checkbox |
|
|
63
|
-
|
|
64
|
-
##### Parameters
|
|
65
|
-
|
|
66
|
-
A checkbox can take the following parameters:
|
|
67
|
-
|
|
68
|
-
| Parameter | Type | Default | Required | Description |
|
|
69
|
-
| --------- | -------- | ------- | -------- | ------------------- |
|
|
70
|
-
| `x` | `number` | 0 | ❌ No | Checkbox x position |
|
|
71
|
-
| `y` | `number` | 0 | ❌ No | Checkbox x position |
|
|
72
|
-
| `width` | `number` | 25 | ❌ No | Checkbox width |
|
|
73
|
-
| `height` | `number` | 25 | ❌ No | Checkbox height |
|
|
36
|
+
or:
|
|
74
37
|
|
|
75
|
-
|
|
38
|
+
yarn add kaplay-ui
|
|
76
39
|
|
|
77
|
-
|
|
40
|
+
````
|
|
78
41
|
|
|
79
|
-
|
|
42
|
+
---
|
|
80
43
|
|
|
81
|
-
|
|
44
|
+
## 🚀 Usage
|
|
45
|
+
Import and register the plugin when initializing your KAPLAY game:
|
|
82
46
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
```javascript
|
|
47
|
+
```js
|
|
86
48
|
import kaplay from "kaplay";
|
|
87
|
-
import "kaplay
|
|
88
|
-
|
|
89
|
-
import { makeSwitch } from "kaplay-ui/inputs";
|
|
49
|
+
import kaplayUI from "kaplay-ui";
|
|
90
50
|
|
|
91
|
-
kaplay(
|
|
51
|
+
const k = kaplay({
|
|
52
|
+
plugins: [kaplayUI],
|
|
53
|
+
});
|
|
54
|
+
````
|
|
92
55
|
|
|
93
|
-
|
|
56
|
+
You now have access to the UI helpers via your `k` instance:
|
|
94
57
|
|
|
95
|
-
|
|
58
|
+
```js
|
|
59
|
+
const btn = k.addTextButton("Play", 200, 100);
|
|
96
60
|
```
|
|
97
61
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
A cehckbox has the following state:
|
|
101
|
-
|
|
102
|
-
| state | Type | Default | State change by |
|
|
103
|
-
| ---------- | --------- | ------- | --------------- |
|
|
104
|
-
| `switched` | `boolean` | false | Click on switch |
|
|
105
|
-
|
|
106
|
-
##### Parameters
|
|
107
|
-
|
|
108
|
-
A switch can take the following parameters:
|
|
62
|
+
---
|
|
109
63
|
|
|
110
|
-
|
|
111
|
-
| --------- | -------- | ------- | -------- | ----------------- |
|
|
112
|
-
| `x` | `number` | 0 | ❌ No | Switch x position |
|
|
113
|
-
| `y` | `number` | 0 | ❌ No | Switch x position |
|
|
114
|
-
| `width` | `number` | 50 | ❌ No | Switch width |
|
|
115
|
-
| `height` | `number` | 25 | ❌ No | Switch height |
|
|
64
|
+
## 🔘 `addTextButton()`
|
|
116
65
|
|
|
117
|
-
|
|
66
|
+
Creates a button-like GameObj with centered text and some convenient defaults.
|
|
118
67
|
|
|
119
|
-
|
|
68
|
+
### **Signature**
|
|
120
69
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
```javascript
|
|
128
|
-
import kaplay from "kaplay";
|
|
129
|
-
import "kaplay/global";
|
|
130
|
-
|
|
131
|
-
import { makeTextButton } from "kaplay-ui/inputs";
|
|
132
|
-
|
|
133
|
-
kaplay();
|
|
134
|
-
|
|
135
|
-
const txtBtn = makeTextButton("Start");
|
|
136
|
-
|
|
137
|
-
add(txtBtn);
|
|
70
|
+
```ts
|
|
71
|
+
addTextButton(
|
|
72
|
+
txt?: string,
|
|
73
|
+
width?: number,
|
|
74
|
+
height?: number
|
|
75
|
+
): GameObj
|
|
138
76
|
```
|
|
139
77
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
A text button can take the following parameters:
|
|
78
|
+
### **Default values**
|
|
143
79
|
|
|
144
|
-
| Parameter
|
|
145
|
-
|
|
|
146
|
-
| `
|
|
147
|
-
| `
|
|
148
|
-
| `
|
|
149
|
-
| `width` | `number` | 100 | ❌ No | Button width |
|
|
150
|
-
| `height` | `number` | 50 | ❌ No | Button height |
|
|
151
|
-
| `btnRadius` | `number` | 8 | ❌ No | Button radius |
|
|
152
|
-
| `btnOutline` | `number` | 1 | ❌ No | Button outline |
|
|
153
|
-
| `txtSize` | `number` | 15 | ❌ No | Text size |
|
|
80
|
+
| Parameter | Default |
|
|
81
|
+
| --------- | ---------- |
|
|
82
|
+
| `txt` | `"Button"` |
|
|
83
|
+
| `width` | `200` |
|
|
84
|
+
| `height` | `100` |
|
|
154
85
|
|
|
155
|
-
|
|
86
|
+
### **Default styling**
|
|
156
87
|
|
|
157
|
-
|
|
88
|
+
When created, the button includes:
|
|
158
89
|
|
|
159
|
-
|
|
90
|
+
- `k.outline(3)`
|
|
91
|
+
- `k.pos(0, 0)`
|
|
92
|
+
- `k.anchor("topleft")`
|
|
93
|
+
- `k.area()` — for click/hover detection
|
|
160
94
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
An example usage of a toggle.
|
|
164
|
-
|
|
165
|
-
```javascript
|
|
166
|
-
import kaplay from "kaplay";
|
|
167
|
-
import "kaplay/global";
|
|
95
|
+
### **Example**
|
|
168
96
|
|
|
169
|
-
|
|
97
|
+
```js
|
|
98
|
+
// Default button
|
|
99
|
+
const btn1 = k.addTextButton();
|
|
170
100
|
|
|
171
|
-
|
|
101
|
+
// Custom label
|
|
102
|
+
const btn2 = k.addTextButton("Start");
|
|
172
103
|
|
|
173
|
-
|
|
104
|
+
// Custom size
|
|
105
|
+
const btn3 = k.addTextButton("Start", 150, 75);
|
|
174
106
|
|
|
175
|
-
|
|
107
|
+
// Add interactivity
|
|
108
|
+
btn2.onClick(() => {
|
|
109
|
+
console.log("Button clicked!");
|
|
110
|
+
});
|
|
176
111
|
```
|
|
177
112
|
|
|
178
|
-
|
|
113
|
+
---
|
|
179
114
|
|
|
180
|
-
|
|
115
|
+
## 🧱 How It Works
|
|
181
116
|
|
|
182
|
-
|
|
183
|
-
| ---------- | --------- | ------- | -------- | ------------------------------ |
|
|
184
|
-
| `x` | `number` | 0 | ❌ No | x position |
|
|
185
|
-
| `y` | `number` | 0 | ❌ No | y position |
|
|
186
|
-
| `width` | `number` | 400 | ❌ No | width |
|
|
187
|
-
| `txtSize` | `number` | 15 | ❌ No | Input text size |
|
|
188
|
-
| `pad` | `number` | 10 | ❌ No | Padding |
|
|
189
|
-
| `hasFocus` | `boolean` | true | ❌ No | If text input has focus or not |
|
|
117
|
+
Internally, the plugin creates a GameObj composed of:
|
|
190
118
|
|
|
191
|
-
|
|
119
|
+
- A rectangle-like button base
|
|
120
|
+
- Centered text using KAPLAY's built‑in text component
|
|
121
|
+
- A combined area for input events
|
|
192
122
|
|
|
193
|
-
|
|
123
|
+
This keeps your UI elements fully compatible with:
|
|
194
124
|
|
|
195
|
-
|
|
125
|
+
- `onClick()`
|
|
126
|
+
- `onHover()`
|
|
127
|
+
- `color()`, `scale()`, etc.
|
|
128
|
+
- Layout within scenes or parent objects
|
|
196
129
|
|
|
197
|
-
|
|
130
|
+
---
|
|
198
131
|
|
|
199
|
-
|
|
132
|
+
## 📱 Mobile‑Friendly UI Demo
|
|
200
133
|
|
|
201
|
-
|
|
202
|
-
import kaplay from "kaplay";
|
|
203
|
-
import "kaplay/global";
|
|
204
|
-
|
|
205
|
-
import { makeToggle } from "kaplay-ui/inputs";
|
|
206
|
-
|
|
207
|
-
kaplay();
|
|
134
|
+
This example shows how to build a touch‑friendly UI using `addTextButton()` on mobile devices. It uses responsive scaling and KAPLAY’s `stretch` and `letterbox` features to adapt to different screen sizes.
|
|
208
135
|
|
|
209
|
-
|
|
136
|
+
### **Example**
|
|
210
137
|
|
|
211
|
-
|
|
138
|
+
```js
|
|
139
|
+
import kaplay from "kaplay";
|
|
140
|
+
import kaplayUI from "kaplay-ui";
|
|
141
|
+
|
|
142
|
+
const k = kaplay({
|
|
143
|
+
width: 480, // required when using letterbox/stretch
|
|
144
|
+
height: 270,
|
|
145
|
+
background: [25, 25, 25],
|
|
146
|
+
plugins: [kaplayUI],
|
|
147
|
+
|
|
148
|
+
stretch: true, // resize canvas on mobile
|
|
149
|
+
letterbox: true, // preserve aspect ratio
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
function uiScale() {
|
|
153
|
+
return Math.min(k.width() / 400, 1.4);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function centerX(width) {
|
|
157
|
+
return k.center().x - width / 2;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
k.scene("mobile-menu", () => {
|
|
161
|
+
const scale = uiScale();
|
|
162
|
+
|
|
163
|
+
k.add([
|
|
164
|
+
k.text("Mobile Menu", { size: 36 * scale }),
|
|
165
|
+
k.anchor("center"),
|
|
166
|
+
k.pos(k.center().x, 70 * scale),
|
|
167
|
+
]);
|
|
168
|
+
|
|
169
|
+
const btnWidth = 260 * scale;
|
|
170
|
+
const btnHeight = 90 * scale;
|
|
171
|
+
|
|
172
|
+
const startBtn = k.addTextButton("Start", btnWidth, btnHeight);
|
|
173
|
+
startBtn.pos = k.vec2(centerX(btnWidth), 150 * scale);
|
|
174
|
+
startBtn.onClick(() => k.go("mobile-game"));
|
|
175
|
+
startBtn.onHover(() => (startBtn.color = k.rgb(140, 220, 140)));
|
|
176
|
+
startBtn.onHoverEnd(() => (startBtn.color = k.WHITE));
|
|
177
|
+
|
|
178
|
+
const settingsBtn = k.addTextButton("Settings", btnWidth, btnHeight);
|
|
179
|
+
settingsBtn.pos = k.vec2(centerX(btnWidth), 280 * scale);
|
|
180
|
+
settingsBtn.onClick(() => k.go("settings"));
|
|
181
|
+
settingsBtn.onHover(() => (settingsBtn.color = k.rgb(140, 160, 240)));
|
|
182
|
+
settingsBtn.onHoverEnd(() => (settingsBtn.color = k.WHITE));
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
k.scene("mobile-game", () => {
|
|
186
|
+
const scale = uiScale();
|
|
187
|
+
|
|
188
|
+
k.add([
|
|
189
|
+
k.text("Game Scene", { size: 28 * scale }),
|
|
190
|
+
k.anchor("center"),
|
|
191
|
+
k.pos(k.center().x, 90 * scale),
|
|
192
|
+
]);
|
|
193
|
+
|
|
194
|
+
const backBtn = k.addTextButton("Back", 200 * scale, 80 * scale);
|
|
195
|
+
backBtn.pos = k.vec2(centerX(200 * scale), k.height() - 120 * scale);
|
|
196
|
+
backBtn.onClick(() => k.go("mobile-menu"));
|
|
197
|
+
backBtn.onHover(() => (backBtn.scale = 1.1 * scale));
|
|
198
|
+
backBtn.onHoverEnd(() => (backBtn.scale = scale));
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
k.scene("settings", () => {
|
|
202
|
+
const scale = uiScale();
|
|
203
|
+
|
|
204
|
+
k.add([
|
|
205
|
+
k.text("Settings", { size: 32 * scale }),
|
|
206
|
+
k.anchor("center"),
|
|
207
|
+
k.pos(k.center().x, 70 * scale),
|
|
208
|
+
]);
|
|
209
|
+
|
|
210
|
+
const backBtn = k.addTextButton("Back", 200 * scale, 80 * scale);
|
|
211
|
+
backBtn.pos = k.vec2(centerX(200 * scale), k.height() - 140 * scale);
|
|
212
|
+
backBtn.onClick(() => k.go("mobile-menu"));
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
k.go("mobile-menu");
|
|
212
216
|
```
|
|
213
217
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
A cehckbox has the following state:
|
|
217
|
-
|
|
218
|
-
| state | Type | Default | State change by |
|
|
219
|
-
| --------- | --------- | ------- | --------------- |
|
|
220
|
-
| `toggled` | `boolean` | false | Click on toggle |
|
|
221
|
-
|
|
222
|
-
##### Parameters
|
|
223
|
-
|
|
224
|
-
A toggle can take the following parameters:
|
|
225
|
-
|
|
226
|
-
| Parameter | Type | Default | Required | Description |
|
|
227
|
-
| --------- | -------- | ------- | -------- | ----------------- |
|
|
228
|
-
| `x` | `number` | 0 | ❌ No | Toggle x position |
|
|
229
|
-
| `y` | `number` | 0 | ❌ No | Toggle y position |
|
|
230
|
-
| `width` | `number` | 50 | ❌ No | Toggle width |
|
|
231
|
-
| `height` | `number` | 25 | ❌ No | Toggle height |
|
|
232
|
-
|
|
233
|
-
<br>
|
|
234
|
-
|
|
235
|
-
## License
|
|
236
|
-
|
|
237
|
-
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
218
|
+
### ✔ Features demonstrated
|
|
238
219
|
|
|
239
|
-
|
|
220
|
+
- Responsive UI scaling
|
|
221
|
+
- Touch‑friendly hit areas
|
|
222
|
+
- Hover animations for mobile
|
|
223
|
+
- Auto‑centered vertical layout
|
|
224
|
+
- Scene navigation
|
|
240
225
|
|
|
241
|
-
|
|
226
|
+
---
|
|
242
227
|
|
|
243
|
-
|
|
228
|
+
## 📄 License
|
|
244
229
|
|
|
245
|
-
|
|
230
|
+
MIT — free for personal and commercial use.
|
package/ROADMAP.md
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# 📘 **KAPLAY‑UI — Updated Development Roadmap (v1)**
|
|
2
|
+
|
|
3
|
+
_(Reflecting current progress as of Phase 2 Step 2.4)_
|
|
4
|
+
|
|
5
|
+
This roadmap tracks the incremental development of the **Container** UI element and the overall plugin architecture for `kaplay-ui`.
|
|
6
|
+
It replaces the old roadmap and reflects the precise, step-based structure we are now following.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# 🌱 **Phase 0 — Planning & API Definition (Completed)**
|
|
11
|
+
|
|
12
|
+
### **0.1 – Folder Structure Setup** ✔
|
|
13
|
+
|
|
14
|
+
- Create `src/components/container/` directory
|
|
15
|
+
- Add `index.ts`, `container.types.ts`, `container.logic.ts`, `container.styles.ts`
|
|
16
|
+
|
|
17
|
+
### **0.2 – Public API Definition** ✔
|
|
18
|
+
|
|
19
|
+
- Define developer experience (“DX sentence”)
|
|
20
|
+
- Draft ideal usage examples
|
|
21
|
+
- Decide initial required options (`width`, `height`)
|
|
22
|
+
- Decide return type (GameObj + UI helpers)
|
|
23
|
+
- Write full API Contract
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
# 🧱 **Phase 1 — Minimal Functional Container (Completed)**
|
|
28
|
+
|
|
29
|
+
### **1.1 – Type Definitions** ✔
|
|
30
|
+
|
|
31
|
+
- Create `UIContainerOptions`
|
|
32
|
+
- Create `UIContainerReturn`
|
|
33
|
+
|
|
34
|
+
### **1.2 – Factory Scaffolding** ✔
|
|
35
|
+
|
|
36
|
+
- Add `createContainer()` factory
|
|
37
|
+
- Export from plugin via `k.addContainer()`
|
|
38
|
+
- Add placeholder logic/style hookups
|
|
39
|
+
|
|
40
|
+
### **1.3 – Minimal Functional Implementation** ✔
|
|
41
|
+
|
|
42
|
+
- Create Kaplay rect
|
|
43
|
+
- Apply width/height
|
|
44
|
+
- Return real container GameObj
|
|
45
|
+
- Implement minimal `addChild()` (no positioning yet)
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
# 🎨 **Phase 2 — Core Container Functionality (In Progress)**
|
|
50
|
+
|
|
51
|
+
## ✔ Completed Steps
|
|
52
|
+
|
|
53
|
+
### **2.1 – Add Basic Styling Support** ✔
|
|
54
|
+
|
|
55
|
+
- Introduce `defaultContainerStyles`
|
|
56
|
+
- Add `container.styles` field
|
|
57
|
+
- Add placeholder `setStyle()` method
|
|
58
|
+
|
|
59
|
+
### **2.2 – Add Anchor Support (Scaffolding)** ✔
|
|
60
|
+
|
|
61
|
+
- Add `anchor?: string` to options
|
|
62
|
+
- Add `container.anchor` property
|
|
63
|
+
- Add `setAnchor()` method
|
|
64
|
+
- Add `applyAnchor()` placeholder
|
|
65
|
+
- Call anchor logic in `initContainerLogic()`
|
|
66
|
+
|
|
67
|
+
## 🔄 **Current Step (Next to Implement)**
|
|
68
|
+
|
|
69
|
+
### **2.3 – Apply Styles & Anchors Visually (NOT STARTED YET)**
|
|
70
|
+
|
|
71
|
+
This will include:
|
|
72
|
+
|
|
73
|
+
- Applying background color to the rect
|
|
74
|
+
- Applying borderWidth, borderColor, radius
|
|
75
|
+
- Applying padding to internal GameObj positioning
|
|
76
|
+
- Applying anchor visually via Kaplay’s `.anchor()` component
|
|
77
|
+
- Ensuring container size + style reflect options
|
|
78
|
+
|
|
79
|
+
## ⏳ **Upcoming Step (Depends on Step 2.3)**
|
|
80
|
+
|
|
81
|
+
### **2.4 – Implement Basic Child Positioning & Padding**
|
|
82
|
+
|
|
83
|
+
- Children positioned relative to container origin
|
|
84
|
+
- Apply padding offsets
|
|
85
|
+
- Children follow container movement
|
|
86
|
+
- Simple update loop to sync child positions
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
# 📦 **Phase 3 — Layout Engine (Future)**
|
|
91
|
+
|
|
92
|
+
### **3.1 – Layout Modes: none, vertical, horizontal**
|
|
93
|
+
|
|
94
|
+
### **3.2 – Spacing support**
|
|
95
|
+
|
|
96
|
+
### **3.3 – Auto-size based on children**
|
|
97
|
+
|
|
98
|
+
### **3.4 – Alignment (start, center, end)**
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
# ✨ **Phase 4 — Advanced Features (Future)**
|
|
103
|
+
|
|
104
|
+
### **4.1 – Borders, shadows, hover states**
|
|
105
|
+
|
|
106
|
+
### **4.2 – Themes & preset styles**
|
|
107
|
+
|
|
108
|
+
### **4.3 – z-index / UI layers**
|
|
109
|
+
|
|
110
|
+
### **4.4 – Optional clipping / scroll masking**
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
# 📚 **Phase 5 — Docs & Testing**
|
|
115
|
+
|
|
116
|
+
### **5.1 – Full README examples**
|
|
117
|
+
|
|
118
|
+
### **5.2 – API documentation**
|
|
119
|
+
|
|
120
|
+
### **5.3 – Unit tests for container behavior**
|
|
121
|
+
|
|
122
|
+
### **5.4 – Interactive demo in `/test/game.ts`**
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
# 🚀 **Phase 6 — v0.1.0 Release**
|
|
127
|
+
|
|
128
|
+
### **6.1 – Code cleanup & final polish**
|
|
129
|
+
|
|
130
|
+
### **6.2 – Publish `kaplay-ui` to npm**
|
|
131
|
+
|
|
132
|
+
### **6.3 – Announce first usable Container component**
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
# 🧭 **Where We Are Right Now**
|
|
137
|
+
|
|
138
|
+
As of your last message, you are here:
|
|
139
|
+
|
|
140
|
+
### ⭐ **Phase 2 → Step 2.4 complete**
|
|
141
|
+
|
|
142
|
+
Meaning the next step to do together is:
|
|
143
|
+
|
|
144
|
+
# 👉 **Phase 2 Step 3 — Apply Styles & Anchors Visually**
|
|
145
|
+
|
|
146
|
+
This is where your container becomes:
|
|
147
|
+
|
|
148
|
+
- visually styled
|
|
149
|
+
- anchored correctly
|
|
150
|
+
- padded properly
|
|
151
|
+
- a _real_ UI element, not just a rectangle
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
# If you'd like, I can now:
|
|
156
|
+
|
|
157
|
+
- Create a “live” ROADMAP.md file matching this structure
|
|
158
|
+
- Move you into Phase 2 Step 3
|
|
159
|
+
- Review your existing code to ensure everything matches the roadmap
|
|
160
|
+
- Add future sections (Buttons, Sliders, Text, etc.)
|
|
161
|
+
|
|
162
|
+
Just tell me what you'd like to do next.
|
|
Binary file
|
package/index.html
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>KAPLAY Plugin Template (TypeScript)</title>
|
|
7
|
+
</head>
|
|
8
|
+
|
|
9
|
+
<body>
|
|
10
|
+
<script src="./test/game.ts" type="module"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kaplay-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-alpha.1",
|
|
4
4
|
"description": "UI components for KAPLAY",
|
|
5
|
-
"
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "vite dev",
|
|
9
|
+
"build": "vite build"
|
|
10
|
+
},
|
|
6
11
|
"repository": {
|
|
7
12
|
"type": "git",
|
|
8
13
|
"url": "git+https://github.com/jbakchr/kaplay-ui.git"
|
|
@@ -19,7 +24,11 @@
|
|
|
19
24
|
},
|
|
20
25
|
"homepage": "https://github.com/jbakchr/kaplay-ui#readme",
|
|
21
26
|
"dependencies": {
|
|
22
|
-
"kaplay": "^3001.0.
|
|
27
|
+
"kaplay": "^3001.0.19"
|
|
23
28
|
},
|
|
24
|
-
"
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/node": "^25.5.0",
|
|
31
|
+
"vite": "^8.0.2",
|
|
32
|
+
"vite-plugin-dts": "^4.5.4"
|
|
33
|
+
}
|
|
25
34
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./text-button";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { KAPLAYCtx } from "kaplay";
|
|
2
|
+
|
|
3
|
+
import { makeButtonText } from "../../texts/index";
|
|
4
|
+
|
|
5
|
+
export function createTextButton(
|
|
6
|
+
k: KAPLAYCtx,
|
|
7
|
+
txt: string,
|
|
8
|
+
width: number,
|
|
9
|
+
height: number,
|
|
10
|
+
) {
|
|
11
|
+
const btn = k.add([
|
|
12
|
+
k.rect(width, height),
|
|
13
|
+
k.outline(3),
|
|
14
|
+
k.pos(0, 0),
|
|
15
|
+
k.anchor("topleft"),
|
|
16
|
+
k.area(),
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
const btnTxt = makeButtonText(k, btn, txt);
|
|
20
|
+
|
|
21
|
+
btn.add(btnTxt);
|
|
22
|
+
|
|
23
|
+
return btn;
|
|
24
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/components/container/container.logic.ts
|
|
2
|
+
|
|
3
|
+
import type { KAPLAYCtx } from "kaplay";
|
|
4
|
+
import type { UIContainerOptions, UIContainerReturn } from "./container.types";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Placeholder for the internal container logic.
|
|
8
|
+
* Will create the actual Kaplay GameObj in Phase 1 Step 3.
|
|
9
|
+
*/
|
|
10
|
+
export function initContainerLogic(
|
|
11
|
+
_k: KAPLAYCtx,
|
|
12
|
+
container: UIContainerReturn,
|
|
13
|
+
opts: UIContainerOptions,
|
|
14
|
+
) {
|
|
15
|
+
console.warn("initContainerLogic() placeholder running.");
|
|
16
|
+
|
|
17
|
+
// NEW: anchor preparation
|
|
18
|
+
applyAnchor(container, opts);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Placeholder function for applying anchor behavior.
|
|
23
|
+
*
|
|
24
|
+
* The real implementation will come in Phase 2 Step 3.
|
|
25
|
+
*/
|
|
26
|
+
export function applyAnchor(
|
|
27
|
+
_container: UIContainerReturn,
|
|
28
|
+
_opts: UIContainerOptions,
|
|
29
|
+
) {
|
|
30
|
+
console.warn("applyAnchor() not implemented yet.");
|
|
31
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// src/components/container/container.styles.ts
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Default styles for all UI Containers.
|
|
5
|
+
*
|
|
6
|
+
* These values will later be applied visually (Phase 2 Step 3),
|
|
7
|
+
* but for now they simply exist as the container's internal style model.
|
|
8
|
+
*/
|
|
9
|
+
export const defaultContainerStyles = {
|
|
10
|
+
backgroundColor: "rgba(0, 0, 0, 0.4)", // translucent dark background
|
|
11
|
+
borderColor: "rgba(255, 255, 255, 0.1)", // subtle border
|
|
12
|
+
borderWidth: 0,
|
|
13
|
+
radius: 0,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Placeholder: in the future, this will apply the
|
|
18
|
+
* default styles to the actual Kaplay GameObj.
|
|
19
|
+
*/
|
|
20
|
+
export function applyDefaultContainerStyles(_container: any) {
|
|
21
|
+
// Implementation will come later in Phase 2 Step 3.
|
|
22
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// src/components/container/container.types.ts
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* UIContainerOptions (initial minimal version)
|
|
5
|
+
*
|
|
6
|
+
* Only width and height are required at this stage.
|
|
7
|
+
*
|
|
8
|
+
* Phase 2 Step 3 introduces padding:
|
|
9
|
+
*
|
|
10
|
+
* padding?: number
|
|
11
|
+
*
|
|
12
|
+
* Padding is optional. Default = 0.
|
|
13
|
+
* Padding represents empty space INSIDE the container.
|
|
14
|
+
* Children added to the container are offset by the padding
|
|
15
|
+
* on all sides (top, left, right, bottom).
|
|
16
|
+
*
|
|
17
|
+
* Example:
|
|
18
|
+
* const panel = k.addContainer({
|
|
19
|
+
* width: 300,
|
|
20
|
+
* height: 200,
|
|
21
|
+
* padding: 16,
|
|
22
|
+
* });
|
|
23
|
+
*/
|
|
24
|
+
export interface UIContainerOptions {
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
|
|
28
|
+
anchor?: string; // "center" and so on
|
|
29
|
+
|
|
30
|
+
// Added in Phase 2 Step 3:
|
|
31
|
+
padding?: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* UIContainerReturn (initial minimal version)
|
|
36
|
+
*
|
|
37
|
+
* The container will eventually merge this with a Kaplay GameObj.
|
|
38
|
+
*/
|
|
39
|
+
export interface UIContainerReturn {
|
|
40
|
+
uiWidth: number;
|
|
41
|
+
uiHeight: number;
|
|
42
|
+
addChild(child: any): void;
|
|
43
|
+
anchor: string;
|
|
44
|
+
setAnchor(anchor: string): void;
|
|
45
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// src/components/container/index.ts
|
|
2
|
+
|
|
3
|
+
import type { KAPLAYCtx } from "kaplay";
|
|
4
|
+
import type { UIContainerOptions } from "./container.types";
|
|
5
|
+
import { initContainerLogic } from "./container.logic";
|
|
6
|
+
import {
|
|
7
|
+
defaultContainerStyles,
|
|
8
|
+
applyDefaultContainerStyles,
|
|
9
|
+
} from "./container.styles";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Factory function for creating a UI Container.
|
|
13
|
+
* Phase 2 Step 1: Add styling scaffolding.
|
|
14
|
+
*/
|
|
15
|
+
export function createContainer(k: KAPLAYCtx, opts: UIContainerOptions) {
|
|
16
|
+
const container = {
|
|
17
|
+
uiWidth: opts.width,
|
|
18
|
+
uiHeight: opts.height,
|
|
19
|
+
|
|
20
|
+
addChild: (_child: any) => {
|
|
21
|
+
console.warn("addChild() not implemented yet.");
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
styles: {
|
|
25
|
+
...defaultContainerStyles,
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
setStyle(_newStyles: any) {
|
|
29
|
+
console.warn("setStyle() not implemented yet.");
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
// NEW: store anchor
|
|
33
|
+
anchor: opts.anchor ?? "topleft",
|
|
34
|
+
|
|
35
|
+
// NEW: runtime anchor setter
|
|
36
|
+
setAnchor(newAnchor: string) {
|
|
37
|
+
this.anchor = newAnchor;
|
|
38
|
+
console.warn("setAnchor() not implemented yet.");
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// placeholder logic and style application
|
|
43
|
+
initContainerLogic(k, container, opts);
|
|
44
|
+
applyDefaultContainerStyles(container);
|
|
45
|
+
|
|
46
|
+
return container as any;
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./buttons";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./text-button/text-button";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
GameObj,
|
|
3
|
+
KAPLAYCtx,
|
|
4
|
+
PosComp,
|
|
5
|
+
RectComp,
|
|
6
|
+
OutlineComp,
|
|
7
|
+
AnchorComp,
|
|
8
|
+
AreaComp,
|
|
9
|
+
} from "kaplay";
|
|
10
|
+
|
|
11
|
+
export function makeButtonText(
|
|
12
|
+
k: KAPLAYCtx,
|
|
13
|
+
btn: GameObj<PosComp | RectComp | OutlineComp | AnchorComp | AreaComp>,
|
|
14
|
+
txt: string,
|
|
15
|
+
) {
|
|
16
|
+
const btnTxt = k.make([
|
|
17
|
+
k.text(txt),
|
|
18
|
+
k.color(0, 0, 0),
|
|
19
|
+
k.pos(btn.width / 2, btn.height / 2),
|
|
20
|
+
k.anchor("center"),
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
return btnTxt;
|
|
24
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { KAPLAYCtx, GameObj } from "kaplay";
|
|
2
|
+
|
|
3
|
+
import { createTextButton } from "./components";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* # KAPLAY UI Plugin
|
|
7
|
+
* _Add UI Game Objects to your game._
|
|
8
|
+
*
|
|
9
|
+
* ## Features
|
|
10
|
+
* - Text Button (`addTextButton()`)
|
|
11
|
+
*/
|
|
12
|
+
export default function kaplayUI(k: KAPLAYCtx) {
|
|
13
|
+
return {
|
|
14
|
+
/**
|
|
15
|
+
* # Text button
|
|
16
|
+
* Creates a clickable game object containing a button with centered text.
|
|
17
|
+
*
|
|
18
|
+
* This helper provides sensible defaults for size, layout, and styling so you can
|
|
19
|
+
* quickly add UI buttons to your KAPLAY game.
|
|
20
|
+
*
|
|
21
|
+
* ## Default Parameter Values
|
|
22
|
+
* | Name | Default |
|
|
23
|
+
* |:---------|:-------------|
|
|
24
|
+
* | `txt` | `"Button"` |
|
|
25
|
+
* | `width` | `200` |
|
|
26
|
+
* | `height` | `100` |
|
|
27
|
+
*
|
|
28
|
+
* ## Default Styling
|
|
29
|
+
* The button object is created with:
|
|
30
|
+
* - `k.outline(3)`
|
|
31
|
+
* - `k.pos(0, 0)`
|
|
32
|
+
* - `k.anchor("topleft")`
|
|
33
|
+
* - `k.area()`
|
|
34
|
+
*
|
|
35
|
+
* @param {string} [txt="Button"]
|
|
36
|
+
* The text label displayed at the center of the button.
|
|
37
|
+
*
|
|
38
|
+
* @param {number} [width=200]
|
|
39
|
+
* Width of the button in pixels.
|
|
40
|
+
*
|
|
41
|
+
* @param {number} [height=100]
|
|
42
|
+
* Height of the button in pixels.
|
|
43
|
+
*
|
|
44
|
+
* @returns {GameObj}
|
|
45
|
+
* A KAPLAY Game Object representing the button with centered text.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* const btn = addTextButton();
|
|
49
|
+
* const playBtn = addTextButton("Play");
|
|
50
|
+
* const wideBtn = addTextButton("Play", 150);
|
|
51
|
+
* const smallBtn = addTextButton("Play", 150, 75);
|
|
52
|
+
*/
|
|
53
|
+
addTextButton: (
|
|
54
|
+
txt: string = "Button",
|
|
55
|
+
width: number = 200,
|
|
56
|
+
height: number = 100,
|
|
57
|
+
): GameObj => createTextButton(k, txt, width, height),
|
|
58
|
+
};
|
|
59
|
+
}
|
package/test/game.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
/* Bundler mode */
|
|
9
|
+
"moduleResolution": "bundler",
|
|
10
|
+
"allowImportingTsExtensions": true,
|
|
11
|
+
"isolatedModules": true,
|
|
12
|
+
"moduleDetection": "force",
|
|
13
|
+
"noEmit": true,
|
|
14
|
+
/* Linting */
|
|
15
|
+
"strict": true,
|
|
16
|
+
"noUnusedLocals": true,
|
|
17
|
+
"noUnusedParameters": true,
|
|
18
|
+
"noFallthroughCasesInSwitch": true
|
|
19
|
+
},
|
|
20
|
+
"include": ["src"]
|
|
21
|
+
}
|
package/vite.config.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { resolve } from "path";
|
|
2
|
+
import { defineConfig } from "vite";
|
|
3
|
+
import dts from "vite-plugin-dts";
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
build: {
|
|
7
|
+
lib: {
|
|
8
|
+
entry: resolve(__dirname, "src/index.ts"),
|
|
9
|
+
name: "uiPlugin",
|
|
10
|
+
fileName: "uiplugin",
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
plugins: [dts({ rollupTypes: true, tsconfigPath: "./tsconfig.json" })],
|
|
14
|
+
});
|
package/assets/cb-icon.png
DELETED
|
Binary file
|
package/inputs/index.js
DELETED
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
import "kaplay/global";
|
|
2
|
-
|
|
3
|
-
import cbIcon from "../assets/cb-icon.png";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Makes button with centered text
|
|
7
|
-
* @param {string} txt - Button text to display
|
|
8
|
-
* @param {number} x - The x postion to set (default is 0).
|
|
9
|
-
* @param {number} y - The x postion to set (default is 0)
|
|
10
|
-
* @param {number} width - Width of button (default is 100)
|
|
11
|
-
* @param {number} height - Height of button (default is 50)
|
|
12
|
-
* @param {number} btnRadius - Border radius of button (default is 8)
|
|
13
|
-
* @param {number} btnOutline - Button outline (default is 1)
|
|
14
|
-
* @param {number} txtSize - Text size of button (default is 15)
|
|
15
|
-
* @returns {GameObj}
|
|
16
|
-
*/
|
|
17
|
-
export const makeTextButton = (
|
|
18
|
-
txt,
|
|
19
|
-
x = 0,
|
|
20
|
-
y = 0,
|
|
21
|
-
width = 100,
|
|
22
|
-
height = 50,
|
|
23
|
-
btnRadius = 8,
|
|
24
|
-
btnOutline = 1,
|
|
25
|
-
txtSize = 15
|
|
26
|
-
) => {
|
|
27
|
-
// Make button
|
|
28
|
-
const btn = make([
|
|
29
|
-
rect(width, height, { radius: btnRadius }),
|
|
30
|
-
pos(x, y),
|
|
31
|
-
area(),
|
|
32
|
-
scale(1),
|
|
33
|
-
outline(btnOutline),
|
|
34
|
-
color(255, 255, 255),
|
|
35
|
-
]);
|
|
36
|
-
|
|
37
|
-
// Make button text
|
|
38
|
-
const btnText = make([
|
|
39
|
-
text(txt, { size: txtSize }),
|
|
40
|
-
pos(width / 2, height / 2),
|
|
41
|
-
anchor("center"),
|
|
42
|
-
color(0, 0, 0),
|
|
43
|
-
]);
|
|
44
|
-
|
|
45
|
-
// Add text to button
|
|
46
|
-
btn.add(btnText);
|
|
47
|
-
|
|
48
|
-
return btn;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Makes toggle
|
|
53
|
-
* @param {number} x - The x postion to set (default is 0)
|
|
54
|
-
* @param {number} y - The x postion to set (default is 0)
|
|
55
|
-
* @param {number} width - Toggle width (default is 50)
|
|
56
|
-
* @param {number} height - Toggle height (default is 25)
|
|
57
|
-
* @returns {GameObj}
|
|
58
|
-
*/
|
|
59
|
-
export const makeToggle = (x = 0, y = 0, width = 50, height = 25) => {
|
|
60
|
-
// Toggle base
|
|
61
|
-
const toggle = make([
|
|
62
|
-
rect(width, height, { radius: height / 2 }),
|
|
63
|
-
pos(x, y),
|
|
64
|
-
color(169, 169, 169),
|
|
65
|
-
area(),
|
|
66
|
-
{
|
|
67
|
-
toggled: false,
|
|
68
|
-
},
|
|
69
|
-
]);
|
|
70
|
-
|
|
71
|
-
// Toggle button
|
|
72
|
-
const toggleBtn = make([
|
|
73
|
-
circle(height * 0.4),
|
|
74
|
-
color(WHITE),
|
|
75
|
-
pos(height / 2, height / 2),
|
|
76
|
-
]);
|
|
77
|
-
|
|
78
|
-
// Add button to toggleBase
|
|
79
|
-
toggle.add(toggleBtn);
|
|
80
|
-
|
|
81
|
-
toggle.onClick(() => {
|
|
82
|
-
if (toggle.toggled) {
|
|
83
|
-
toggle.use(color(169, 169, 169));
|
|
84
|
-
toggleBtn.use(pos(height / 2, height / 2));
|
|
85
|
-
toggle.toggled = false;
|
|
86
|
-
} else {
|
|
87
|
-
toggle.use(color(148, 188, 236));
|
|
88
|
-
toggleBtn.use(pos(width - height / 2, height / 2));
|
|
89
|
-
toggle.toggled = true;
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
return toggle;
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Makes checkbox
|
|
98
|
-
* @param {number} x - The x postion to set (default is 0)
|
|
99
|
-
* @param {number} y - The x postion to set (default is 0)
|
|
100
|
-
* @param {number} width - Checkbox width (default is 25)
|
|
101
|
-
* @param {number} height - Checkbox height (default is 25)
|
|
102
|
-
* @returns {GameObj}
|
|
103
|
-
*/
|
|
104
|
-
export const makeCheckbox = (x = 0, y = 0, width = 25, height = 25) => {
|
|
105
|
-
loadSprite("cb", cbIcon);
|
|
106
|
-
|
|
107
|
-
const checkbox = make([
|
|
108
|
-
rect(width, height, { radius: 4 }),
|
|
109
|
-
pos(x, y),
|
|
110
|
-
color(255, 255, 255),
|
|
111
|
-
outline(1),
|
|
112
|
-
area(),
|
|
113
|
-
{
|
|
114
|
-
checked: false,
|
|
115
|
-
},
|
|
116
|
-
]);
|
|
117
|
-
|
|
118
|
-
const checkedIcon = make([sprite("cb", { width, height }), area()]);
|
|
119
|
-
|
|
120
|
-
checkbox.onClick(() => {
|
|
121
|
-
if (checkbox.checked) {
|
|
122
|
-
checkbox.use(color(255, 255, 255));
|
|
123
|
-
checkbox.remove(checkedIcon);
|
|
124
|
-
checkbox.checked = false;
|
|
125
|
-
} else {
|
|
126
|
-
checkbox.use(color(148, 188, 236));
|
|
127
|
-
checkbox.add(checkedIcon);
|
|
128
|
-
checkbox.checked = true;
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
return checkbox;
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Makes switch
|
|
137
|
-
* @param {number} x - Switch x postion (default is 0)
|
|
138
|
-
* @param {number} y - Switch y postion (default is 0)
|
|
139
|
-
* @param {number} width - Switch width (default is 50)
|
|
140
|
-
* @param {number} height - Switch height (default is 25)
|
|
141
|
-
* @returns {GameObj}
|
|
142
|
-
*/
|
|
143
|
-
export const makeSwitch = (x = 0, y = 0, width = 50, height = 25) => {
|
|
144
|
-
// Make switch base
|
|
145
|
-
const switchBase = make([
|
|
146
|
-
rect(width, height),
|
|
147
|
-
pos(x, y),
|
|
148
|
-
opacity(0),
|
|
149
|
-
area(),
|
|
150
|
-
{
|
|
151
|
-
switched: false,
|
|
152
|
-
},
|
|
153
|
-
]);
|
|
154
|
-
|
|
155
|
-
// Make switch line
|
|
156
|
-
const switchLine = make([
|
|
157
|
-
rect(width, height / 2, { radius: height / 4 }),
|
|
158
|
-
color(169, 169, 169),
|
|
159
|
-
pos(0, height / 2 - height / 4),
|
|
160
|
-
area(),
|
|
161
|
-
]);
|
|
162
|
-
|
|
163
|
-
// Make switch circle
|
|
164
|
-
const switchCircle = make([circle(height / 2), pos(height / 2, height / 2)]);
|
|
165
|
-
|
|
166
|
-
// On click
|
|
167
|
-
switchBase.onClick(() => {
|
|
168
|
-
if (switchBase.switched) {
|
|
169
|
-
switchLine.use(color(169, 169, 169));
|
|
170
|
-
switchCircle.use(color(255, 255, 255));
|
|
171
|
-
switchCircle.use(pos(height / 2, height / 2));
|
|
172
|
-
switchBase.switched = false;
|
|
173
|
-
} else {
|
|
174
|
-
switchLine.use(color(148, 188, 236));
|
|
175
|
-
switchCircle.use(color(24, 118, 210));
|
|
176
|
-
switchCircle.use(pos(width - switchCircle.radius, height / 2));
|
|
177
|
-
switchBase.switched = true;
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
// Add line and circle
|
|
182
|
-
switchBase.add(switchLine);
|
|
183
|
-
switchBase.add(switchCircle);
|
|
184
|
-
|
|
185
|
-
return switchBase;
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Makes text input
|
|
190
|
-
* @param {number} x - Text input x postion (default is 0)
|
|
191
|
-
* @param {number} y - Text input y postion (default is 0)
|
|
192
|
-
* @param {number} width - Text input width (default is 400)
|
|
193
|
-
* @param {number} txtSize - Text input text size (default is 15)
|
|
194
|
-
* @param {number} pad - Text input padding (default is 10)
|
|
195
|
-
* @param {boolean} hasFocus - Text input focus (default is true)
|
|
196
|
-
* @returns {GameObj}
|
|
197
|
-
*/
|
|
198
|
-
export const makeTextInput = (
|
|
199
|
-
x = 0,
|
|
200
|
-
y = 0,
|
|
201
|
-
width = 400,
|
|
202
|
-
txtSize = 15,
|
|
203
|
-
pad = 10,
|
|
204
|
-
hasFocus = true
|
|
205
|
-
) => {
|
|
206
|
-
// Text input container
|
|
207
|
-
const inputBase = make([
|
|
208
|
-
rect(width, txtSize + pad * 2),
|
|
209
|
-
pos(x, y),
|
|
210
|
-
area(),
|
|
211
|
-
outline(1),
|
|
212
|
-
]);
|
|
213
|
-
|
|
214
|
-
// Text input
|
|
215
|
-
const input = make([
|
|
216
|
-
text("", { width: width - pad * 2, size: txtSize }),
|
|
217
|
-
textInput(hasFocus),
|
|
218
|
-
color(BLACK),
|
|
219
|
-
pos(pad, pad),
|
|
220
|
-
area(),
|
|
221
|
-
]);
|
|
222
|
-
|
|
223
|
-
inputBase.add(input);
|
|
224
|
-
|
|
225
|
-
return inputBase;
|
|
226
|
-
};
|
|
File without changes
|