-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpixel_map.js
executable file
·154 lines (135 loc) · 4.9 KB
/
pixel_map.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
var jaws = (function(jaws) {
/**
* @class jaws.PixelMap
* @constructor
*
* Worms-style terrain collision detection. Created from a normal image.
* Read out specific pixels. Modify as you would do with a canvas.
*
* @property {string} image the image of the terrain
* @property {int} scale_image Scale the image by this factor
*
* @example
* tile_map = new jaws.Parallax({image: "map.png", scale_image: 4}) // scale_image: 4 for retro blocky feeling!
* tile_map.draw() // draw on canvas
* tile_map.nameColor([0,0,0,255], "ground") // give the color black the name "ground"
* tile_map.namedColorAtRect("ground", player.rect()) // True if players boundingbox is touching any black pixels on tile_map
*
*/
jaws.PixelMap = function PixelMap(options) {
if( !(this instanceof arguments.callee) ) return new arguments.callee( options );
this.options = options
this.scale = options.scale || 1
this.x = options.x || 0
this.y = options.y || 0
if(options.image) {
this.setContext(options.image);
if(options.scale_image) {
this.setContext( jaws.retroScaleImage(this.context.canvas, options.scale_image) )
}
this.width = this.context.canvas.width * this.scale;
this.height = this.context.canvas.height * this.scale;
}
else { jaws.log.warn("PixelMap needs an image to work with") }
this.named_colors = [];
this.update();
}
/*
* Initiates a drawable context from given image.
* @private
*/
jaws.PixelMap.prototype.setContext = function(image) {
var image = jaws.isDrawable(image) ? image : jaws.assets.get(image)
this.context = jaws.imageToCanvasContext(image)
}
/**
* Updates internal pixel-array from the canvas. If we modify the 'terrain' (paint on pixel_map.context) we'll need to call this method.
*/
jaws.PixelMap.prototype.update = function(x, y, width, height) {
if(x === undefined || x < 0) x = 0;
if(y === undefined || y < 0) y = 0;
if(width === undefined || width > this.width) width = this.width;
if(height === undefined || height > this.height) height = this.height;
// No arguments? Read whole canvas, replace this.data
if(arguments.length == 0) {
this.data = this.context.getImageData(x, y, width, height).data
}
// Read a rectangle from the canvas, replacing relevant pixels in this.data
else {
var tmp = this.context.getImageData(x, y, width, height).data
var tmp_count = 0;
// Some precalculation-optimizations
var one_line_down = this.width * 4;
var offset = (y * this.width * 4) + (x*4);
var horizontal_line = width*4;
for(var y2 = 0; y2 < height; y2++) {
for(var x2 = 0; x2 < horizontal_line; x2++) {
this.data[offset + x2] = tmp[tmp_count++];
}
offset += one_line_down;
}
}
}
/**
* Draws the pixel map on the maincanvas
*/
jaws.PixelMap.prototype.draw = function() {
jaws.context.drawImage(this.context.canvas, this.x, this.y, this.width, this.height)
}
/**
* Trace the outline of a Rect until a named color found.
*
* @param {object} Rect Instance of jaws.Rect()
* @param {string} Color_Filter Only look for this named color
*
* @return {string} name of found color
*/
jaws.PixelMap.prototype.namedColorAtRect = function(rect, color) {
var x = rect.x
var y = rect.y
for(; x < rect.right-1; x++) if(this.namedColorAt(x, y) == color || color===undefined) return this.namedColorAt(x,y);
for(; y < rect.bottom-1; y++) if(this.namedColorAt(x, y) == color || color===undefined) return this.namedColorAt(x,y);
for(; x > rect.x; x--) if(this.namedColorAt(x, y) == color || color===undefined) return this.namedColorAt(x,y);
for(; y > rect.y; y--) if(this.namedColorAt(x, y) == color || color===undefined) return this.namedColorAt(x,y);
return false;
}
/**
* Read current color at given coordinates X/Y
*
* @return {array} 4 integers [R, G, B, A] representing the pixel at x/y
*/
jaws.PixelMap.prototype.at = function(x, y) {
x = parseInt(x)
y = parseInt(y)
if(y < 0) y = 0;
var start = (y * this.width * 4) + (x*4);
var R = this.data[start];
var G = this.data[start + 1];
var B = this.data[start + 2];
var A = this.data[start + 3];
return [R, G, B, A];
}
/**
* Get previously named color if it exists at given x/y-coordinates.
*
* @return {string} name or color
*/
jaws.PixelMap.prototype.namedColorAt = function(x, y) {
var a = this.at(x, y);
for(var i=0; i < this.named_colors.length; i++) {
var name = this.named_colors[i].name;
var c = this.named_colors[i].color;
if(c[0] == a[0] && c[1] == a[1] && c[2] == a[2] && c[3] == a[3]) return name;
}
}
/**
* Give a RGBA-array a name. Later on we can work with names instead of raw colorvalues.
*
* @example
* pixel_map.nameColor([0,0,0,255], "ground") // Give the color black (with no transparency) the name "ground"
*/
jaws.PixelMap.prototype.nameColor = function(color, name) {
this.named_colors.push({name: name, color: color});
}
return jaws;
})(jaws || {});