snake: update
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
import Vec2d from "./vec.js";
|
||||
import { fillCircle, lerpRgb } from "./common.js";
|
||||
import { fillCircle, lerp, lerpRgb } from "./common.js";
|
||||
|
||||
// constants
|
||||
const SNAKE_SIZE = 20;
|
||||
const SNAKE_RADIUS = 10;
|
||||
const SNAKE_PADDING = 10;
|
||||
const SEGMENT_SPACING = SNAKE_SIZE + SNAKE_PADDING;
|
||||
const SEGMENT_SPACING = SNAKE_RADIUS + SNAKE_PADDING;
|
||||
const HEAD_COLOR = 0xf43f5e;
|
||||
const TAIL_COLOR = 0xf4c3cc;
|
||||
const APPLE_COLOR = 0x58f474;
|
||||
const APPLE_COLOR_2 = 0x0a6f4b4;
|
||||
|
||||
const DIRECTIONS = {
|
||||
up: new Vec2d(0, -1),
|
||||
@@ -32,10 +33,25 @@ function resizeCanvas(ctx: CanvasRenderingContext2D) {
|
||||
|
||||
let lastTime: number | undefined = undefined;
|
||||
|
||||
function update(ctx: CanvasRenderingContext2D, t: number) {
|
||||
if (lastTime == null) lastTime = t;
|
||||
const dt = (t - lastTime) / 1000; // s
|
||||
lastTime = t;
|
||||
function drawSnake(ctx: CanvasRenderingContext2D, bounds: Vec2d) {
|
||||
for (let i = 0; i < snake.length - 1; ++i) {
|
||||
// draw a trail of overlapping circles by interpolating between the body positions
|
||||
for (let j = 0; j < interpolation_factor; ++j) {
|
||||
const pos = snake[i].lerp(snake[i + 1], j / interpolation_factor).wrap(bounds);
|
||||
const t = (i + j / interpolation_factor) / snake.length;
|
||||
const color = lerpRgb(HEAD_COLOR, TAIL_COLOR, t);
|
||||
const size = lerp(SNAKE_RADIUS, SNAKE_RADIUS / 2, t);
|
||||
fillCircle(ctx, pos, size, color)
|
||||
}
|
||||
}
|
||||
const tail = snake[snake.length - 1].wrap(bounds)
|
||||
fillCircle(ctx, tail, SNAKE_RADIUS / 2, TAIL_COLOR)
|
||||
}
|
||||
|
||||
function update(ctx: CanvasRenderingContext2D, time: number) {
|
||||
if (lastTime == null) lastTime = time;
|
||||
const dt = (time - lastTime) / 1000; // s
|
||||
lastTime = time;
|
||||
apple = apple as Vec2d;
|
||||
const bounds = new Vec2d(ctx.canvas.width, ctx.canvas.height);
|
||||
|
||||
@@ -57,8 +73,7 @@ function update(ctx: CanvasRenderingContext2D, t: number) {
|
||||
// convert snake_head coords to screen space
|
||||
//const head = wrapCoords(snake_body[0], bounds);
|
||||
const head = snake[0].wrap(bounds)
|
||||
// check if snake head is overlapping apple
|
||||
if (head.distance(apple) < SNAKE_SIZE) {
|
||||
if (head.distance(apple) < SNAKE_RADIUS * 2) {
|
||||
apple = Vec2d.random(bounds.x, bounds.y)
|
||||
const { x: lastX, y: lastY } = snake[snake.length - 1];
|
||||
snake.push(new Vec2d(lastX, lastY));
|
||||
@@ -67,26 +82,16 @@ function update(ctx: CanvasRenderingContext2D, t: number) {
|
||||
}
|
||||
}
|
||||
|
||||
// draw apple
|
||||
// drawing
|
||||
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||
fillCircle(ctx, apple, SNAKE_SIZE / 2, APPLE_COLOR);
|
||||
|
||||
// draw snake
|
||||
for (let i = 0; i < snake.length - 1; ++i) {
|
||||
// draw a trail of overlapping circles by interpolating between the body positions
|
||||
for (let j = 0; j < interpolation_factor; ++j) {
|
||||
const pos = snake[i].lerp(snake[i + 1], j / interpolation_factor).wrap(bounds);
|
||||
const color = lerpRgb(HEAD_COLOR, TAIL_COLOR, (i + j / interpolation_factor) / snake.length)
|
||||
fillCircle(ctx, pos, SNAKE_SIZE / 2, color)
|
||||
}
|
||||
}
|
||||
const tail = snake[snake.length - 1].wrap(bounds)
|
||||
fillCircle(ctx, tail, SNAKE_SIZE / 2, TAIL_COLOR)
|
||||
const t = (Math.sin(0.01 * time) + 1.0) * 0.5;
|
||||
const apple_size = lerp(SNAKE_RADIUS, SNAKE_RADIUS * 0.9, t)
|
||||
fillCircle(ctx, apple, apple_size, APPLE_COLOR); // draw apple
|
||||
drawSnake(ctx, bounds);
|
||||
|
||||
window.requestAnimationFrame((t) => update(ctx, t));
|
||||
}
|
||||
|
||||
|
||||
function init() {
|
||||
const canvas = document.getElementById("game-canvas") as HTMLCanvasElement | null;
|
||||
if (!canvas) throw new Error("unable to get canvas HTML element");
|
||||
@@ -109,7 +114,7 @@ function init() {
|
||||
case "ArrowRight": case "d": new_direction = DIRECTIONS.right; break;
|
||||
case "j": interpolation_factor++; break;
|
||||
case "k": interpolation_factor = Math.max(1, interpolation_factor-1); break;
|
||||
case "p":
|
||||
case "Space": case "p":
|
||||
paused = !paused;
|
||||
setStatusLine(paused ? "paused" : "", null);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user