html5 strongeaseinout,HTML5键盘侠百米赛跑运动会

JavaScript

语言:

JaveScriptBabelCoffeeScript

确定

// ----------

// Utility

// ----------

Util = {};

Util.timeStamp = function() {

return window.performance.now();

};

Util.random = function(min, max) {

return min + Math.random() * (max - min);

};

Util.array2D = function(tableau, largeur) {

var result = [];

for (var i = 0; i < tableau.length; i += largeur) result.push(tableau.slice(i, i + largeur));

return result;

};

Util.map = function(a, b, c, d, e) {

return (a - b) / (c - b) * (e - d) + d;

};

Util.lerp = function(value1, value2, amount) {

return value1 + (value2 - value1) * amount;

};

Util.linearTween = function(currentTime, start, degreeOfChange, duration) {

return degreeOfChange * currentTime / duration + start;

};

Util.easeInOutQuad = function(t, b, c, d) {

t /= d / 2;

if (t < 1) return c / 2 * t * t + b;

t--;

return -c / 2 * (t * (t - 2) - 1) + b;

};

Util.easeInOutExpo = function(t, b, c, d) {

t /= d / 2;

if (t < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;

t--;

return c / 2 * (-Math.pow(2, -10 * t) + 2) + b;

};

// ----------

// Scene

// ----------

class Scene {

constructor(name) {

this.name = name;

this.loop = true;

this.init_once = false;

}

giveWorld(world) {

this.world = world;

this.ctx = world.ctx;

}

keyEvents(event) {

}

init() {

}

render() {

}

addEntity() {

}

}

class Entity {

constructor(scene, x, y) {

this.scene = scene;

this.world = scene.world;

this.ctx = this.world.ctx;

this.body = new Body(this, x, y);

}

setSprite(sprite_data) {

this.sprite = new Sprite(this, sprite_data);

}

display() {

if (this.sprite === undefined) {

this.ctx.strokeStyle = "#000";

this.ctx.strokeRect(this.body.position.x, this.body.position.y, this.body.size.x, this.body.size.y);

} else {

this.sprite.display();

}

}

integration() {

this.body.integration();

}

}

// class for animated sprites !

class Sprite {

constructor(entity, sprite_data) {

this.entity = entity;

this.world = this.entity.world;

this.tile_size = this.world.tile_size;

this.ctx = this.world.ctx;

// image data

this.image = this.world.assets.image[sprite_data.image].image;

// sprite

this.size = sprite_data.size;

this.current_frame = 0;

this.animations = {};

this.current_animation = undefined;

this.width = this.image.width / this.size.x;

this.height = this.image.height / this.size.y;

// timer

this.tick = 0;

this.speed = 0.2;

// offset

this.offset = {

x: 0,

y: 0,

}

}

addAnimation(name, frames) {

this.animations[name] = frames;

this.current_animation = name;

}

animate(animation_name) {

this.current_animation = animation_name;

if (this.tick < 1) {

this.tick += this.speed;

} else {

this.tick = 0;

if (this.current_frame < this.animations[animation_name].length - 1) {

this.current_frame += 1;

} else {

this.current_frame = 0;

}

}

}

display() {

this.ctx.drawImage(this.image,

Math.floor(this.animations[this.current_animation][this.current_frame] % this.width) * this.size.x,

Math.floor(this.animations[this.current_animation][this.current_frame] / this.width) * this.size.y,

this.size.x,

this.size.y,

this.entity.body.position.x + (this.tile_size / 2 - this.size.x / 2) + this.offset.x,

this.entity.body.position.y + (this.tile_size / 2 - this.size.x / 2) + this.offset.y,

this.size.x,

this.size.y

);

}

}

class Body {

constructor(entity, x, y) {

this.world = entity.world;

this.step = this.world.FPS.step;

this.position = new Vector(x, y);

this.next_position = new Vector(x, y);

this.velocity = new Vector(0, 0);

this.stepped_velocity = new Vector(0, 0);

this.acceleration = new Vector(0, 0);

this.drag = 0.98;

this.size = {

x: 16,

y: 16

};

}

setSize(x, y) {

this.size.x = x;

this.size.y = y;

}

updateVelocity() {

this.velocity.add(this.acceleration);

this.velocity.mult(this.drag);

this.stepped_velocity = this.velocity.copy();

this.stepped_velocity.mult(this.step);

this.next_position = this.position.copy();

this.next_position.add(this.stepped_velocity);

// reset acceleration

this.acceleration.mult(0);

}

updatePosition() {

this.position.add(this.stepped_velocity);

}

integration() {

this.updateVelocity();

this.updatePosition();

}

applyForce(force_vector) {

this.acceleration.add(force_vector);

}

}

class Vector {

constructor(x, y) {

this.x = x || 0;

this.y = y || 0;

}

set(x, y) {

this.x = x;

this.y = y;

}

add(vector) {

this.x += vector.x;

this.y += vector.y;

}

sub(vector) {

this.x -= vector.x;

this.y -= vector.y;

}

mult(scalar) {

this.x *= scalar;

this.y *= scalar;

}

div(scalar) {

this.x /= scalar;

this.y /= scalar;

}

limit(limit_value) {

if (this.mag() > limit_value) this.setMag(limit_value);

}

mag() {

return Math.hypot(this.x, this.y);

}

setMag(new_mag) {

if (this.mag() > 0) {

this.normalize();

} else {

this.x = 1;

this.y = 0;

}

this.mult(new_mag);

}

dist(vector) {

return new Vector(this.x - vector.x, this.y - vector.y).mag();

}

normalize() {

let mag = this.mag();

if (mag > 0) {

this.x /= mag;

this.y /= mag;

}

}

heading() {

return Math.atan2(this.x, this.y);

}

setHeading(angle) {

let mag = this.mag();

this.x = Math.cos(angle) * mag;

this.y = Math.sin(angle) * mag;

}

copy() {

return new Vector(this.x, this.y);

}

}

class Box {

constructor(world, box_data) {

this.world = world;

this.ctx = world.ctx;

this.c_ctx = world.c_ctx;

this.box_data = box_data;

this.resolution = box_data.resolution;

this.image = world.assets.image[box_data.image].image;

}

display(x, y, width, height) {

// background

this.ctx.fillRect(x + 1, y + 1, width - 2, height - 2);

// corners

this.ctx.lineWidth = 2;

let coners = [0, 2, 6, 8];

for (let i = 0; i < 4; i++) {

let pos_x = x + Math.floor(i % 2) * (width - this.resolution),

pos_y = y + Math.floor(i / 2) * (height - this.resolution);

let clip_x = Math.floor(i % 2) * (this.resolution * 2),

clip_y = Math.floor(i / 2) * (this.resolution * 2);

this.ctx.drawImage(this.image,

clip_x, clip_y,

this.resolution, this.resolution,

pos_x, pos_y,

this.resolution, this.resolution);

}

let offset = this.resolution * 3;

// top

this.ctx.drawImage(this.image,

8, 0,

this.resolution, this.resolution,

x + 8, y,

this.resolution + width - offset, this.resolution);

// bottom

this.ctx.drawImage(this.image,

8, 16,

this.resolution, this.resolution,

x + 8, y + height - this.resolution,

this.resolution + width - offset, this.resolution);

// left

this.ctx.drawImage(this.image,

0, 8,

this.resolution, this.resolution,

x, y + 8,

this.resolution, this.resolution + height - offset);

// right

this.ctx.drawImage(this.image,

16, 8,

this.resolution, this.resolution,

x + width - this.resolution, y + this.resolution,

this.resolution, this.resolution + height - offset);

}

}

// ----------

// Diorama.js

// ----------

class Diorama {

constructor(parameters) {

this.parameters = parameters;

// Game and author's name

this.game_info = {

name: parameters.name || "Untitled",

author: parameters.author || "Anonymous",

};

// canvas

this.background_color = parameters.background_color || "#000";

this.initCanvas(parameters);

// Assets

this.counter = 0;

this.toLoad = parameters.assets.length;

this.assets = {

image: {},

audio: {},

};

this.audio_muted = false;

// keyboard event

this.keys = {};

// Scenes

this.scenes = {};

this.start_screen = parameters.start_screen || undefined;

this.current_scene = "";

// Bitmap font Data

this.alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ?!:',.()<>[]";

this.fonts = {};

// Maps

this.tile_size = parameters.tile_size || 16;

this.tiles_data = {};

if (parameters.tiles !== undefined) {

parameters.tiles.map(tile => {

this.tiles_data[tile.id] = tile;

});

}

this.mapsMax = parameters.maps.length;

this.maps = {};

if (parameters.maps !== undefined) {

parameters.maps.map(map => {

this.maps[map.name] = map;

});

}

// Box system

this.boxes = {};

// By default the current font is the first font you create

this.currentFont = undefined;

// Game loop Data

this.FPS = {

now: 0,

delta: 0,

last: Util.timeStamp(),

step: 1 / (parameters.frame_rate || 60),

};

this.requestChange = {

value: false,

action: ""

};

this.main_loop = undefined;

this.setScale();

}

// ---

// Setup & Loading

// ---

ready() {

this.loadAssets(this.parameters.assets);

}

initCanvas(parameters) {

this.canvas = document.createElement("canvas");

this.ctx = this.canvas.getContext('2d');

this.W = this.canvas.width = parameters.width || 256;

this.H = this.canvas.height = parameters.height || 256;

this.scale = parameters.scale || 1;

this.full = false;

this.ctx.imageSmoothingEnabled = false;

this.canvas.classList.add("crisp");

document.body.appendChild(this.canvas);

// cache canvas

this.cache = document.createElement("canvas");

this.c_ctx = this.cache.getContext("2d");

}

loader() {

// increment loader

this.clear("#222");

this.counter += 1;

let padding = 20;

let width = this.W - padding * 2,

x = padding,

y = this.H - padding * 2;

this.ctx.fillStyle = "#111";

this.ctx.fillRect(x, y, width, 20);

this.ctx.fillStyle = "#333";

this.ctx.fillRect(x, y, (this.counter * width / this.toLoad), 20);

this.ctx.strokeStyle = "#000";

this.ctx.lineWidth = 4;

this.ctx.strokeRect(x, y, width, 20);

if (this.counter === this.toLoad) {

this.launch();

}

}

loadAssets(assets) {

if (assets === undefined) console.log("Nothing to load");

assets.map(obj => this.checkAssets(obj));

}

checkAssets(obj) {

let subject = obj;

switch (obj.type) {

case "img":

let img = new Image();

img.onload = () => {

this.loader();

};

img.onerror = () => {

console.log("can't load Image: " + obj.name);

};

img.src = obj.path;

subject.image = img;

this.assets.image[obj.name] = subject;

break;

case "audio":

let audio = new Audio(obj.path);

audio.addEventListener('canplaythrough', this.loader());

audio.onerror = () => {

console.log("can't load audio: " + obj.name);

};

subject.audio = audio;

this.assets.audio[obj.name] = subject;

break;

case undefined:

console.log(obj.name, " doesn't have any type");

break;

default:

console.log(obj.name, " has a none known type");

}

}

launch() {

this.eventSetup();

this.initBoxes(this.parameters.boxes);

this.initFonts(this.parameters.fonts);

this.startScene(this.start_screen);

}

initBoxes(boxes_data) {

if (boxes_data === undefined) return false;

boxes_data.map(box => {

this.boxes[box.name] = new Box(this, box);

});

}

drawBox(box_name, x, y, width, height) {

this.boxes[box_name].display(x, y, width, height);

}

// ---

// Font manager

// ---

setFont(font_name) {

this.currentFont = font_name;

}

initFonts(fonts_data) {

if (fonts_data === undefined && fonts_data.length > 0) return false;

fonts_data.map(font => {

if (this.assets.image[font.image] === undefined) {

console.log("can't load font, " + font.image + " doesn't exist");

return false

};

font.image = this.assets.image[font.image].image;

this.fonts[font.name] = font;

});

// set current font to the first font !

this.currentFont = Object.keys(this.fonts)[0];

}

write(text, x, y, justify, colorID) {

if (this.currentFont === undefined) {

console.log("No bitmap_font");

return false;

}

if (typeof(justify) === "string") {

switch (justify) {

case "center":

x -= (text.length * this.fonts[this.currentFont].size.x) / 2;

break;

case "right":

x -= (text.length * this.fonts[this.currentFont].size.x);

break;

default:

}

this.writeLine(text, x, y, colorID || 0);

} else {

this.writeParagraph(text, x, y, justify, colorID || 0)

}

}

writeParagraph(text, x, y, justify, colorID) {

let y_offset = 0,

line_height = this.fonts[this.currentFont].size.y + 5,

size_x = this.fonts[this.currentFont].size.x,

words = text.split(' '),

line = "";

for (let i = 0; i < words.length; i++) {

line += words[i] + " ";

let nextword_width = 0,

next_word = words[i + 1],

line_length = line.length * size_x;

(next_word) ? nextword_width = next_word.length * size_x: 0;

if (line_length + nextword_width > justify) {

this.writeLine(line, x, y + y_offset, colorID);

y_offset += line_height;

line = "";

} else {

this.writeLine(line, x, y + y_offset, colorID);

}

}

}

writeLine(text, x, y, colorID) {

// write line

let size_x = this.fonts[this.currentFont].size.x,

size_y = this.fonts[this.currentFont].size.y,

font_img = this.fonts[this.currentFont].image;

for (let i = 0; i < text.length; i++) {

let index = this.alphabet.indexOf(text.charAt(i)),

clipX = size_x * index,

posX = x + (i * size_x);

this.ctx.drawImage(font_img, clipX, (colorID * size_y), size_x, size_y, posX, y, size_x, size_y);

}

}

// -----------------

// Events

// -----------------

eventSetup() {

document.addEventListener("keydown", event => this.keyDown(event), false);

document.addEventListener("keyup", event => this.keyUp(event), false);

}

keyDown(event) {

event.preventDefault();

this.keys[event.key.toLowerCase()] = true;

if (this.keys.KeyF) {

this.fullScreen();

}

if (this.keys.KeyM) {

this.mute();

}

this.current_scene.keyEvents(event);

}

keyUp(event) {

this.keys[event.key.toLowerCase()] = false;

}

// ---

// Scene Manager

// ---

startScene(scene_name) {

// check if the scene exist

if (this.scenes[scene_name] === undefined) return scene_name + " - doesn't exist";

// request the change of scene if this.main_loop is active

if (this.main_loop !== undefined) {

this.requestChange.value = true;

this.requestChange.action = scene_name;

return false;

}

this.requestChange.value = false;

this.requestChange.action = "";

this.FPS.last = Util.timeStamp();

this.current_scene = this.scenes[scene_name];

this.initScene();

// does this scenes needs a gameloop ?

if (this.current_scene.loop === true) {

this.gameLoop();

} else {

this.mainRender();

}

}

initScene() {

if (this.current_scene.init_once) return false;

this.current_scene.init();

}

addScene(scene) {

// links this world to this scene

scene.giveWorld(this);

this.scenes[scene.name] = scene;

}

// ---

// Main Loop

// ---

mainRender() {

this.clear();

this.current_scene.render();

}

loopCheck() {

if (this.requestChange.value === false) {

this.main_loop = requestAnimationFrame(() => this.gameLoop());

} else {

cancelAnimationFrame(this.main_loop);

this.main_loop = undefined;

this.startScene(this.requestChange.action);

}

}

gameLoop() {

this.FPS.now = Util.timeStamp();

this.FPS.delta += Math.min(1, (this.FPS.now - this.FPS.last) / 1000)

while (this.FPS.delta > this.FPS.step) {

this.FPS.delta -= this.FPS.step;

this.mainRender();

}

this.FPS.last = this.FPS.now;

this.loopCheck();

}

// Basic functions

soundLevel(volume) {

for (let [k, v] of Object.entries(this.assets.audio)) {

v.audio.volume = volume;

}

}

mute() {

this.audio_muted = !this.audio_muted;

for (let [k, v] of Object.entries(this.assets.audio)) {

v.audio.muted = this.audio_muted;

}

}

clear(custom_color) {

this.ctx.fillStyle = custom_color || this.background_color;

this.ctx.fillRect(0, 0, this.W, this.H);

}

setScale() {

this.canvas.style.maxWidth = this.W * this.scale + "px";

this.canvas.style.maxHeight = this.H * this.scale + "px";

this.canvas.style.width = "100%";

this.canvas.style.height = "100%";

}

fullScreen() {

this.full = !this.full;

if (!this.full) {

this.setScale();

} else {

// reset

this.canvas.style.maxWidth = "";

this.canvas.style.maxHeight = "";

this.canvas.style.width = "";

this.canvas.style.height = "";

// set full screen

this.canvas.style.width = "100%";

this.canvas.style.height = "100%";

}

}

// ---

// Tile map

// ---

getTile(layer_id, x, y) {

if (x < 0 || x > this.terrain.layers[layer_id].size.x - 1) return false;

if (y < 0 || y > this.terrain.layers[layer_id].size.y - 1) return false;

let tile = this.tiles_data[this.terrain.layers[layer_id].geometry[y][x]];

if (tile === undefined) return false;

return tile;

}

findTile(layer_id, tile_id) {

let layer = this.terrain.layers[layer_id];

let result = [];

for (let y = 0; y < layer.size.y; y++) {

for (let x = 0; x < layer.size.x; x++) {

let id = layer.geometry[y][x];

if (id === tile_id) {

result.push({

x: x,

y: y

});

}

}

}

return result;

}

initMap(map_name) {

this.terrain = JSON.parse(JSON.stringify(this.maps[map_name]));

// give size to layers

for (var i = 0; i < this.terrain.layers.length; i++) {

this.terrain.layers[i].size = {

x: this.terrain.layers[i].geometry[0].length,

y: this.terrain.layers[i].geometry.length,

}

}

this.terrain.tileset = this.assets.image[this.maps[map_name].tileset].image;

this.terrain.tileset_size = {

width: (this.terrain.tileset.width / this.tile_size),

height: (this.terrain.tileset.height / this.tile_size) + 1,

};

this.terrain.layers.forEach((layer, index) => {

this.marchingSquare(layer);

this.bitMasking(layer);

// create a cache for reducing draw call in the gameLoop

this.terrainCache(layer);

// prepare animated tiles

layer.animated = [];

for (var id in this.tiles_data) {

if (this.tiles_data[id].animated === true) {

let tiles = this.findTile(index, parseInt(id));

layer.animated.push({

id: id,

spritesheet: this.assets.image[this.tiles_data[id].spritesheet].image,

positions: tiles,

current: 0,

steps: this.tiles_data[id].steps,

max_frame: this.assets.image[this.tiles_data[id].spritesheet].image.width / this.tile_size,

});

}

}

});

this.clear("black");

}

terrainCache(layer) {

layer.cache = {};

let c = layer.cache.c = document.createElement("canvas");

let ctx = layer.cache.ctx = layer.cache.c.getContext('2d');

let W = c.width = layer.size.x * this.tile_size,

H = c.height = layer.size.y * this.tile_size;

// Draw on cache

this.ctx.clearRect(0, 0, W, H);

this.drawLayer(layer);

ctx.drawImage(this.canvas, 0, 0);

this.clear();

}

marchingSquare(layer) {

layer.square = [];

for (let y = 0; y < layer.size.y; y++) {

for (let x = 0; x < layer.size.x; x++) {

let p1 = 0,

p2 = 0,

p3 = 0,

p4 = 0;

if (y + 1 < layer.size.y && x + 1 < layer.size.x) {

p1 = layer.geometry[y][x];

p2 = layer.geometry[y][x + 1];

p3 = layer.geometry[y + 1][x + 1];

p4 = layer.geometry[y + 1][x];

}

let id = (p1 * 8) + (p2 * 4) + (p3 * 2) + p4;

layer.square.push(id);

}

}

layer.square = Util.array2D(layer.square, layer.size.x);

}

bitMasking(layer) {

layer.bitMask = [];

for (let y = 0; y < layer.size.y; y++) {

for (let x = 0; x < layer.size.x; x++) {

let id = layer.geometry[y][x];

let neighbor = [0, 0, 0, 0];

if (y - 1 > -1) {

if (id === layer.geometry[y - 1][x]) {

//top

neighbor[0] = 1;

}

} else {

neighbor[0] = 1;

}

if (x - 1 > -1) {

if (id === layer.geometry[y][x - 1]) {

// left

neighbor[1] = 1;

}

} else {

neighbor[1] = 1;

}

if (x + 1 < layer.size.x) {

if (id === layer.geometry[y][x + 1]) {

// right

neighbor[2] = 1;

}

} else {

neighbor[2] = 1;

}

if (y + 1 < layer.size.y) {

if (id === layer.geometry[y + 1][x]) {

//down

neighbor[3] = 1;

}

} else {

neighbor[3] = 1;

}

id = 1 * neighbor[0] + 2 * neighbor[1] + 4 * neighbor[2] + 8 * neighbor[3];

layer.bitMask.push(id);

}

}

layer.bitMask = Util.array2D(layer.bitMask, layer.size.x);

}

renderMap() {

this.terrain.layers.forEach(layer => {

this.ctx.drawImage(layer.cache.c, 0, 0);

// draw animated layer

layer.animated.forEach(tile => {

if (tile.current < tile.max_frame - 1) {

tile.current += tile.steps;

} else {

tile.current = 0;

}

// render animated tiles

tile.positions.forEach(position => {

let x = position.x * this.tile_size,

y = position.y * this.tile_size;

this.ctx.drawImage(tile.spritesheet,

Math.floor(tile.current) * this.tile_size,

0,

this.tile_size,

this.tile_size,

x,

y,

this.tile_size,

this.tile_size

)

});

});

});

}

drawMap() {

this.terrain.layers.forEach(layer => {

this.drawLayer(layer);

});

}

drawLayer(layer) {

for (let y = 0; y < layer.size.y; y++) {

for (let x = 0; x < layer.size.x; x++) {

// ID of the tile

let id = layer.geometry[y][x];

// Don't draw invisible tiles

// Position of the tile :)

let positionX = (x * this.tile_size) + layer.offset.x,

positionY = (y * this.tile_size) + layer.offset.y;

let sourceX = Math.floor(id % this.terrain.tileset_size.width) * this.tile_size,

sourceY = Math.floor(id / this.terrain.tileset_size.width) * this.tile_size;

if (this.tiles_data[id] && this.tiles_data[id].visibility === false) {

continue;

}

if (this.tiles_data[id] && this.tiles_data[id].look === "bitmask") {

sourceX = Math.floor(layer.bitMask[y][x]) * this.tile_size;

sourceY = this.tiles_data[id].line * this.tile_size;

}

if (layer.look === "square") {

if (layer.square[y][x] === 0) continue;

positionX += this.tile_size / 2;

positionY += this.tile_size / 2;

sourceX = Math.floor(layer.square[y][x] % 16) * 16;

sourceY = (7 * this.tile_size);

}

if (this.tiles_data[id] && this.tiles_data[id].animated === true) {

// hide animated sprites on the cache

continue;

}

// render tile

this.ctx.drawImage(this.terrain.tileset, sourceX, sourceY, this.tile_size, this.tile_size, positionX, positionY, this.tile_size, this.tile_size);

}

}

}

}

let parameters = {

name: "Title",

start_screen: "inGame",

background_color: "white",

width: 192,

height: 128,

scale: 3,

assets: [

// Images

{

type: "img",

name: "coderscrux_font",

path: "https://image.ibb.co/jOtcse/coderscrux_font.png"

}, {

type: "img",

name: "nano_font",

path: "https://image.ibb.co/fXA1JK/nano_font.png"

}, {

type: "img",

name: "box_texture",

path: "https://image.ibb.co/hhgK5z/box.png"

}, {

type: "img",

name: "bonhomme_1",

path: "https://image.ibb.co/mWyoyK/bonhomme_1.png"

}, {

type: "img",

name: "bonhomme_2",

path: "https://image.ibb.co/m9aCQz/bonhomme_2.png"

}, {

type: "img",

name: "bonhomme_3",

path: "https://image.ibb.co/dCpiXe/bonhomme_3.png"

}, {

type: "img",

name: "background",

path: "https://image.ibb.co/nGUHse/background.png"

}, {

type: "img",

name: "button_key",

path: "https://image.ibb.co/iVU6kz/button_key.png"

}, {

type: "img",

name: "main_title",

path: "https://image.ibb.co/epYcse/main_title.png"

}, {

type: "img",

name: "shadow",

path: "https://image.ibb.co/kxqe5z/shadow.png"

}, {

type: "img",

name: "rabbit",

path: "https://image.ibb.co/ij7gJK/rabbit.png"

}, {

type: "img",

name: "cloud_1",

path: "https://image.ibb.co/nbRVCe/cloud_1.png"

}, {

type: "img",

name: "cloud_2",

path: "https://image.ibb.co/nGocse/cloud_2.png"

}

// Bitmap font

],

fonts: [

// basic font

{

name: "coder",

image: "coderscrux_font",

size: {

x: 6,

y: 9

}

}, {

name: "nano",

image: "nano_font",

size: {

x: 4,

y: 6

}

}

],

// box system

boxes: [{

name: "box",

resolution: 8,

image: "box_texture"

}],

maps: []

};

// inGame scene

function randomUnique(length, size) {

if (length < size) return false;

let result = [];

while (result.length < size) {

let ID = Math.floor(Util.random(0, length));

let test = result.every(value => {

return value !== ID;

});

if (test) {

result.push(ID);

}

}

return result;

}

let sprites = [{

image: "bonhomme_1",

size: {

x: 16,

y: 20

},

run: [0, 1, 2, 3, 4, 5, 6, 7]

}, {

image: "bonhomme_2",

size: {

x: 16,

y: 20

},

run: [0, 1, 2, 3, 4, 5, 6, 7]

}, {

image: "bonhomme_3",

size: {

x: 16,

y: 20

},

run: [0, 1, 2, 3, 4, 5, 6, 7]

}];

let inGame = new Scene("inGame");

inGame.init = function() {

this.ctx = this.world.ctx;

this.players = [];

// add players in the scene :)

let IDS = randomUnique(sprites.length, 2);

let keySet_1 = {

set: ["a", "z", "q", "s", "e", "d", "r", "f"],

x: this.world.W / 4

};

let keySet_2 = {

set: ["p", "o", "m", "l", "i", "u", "k", "j"],

x: this.world.W / 2 + this.world.W / 4

};

let P_1 = new Runner(this, 28, 64, IDS[0], keySet_1),

P_2 = new Runner(this, 20, 72, IDS[1], keySet_2);

this.players.push(P_1, P_2);

// GLOBAL VARIABLES

this.title_phase = 0;

this.title_out = false;

this.title_pos = {

start: 10,

actual: 10,

target: -50

};

//

this.count_down_text = ["Ready...", "steady...", "go !"];

this.count_down_current = 0;

// states !

this.STATE = "menu";

this.winner = 0;

//

this.trans = [];

// transition effects

this.transition = {

scene: this,

active: true,

// between 0 and 100

state: 0,

value: 0,

duration: 500,

start: 0,

// between whatever and whatever

from: 0,

to: Math.max(this.world.W, this.world.H),

//

start: function(from, to, callback) {

this.active = true;

this.from = from;

this.start_time = new Date();

this.to = to;

this.callback = callback;

},

update: function() {

let time = new Date() - this.start_time;

if (time < this.duration) {

this.value = Util.easeInOutQuad(

time,

this.from,

this.to - this.from,

this.duration

);

} else {

this.active = false;

if (this.callback !== undefined) {

this.callback();

}

}

},

render: function() {

this.scene.ctx.fillStyle = "black";

this.scene.ctx.fillRect(0, 0, this.scene.world.W, this.value);

this.scene.ctx.fillRect(

0,

this.scene.world.H,

this.scene.world.W, -this.value

);

this.scene.ctx.fillRect(0, 0, this.value, this.scene.world.H);

this.scene.ctx.fillRect(

this.scene.world.W,

0, -this.value,

this.scene.world.H

);

}

};

this.transition.start(Math.max(this.world.W / 2, this.world.H / 2), 0);

// roger the rabbit :)

this.roger = new Rabbit(this, this.world.W - 40, this.world.H - 20);

this.clouds = [];

this.clouds.push(new Cloud(this, 0, 0));

this.clouds.push(new Cloud(this, 0, 0));

this.clouds.push(new Cloud(this, 0, 0));

this.clouds.push(new Cloud(this, 0, 0));

};

inGame.render = function() {

// draw background

this.renderScenery();

// render clouds

this.renderClouds();

// players

this.renderPlayer();

// render roger

this.roger.render();

// ui

this.title_screen();

this.countDown();

this.renderWin();

// trans

for (let i = this.trans.length; i--;) {

this.trans[i].update();

}

if (this.transition.active) {

this.transition.update();

this.transition.render();

}

};

inGame.renderClouds = function() {

this.clouds.forEach(cloud => {

cloud.render();

});

};

inGame.renderPlayer = function() {

this.players.forEach(player => {

// update player

if (this.STATE === "running") {

player.checkKeys();

player.update();

player.checkWin();

}

// draw keys

if (this.STATE === "running") {

player.drawKeys();

}

// draw player

player.draw();

});

};

inGame.title_screen = function() {

// title state

if (this.STATE !== "menu") return false;

this.title_phase += 0.04;

let y = Math.sin(this.title_phase) * 4;

let title_image = this.world.assets.image.main_title.image;

this.world.ctx.drawImage(

title_image,

this.world.W / 2 - title_image.width / 2,

y + this.title_pos.actual

);

this.world.setFont("nano");

this.world.write(

"Press space when ready !",

this.world.W / 2,

this.world.H - 23,

"center"

);

if (this.world.keys[" "] && !this.title_out) {

this.title_out = true;

let callback = () => {

this.STATE = "count_down";

setTimeout(() => {

this.count_down_current = 1;

setTimeout(() => {

this.count_down_current = 2;

setTimeout(() => {

this.STATE = "running";

}, 1000);

}, 1000);

}, 1000);

};

let t = new transition(this, callback);

t.update = function() {

let time = new Date() - this.start;

let duration = 1000;

if (time < duration) {

this.scene.title_pos.actual = Util.easeInOutExpo(

time,

this.scene.title_pos.start,

this.scene.title_pos.target - this.scene.title_pos.start,

duration

);

} else {

this.end();

}

};

this.trans.push(t);

}

};

inGame.countDown = function() {

if (this.STATE !== "count_down") return false;

this.world.setFont("nano");

this.world.write(

this.count_down_text[this.count_down_current].toString(),

this.world.W / 2,

this.world.H - 20,

"center"

);

};

inGame.renderWin = function() {

if (this.STATE !== "win") return false;

this.world.setFont("nano");

this.world.write(

"player " + (this.winner + 1).toString() + " won the race !",

this.world.W / 2,

20,

"center"

);

this.world.write(

"Space to restart !",

this.world.W / 2,

this.world.H - 20,

"center"

);

if (this.world.keys[" "] && !this.transition.active) {

this.restart();

}

};

inGame.restart = function() {

this.transition.start(0, Math.max(this.world.W / 2, this.world.H / 2), () => {

this.world.startScene("inGame");

});

};

inGame.renderScenery = function() {

this.ctx.drawImage(game.assets.image.background.image, 0, 0);

};

// init sprites

class Runner extends Entity {

constructor(scene, x, y, sprite_id, keySet) {

super(scene, x, y);

this.setSprite(sprites[sprite_id]);

this.sprite.addAnimation("run", sprites[sprite_id].run);

this.keySet = keySet;

this.next_key;

this.last_key;

this.getNextKey();

this.keyPressed = false;

this.start = x;

}

getNextKey() {

this.next_key = this.keySet.set[

Math.floor(Util.random(0, this.keySet.set.length))

];

}

checkKeys() {

if (this.world.keys[this.next_key] && !this.keyPressed) {

this.last_key = this.next_key;

this.keyPressed = true;

let force = new Vector(10, 0);

this.body.applyForce(force);

}

if (this.keyPressed && !this.world.keys[this.last_key]) {

this.getNextKey();

this.keyPressed = false;

}

}

drawKeys() {

// draw key

this.world.setFont("coder");

let key_image = this.world.assets.image.button_key.image;

this.world.ctx.drawImage(

key_image,

this.keyPressed * 19,

0,

19,

20,

this.keySet.x - 7,

16,

19,

20

);

this.world.write(

this.next_key.toUpperCase().toString(),

this.keySet.x,

20 + this.keyPressed * 3

);

}

checkWin() {

if (this.body.position.x - this.start > 130) {

this.scene.STATE = "win";

this.scene.winner = this.scene.players.indexOf(this);

}

}

draw() {

let shadow = this.world.assets.image.shadow.image;

this.world.ctx.drawImage(

shadow,

this.body.position.x + 3,

this.body.position.y + 18

);

this.sprite.animate("run");

this.display();

}

update() {

this.sprite.speed = Util.map(

this.body.stepped_velocity.mag(),

0,

0.2,

0,

0.1

);

this.body.integration();

}

}

class transition {

constructor(scene, callback) {

this.scene = scene;

this.world = scene.world;

this.callback = callback;

this.start = new Date();

}

update() {}

end() {

this.callback();

this.scene.trans.splice(this.scene.trans.indexOf(this), 1);

}

}

class Rabbit extends Entity {

constructor(scene, x, y) {

super(scene, x, y);

let sprite = {

image: "rabbit",

size: {

x: 20,

y: 20

}

};

this.setSprite(sprite);

this.sprite.speed = 0.3;

this.sprite.addAnimation("run_left", [0, 1, 2, 3, 4, 5]);

this.sprite.addAnimation("run_right", [6, 7, 8, 9, 10, 11]);

this.body.position = new Vector(

Util.random(20, this.world.W - 20),

Util.random(this.world.H / 1.5, this.world.H - 20)

);

this.init_trans();

}

init_trans() {

this.start = new Date();

this.from = this.body.position.copy();

this.target = new Vector(

Util.random(20, this.world.W - 20),

Util.random(this.world.H / 1.5, this.world.H - 20)

);

this.duration = this.target.dist(this.body.position) / 0.04;

this.inTransition = true;

}

update() {

if (!this.inTransition) return false;

let time = new Date() - this.start;

if (time < this.duration) {

if (this.target.x > this.from.x) {

this.sprite.animate("run_right");

} else {

this.sprite.animate("run_left");

}

this.body.position.x = Util.linearTween(

time,

this.from.x,

this.target.x - this.from.x,

this.duration

);

this.body.position.y = Util.linearTween(

time,

this.from.y,

this.target.y - this.from.y,

this.duration

);

} else {

this.inTransition = false;

this.sprite.current_frame = 2;

setTimeout(() => {

this.init_trans();

}, Util.random(500, 10000));

}

}

draw() {

this.display();

}

render() {

this.update();

this.draw();

}

}

class Cloud extends Entity {

constructor(scene, x, y) {

super(scene, x, y);

this.init_trans();

this.body.position = new Vector(

Util.random(0, this.world.W + 200),

Util.random(-10, 36)

);

this.from = this.body.position.copy();

this.target = this.body.position.copy();

this.target.x = -this.sprite.width * 2;

}

init_trans() {

this.body.position = new Vector(this.world.W, Util.random(-10, 36));

let id = Math.floor(Util.random(0, 2)) + 1;

this.sprite = this.world.assets.image["cloud_" + id].image;

this.start = new Date();

this.from = this.body.position.copy();

this.target = this.body.position.copy();

this.target.x = -this.sprite.width * 2;

this.duration =

this.target.dist(this.body.position) / Util.random(0.01, 0.02);

this.inTransition = true;

}

update() {

if (!this.inTransition) return false;

let time = new Date() - this.start;

if (time < this.duration) {

this.body.position.x = Util.linearTween(

time,

this.from.x,

this.target.x - this.from.x,

this.duration

);

this.body.position.y = Util.linearTween(

time,

this.from.y,

this.target.y - this.from.y,

this.duration

);

} else {

this.inTransition = false;

setTimeout(() => {

this.init_trans();

}, Util.random(2, 10000));

}

}

draw() {

this.world.ctx.drawImage(

this.sprite,

this.body.position.x,

this.body.position.y

);

}

render() {

this.update();

this.draw();

}

}

let game = new Diorama(parameters);

// Add the different scenes here

// the addScene function link the scene with the world (game)

game.addScene(inGame);

game.ready();

// everything start being loaded now !

// the ready function must be called last !

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值