Make element behave a certain way until event (Making a pacman game) - javascript

I'm making a pacman game in Javascript as an exercise. What would be a good way to make the character go one direction indefinitely until another key is pressed?
function Player(){
this.left = $('#pacMan').css('left');
this.leftMove = function(){
this.left = parseInt(this.left) - 20;
$('#pacMan').animate({'left': this.left}, 100);
};
//Pressing directional keys calls appropriate methods.
$('body').keydown(function(){
if (event.which === 39){
for (i=0; i<13; i++){
pacMan.rightMove();
}
}
if (event.which === 37){
pacMan.leftMove();
}
if (event.which === 38){
pacMan.topMove();
}
if (event.which === 40){
pacMan.bottomMove();
}
});*/
How do I make it so the element keeps moving a direction until a new key is pressed, where it would go in that direction?

A general approach I tend to use for this type of problem is have your object have a changeX (vx) and a changeY (vy) variable. Then in your main game loop change the position of the object by those to variables:
this.left = parseInt(this.left) - this.vx;
this.top = parseInt(this.top) - this.vy;
In your event handler you would set the vales of vx and vy depending on where you want to move. For example setting vx = 10 and vy = 0 would make it move left by 10 units each loop.
if (event.which === 39) {
//pacMan.leftMove();
pacMan.vx = 10; pacMan.vy = 0;
}
The player would simply have a move() function that would move based on those values in the main loop:
var timer = setInterval(function () {
pacMan.move();
}, 50);
Where move() is:
this.move = function(){
this.left = parseInt(this.left) - this.vx;
$('#pacMan').css({'left': this.left})
this.top = parseInt(this.top) - this.vy;
$('#pacMan').css({'top': this.top});
}
Working Example

I recommend setTimeout function for that
setTimeout( function() {
// leftMove, topMove, bottomMove, rightMove
// if you press new key, you have to change direction
} , 1000 );
// 1000 moving delay

You could do it using window.setInterval, something like this should work
var timer;
$('body').keydown(function () {
var key = event.which;
window.clearInterval(timer);
timer = window.setInterval(function () {
switch (key) {
case 37:
pacMan.leftMove();
break;
case 38:
pacMan.topMove();
break;
case 39:
pacMan.rightMove();
break;
case 40:
pacMan.bottomMove();
break;
}
}, 100);
});

Related

Three.js Set relative position to another Object

Recently, I've been working on a video game with Three.js and I want the up arrow key to go forward relative to the camera.
Here is my code for the arrow key.
var x = 0;
var rotx = 0;
setInterval(function() {
if (x == 1){
camera.position.z += 0.05
}
}
document.addEventListener("keydown", function(event){
if (event.key == "ArrowUp"){
x = 1
}
});
document.addEventListener("keyup", function(event){
if (event.key == "ArrowUp"){
x = 0
}
});
Many times I've been searching for the answer. Usually coming across both
object.localToWorld();
object.worldToLocal();
but I can't seem to understand how to use this method.

How can I create the detection for this javascript program of mine?

I've been building on top of an assignment we did in class and I'm stumped at the detection part.
I want my Mew to be "caught" when he stands on top of the pokeball, the player moves the keyboard to control the Mew and the pokeball randomly repositions on a time delay.
How can I create a function that will detect when the mew.gif is in overlap with the pokeball?
var _stage = document.getElementById("stage");
var _Mew = document.querySelector("img");
var _PokeBall = document.getElementById("PokeBall");
_stage.style.width = "800px";
_stage.style.height = "600px";
_stage.style.backgroundColor = "black";
_stage.style.marginLeft = "auto";
_stage.style.marginRight = "auto";
_Mew.style.position = "relative"; // Uses top and left from parent
_PokeBall.style.position = "relative"; // Uses top and left from parent
var leftPressed = false;
var rightPressed = false;
var upPressed = false;
var downPressed = false;
var player = [ 400, 300 ]; // Left, Top
var PokeBall = [100, 100];// Top, Left
var uIval = setInterval(update, 22.22); // 30fps update loop
var map = []; // empty Map Array
window.addEventListener("keydown", onKeyDown);
window.addEventListener("keyup", onKeyUp);
var Pval= setInterval(MovePokeball, 2000);
function generateMap()
{
for (var row = 0; row < 2; row++)
{
for(var col = 0; col <8; col++)
{
console.log("In row "+row);
}
}
}
/*map[row] = []; // Creating new array in specified row
for (var col = 0; col <8; col++)
{
console.log("In row "+row+"doing col"+col);
}
*/
function onKeyDown(event)
{
switch(event.keyCode)
{
case 37: // Left.
if ( leftPressed == false )
leftPressed = true;
break;
case 39: // Right.
if ( rightPressed == false )
rightPressed = true;
break;
case 38: // Up.
if ( upPressed == false )
upPressed = true;
break;
case 40: // Down.
if ( downPressed == false )
downPressed = true;
break;
default:
console.log("Unhandled key.");
break;
}
}
function onKeyUp(event)
{
switch(event.keyCode)
{
case 37: // Left.
leftPressed = false;
break;
case 39: // Right.
rightPressed = false;
break;
case 38: // Up.
upPressed = false;
break;
case 40: // Down.
downPressed = false;
break;
default:
console.log("Unhandled key.");
break;
}
}
function update() // Going to run 30fps
{
movePlayer();
// move enemies
// collision check
// animate sprites
PlayerCaught();
render();
}
function movePlayer()
{
if ( leftPressed == true && player[0] >= _Mew.width/2)
player[0] -= 10;
if ( rightPressed == true && player[0] < 800 - _Mew.width/2)
player[0] += 10;
if ( upPressed == true && player[1] >= _Mew.height/2 )
player[1] -= 10;
if ( downPressed == true && player[1] < 600 - _Mew.width/2)
player[1] += 10;
}
function render()
{
_Mew.style.left = player[0]-_Mew.width/2+"px";
_Mew.style.top = player[1]-_Mew.width/2+"px";
}
function PlayerCaught()
{
if (_PokeBall [100,100] = player [100,100])
window.alert("Mew Has Been Captured!")
}
function MovePokeball()
{
_PokeBall.style.left= Math.floor(Math.random()*801)+"px";
_PokeBall.style.top= Math.floor(Math.random()*601)+"px";
}
You're asking about collision detection. This is done by determining if two polygons intersect. Since your program is very simplified, I'm offering a very simplified solution. We're going to determine if the graphics intersect. This is not the ideal way to do it. Normally, graphics and physics are completely separated. But this will work (mostly), and hopefully it'll encourage you to continue to experiment.
First, we need the height and width of both images so we can do our geometric magic. This can be easily set in JavaScript, just like you did for _stage. However, you've already defined the src of your images elsewhere (probably in HTML), so it would be best to define the height and width there.
HTML Example:
<img id="PokeBall" src="pokeball.png" style="width:50px; height:50px" />
Note: This uses "inline CSS" which is another bad practice. But this works, and I don't want to overcomplicate simple things right now.
Now your PlayerCaught method has all the information it needs to do it's job, so how do we detect collisions? If we're working with rectangles, it's very simple. We just determine if any of the corners of one object are inside the other object. So how do we do that? Basically, we see if they intersect on both the X and Y axes.
Take two rectangles: A and B. Both have four edges: top, left, right, and bottom. The edges top and bottom are Y values, and the edges left and right are X values. The two rectangles intersect if any of the following is true:
(
A.left < B.left < A.right
OR A.left < B.right < A.right
) AND (
A.top < B.top < A.bottom
OR A.top < B.bottom < A.bottom
)
Translate that into JavaScript and you've got your collision detection function. To get the edges in your program, use the following:
function findEdges(img){
var result = [];
result["left"] = parseInt(img.style.left, 10);
result["top"] = parseInt(img.style.top, 10);
result["right"] = result["left"] + parseInt(img.style.width, 10);
result["bottom"] = result["top"] + parseInt(img.style.height, 10);
return result;
}
You can see that we are using the inline style that we set earlier for the width and height as well as the top and left you are already using for rendering.
SPOILER...
Putting all the pieces together might look like:
function PlayerCaught(){
if (detectImgCollision(_PokeBall, _Mew)){
window.alert("Mew Has Been Captured!")
}
}
function detectImgCollision(imgA, imgB){
var A = findEdges(imgA);
var B = findEdges(imgB);
return detectRectCollision(A, B);
}
function detectRectCollision(A, B){
return (
isBetween(A.left, B.left, A.right)
|| isBetween(A.left, B.right, A.right)
) && (
isBetween(A.top, B.top, A.bottom)
|| isBetween(A.top, B.bottom, A.bottom)
);
}
function isBetween(low, middle, high){
return (low <= middle && middle <= high);
}

Javascript: Moving an Object with Arrow Keys

Im making a simple Tetris game. So far I have a Tetris piece that rotates when the space bar is clicked.
The next step for me is to move the objects left and right using the arrow keys. From looking at other Stack Questions I found that this was possible by changing the margins.
var angle = 0;
var obj = document.getElementById('image')
document.onkeydown = checkKey;
function checkKey(e) {
e = e || window.event;
if (e.keyCode == '32') {
rotate();
}
else if (e.keyCode == '37') {
moveLeft();
}
else if (e.keyCode == '39') {
moveRight();
}
}
function rotate() {
angle = angle + 90;
console.log(angle)
obj.className = "image" + angle;
console.log(obj.className)
if (angle == 360) {
angle = 0;
}
}
function moveLeft() {
obj.style.left = parseInt(obj.style.left) - 5 + 'px';
}
function moveRight() {
obj.style.left = parseInt(obj.style.left) + 5 + 'px';
}
For some reason this isn't working for me.
I've also re-created my code in a JSFiddle using a banana instead of a Tetris piece.
The problem is not with your Javascript, but with your styles. You need to absolutely position your image (banana in this case), and set an initial "left" value. The position: absolute; can be set either in the HTML or CSS, but the left: 0; must be set in the HTML style attribute. Here is an updated jsfiddle with the changes.

Keydown producing unexpected result. HTML5 Game

So I am at the very beginning stages of creating my first platform style game in html5.So far I have only implemented left and right movement and no 'gravity' or collision detection is at play.
However, I've already hit an issue.
If you go left or right for a short period of time the 'character' acts as intended (I use character loosely as it's the map that is actually moving). If, however, you hold the key down the map moves too fast.
I figure the issue is that the keydown event listener is listening all of the time, there for moving the map is moving before each tick or frame of the game.
So my question is how can I make the keydown increase the map offset only on every tick of the game (20 milliseconds).
Here is my JSFiddle: CLICK HERE
document.addEventListener('keydown',function(event){
var dir = event.which;
if(dir == directions.LEFT){
mapOffsetX += mapOffsetDistanceX;
event.preventDefault();
};
if(dir == directions.RIGHT){
mapOffsetX -= mapOffsetDistanceX;
event.preventDefault();
};
});
document.addEventListener('keyup',function(event){
var dir = event.which;
if(dir == directions.LEFT){
mapOffsetX -= mapOffsetDistanceX;
};
if(dir == directions.RIGHT){
mapOffsetX += mapOffsetDistanceX;
};
});
initFloorObject(100,c.height/2,300,20,0,0,0,1);
var myInt = setInterval(function(){
clearScreen();
for(var i=0;i<floorObject.length;i++){
floorObject[i][0] = parseInt(floorObject[i][0])+mapOffsetX;
};
drawChar();
drawFloorObjects();
},20);
Set variable to false every time you keydown and set it back to true every 20 milliseconds.
var isKeydownAvailable = true;
document.addEventListener('keydown', function (event) {
var dir = event.which;
if(isKeydownAvailable){
if (dir == directions.LEFT) {
mapOffsetX += mapOffsetDistanceX;
event.preventDefault();
};
if (dir == directions.RIGHT) {
mapOffsetX -= mapOffsetDistanceX;
event.preventDefault();
};
isKeydownAvailable = false;
};
});
In the interval, reset the isKeydownAvailable to true.
var myInt = setInterval(function () {
clearScreen();
for (var i = 0; i < floorObject.length; i++) {
floorObject[i][0] = parseInt(floorObject[i][0]) + mapOffsetX;
};
drawChar();
drawFloorObjects();
isKeydownAvailable = true;
}, 20);
Use booleans for actions and check for them inside your interval.
On keydown you set the boolean isMovingLeft to true, then you add the offset in your interval function only if(isMovingLeft).
Do that for the other actions and you are good to go.

Javascript HTML5 Canvas Mario Bros NES clone, collisions and jumping broken

I am hoping someone might be able to look at this javascript code I have been working on for a simple old-school Mario clone.
I have pieced together what I know about canvas from several tutorials and I am not able to get the collisions with blocks or the jumping working correctly.
the jumping seems to set Mario on an infinite loop of bouncing over and over, which looks funny but is not very conducive of playing a game!
function Player() {
this.srcX = 0;
this.srcY = 0;
this.drawX = gameWidth /2;
this.drawY = 0;
this.scaleWidth = 38;
this.scaleHeight = 50;
this.width = 48;
this.height = 60;
this.speed = 10;
this.maxJump = 50;
this.velY = 0;
this.velX = 0;
this.isJumpKey = false;
this.isRightKey = false;
this.isCrouchKey = false;
this.isLeftKey = false;
this.jumping = false;
this.grounded = false;
}
Player.prototype.draw = function(){
clearPlayer();
this.checkKeys();
ctxPlayer.drawImage(
player,
this.srcX,
this.srcY,
this.width,
this.height,
this.drawX,
this.drawY,
this.scaleWidth,
this.scaleHeight);
};
Player.prototype.checkKeys = function () {
if(this.isJumpKey){
if (!this.jumping && this.grounded ) {
this.jumping = true;
this.grounded = false;
this.velY = -this.speed * 2;
}
}
if(this.isRightKey){
if (this.velX < this.speed) {
this.velX++;
}
}
if(this.isLeftKey){
if (this.velX < this.speed) {
this.velX--;
}
}
if(this.isCrouchKey){
player1.grounded = true;
player1.jumping = false;
}
};
Here is a codepen with where I am at right now: http://codepen.io/AlexBezuska/pen/ysJcI
I really appreciate any help, I will continue to search and play around with this in the meantime, but any pointers you can give, even suggestions for formatting, prototype creation etc are really appreciated (I am quite new to both canvas and prototypes)
In your checkKeyDown() and checkKeyUp() functions, you have them checking for different 'jump' keys. From checkKeyDown():
if (keyID === 74) { //spacebar
e.preventDefault();
player1.isJumpKey = true;
}
From checkKeyUp():
if (keyID === 32) { // spacebar
player1.isJumpKey = false;
e.preventDefault();
}
So checkKeyUp() isn't properly resetting player1.isJumpKey. Set them both to the same, and it works fine for me.
As a general point, it might be worth setting up an object that holds all the parameters that have multiple instances in your code. Then write them into your code by referring to this object. That way you've only got to change them in a single place:
CONSTS = {
upKeyID: 32,
etc.
}
// then later:
if (keyID === CONSTS.upKeyID) {
player1.isJumpKey = false;
e.preventDefault();
}
I figured out the collision problem, I had the x position and y position vars in the player prototype named 'drawX' and 'drawY', but in the collision detection function, they were simply 'x' and 'y', now it works: http://codepen.io/AlexBezuska/pen/ysJcI w00t!

Categories

Resources