<commit_before><!doctype html>
<html>
<head>
<style>
body { margin: 0; padding: 0; }
</style>
</head>
<body>
<canvas id="canvas">
</canvas>
<script>
document.body.style.overflow = 'hidden';
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.setAttribute('width', window.innerWidth || document.body.clientWidth);
canvas.setAttribute('height', window.innerHeight || document.body.clientHeight);

var grid_width = 100;
var grid_height = 100;
var grid = [];
var block_size = 40;

var player = {x: 0, y: 0, vel_x: 0, vel_y: 0, accel_y: 1};

// initialize grid with 0 objects
for (var x = 0; x < grid_width; x++) {
  grid[x] = [];
  for (var y = 0; y < grid_height; y++)
    grid[x][y] = 0;
}

canvas.addEventListener('mouseup', function(evt) {
  var pos = posFromEvt(evt);
  if (!grid[pos.x][pos.y])
    grid[pos.x][pos.y] = 1;
  else
    grid[pos.x][pos.y] = 0;
});

function posFromEvt(evt) {
  var pos = {x: evt.pageX, y: evt.pageY};
  return toBlockCoords(pos);
}

function toBlockCoords(pos) {
  return {x: Math.floor(pos.x / block_size), y: Math.floor(pos.y / block_size)};
}

requestAnimationFrame(draw);
function draw() {
  ctx.clearRect(0, 0, grid_width * block_size, grid_height * block_size);
  
  update();

  // draw blocks on the grid
  for (var x = 0; x < grid_width; x++) {
    for (var y = 0; y < grid_height; y++) {
      if (grid[x][y] == 0)
        ctx.fillStyle="#FFFFFF";
      else
        ctx.fillStyle = '#666666';
      ctx.fillRect(x * block_size, y * block_size, x * block_size + block_size, y * block_size + block_size);
    }
  }

  // draw player
  ctx.beginPath();
  var radius = block_size / 2;
  ctx.arc(Math.floor(player.x) + radius, Math.floor(player.y) + radius, radius, 0, 2 * Math.PI, false);
  ctx.fillStyle = '#000099';
  ctx.fill();
  requestAnimationFrame(draw);
}

function update() {
  // friction/drag
  if (player.vel_x > 0)
    player.vel_x -= 0.1;
  else if (player.vel_y < 0)
    player.vel_x += 0.1;
  if (player.vel_y > 0)
    player.vel_y -= 0.1;
  else if (player.vel_y < 0)
    player.vel_y += 0.1;

  // y-axis acceleration (gravity) & x-axis acceleration (sideways gravity)
  if (player.accel_y)
    player.vel_y += player.accel_y;
  if (player.accel_x)
    player.vel_x += player.accel_x;

  // TODO: use a clamp() function
  if (player.vel_x > MAX_VEL)
    player.vel_x = MAX_VEL;
  else if (player.vel_x < -MAX_VEL)
    player.vel_x = -MAX_VEL;
  if (player.vel_y > MAX_VEL)
    player.vel_y = MAX_VEL;
  else if (player.vel_y < -MAX_VEL)
    player.vel_y = -MAX_VEL;

  player.x = player.x + player.vel_x;
  player.y = player.y + player.vel_y;

  // super-simple AABB collision detection & "slide" resolution
  for (var x = 0; x < grid_width; x++) {
    for (var y = 0; y < grid_height; y++) {
      if (grid[x][y]) {
        var intersection = getIntersection(
          {x1: player.x, x2: player.x + block_size, y1: player.y, y2: player.y + block_size},
          {x1: x * block_size, x2: (x + 1) * block_size, y1: y * block_size, y2: (y + 1) * block_size}
        );

        if (intersection) {
          var x_overlap = intersection.x2 - intersection.x1;
          var y_overlap = intersection.y2 - intersection.y1;
          if (x_overlap < y_overlap) {
            // back out the x overlap
            var player_on_left = player.x < x * block_size;
            if (player_on_left)
              player.x -= x_overlap;
            else
              player.x += x_overlap;
          }
          else {
            // back out the y overlap
            var player_above = player.y < y * block_size;
            if (player_above)
              player.y -= y_overlap;
            else
              player.y += y_overlap;
          }
        }
      }
    }
  }
}

function getIntersection(rect1, rect2) {
  if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2)
    throw new Error('rect1 is degenerate');
  if (rect2.x1 > rect2.x2 || rect2.y1 > rect2.y2)
    throw new Error('rect2 is degenerate');

  var x1 = Math.max(rect1.x1, rect2.x1); // biggest left edge
  var x2 = Math.min(rect1.x2, rect2.x2); // smallest right edge

  var y1 = Math.max(rect1.y1, rect2.y1); // lowest top edge
  var y2 = Math.min(rect1.y2, rect2.y2); // highest bottom edge

  if (x1 >= x2 // if the biggest left edge is bigger than the smallest right edge
    || y1 >= y2) // or the lowest top edge is lower than the highest bottom edge
    return null; // then they don't actually intersect
  
  return {x1: x1, y1: y1, x2: x2, y2: y2};
}

// load & save
document.addEventListener('keypress', function(evt) {
  if (evt.keyCode == 's'.charCodeAt(0))<commit_msg>Made collision-handling a little better & documented the bugs<commit_after><!doctype html>
<html>
<head>
<style>
body { margin: 0; padding: 0; }
</style>
</head>
<body>
<canvas id="canvas">
</canvas>
<script>
document.body.style.overflow = 'hidden';
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.setAttribute('width', window.innerWidth || document.body.clientWidth);
canvas.setAttribute('height', window.innerHeight || document.body.clientHeight);

var grid_width = 100;
var grid_height = 100;
var grid = [];
var block_size = 40;

var player = {x: 0, y: 0, vel_x: 0, vel_y: 0, accel_y: 1};

// initialize grid with 0 objects
for (var x = 0; x < grid_width; x++) {
  grid[x] = [];
  for (var y = 0; y < grid_height; y++)
    grid[x][y] = 0;
}

canvas.addEventListener('mouseup', function(evt) {
  var pos = posFromEvt(evt);
  if (!grid[pos.x][pos.y])
    grid[pos.x][pos.y] = 1;
  else
    grid[pos.x][pos.y] = 0;
});

function posFromEvt(evt) {
  var pos = {x: evt.pageX, y: evt.pageY};
  return toBlockCoords(pos);
}

function toBlockCoords(pos) {
  return {x: Math.floor(pos.x / block_size), y: Math.floor(pos.y / block_size)};
}

requestAnimationFrame(draw);
function draw() {
  ctx.clearRect(0, 0, grid_width * block_size, grid_height * block_size);
  
  update();

  // draw blocks on the grid
  for (var x = 0; x < grid_width; x++) {
    for (var y = 0; y < grid_height; y++) {
      if (grid[x][y] == 0)
        ctx.fillStyle="#FFFFFF";
      else
        ctx.fillStyle = '#666666';
      ctx.fillRect(x * block_size, y * block_size, x * block_size + block_size, y * block_size + block_size);
    }
  }

  // draw player
  ctx.beginPath();
  var radius = block_size / 2;
  ctx.arc(Math.floor(player.x) + radius, Math.floor(player.y) + radius, radius, 0, 2 * Math.PI, false);
  ctx.fillStyle = '#000099';
  ctx.fill();
  requestAnimationFrame(draw);
}

function update() {
  // friction/drag
  if (player.vel_x > 0)
    player.vel_x -= 0.1;
  else if (player.vel_y < 0)
    player.vel_x += 0.1;
  if (player.vel_y > 0)
    player.vel_y -= 0.1;
  else if (player.vel_y < 0)
    player.vel_y += 0.1;

  // y-axis acceleration (gravity) & x-axis acceleration (sideways gravity)
  if (player.accel_y)
    player.vel_y += player.accel_y;
  if (player.accel_x)
    player.vel_x += player.accel_x;

  // TODO: use a clamp() function
  if (player.vel_x > MAX_VEL)
    player.vel_x = MAX_VEL;
  else if (player.vel_x < -MAX_VEL)
    player.vel_x = -MAX_VEL;
  if (player.vel_y > MAX_VEL)
    player.vel_y = MAX_VEL;
  else if (player.vel_y < -MAX_VEL)
    player.vel_y = -MAX_VEL;

  player.x = player.x + player.vel_x;
  player.y = player.y + player.vel_y;

  // super-simple AABB collision detection & "slide" resolution
  for (var x = 0; x < grid_width; x++) {
    for (var y = 0; y < grid_height; y++) {
      if (grid[x][y]) {
        var intersection = getIntersection(
          {x1: player.x, x2: player.x + block_size, y1: player.y, y2: player.y + block_size},
          {x1: x * block_size, x2: (x + 1) * block_size, y1: y * block_size, y2: (y + 1) * block_size}
        );

        if (intersection) {
          var x_overlap = intersection.x2 - intersection.x1;
          var y_overlap = intersection.y2 - intersection.y1;
          if (x_overlap < y_overlap) {
            // back out the x overlap
            var player_on_left = player.x < x * block_size;
            if (player_on_left)
              player.x -= x_overlap;
            else
              player.x += x_overlap;
            // player.vel_x = 0;
          }
          else {
            // back out the y overlap
            var player_above = player.y < y * block_size;
            if (player_above)
              player.y -= y_overlap;
            else
              player.y += y_overlap;

            // drop the y velocity to zero on a vertical collision
            // w/out this, the constant collisions caused by gravity
            // cause some side-effects
            // but sometimes it's not perfect, like when hitting a corner
            // dropping the `vel_x` to zero makes the sideways velocity drop to zero sometimes
            // when dropping to the ground
            player.vel_y = 0;
          }
        }
      }
    }
  }
}

function getIntersection(rect1, rect2) {
  if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2)
    throw new Error('rect1 is degenerate');
  if (rect2.x1 > rect2.x2 || rect2.y1 > rect2.y2)
    throw new Error('rect2 is degenerate');

  var x1 = Math.max(rect1.x1, rect2.x1); // biggest left edge
  var x2 = Math.min(rect1.x2, rect2.x2); // smallest right edge

  var y1 = Math.max(rect1.y1, rect2.y1); // lowest top edge
  var y2 = Math.min(rect1.y2, rect2.y2); // highest bottom edge

  if (x1 >= x2 // if the biggest left edge is bigger than the smallest right edge
    || y1 >= y2) // or the lowest top edge is lower than the highest bottom edge
    return null; // then they don't actually intersect
  
  return {x1: x1, y1: y1, x2: x2, y2: y2};
}

// load & save
document.addEventListener('keypress', function(evt) {
  if (evt.keyCode == 's'.charCodeAt(0))
{'fraction_non_alphanumeric': 0.1454899150199652, 'fraction_numerical': 0.025391624859219822, 'mean_word_length': 2.548129313476208, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5025653', 'n_tokens_mistral': 3671, 'n_tokens_neox': 3555, 'n_words': 951}