Files
novafarma/src/systems/BreedingUISystem.js
2025-12-13 00:02:38 +01:00

492 lines
14 KiB
JavaScript

/**
* BREEDING UI SYSTEM
* Visual family tree and genetics display for animal breeding
*/
class BreedingUISystem {
constructor(scene) {
this.scene = scene;
this.enabled = true;
// UI elements
this.container = null;
this.familyTreeView = null;
this.geneticsPanel = null;
this.isVisible = false;
// Selected animal
this.selectedAnimal = null;
// Family tree data
this.familyTree = new Map();
// UI settings
this.settings = {
nodeWidth: 80,
nodeHeight: 60,
horizontalSpacing: 100,
verticalSpacing: 80,
maxGenerations: 5
};
this.init();
console.log('✅ Breeding UI System initialized');
}
init() {
this.createUI();
console.log('🌳 Family tree UI ready');
}
// ========== UI CREATION ==========
createUI() {
// Main container (hidden by default)
this.container = this.scene.add.container(0, 0);
this.container.setDepth(1000);
this.container.setVisible(false);
// Background overlay
const overlay = this.scene.add.rectangle(
this.scene.cameras.main.width / 2,
this.scene.cameras.main.height / 2,
this.scene.cameras.main.width,
this.scene.cameras.main.height,
0x000000,
0.8
);
overlay.setInteractive();
overlay.on('pointerdown', () => this.hide());
this.container.add(overlay);
// Panel background
const panelWidth = 800;
const panelHeight = 600;
const panelX = this.scene.cameras.main.width / 2;
const panelY = this.scene.cameras.main.height / 2;
const panel = this.scene.add.rectangle(
panelX, panelY,
panelWidth, panelHeight,
0x2a2a2a
);
panel.setStrokeStyle(2, 0x4a4a4a);
this.container.add(panel);
// Title
const title = this.scene.add.text(
panelX, panelY - panelHeight / 2 + 30,
'Family Tree & Genetics',
{
fontSize: '24px',
fontStyle: 'bold',
color: '#ffffff'
}
);
title.setOrigin(0.5);
this.container.add(title);
// Close button
const closeBtn = this.scene.add.text(
panelX + panelWidth / 2 - 30,
panelY - panelHeight / 2 + 30,
'✕',
{
fontSize: '32px',
color: '#ff4444'
}
);
closeBtn.setOrigin(0.5);
closeBtn.setInteractive({ useHandCursor: true });
closeBtn.on('pointerdown', () => this.hide());
this.container.add(closeBtn);
// Family tree view area
this.familyTreeView = this.scene.add.container(panelX - 300, panelY);
this.container.add(this.familyTreeView);
// Genetics panel
this.geneticsPanel = this.scene.add.container(panelX + 200, panelY);
this.container.add(this.geneticsPanel);
}
// ========== SHOW/HIDE ==========
show(animalId) {
if (!this.scene.animalBreeding) {
console.log('❌ Animal Breeding System not found');
return;
}
const animal = this.scene.animalBreeding.animals.get(animalId);
if (!animal) {
console.log('❌ Animal not found');
return;
}
this.selectedAnimal = animal;
this.buildFamilyTree(animal);
this.displayGeneticsInfo(animal);
this.container.setVisible(true);
this.isVisible = true;
}
hide() {
this.container.setVisible(false);
this.isVisible = false;
this.selectedAnimal = null;
}
// ========== FAMILY TREE ==========
buildFamilyTree(animal) {
// Clear previous tree
this.familyTreeView.removeAll(true);
// Build tree structure
const tree = this.generateTreeStructure(animal);
// Render tree
this.renderTree(tree, 0, 0, 0);
}
generateTreeStructure(animal, generation = 0) {
if (generation >= this.settings.maxGenerations) {
return null;
}
const node = {
animal,
generation,
parents: []
};
// Get parents (if stored)
if (animal.parents) {
node.parents = animal.parents.map(parentId => {
const parent = this.scene.animalBreeding.animals.get(parentId);
return parent ? this.generateTreeStructure(parent, generation + 1) : null;
}).filter(p => p !== null);
}
return node;
}
renderTree(node, x, y, generation) {
if (!node) return;
const settings = this.settings;
// Draw node
this.drawAnimalNode(node.animal, x, y);
// Draw parents
if (node.parents.length > 0) {
const parentY = y - settings.verticalSpacing;
const parentSpacing = settings.horizontalSpacing;
node.parents.forEach((parent, index) => {
const parentX = x + (index - 0.5) * parentSpacing;
// Draw connection line
const line = this.scene.add.line(
0, 0,
x, y - settings.nodeHeight / 2,
parentX, parentY + settings.nodeHeight / 2,
0x888888
);
line.setLineWidth(2);
this.familyTreeView.add(line);
// Render parent node
this.renderTree(parent, parentX, parentY, generation + 1);
});
}
}
drawAnimalNode(animal, x, y) {
const settings = this.settings;
// Node background
const nodeColor = this.getNodeColor(animal);
const node = this.scene.add.rectangle(
x, y,
settings.nodeWidth,
settings.nodeHeight,
nodeColor
);
node.setStrokeStyle(2, 0xffffff);
this.familyTreeView.add(node);
// Animal icon/emoji
const icon = this.getAnimalIcon(animal.species);
const iconText = this.scene.add.text(x, y - 10, icon, {
fontSize: '24px'
});
iconText.setOrigin(0.5);
this.familyTreeView.add(iconText);
// Animal name/gender
const genderSymbol = animal.gender === 'male' ? '♂' : '♀';
const nameText = this.scene.add.text(
x, y + 15,
`${genderSymbol} ${animal.species}`,
{
fontSize: '10px',
color: '#ffffff'
}
);
nameText.setOrigin(0.5);
this.familyTreeView.add(nameText);
// Mutation indicator
if (animal.genetics.mutation) {
const mutationBadge = this.scene.add.text(
x + settings.nodeWidth / 2 - 5,
y - settings.nodeHeight / 2 + 5,
'⭐',
{ fontSize: '12px' }
);
mutationBadge.setOrigin(0.5);
this.familyTreeView.add(mutationBadge);
}
// Make interactive
node.setInteractive({ useHandCursor: true });
node.on('pointerdown', () => {
this.selectedAnimal = animal;
this.displayGeneticsInfo(animal);
});
}
getNodeColor(animal) {
// Color based on genetics
const colorMap = {
brown: 0x8B4513,
black: 0x000000,
white: 0xFFFFFF,
golden: 0xFFD700,
rainbow: 0xFF00FF
};
return colorMap[animal.genetics.color] || 0x888888;
}
getAnimalIcon(species) {
const icons = {
sheep: '🐑',
cow: '🐄',
chicken: '🐔',
pig: '🐷',
horse: '🐴'
};
return icons[species] || '🐾';
}
// ========== GENETICS PANEL ==========
displayGeneticsInfo(animal) {
// Clear previous info
this.geneticsPanel.removeAll(true);
let yOffset = -200;
// Title
const title = this.scene.add.text(0, yOffset, 'Genetics Info', {
fontSize: '18px',
fontStyle: 'bold',
color: '#ffffff'
});
title.setOrigin(0.5);
this.geneticsPanel.add(title);
yOffset += 40;
// Animal info
const info = [
`Species: ${animal.species}`,
`Gender: ${animal.gender}`,
`Age: ${Math.floor(animal.age)} days`,
`Stage: ${animal.stage}`,
'',
'--- Genetics ---',
`Color: ${animal.genetics.color}`,
`Size: ${animal.genetics.size}`,
`Speed: ${animal.genetics.speed}`,
`Production: ${animal.genetics.production}`
];
// Mutation info
if (animal.genetics.mutation) {
info.push('', '--- Mutation ---');
info.push(`Type: ${animal.genetics.mutation}`);
info.push('⭐ RARE MUTATION!');
}
// Breeding info
if (animal.pregnant) {
info.push('', '--- Breeding ---');
info.push(`Pregnant: ${Math.floor(animal.gestationProgress * 100)}%`);
}
// Display all info
info.forEach(line => {
const text = this.scene.add.text(0, yOffset, line, {
fontSize: '14px',
color: line.includes('---') ? '#ffff00' : '#ffffff'
});
text.setOrigin(0.5);
this.geneticsPanel.add(text);
yOffset += 20;
});
// DNA Helix Animation
if (animal.genetics.mutation) {
this.addDNAHelixAnimation(0, yOffset + 50);
}
}
addDNAHelixAnimation(x, y) {
// Create mini DNA helix
const helix = this.scene.add.container(x, y);
for (let i = 0; i < 10; i++) {
const yPos = i * 5 - 25;
const angle = (i / 10) * Math.PI * 2;
const x1 = Math.cos(angle) * 10;
const x2 = Math.cos(angle + Math.PI) * 10;
const dot1 = this.scene.add.circle(x1, yPos, 2, 0x00ff00);
const dot2 = this.scene.add.circle(x2, yPos, 2, 0x00ffff);
helix.add(dot1);
helix.add(dot2);
}
// Rotate animation
this.scene.tweens.add({
targets: helix,
rotation: Math.PI * 2,
duration: 3000,
repeat: -1,
ease: 'Linear'
});
this.geneticsPanel.add(helix);
}
// ========== BREEDING PREDICTION ==========
showBreedingPrediction(animal1, animal2) {
if (!animal1 || !animal2) return;
// Predict offspring genetics
const prediction = this.predictOffspring(animal1, animal2);
// Show in UI
this.displayPrediction(prediction);
}
predictOffspring(parent1, parent2) {
// Simulate genetics inheritance
const prediction = {
possibleColors: this.predictColor(parent1, parent2),
possibleSizes: this.predictTrait(parent1.genetics.size, parent2.genetics.size),
possibleSpeeds: this.predictTrait(parent1.genetics.speed, parent2.genetics.speed),
mutationChance: 0.05 // 5%
};
return prediction;
}
predictColor(p1, p2) {
const colors = [p1.genetics.color, p2.genetics.color];
// Add dominant/recessive logic
const dominant = ['brown', 'black'];
const recessive = ['white', 'golden'];
if (dominant.includes(p1.genetics.color)) {
return [p1.genetics.color];
}
if (dominant.includes(p2.genetics.color)) {
return [p2.genetics.color];
}
return colors;
}
predictTrait(trait1, trait2) {
return [trait1, trait2];
}
displayPrediction(prediction) {
// Clear genetics panel
this.geneticsPanel.removeAll(true);
let yOffset = -200;
const title = this.scene.add.text(0, yOffset, 'Breeding Prediction', {
fontSize: '18px',
fontStyle: 'bold',
color: '#ffff00'
});
title.setOrigin(0.5);
this.geneticsPanel.add(title);
yOffset += 40;
// Display predictions
const info = [
'Possible Offspring:',
'',
`Colors: ${prediction.possibleColors.join(', ')}`,
`Sizes: ${prediction.possibleSizes.join(', ')}`,
`Speeds: ${prediction.possibleSpeeds.join(', ')}`,
'',
`Mutation Chance: ${prediction.mutationChance * 100}%`
];
info.forEach(line => {
const text = this.scene.add.text(0, yOffset, line, {
fontSize: '14px',
color: '#ffffff'
});
text.setOrigin(0.5);
this.geneticsPanel.add(text);
yOffset += 20;
});
}
// ========== KEYBOARD SHORTCUT ==========
setupKeyboard() {
// Press 'F' to open family tree for selected animal
this.scene.input.keyboard.on('keydown-F', () => {
if (this.selectedAnimal) {
if (this.isVisible) {
this.hide();
} else {
this.show(this.selectedAnimal.id);
}
}
});
}
// ========== UPDATE ==========
update(delta) {
// Update animations if visible
if (this.isVisible) {
// Any dynamic updates here
}
}
destroy() {
if (this.container) {
this.container.destroy();
}
console.log('🌳 Breeding UI System destroyed');
}
}