From 32498e92c00ca613b482e22ea76939d1c0fc647a Mon Sep 17 00:00:00 2001 From: chdonncha Date: Wed, 21 Aug 2024 18:45:49 +0100 Subject: [PATCH 1/5] :sparkles: Prevent placement of structures on water --- src/components/Grid/Grid.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Grid/Grid.tsx b/src/components/Grid/Grid.tsx index a5a861a..4d53d0d 100644 --- a/src/components/Grid/Grid.tsx +++ b/src/components/Grid/Grid.tsx @@ -108,7 +108,7 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = for (let i = 0; i < 2; i++) { for (let j = 0; j < 2; j++) { const cell = cells.find(cell => cell.x === x + i * CELL_SIZE && cell.y === y + j * CELL_SIZE); - if (!cell || cell.building) { + if (!cell || cell.building || cell.type === 'water') { return false; } } From 34201cf79876a39bb1aed7c9aa420193c4d0990c Mon Sep 17 00:00:00 2001 From: chdonncha Date: Wed, 21 Aug 2024 19:26:22 +0100 Subject: [PATCH 2/5] :recycle: Replace Structure naming with Building --- src/components/BuildMenu/BuildMenu.css | 2 +- src/components/BuildMenu/BuildMenu.tsx | 2 +- .../DeleteBuildingButton.tsx | 17 +++++++++++++++++ .../DeleteStructureButton.tsx | 17 ----------------- src/components/Grid/Grid.css | 2 +- src/components/RenderGrid/RenderGrid.tsx | 4 ++-- 6 files changed, 22 insertions(+), 22 deletions(-) create mode 100644 src/components/DeleteStructureButton/DeleteBuildingButton.tsx delete mode 100644 src/components/DeleteStructureButton/DeleteStructureButton.tsx diff --git a/src/components/BuildMenu/BuildMenu.css b/src/components/BuildMenu/BuildMenu.css index 8318048..c1ff363 100644 --- a/src/components/BuildMenu/BuildMenu.css +++ b/src/components/BuildMenu/BuildMenu.css @@ -3,7 +3,7 @@ color: white; } -.construction-menu-button { +.build-menu-button { position: absolute !important; z-index: 1000; right: 0; diff --git a/src/components/BuildMenu/BuildMenu.tsx b/src/components/BuildMenu/BuildMenu.tsx index 4ae50de..3c76c07 100644 --- a/src/components/BuildMenu/BuildMenu.tsx +++ b/src/components/BuildMenu/BuildMenu.tsx @@ -151,7 +151,7 @@ const BuildMenu = ({ return ( <> - + diff --git a/src/components/DeleteStructureButton/DeleteBuildingButton.tsx b/src/components/DeleteStructureButton/DeleteBuildingButton.tsx new file mode 100644 index 0000000..8ad480d --- /dev/null +++ b/src/components/DeleteStructureButton/DeleteBuildingButton.tsx @@ -0,0 +1,17 @@ +import DeleteIcon from '@mui/icons-material/Delete'; +import { Fab } from '@mui/material'; +import React from 'react'; + +interface DeleteBuildingButtonProps { + onDeleteBuilding: () => void; +} + +const DeleteBuildingButton: React.FC = ({ onDeleteBuilding }) => { + return ( + + + + ); +}; + +export { DeleteBuildingButton }; diff --git a/src/components/DeleteStructureButton/DeleteStructureButton.tsx b/src/components/DeleteStructureButton/DeleteStructureButton.tsx deleted file mode 100644 index efd32df..0000000 --- a/src/components/DeleteStructureButton/DeleteStructureButton.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import DeleteIcon from '@mui/icons-material/Delete'; -import { Fab } from '@mui/material'; -import React from 'react'; - -interface DeleteStructureButtonProps { - onDeleteStructure: () => void; -} - -const DeleteStructureButton: React.FC = ({ onDeleteStructure }) => { - return ( - - - - ); -}; - -export { DeleteStructureButton }; diff --git a/src/components/Grid/Grid.css b/src/components/Grid/Grid.css index 038b8c2..79c1071 100644 --- a/src/components/Grid/Grid.css +++ b/src/components/Grid/Grid.css @@ -34,7 +34,7 @@ canvas { margin: 230px 16px 0 0 !important; } -.delete-structure-button { +.delete-building-button { position: absolute !important; z-index: 1000; right: 0; diff --git a/src/components/RenderGrid/RenderGrid.tsx b/src/components/RenderGrid/RenderGrid.tsx index 0c9650f..cc688c5 100644 --- a/src/components/RenderGrid/RenderGrid.tsx +++ b/src/components/RenderGrid/RenderGrid.tsx @@ -25,7 +25,7 @@ const RenderGrid: React.FC = () => { const handleSelectAssembler = (level: number) => setSelectedBuilding({ type: `assembler${level}` }); const handleSelectExcavator = (level: number) => setSelectedBuilding({ type: `excavator${level}` }); const handleSelectConveyor = () => setSelectedBuilding({ type: 'conveyor' }); - const handleDeleteStructure = () => setSelectedBuilding({ type: 'delete' }); + const handleDeleteBuilding = () => setSelectedBuilding({ type: 'delete' }); const orbitControlsRef = useRef(null); const cameraRef = useRef(null); @@ -55,7 +55,7 @@ const RenderGrid: React.FC = () => { onSelectAssembler={handleSelectAssembler} onSelectExcavator={handleSelectExcavator} onSelectConveyor={handleSelectConveyor} - onSelectDelete={handleDeleteStructure} + onSelectDelete={handleDeleteBuilding} showGrid={showGrid} showAxes={showAxes} /> From 8413260dc68816cee49d92a1e72ca548a9376954 Mon Sep 17 00:00:00 2001 From: chdonncha Date: Tue, 27 Aug 2024 22:30:27 +0100 Subject: [PATCH 3/5] :sparkles: Add gridoutline for placing conveyor belts --- src/components/Grid/Grid.tsx | 40 ++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/components/Grid/Grid.tsx b/src/components/Grid/Grid.tsx index 4d53d0d..53a2a91 100644 --- a/src/components/Grid/Grid.tsx +++ b/src/components/Grid/Grid.tsx @@ -38,6 +38,7 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = y: i * CELL_SIZE - GRID_SIZE / 2, type: map[i][j], building: null, + isTemporary: false, }); } } @@ -69,7 +70,18 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = const handleMouseUp = (event: ThreeEvent) => { if (event.nativeEvent.button !== 0) return; // Ensure it is a left-click if (isDragging && selectedBuilding.type === 'conveyor') { - setCells(tempCells); + const finalizedCells = tempCells.map(cell => { + if (cell.type === 'conveyor') { + return { + ...cell, + building: 'conveyor', + }; + } + return cell; + }); + + setCells(finalizedCells); + setTempCells(finalizedCells); } setIsDragging(false); setDragStart(null); @@ -94,6 +106,7 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = ...cell, type: 'grass', // Revert to grass building: null, + isTemporary: false, }; } return cell; @@ -134,6 +147,7 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = ...cell, type: buildingType, building: buildingType, + isTemporary: false, }; } return cell; @@ -159,8 +173,8 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = if (cell.x === dragStart.x && cell.y >= yMin && cell.y <= yMax) { return { ...cell, - type: selectedBuilding.type, - building: selectedBuilding.type, + type: 'conveyor', + building: null, // Do not display the building sprite yet }; } } else if (dragStart.y === y) { @@ -168,8 +182,8 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = if (cell.y === dragStart.y && cell.x >= xMin && cell.x <= xMax) { return { ...cell, - type: selectedBuilding.type, - building: selectedBuilding.type, + type: 'conveyor', + building: null, // Do not display the building sprite yet }; } } @@ -182,6 +196,9 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = const getColor = (cell, currentSelected) => { if (currentSelected && cell.x === currentSelected.x && cell.y === currentSelected.y) return 'lightgrey'; + if (cell.building === null && cell.type === 'conveyor') { + return 'transparent'; // or return 'none' to show no color for temporary cells + } switch (cell.type) { case 'assembler1A': case 'assembler1B': @@ -210,7 +227,7 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = case 'excavator3D': return 'yellow'; case 'conveyor': - return 'dimgrey'; + return 'dimgrey'; // This color is applied when the conveyor is fully placed case 'water': return 'blue'; case 'grass': @@ -300,6 +317,17 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = GRID_DIVISIONS={GRID_DIVISIONS} /> )} + {cell.type === 'conveyor' && !cell.building && ( + + )} ))} From 69426268cfdd5cd934412571e81dbde4b66c502c Mon Sep 17 00:00:00 2001 From: chdonncha Date: Thu, 29 Aug 2024 18:59:24 +0100 Subject: [PATCH 4/5] :recycle: Extracted getColor and getBuildingTexture functions into utility files for improved code organisation --- src/components/Grid/Grid.tsx | 102 +---------------------------------- src/utils/gridUtils.ts | 100 ++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 101 deletions(-) create mode 100644 src/utils/gridUtils.ts diff --git a/src/components/Grid/Grid.tsx b/src/components/Grid/Grid.tsx index 53a2a91..a7f2399 100644 --- a/src/components/Grid/Grid.tsx +++ b/src/components/Grid/Grid.tsx @@ -2,16 +2,7 @@ import { ThreeEvent } from '@react-three/fiber'; import React, { useState } from 'react'; import { GridSquare } from './GridSquare'; - -import conveyorTexture from '../../textures/conveyor.png'; -import assemblerMultispriteA from '../../textures/excavatorA.png'; -import excavatorMultispriteA from '../../textures/excavatorA.png'; -import excavatorMultispriteB from '../../textures/excavatorB.png'; -import assemblerMultispriteB from '../../textures/excavatorB.png'; -import excavatorMultispriteC from '../../textures/excavatorC.png'; -import assemblerMultispriteC from '../../textures/excavatorC.png'; -import excavatorMultispriteD from '../../textures/excavatorD.png'; -import assemblerMultispriteD from '../../textures/excavatorD.png'; +import { getColor, getBuildingTexture } from '../../utils/gridUtils'; import { GridSprite } from '../CitySprite/GridSprite'; import { GridOutline } from '../GridOutline/GridOutline'; import './Grid.css'; @@ -194,97 +185,6 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = setTempCells(newTempCells); }; - const getColor = (cell, currentSelected) => { - if (currentSelected && cell.x === currentSelected.x && cell.y === currentSelected.y) return 'lightgrey'; - if (cell.building === null && cell.type === 'conveyor') { - return 'transparent'; // or return 'none' to show no color for temporary cells - } - switch (cell.type) { - case 'assembler1A': - case 'assembler1B': - case 'assembler1C': - case 'assembler1D': - case 'assembler2A': - case 'assembler2B': - case 'assembler2C': - case 'assembler2D': - case 'assembler3A': - case 'assembler3B': - case 'assembler3C': - case 'assembler3D': - return 'lightgreen'; - case 'excavator1A': - case 'excavator1B': - case 'excavator1C': - case 'excavator1D': - case 'excavator2A': - case 'excavator2B': - case 'excavator2C': - case 'excavator2D': - case 'excavator3A': - case 'excavator3B': - case 'excavator3C': - case 'excavator3D': - return 'yellow'; - case 'conveyor': - return 'dimgrey'; // This color is applied when the conveyor is fully placed - case 'water': - return 'blue'; - case 'grass': - return 'lime'; - case 'gold': - return 'gold'; - case 'iron': - return 'grey'; - case 'coal': - return 'black'; - default: - return 'white'; - } - }; - - const getBuildingTexture = (type: any) => { - switch (type) { - case 'assembler1A': - case 'assembler2A': - case 'assembler3A': - return assemblerMultispriteA; - case 'assembler1B': - case 'assembler2B': - case 'assembler3B': - return assemblerMultispriteB; - case 'assembler1C': - case 'assembler2C': - case 'assembler3C': - return assemblerMultispriteC; - case 'assembler1D': - case 'assembler2D': - case 'assembler3D': - return assemblerMultispriteD; - case 'excavator1A': - case 'excavator2A': - case 'excavator3A': - return excavatorMultispriteA; - case 'excavator1B': - case 'excavator2B': - case 'excavator3B': - return excavatorMultispriteB; - case 'excavator1C': - case 'excavator2C': - case 'excavator3C': - return excavatorMultispriteC; - case 'excavator1D': - case 'excavator2D': - case 'excavator3D': - return excavatorMultispriteD; - case 'conveyor': - return conveyorTexture; - default: - console.warn('Unknown building type:', type); // Warning for unknown types - return null; // Default or unknown type - } - }; - return ( <> {hoveredCell && selectedBuilding.type !== 'conveyor' && selectedBuilding.type !== 'delete' && selectedBuilding.type && ( diff --git a/src/utils/gridUtils.ts b/src/utils/gridUtils.ts new file mode 100644 index 0000000..74c13fa --- /dev/null +++ b/src/utils/gridUtils.ts @@ -0,0 +1,100 @@ +import conveyorTexture from '../textures/conveyor.png'; +import assemblerMultispriteA from '../textures/excavatorA.png'; +import excavatorMultispriteA from '../textures/excavatorA.png'; +import excavatorMultispriteB from '../textures/excavatorB.png'; +import assemblerMultispriteB from '../textures/excavatorB.png'; +import excavatorMultispriteC from '../textures/excavatorC.png'; +import assemblerMultispriteC from '../textures/excavatorC.png'; +import excavatorMultispriteD from '../textures/excavatorD.png'; +import assemblerMultispriteD from '../textures/excavatorD.png'; + +export const getColor = (cell, currentSelected) => { + if (currentSelected && cell.x === currentSelected.x && cell.y === currentSelected.y) return 'lightgrey'; + if (cell.building === null && cell.type === 'conveyor') { + return 'transparent'; + } + switch (cell.type) { + case 'assembler1A': + case 'assembler1B': + case 'assembler1C': + case 'assembler1D': + case 'assembler2A': + case 'assembler2B': + case 'assembler2C': + case 'assembler2D': + case 'assembler3A': + case 'assembler3B': + case 'assembler3C': + case 'assembler3D': + return 'lightgreen'; + case 'excavator1A': + case 'excavator1B': + case 'excavator1C': + case 'excavator1D': + case 'excavator2A': + case 'excavator2B': + case 'excavator2C': + case 'excavator2D': + case 'excavator3A': + case 'excavator3B': + case 'excavator3C': + case 'excavator3D': + return 'yellow'; + case 'conveyor': + return 'dimgrey'; + case 'water': + return 'blue'; + case 'grass': + return 'lime'; + case 'gold': + return 'gold'; + case 'iron': + return 'grey'; + case 'coal': + return 'black'; + default: + return 'white'; + } +}; + +export const getBuildingTexture = (type: any) => { + switch (type) { + case 'assembler1A': + case 'assembler2A': + case 'assembler3A': + return assemblerMultispriteA; + case 'assembler1B': + case 'assembler2B': + case 'assembler3B': + return assemblerMultispriteB; + case 'assembler1C': + case 'assembler2C': + case 'assembler3C': + return assemblerMultispriteC; + case 'assembler1D': + case 'assembler2D': + case 'assembler3D': + return assemblerMultispriteD; + case 'excavator1A': + case 'excavator2A': + case 'excavator3A': + return excavatorMultispriteA; + case 'excavator1B': + case 'excavator2B': + case 'excavator3B': + return excavatorMultispriteB; + case 'excavator1C': + case 'excavator2C': + case 'excavator3C': + return excavatorMultispriteC; + case 'excavator1D': + case 'excavator2D': + case 'excavator3D': + return excavatorMultispriteD; + case 'conveyor': + return conveyorTexture; + default: + console.warn('Unknown building type:', type); + return null; + } +}; From a86d30bbc2b7377e4b6bb89828a1f8bf07f924ac Mon Sep 17 00:00:00 2001 From: chdonncha Date: Fri, 30 Aug 2024 19:08:28 +0100 Subject: [PATCH 5/5] :sparkles: Prevent building of conveyors over water --- src/components/Grid/Grid.tsx | 48 +++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/src/components/Grid/Grid.tsx b/src/components/Grid/Grid.tsx index a7f2399..72597fc 100644 --- a/src/components/Grid/Grid.tsx +++ b/src/components/Grid/Grid.tsx @@ -61,18 +61,26 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = const handleMouseUp = (event: ThreeEvent) => { if (event.nativeEvent.button !== 0) return; // Ensure it is a left-click if (isDragging && selectedBuilding.type === 'conveyor') { - const finalizedCells = tempCells.map(cell => { - if (cell.type === 'conveyor') { - return { - ...cell, - building: 'conveyor', - }; - } - return cell; - }); + const validPlacement = tempCells.every(cell => cell.type !== 'conveyor' || cell.validPlacement); + + if (validPlacement) { + const finalizedCells = tempCells.map(cell => { + if (cell.type === 'conveyor') { + return { + ...cell, + building: 'conveyor', + isTemporary: false, + }; + } + return cell; + }); - setCells(finalizedCells); - setTempCells(finalizedCells); + setCells(finalizedCells); + setTempCells(finalizedCells); + } else { + // If the placement is invalid, reset tempCells to match cells (remove grid outlines) + setTempCells(cells); + } } setIsDragging(false); setDragStart(null); @@ -156,6 +164,18 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = const yMin = Math.min(dragStart.y, y); const yMax = Math.max(dragStart.y, y); + let validPlacement = true; + + // Check if any segment of the conveyor overlaps water + for (let i = xMin; i <= xMax; i += CELL_SIZE) { + for (let j = yMin; j <= yMax; j += CELL_SIZE) { + const cell = cells.find(cell => cell.x === i && cell.y === j); + if (cell && cell.type === 'water') { + validPlacement = false; + } + } + } + const newTempCells = cells.map(cell => { if (selectedBuilding.type === 'conveyor') { // Allow conveyors only in straight lines @@ -166,6 +186,8 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = ...cell, type: 'conveyor', building: null, // Do not display the building sprite yet + isTemporary: true, + validPlacement, }; } } else if (dragStart.y === y) { @@ -175,6 +197,8 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = ...cell, type: 'conveyor', building: null, // Do not display the building sprite yet + isTemporary: true, + validPlacement, }; } } @@ -225,7 +249,7 @@ const Grid: React.FC = ({ selectedBuilding, currentSelected, map }) = cell.y + CELL_SIZE * 0.5, ]} cellSize={CELL_SIZE / 2} - valid={true} // Assume the conveyor placement is valid for now + valid={cell.validPlacement} // Use validPlacement to determine color /> )}