Merge pull request #754 from redbirdly/main
Update circuitcore.js, fix error and add destructable circuits
This commit is contained in:
commit
591eada295
|
|
@ -98,15 +98,23 @@ function createCircuitFrame(pixel, width_, height_, center=true, rotation=0) {
|
||||||
var [rx, ry] = rotateCoordinate(x, y, rotation);
|
var [rx, ry] = rotateCoordinate(x, y, rotation);
|
||||||
var px = pixel.x + rx;
|
var px = pixel.x + rx;
|
||||||
var py = pixel.y + ry;
|
var py = pixel.y + ry;
|
||||||
|
|
||||||
if (!(0 <= px && px < width && 0 <= py && py < height)) {continue;}
|
if (!(0 <= px && px < width && 0 <= py && py < height)) {continue;}
|
||||||
|
|
||||||
|
// Create the pixel
|
||||||
if (!pixelMap[px] || pixelMap[px][py] === undefined) {
|
if (!pixelMap[px] || pixelMap[px][py] === undefined) {
|
||||||
createPixel("circuit_material", px, py);
|
createPixel("circuit_material", px, py);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the core position property
|
||||||
|
if (pixelMap[px] && pixelMap[px][py] && pixelMap[px][py].element === "circuit_material") {
|
||||||
|
pixelMap[px][py].corePosition = { x: pixel.x, y: pixel.y };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function createPins(pixel, pins, rotation=0) {
|
function createPins(pixel, pins, rotation=0) {
|
||||||
for (var i = 0; i < pins.length; i++) {
|
for (var i = 0; i < pins.length; i++) {
|
||||||
var [rx, ry] = rotateCoordinate(pins[i][0], pins[i][1], rotation);
|
var [rx, ry] = rotateCoordinate(pins[i][0], pins[i][1], rotation);
|
||||||
|
|
@ -691,75 +699,75 @@ elements.four_bit_SIPO_shift_register_circuit = {
|
||||||
};
|
};
|
||||||
|
|
||||||
elements.four_bit_program_counter_circuit = {
|
elements.four_bit_program_counter_circuit = {
|
||||||
tick: function(pixel) {
|
tick: function(pixel) {
|
||||||
var pins = [
|
var pins = [
|
||||||
// Data inputs (D0-D3)
|
// Data inputs (D0-D3)
|
||||||
[-3, -3, true], // D0
|
[-3, -3, true], // D0
|
||||||
[-1, -3, true], // D1
|
[-1, -3, true], // D1
|
||||||
[1, -3, true], // D2
|
[1, -3, true], // D2
|
||||||
[3, -3, true], // D3
|
[3, -3, true], // D3
|
||||||
|
|
||||||
// Control inputs (Increment, Write Enable)
|
// Control inputs (Increment, Write Enable)
|
||||||
[5, -1, true], // Increment
|
[5, -1, true], // Increment
|
||||||
[5, 1, true], // Write Enable
|
[5, 1, true], // Write Enable
|
||||||
|
|
||||||
// Outputs (Q0-Q3)
|
// Outputs (Q0-Q3)
|
||||||
[-3, 3, false], // Q0
|
[-3, 3, false], // Q0
|
||||||
[-1, 3, false], // Q1
|
[-1, 3, false], // Q1
|
||||||
[1, 3, false], // Q2
|
[1, 3, false], // Q2
|
||||||
[3, 3, false], // Q3
|
[3, 3, false], // Q3
|
||||||
];
|
];
|
||||||
|
|
||||||
initializeCircuit(pixel, pins, 9, 5);
|
initializeCircuit(pixel, pins, 9, 5);
|
||||||
|
|
||||||
// Read data inputs
|
// Read data inputs
|
||||||
var D = [
|
var D = [
|
||||||
checkPin(pixel, pins, 0),
|
checkPin(pixel, pins, 0),
|
||||||
checkPin(pixel, pins, 1),
|
checkPin(pixel, pins, 1),
|
||||||
checkPin(pixel, pins, 2),
|
checkPin(pixel, pins, 2),
|
||||||
checkPin(pixel, pins, 3)
|
checkPin(pixel, pins, 3)
|
||||||
];
|
];
|
||||||
|
|
||||||
// Read control inputs
|
// Read control inputs
|
||||||
var Increment = checkPin(pixel, pins, 4);
|
var Increment = checkPin(pixel, pins, 4);
|
||||||
var WriteEnable = checkPin(pixel, pins, 5);
|
var WriteEnable = checkPin(pixel, pins, 5);
|
||||||
|
|
||||||
// Initialize the state if not already done
|
// Initialize the state if not already done
|
||||||
if (pixel._state === undefined) {
|
if (pixel._state === undefined) {
|
||||||
pixel._state = [false, false, false, false];
|
pixel._state = [false, false, false, false];
|
||||||
pixel.prevIncrement = false; // Previous state of Increment pin
|
pixel.prevIncrement = false; // Previous state of Increment pin
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the state to a 4-bit binary number
|
// Convert the state to a 4-bit binary number
|
||||||
var stateValue = binaryArrayToNumber(pixel._state);
|
var stateValue = binaryArrayToNumber(pixel._state);
|
||||||
|
|
||||||
// Detect the positive edge on the Increment pin
|
// Detect the positive edge on the Increment pin
|
||||||
if (Increment && !pixel.prevIncrement) {
|
if (Increment && !pixel.prevIncrement) {
|
||||||
stateValue = (stateValue + 1) % 16; // Ensure the value wraps around at 4 bits
|
stateValue = (stateValue + 1) % 16; // Ensure the value wraps around at 4 bits
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the register state if WriteEnable is active
|
// Update the register state if WriteEnable is active
|
||||||
if (WriteEnable) {
|
if (WriteEnable) {
|
||||||
stateValue = binaryArrayToNumber(D); // Load data inputs into state
|
stateValue = binaryArrayToNumber(D); // Load data inputs into state
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the state
|
// Update the state
|
||||||
pixel._state = [
|
pixel._state = [
|
||||||
(stateValue & 8) !== 0,
|
(stateValue & 8) !== 0,
|
||||||
(stateValue & 4) !== 0,
|
(stateValue & 4) !== 0,
|
||||||
(stateValue & 2) !== 0,
|
(stateValue & 2) !== 0,
|
||||||
(stateValue & 1) !== 0
|
(stateValue & 1) !== 0
|
||||||
];
|
];
|
||||||
|
|
||||||
// Output the register state
|
// Output the register state
|
||||||
setPin(pixel, pins, 6, pixel._state[0]); // Q0
|
setPin(pixel, pins, 6, pixel._state[0]); // Q0
|
||||||
setPin(pixel, pins, 7, pixel._state[1]); // Q1
|
setPin(pixel, pins, 7, pixel._state[1]); // Q1
|
||||||
setPin(pixel, pins, 8, pixel._state[2]); // Q2
|
setPin(pixel, pins, 8, pixel._state[2]); // Q2
|
||||||
setPin(pixel, pins, 9, pixel._state[3]); // Q3
|
setPin(pixel, pins, 9, pixel._state[3]); // Q3
|
||||||
|
|
||||||
// Update previous state of Increment pin
|
// Update previous state of Increment pin
|
||||||
pixel.prevIncrement = Increment;
|
pixel.prevIncrement = Increment;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
elements.four_bit_register_circuit = {
|
elements.four_bit_register_circuit = {
|
||||||
|
|
@ -1200,6 +1208,11 @@ elements.very_fast_clock = {
|
||||||
tick: general_clock(8, 4),
|
tick: general_clock(8, 4),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
elements.fast_clock = {
|
||||||
|
color: "#FFAAFF",
|
||||||
|
tick: general_clock(16, 8),
|
||||||
|
}
|
||||||
|
|
||||||
var addDisplayCallback = function(pixel, pins, w, h) {
|
var addDisplayCallback = function(pixel, pins, w, h) {
|
||||||
for (var y = 1; y < h - 1; y++) {
|
for (var y = 1; y < h - 1; y++) {
|
||||||
for (var x = 1; x < w - 1; x++) {
|
for (var x = 1; x < w - 1; x++) {
|
||||||
|
|
@ -1324,15 +1337,84 @@ elements.simple_double_seven_segment_display = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function malfunction_chip(pixel) {
|
||||||
|
var emptySpaces = [];
|
||||||
|
|
||||||
|
// Search in a 5x5 neighborhood for empty spaces
|
||||||
|
for (var dy = -2; dy <= 2; dy++) {
|
||||||
|
for (var dx = -2; dx <= 2; dx++) {
|
||||||
|
var neighborX = pixel.x + dx;
|
||||||
|
var neighborY = pixel.y + dy;
|
||||||
|
if (pixelMap[neighborX] && pixelMap[neighborX][neighborY] === undefined) {
|
||||||
|
emptySpaces.push({ x: neighborX, y: neighborY });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emptySpaces.length > 0) {
|
||||||
|
// Randomly select one of the empty spaces
|
||||||
|
var randomSpace = emptySpaces[Math.floor(Math.random() * emptySpaces.length)];
|
||||||
|
|
||||||
|
// Determine what to spawn based on probability
|
||||||
|
var rand = Math.random();
|
||||||
|
if (rand < 0.7) {
|
||||||
|
createPixel("electric", randomSpace.x, randomSpace.y);
|
||||||
|
} else if (rand < 0.99) {
|
||||||
|
createPixel("fire", randomSpace.x, randomSpace.y);
|
||||||
|
} else {
|
||||||
|
createPixel("explosion", randomSpace.x, randomSpace.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
elements.circuit_material = {
|
elements.circuit_material = {
|
||||||
color: "#444444",
|
color: "#444444",
|
||||||
category: "logic"
|
category: "logic",
|
||||||
|
state: "solid",
|
||||||
|
behavior: behaviors.WALL,
|
||||||
|
hoverStat: function(pixel) {
|
||||||
|
return `Circuit: ${pixel.corePosition}`;
|
||||||
|
},
|
||||||
|
tick: function(pixel) {
|
||||||
|
// Make it that extreme temperatures can stop the chip from working (for realism)
|
||||||
|
if (Math.random() < 0.003) { // Chance to check for temperature or nearby particles
|
||||||
|
// Check temperature
|
||||||
|
if (pixel.temp > 120) {
|
||||||
|
// Replace the circuit core with lead if overheating
|
||||||
|
if (pixel.corePosition && Math.random() < (0.00015) * (pixel.temp - 120)) {
|
||||||
|
var corePos = pixel.corePosition;
|
||||||
|
if (pixelMap[corePos.x] && pixelMap[corePos.x][corePos.y]) {
|
||||||
|
deletePixel(corePos.x, corePos.y);
|
||||||
|
createPixel("lead", corePos.x, corePos.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Randomly trigger malfunction if overheating
|
||||||
|
if (Math.random() < 0.001 * (pixel.temp - 120)) {
|
||||||
|
malfunction_chip(pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Break the circuit material itself if overheating
|
||||||
|
if (Math.random() < 0.001 * (pixel.temp - 120)) {
|
||||||
|
var px = pixel.x;
|
||||||
|
var py = pixel.y;
|
||||||
|
deletePixel(px, py);
|
||||||
|
if (Math.random() < 0.5) {createPixel("lead", px, py);}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
elements.input_pin = {
|
elements.input_pin = {
|
||||||
color: "#DDAA33",
|
color: "#DDAA33",
|
||||||
category: "logic",
|
category: "logic",
|
||||||
|
state: "solid",
|
||||||
active: false,
|
active: false,
|
||||||
|
stateHigh: "lead",
|
||||||
|
tempHigh: 570,
|
||||||
|
behavior: behaviors.WALL,
|
||||||
tick: function(pixel) {
|
tick: function(pixel) {
|
||||||
pixel.active = false;
|
pixel.active = false;
|
||||||
var neighbors = getNeighbors(pixel);
|
var neighbors = getNeighbors(pixel);
|
||||||
|
|
@ -1349,7 +1431,11 @@ elements.input_pin = {
|
||||||
elements.output_pin = {
|
elements.output_pin = {
|
||||||
color: "#AAAAAA",
|
color: "#AAAAAA",
|
||||||
category: "logic",
|
category: "logic",
|
||||||
|
state: "solid",
|
||||||
active: false,
|
active: false,
|
||||||
|
stateHigh: "lead",
|
||||||
|
tempHigh: 570,
|
||||||
|
behavior: behaviors.WALL,
|
||||||
tick: function(pixel) {
|
tick: function(pixel) {
|
||||||
var neighbors = getNeighbors(pixel);
|
var neighbors = getNeighbors(pixel);
|
||||||
for (var i = 0;i < neighbors.length;i++) {
|
for (var i = 0;i < neighbors.length;i++) {
|
||||||
|
|
@ -1486,6 +1572,7 @@ var circuits = [
|
||||||
{ circuit: elements.medium_clock },
|
{ circuit: elements.medium_clock },
|
||||||
{ circuit: elements.fast_clock },
|
{ circuit: elements.fast_clock },
|
||||||
{ circuit: elements.very_fast_clock },
|
{ circuit: elements.very_fast_clock },
|
||||||
|
{ circuit: elements.very_fast_clock },
|
||||||
// Displays/visual circuits: white
|
// Displays/visual circuits: white
|
||||||
{ circuit: elements.simple_seven_segment_display, color: cc_WHITE, size: [5, 9, false] },
|
{ circuit: elements.simple_seven_segment_display, color: cc_WHITE, size: [5, 9, false] },
|
||||||
{ circuit: elements.simple_double_seven_segment_display, color: cc_WHITE, size: [9, 9, false] },
|
{ circuit: elements.simple_double_seven_segment_display, color: cc_WHITE, size: [9, 9, false] },
|
||||||
|
|
@ -1497,6 +1584,32 @@ circuits.forEach(circuitInfo => {
|
||||||
circuitInfo.circuit.maxSize = 1;
|
circuitInfo.circuit.maxSize = 1;
|
||||||
circuitInfo.circuit.isCircuitCore = true;
|
circuitInfo.circuit.isCircuitCore = true;
|
||||||
circuitInfo.circuit.previewSize = circuitInfo.size;
|
circuitInfo.circuit.previewSize = circuitInfo.size;
|
||||||
|
|
||||||
|
// Exclude circuits without a frame
|
||||||
|
if (circuitInfo.size) {
|
||||||
|
var previousCircuitTick = circuitInfo.circuit.tick;
|
||||||
|
circuitInfo.circuit.tick = function(pixel) {
|
||||||
|
previousCircuitTick(pixel);
|
||||||
|
|
||||||
|
// Don't constantly check
|
||||||
|
if (Math.random() < 0.1) {
|
||||||
|
// If there aren't 4 neighboring circuit_material elements then remove the circuit's core
|
||||||
|
var neighbors = getNeighbors(pixel);
|
||||||
|
var circuitMaterialCount = 0;
|
||||||
|
for (var i = 0;i < neighbors.length;i++) {
|
||||||
|
if (neighbors[i].element == "circuit_material") {
|
||||||
|
circuitMaterialCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (circuitMaterialCount < 2) {
|
||||||
|
deletePixel(pixel.x, pixel.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixel.temp += Math.random(0, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var circuitRotation = 0;
|
var circuitRotation = 0;
|
||||||
|
|
@ -1508,41 +1621,41 @@ document.addEventListener('keydown', function(event) {
|
||||||
});
|
});
|
||||||
|
|
||||||
function drawCircuitExtras() {
|
function drawCircuitExtras() {
|
||||||
if (elements[currentElement].isCircuitCore && elements[currentElement].previewSize) {
|
if (elements[currentElement].isCircuitCore && elements[currentElement].previewSize) {
|
||||||
var circuitWidth = elements[currentElement].previewSize[0];
|
var circuitWidth = elements[currentElement].previewSize[0];
|
||||||
var circuitHeight = elements[currentElement].previewSize[1];
|
var circuitHeight = elements[currentElement].previewSize[1];
|
||||||
var centered = elements[currentElement].previewSize[2];
|
var centered = elements[currentElement].previewSize[2];
|
||||||
var rotation = circuitRotation;
|
var rotation = circuitRotation;
|
||||||
|
|
||||||
var startX = 0;
|
var startX = 0;
|
||||||
var startY = 0;
|
var startY = 0;
|
||||||
var endX = circuitWidth - 1;
|
var endX = circuitWidth - 1;
|
||||||
var endY = circuitHeight - 1;
|
var endY = circuitHeight - 1;
|
||||||
|
|
||||||
if (centered) {
|
if (centered) {
|
||||||
startX = -Math.floor(circuitWidth / 2);
|
startX = -Math.floor(circuitWidth / 2);
|
||||||
startY = -Math.floor(circuitHeight / 2);
|
startY = -Math.floor(circuitHeight / 2);
|
||||||
endX = Math.floor(circuitWidth / 2);
|
endX = Math.floor(circuitWidth / 2);
|
||||||
endY = Math.floor(circuitHeight / 2);
|
endY = Math.floor(circuitHeight / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var y = startY; y <= endY; y++) {
|
for (var y = startY; y <= endY; y++) {
|
||||||
for (var x = startX; x <= endX; x++) {
|
for (var x = startX; x <= endX; x++) {
|
||||||
// if (!(0 <= x && x < width && 0 <= y && y < height)) {continue;}
|
// if (!(0 <= x && x < width && 0 <= y && y < height)) {continue;}
|
||||||
|
|
||||||
var [rx, ry] = rotateCoordinate(x, y, rotation);
|
var [rx, ry] = rotateCoordinate(x, y, rotation);
|
||||||
var px = mousePos.x + rx;
|
var px = mousePos.x + rx;
|
||||||
var py = mousePos.y + ry;
|
var py = mousePos.y + ry;
|
||||||
|
|
||||||
ctx.fillStyle = "rgba(255, 255, 255, 0.1)";
|
ctx.fillStyle = "rgba(255, 255, 255, 0.1)";
|
||||||
if ((rotation != 0 && !centered) || (0 <= px && px < width && 0 <= py && py < height) && pixelMap[px][py]) {
|
if ((rotation != 0 && !centered) || (0 <= px && px < width && 0 <= py && py < height) && pixelMap[px][py]) {
|
||||||
ctx.fillStyle = "rgba(255, 0, 0, 0.3)";
|
ctx.fillStyle = "rgba(255, 0, 0, 0.3)";
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.fillRect(px * pixelSize, py * pixelSize, pixelSize, pixelSize);
|
ctx.fillRect(px * pixelSize, py * pixelSize, pixelSize, pixelSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
runAfterLoad(() => {
|
runAfterLoad(() => {
|
||||||
|
|
@ -1550,6 +1663,7 @@ runAfterLoad(() => {
|
||||||
drawPixels = function(forceTick=false) {
|
drawPixels = function(forceTick=false) {
|
||||||
originalDrawPixels3(forceTick);
|
originalDrawPixels3(forceTick);
|
||||||
drawCircuitExtras();
|
drawCircuitExtras();
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
resetInterval(tps);
|
resetInterval(tps);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue