webglmusti 0.0.0
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/.gitattributes +2 -0
- package/idea_list.txt +13 -0
- package/index.html +17 -0
- package/package.json +20 -0
- package/public/apple.png +0 -0
- package/public/base.png +0 -0
- package/public/car.png +0 -0
- package/public/drop.png +0 -0
- package/public/font16-Sheet.png +0 -0
- package/public/font16-Sheet.txt +52 -0
- package/public/letters-Sheet.png +0 -0
- package/public/letters-Sheet.txt +27 -0
- package/public/letters_Sheet.png +0 -0
- package/public/letters_Sheet.txt +4 -0
- package/public/vite.svg +1 -0
- package/src/App/ResourceSim/car.ts +172 -0
- package/src/App/ResourceSim/grid.ts +993 -0
- package/src/App/ResourceSim/grid_app.ts +1326 -0
- package/src/App/ResourceSim/grid_test.test.ts +18 -0
- package/src/App/ResourceSim/node_graph.ts +293 -0
- package/src/App/ResourceSim/nodes.ts +151 -0
- package/src/App/ResourceSim/resource.ts +8 -0
- package/src/App/ResourceSim/texts.ts +6 -0
- package/src/App/card/card.test.ts +22 -0
- package/src/App/card/card.ts +763 -0
- package/src/App/puzzle_box/app.ts +10 -0
- package/src/App/puzzle_box/engine.ts +374 -0
- package/src/App/puzzle_box/renderer.ts +102 -0
- package/src/App/puzzle_box/test.test.ts +49 -0
- package/src/App/water/water.ts +206 -0
- package/src/Interface/button.ts +345 -0
- package/src/Interface/interface_element.ts +30 -0
- package/src/Interface/internal_window.ts +100 -0
- package/src/Interface/options.ts +332 -0
- package/src/Interface/text_input.ts +183 -0
- package/src/WebGL/Matrix/matrix.test.ts +30 -0
- package/src/WebGL/Matrix/matrix.ts +293 -0
- package/src/WebGL/Shaders/Fragment/Program/circle.ts +49 -0
- package/src/WebGL/Shaders/Fragment/Program/circle_only.ts +47 -0
- package/src/WebGL/Shaders/Fragment/Program/circle_outline.ts +54 -0
- package/src/WebGL/Shaders/Fragment/Program/colour.ts +39 -0
- package/src/WebGL/Shaders/Fragment/Program/colour_alpha.ts +37 -0
- package/src/WebGL/Shaders/Fragment/Program/line.ts +39 -0
- package/src/WebGL/Shaders/Fragment/Program/multi_colour_centre_circle_path.ts +69 -0
- package/src/WebGL/Shaders/Fragment/Program/multi_colour_path.ts +69 -0
- package/src/WebGL/Shaders/Fragment/Program/path_centre_circle.ts +69 -0
- package/src/WebGL/Shaders/Fragment/Program/rect_outline.ts +39 -0
- package/src/WebGL/Shaders/Fragment/Program/solid_path.ts +64 -0
- package/src/WebGL/Shaders/Fragment/Program/sprite_sheet.ts +54 -0
- package/src/WebGL/Shaders/Fragment/Program/sprite_sheet_colour.ts +62 -0
- package/src/WebGL/Shaders/Fragment/Program/texture.ts +34 -0
- package/src/WebGL/Shaders/Fragment/Source/circle.frag +19 -0
- package/src/WebGL/Shaders/Fragment/Source/circle_only.frag +15 -0
- package/src/WebGL/Shaders/Fragment/Source/circle_outline.frag +23 -0
- package/src/WebGL/Shaders/Fragment/Source/colour.frag +9 -0
- package/src/WebGL/Shaders/Fragment/Source/colour_alpha.frag +7 -0
- package/src/WebGL/Shaders/Fragment/Source/fragment.frag +5 -0
- package/src/WebGL/Shaders/Fragment/Source/fragment_source.ts +15 -0
- package/src/WebGL/Shaders/Fragment/Source/line.frag +12 -0
- package/src/WebGL/Shaders/Fragment/Source/multi_colour_centre_circle_path.frag +36 -0
- package/src/WebGL/Shaders/Fragment/Source/multi_colour_path.frag +34 -0
- package/src/WebGL/Shaders/Fragment/Source/path_centre_circle.frag +29 -0
- package/src/WebGL/Shaders/Fragment/Source/rect_outline.frag +20 -0
- package/src/WebGL/Shaders/Fragment/Source/solid_path.frag +24 -0
- package/src/WebGL/Shaders/Fragment/Source/sprite_sheet.frag +17 -0
- package/src/WebGL/Shaders/Fragment/Source/sprite_sheet_colour.frag +19 -0
- package/src/WebGL/Shaders/Fragment/Source/texture.frag +11 -0
- package/src/WebGL/Shaders/Fragment/fragment.ts +43 -0
- package/src/WebGL/Shaders/Fragment/fragment_old.ts +261 -0
- package/src/WebGL/Shaders/Vertex/Program/mvp2d.ts +41 -0
- package/src/WebGL/Shaders/Vertex/Program/transform2d.ts +39 -0
- package/src/WebGL/Shaders/Vertex/Source/mvp2d.vert +17 -0
- package/src/WebGL/Shaders/Vertex/Source/mvp_i_2d.vert +18 -0
- package/src/WebGL/Shaders/Vertex/Source/simple.vert +9 -0
- package/src/WebGL/Shaders/Vertex/Source/transform2d.vert +13 -0
- package/src/WebGL/Shaders/Vertex/Source/transform2d_rel.vert +16 -0
- package/src/WebGL/Shaders/Vertex/Source/translate2d.vert +7 -0
- package/src/WebGL/Shaders/Vertex/Source/vertex_source.ts +13 -0
- package/src/WebGL/Shaders/Vertex/vertex.ts +10 -0
- package/src/WebGL/Shaders/Vertex/vertex_old.ts +289 -0
- package/src/WebGL/Shaders/custom.ts +129 -0
- package/src/WebGL/Shaders/shader.ts +197 -0
- package/src/WebGL/Shapes/Line.ts +29 -0
- package/src/WebGL/Shapes/Shapes.ts +189 -0
- package/src/WebGL/Texture/texture.ts +214 -0
- package/src/WebGL/Util/file.ts +24 -0
- package/src/WebGL/app.ts +150 -0
- package/src/WebGL/colour.ts +71 -0
- package/src/WebGL/globals.ts +353 -0
- package/src/WebGL/index.ts +3 -0
- package/src/WebGL/mixin.ts +2 -0
- package/src/global.d.ts +13 -0
- package/src/index.ts +4 -0
- package/src/main.ts +139 -0
- package/src/utils/array.ts +154 -0
- package/src/utils/assert.ts +8 -0
- package/src/utils/file.ts +0 -0
- package/src/utils/mixin.ts +22 -0
- package/src/utils/numbers.ts +11 -0
- package/src/utils/utils.test.ts +23 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as WebGL from "./../../WebGL/globals";
|
|
2
|
+
import { PuzzleEngine } from "./engine";
|
|
3
|
+
import { PuzzleRenderer } from "./renderer";
|
|
4
|
+
|
|
5
|
+
type Int32 = number;
|
|
6
|
+
export function newPuzzleApp(w: Int32, h:Int32): WebGL.App.App<PuzzleEngine>{
|
|
7
|
+
const engine = new PuzzleEngine();
|
|
8
|
+
const renderer = new PuzzleRenderer(w, h);
|
|
9
|
+
return new WebGL.App.App(engine, renderer);
|
|
10
|
+
}
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
import * as WebGL from "./../../WebGL/globals";
|
|
2
|
+
import * as Options from "./../../Interface/options";
|
|
3
|
+
import * as Button from "./../../Interface/button";
|
|
4
|
+
import * as InterfaceElement from "./../../Interface/interface_element";
|
|
5
|
+
|
|
6
|
+
type Int32 = number;
|
|
7
|
+
type Float = number;
|
|
8
|
+
|
|
9
|
+
class IdGrid{
|
|
10
|
+
width: Int32;
|
|
11
|
+
height: Int32;
|
|
12
|
+
object_id: (Int32 | undefined)[];
|
|
13
|
+
constructor(w: Int32, h: Int32){
|
|
14
|
+
this.width = w;
|
|
15
|
+
this.height = h;
|
|
16
|
+
this.object_id = Array.from({length: this.height*this.width}, () => undefined);
|
|
17
|
+
}
|
|
18
|
+
getId(x: Int32, y: Int32) : (Int32 | undefined){
|
|
19
|
+
return this.object_id[x + y*this.width];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class ShapeGridInterface{
|
|
24
|
+
x: Int32;
|
|
25
|
+
y: Int32;
|
|
26
|
+
cell_size: Int32;
|
|
27
|
+
grid: ShapeIdGrid;
|
|
28
|
+
constructor(x: Int32, y: Int32, size: Int32, grid: ShapeIdGrid){
|
|
29
|
+
this.x = x;
|
|
30
|
+
this.y = y;
|
|
31
|
+
this.cell_size = size;
|
|
32
|
+
this.grid = grid;
|
|
33
|
+
}
|
|
34
|
+
isInside(point: WebGL.Matrix.Point2D): boolean{
|
|
35
|
+
const in_x = this.x < point.x && point.x < this.x+this.interfaceWidth();
|
|
36
|
+
const in_y = this.y < point.y && point.y < this.y+this.interfaceHeight();
|
|
37
|
+
return in_x && in_y;
|
|
38
|
+
}
|
|
39
|
+
interfaceWidth(): Int32{
|
|
40
|
+
return this.cell_size*this.grid.width;
|
|
41
|
+
}
|
|
42
|
+
interfaceHeight(): Int32{
|
|
43
|
+
return this.cell_size*this.grid.height;
|
|
44
|
+
}
|
|
45
|
+
getCoord(point: WebGL.Matrix.Point2D): Coord | undefined{
|
|
46
|
+
if(!this.isInside(point)) return undefined;
|
|
47
|
+
const x = Math.floor((point.x-this.x)/this.cell_size);
|
|
48
|
+
const y = Math.floor((point.y-this.y)/this.cell_size);
|
|
49
|
+
return {x, y};
|
|
50
|
+
}
|
|
51
|
+
trueCoord(point: WebGL.Matrix.Point2D): WebGL.Matrix.Point2D | undefined{
|
|
52
|
+
return new WebGL.Matrix.Point2D((point.x-this.x)/this.cell_size, (point.y-this.y)/this.cell_size);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
class ShapeIdGrid extends IdGrid{
|
|
57
|
+
isFree(x: Int32, y: Int32): boolean{
|
|
58
|
+
return this.object_id[x+y*this.width] == undefined;
|
|
59
|
+
}
|
|
60
|
+
canFitShape(shape: GridShapeInstance, x: Int32, y: Int32): boolean{
|
|
61
|
+
//test borders
|
|
62
|
+
if(x < 0 || y < 0 || x+shape.width > this.width || y+shape.height > this.height){
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
//test individual parts
|
|
67
|
+
for(let py = 0; py < shape.height; py++){
|
|
68
|
+
for(let px = 0; px < shape.width; px++){
|
|
69
|
+
if(shape.getPart(px, py) && !this.isFree(x+px, y+py)){
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
addShape(shape: GridShapeInstance, x: Int32, y: Int32){
|
|
77
|
+
for(let py = 0; py < shape.height; py++){
|
|
78
|
+
for(let px = 0; px < shape.width; px++){
|
|
79
|
+
if(shape.getPart(px, py)){
|
|
80
|
+
this.object_id[(x+px)+(y+py)*this.width] = shape.id;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
export const RotationEnum = {
|
|
89
|
+
None: 0,
|
|
90
|
+
Clockwise: 1,
|
|
91
|
+
Opposite: 2,
|
|
92
|
+
AntiClockwise: 3
|
|
93
|
+
} as const;
|
|
94
|
+
|
|
95
|
+
export type Rotation = (typeof RotationEnum)[keyof typeof RotationEnum];
|
|
96
|
+
|
|
97
|
+
//shape made out of grid pieces
|
|
98
|
+
export class GridShape{
|
|
99
|
+
width: Int32;
|
|
100
|
+
height: Int32;
|
|
101
|
+
parts: boolean[];
|
|
102
|
+
|
|
103
|
+
constructor(w: Int32, h: Int32, parts?: boolean[]){
|
|
104
|
+
this.width = w;
|
|
105
|
+
this.height = h;
|
|
106
|
+
this.parts = parts != undefined ? parts : Array.from({length: this.height*this.width}, () => false);
|
|
107
|
+
}
|
|
108
|
+
addPart(x: Int32, y: Int32){
|
|
109
|
+
this.parts[this.getIndexKey(x, y)] = true;
|
|
110
|
+
}
|
|
111
|
+
private getIndexKey(x: Int32, y: Int32){
|
|
112
|
+
return x+(y*this.width);
|
|
113
|
+
}
|
|
114
|
+
hasPartAt(x: Int32, y: Int32){
|
|
115
|
+
return this.parts[this.getIndexKey(x, y)];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
static equals(s1: GridShape, s2: GridShape){
|
|
119
|
+
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export class GridShapeInstance{
|
|
124
|
+
static current_id = 0;
|
|
125
|
+
id: Int32;
|
|
126
|
+
shape: GridShape;
|
|
127
|
+
private rotation: Rotation;
|
|
128
|
+
width: Int32;
|
|
129
|
+
height: Int32;
|
|
130
|
+
constructor(shape: GridShape){
|
|
131
|
+
this.id = GridShapeInstance.current_id;
|
|
132
|
+
GridShapeInstance.current_id++;
|
|
133
|
+
this.shape = shape;
|
|
134
|
+
this.rotation = RotationEnum.None;
|
|
135
|
+
this.width = this.shape.width;
|
|
136
|
+
this.height = this.shape.height;
|
|
137
|
+
}
|
|
138
|
+
setRotation(rotation: Rotation){
|
|
139
|
+
this.rotation = rotation;
|
|
140
|
+
if(this.rotation == RotationEnum.Clockwise || this.rotation == RotationEnum.AntiClockwise){
|
|
141
|
+
this.width = this.shape.height;
|
|
142
|
+
this.height = this.shape.width;
|
|
143
|
+
}else{
|
|
144
|
+
this.width = this.shape.width;
|
|
145
|
+
this.height = this.shape.height;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
isInside(x: Int32, y: Int32){
|
|
149
|
+
const in_x = 0 <= x && x < this.width;
|
|
150
|
+
const in_y = 0 <= y && y < this.height;
|
|
151
|
+
return in_x && in_y;
|
|
152
|
+
}
|
|
153
|
+
getTrueCoord(x: Int32, y: Int32, rotation: Rotation=RotationEnum.None): {x: Int32, y: Int32}{
|
|
154
|
+
switch(rotation){
|
|
155
|
+
case RotationEnum.AntiClockwise:
|
|
156
|
+
return {x: this.height-1-y, y: x};
|
|
157
|
+
case RotationEnum.Clockwise:
|
|
158
|
+
return {x: y, y: this.width-1-x};
|
|
159
|
+
case RotationEnum.Opposite:
|
|
160
|
+
return {x: this.width-1-x, y: this.height-1-y};
|
|
161
|
+
}
|
|
162
|
+
return {x, y};
|
|
163
|
+
}
|
|
164
|
+
getIndexKey(x: Int32, y: Int32, rotation: Rotation=RotationEnum.None){
|
|
165
|
+
switch(rotation){
|
|
166
|
+
case RotationEnum.AntiClockwise:
|
|
167
|
+
return (this.height-1-y) + x*this.height;
|
|
168
|
+
case RotationEnum.Clockwise:
|
|
169
|
+
return (y) + (this.width-1-x)*this.height;
|
|
170
|
+
case RotationEnum.Opposite:
|
|
171
|
+
return (this.width-1-x) + (this.height-1-y)*this.width;
|
|
172
|
+
}
|
|
173
|
+
return x + y*this.width;
|
|
174
|
+
}
|
|
175
|
+
getPart(x: Int32, y: Int32): boolean | undefined{
|
|
176
|
+
if(!this.isInside(x, y)) return undefined;
|
|
177
|
+
return this.shape.parts[this.getIndexKey(x, y, this.rotation)];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
export class ShapeLabel extends InterfaceElement.InterfaceElement{
|
|
183
|
+
shape: GridShape;
|
|
184
|
+
is_hovered: boolean;
|
|
185
|
+
onSelect: ((shape: GridShape) => void) | undefined;
|
|
186
|
+
constructor(x: Int32, y: Int32, width: Int32, height: Int32, shape: GridShape, on_select?: () => void){
|
|
187
|
+
super(x, y, width, height);
|
|
188
|
+
this.shape = shape;
|
|
189
|
+
this.is_hovered = false;
|
|
190
|
+
this.onSelect = on_select;
|
|
191
|
+
}
|
|
192
|
+
onMouseDown(){
|
|
193
|
+
if(this.is_hovered){
|
|
194
|
+
if(this.onSelect) this.onSelect(this.shape);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
onMouseOver(point: WebGL.Matrix.Point2D){
|
|
198
|
+
this.is_hovered = this.isInside(point);
|
|
199
|
+
}
|
|
200
|
+
draw(vp: WebGL.Matrix.TransformationMatrix3x3, colour_shader: WebGL.Shader.MVPColourProgram){
|
|
201
|
+
const bg = this.is_hovered ? WebGL.Colour.ColourUtils.blue() : WebGL.Colour.ColourUtils.red();
|
|
202
|
+
this.drawBackground(vp, colour_shader, bg);
|
|
203
|
+
const green = WebGL.Colour.ColourUtils.green();
|
|
204
|
+
|
|
205
|
+
//draw shape
|
|
206
|
+
const mx = this.x+(this.width*0.5);
|
|
207
|
+
const my = this.y+(this.height*0.5);
|
|
208
|
+
const cell_size = 24;
|
|
209
|
+
const rect_size = 20;
|
|
210
|
+
const clear_border = (cell_size-rect_size)*0.5;
|
|
211
|
+
let y = my-(cell_size*this.shape.height*0.5);
|
|
212
|
+
const sx = mx-(cell_size*this.shape.width*0.5);
|
|
213
|
+
let gx = sx;
|
|
214
|
+
for(let py = 0; py < this.shape.height; py++){
|
|
215
|
+
gx = sx;
|
|
216
|
+
for(let px = 0; px < this.shape.width; px++){
|
|
217
|
+
if(this.shape.hasPartAt(px, py)){
|
|
218
|
+
WebGL.WebGL.drawColourRect(vp, colour_shader,
|
|
219
|
+
gx+clear_border, y+clear_border,
|
|
220
|
+
rect_size, rect_size, green);
|
|
221
|
+
}
|
|
222
|
+
gx += cell_size;
|
|
223
|
+
}
|
|
224
|
+
y += cell_size;
|
|
225
|
+
}
|
|
226
|
+
//WebGL.WebGL.drawColourRect(vp, colour_shader, this.x, )
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
type LayoutPosition = WebGL.Matrix.Point2D;
|
|
231
|
+
|
|
232
|
+
class GridLayout{
|
|
233
|
+
start_x: Int32;
|
|
234
|
+
start_y: Int32;
|
|
235
|
+
cell_width: Int32;
|
|
236
|
+
cell_height: Int32;
|
|
237
|
+
layout_width: Int32;
|
|
238
|
+
layout_height: Int32;
|
|
239
|
+
constructor(start_x: Int32, start_y: Int32,
|
|
240
|
+
cell_width: Int32, cell_height: Int32,
|
|
241
|
+
layout_width: Int32, layout_height: Int32){
|
|
242
|
+
this.start_x = start_x;
|
|
243
|
+
this.start_y = start_y;
|
|
244
|
+
this.cell_width = cell_width;
|
|
245
|
+
this.cell_height = cell_height;
|
|
246
|
+
this.layout_width = layout_width;
|
|
247
|
+
this.layout_height = layout_height;
|
|
248
|
+
}
|
|
249
|
+
firstPosition(): LayoutPosition{
|
|
250
|
+
return new WebGL.Matrix.Point2D(this.start_x, this.start_y);
|
|
251
|
+
}
|
|
252
|
+
next(position: LayoutPosition): LayoutPosition | undefined{
|
|
253
|
+
let next_x = position.x + this.cell_width;
|
|
254
|
+
let next_y = position.y;
|
|
255
|
+
if(next_x > this.start_x + this.layout_width){
|
|
256
|
+
next_y = position.y + this.cell_height;
|
|
257
|
+
if(next_y > this.start_y + this.layout_height){
|
|
258
|
+
return undefined;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return new WebGL.Matrix.Point2D(next_x, next_y);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
type Coord = {
|
|
265
|
+
x: Int32,
|
|
266
|
+
y: Int32
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export class PuzzleEngine extends WebGL.App.BaseEngine{
|
|
270
|
+
option_select: Options.DropdownOptions;
|
|
271
|
+
mouse_point: WebGL.Matrix.Point2D | undefined;
|
|
272
|
+
|
|
273
|
+
my_shapes: GridShape[];
|
|
274
|
+
|
|
275
|
+
shape_label_layout: GridLayout;
|
|
276
|
+
shape_labels: ShapeLabel[];
|
|
277
|
+
|
|
278
|
+
dragged_shape: Int32 | undefined;
|
|
279
|
+
|
|
280
|
+
grid: ShapeIdGrid;
|
|
281
|
+
interface_grid: ShapeGridInterface;
|
|
282
|
+
|
|
283
|
+
hovered_coord: Coord | undefined;
|
|
284
|
+
|
|
285
|
+
pieces_on_grid: Map<Int32, GridShapeInstance>;
|
|
286
|
+
constructor(){
|
|
287
|
+
super();
|
|
288
|
+
this.option_select = new Options.DropdownOptions(100, 100, 150, 25, ["hello", "good", "bye"]);
|
|
289
|
+
this.my_shapes = this.createShapes();
|
|
290
|
+
|
|
291
|
+
this.shape_label_layout = new GridLayout(100, 100, 120, 80, 500, 500);
|
|
292
|
+
this.shape_labels = [];
|
|
293
|
+
|
|
294
|
+
let position: LayoutPosition | undefined = this.shape_label_layout.firstPosition();
|
|
295
|
+
for(const shape of this.my_shapes){
|
|
296
|
+
if(position == undefined) break;
|
|
297
|
+
const label = new ShapeLabel(position.x, position.y,
|
|
298
|
+
this.shape_label_layout.cell_width,
|
|
299
|
+
this.shape_label_layout.cell_height,
|
|
300
|
+
shape
|
|
301
|
+
);
|
|
302
|
+
this.shape_labels.push(label);
|
|
303
|
+
position = this.shape_label_layout.next(position);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
this.grid = new ShapeIdGrid(10, 10);
|
|
307
|
+
this.interface_grid = new ShapeGridInterface(100, 250, 25, this.grid);
|
|
308
|
+
this.hovered_coord = undefined;
|
|
309
|
+
|
|
310
|
+
this.pieces_on_grid = new Map();
|
|
311
|
+
}
|
|
312
|
+
createShapes(): GridShape[]{
|
|
313
|
+
const one = new GridShape(1, 1, [true]);
|
|
314
|
+
const two = new GridShape(2, 1, [true, true]);
|
|
315
|
+
const l = new GridShape(3, 2, [false, false, true, true, true, true]);
|
|
316
|
+
const t = new GridShape(3, 2, [false, true, false, true, true, true]);
|
|
317
|
+
return [one, two, l, t];
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
override handleKeyDown(ev: KeyboardEvent){};
|
|
321
|
+
//to override
|
|
322
|
+
override handleKeyUp(ev: KeyboardEvent){};
|
|
323
|
+
//to override
|
|
324
|
+
override handleMouseMove(ev: MouseEvent){
|
|
325
|
+
const point = new WebGL.Matrix.Point2D(ev.clientX, ev.clientY);
|
|
326
|
+
this.mouse_point = point;
|
|
327
|
+
this.option_select.onMouseOver(point);
|
|
328
|
+
|
|
329
|
+
for(const label of this.shape_labels){
|
|
330
|
+
label.onMouseOver(point);
|
|
331
|
+
}
|
|
332
|
+
this.hovered_coord = this.interface_grid.getCoord(point);
|
|
333
|
+
//console.log(this.hovered_coord);
|
|
334
|
+
};
|
|
335
|
+
//to override
|
|
336
|
+
override handleMouseDown(ev: MouseEvent){
|
|
337
|
+
if(this.mouse_point != undefined){
|
|
338
|
+
this.option_select.onMouseDown(this.mouse_point);
|
|
339
|
+
}
|
|
340
|
+
for(let i = 0; i < this.shape_labels.length; i++){
|
|
341
|
+
const label = this.shape_labels[i];
|
|
342
|
+
label.onMouseDown();
|
|
343
|
+
if(label.is_hovered){
|
|
344
|
+
this.dragged_shape = i;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
//to override
|
|
349
|
+
override handleMouseUp(ev: MouseEvent){
|
|
350
|
+
const shape = 0;
|
|
351
|
+
if(this.mouse_point != undefined){
|
|
352
|
+
const coord = this.interface_grid.trueCoord(this.mouse_point);
|
|
353
|
+
console.log(coord);
|
|
354
|
+
if(this.dragged_shape != undefined && coord != undefined){
|
|
355
|
+
const shape_label = this.shape_labels[this.dragged_shape];
|
|
356
|
+
coord.x -= (shape_label.shape.width*0.5 - 0.5);
|
|
357
|
+
coord.y -= (shape_label.shape.height*0.5 - 0.5);
|
|
358
|
+
const x = Math.floor(coord.x);
|
|
359
|
+
const y = Math.floor(coord.y);
|
|
360
|
+
console.log({x, y});
|
|
361
|
+
const new_shape = new GridShapeInstance(shape_label.shape);
|
|
362
|
+
if(this.grid.canFitShape(new_shape, x, y)){
|
|
363
|
+
this.grid.addShape(new_shape, x, y);
|
|
364
|
+
}else{
|
|
365
|
+
console.log("no room for shape");
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
this.dragged_shape = undefined;
|
|
373
|
+
};
|
|
374
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import * as WebGL from "./../../WebGL/globals";
|
|
2
|
+
import * as PEngine from "./engine";
|
|
3
|
+
import { PuzzleEngine } from "./engine";
|
|
4
|
+
|
|
5
|
+
type Int32 = number;
|
|
6
|
+
|
|
7
|
+
export class PuzzleRenderer extends WebGL.App.SimpleAppRenderer<PuzzleEngine>{
|
|
8
|
+
colour_shader: WebGL.Shader.MVPColourProgram;
|
|
9
|
+
|
|
10
|
+
my_shape_colour: WebGL.Colour.ColourRGB;
|
|
11
|
+
grid_colours: WebGL.Colour.ColourRGB[];
|
|
12
|
+
constructor(w: Int32, h: Int32){
|
|
13
|
+
super(w, h);
|
|
14
|
+
this.font_names.push("font16-Sheet.png");
|
|
15
|
+
|
|
16
|
+
this.colour_shader = new WebGL.Shader.MVPColourProgram();
|
|
17
|
+
this.my_shape_colour = WebGL.Colour.ColourUtils.red();
|
|
18
|
+
this.grid_colours = [];
|
|
19
|
+
}
|
|
20
|
+
render(engine: PuzzleEngine){
|
|
21
|
+
engine.option_select.draw(this.orthographic, this.colour_shader, this.text_drawer);
|
|
22
|
+
|
|
23
|
+
//this.drawStaticShapeLabel(engine.my_shapes[2], 200, 200);
|
|
24
|
+
|
|
25
|
+
this.drawShapeGrid(engine, engine.interface_grid);
|
|
26
|
+
|
|
27
|
+
for(const label of engine.shape_labels){
|
|
28
|
+
this.drawShapeLabel(label);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if(engine.dragged_shape != undefined && engine.mouse_point != undefined){
|
|
32
|
+
this.drawShape(engine.shape_labels[engine.dragged_shape].shape, engine.mouse_point.x, engine.mouse_point.y);
|
|
33
|
+
}
|
|
34
|
+
if(engine.hovered_coord != undefined){
|
|
35
|
+
const id = engine.grid.getId(engine.hovered_coord.x, engine.hovered_coord.y);
|
|
36
|
+
if(id != undefined){
|
|
37
|
+
this.text_drawer.drawText(this.orthographic, 50, 50, id.toString(), 15);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
fillColours(n_colours: Int32){
|
|
43
|
+
while(this.grid_colours.length < n_colours){
|
|
44
|
+
this.grid_colours.push(WebGL.Colour.ColourUtils.random());
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
drawShapeGrid(engine: PuzzleEngine, grid: PEngine.ShapeGridInterface){
|
|
49
|
+
const grey = WebGL.Colour.ColourUtils.grey();
|
|
50
|
+
WebGL.WebGL.drawColourRect(this.orthographic, this.colour_shader,
|
|
51
|
+
grid.x, grid.y,
|
|
52
|
+
grid.interfaceWidth(), grid.interfaceHeight(),
|
|
53
|
+
grey
|
|
54
|
+
);
|
|
55
|
+
const black = WebGL.Colour.ColourUtils.black();
|
|
56
|
+
const red = WebGL.Colour.ColourUtils.red();
|
|
57
|
+
const rect_size = grid.cell_size - 4;
|
|
58
|
+
const clear_border = (grid.cell_size-rect_size)*0.5;
|
|
59
|
+
for(let gy = 0; gy < grid.grid.height; gy++){
|
|
60
|
+
for(let gx = 0; gx < grid.grid.width; gx++){
|
|
61
|
+
const id = grid.grid.object_id[gx+gy*grid.grid.width];
|
|
62
|
+
let col = black;
|
|
63
|
+
if(id != undefined){
|
|
64
|
+
this.fillColours(id+1);
|
|
65
|
+
col = this.grid_colours[id];
|
|
66
|
+
}
|
|
67
|
+
WebGL.WebGL.drawColourRect(this.orthographic, this.colour_shader,
|
|
68
|
+
grid.x+gx*grid.cell_size+clear_border, grid.y+gy*grid.cell_size+clear_border,
|
|
69
|
+
rect_size, rect_size, col
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
drawShapeLabel(label: PEngine.ShapeLabel){
|
|
77
|
+
label.draw(this.orthographic, this.colour_shader);
|
|
78
|
+
}
|
|
79
|
+
drawShape(shape: PEngine.GridShape, x: Int32, y: Int32){
|
|
80
|
+
const mx = x+(shape.width*0.5);
|
|
81
|
+
const my = y+(shape.height*0.5);
|
|
82
|
+
const cell_size = 24;
|
|
83
|
+
const rect_size = 20;
|
|
84
|
+
const clear_border = (cell_size-rect_size)*0.5;
|
|
85
|
+
let sy = my-(cell_size*shape.height*0.5);
|
|
86
|
+
const sx = mx-(cell_size*shape.width*0.5);
|
|
87
|
+
let gx = sx;
|
|
88
|
+
for(let py = 0; py < shape.height; py++){
|
|
89
|
+
gx = sx;
|
|
90
|
+
for(let px = 0; px < shape.width; px++){
|
|
91
|
+
if(shape.hasPartAt(px, py)){
|
|
92
|
+
WebGL.WebGL.drawColourRect(this.orthographic, this.colour_shader,
|
|
93
|
+
gx+clear_border, sy+clear_border,
|
|
94
|
+
rect_size, rect_size, this.my_shape_colour);
|
|
95
|
+
}
|
|
96
|
+
gx += cell_size;
|
|
97
|
+
}
|
|
98
|
+
sy += cell_size;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {test, expect} from "vitest";
|
|
2
|
+
import * as Puzzle from "./engine";
|
|
3
|
+
|
|
4
|
+
test("grid_shape", () => {
|
|
5
|
+
const shape = new Puzzle.GridShape(3, 2);
|
|
6
|
+
shape.addPart(0, 0);
|
|
7
|
+
shape.addPart(1, 0);
|
|
8
|
+
shape.addPart(2, 0);
|
|
9
|
+
shape.addPart(2, 1);
|
|
10
|
+
|
|
11
|
+
const i1 = new Puzzle.GridShapeInstance(shape);
|
|
12
|
+
|
|
13
|
+
expect(i1.getPart(0, 0)).toBe(true);
|
|
14
|
+
expect(i1.getPart(1, 0)).toBe(true);
|
|
15
|
+
expect(i1.getPart(2, 0)).toBe(true);
|
|
16
|
+
expect(i1.getPart(0, 1)).toBe(false);
|
|
17
|
+
expect(i1.getPart(1, 1)).toBe(false);
|
|
18
|
+
expect(i1.getPart(2, 1)).toBe(true);
|
|
19
|
+
|
|
20
|
+
const i2 = new Puzzle.GridShapeInstance(shape);
|
|
21
|
+
i2.setRotation(Puzzle.RotationEnum.Clockwise);
|
|
22
|
+
expect(i2.getPart(0, 0)).toBe(false);
|
|
23
|
+
expect(i2.getPart(1, 0)).toBe(true);
|
|
24
|
+
expect(i2.getPart(0, 1)).toBe(false);
|
|
25
|
+
expect(i2.getPart(1, 1)).toBe(true);
|
|
26
|
+
expect(i2.getPart(0, 2)).toBe(true);
|
|
27
|
+
expect(i2.getPart(1, 2)).toBe(true);
|
|
28
|
+
expect(i2.getPart(2, 2)).toBe(undefined);
|
|
29
|
+
|
|
30
|
+
const i3 = new Puzzle.GridShapeInstance(shape);
|
|
31
|
+
i3.setRotation(Puzzle.RotationEnum.AntiClockwise);
|
|
32
|
+
expect(i3.getPart(0, 0)).toBe(true);
|
|
33
|
+
expect(i3.getPart(1, 0)).toBe(true);
|
|
34
|
+
expect(i3.getPart(0, 1)).toBe(true);
|
|
35
|
+
expect(i3.getPart(1, 1)).toBe(false);
|
|
36
|
+
expect(i3.getPart(0, 2)).toBe(true);
|
|
37
|
+
expect(i3.getPart(1, 2)).toBe(false);
|
|
38
|
+
expect(i3.getPart(2, 2)).toBe(undefined);
|
|
39
|
+
|
|
40
|
+
const i4 = new Puzzle.GridShapeInstance(shape);
|
|
41
|
+
i4.setRotation(Puzzle.RotationEnum.Opposite);
|
|
42
|
+
expect(i4.getPart(0, 0)).toBe(true);
|
|
43
|
+
expect(i4.getPart(1, 0)).toBe(false);
|
|
44
|
+
expect(i4.getPart(2, 0)).toBe(false);
|
|
45
|
+
expect(i4.getPart(0, 1)).toBe(true);
|
|
46
|
+
expect(i4.getPart(1, 1)).toBe(true);
|
|
47
|
+
expect(i4.getPart(2, 1)).toBe(true);
|
|
48
|
+
expect(i4.getPart(2, 2)).toBe(undefined);
|
|
49
|
+
});
|