From 94b9fe0beb6f4a9a4fdf9b46f7087cbc160018ac Mon Sep 17 00:00:00 2001 From: RaihanRasheedApurbo Date: Fri, 8 Nov 2024 17:51:00 +0000 Subject: [PATCH] fix: allow cows to be placed on a non-road square (#1746) * allow cows to be placed on a non road square * fix bug during playing a custom game * Merge branch 'master' into Allow-for-cows-to-be-placed-on-a-non-road-square Co-Authored-By: Raihan Rasheed Co-Authored-By: Florian Aucomte --- game/static/game/js/animation.js | 14 ++-- game/static/game/js/cow.js | 11 ++- game/static/game/js/drawing.js | 7 +- game/static/game/js/level_editor.js | 113 +++++++++++++--------------- 4 files changed, 73 insertions(+), 72 deletions(-) diff --git a/game/static/game/js/animation.js b/game/static/game/js/animation.js index e57fe656b..d504afa8b 100644 --- a/game/static/game/js/animation.js +++ b/game/static/game/js/animation.js @@ -38,11 +38,11 @@ ocargo.Animation.prototype.isFinished = function() { ocargo.Animation.prototype.addCows = function() { let cows = this.model.cows; - + for (let i = 0 ; i < cows.length ; i++){ let cow = cows[i]; - for (let j = 0; j < cow.potentialNodes.length; j++) { - const cowImage = this.drawing.renderCow(cow.id, cow.potentialNodes[j].coordinate, cow.potentialNodes[j], 0, cow.type); + for (let j = 0; j < cow.coordinates.length; j++) { + const cowImage = this.drawing.renderCow(cow.id, cow.coordinates[j], cow.potentialNodes[j], 0, cow.type); this.numberOfCowsOnMap++; this.activeCows.push(cowImage); } @@ -385,9 +385,9 @@ ocargo.Animation.prototype.performAnimation = function(animation) { this.drawing.transitionTrafficLight(animation.id, animation.colour, duration/2); break; case 'cow_leave': - this.numberOfCowsOnMap--; - var cow = this._extractCowAt(animation.coordinate); - this.drawing.removeCow(cow, duration); // remove it from drawing + this.numberOfCowsOnMap--; + var cow = this._extractCowAt(animation.coordinate); + this.drawing.removeCow(cow, duration); // remove it from drawing break; case 'console': ocargo.pythonControl.appendToConsole(animation.text); @@ -399,7 +399,7 @@ ocargo.Animation.prototype.performAnimation = function(animation) { ocargo.Animation.prototype._extractCowAt = function(coordinate) { for (var i = 0; i < this.activeCows.length; i++) { var cow = this.activeCows[i]; - if (cow.coordinate == coordinate) { + if (coordinate.equals(cow.coordinate)) { this.activeCows.splice(i, 1); // remove cow from array return cow; } diff --git a/game/static/game/js/cow.js b/game/static/game/js/cow.js index 03eedb410..662903a1f 100644 --- a/game/static/game/js/cow.js +++ b/game/static/game/js/cow.js @@ -8,12 +8,15 @@ ocargo.Cow = function(id, data, nodes) { this.type = data.type; this.potentialNodes = []; // Potential nodes at which a cow could appear this.activeNodes = {}; // Actual nodes at which cows will appear during a run. + this.coordinates = []; // coordinates of the cows, some cows may have null nodes that denotes they are outside of road + for(var i = 0; i < data.potentialCoordinates.length; i++) { var coordinate = new ocargo.Coordinate(data.potentialCoordinates[i].x, data.potentialCoordinates[i].y); - var node = ocargo.Node.findNodeByCoordinate(coordinate, nodes) - this.potentialNodes.push(ocargo.Node.findNodeByCoordinate(coordinate, nodes)); - var coordinate_str = JSON.stringify(node.coordinate) - this.activeNodes[coordinate_str] = ocargo.Cow.ACTIVE + var node = ocargo.Node.findNodeByCoordinate(coordinate, nodes); + this.potentialNodes.push(node); + var coordinate_str = JSON.stringify(coordinate); + this.activeNodes[coordinate_str] = ocargo.Cow.ACTIVE; + this.coordinates.push(coordinate); } }; ocargo.Cow.prototype.reset = function() { diff --git a/game/static/game/js/drawing.js b/game/static/game/js/drawing.js index 10caee484..42b94d1bd 100644 --- a/game/static/game/js/drawing.js +++ b/game/static/game/js/drawing.js @@ -753,8 +753,11 @@ ocargo.Drawing = function (startingPosition) { let xOffset = 0 let yOffset = 0 let rotation = 0 - - if (node.connectedNodes.length === 1) { + if (node == null) { + // the cow is outside of road + rotation = 0 + } + else if (node.connectedNodes.length === 1) { // Deadends let previousNode = node.connectedNodes[0] let nextNode = {} diff --git a/game/static/game/js/level_editor.js b/game/static/game/js/level_editor.js index 7ad26bcf2..888116bf3 100644 --- a/game/static/game/js/level_editor.js +++ b/game/static/game/js/level_editor.js @@ -1061,7 +1061,7 @@ ocargo.LevelEditor = function(levelId) { } else { closeTrashcan(); } - } +} function openTrashcan() { $('#trashcanLidOpen').css('display', 'block'); @@ -1226,8 +1226,8 @@ ocargo.LevelEditor = function(levelId) { if (cows) { for (var i = 0; i < cows.length; i++) { var internalCow = cows[i]; - if (internalCow.controlledNode) { - mark(internalCow.controlledNode.coordinate, internalCow.data.group.color, 0.3, true); + if (internalCow.coordinate) { + mark(internalCow.coordinate, internalCow.data.group.color, 0.3, true); } } } @@ -1683,7 +1683,7 @@ ocargo.LevelEditor = function(levelId) { var bBox = image.getBBox(); imageWidth = bBox.width; imageHeight = bBox.height; - + var paperPosition = paper.position(); originX = x - paperPosition.left + paper.scrollLeft() - imageWidth/2; originY = y - paperPosition.top + paper.scrollTop() - imageHeight/2; @@ -1699,33 +1699,32 @@ ocargo.LevelEditor = function(levelId) { if (trashcanOpen) { cow.destroy(); - } else if (isValidDraggedCowPlacement(controlledCoord, cow)) { - // Add back to the list of cows if on valid nodes - var controlledNode = ocargo.Node.findNodeByCoordinate(controlledCoord, nodes); - cow.controlledNode = controlledNode; - cow.valid = true; - drawing.setCowImagePosition(controlledCoord, image, controlledNode); + closeTrashcan(); } else { - cow.controlledNode = null; - cow.valid = false; - - var cowX = paperX; - var cowY = paperY; - - if (paperWidth < paperX + imageWidth) { - cowX = paperWidth - imageWidth + cow.coordinate = controlledCoord; + cow.valid = isValidDraggedCowPlacement(controlledCoord, cow); + if (cow.isOnRoad()) { + const controlledNode = ocargo.Node.findNodeByCoordinate(controlledCoord, nodes); + drawing.setCowImagePosition(controlledCoord, image, controlledNode); } - - if (paperHeight < paperY + imageHeight) { - cowY = paperHeight - imageHeight + else { + var cowX = paperX; + var cowY = paperY; + + if (paperWidth < paperX + imageWidth) { + cowX = paperWidth - imageWidth + } + + if (paperHeight < paperY + imageHeight) { + cowY = paperHeight - imageHeight + } + + image.transform('t' + cowX + ',' + cowY); } - - image.transform('t' + cowX + ',' + cowY); } - adjustCowGroupMinMaxFields(cow); + adjustCowGroupMinMaxFields(cow); image.attr({'cursor':'pointer'}); - closeTrashcan(); } image.drag(onDragMove, onDragStart, onDragEnd); @@ -1733,12 +1732,11 @@ ocargo.LevelEditor = function(levelId) { } function isValidDraggedCowPlacement(controlledCoord, cow){ - var controlledNode = ocargo.Node.findNodeByCoordinate(controlledCoord, nodes); - if (!controlledNode || isOriginCoordinate(controlledCoord) || isHouseCoordinate(controlledCoord)) + if (isOriginCoordinate(controlledCoord) || isHouseCoordinate(controlledCoord)) return false; for (var i=0; i < cows.length; i++) { var otherCow = cows[i]; - if (otherCow.controlledNode == controlledNode && (cow === "undefined" || cow != otherCow)) + if (cow != otherCow && otherCow.coordinate && otherCow.coordinate.equals(controlledCoord)) return false; } return true; @@ -1764,14 +1762,6 @@ ocargo.LevelEditor = function(levelId) { if (controlledCoord) { markAsBackground(controlledCoord); } - if (cows) { - for( let i = 0; i < cows.length; i++){ - let internalCow = cows[i]; - if(internalCow !== cow && internalCow.controlledNode) { - mark(internalCow.controlledNode.coordinate, internalCow.data.group.color, 0.3, true); - } - } - } if (originNode) { markAsOrigin(originNode.coordinate); } @@ -1783,8 +1773,8 @@ ocargo.LevelEditor = function(levelId) { } function setCowMarkingsOnMouseUp(controlledCoord, cow) { - if (cow.controlledNode) { - markAsBackground(cow.controlledNode.coordinate); + if (cow.isOnRoad()) { + markAsBackground(cow.coordinate); } if (controlledCoord) { mark(controlledCoord, cow.data.group.color, 0.3, true); @@ -1858,20 +1848,18 @@ ocargo.LevelEditor = function(levelId) { function handleDraggableCowMouseUp(e){ let internalCow = new InternalCow({group: cowGroups["group1"]}); let image = internalCow.image; + internalCow.coordinate = controlledCoord; + internalCow.valid = isValidDraggedCowPlacement(controlledCoord, internalCow); - if (isValidDraggedCowPlacement(controlledCoord)) { - internalCow.controlledNode = ocargo.Node.findNodeByCoordinate(controlledCoord, nodes); - internalCow.valid = true; - drawing.setCowImagePosition(controlledCoord, image, internalCow.controlledNode); + if (internalCow.isOnRoad()) { + const controlledNode = ocargo.Node.findNodeByCoordinate(controlledCoord, nodes); + drawing.setCowImagePosition(controlledCoord, image, controlledNode); } else { - internalCow.controlledNode = null; - internalCow.valid = false; - const cowX = e.pageX + paper.scrollLeft() - TAB_PANE_WIDTH - dragged_cow.width / 2; const cowY = e.pageY + paper.scrollTop() - dragged_cow.height / 2; if (draggedObjectOnGrid(e, dragged_cow)) { - image.transform('t' + cowX + ',' + cowY + 'r90'); + image.transform('t' + cowX + ',' + cowY); } else { internalCow.destroy(); } @@ -2488,7 +2476,7 @@ ocargo.LevelEditor = function(levelId) { type: cowGroups[groupId].type}; //editor can only add white cow for now } - var coordinates = cows[i].controlledNode.coordinate; + var coordinates = cows[i].coordinate; var strCoordinates = {'x':coordinates.x, 'y':coordinates.y}; cowGroupData[groupId].potentialCoordinates.push(strCoordinates); } @@ -2920,9 +2908,8 @@ ocargo.LevelEditor = function(levelId) { if (!this.valid) { throw "Error: cannot create actual cow from invalid internal cow!"; } - // Where the cow is placed. - var coordinates = this.controlledNode.coordinate; + var coordinates = this.coordinate; var strCoordinates= {'x':coordinates.x, 'y':coordinates.y}; return { "coordinates": [strCoordinates], @@ -2944,6 +2931,10 @@ ocargo.LevelEditor = function(levelId) { }; + this.isOnRoad = function() { + return this.coordinate && ocargo.Node.findNodeByCoordinate(this.coordinate, nodes); + } + this.updateTheme = function() { let newType = currentTheme == THEMES.city ? ocargo.Cow.PIGEON : ocargo.Cow.WHITE; let transformDimensions = this["image"]["_"]["transform"][0] @@ -2958,10 +2949,9 @@ ocargo.LevelEditor = function(levelId) { this.image.remove(); this.image = drawing.createCowImage(newType); - if (this.controlledNode !== null) { - let controlledNode = this.controlledNode; - let coordinates = controlledNode.coordinate; - drawing.setCowImagePosition(coordinates, this.image, controlledNode); + if (this.isOnRoad()) { + let controlledNode = ocargo.Node.findNodeByCoordinate(coordinates, nodes); + drawing.setCowImagePosition(this.coordinate, this.image, controlledNode); } else { this.image.transform("t" + x + "," + y + " r" + r); } @@ -2972,14 +2962,19 @@ ocargo.LevelEditor = function(levelId) { this.image = drawing.createCowImage(data.group.type); this.valid = false; - if ( data.coordinates && data.coordinates.length > 0 ) { - var coordinates = new ocargo.Coordinate(data.coordinates[0].x, data.coordinates[0].y); - this.controlledNode = ocargo.Node.findNodeByCoordinate(coordinates, nodes); + this.coordinate = new ocargo.Coordinate(data.coordinates[0].x, data.coordinates[0].y); + this.valid = isValidDraggedCowPlacement(this.coordinate, this); - if (this.controlledNode) { - this.valid = true; - drawing.setCowImagePosition(coordinates, this.image, this.controlledNode); + if (this.isOnRoad()) { + const controlledNode = ocargo.Node.findNodeByCoordinate(this.coordinate, nodes); + drawing.setCowImagePosition(this.coordinate, this.image, controlledNode); + } else { + const box = this.image.getBBox(); + // calculate position of the image + const paperX = (this.coordinate.x + 1) * GRID_SPACE_SIZE - box.width/2; + const paperY = (GRID_HEIGHT - this.coordinate.y) * GRID_SPACE_SIZE - box.height/2; + this.image.transform('t' + paperX + ',' + paperY ); } } else { this.image.transform('...t' + (-paper.scrollLeft()) + ',' + paper.scrollTop());