Spaces:
Sleeping
Sleeping
Update static/tribalStage.js
Browse files- static/tribalStage.js +86 -89
static/tribalStage.js
CHANGED
@@ -1,87 +1,53 @@
|
|
1 |
-
let game;
|
2 |
-
|
3 |
class TribalStage extends GameStage {
|
4 |
-
constructor() {
|
5 |
-
super();
|
6 |
this.creatures = [];
|
7 |
this.huts = [];
|
8 |
this.rivalTribes = [];
|
|
|
|
|
|
|
9 |
|
10 |
-
|
11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
}
|
13 |
|
14 |
-
|
15 |
-
const
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
(error) => console.error("Grass texture load error:", error)
|
28 |
-
);
|
29 |
-
|
30 |
-
// Tribal Creature (Player)
|
31 |
-
loader.load(
|
32 |
-
"/static/assets/tribal_warrior.gltf",
|
33 |
-
(gltf) => {
|
34 |
-
this.creatureModel = gltf.scene;
|
35 |
-
this.creatureModel.scale.set(0.5, 0.5, 0.5); // Scale down for game size
|
36 |
-
this.spawnCreature(0, 0);
|
37 |
-
},
|
38 |
-
undefined,
|
39 |
-
(error) => console.error("Creature load error:", error)
|
40 |
-
);
|
41 |
-
|
42 |
-
// Hut
|
43 |
-
loader.load(
|
44 |
-
"/static/assets/hut.gltf",
|
45 |
-
(gltf) => {
|
46 |
-
this.hutModel = gltf.scene;
|
47 |
-
this.hutModel.scale.set(0.5, 0.5, 0.5);
|
48 |
-
},
|
49 |
-
undefined,
|
50 |
-
(error) => console.error("Hut load error:", error)
|
51 |
-
);
|
52 |
-
|
53 |
-
// Rival Tribe
|
54 |
-
loader.load(
|
55 |
-
"/static/assets/rival_warrior.gltf",
|
56 |
-
(gltf) => {
|
57 |
-
this.rivalModel = gltf.scene;
|
58 |
-
this.rivalModel.scale.set(0.5, 0.5, 0.5);
|
59 |
-
this.spawnRivalTribe(5, 5);
|
60 |
-
},
|
61 |
-
undefined,
|
62 |
-
(error) => console.error("Rival load error:", error)
|
63 |
-
);
|
64 |
}
|
65 |
|
66 |
init() {
|
67 |
-
this.
|
68 |
-
|
|
|
69 |
}
|
70 |
|
71 |
-
spawnCreature(x,
|
72 |
-
|
73 |
-
creature.position.set(x, 0, z);
|
74 |
-
this.scene.add(creature);
|
75 |
-
this.creatures.push({ model: creature, speed: 0.05 });
|
76 |
this.population = this.creatures.length;
|
77 |
this.updateUI();
|
78 |
}
|
79 |
|
80 |
-
spawnRivalTribe(x,
|
81 |
-
|
82 |
-
tribe.position.set(x, 0, z);
|
83 |
-
this.scene.add(tribe);
|
84 |
-
this.rivalTribes.push({ model: tribe, members: 3, hostile: true });
|
85 |
}
|
86 |
|
87 |
gatherFood() {
|
@@ -92,12 +58,9 @@ class TribalStage extends GameStage {
|
|
92 |
buildHut() {
|
93 |
if (this.resources.food >= 20 && this.huts.length < 5) {
|
94 |
this.resources.food -= 20;
|
95 |
-
|
96 |
-
hut.position.set(-5 + this.huts.length, 0, 0);
|
97 |
-
this.scene.add(hut);
|
98 |
-
this.huts.push(hut);
|
99 |
this.maxPopulation += 2;
|
100 |
-
this.spawnCreature(
|
101 |
}
|
102 |
this.updateUI();
|
103 |
}
|
@@ -106,7 +69,6 @@ class TribalStage extends GameStage {
|
|
106 |
if (this.rivalTribes.length > 0 && this.creatures.length > 1) {
|
107 |
this.rivalTribes[0].members -= 1;
|
108 |
if (this.rivalTribes[0].members <= 0) {
|
109 |
-
this.scene.remove(this.rivalTribes[0].model);
|
110 |
this.rivalTribes.shift();
|
111 |
this.relations = "Victorious";
|
112 |
} else {
|
@@ -127,35 +89,70 @@ class TribalStage extends GameStage {
|
|
127 |
|
128 |
applyCreatureChanges() {
|
129 |
const color = document.getElementById("creatureColor").value;
|
130 |
-
const
|
131 |
this.creatures.forEach(c => {
|
132 |
-
c.
|
133 |
-
|
134 |
-
child.material.color.set(color);
|
135 |
-
c.model.scale.set(scale, scale, scale);
|
136 |
-
}
|
137 |
-
});
|
138 |
});
|
139 |
toggleEditor(); // Hide editor after applying
|
140 |
}
|
141 |
|
142 |
update() {
|
143 |
this.creatures.forEach(creature => {
|
144 |
-
creature.
|
145 |
-
creature.
|
146 |
-
creature.
|
147 |
-
creature.
|
148 |
});
|
149 |
}
|
150 |
|
151 |
-
|
152 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
153 |
this.update();
|
154 |
-
this.
|
155 |
}
|
156 |
}
|
157 |
|
|
|
158 |
document.addEventListener("DOMContentLoaded", () => {
|
159 |
-
game = new TribalStage();
|
160 |
game.init();
|
161 |
});
|
|
|
|
|
|
|
1 |
class TribalStage extends GameStage {
|
2 |
+
constructor(canvas) {
|
3 |
+
super(canvas);
|
4 |
this.creatures = [];
|
5 |
this.huts = [];
|
6 |
this.rivalTribes = [];
|
7 |
+
this.patterns = {}; // Store loaded patterns
|
8 |
+
this.loadPatterns();
|
9 |
+
}
|
10 |
|
11 |
+
loadPatterns() {
|
12 |
+
// Load grass texture for background
|
13 |
+
this.patterns.grass = this.loadPattern("https://cdn.pixabay.com/photo/2013/07/12/18/40/grass-150056_1280.png", 32, 32);
|
14 |
+
// Load tribal pattern for creatures
|
15 |
+
this.patterns.creature = this.loadPattern("https://cdn.pixabay.com/photo/2023/05/15/10/32/ai-generated-7994367_1280.png", 32, 32);
|
16 |
+
// Load wood texture for huts
|
17 |
+
this.patterns.hut = this.loadPattern("https://cdn.pixabay.com/photo/2014/03/25/16/53/wood-295552_1280.png", 48, 48);
|
18 |
+
// Load apple for food
|
19 |
+
this.patterns.food = this.loadPattern("https://cdn.pixabay.com/photo/2013/07/12/07/25/apple-151229_1280.png", 16, 16);
|
20 |
}
|
21 |
|
22 |
+
loadPattern(url, width, height) {
|
23 |
+
const img = new Image();
|
24 |
+
img.crossOrigin = "anonymous"; // Try to handle CORS, but we’ll fallback if it fails
|
25 |
+
img.src = url;
|
26 |
+
let pattern = null;
|
27 |
+
img.onload = () => {
|
28 |
+
pattern = this.ctx.createPattern(img, "repeat");
|
29 |
+
};
|
30 |
+
img.onerror = () => {
|
31 |
+
console.error("Failed to load pattern:", url);
|
32 |
+
pattern = this.ctx.createPattern(new Uint8ClampedArray([255, 255, 255, 255]), "repeat"); // Fallback to white
|
33 |
+
};
|
34 |
+
return () => pattern || this.ctx.createPattern(new Uint8ClampedArray([255, 255, 255, 255]), "repeat"); // Fallback
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
}
|
36 |
|
37 |
init() {
|
38 |
+
this.spawnCreature(400, 300); // Player's creature
|
39 |
+
this.spawnRivalTribe(600, 100); // Rival tribe
|
40 |
+
this.render();
|
41 |
}
|
42 |
|
43 |
+
spawnCreature(x, y) {
|
44 |
+
this.creatures.push({ x, y, speed: 2, size: 32 });
|
|
|
|
|
|
|
45 |
this.population = this.creatures.length;
|
46 |
this.updateUI();
|
47 |
}
|
48 |
|
49 |
+
spawnRivalTribe(x, y) {
|
50 |
+
this.rivalTribes.push({ x, y, members: 3, hostile: true });
|
|
|
|
|
|
|
51 |
}
|
52 |
|
53 |
gatherFood() {
|
|
|
58 |
buildHut() {
|
59 |
if (this.resources.food >= 20 && this.huts.length < 5) {
|
60 |
this.resources.food -= 20;
|
61 |
+
this.huts.push({ x: 350 + this.huts.length * 50, y: 250 });
|
|
|
|
|
|
|
62 |
this.maxPopulation += 2;
|
63 |
+
this.spawnCreature(400, 300);
|
64 |
}
|
65 |
this.updateUI();
|
66 |
}
|
|
|
69 |
if (this.rivalTribes.length > 0 && this.creatures.length > 1) {
|
70 |
this.rivalTribes[0].members -= 1;
|
71 |
if (this.rivalTribes[0].members <= 0) {
|
|
|
72 |
this.rivalTribes.shift();
|
73 |
this.relations = "Victorious";
|
74 |
} else {
|
|
|
89 |
|
90 |
applyCreatureChanges() {
|
91 |
const color = document.getElementById("creatureColor").value;
|
92 |
+
const size = parseInt(document.getElementById("creatureSize").value);
|
93 |
this.creatures.forEach(c => {
|
94 |
+
c.color = color;
|
95 |
+
c.size = size;
|
|
|
|
|
|
|
|
|
96 |
});
|
97 |
toggleEditor(); // Hide editor after applying
|
98 |
}
|
99 |
|
100 |
update() {
|
101 |
this.creatures.forEach(creature => {
|
102 |
+
creature.x += (Math.random() - 0.5) * creature.speed;
|
103 |
+
creature.y += (Math.random() - 0.5) * creature.speed;
|
104 |
+
creature.x = Math.max(0, Math.min(800, creature.x));
|
105 |
+
creature.y = Math.max(0, Math.min(600, creature.y));
|
106 |
});
|
107 |
}
|
108 |
|
109 |
+
render() {
|
110 |
+
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
111 |
+
|
112 |
+
// Draw grass background (using pattern)
|
113 |
+
this.ctx.fillStyle = this.patterns.grass();
|
114 |
+
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
115 |
+
|
116 |
+
// Draw huts (wood-patterned rectangles)
|
117 |
+
this.huts.forEach(hut => {
|
118 |
+
this.ctx.fillStyle = this.patterns.hut();
|
119 |
+
this.ctx.fillRect(hut.x, hut.y, 48, 48);
|
120 |
+
});
|
121 |
+
|
122 |
+
// Draw rival tribes (red or green circles with tribal pattern)
|
123 |
+
this.rivalTribes.forEach(tribe => {
|
124 |
+
this.ctx.fillStyle = tribe.hostile ? "red" : "green";
|
125 |
+
this.ctx.beginPath();
|
126 |
+
this.ctx.arc(tribe.x + 16, tribe.y + 16, 16, 0, Math.PI * 2);
|
127 |
+
this.ctx.fill();
|
128 |
+
this.ctx.fillStyle = this.patterns.creature();
|
129 |
+
this.ctx.fill();
|
130 |
+
this.ctx.fillText(`Members: ${tribe.members}`, tribe.x, tribe.y - 10);
|
131 |
+
});
|
132 |
+
|
133 |
+
// Draw creatures (circles with tribal pattern and custom color overlay)
|
134 |
+
this.creatures.forEach(creature => {
|
135 |
+
this.ctx.fillStyle = creature.color || "#ff0000";
|
136 |
+
this.ctx.beginPath();
|
137 |
+
this.ctx.arc(creature.x + creature.size / 2, creature.y + creature.size / 2, creature.size / 2, 0, Math.PI * 2);
|
138 |
+
this.ctx.fill();
|
139 |
+
this.ctx.fillStyle = this.patterns.creature();
|
140 |
+
this.ctx.fill();
|
141 |
+
});
|
142 |
+
|
143 |
+
// Optionally draw food (small apple icon)
|
144 |
+
if (this.resources.food > 0 && this.patterns.food()) {
|
145 |
+
this.ctx.fillStyle = this.patterns.food();
|
146 |
+
this.ctx.fillRect(50, 50, 16, 16); // Example position for food
|
147 |
+
}
|
148 |
+
|
149 |
this.update();
|
150 |
+
requestAnimationFrame(() => this.render());
|
151 |
}
|
152 |
}
|
153 |
|
154 |
+
let game;
|
155 |
document.addEventListener("DOMContentLoaded", () => {
|
156 |
+
game = new TribalStage(document.getElementById("gameCanvas"));
|
157 |
game.init();
|
158 |
});
|