Skip to content

Instantly share code, notes, and snippets.

@darrentorpey
Created January 20, 2014 01:34
Show Gist options
  • Save darrentorpey/8513544 to your computer and use it in GitHub Desktop.
Save darrentorpey/8513544 to your computer and use it in GitHub Desktop.
Updated code to adapt the original code from my Crafty tutorial (http://buildnewgames.com/introduction-to-crafty/) to work with Crafty 0.6.1
// The Grid component allows an element to be located
// on a grid of tiles
Crafty.c('Grid', {
init: function() {
this.attr({
w: Game.map_grid.tile.width,
h: Game.map_grid.tile.height
});
},
// Locate this entity at the given position on the grid
at: function(x, y) {
if (x === undefined && y === undefined) {
return { x: this.x/Game.map_grid.tile.width, y: this.y/Game.map_grid.tile.height };
} else {
this.attr({ x: x * Game.map_grid.tile.width, y: y * Game.map_grid.tile.height });
return this;
}
}
});
// An "Actor" is an entity that is drawn in 2D on canvas
// via our logical coordinate grid
Crafty.c('Actor', {
init: function() {
this.requires('2D, Canvas, Grid');
},
});
// A Tree is just an Actor with a certain sprite
Crafty.c('Tree', {
init: function() {
this.requires('Actor, Solid, spr_tree');
},
});
// A Bush is just an Actor with a certain sprite
Crafty.c('Bush', {
init: function() {
this.requires('Actor, Solid, spr_bush');
},
});
// A Rock is just an Actor with a certain sprite
Crafty.c('Rock', {
init: function() {
this.requires('Actor, Solid, spr_rock');
},
});
// This is the player-controlled character
Crafty.c('PlayerCharacter', {
init: function() {
this.requires('Actor, Fourway, Collision, spr_player, SpriteAnimation')
.fourway(2)
.stopOnSolids()
.onHit('Village', this.visitVillage)
// These next lines define our four animations
// each call to .animate specifies:
// - the name of the animation
// - the x and y coordinates within the sprite
// map at which the animation set begins
// - the number of animation frames *in addition to* the first one
.reel('PlayerMovingUp', 600, 0, 0, 3)
.reel('PlayerMovingRight', 600, 0, 1, 3)
.reel('PlayerMovingDown', 600, 0, 2, 3)
.reel('PlayerMovingLeft', 600, 0, 3, 3);
// Watch for a change of direction and switch animations accordingly
var animation_speed = 4;
this.bind('NewDirection', function(data) {
if (data.x > 0) {
this.animate('PlayerMovingRight', -1);
} else if (data.x < 0) {
this.animate('PlayerMovingLeft', -1);
} else if (data.y > 0) {
this.animate('PlayerMovingDown', -1);
} else if (data.y < 0) {
this.animate('PlayerMovingUp', -1);
} else {
this.pauseAnimation();
}
});
},
// Registers a stop-movement function to be called when
// this entity hits an entity with the "Solid" component
stopOnSolids: function() {
this.onHit('Solid', this.stopMovement);
return this;
},
// Stops the movement
stopMovement: function() {
this._speed = 0;
if (this._movement) {
this.x -= this._movement.x;
this.y -= this._movement.y;
}
},
// Respond to this player visiting a village
visitVillage: function(data) {
villlage = data[0].obj;
villlage.visit();
}
});
// A village is a tile on the grid that the PC must visit in order to win the game
Crafty.c('Village', {
init: function() {
this.requires('Actor, spr_village');
},
// Process a visitation with this village
visit: function() {
this.destroy();
Crafty.audio.play('knock');
Crafty.trigger('VillageVisited', this);
}
});
Game = {
// This defines our grid's size and the size of each of its tiles
map_grid: {
width: 24,
height: 16,
tile: {
width: 16,
height: 16
}
},
// The total width of the game screen. Since our grid takes up the entire screen
// this is just the width of a tile times the width of the grid
width: function() {
return this.map_grid.width * this.map_grid.tile.width;
},
// The total height of the game screen. Since our grid takes up the entire screen
// this is just the height of a tile times the height of the grid
height: function() {
return this.map_grid.height * this.map_grid.tile.height;
},
// Initialize and start our game
start: function() {
// Start crafty and set a background color so that we can see it's working
Crafty.init(Game.width(), Game.height());
Crafty.background('rgb(87, 109, 20)');
// Simply start the "Loading" scene to get things going
Crafty.scene('Loading');
}
};
$text_css = { 'size': '24px', 'family': 'Arial', 'color': 'red', 'text-align': 'center' };
// Game scene
// -------------
// Runs the core gameplay loop
Crafty.scene('Game', function() {
// A 2D array to keep track of all occupied tiles
this.occupied = new Array(Game.map_grid.width);
for (var i = 0; i < Game.map_grid.width; i++) {
this.occupied[i] = new Array(Game.map_grid.height);
for (var y = 0; y < Game.map_grid.height; y++) {
this.occupied[i][y] = false;
}
}
// Player character, placed at 5, 5 on our grid
this.player = Crafty.e('PlayerCharacter').at(5, 5);
this.occupied[this.player.at().x][this.player.at().y] = true;
// Place a tree at every edge square on our grid of 16x16 tiles
for (var x = 0; x < Game.map_grid.width; x++) {
for (var y = 0; y < Game.map_grid.height; y++) {
var at_edge = x == 0 || x == Game.map_grid.width - 1 || y == 0 || y == Game.map_grid.height - 1;
if (at_edge) {
// Place a tree entity at the current tile
Crafty.e('Tree').at(x, y)
this.occupied[x][y] = true;
} else if (Math.random() < 0.06 && !this.occupied[x][y]) {
// Place a bush entity at the current tile
var bush_or_rock = (Math.random() > 0.3) ? 'Bush' : 'Rock'
Crafty.e(bush_or_rock).at(x, y)
this.occupied[x][y] = true;
}
}
}
// Generate five villages on the map in random locations
var max_villages = 5;
for (var x = 0; x < Game.map_grid.width; x++) {
for (var y = 0; y < Game.map_grid.height; y++) {
if (Math.random() < 0.03) {
if (Crafty('Village').length < max_villages && !this.occupied[x][y]) {
Crafty.e('Village').at(x, y);
}
}
}
}
// Play a ringing sound to indicate the start of the journey
Crafty.audio.play('ring');
// Show the victory screen once all villages are visisted
this.show_victory = this.bind('VillageVisited', function() {
if (!Crafty('Village').length) {
Crafty.scene('Victory');
}
});
}, function() {
// Remove our event binding from above so that we don't
// end up having multiple redundant event watchers after
// multiple restarts of the game
this.unbind('VillageVisited', this.show_victory);
});
// Victory scene
// -------------
// Tells the player when they've won and lets them start a new game
Crafty.scene('Victory', function() {
// Display some text in celebration of the victory
Crafty.e('2D, DOM, Text')
.text('All villages visited!')
.attr({ x: 0, y: Game.height()/2 - 24, w: Game.width() })
.textFont($text_css);
// Give'em a round of applause!
Crafty.audio.play('applause');
// After a short delay, watch for the player to press a key, then restart
// the game when a key is pressed
var delay = true;
setTimeout(function() { delay = false; }, 5000);
this.restart_game = function() {
if (!delay) {
Crafty.scene('Game');
}
};
Crafty.bind('KeyDown', this.restart_game);
}, function() {
// Remove our event binding from above so that we don't
// end up having multiple redundant event watchers after
// multiple restarts of the game
this.unbind('KeyDown', this.restart_game);
});
// Loading scene
// -------------
// Handles the loading of binary assets such as images and audio files
Crafty.scene('Loading', function(){
// Draw some text for the player to see in case the file
// takes a noticeable amount of time to load
Crafty.e('2D, DOM, Text')
.text('Loading; please wait...')
.attr({ x: 0, y: Game.height()/2 - 24, w: Game.width() })
.textFont($text_css);
// Load our sprite map image
Crafty.load([
'assets/16x16_forest_2.gif',
'assets/hunter.png',
'assets/door_knock_3x.mp3',
'assets/door_knock_3x.ogg',
'assets/door_knock_3x.aac',
'assets/board_room_applause.mp3',
'assets/board_room_applause.ogg',
'assets/board_room_applause.aac',
'assets/candy_dish_lid.mp3',
'assets/candy_dish_lid.ogg',
'assets/candy_dish_lid.aac'
], function(){
// Once the images are loaded...
// Define the individual sprites in the image
// Each one (spr_tree, etc.) becomes a component
// These components' names are prefixed with "spr_"
// to remind us that they simply cause the entity
// to be drawn with a certain sprite
Crafty.sprite(16, 'assets/16x16_forest_2.gif', {
spr_tree: [0, 0],
spr_bush: [1, 0],
spr_village: [0, 1],
spr_rock: [1, 1]
});
// Define the PC's sprite to be the first sprite in the third row of the
// animation sprite map
Crafty.sprite(16, 'assets/hunter.png', {
spr_player: [0, 2],
}, 0, 2);
// Define our sounds for later use
Crafty.audio.add({
knock: ['assets/door_knock_3x.mp3', 'assets/door_knock_3x.ogg', 'assets/door_knock_3x.aac'],
applause: ['assets/board_room_applause.mp3', 'assets/board_room_applause.ogg', 'assets/board_room_applause.aac'],
ring: ['assets/candy_dish_lid.mp3', 'assets/candy_dish_lid.ogg', 'assets/candy_dish_lid.aac']
});
// Now that our sprites are ready to draw, start the game
Crafty.scene('Game');
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment