jeudi 8 décembre 2022

How can I generate a random position for an element so that it does not overlap with the position of a different element in javascript?

I am trying to generate random player locations that do not overlap. My initial assumption is that maybe I should (1) generate random positions, (2) check if random positions are overlapping, (3) regenerate positions that are overlapping.

I do not want the flowers or the players to overlap when they are initially generated. Another idea that I had: is there a way I can make a grid system, where players and flowers are initially generated at a spot on the grid and the random function shuffles through grid points?

// game.js

let mapWidth = 200;
let mapHeight = 200;

// let playerWidth = 10;
// let playerHeight = 10;

let flowerWidth = 10;
let flowerHeight = 10;

let player; 

let gameMap = document.createElement('div');
gameMap.setAttribute('id', 'gameMap');
document.body.append(gameMap);
gameMap.style.width = mapWidth  + 'px';
gameMap.style.height = mapHeight + 'px';

const leftKey = "ArrowLeft";
const rightKey = "ArrowRight";
const upKey = "ArrowUp";
const downKey = "ArrowDown";

window.onkeydown = function(event) {
  const keyCode = event.key;
  event.preventDefault();

    if(keyCode == leftKey) {  
      player.stepLeft();
    } else if(keyCode == rightKey) {
      player.stepRight();
    } else if(keyCode == upKey) {
      player.stepUp();
    } else if(keyCode == downKey) {
      player.stepDown();
    } 
}
  

// Game Objects & Players
class Player {
  constructor(posX, posY, playerId, isMe) {
      // this.posX = 0; // for debugging
      // this.posY = 0; // for debugging
      this.posX = posX;
      this.posY = posY;
      this.width = 10;
      this.height = 10;
      this.playerId = playerId;
      this.speed = 2;
      this.isMe = isMe;
      this.elm;
      this.myFlowers = [];
  }
  
  stepRight(){
    // check if step would collide
    if( this.isColliding(this.posX + this.speed, this.posY) == true ){

    }else{
      this.posX = this.posX + this.speed;
      socket.emit('playerMovement', ({x: this.posX, y: this.posY})); 
      this.updatePosition();
    }
    // if not
    // apply step to this.posX 
    // update the DOM (gameMap)
    // tell server that player moved
  }
  stepLeft() {
    if( this.isColliding(this.posX - this.speed, this.posY) == true ){

    }else{
      this.posX = this.posX - this.speed;
      socket.emit('playerMovement', ({x: this.posX, y: this.posY})); 
      this.updatePosition();
    }

  }
  stepUp() {
    if( this.isColliding(this.posX, this.posY - this.speed) == true ){

    }else{
      this.posY = this.posY - this.speed;
      socket.emit('playerMovement', ({x: this.posX, y: this.posY})); 
      this.updatePosition();
    }

  }
  stepDown() {
    if( this.isColliding(this.posX, this.posY + this.speed) == true ){

    }else{
      this.posY = this.posY + this.speed;
      socket.emit('playerMovement', ({x: this.posX, y: this.posY})); 
      this.updatePosition();
    }

  }
  isColliding(nextStepX, nextStepY) {
    //    - bounds of map
    if(nextStepX >= 0 && nextStepX < mapWidth - this.width && nextStepY >= 0 && nextStepY < mapHeight - this.height) {
    //    - other players
      for(let i = 0; i < activePlayers.length; i++) {
        
        if(activePlayers[i].playerId != this.playerId) {
         // other
         let other = activePlayers[i];
         if((other.posX > nextStepX - other.width) && 
            (other.posX <= nextStepX + this.width) && 
            (other.posY > nextStepY - other.height) && 
            (other.posY <= nextStepY + this.height) ) {
              return true
            }
        }
        // console.log(activePlayers[i]);      
      }
      return false
    } else {
      return true
    }
  }
  updatePosition() {
    // if me:
    if(this.isMe === true) {
      gameMap.style.left = - this.posX  + 'px';
      gameMap.style.top = - this.posY  + 'px';
    } else {
      this.elm.style.left = this.posX + 'px';
      this.elm.style.top = this.posY  + 'px';
    }
    // else:
    // move actal this.elm to location
  }
  createElement(){
    this.elm = document.createElement('div');
    // if me....
    if(this.isMe === true) {
      this.elm.setAttribute('class', 'mainPlayer');
    // if not me...
    } else {
      this.elm.setAttribute('class', 'otherPlayer');
    }
    // else
    //  ///
    this.elm.style.width = this.width + 'px';
    this.elm.style.height = this.height + 'px';
  
    // append the mainPlayer to the map
    gameMap.append(this.elm)
  
    // assign element id as the socket id
    this.elm.id =  this.playerId;
  
    // push id to activePlayers array 
    // activePlayers.push(playerInfo.playerId);
  
    // name tag for debug tracking
    let nameTag = document.createElement("p");
    nameTag.innerHTML = this.playerId;
    this.elm.append(nameTag)

     // set map coordinates from random player location
    this.updatePosition();
  }
};

class worldObject {
    constructor(name, posX, posY, width, height) {
        this.name = name;
        this.posX = posX;
        this.posY = posY;
        this.width = width;
        this.height = height;
    }
  };
  
  class Flower extends worldObject { 
    constructor (name, posX, posY, isPicked) {
        super(name, posX, posY); 
        // this.scientific = scientific;
        // this.rarity = rarity;
        this.posX = posX;
        this.posY = posY;
        this.width = 10;
        this.height = 10;
        this.flowerElm;
        this.isPicked = isPicked;
    }
    createElement(){
      this.flowerElm = document.createElement('div');

      this.flowerElm.setAttribute('class', 'flower');

      this.flowerElm.style.width = this.width + 'px';
      this.flowerElm.style.height = this.height + 'px';

      gameMap.append(this.flowerElm)

      this.updatePosition();
    }
    updatePosition() {
      this.flowerElm.style.left = this.posX + 'px';
      this.flowerElm.style.top = this.posY  + 'px';
    }
  };


  // let flowers = [
  //   ghostOrchid = new Flower ("Ghost Orchid", "Dendrophylax Lindenii", 10, randomPosition() - 5, randomPosition() - 5, 10, 10),
  // ];


let activePlayers = [];
let activeObjects = [];
let activeFlowers = [];

let socket = io();
 
socket.on('currentPlayers', function (players) {
  Object.keys(players).forEach(function (id) {
    // me:
    if (players[id].playerId === socket.id) {
      // create an asset for the main player
      if(activePlayers.indexOf(socket.id) === -1) {
        console.log("adding main player");
        // addPlayer(players[id]);
        player = new Player (players[id].x, players[id].y, players[id].playerId, true);
        // push player (mainPlayer) instance to activePlayers array
        activePlayers.push(player);
        // create mainPlayer element 
        player.createElement();
      }
      // or them:
    } else {
      // otherwise, create an other player
      if(activePlayers.indexOf(socket.id) === -1) {
        console.log("adding other player");
        // addOtherPlayers(players[id]);
        let guestPlayer = new Player (players[id].x, players[id].y, players[id].playerId, false);
        // push player (mainPlayer) instance to activePlayers array
        activePlayers.push(guestPlayer);
        // create mainPlayer element 
        guestPlayer.createElement();
      }
    }
  });
});
socket.on('newPlayer', function (playerInfo) {
  console.log("A new player has joined");
  // addOtherPlayers(playerInfo);
  let guestPlayer = new Player (playerInfo.x, playerInfo.y, playerInfo.playerId, false);
  // push player (mainPlayer) instance to activePlayers array
  activePlayers.push(guestPlayer);
  // create mainPlayer element 
  guestPlayer.createElement();
});
socket.on('playerMoved', function (playerInfo) {
  // console.log("a player moved");

  // console.log('delete this: ', players[i].playerId.indexOf(socket.id));
  let movedPlayer = activePlayers.find(player => player.playerId === playerInfo.playerId);
  // console.log(movedPlayer);

  movedPlayer.posX = playerInfo.x;
  movedPlayer.posY = playerInfo.y;

  movedPlayer.updatePosition();

  // let playerOnMove = document.getElementById(playerInfo.playerId)
  // // let movePlayer = document.getElementById(playerInfo.playerId);
  // playerOnMove.style.left = playerInfo.x + 'px';
  // playerOnMove.style.top = playerInfo.y + 'px';

  // console.log(playerInfo.playerId + " moved to: " + playerInfo.x, playerInfo.y);
});
socket.on('flowerData', function (flowerData) {

  
  for(let i=0; i < 5; i++) {
    console.log(flowerData[i].x, flowerData[i].y);
    let flower = new Flower (flowerData[i].id, flowerData[i].x, flowerData[i].y, flowerData[i].isPicked);

    activeFlowers.push(flower);
    // create mainPlayer element 
    flower.createElement();
  }
  
  // gameMap.append(flower);
  // if collide with flower: emit and push to player's inventory
  // this.socket.emit('flowerCollected');
  
});


socket.on('disconnectUser', function (playerId) {
    // remove the div element of the disconnected player
    let el = document.getElementById(playerId);
    console.log(el);
    el.remove(gameMap);

    console.log(activePlayers);
    for(let i = 0; i < activePlayers.length; i++) {
      // console.log('delete this: ', players[i].playerId.indexOf(socket.id));
      let disconnectedPlayer = activePlayers[i].playerId.indexOf(socket.id);
      activePlayers.splice(disconnectedPlayer, 1);
    }

    console.log("A player has left the game");
});

// server.js

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);

const port = process.env.PORT;

app.use(express.static('public'));

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

function randomPosition() {
  let random = parseInt( (50 + Math.random()*100));
  return random
}
 
let flower = [
  {
    id: "flowerOne",
    x: randomPosition() - 5,
    y: randomPosition() -5,
    isPicked: false
  },
  {
    id: "flowerTwo",
    x: randomPosition() - 5,
    y: randomPosition() -5,
    isPicked: false
  },
  {
    id: "flowerThree",
    x: randomPosition() - 5,
    y: randomPosition() -5,
    isPicked: false
  },
  {
    id: "flowerFour",
    x: randomPosition() - 5,
    y: randomPosition() -5,
    isPicked: false
  },
  {
    id: "flowerFive",
    x: randomPosition() - 5,
    y: randomPosition() -5,
    isPicked: false
  }
]
players = {};


// while debugging. positions will; mot be random,
// let y = 100; // for debugging
// let x = 10; // for debugging

io.on('connection', function (socket) {
  console.log('a user connected: ', socket.id);

    // create a new player and add it to our players object
  players[socket.id] = {
    // x and y positioning of the map:
    // subtract half of the playerWidth and playerHeight 
    x: randomPosition() - 5,
    y: randomPosition() - 5,
    // x: x, // for debugging
    // y: y, // for debugging
    playerId: socket.id,
  };
  // x += 50; // for debugging
  // if(x>200) x=10; // for debugging

  console.log(players);

  // send the players object to the new player
  socket.emit('currentPlayers', players);
  // update all other players of the new player
  socket.broadcast.emit('newPlayer', players[socket.id]);
  // send flowers to the new player
  socket.emit('flowerData', flower);
  console.log(flower);

  // when a player moves, update the player data
  socket.on('playerMovement', function (movementData) {
    // console.log(movementData);
    players[socket.id].x = movementData.x;
    players[socket.id].y = movementData.y;
    // console.log(movementData.x, movementData.y)
    // emit a message to all players about the player that moved
    socket.broadcast.emit('playerMoved', players[socket.id]);
  });

  // when a player disconnects, remove them from our players object
  socket.on('disconnect', function () {
    console.log('user disconnected: ', socket.id);
    delete players[socket.id];
    // emit a message to all players to remove this player
    io.emit('disconnectUser', socket.id);
  });
});


server.listen(3000, () => {
  console.log('listening on *:3000');
});



Aucun commentaire:

Enregistrer un commentaire