Question

I’m fairly new to web development and I’ve only ever used jQuery to write my scripts. Today however, I’d like to improve my skills and build a little game that could be used on a smartphone as a web app in vanilla JS.

The game’s pretty straightforward: You hold your phone in portrait mode and control a character that stays at the bottom of the screen and has to dodge objects that are falling on him. The character can only move left or right and thus always stays on the same x-axis. In order to control him, your finger has to stay on the screen. Once you take it off, you lose. Also, the move isn’t triggered by tapping the screen, but by moving your finger left or right.

For now, I’ve only been experimenting to get the hang of touchevents and was able to make the character move when swiping:

document.addEventListener('touchmove',function(e){
e.preventDefault(); //disable scroll

var board = document.getElementById(‘board);
var character = document.getElementById(‘character’);

if (e.targetTouches.length === 1) {
    var touch = e.targetTouches[0];
    board.classList.add(‘moving’);

    character.style.left = touch.pageX + 'px';
}

}, false);

(The ‘moving’ class is used to move the background-position of the board and animate the character’s sprite in plain CSS.)

Separately, I made a little script that puts objects with random classes in a container with a set interval. These objects are then animated in css and fall from the top to the bottom of the screen.

Now, here comes the tricky part: the collision detection. As I said, I’m new to development and vanilla JS, so I searched a bit to figure out how to detect when two objects collide, and it seems that most tutorials do this using canvases. The thing is, I’ve never used them and they scare me quite a bit. What’s more, I think it would render what I’ve done so far useless.

I’m okay with trying the canvas way, but before I do, I’d like to know if there’s any other way to detect if two moving objects collide?

Also, if there turns out to be no real way to do this without canvas, I plan on using this tutorial to learn how to build the app. However, this game wasn’t built for touchscreen devices, and the spaceship’s position changes on certain keystrokes (left & right) :

function update() {
  if (keydown.left) {
    player.x -= 5;
   }

  if (keydown.right) {
    player.x += 5;
  }

  player.x = player.x.clamp(0, CANVAS_WIDTH - player.width);
}

My question is: how should I do to update the position using touchmove instead of keystrokes?

Thank you all in advance.

Was it helpful?

Solution

1) the idea : 'if you stop touching, you loose', is just a bad idea, drop it.
2) most convenient way to control is to handle any touch event (touch start/move/end/cancel), and to have the character align on the x coordinate of this event.
3) the intersection test is just a basic boundig box intersection check.

I made a very basic demo here, that uses touch, but also mouse to ease testing :

http://jsbin.com/depo/1/edit?js,output

a lot of optimisations are possible here, but you will see that touches adjust the ship's position, and that collisions are detected, so it will hopefully lead you to your own solution

Edit : i added default to 0 for left, top, in case they were not set.

boilerplate code :

var collisionDisplay = document.getElementById('collisionDisplay');

// hero ship
var ship = document.getElementById('ship');
ship.onload = launchWhenReady ;

//  bad ship
var shipBad = document.getElementById('shipBad');
shipBad.onload = launchWhenReady ;

// image loader
imagesCount = 2 ;

function launchWhenReady() {
  imagesCount --;
  if (imagesCount) return;
  setInterval(animate, 20);
}

var shipBadY = 0;

touch events :

// listen any touch event
document.addEventListener('touchstart', handleTouchEvent, true);
document.addEventListener('touchmove', handleTouchEvent, true);
document.addEventListener('touchend', handleTouchEvent, true);
document.addEventListener('touchcancel', handleTouchEvent, true);

// will adjust ship's x to latest touch
function handleTouchEvent(e) {
    if (e.touches.length === 0 ) return;
    e.preventDefault();
    e.stopPropagation();
    var touch = e.touches[0];
    ship.style.left = (touch.pageX - ship.width / 2) + 'px';
}

animation :

// animation loop
function animate()  {
    // move ship
    shipBadY += 1;
    shipBad.style.top = Math.ceil(shipBadY) + 'px';
    // test collision
    var isColliding = testCollide(shipBad);
    collisionDisplay.style.display = isColliding ? 'block' : 'none';
}

collision :

// collision test when the enemy and the ship are images
function testCollide(enemi) {
    var shipPosX = parseInt(ship.style.left) || 0 ;
    var shipPosY = parseInt(ship.style.top) || 0 ;
    var shipWidth = ship.width ;
    var shipHeight = ship.height;
    var badX = parseInt(enemi.style.left) || 0 ;
    var badY = parseInt(enemi.style.top) || 0 ;
    var badWidth = enemi.width;
    var badHeight = enemi.height;
    return bBoxIntersect(shipPosX, shipPosY, shipWidth, shipHeight,
    badX, badY, badWidth, badHeight);
}

EDIT : in case you're not using images :

   // collision test when the enemy and the ship are ** NOT ** images
   function testCollide(o) {
    var characterPosX = parseInt(character.style.left);
    var characterPosY = parseInt(character.style.top);
    var characterWidth = parseInt(character.style.width);
    var characterHeight = parseInt(character.style.height);

    var obstacleX = parseInt(o.style.left) || 0 ;
    var obstacleY = parseInt(o.style.top) || 0 ;
    var obstacleWidth = parseInt(o.style.width);
    var obstacleHeight = parseInt(o.style.height);

    return boundingBoxIntersect(characterPosX, characterPosY, characterWidth, characterHeight, obstacleX, obstacleY, obstacleWidth, obstacleHeight);
}
function bBoxIntersect(x1, y1, w1, h1, x2, y2, w2, h2) {
    return !(x1 + w1 < x2 || x1 > x2 + w2 || y1 + h1 < y2 || y1 > y2 + w2);
}

mouse events :

// -----------------------------------------------------
// Handle mouse event for easy testing on Browser

document.addEventListener('mousemove', handleMouseEvent);

function handleMouseEvent(e) {
    ship.style.left = (e.pageX - ship.width / 2) + 'px';
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top