I started to make a video game with Html canvas and JavaScript: you are an alien have to shoot out other red aliens. If you come near an alien(enemy) the enemy starts to move in your direction. Now if the player comes near an Enemy, that is near another Enemy(but not as much to see the player) the game starts to lag.
This is the function of the distance and move to function:
this.moveto = function(vec,vel){
distX = vec.x - vec.offsetx - this.x
distY = vec.y - vec.offsety - this.y
dist = Math.sqrt(distX*distX + distY*distY)
distX /= dist
distY /= dist
i+= 1
if(dist >= 2){
this.x += (distX/100)*vel
this.y += (distY/100)*vel
}
}
this.dist = function(vec){
dist2X = vec.x - vec.offsetx - this.x
dist2Y = vec.y - vec.offsety - this.y
dist2 = Math.sqrt(dist2X*dist2X + dist2Y*dist2Y)
return(dist2)
}
and this is how it's used:
for(i = 0; i < this.enemies.length; i++){
this.enemies[i].update()
if(this.enemies[i].dist(this.player) > 100){
this.enemies[i].move()
}else{
this.enemies[i].moveto(this.player,30)
}
if(this.enemies[i].lives <= 0){
this.enemies.splice(i,1)
}
}
("enemies" is an array with 5 enemies)
This is the enemy.move():
this.vector = new Vector(x,y,534/8,1517/8)
this.vector.move = function(){
if(this.passi <= 2){ //1
game.rspe.play()
if(game.level.tick){
this.IndexX++;
}
this.currentImage = game.enemyl
this.x-=3;
if (this.IndexX > 10){
this.passi++
this.IndexX = 0;
}
}else if(this.passi > 2 && this.passi <= 5){ //2
game.rspe.play()
if(game.level.tick){
this.IndexX++;
}
this.currentImage = game.enemyr
this.x+=3;
if (this.IndexX > 10){
this.IndexX = 0;
this.passi++
}
}else{
this.passi = 0
}
}
return(this.vector)
this is the git repository: https://github.com/Lollipopper/A1bKJBABJQ-W6-hi-jH-
Related
I'm making the popular snake game for js homework.
I have a function which is meant to ensure that after an apple is eaten it moves to a different location on the canvas while not being on any part of the snake,
the function without the loop works fine (though apples are placed on the snake too):
move() {
let onSnake = true;
let x = this.getRandomNumber(0, canvas.width - 1); //UnitSize);;
let y = this.getRandomNumber(0, canvas.height - 1); //UnitSize);;
this.x = x;
this.y = y;
this.draw();
}
the function though with the loop ends up freezing after a few apples are eaten (right before hitting an apple):
move() {
let onSnake = true;
let x = this.getRandomNumber(0, canvas.width - 1); //UnitSize);;
let y = this.getRandomNumber(0, canvas.height - 1); //UnitSize);;
while (onSnake) {
onSnake = false;
x = this.getRandomNumber(0, canvas.width - 1); //UnitSize);
y = this.getRandomNumber(0, canvas.height - 1); //UnitSize);
for (let index = 0; index < snake.parts.length; index++) {
if (x === snake.parts[index].x || y === snake.parts[index].y) {
onSnake = true;
break;
}
}
}
this.x = x;
this.y = y;
this.draw();
}
with getRandomNumber being:
getRandomNumber(min, max) {
let r = Math.floor(Math.random() * (max - min + 1)) + min;
r = r - (r % UnitSize);
return r;
}
this is my second question on SO, don't fry me please....
I didn't get a moment to test but I suspect it's as simple as the following evalutation.
if (x === snake.parts[index].x || y === snake.parts[index].y) {
onSnake = true;
break;
}
You are accepting either X or Y collision. Meaning the apple cannot share any X or Y coordinates with any of the snake pieces. What you want instead is and I believe. It's like saying we both live on the same house because we live on the same street. No, we need to also have the same address.
As a safety, you could add a limit to how many iterations of the loop can run in the event their is no more space remaining for an apple.
let counter = 0;
while (onSnake && counter < 5000) {
onSnake = false;
x = this.getRandomNumber(0, canvas.width - 1); //UnitSize);
y = this.getRandomNumber(0, canvas.height - 1); //UnitSize);
for (let index = 0; index < snake.parts.length; index++) {
if (x === snake.parts[index].x && y === snake.parts[index].y) {
onSnake = true;
break;
}
}
counter += 1;
}
if (counter == 5000) {
alert("Could not find space for any more apples!");
}
I have an agent called cube (cube its just the name, it is a square in reality). Every cube falls and stops on the ground, and I want them to detect the other cubes and stack up.
I am having problems with this method for detecting collision: https://www.youtube.com/watch?v=GY-c2HO2liA&list=PLRqwX-V7Uu6Zy51Q-x9tMWIv9cueOFTFA
I made 2 for loops and all but it doesn't work for some reason.
this is the main script:
var cubes = [];
var nb = 10; //number of cubes
var gravity = .1;
var sz = 10; //cube size
function setup() {
createCanvas(400, 400);
for (i = 0; i < nb; i++) {
cubes.push(new Cube());
}
}
function draw() {
background(51);
for (var i = 0; i < cubes.length; i++) {
cubes[i].show();
for (var j = 0; j < cubes.length; j++) {
if (i != j && !cubes[i].collide(cubes[j]) && !(cubes[i].pos.y + sz > height)) {
cubes[i].pos.y += gravity;
}
}
}
}
this is the cube function linked with p5.js in an HTML file:
function Cube() {
this.rx = (round((random(0, width - sz)) / sz) * sz);
this.ry = (round((random(sz, height - sz)) / sz) * sz);
this.pos = createVector(this.rx, this.ry);
this.show = function() {
fill(220);
noStroke();
rect(this.pos.x, this.pos.y, sz, sz);
}
this.collide = function(other) {
if (this.pos.y + sz == other.pos.y && this.pos.x == other.pos.x) {
return true;
} else {
return false;
}
}
}
I want the cubes to stack up when they hit the ground but they only pass through each other completely ignoring the collision I've set up.
I think your problem is coming from the fact that you are using ==, please try modifying this line :
if (this.pos.y + sz == other.pos.y && this.pos.x == other.pos.x) {
into
if (this.pos.y + sz > other.pos.y && this.pos.y <= other.pos.y+sz &&
this.pos.x < other.pos.x+sz && this.pos.x + sz > other.pos.x)
I'm just trying to create a small 2d game where we control a character that can place block on the "map" with the mouse and jump on it to climb etc. It's just a test to practice.
I've achieved to make the character stops when he walk into blocks.
But, i'm facing a problem when I want my character to jump on a block, i'm not able to make him land on it. I can't find the condition to.
Can someone helps me on it ? The code that handle the collision between the character and blocks is in the draw function and in the for.
Controls
Left: Q
Right: D
Jump: Space Bar
Place a block: Mouse Click
Remove a block: Mouse Click
Edit: You might have ask yourself why i'm using some variables that are not declared anywhere. It's because they are given by P5.js. (ex: width)
function Man() {
this.w = 20;
this.h = 40;
this.x = width/2;
this.y = height - this.h;
this.canJump = true;
this.velocity = 0;
this.show = function(){
fill(255);
rect(this.x, this.y, this.w, this.h);
}
this.update = function(){
this.velocity += gravity;
this.y += this.velocity;
if(this.y + this.h > height) {
this.y = height - this.h ;
this.velocity = 0;
this.canJump = true;
}
if(this.x <= 0) {
this.x = 0;
}
if(this.x + this.w >= width) {
this.x = width - this.w;
}
}
this.jump = function(){
if(this.canJump) {
man.velocity -= 6;
this.canJump = false;
}
}
}
var man;
var ground;
var gravity = 0.4;
function setup(){
frameRate(60);
createCanvas(640, 480);
man = new Man();
}
var tilesSize = 20;
var tiles = [];
for(var i = 0; i < 640; i+= tilesSize) {
for(var j = 0; j < 480; j+= tilesSize) {
tiles.push({x:i, y:j, empty: true});
}
}
function draw(){
background(0);
noStroke();
push();
for(var i = 0; i < tiles.length; i++) {
if(!tiles[i].empty) {
fill(150);
rect(tiles[i].x, tiles[i].y, tilesSize, tilesSize);
}
if(mouseX >= tiles[i].x && mouseX < tiles[i].x + tilesSize && mouseY >= tiles[i].y && mouseY < tiles[i].y + tilesSize) {
if(tiles[i].empty) {
fill(50);
rect(tiles[i].x, tiles[i].y, tilesSize, tilesSize);
}else {
fill(255,0,0);
rect(tiles[i].x, tiles[i].y, tilesSize, tilesSize);
}
}
// HERE IS CONDITIONS FOR COLLISION WITH BLOCK
if(!tiles[i].empty) {
if(tiles[i].x + tilesSize >= man.x && tiles[i].x < man.x && tiles[i].y < man.y + man.h ) {
man.x = tiles[i].x + tilesSize;
}
if(man.x + man.w >= tiles[i].x && man.x <= tiles[i].x && tiles[i].y < man.y + man.h) {
man.x = tiles[i].x - man.w;
}
}
}
pop();
man.show();
man.update();
moveMan();
}
function moveMan(){
if(keyIsDown(81)) {
man.x -= 2;
}
if(keyIsDown(68)) {
man.x += 2;
}
}
function keyPressed() {
if(keyIsDown(32)) {
man.jump();
}
}
function mouseClicked() {
for(var i = 0; i < tiles.length; i++) {
if(mouseX >= tiles[i].x && mouseX < tiles[i].x + tilesSize && mouseY >= tiles[i].y && mouseY < tiles[i].y + tilesSize) {
if(tiles[i].empty) {
tiles[i].empty = false;
}else {
tiles[i].empty = true;
}
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.min.js"></script>
I've been experementing with 2d rectangular collision but i stumbled into an error i can't fix, even after over an hour of tweaking.
Collision works fine up, down and left. but the right causes the player to go up to the y value of the collision. The code is the exact same as the left site (correctly mirrored. I think)
var player = new Player(50,50,100,0.3,false,0,0)
var playerCollision = new Collision(player.x,player.y,64,64);
var ground = new Collision(0,500,300,100);
var wall = new Collision(200,400,100,100);
var wall2 = new Collision(0,400,100,100);
var collisions = [ground,wall,wall2];
for (i=0;i<collisions.length;i++) {
if (collisions[i].checkCollision(playerCollision)) {
if (collisions[i].x - playerCollision.x > 0 && playerCollision.x + playerCollision.width > collisions[i].x-1 && playerCollision.y+playerCollision.height-20 > collisions[i].y) {
player.dx = 0;
player.x = collisions[i].x-64;
} else if ((collisions[i].x + collisions[i].width)- playerCollision.x < 0 && playerCollision.x < collisions[i].x+collisions[i].width+1 && playerCollision.y+playerCollision.height-20 > collisions[i].y) {
player.dx = 0;
player.x = collisions[i].x+collisions[i].width;
} else if (collisions[i].y - playerCollision.y+playerCollision.height > 0) {
player.dy = 0;
player.y = collisions[i].y-64;
} else if ((collisions[i].y+collisions[i].height) - playerCollision.y < 0) {
player.dy = 0;
player.y = collisions[i].y+collisions[i].height;
}
}
}
Collision.js:
function Collision(x,y,width,height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.checkCollision = function(other) {
if (this.x < other.x + other.width &&
this.x + this.width > other.x &&
this.y < other.y + other.height &&
this.height + this.y > other.y) {
return true
} else {
return false;
}
}
this.show = function() {
ctx.strokeStyle = "#38ff35";
ctx.strokeRect(this.x,this.y,this.width,this.height);
}
}
EDIT:
changed some code (didn't fix the problem tho)
obj1
position = (0, 0)
dimensions = (2, 0)
obj2
position = (2, 0)
dimensions = (2, 0)
0 < 2 + 2 = true
0 + 2 > 2 = false
this already shows that your check doesn't mathematically make sense. These two blocks should be overlapping but return false
Try:
if (this.x + this.width < other.x - other.width ||
this.x - this.width > other.y + other.width ||
this.y + this.height < other.y - other.height ||
this.y - this.height > other.y + other.height)
{
no collisions
}
I am coding a Pacman clone. The steps that I have accomplished are the floor, the maze, as also the pacman and the movement of pacman through wall paths.
The maze is in array format where the walls are represented as "x". Also the movement should go with wasd keys from the keyboard. Currently the movement of the object is smooth and can walk in the path and change directions correctly only if I have the good timing with the hit.
I have also read this post Relevant Post and I followed some of these techniques so that I can store the key presses. After I did that I don't think that something changed from the previous design. Also when I change to a direction that is not allowed it rotates to that direction and stops moving. I want to implement this like classic Pac-man game. Below is the code of my issue.
That's the handleKeyDown function where i check for key press.
function handleKeyDown(event) {
currentlyPressedKeys[event.keyCode] = true;
if (String.fromCharCode(event.keyCode) == "A") {
curr_key=temp;
curr_key="A";
memory_key = temp;
pacRot = 0;
}
if (String.fromCharCode(event.keyCode) == "D") {
curr_key=temp;
curr_key="D";
memory_key = temp;
pacRot = 180;
}
if (String.fromCharCode(event.keyCode) == "W") {
curr_key=temp;
curr_key="W";
memory_key = temp;
pacRot = 270;
}
if (String.fromCharCode(event.keyCode) == "S") {
curr_key=temp;
curr_key="S";
memory_key = temp;
pacRot = 90;
}
}
Now the function can_move(key) that checks if the object can move to a direction
function can_move(key){
if (key == "W") {
if (stage[Math.round(y) - 1][x] == "x") {
y = Math.round(y);
return false;
} else {
return true;
}
}
if (key == "A") {
if (stage[y][Math.round(x) - 1] == "x") {
x = Math.round(x);
return false;
} else {
return true;
}
}
if (key == "S") {
if (stage[Math.round(y) + 1][x] == "x") {
y = Math.round(y);
return false;
} else {
return true;
}
}
if (key == "D") {
if (stage[y][Math.round(x) + 1] == "x") {
x = Math.round(x);
return false;
} else {
return true;
}
}
}
And finally the main moving function move_conditions that is called inside tick() after drawScene()
function move_conditions(elapsed) {
if(can_move(curr_key)==true){
if(curr_key=="W"){
ySpeed = 5;
xSpeed = 0;
y -= (ySpeed * 25) / 1000.0;
x = Math.round(x);
}
if(curr_key=="A"){
ySpeed = 0;
xSpeed = 5;
x -= (xSpeed * 25) / 1000.0;
y = Math.round(y);
}
if(curr_key=="S"){
ySpeed = 5;
xSpeed = 0;
y += (ySpeed * 25) / 1000.0;
x = Math.round(x);
}
if(curr_key=="D"){
ySpeed = 0;
xSpeed = 5;
x += (xSpeed * 25) / 1000.0;
y = Math.round(y);
}
}else if(can_move(memory_key)==true){
if(memory_key=="W"){
ySpeed = 5;
xSpeed = 0;
y -= (ySpeed * 25) / 1000.0;
x = Math.round(x);
}
if(memory_key=="A"){
ySpeed = 0;
xSpeed = 5;
x -= (xSpeed * 25) / 1000.0;
y = Math.round(y);
}
if(memory_key=="S"){
ySpeed = 5;
xSpeed = 0;
y += (ySpeed * 25) / 1000.0;
x = Math.round(x);
}
if(memory_key=="D"){
ySpeed = 0;
xSpeed = 5;
x += (xSpeed * 25) / 1000.0;
y = Math.round(y);
}
}