Figg 8 месяцев назад
Родитель
Сommit
e952928bea
7 измененных файлов: 334 добавлений и 0 удалений
  1. 21
    0
      css/style.css
  2. 40
    0
      index.html
  3. 81
    0
      js/drawer.js
  4. 81
    0
      js/game.js
  5. 2
    0
      js/p5.min.js
  6. 50
    0
      js/sketch.js
  7. 59
    0
      js/tube.js

+ 21
- 0
css/style.css Просмотреть файл

@@ -0,0 +1,21 @@
1
+body {
2
+	padding: 0;
3
+	margin: 0;
4
+}
5
+
6
+menu {
7
+	padding: 0;
8
+	margin: 5px;
9
+}
10
+
11
+menuitem {
12
+	margin-right: 10px;
13
+}
14
+
15
+menuitem label::after {
16
+	content: " :";
17
+}
18
+
19
+menuitem input {
20
+	max-width: 50px;
21
+}

+ 40
- 0
index.html Просмотреть файл

@@ -0,0 +1,40 @@
1
+<!DOCTYPE html>
2
+<html lang="">
3
+
4
+<head>
5
+	<meta charset="utf-8">
6
+	<meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+	<title>p5.js example</title>
8
+	<link href="./css/style.css" rel="stylesheet">
9
+	<script src="./js/p5.min.js"></script>
10
+	<script src="./js/tube.js"></script>
11
+	<script src="./js/game.js"></script>
12
+	<script src="./js/drawer.js"></script>
13
+	<script src="./js/sketch.js"></script>
14
+</head>
15
+
16
+<body>
17
+	<menu>
18
+		<menuitem>
19
+			<label>Tubes Number</label>
20
+			<input type="number" size="5" id="tbNumber" value="10">
21
+		</menuitem>
22
+		<menuitem>
23
+			<label>Tubes Levels</label>
24
+			<input type="number" size="5" id="tbLevel" value="5">
25
+		</menuitem>
26
+		<menuitem>
27
+			<label>Padding</label>
28
+			<input type="number" size="5" id="padding" value="5">
29
+		</menuitem>
30
+		<menuitem>
31
+			<label>Tube Size</label>
32
+			<input type="number" size="5" id="tbSize" value="5">
33
+		</menuitem>
34
+		<button type="button" onclick="newGame()">New game</button>
35
+	</menu>
36
+	<main oncontextmenu="return false;">
37
+	</main>
38
+</body>
39
+
40
+</html>

+ 81
- 0
js/drawer.js Просмотреть файл

@@ -0,0 +1,81 @@
1
+class Drawer
2
+{
3
+	#canvasWidth
4
+	#canvasHeight
5
+	
6
+	constructor(_padding)
7
+	{
8
+		this.padding = _padding;
9
+		
10
+		createCanvas(0, 0);
11
+	}
12
+	
13
+	setTubesParams(_tubesNumbers, _tubeLevels, _tubeSize)
14
+	{
15
+		this.tubesNumbers = _tubesNumbers;
16
+		this.tubeLevels = _tubeLevels;
17
+		this.tubeSize = _tubeSize;
18
+		
19
+		this.#canvasWidth = this.tubesNumbers * (this.tubeSize + this.padding) + this.padding;
20
+		this.#canvasHeight = 3 * this.padding + this.tubeLevels * this.tubeSize;
21
+		
22
+		resizeCanvas(this.#canvasWidth, this.#canvasHeight);
23
+	}
24
+	
25
+	draw(game)
26
+	{
27
+		let tubes = game.tubes;
28
+		let selectedTube = game.selectedTube;
29
+		
30
+		background('white');
31
+		
32
+		this.drawTubes(this.padding, 2*this.padding, tubes, selectedTube);
33
+	}
34
+
35
+	drawTubes(x, y, tubes, selectedTube)
36
+	{
37
+		let tubeX = x;
38
+		let tubeY = y;
39
+		let selectionOffset = 0;
40
+		
41
+		tubes.forEach(tube => {
42
+			selectionOffset = (tube == selectedTube ? this.padding : 0);
43
+			
44
+			this.drawTube(tubeX, tubeY - selectionOffset, tube);
45
+			tubeX += this.padding + this.tubeSize;
46
+		});
47
+	}
48
+
49
+	drawTube(x, y, tube)
50
+	{
51
+		
52
+		y += (this.tubeLevels-1) * this.tubeSize;
53
+		
54
+		for(let i = 0; i < this.tubeLevels; i++)
55
+		{
56
+			color = tube.getColorAtLevel(i);
57
+			color == null ? noFill() : fill(color);
58
+			
59
+			if (i >= 0)
60
+			{
61
+				rect(x, y - i * this.tubeSize, this.tubeSize);
62
+			}
63
+		}
64
+	}
65
+	
66
+	getTubeIdAt(x, y)
67
+	{
68
+		if (!this.isInboundsCanvas(x,y)) return -1;
69
+		
70
+		let idWithPadding = (x - this.padding) / (this.tubeSize + this.padding);
71
+		return idWithPadding % 1 > 1 - (this.padding / (this.tubeSize + this.padding)) ? -1 : int(idWithPadding);
72
+	}
73
+	
74
+	isInboundsCanvas(x, y)
75
+	{
76
+		return x >= this.padding
77
+			&& y >= this.padding
78
+			&& x < this.#canvasWidth - this.padding
79
+			&& y < this.#canvasHeight - this.padding;
80
+	}
81
+}

+ 81
- 0
js/game.js Просмотреть файл

@@ -0,0 +1,81 @@
1
+class Game {
2
+	#colorsBank = ['black','silver','gray','maroon','red','purple','fuchsia','green','lime','olive','yellow','navy','blue','teal','aqua'];
3
+	
4
+	constructor(nbTubes, tubeLevel)
5
+	{
6
+		this.tubes = [];
7
+		this.selectedTube = null;
8
+		
9
+		for (let i = 0; i < nbTubes; i++)
10
+		{
11
+			this.tubes.push(new Tube(tubeLevel));
12
+		}
13
+		
14
+		this.initializeColorTubes(tubeLevel);
15
+	}
16
+	
17
+	/*	The goal is to have each tube filled with its own color. Thus, there
18
+		is (tubes minus one) different colors divided in (tubeLevel) layers
19
+		mixed in the tubes.
20
+		One tube is empty to allow movement.
21
+	*/
22
+	initializeColorTubes(tubeLevel)
23
+	{
24
+		let nbColors = this.tubes.length - 1;
25
+		let allColors = [];
26
+		
27
+		for (let coloridx = 0; coloridx < nbColors; coloridx++)
28
+		{
29
+			for (let times = 0; times < tubeLevel; times++)
30
+			{
31
+				allColors.push(this.#colorsBank[coloridx]);
32
+			}
33
+		}
34
+		
35
+		for (let i = allColors.length - 1; i > 0; i--) {
36
+			let j = Math.floor(Math.random() * (i + 1));
37
+			let temp = allColors[i];
38
+			allColors[i] = allColors[j];
39
+			allColors[j] = temp;
40
+		}
41
+		
42
+		for (let index = 0; index < allColors.length; index++)
43
+		{
44
+			this.tubes[Math.floor(index/tubeLevel)].addColor(allColors[index]);
45
+		}
46
+	}
47
+	
48
+	selectTube(tubeId)
49
+	{
50
+		let newSelectedTube = this.tubes[tubeId];
51
+		
52
+		if (this.selectedTube == null && newSelectedTube.isEmpty()) return;
53
+		
54
+		if(this.selectedTube == null && !newSelectedTube.isEmpty())
55
+		{
56
+			this.selectedTube = newSelectedTube;
57
+		}
58
+		else if (this.selectedTube == newSelectedTube)
59
+		{
60
+			this.selectedTube = null;
61
+		}
62
+		else if (newSelectedTube.isEmpty() || this.selectedTube.peekTopColor() == newSelectedTube.peekTopColor())
63
+		{
64
+			this.pourColorInto(this.selectedTube, newSelectedTube);
65
+		}
66
+	}
67
+	
68
+	pourColorInto(sourceTube, targetTube)
69
+	{
70
+		if (sourceTube.isEmpty()) return;
71
+		
72
+		let pouringColor = sourceTube.peekTopColor();
73
+		
74
+		while (sourceTube.peekTopColor() == pouringColor && !targetTube.isFull())
75
+		{
76
+			targetTube.addColor(sourceTube.removeColorLayer());
77
+		}
78
+	}
79
+	
80
+	
81
+}

+ 2
- 0
js/p5.min.js
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 50
- 0
js/sketch.js Просмотреть файл

@@ -0,0 +1,50 @@
1
+function setup()
2
+{
3
+	newGame();
4
+}
5
+
6
+function newGame() {
7
+	let params = gatherMenuValues();
8
+	
9
+	this.game = new Game(params.TUBESNUMBERS, params.TUBESLEVELS);
10
+	this.drawer = new Drawer(params.PADDING);
11
+	
12
+	this.drawer.setTubesParams(params.TUBESNUMBERS, params.TUBESLEVELS, params.TUBESIZE);
13
+	
14
+	this.needUpdate = true;
15
+}
16
+
17
+function mousePressed(e) 
18
+{
19
+	let tubeId = this.drawer.getTubeIdAt(mouseX, mouseY);
20
+	
21
+	if (tubeId != -1)
22
+	{
23
+		this.game.selectTube(tubeId);
24
+	}
25
+	
26
+	this.needUpdate = true;
27
+}
28
+
29
+function gatherMenuValues()
30
+{
31
+	let inputTubesNumbers = parseInt(document.getElementById("tbNumber").value);
32
+	let inputTubesLevels = parseInt(document.getElementById("tbLevel").value);
33
+	let inputTubeSize = parseInt(document.getElementById("tbSize").value);
34
+	let inputPadding = parseInt(document.getElementById("padding").value);
35
+	
36
+	return {
37
+		TUBESNUMBERS: inputTubesNumbers,
38
+		TUBESLEVELS: inputTubesLevels,
39
+		TUBESIZE: inputTubeSize,
40
+		PADDING: inputPadding
41
+	};
42
+}
43
+function draw()
44
+{
45
+	if (!this.needUpdate) return;
46
+	
47
+	this.drawer.draw(this.game);
48
+	
49
+	this.needUpdate = false;
50
+}

+ 59
- 0
js/tube.js Просмотреть файл

@@ -0,0 +1,59 @@
1
+class Tube {	
2
+	#maxLevels;
3
+	#colors;
4
+	
5
+	constructor(levels)
6
+	{
7
+		this.#maxLevels = levels;
8
+		this.#colors = [];
9
+	}
10
+	
11
+	addColor(color)
12
+	{
13
+		if (this.isFull()) return false;
14
+		
15
+		this.#colors.push(color);
16
+		return true;
17
+	}
18
+	
19
+	removeColorLayer()
20
+	{
21
+		if (this.isEmpty()) return null;
22
+		
23
+		return this.#colors.pop();
24
+	}
25
+	
26
+	drain()
27
+	{
28
+		this.#colors = [];
29
+	}
30
+	
31
+	isFull()
32
+	{
33
+		return this.#colors.length == this.#maxLevels;
34
+	}
35
+	
36
+	isEmpty()
37
+	{
38
+		return this.#colors.length == 0;
39
+	}
40
+	
41
+	emptySpaceSize()
42
+	{
43
+		return this.#maxLevels - this.#colors.length;
44
+	}
45
+	
46
+	getColorAtLevel(index)
47
+	{
48
+		if (index < 0 || index >= this.#colors.length) return '';
49
+		
50
+		return this.#colors[index].toString();
51
+	}
52
+	
53
+	peekTopColor()
54
+	{
55
+		let length = this.#colors.length;
56
+		
57
+		return this.getColorAtLevel(length-1);
58
+	}
59
+}

Загрузка…
Отмена
Сохранить