I am making a 2d platformer and am working on gravity and collision but when I actually get the collision working my gravity became very stuttery, is there a way to fix this? here is code:
gravity(){
if(this.y <= 400 - this.scale){
let gc = get(this.x, this.y + 20);
print(gc);
if(gc[0] == 0 && gc[1] == 0 && gc[2] == 255 && gc[3] == 255){
return;
}
else{
this.y += 2;
}
}
}
edit: I have heard this should be working so I will provide more code to see if it helps. here is the function that runs everything:
var groundArray = [];
groundArray[0] = [0];
groundArray[1] = [0];
groundArray[2] = [0];
groundArray[3] = [0];
groundArray[4] = [0];
groundArray[5] = [0];
groundArray[6] = [0];
groundArray[7] = [0];
groundArray[8] = [1];
groundArray[9] = [1, 1];
function setup() {
noStroke();
createCanvas(400, 400);
for(let y = 0; y < groundArray.length; y++){
for(let x = 0; x < groundArray[y].length; x++){
if(groundArray[y][x] != 0){
groundArray[y][x] = new ground(x * 40, y * 40);
}
}
}
}
var play = new player(35, 0, 20);
function draw() {
background(255);
for(let y = 0; y < groundArray.length; y++){
for(let x = 0; x < groundArray[y].length; x++){
if(groundArray[y][x] != 0){
groundArray[y][x].draw();
}
}
}
play.draw();
play.gravity();
}
Normally a function named draw() is called every frame, is that what's happening here? It looks like it. In which case, do you really want to be calling new ground(x * 40, y * 40) every frame, wouldn't this object creation be better placed in setup()?
I suspect it's unnecessary and possibly doing expensive initialization work every frame, but without seeing the full source code one can't be sure.
Related
I have a object that has many child objects and I only want the children to change a specific value, not affecting the parent object. In short, the children have values that WILL change but the children are changing the parent as well, which is bad.
Only Relevant JS:
let p1 = {super:{vel:{x:3,y:0}, timeLeft:100}} // Very Shortened player objects
let p2 = {y:100}
var supers = {p1:[], p2:[]};
function draw(){
superProject();
if (p1.super.timeLeft >= 1 && p1.super.type == 'MISSILE'){
p1.super.timeLeft--;
let randY = Math.round(random(50, 150));
let missile = {x:40, y:randY, vel:p1.super.vel, dist:{x:0, y:0}}
supers.p1.push(missile);
}
}
function superProject(){
if (supers.p1.length > 0){
for (let i = 0; i < supers.p1.length; i++){
supers.p1[i].x += supers.p1[i].vel.x;
supers.p1[i].y += supers.p1[i].vel.y;
let distY = 0;
distY = p2.y - supers.p1[i].y;
let distX = 0;
distX = 170 - supers.p1[i].x
supers.p1[i].dist.x = distX;
supers.p1[i].dist.y = distY;
if (distY > 0){
supers.p1[i].vel.y += 1;
} else if (distY < 0){
supers.p1[i].vel.y -= 1;
}
circle(supers.p1[i].x, supers.p1[i].y, 4);
}
}
}
Link to full source. I would appreciate any help you can give me.
enter image description hereI got an exercise , where i have to create a rectangle-canvas using p5.js , but that canvas will consist small rects ,so i do it , but there is also 1 point in the exrecise . How can i get those small rects in 2 different colors , but 50% of those colores must be green and the other red , using matrix .
Here is the code .
var matrix = [
];
var ab = 36;
for (var y = 0; y < ab; y++) {
matrix.push([])
for (var x = 0; x < 36; x++) {
matrix[y][x] = Math.floor(Math.random() * 2)
}
}
console.log(matrix)
var side = 16;
function setup() {
createCanvas(matrix[0].length * side, matrix.length * side);
background('#acacac');
frameRate()
}
function draw() {
for (var y = 0; y < matrix.length; y++) {
for (var x = 0; x < matrix[y].length; x++) {
if (matrix[y][x] == 0) {
fill(0, 255, 0)
rect(y * side, x * side, side, side)
}
else if (matrix[y][x] == 1) {
fill("red")
rect(y * side, x * side, side, side)
}
function Shuffle (arguments) {
for(var k = 0; k < arguments.length; k++){
var i = arguments[k].length;
if ( i == 0 ) return false;
else{
while ( --i ) {
var j = Math.floor( Math.random() * ( i + 1 ) );
var tempi = arguments[k][i];
var tempj = arguments[k][j];
arguments[k][i] = tempj;
arguments[k][j] = tempi;
}
return arguments;
}
}
}
so as discussed in comments , the problem reduces to filling exactly half the matrix with one color and other half with other.
your matrix is in two dimension i will give a solution in one dimension, which should be quite easy to extend to 2-d
var count = 0;
var arr = [];
for( var i = 0 ;i < ab;i++){
arr[i] = 0;
}
while(true) {
var i = floor(random(ab));
if(arr[i] !==1) {
arr[i] = 1;
count++;
}
if(count === ab/2) break; // assume ab is even
}
there is one more way
fill half the array with 1 and half with 0 and then shuffle the array
you can very easily google algorithms for shuffling,
one pseudocode i could find
// after filling half elements with 1 and half with zero
// To shuffle an array a of n elements (indices 0..n-1):
for i from n - 1 downto 1 do
j = random integer with 0 <= j <= i
exchange a[j] and a[i]
source: https://www.geeksforgeeks.org/shuffle-a-given-array/
There it is my problem
var matrix = [
];
var ab = 36;
for (var y = 0; y < ab; y++) {
matrix.push([])
for(var x = 0 ; x<ab;x++){
matrix[y][x] = Math.floor(Math.random()*1)
}
for(var x = 0 ; x<ab/2;x++){
matrix[y][x] = 1
}
}
var count = 0;
var arr = [];
for( var i = 0 ;i < ab;i++){
arr[i] = 0;
}
while(true) {
var i = Math.floor(Random(ab));
if(arr[i] !==1) {
arr[i] = 1;
count++;
}
if(count === ab/2) break; // assume ab is even
}
console.log(arr)
var side = 16;
function setup() {
createCanvas(arr[0].length * side, arr.length * side);
background('#acacac');
frameRate()
}
function draw() {
for (var y = 0; y < arr.length; y++) {
for (var x = 0; x < arr[y].length; x++) {
if (matrix[y][x] == 0) {
fill(0, 255, 0)
rect(y * side, x * side, side, side)
}
else if (matrix[y][x] == 1) {
fill("red")
rect(y * side, x * side, side, side)
}
else if (matrix[y][x] == 2) {
fill(255, 255, 0)
rect(y * side, x * side, side, side)
}
else if (matrix[y][x] == 3) {
fill(255, 0, 0)
rect(y * side, x * side, side, side)
}
}
}
}
I'm attempting to make a top-down shooter style game reminiscent of the old Galaga games.
I've got the player and enemies and projectiles moving and working fine apart from when I try to check for collisions between the bullets being fired by the player and the enemy spaceships.
both the bullets and enemies are made using constructors and then placed in an array to keep track of them.
//due to the number of enemies on screen they'll be held in an array
var enemies = [];
for(e = 0; e < enemies; e++) {
enemies[e] = [];
enemies[e] = {x:0,y:0};
}
//class constructor to create enemies
class enemy {
constructor(x,y) {
this.enemyX = x;
this.enemyY = y;
this.enemyWidth = 32;
this.enemyHeight = 32;
}
}
//variable array for the bullets
var playerBullets = [];
for(i = 0; i < playerBullets; i++) {
playerBullets[i] = { x: 0, y: 0 };
}
//class constructor to create the bullets
class bullet {
constructor(x,y){
this.bulletX = x;
this.bulletY = y;
this.bulletWidth = 5;
this.bulletHeight = 5;
}
}
I have tried to make a collision detector function that first goes through the array of bullets and then the array of enemies and checks for overlapping borders and to give an alert when a collision has been found, but I'm having trouble with it. If anyone can help I would greatly appreciate it.
//code for detecting collisions from the bullets
function collisionDetection() {
for(i = 0; i < playerBullets.length; i++) {
for(e = 0; e < enemies.length; e++) {
if (playerBullets[i].x < enemies.x + enemy.width &&
playerBullets[i].x + bullet.width > enemies.x &&
playerBullets[i].y < enemies.y + enemy.height &&
playerBullets[i].y + bullet.height > enemies.y){
alert("HIT");
}
}
}
}
you missed the index of the enemies: enemies[e] and enemy has enemyX enemyY enemyWidth and enemyHeight property, and bullets has: bulletX, bulletY bulletWidth bulletHeight
function collisionDetection() {
for(i = 0; i < playerBullets.length; i++) {
for(e = 0; e < enemies.length; e++) {
if (playerBullets[i].bulletX < enemies[e].enemyX + enemies[e].enemyWidth &&
playerBullets[i].bulletX + playerBullets[i].bulletWidth > enemies[e].enemyX &&
playerBullets[i].bulletY < enemies[e].enemyY + enemies[e].enemyHeight &&
playerBullets[i].bulletY + playerBullets[i].bulletHeight > enemies[e].enemyY){
alert("HIT");
}
}
}
}
I'm trying to solve a programming exercise in which there are several bugs to be fixed. Ultimately, it is supposed to represent an animation with a grid of cells where at each time step, if a cell has exactly three neighbors which are alive (each cell has 8 neighbors), it 'comes to life', and if it has less than 2 or more than 3 neighbors, it 'dies' (where the neighbors 'wrap around' the grid). The initial script is as follows:
<html>
<head>
<script type="text/javascript">
var Board;
var xsize = 10;
var ysize = 10;
var dead = 0;
var alive = 1;
function Neighbors(Board, x, y)
{
var n = 0
for(dx=-1;dx < 1; ++dx)
for(dy=-1;dy < 1; ++dy)
{
var ax = x+dx;
var ay = y+dy;
if(Board[ax][ay]==alive) ++n;
}
return n;
}
function Kill(Board,x,y)
{
if(Board[x][y] == alive)
Board[x][y] = dead;
}
function MakeLive(Board,x,y)
{
if(Board[x][y] == dead)
Board[x][y] = alive;
}
function NextStep(Board)
{
for(var x = 0; x <= xsize; ++x)
{
for(var y = 0; y <= ysize; ++x)
{
n = Neighbors(Board,x,y);
if(n=3) MakeLive(Board,x,y);
if((n<2)||(n>3)) Kill(Board,x,y);
}
}
}
function DrawBoard(Board)
{
var Text = "";
for(var y = 0; y < ysize; ++y)
{
for(var x = 0; x < xsize; ++x)
Text += Board[x][y]==alive ? "o":"_";
Text += "<br/>";
}
document.getElementById("board").innerHTML = Text;
}
function Main()
{
// *** Change this variable to choose a different baord setup from below
var BoardSetup = "blinker";
Board = new Array(xsize);
for(var x = 0; x < xsize; ++x)
{
Board[x] = new Array(ysize);
for(var y = 0; y < ysize; ++y)
Board[x][y] = 0;
}
if(BoardSetup == "blinker")
{
Board[1][0] = 1;
Board[1][1] = 1;
Board[1][2] = 1;
}
else if(BoardSetup == "glider")
{
Board[2][0] = 1;
Board[2][1] = 1;
Board[2][2] = 1;
Board[1][2] = 1;
Board[0][1] = 1;
}
else if(BoardSetup == "flower")
{
Board[4][6] = 1;
Board[5][6] = 1;
Board[6][6] = 1;
Board[7][6] = 1;
Board[8][6] = 1;
Board[9][6] = 1;
Board[10][6] = 1;
Board[4][7] = 1;
Board[6][7] = 1;
Board[8][7] = 1;
Board[10][7] = 1;
Board[4][8] = 1;
Board[5][8] = 1;
Board[6][8] = 1;
Board[7][8] = 1;
Board[8][8] = 1;
Board[9][8] = 1;
Board[10][8] = 1;
}
DrawBoard(Board);
}
</script>
</head>
<body onload="Main()">
<div id="board">
</div>
Next ->
</body>
</html>
The problem is that if I press the 'Next' button, in the console I see the following error:
Uncaught TypeError: Cannot read property '-1' of undefined
at Neighbors (life_broken__281_29.html:19)
at Function.NextStep (life_broken__281_29.html:42)
at HTMLAnchorElement.onclick (life_broken__281_29.html:117)
Neighbors # life_broken__281_29.html:19
NextStep # life_broken__281_29.html:42
onclick # life_broken__281_29.html:117
The problem, I believe, is that the Board is defined in the Main() function, which is not in the scope of the onclick callback function.
My initial approach was to move the initialization of the Board outside of the Main() function, making it a global variable, and removing Board from all function calls. This does not seem like an elegant approach, however. Instead, I tried using Function.prototype.call() as follows:
Next ->
Further, I implemented a wrapAround function to avoid the indices going out of bounds:
function Neighbors(Board, x, y)
{
var n = 0
for(dx=-1;dx < 1; ++dx)
for(dy=-1;dy < 1; ++dy)
{
var ax = x+dx;
var ay = y+dy;
ax = wrapAround(ax, xsize);
ay = wrapAround(ay, ysize);
if(Board[ax][ay]==alive) ++n;
}
return n;
}
function wrapAround(coordinate, size) {
var result = coordinate % size;
if (result < 0) {
result += size;
}
return result;
}
However, now I get a new error:
life_broken__281_29.html:42 Uncaught TypeError: Cannot read property '0' of undefined
at MakeLive (life_broken__281_29.html:42)
at Function.NextStep (life_broken__281_29.html:53)
at HTMLAnchorElement.onclick (life_broken__281_29.html:127)
Apparently, the Neighbors function is now not raising any errors, but the next function in NextStep, MakeLive, is. This I don't understand however because they are both defined at the same 'level' and have similar invocations in NextStep. Can anyone explain what the issue is here?
Update
Indeed Board is declared in the global scope, so there was no need for Function.prototype.call(). (I'm used to Python where declaration and definition are always in the same place). I also changed the Boolean expression to (x === 3).
However, for some reason x is still going up to 10 even if I replace the <= by a <. Here is the updated code, with a console.log statement for debugging:
<html>
<head>
<script type="text/javascript">
var Board;
var xsize = 10;
var ysize = 10;
var dead = 0;
var alive = 1;
function Neighbors(Board, x, y)
{
var n = 0
for(dx=-1;dx < 1; ++dx)
for(dy=-1;dy < 1; ++dy)
{
var ax = x+dx;
var ay = y+dy;
ax = wrapAround(ax, xsize);
ay = wrapAround(ay, ysize);
if(Board[ax][ay]==alive) ++n;
}
return n;
}
function wrapAround(coordinate, size) {
var result = coordinate % size;
if (result < 0) {
result += size;
}
return result;
}
function Kill(Board, x, y)
{
if (Board[x][y] == alive)
Board[x][y] = dead;
}
function MakeLive(Board, x, y)
{
if (Board[x][y] == dead)
Board[x][y] = alive;
}
function NextStep(Board)
{
for(var x = 0; x < xsize; ++x)
{
for(var y = 0; y < ysize; ++x)
{
n = Neighbors(Board,x,y);
console.log("x = " + x + ", y = " + y + ", n = " + n);
if (n===3) MakeLive(Board,x,y);
if ((n<2)||(n>3)) Kill(Board,x,y);
}
}
}
function DrawBoard(Board)
{
var Text = "";
for(var y = 0; y < ysize; ++y)
{
for(var x = 0; x < xsize; ++x)
Text += Board[x][y]==alive ? "o":"_";
Text += "<br/>";
}
document.getElementById("board").innerHTML = Text;
}
function Main()
{
// *** Change this variable to choose a different baord setup from below
var BoardSetup = "blinker";
Board = new Array(xsize);
for(var x = 0; x < xsize; ++x)
{
Board[x] = new Array(ysize);
for(var y = 0; y < ysize; ++y)
Board[x][y] = 0;
}
if(BoardSetup == "blinker")
{
Board[1][0] = 1;
Board[1][1] = 1;
Board[1][2] = 1;
}
else if(BoardSetup == "glider")
{
Board[2][0] = 1;
Board[2][1] = 1;
Board[2][2] = 1;
Board[1][2] = 1;
Board[0][1] = 1;
}
else if(BoardSetup == "flower")
{
Board[4][6] = 1;
Board[5][6] = 1;
Board[6][6] = 1;
Board[7][6] = 1;
Board[8][6] = 1;
Board[9][6] = 1;
Board[10][6] = 1;
Board[4][7] = 1;
Board[6][7] = 1;
Board[8][7] = 1;
Board[10][7] = 1;
Board[4][8] = 1;
Board[5][8] = 1;
Board[6][8] = 1;
Board[7][8] = 1;
Board[8][8] = 1;
Board[9][8] = 1;
Board[10][8] = 1;
}
DrawBoard(Board);
}
</script>
</head>
<body onload="Main()">
<div id="board">
</div>
Next ->
</body>
</html>
and here is the result of the console when I click 'Next':
x = 0, y = 0, n = 0
life_broken__281_29.html:53 x = 1, y = 0, n = 1
life_broken__281_29.html:53 x = 2, y = 0, n = 0
life_broken__281_29.html:53 x = 3, y = 0, n = 0
life_broken__281_29.html:53 x = 4, y = 0, n = 0
life_broken__281_29.html:53 x = 5, y = 0, n = 0
life_broken__281_29.html:53 x = 6, y = 0, n = 0
life_broken__281_29.html:53 x = 7, y = 0, n = 0
life_broken__281_29.html:53 x = 8, y = 0, n = 0
life_broken__281_29.html:53 x = 9, y = 0, n = 0
life_broken__281_29.html:53 x = 10, y = 0, n = 0
life_broken__281_29.html:36 Uncaught TypeError: Cannot read property '0' of undefined
at Kill (life_broken__281_29.html:36)
at NextStep (life_broken__281_29.html:55)
at HTMLAnchorElement.onclick (life_broken__281_29.html:128)
I'm a bit nonplussed why this is happening because a simple for loop in this fashion does work:
for (var i = 0; i < 10; ++i) {
console.log("i = " + i);
}
VM158:2 i = 0
VM158:2 i = 1
VM158:2 i = 2
VM158:2 i = 3
VM158:2 i = 4
VM158:2 i = 5
VM158:2 i = 6
VM158:2 i = 7
VM158:2 i = 8
VM158:2 i = 9
undefined
Is the console somehow using a cached version of the old code? (I'm using the Live Preview in Brackets).
Update 2
This is because I should use a post-increment instead of a pre-increment (cf. http://jsforallof.us/2014/07/10/pre-increment-vs-post-increment/). Changing the ++x to x++ solved the problem.
The error has nothing to do with variable scope. Board is a global variable, so it's accessible to any function.
Your original problem was because you were accessing outside the Board array when x = 0 and dx = -1, and you fixed that with your wrapAround() function.
The next problem is that your loops in NextStep go too far. The row indexes go from 0 to xsize-1 and the columns go from 0 to ysize-1. But the loop there uses x <= xsize and y <= ysize, so it will try to access Board[xsize], which doesn't exist. Change those <= to <, just like the loop in Main().
if(n=3) MakeLive(Board,x,y);, your n = 3 should be n === 3, I'm sure you don't want to assign 3 to n which would cause a truthy value, which will call MakeLive(Board,x,y); every time.
Also, in NextStep you have your x and y go all the way up to xsize and ysize (<=) whereas everywhere else you use <, think that causes your undefined value in Board[x]
This seems pretty basic, but I can't find the best method to do this... I'm trying to set up a function that loops between a user selected start and end variables. This is what I ended up with but I'm sure there is a better way to do it (demo).
Note: the x & y variables are indexed to one, not zero.
getWidths1 = function(x, y) {
var start = (x < y) ? x : y,
end = (x < y) ? y : x,
total = 0;
for (; start < end; start++) {
total += values[start - 1] || 0;
}
return total;
};
I tried this function, but the results are one result off when y > x:
getWidths2 = function(x, y) {
var total = 0,
diff = (x < y) ? 1 : -1;
while (x !== y) {
total += values[x - 1] || 0;
x += diff;
}
return w;
};
So, is the first function the best, or does someone have a better method?
The first isn't bad. I think this is slightly more traditional:
for (var i = start; i < end; i++){
}
Only real difference is that it doesn't affect start and end.
I'd make a few changes:
Use Math.min and Math.max - much more readable.
Don't subtract one from start if the first value you want is values[start].
var getWidths1 = function(x, y) {
var start = Math.min(x,y), end = Math.max(x,y);
var total = 0;
for (; start < end; start++) {
total += values[start] || 0;
}
return(total);
}
I agree with #kingjiv with the added caveat that if you want to include the item at y then you need:
for (var i = start; i <= end; i++){
...
}
As it is your code (both versions) will total the values from x inclusive to y exclusive.