Files
memory-manager-concurrent/games/mario/super-mario-bros/tiles.js
2026-01-21 18:11:33 +08:00

364 lines
13 KiB
JavaScript

(function() {
/**
*
* Backbone Game Engine - An elementary HTML5 canvas game engine using Backbone.
*
* Copyright (c) 2014 Martin Drapeau
* https://github.com/martindrapeau/backbone-game-engine
*
*/
Backbone.Tile = Backbone.Sprite.extend({
defaults: {
type: "tile",
width: 32,
height: 32,
spriteSheet: "tiles",
state: "idle",
static: true,
persist: true
},
initialize: function(attributes, options) {
options || (options = {});
this.world = options.world;
this.lastSequenceChangeTime = 0;
}
});
function extendSprite(cls, name, attributes, animations) {
var newCls = _.classify(name);
Backbone[newCls] = Backbone[cls].extend({
defaults: _.extend(
_.deepClone(Backbone[cls].prototype.defaults),
{name: name},
attributes || {}
),
animations: _.extend(
_.deepClone(Backbone[cls].prototype.animations),
animations || {}
)
});
return Backbone[newCls];
}
extendSprite("Tile", "ground", {collision: true}, {idle: {sequences: [0]}});
extendSprite("Tile", "ground2", {collision: true}, {idle: {sequences: [31]}});
extendSprite("Tile", "block", {collision: true}, {idle: {sequences: [3]}});
extendSprite("Tile", "block2", {collision: true}, {idle: {sequences: [29]}});
extendSprite("Tile", "tube1", {collision: true}, {idle: {sequences: [290]}});
extendSprite("Tile", "tube2", {collision: true}, {idle: {sequences: [291]}});
extendSprite("Tile", "tube1-mirror", {collision: true}, {idle: {sequences: [261]}});
extendSprite("Tile", "tube2-mirror", {collision: true}, {idle: {sequences: [262]}});
extendSprite("Tile", "tube1-ug", {collision: true}, {idle: {sequences: [406]}});
extendSprite("Tile", "tube2-ug", {collision: true}, {idle: {sequences: [407]}});
extendSprite("Tile", "bush1", {collision: false}, {idle: {sequences: [240]}});
extendSprite("Tile", "bush2", {collision: false}, {idle: {sequences: [241]}});
extendSprite("Tile", "bush3", {collision: false}, {idle: {sequences: [242]}});
extendSprite("Tile", "cloud1", {collision: false}, {idle: {sequences: [580]}});
extendSprite("Tile", "cloud2", {collision: false}, {idle: {sequences: [581]}});
extendSprite("Tile", "cloud3", {collision: false}, {idle: {sequences: [582]}});
extendSprite("Tile", "cloud-happy1", {collision: false}, {idle: {sequences: [585]}});
extendSprite("Tile", "cloud-happy2", {collision: false}, {idle: {sequences: [586]}});
extendSprite("Tile", "cloud-happy3", {collision: false}, {idle: {sequences: [587]}});
extendSprite("Tile", "flag-pole1", {collision: false}, {idle: {sequences: [306]}});
extendSprite("Tile", "cloud-small", {collision: true}, {idle: {sequences: [613]}});
extendSprite("Tile", "ground-ug", {collision: true}, {idle: {sequences: [116]}});
extendSprite("Tile", "ground2-ug", {collision: true}, {idle: {sequences: [147]}});
extendSprite("Tile", "block-ug", {collision: true}, {idle: {sequences: [119]}});
extendSprite("Tile", "block2-ug", {collision: true}, {idle: {sequences: [145]}});
extendSprite("Tile", "tube3", {collision: true}, {idle: {sequences: [319]}});
extendSprite("Tile", "tube4", {collision: true}, {idle: {sequences: [320]}});
extendSprite("Tile", "tube3-mirror", {collision: true}, {idle: {sequences: [232]}});
extendSprite("Tile", "tube4-mirror", {collision: true}, {idle: {sequences: [233]}});
extendSprite("Tile", "tube3-ug", {collision: true}, {idle: {sequences: [435]}});
extendSprite("Tile", "tube4-ug", {collision: true}, {idle: {sequences: [436]}});
extendSprite("Tile", "bush4", {collision: false}, {idle: {sequences: [269]}});
extendSprite("Tile", "bush5", {collision: false}, {idle: {sequences: [270]}});
extendSprite("Tile", "bush6", {collision: false}, {idle: {sequences: [271]}});
extendSprite("Tile", "cloud4", {collision: false}, {idle: {sequences: [609]}});
extendSprite("Tile", "cloud5", {collision: false}, {idle: {sequences: [610]}});
extendSprite("Tile", "cloud6", {collision: false}, {idle: {sequences: [611]}});
extendSprite("Tile", "cloud-happy4", {collision: false}, {idle: {sequences: [614]}});
extendSprite("Tile", "cloud-happy5", {collision: false}, {idle: {sequences: [615]}});
extendSprite("Tile", "cloud-happy6", {collision: false}, {idle: {sequences: [616]}});
extendSprite("Tile", "flag-pole2", {collision: false}, {idle: {sequences: [335]}});
extendSprite("Tile", "tube1-out", {collision: true}, {idle: {sequences: [292]}});
extendSprite("Tile", "tube2-out", {collision: true}, {idle: {sequences: [293]}});
extendSprite("Tile", "tube3-out", {collision: true}, {idle: {sequences: [294]}});
extendSprite("Tile", "tube1-out-mirror", {collision: true}, {idle: {sequences: [234]}});
extendSprite("Tile", "tube2-out-mirror", {collision: true}, {idle: {sequences: [235]}});
extendSprite("Tile", "tube3-out-mirror", {collision: true}, {idle: {sequences: [236]}});
extendSprite("Tile", "tube1-out-ug", {collision: true}, {idle: {sequences: [408]}});
extendSprite("Tile", "tube2-out-ug", {collision: true}, {idle: {sequences: [409]}});
extendSprite("Tile", "tube3-out-ug", {collision: true}, {idle: {sequences: [410]}});
extendSprite("Tile", "brick7-castle", {collision: true}, {idle: {sequences: [42]}});
extendSprite("Tile", "bush7", {collision: false}, {idle: {sequences: [272]}});
extendSprite("Tile", "bush8", {collision: false}, {idle: {sequences: [273]}});
extendSprite("Tile", "bush9", {collision: false}, {idle: {sequences: [274]}});
extendSprite("Tile", "water1", {collision: false}, {idle: {sequences: [583]}});
extendSprite("Tile", "water2", {collision: false}, {idle: {sequences: [612]}});
extendSprite("Tile", "water-bridge", {collision: true}, {idle: {sequences: [32]}});
extendSprite("Tile", "lava1", {collision: false}, {idle: {sequences: [699]}});
extendSprite("Tile", "lava2", {collision: false}, {idle: {sequences: [728]}});
extendSprite("Tile", "lava-bridge", {collision: true}, {idle: {sequences: [148]}});
extendSprite("Tile", "tube4-out", {collision: true}, {idle: {sequences: [321]}});
extendSprite("Tile", "tube5-out", {collision: true}, {idle: {sequences: [322]}});
extendSprite("Tile", "tube6-out", {collision: true}, {idle: {sequences: [323]}});
extendSprite("Tile", "tube4-out-mirror", {collision: true}, {idle: {sequences: [263]}});
extendSprite("Tile", "tube5-out-mirror", {collision: true}, {idle: {sequences: [264]}});
extendSprite("Tile", "tube6-out-mirror", {collision: true}, {idle: {sequences: [265]}});
extendSprite("Tile", "tube4-out-ug", {collision: true}, {idle: {sequences: [437]}});
extendSprite("Tile", "tube5-out-ug", {collision: true}, {idle: {sequences: [438]}});
extendSprite("Tile", "tube6-out-ug", {collision: true}, {idle: {sequences: [439]}});
extendSprite("Tile", "brick-castle", {collision: true}, {idle: {sequences: [11]}});
extendSprite("Tile", "brick2-castle", {collision: true}, {idle: {sequences: [12]}});
extendSprite("Tile", "brick3-castle", {collision: true}, {idle: {sequences: [13]}});
extendSprite("Tile", "brick4-castle", {collision: true}, {idle: {sequences: [14]}});
extendSprite("Tile", "brick5-castle", {collision: true}, {idle: {sequences: [40]}});
extendSprite("Tile", "brick6-castle", {collision: true}, {idle: {sequences: [41]}});
extendSprite("Tile", "railing", {collision: false}, {idle: {sequences: [363]}});
extendSprite("Tile", "platform1", {collision: true}, {idle: {sequences: [237]}});
extendSprite("Tile", "platform2", {collision: true}, {idle: {sequences: [238]}});
extendSprite("Tile", "platform3", {collision: true}, {idle: {sequences: [239]}});
extendSprite("Tile", "platform-pole", {collision: false}, {idle: {sequences: [208]}});
// Subclass Sprite to use a global timer - so all animated
// sprites animate in sync.
Backbone.AnimatedTile = Backbone.Tile.extend({
initialize: function(attributes, options) {
Backbone.Tile.prototype.initialize.apply(this, arguments);
this.on("attach", this.onAttach, this);
this.on("detach", this.onDetach, this);
},
onAttach: function() {
if (!this.engine) return;
this.onDetach();
this.clock = this.engine.sprites.findWhere({name: "animatedTileClock"});
if (!this.clock)
this.clock = this.engine.add(new Backbone.Clock({name: "animatedTileClock", delay: 200}));
this.listenTo(this.clock, "change:ticks", this.updateAnimationIndex);
},
onDetach: function() {
if (this.clock) this.stopListening(this.clock);
this.clock = undefined;
},
update: function(dt) {
return true;
},
updateAnimationIndex: function() {
var animation = this.getAnimation(),
sequenceIndex = this.get("sequenceIndex") || 0;
if (!animation) return;
this.set("sequenceIndex", sequenceIndex < animation.sequences.length-1 ? sequenceIndex + 1 : 0);
}
});
Backbone.Brick = Backbone.AnimatedTile.extend({
defaults: _.extend({}, Backbone.Tile.prototype.defaults, {
name: "brick",
state: "idle",
collision: true,
static: false
}),
animations: {
idle: {
sequences: [2]
},
bounce: {
sequences: [
{frame: 2, x: 0, y: -8},
{frame: 2, x: 0, y: -8},
{frame: 2, x: 0, y: -4},
{frame: 2, x: 0, y: 0}
],
delay: 50
}
},
initialize: function(attributes, options) {
Backbone.AnimatedTile.prototype.initialize.apply(this, arguments);
this.on("hit", this.hit, this);
},
hit: function(sprite, dir, dir2) {
if (sprite.get("hero") && dir == "bottom") {
var tile = this;
this.set({state: "bounce", sequenceIndex: 0});
this.world.setTimeout(function() {
tile.set({state: "idle"});
}, 200);
} else if (dir == "top") {
sprite.trigger("hit", this, "bottom");
}
return this;
}
});
var NewTile = extendSprite("Brick", "brick-top");
animations = NewTile.prototype.animations;
animations.idle.sequences = [1];
_.each(animations.bounce.sequences, function(sequence) {sequence.frame = 1;});
NewTile = extendSprite("Brick", "brick-ug");
animations = NewTile.prototype.animations;
animations.idle.sequences = [118];
_.each(animations.bounce.sequences, function(sequence) {sequence.frame = 118;});
NewTile = extendSprite("Brick", "brick-top-ug");
animations = NewTile.prototype.animations;
animations.idle.sequences = [117];
_.each(animations.bounce.sequences, function(sequence) {sequence.frame = 117;});
Backbone.QuestionBlock = Backbone.AnimatedTile.extend({
defaults: _.extend({}, Backbone.Tile.prototype.defaults, {
name: "question-block",
state: "idle",
collision: true,
static: false
}),
animations: {
idle: {
sequences: [23, 23, 24, 25, 24, 23],
delay: 150
},
bounce: {
sequences: [
{frame: 3, x: 0, y: -8},
{frame: 3, x: 0, y: -8},
{frame: 3, x: 0, y: -4},
{frame: 3, x: 0, y: 0}
],
delay: 50
},
empty: {
sequences: [3]
}
},
initialize: function(attributes, options) {
Backbone.AnimatedTile.prototype.initialize.apply(this, arguments);
this.on("hit", this.hit, this);
},
hit: function(sprite, dir, dir2) {
if (!sprite || !sprite.get("hero") || dir != "bottom") return;
if (this.get("state") != "idle") return;
var tile = this;
this.set({state: "bounce", sequenceIndex: 0});
if (this.world)
this.world.add(new Backbone.FlyingPennie({
x: this.get("x"),
y: this.get("y")
}));
setTimeout(function() {
tile.set({state: "empty"});
}, 200);
}
});
NewTile = extendSprite("QuestionBlock", "question-block-ug");
animations = NewTile.prototype.animations;
animations.idle.sequences = [139, 139, 140, 141, 140, 139];
_.each(animations.bounce.sequences, function(sequence) {sequence.frame = 119;});
animations.empty.sequences = [119];
NewTile = extendSprite("QuestionBlock", "invisible-question-block");
animations = NewTile.prototype.animations;
animations.idle.sequences = [];
_.each(animations.bounce.sequences, function(sequence) {sequence.frame = 3;});
animations.empty.sequences = [3];
NewTile = extendSprite("QuestionBlock", "invisible-question-block-ug");
animations = NewTile.prototype.animations;
animations.idle.sequences = [];
_.each(animations.bounce.sequences, function(sequence) {sequence.frame = 119;});
animations.empty.sequences = [119];
}).call(this);