I'm making a game where the player will move using their cursor and will have to dodge objects. Each object has a hitbox, so I want to be able to update the number of lives whenever the cursor hits one. I'm just not sure what an efficient way is to keep track of all the hitboxes. I'd also like to record the object that the cursor collided with, so that bonus objects can be counted. The objects constantly respawn and move off the canvas, so I think keeping an array of all the hitboxes would pretty quickly get out of hand. Here's some code with some pseudo code for what I want to do.
canvas.addEventListener("mousemove", e => {
mouseX = e.clientX - rect.left;
mouseY = e.clientY - rect.top;
if (somehitboxX<=mouseX<=somehitboxX + 50 and somehitboxY<=mouseY<=somehitboxY + 50){
doSomething
}
});
EDIT: Instead of having my cursor keep track of all the hitboxes, would it be possible to have the hitboxes keep track of the cursor? Maybe by adding an event listener to each object? If that's possible, how would I go about doing it?
EDIT: Here's some code to get a better idea of what I'm working with. The emoji objects are what need to be dodged by the player. Each one has an emoji, a score, coordinates, speed, a hitbox, and a boolean that says whether it's been hit or not (though I'm not sure how to control it yet since that's what I need help with).
function Emoji(emojicon, score, x, y, speed) {
this.emojicon = emojicon;
this.score = score;
this.x = x;
this.y = y;
this.speed = speed;
this.hitbox = { hbx: x, hby: y - 50, hbWidth: 50, hbHeight: 50 };
this.hit = false;
}
The emoji objects are initialized like this:
var xPos = 0;
for (var i = 0; i < 9; i++) {
var emo = new Emoji("😜", 5, xPos, 520, 1);
emojis.push(emo);
xPos += 55;
}
emojis.forEach(emoji => drawEmoji(emoji));
}
And then Emoji.prototype.update updates both the coordinates of the emoji and its hitbox:
Emoji.prototype.update = function() {
if (this.y < 520) {
this.y -= this.speed;
this.hitbox.hby = this.y - 50;
} else {
var flip = Math.floor(Math.random() * 1000);
if (flip == 1) {
this.y -= this.speed;
this.hitbox.y = this.y - 50;
}
}
};
I hope this is enough code to get an idea of what I have so far.
Related
I'm trying to make a basic 2d game with p5js and p5.play. An issue that seems to cause issues every time I try to do anything is the keyIsDown function. Is there a way to determine if a key is down before pressing it? If I used
upKey = keyIsDown(UP_ARROW);
upKey will show as undefined until I press the up arrow. Is there any way to assign the respective boolean values to these types of things prior to pressing them?
As of now, my game will not properly work until I have pressed every involed key one time.
The keyIsDown() function checks if the key is currently down, i.e. pressed. It can be used if you have an object that moves, and you want several keys to be able to affect its behaviour simultaneously, such as moving a sprite diagonally.
Note that the arrow keys will also cause pages to scroll so you may want to use other keys for your game.. but if you want to use arrow keys this is the code snippet from the reference page
let x = 100;
let y = 100;
function setup() {
createCanvas(512, 512);
}
function draw() {
if (keyIsDown(LEFT_ARROW)) {
x -= 5;
}
if (keyIsDown(RIGHT_ARROW)) {
x += 5;
}
if (keyIsDown(UP_ARROW)) {
y -= 5;
}
if (keyIsDown(DOWN_ARROW)) {
y += 5;
}
clear();
fill(255, 0, 0);
ellipse(x, y, 50, 50);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.min.js"></script>
To implement similar logic without the use of arrow keys you will need to determine the key code of the keys you want to use.
Here is an example that uses awsd keys and also logs out the key code of the currently pressed key.
let x = 50;
let y = 50;
function setup() {
createCanvas(512, 512);
}
function keyPressed(){
console.log(keyCode);
}
function draw() {
if (keyIsDown(65)) {
x -= 5;
if (x < 0) x = 0;
}
if (keyIsDown(68)) {
x += 5;
if (x > width) x = width;
}
if (keyIsDown(87)) {
y -= 5;
if (y < 0) y = 0;
}
if (keyIsDown(83)) {
y += 5;
if ( y > height) y = height;
}
clear();
fill(255, 0, 0);
ellipse(x, y, 50, 50);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.min.js"></script>
i was making a game. i dont want the players to move out of the borders. i wrote a little for this. i also want the players to reflect back or boost back when collided with the borders with a boost. here's what i tried. it doesn't work for reflecting back.
Blob.prototype.borderCheck = function() {
var xStart = 0;
var xEnd = this.server.config.width;
var yStart = 0;
var yEnd = this.server.config.width;
if (this.isBoosting() && this.x <= xStart) {
this.setBoost(-this.getBoostAngle());
}
if (this.isBoosting() && this.x >= xEnd) {
this.setBoost(-this.getBoostAngle());
}
if (this.isBoosting() && this.y <= yStart) {
this.setBoost(-this.getBoostAngle());
}
if (this.isBoosting() && this.y >= yEnd) {
this.setBoost(-this.getBoostAngle());
}
this.x = Math.min(xEnd, Math.max(this.x, xStart));
this.y = Math.min(yEnd, Math.max(this.y, yStart));
};
it should be more like this one: https://cs.stanford.edu/people/eroberts/courses/soco/projects/1997-98/ray-tracing/images/reflection.gif
When I wrote a similar program in the past, I stored the velocity vector as x and y components. Then collision with vertical or horizontal walls is as simple as negating the correct component.
I created a sprite which moves in a circular motion. I want to change the direction if the mouse button (touch) is clicked, but when the mouse is clicked, the direction does not change.
This is my code:
create: function() {
this.stage.backgroundColor = '#FFFFFF';
x = this.world.centerX;
y = this.world.centerY;
this.direction = 1;
this.speedDelta = 0.002;
this.radius = 114;
this.physics.startSystem(Phaser.Physics.ARCADE);
//adding player
this.player = this.add.sprite(x, y, 'player');
this.player.anchor.setTo(0.5, 0.5);
this.game.physics.arcade.enable(this.player);
this.input.onDown.add(this.changeDirection, this);
},
update: function() {
if (this.direction == 1) {
this.speedDelta = 0.002;
} else if (this.direction == 1) {
this.speedDelta = -0.002;
}
var period = this.time.now * this.speedDelta;
this.player.x = Math.cos(period) * this.radius;
this.player.y = d + Math.sin(period) * this.radius;
},
changeDirection: function() {
this.direction = -this.direction;
}
}
Your basic assumptions about the behavior of cos and sin are incorrect. You can't simply change the sign of the input and get a different answer.
Notice:
cos(pi/4) = 0.707
cos(-pi/4) = 0.707
sin(pi/4) = -0.707
sin(-pi/4) = -0.707
Also I think your code would benefit by using a slightly different approach in general.
Currently you're recalculating the position from scratch on every update cycle. To get the behavior you want, I think it would be simpler to instead calculate a location delta based off of the speed and direction, then simply add the delta to the current location.
That would also allow you to eliminate your conditional statement, which will make the code cleaner.
I've been struggling with the bullet code for a while now. I know there is most likely a simpler solution (in fact I recall something similar I've done before, but I just can't remember it). But anyway;
PROBLEM: My bullets fire in all 4 directions, as they should. However if I choose to move after firing, in a different direction, the direction, and position, of the bullets will also change.
For example, if I am facing up and fire 3 bullets, then travel to the right, the bullets will change direction and velocity with me, instead I want it to continue travelling in that direction as I move in a different direction.
Here is the code for the bullets;
function Bullet(w, h, s){
this.x = tank.x;
this.y = tank.y
this.width = w;
this.height = h;
this.speed = s;
}
//setInterval of firing
function setFire(){
tankCanFire = true;
}
//Create a new bullet
function fireBullet(){
if(tankCanFire){
tankCanFire = false;
bullets.push(new Bullet(5, 10, 15));
ctx.fillText("Ding", 300, 300);
}
}
//DRAW the Bullets + velocities.
function drawBullet(){
ctx.fillText("length = " +bullets.length, 200, 200);
if (bullets.length > 0){
for (var key in bullets)
{
ctx.fillText("DONG", 200, 250);
if (tank.up == true)
{
ctx.drawImage(bulletImage, bullets[key].x + 13, bullets[key].y - 8);
bullets[key].y -= 15;
if (bullets[key].y < 0)
delete bullets[key];
}
else if (tank.down == true)
{
ctx.drawImage(bulletImage, bullets[key].x + 13, bullets[key].y + 40);
bullets[key].y += 15;
if (bullets[key].y > 400)
delete bullets[key];
}
else if (tank.left == true)
{
ctx.drawImage(bulletImage, bullets[key].x - 8, bullets[key].y + 13);
bullets[key].x -= 15;
if (bullets[key].x < 0)
delete bullets[key];
}
else if (tank.right == true)
{
ctx.drawImage(bulletImage, bullets[key].x + 40, bullets[key].y + 13);
bullets[key].x += 15;
if (bullets[key].x > 600)
delete bullets[key];
}
}
}
}
In Bullet, in addition to x,y,width,height,speed you also need to store the direction this particular bullet is going. The current code will look at the tank's orientation when moving the bullet, so the bullet's direction will change if you turn the tank. This can be fun too, but if you want traditional bullets it makes sense to store, in the bullet, the direction it's going.
The easiest way to do this is to store, not the speed, but the velocity. Something like this:
function Bullet(w, h, dx, dy){
this.x = tank.x;
this.y = tank.y
this.width = w;
this.height = h;
this.dx = dx; // how much x changes at every time step
this.dy = dy;
}
I'm creating a small game in Node.js/Socket.IO and need some advice on creating the AI. The code I have below is a real quick example I came up with but it's so fast the player doesn't even see the enemy move on the client-side. Am I on the right lines with this approach or is there a better way I should be doing it?
Thanks!
var random;
setInterval(function() {
random = Math.round(Math.random() * 200);
move(random, random);
console.log("Moving player");
}, 10000)
var move = function(targetX, targetY) {
if (x < targetX) {
while (x < targetX) {
x++;
sendNewCoordinates(x, y);
}
} else if (x > targetX) {
while (x > targetX) {
x--;
sendNewCoordinates(x, y);
}
} else if (y < targetY) {
while (y < targetX) {
y++;
sendNewCoordinates(x, y);
}
} else if (y > targetY) {
while (y > targetX) {
y--;
sendNewCoordinates(x, y);
}
}
};
var sendNewCoordinates = function(newX, newY) {
socket.sockets.emit("move enemy", {x: newX, y: newY});
};
That's actually a pretty good AI! Randomizing the interval between movements is a very easy, common technique for things like this. Im curious and would love to try whatever you are making! One thing to be aware of though, is to make sure the AI is not TOO good.
One other thing you could implement in your code is to have your AI "aim" for a point slightly away from the target. Eg:
var move = function(targetX + randomX, targetY + randomY)
You can also use the position of the target before it moved to predict where it is heading.
var xChange = (targetX2 - targetX1)/(timeInterval1);
var yChange = (targetY2 - targetY1)/(timeInterval1);
var move = function(targetX + xChange * timeInterval2, targetY + yChange * timeInterval2)
where timeInterval1 is the time interval between two of the targets positions and timeInterval2 is the time interval between your current position and your next position.
The key is not making the AI too hard for the player though. ;)