I'm trying to make my sprite be able to move left or right. It can jump, but not move. I have tried different approaches, but I'm clearly missing something.
I'm using p5.js and its addon p5.play.js.
Here's my code:
p5.prototype.print = p5.prototype.println;
var asterisk;
var platform;
var GRAVITY = 1;
var JUMP = 15;
function setup() {
createCanvas(800, 600);
asterisk = createSprite(30, 200, 20, 60);
//if defined, the collider will be used for mouse events
asterisk.setCollider("circle", 0,0,33);
platform = createSprite(200, 585, 500, 20);
}
function draw() {
background(51);
asterisk.velocity.y += GRAVITY;
if(asterisk.collide(platform)) {
asterisk.velocity.y = 0;
}
if(keyWentDown("UP_ARROW") || mouseWentDown(LEFT)){
asterisk.velocity.y = -JUMP;
}
function keyReleased() {
if (key != ' '){
asterisk.setDir(0);
}
}
function keyPressed(){
if (keyCode === RIGHT_ARROW){
asterisk.setDir(1);
}else if (keyCode === LEFT_ARROW){
asterisk.setDir(-1);
}
}
drawSprites();
}
Related
I am learning P5.JS with "The Nature of Code", and trying out the first example code.
https://github.com/nature-of-code/noc-examples-p5.js/tree/master/chp00_introduction/NOC_I_01_RandomWalkTraditional
let walker;
let bg_color_x = 255;
let bg_color_y = 51;
let bg_color_z = 153;
let stroke_color_x = 51;
let stroke_color_y = 51;
let stroke_color_z = 204;
let stroke_weight = 10;
let random_number_for_walking = 5;
function setup() {
var cnv = createCanvas(windowWidth, windowHeight);
cnv.style('display', 'block');
background(bg_color_x, bg_color_y, bg_color_z);
walker = new Walker();
}
function draw() {
walker.step();
walker.render();
}
class Walker {
constructor() {
this.x = width / 2;
this.y = height / 2;
}
render() {
stroke(stroke_color_x, stroke_color_y, stroke_color_z);
strokeWeight(stroke_weight);
point(this.x, this.y);
}
step() {
var choice = floor(random(random_number_for_walking));
if (choice === 0) {
// this.x++;
this.x = this.x + stroke_weight;
} else if (choice == 1) {
// this.x--;
this.x = this.x - stroke_weight;
} else if (choice == 2) {
// this.y++;
this.y = this.y + stroke_weight;
} else {
// this.y--;
this.y = this.y - stroke_weight;
}
this.x = constrain(this.x, 0, width - stroke_weight);
this.y = constrain(this.y, 0, height - stroke_weight);
}
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
background(bg_color_x, bg_color_y, bg_color_z);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
However, no matter how many times I run it, the art settles at the top of the window. For example, like this.
How can I fix this? Is there a way to make it go left or right when it hits one of the four borders?
Your random_number_for_walking is wrong!
Your step function has 4 paths:
step() {
var choice = floor(random(random_number_for_walking));
if (choice === 0) {
// Right
} else if (choice == 1) {
// Left
} else if (choice == 2) {
// Down
} else {
// Up
}
// ...
}
But your random_number_for_walking is 5 and random(number) gives you a number between [0, number), so in your case: 0, 1, 2, 3, 4.
And if you look closer, you do not handle choice == 3, with that else you are actually handling choice == 3 || choice == 4.
This makes it so its more probable that your Walker moves up than down.
Handling correctly the last choice and reducing random_number_for_walking to 4 will solve the issue.
I am trying to make a 2D platforming game and I am missing an essential part of it, gravity.
I have tried everything from look at questions on this website to looking at online tutorials and you-tube videos.
I really need help with getting gravity into this game as I am out of ideas.
As I said I have already tried looking at multiple tutorials and videos, including this one:
http://www.somethinghitme.com/2013/01/09/creating-a-canvas-platformer-tutorial-part-one/
but this one uses shapes created in canvas rather than images.
I already know that you have to use a velocity function as well as variable for the gravity. Then you have to put this all inside the key handler function so that it can get executed.
//spaceman variables
var sx = canvasWidth / 2; // start the spaceman in the centre
var sy = canvasHeight / 2;
var sdx = 0; // set initial speed to 0
var sdy = 0;
var sspeed = 3; // create a variable for speed
var gravity = 0.2;
var svX = 0;
var svY = (Math.random() * -10) - 5;
//set variables to use for key presses
//these are Boolean variables
//they can only be true or false
var rightPressed = false;
var leftPressed = false;
var upPressed = false;
var downPressed = false;
function keyDownHandler(e) {
if (e.keyCode == 39) {
rightPressed = true;
} else if (e.keyCode == 37) {
spaceman2Ready = true;
spacemanReady = false;
leftPressed = true;
} else if (e.keyCode == 38) {
upPressed = true;
} else if (e.keyCode == 40) {
downPressed = true;
}
}
function keyUpHandler(e) {
if (e.keyCode == 39) {
rightPressed = false;
sdx--;
} else if (e.keyCode == 37) {
spaceman2Ready = false;
spacemanReady = true;
leftPressed = false;
sdx--;
} else if (e.keyCode == 38) {
upPressed = false;
sdx--;
} else if (e.keyCode == 40) {
downPressed = false;
sdx--;
}
}
// add something to "listen" for an event
//an event is keypress, mouse movement, mouse click etc.
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (rightPressed == true) {
sdx = sspeed;
} else if (leftPressed == true) {
sdx = -sspeed;
} else if (upPressed == true) {
sdy = -sspeed;
} else if (downPressed == true) {
sdy = sspeed
}
if (rightPressed == false && leftPressed == false && upPressed == false && downPressed == false) {
sdx = 0;
sdy = 0;
}
sx = sx + sdx;
sy = sy + sdy;
}
if (spacemanReady) {
ctx.drawImage(spacemanImage, sx, sy);
if (spaceman2Ready) {
ctx.drawImage(spaceman2Image, sx, sy);
}
// basically the setTimeout part, but this time its requesting the function that we made at the top
requestAnimationFrame(draw);
}
// this is to get the loop for the animation to start going
window.addEventListener("load",
function() {
draw();
});
< /script>
</body >
</html>/
You should be using gravity to update your position every frame (in the draw function). This would look like:
if(sy > 0){
sdy += gravity
}
I have created a codepen with your game with gravity. I hope this helps!
I'm making a game in which a player character moves left and right.
Since simply using an onKeyDown eventListener had my character move in a choppy fashion, and with a slight delay, I tried using requestAnimationFrame to call the movement function as often as possible, as suggested by another answer(How can I move my JS objects smoothly using keyboard input?)
however, that has changed nothing.
Here is my Javascript Code
var NodoCampo = document.getElementById("campo");
var NodoGiocatore = null;
var Left = false;
var Right = false;
var FRAMERATE = 20;
//cache giocatore
var LARG_GIOCATORE = 30;
var ALT_GIOCATORE = 30;
var X_GIOCATORE = 300;
var Y_GIOCATORE = 1100;
var VEL_GIOCATORE = 10;
function mostra_giocatore() {
if (NodoGiocatore === null) {
NodoGiocatore = document.createElement('div');
NodoGiocatore.setAttribute ('id', 'player');
NodoCampo.appendChild (NodoGiocatore);
}
NodoGiocatore.style.marginLeft = (X_GIOCATORE - LARG_GIOCATORE) + 'px';
NodoGiocatore.style.marginTop = (Y_GIOCATORE - ALT_GIOCATORE) + 'px';
}
function muovi() {
if (Left) {
X_GIOCATORE = X_GIOCATORE - VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
else if (Right) {
X_GIOCATORE = X_GIOCATORE + VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
}
function stop() {
Left = false;
Right = false;
}
function interfaccia(e) {
//freccia sinstra
if (e.keyCode === 37) {
X_GIOCATORE = X_GIOCATORE - VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
//freccia destra
else if (e.keyCode === 39) {
X_GIOCATORE = X_GIOCATORE + VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
}
function inizia() {
mostra_giocatore();
requestAnimationFrame(muovi);
}
window.document.onkeypress = interfaccia;
window.document.onkeyup = stop;
Your choppy movement is likely a result of the amount you are moving the player on each frame with VEL_GIOCATORE. Try reducing this amount to observe smoother movement.
The delay you are experiencing is likely due to your operating system or browsers individual settings on how key presses should repeat. You can work around this by implementing your own key tracking -- it looks like you've started to experiment with this. Track the state of your left and right keys by updating a boolean value in onkeydown and onkeyup event listeners.
var keys = {
left: false,
right: false
};
window.document.onkeydown = function (e) {
if (e.keyCode === 37) {
keys.left = true;
} else if (e.keyCode === 39) {
keys.right = true;
}
window.document.onkeyup = function (e) {
if (e.keyCode === 37) {
keys.left = false;
} else if (e.keyCode === 39) {
keys.right = false;
}
Then, in your muovi function, check the state of these variables to determine if you should update the position of the player.
I am creating a Canvas game of 'Snake'. Using your arrow keys, you can move the snake around.
What I'm working on is clearing an interval when a different arrow key is pressed. I am trying to make use of both setInterval and clearInterval. Here is one of the four such functions I have.
https://jsfiddle.net/2q1svfod/2/
function moveUp() {
if (direction != "up") {
incrementScore();
}
direction = "up";
if (direction == "up") {
var goUp = setInterval(function() {
ctx.lineTo(headX, headY - 10);
ctx.stroke();
headY -= 10;
}, 1000);
}
else {
clearInterval(goUp);
}
}
The objective is to avoid crashing into the walls, which will result in losing the game, and your score will be reset. I'd like to prevent players from repeatedly tapping on a key to get extra points, so I only increase their score once per direction.
As long as the direction stays the same, I want the interval to keep running. That's why I declared the goUp interval inside this conditional.
If the direction has changed, I clear that interval. However, two intervals are now going on at the same time instead of 1.
Does anyone know where I'm going wrong here?
This is one implementation (out of many) you might consider.
var currentInput = {
left: false,
up: false,
right: false,
down: false
};
function getKey(keyCode) {
if (keyCode === 37) {
return 'left';
} else if (keyCode === 38) {
return 'up';
} else if (keyCode === 39) {
return 'right';
} else if (keyCode === 40) {
return 'down';
}
}
function onKeyDown(event) {
var key = getKey(event.keyCode);
currentInput[key] = true;
}
function onKeyUp(event) {
var key = getKey(event.keyCode);
currentInput[key] = false;
}
document.addEventListener('keydown', onKeyDown, false)
document.addEventListener('keyup', onKeyUp, false)
function update() {
requestAnimationFrame(update);
if (currentInput.left) {
// move snake left
} else if (currentInput.right) {
// etc.
}
}
// Kick off the event loop
requestAnimationFrame(update);
I managed to find a solution, but I'm not too thrilled I had to resort to using global variables.
It looks something like this
function moveUp() {
if (direction != "up") {
incrementScore();
}
direction = "up";
clearInterval(goRight);
upArrow();
}
function upArrow() {
if (direction == "up") {
goUp = setInterval(function() {
ctx.lineTo(headX, headY - 10);
ctx.stroke();
headY -= 10;
}, 1000);
}
}
It works and I'm able to change directions. But I don't like using globals.
Here's the updated fiddle
https://jsfiddle.net/2q1svfod/6/
I'm brand new to JavaScript, and have a crashing application. I have no idea what would cause the crash.
Here is the code:
<script>
//constants
var Col = 20, Rows = 20;
var cellHeight = 25;
var cellWidth = 25;
var foodX;
var score;
var foodY;
var Nothing = 0, Snake = 1, Food = 2;
var Left = 37, Up = 38, Right = 39, Down = 40;
var canvas = document.getElementById('snakeCanvas');
var context = canvas.getContext('2d');
var dead = "false";
var snakeDirection = null;
var keystate;
var snake = [];
function start() //this is where we begin the long journey
{
init();
Tick();
}
function init() {
snake = [{ x: 5, y: 5 }];
snakeDirection = null;
score = 0;
document.getElementById("score").innerHTML = "Score: " + score;
setFood();
keystate = null;
}
function Tick() // just liker a timer tick
{
document.addEventListener("keydown", function (evt) {
keystate = evt.keyCode; // checks key presses
});
//document.addEventListener("keyup", function (evt) {
//delete keystate[evt.keyCode];
//});
update(); //after we check for a key press we update alllll the
stuff
setTimeout(Tick, 300);
//}
}
function update()
{
checkKey(); // checks what key has been pressed
for (var i = snake.length-1; i > 0; i--) {
snake[i].y = snake[i-1].y;
snake[i].x = snake[i-1].x
}
switch (snakeDirection) { // keys
case "DOWN":
snake[0].y++;
break;
case "UP":
snake[0].y--;
break;
case "RIGHT":
snake[0].x++;
break;
case "LEFT":
snake[0].x--;
break;
}
draw(); //draws all the stuff like food and snake
checkCollisions(); // self explaintory name
}
function checkKey() //Change the direction of the snake cant go
backwards too
{
if (keystate == Left && snakeDirection != "RIGHT" )
{
snakeDirection = "LEFT";
}
if (keystate == Up && snakeDirection != "DOWN")
{
snakeDirection = "UP";
}
if (keystate == Right && snakeDirection != "LEFT")
{
snakeDirection = "RIGHT";
}
if (keystate == Down && snakeDirection != "UP")
{
snakeDirection = "DOWN";
}
}
function setFood()
{ //WE ARE RUNNING OUT OF FOOD WE NEED NEW PROVISIONS
var next = "true"
do {
foodX = Math.floor((Math.random() * Rows));
foodY = Math.floor((Math.random() * Col));
for (var i = 0; i < snake.length; i++) { // IT SUCKS WHEN I
CANT EAT FOOD BECAUSE ITS ALREADY INSIDE OF ME
if (snake[i].x == foodX && snake[i].y == foodY) {
next = "false"
}
}
}
while (next == "false")
draw(); // Pretty pictures
}
function checkCollisions()
{
for (var i = 1; i < snake.length; i++) { // STOP hitting
yourself
if (snake[0].x == snake[i].x && snake[0].y == snake[i].y) {
init();
}
}
if (snake[0].y < 0 || snake[0].y > Rows || snake[0].x < 0 ||
snake[0].x > Col) // you are forbidon to veture from the canvas
{
init();
}
if (snake[0].x == foodX && snake[0].y == foodY) { //Yummy FOOD EAT
EAT EAT
score++;
document.getElementById("score").innerHTML = "Score: " + score;
setFood();
snake.push({ x: null, y: null }); // I got fatter
}
}
function draw()
{
context.clearRect(0, 0, canvas.width, canvas.height); // clears
canvas
context.fillStyle = "#FF0000"; // pretty colour for the head of
the snake
context.fillRect(snake[0].x * cellWidth, snake[0].y * cellWidth,
cellWidth, cellHeight);
context.fillStyle = "#09F";
for (var i = 1; i < snake.length; i++)
{
context.fillRect(snake[i].x * cellWidth, snake[i].y * cellWidth,
cellWidth, cellHeight);
}
context.fillStyle = "#F90"; // FOOD FOOD FOOD FOOD
context.fillRect(foodX * cellWidth, foodY * cellWidth, cellWidth,
cellHeight);
}
start(); // starts hence the name start
</script>
OK not bad for a beginer if you wrote it all your self.
Your problem is with the keydown event. You are creating a new handler each time you tick. This will lead to a crash. You only need to create the event handler once for the page, it will remain active until you leave the page.
To fix your problem move adding the keyDown listener to just above the function Start, as shown below.
var snake = [];
document.addEventListener("keydown", function (evt) {
keystate = evt.keyCode; // checks key presses
});
function start(){
init();
Tick();
}
Also just a because to me it looks weird. true and false are not strings you dont need to put quotes around them. Though using them as strings still works.
You have
function setFood() { //WE ARE RUNNING OUT OF FOOD WE NEED NEW PROVISIONS
var next = "true"
do {
foodX = Math.floor((Math.random() * Rows));
foodY = Math.floor((Math.random() * Col));
for (var i = 0; i < snake.length; i++) {
if (snake[i].x == foodX && snake[i].y == foodY) {
next = "false"
}
}
} while (next == "false")
draw();
}
would be better written as follows
function setFood() {
var next = true; // removed the qoutes
do {
foodX = Math.floor((Math.random() * Rows));
foodY = Math.floor((Math.random() * Col));
for (var i = 0; i < snake.length; i++) {
if (snake[i].x == foodX && snake[i].y == foodY) {
next = false; // removed the quotes.
// no point continuing the for loop as you know you need to
// reposition the food so use the break token
break; // breaks out of the closest loop
}
}
} while ( !next ) // removed next == "false" and replaced with
// ! next. "!" means "Not". do while next not true
// you have the draw here but you draw every tick so it would be best if
// you removed it as the next draw is less than 1/3 of a second away anyways
// draw(); // removed needless draw
}
Good work. Hope you get a good mark for it.